# `StatifierBlocks.Core.DeadlineRecipe`
[🔗](https://github.com/riddler/statifier_blocks/blob/v0.44.1/lib/statifier_blocks/core/deadline_recipe.ex#L1)

The core `"deadline"` recipe: one palette pick puts down the `core.send`
and `core.on_event` pair that ADR-0010 decision 1 spells (ADR-0005
clause 4C).

A clock interrupt on a group is two blocks, and which two and where is
knowledge an author otherwise has to hold in their head:

  * a `core.send` carrying the deadline event and a `delay`, at **index 0
    of the enclosing group's `body`** - first, so the deadline starts when
    the group starts; and
  * a `core.on_event` naming **the same event**, on that same group's
    `interrupts` rail.

Both halves are ordinary blocks of ordinary core types. The recipe is the
knowledge of how they go together and nothing more: it adds no vocabulary,
no row to ADR-0002 decision 10's table, and nothing a document holds that
it could not have held before.

The event name is generated rather than asked for, and it is written twice
by the recipe rather than twice by the author - which is the coupling
ADR-0010 decision 5 records as the family rule, and the half of it that
was most easily got wrong by hand. It is derived from the send block's own
minted id, so two deadlines in one group never name the same event.

## What it refuses, and why that is a refusal rather than a finding

The pair only means anything on a block with an `interrupts` rail, which
in the core vocabulary is `core.group` and `core.resumable_group` and
nothing else - `core.sequence`'s moduledoc says so in terms. Armed
anywhere else, `insert/2` answers `{:error, {:no_interrupts_slot, id}}`
and nothing is written, so there is no document for the view model to say
anything about. A refused gesture is not a finding (clause 3C).

`insert/2` is handed the armed position and the document and nothing else
(clause 2C), so the enclosing block's **declared** slots are out of its
reach - a palette is not one of its arguments. It reads the two core type
names instead. That is core knowledge about core types inside a core
recipe, not the editor learning what a block is called: a host whose own
group type carries an `interrupts` rail registers its own recipe under
this name, which is exactly what clause 1C's collision rule is for.

## Recognising the pair again at delete time

`members/2` (ADR-0005's 2026-09-07 amendment, clause `2D`) is `insert/2`
read backwards. It is handed a block id and the document and answers the
ids of the pair that block is half of, so the editor can take the
arrangement out in the one gesture it went in as.

It recognises the **shape**, not the origin. Nothing in the document says
a send is a deadline's send (clause `11u`), so the recipe looks for what
`insert/2` writes: a `core.send` carrying an `event` and a `delay` in a
group's `body`, and a `core.on_event` on **that same group's**
`interrupts` rail whose `event` is the same string. Three consequences
follow, and each is the amendment's:

  * a **hand-built** pair is claimed - an author who put both halves down
    themselves built the arrangement, and the recipe cannot tell the
    difference;
  * a **renamed** event still matches, because the test is that the two
    halves AGREE, not that either matches `event_name/1`'s generated form.
    The config form writes one half at a time, so a pair renamed apart is
    no longer a pair and is not claimed;
  * nothing outside the enclosing group is ever named. The rail is read
    off the group the asked-about block sits in and off no other block,
    which is clause `3C`'s bound arriving by construction the way
    `insert/2`'s does.

The answer includes the asked-about id, and is `[]` for everything else -
a block of another type, a half whose partner is absent, and a half whose
partner disagrees. The last of those is the amendment's conservative
reading of a partial arrangement, which it records as the behaviour in the
absence of a decision rather than as the decision.

# `default_delay`

```elixir
@spec default_delay() :: String.t()
```

The default deadline. `core.wait`'s own default, for `core.wait`'s reason:
a duration the author will almost always change, but a real one, so the
pair the pick produces compiles before it is touched.

# `insert`

The pair, as two `:insert` commands, or a refusal.

The armed position names its parent, and that parent is the enclosing
group both halves land in - the send at the head of `body`, the handler at
the end of `interrupts`. Clause 3C's bound is therefore met by
construction: neither command names a block above the group the author is
already inside.

# `members`

Both ids of the deadline pair `block_id` is half of, or `[]`.

The send first and the handler second, whichever half was asked about, so
one arrangement answers one list however the author reached it.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
