core.group: a boundary around a run of steps that interrupt rules can
fire against.
Two named slots - body for the steps, interrupts for the handlers -
which is ADR-0001 decision 10's "a second, differently-meaning slot on
the same block", the case slots are named for. Interrupt rules are not a
block type that wraps a group; they are handler blocks in the group's
interrupts slot, because that is the arrangement they compile to and
the arrangement an author reads as "these can interrupt this".
Against core.resumable_group
This type is core.resumable_group without the history mode: the same
two slots, the same kind tags, no config at all. Reach for the
resumable one when re-entering the group after an interrupt should return
to where it left off; reach for this one when the group has nothing to
remember. ADR-0002 decision 10 names only the resumable form, so the
split is this bead's, and it is drawn so that the resumable row of that
table is untouched.
Unlike StatifierBlocks.Core.Sequence, a group is not transparent to
type flow: it can be left early by an interrupt, so what reaches the
block after it is not simply what its last step produced. It declares no
produces and takes ADR-0003 decision 5's permissive :unknown.
Summary
Functions
A compound state whose body runs in order, guarded by whatever sits in
interrupts (StatifierBlocks.Core.Emit). With no interrupt handlers it
is exactly a sequence; with them, the body and the handlers run as
regions of a <parallel> and the two-event interrupt protocol is wired
on the group's own state.
Half of ADR-0003 decision 3's placement rule: interrupts admits
interrupt handlers and body admits steps, so an ordinary step dropped
into interrupts is a :kind_not_admitted finding without this type
knowing that core.on_event exists.
This block as one line of prose (ADR-0002's 2026-09-07 amendment).
Functions
A compound state whose body runs in order, guarded by whatever sits in
interrupts (StatifierBlocks.Core.Emit). With no interrupt handlers it
is exactly a sequence; with them, the body and the handlers run as
regions of a <parallel> and the two-event interrupt protocol is wired
on the group's own state.
A group has nothing to remember, so a "resume" handler re-enters the
<parallel> and the body restarts from its first step. Resuming where it
left off is StatifierBlocks.Core.ResumableGroup, and that difference is
the whole of what separates the two types.
Half of ADR-0003 decision 3's placement rule: interrupts admits
interrupt handlers and body admits steps, so an ordinary step dropped
into interrupts is a :kind_not_admitted finding without this type
knowing that core.on_event exists.
This block as one line of prose (ADR-0002's 2026-09-07 amendment).
A group has no config, so the line is the same for every block of this
type. It says what separates a group from a sequence - its steps can be
interrupted - rather than counting the rules in interrupts, which are
blocks with lines of their own (StatifierBlocks.Core.OnEvent's
"When ..., abandon") and are read there. It is kept short because other
lines also name the group by it, as in "abandons Group (Run
interruptible steps)" (StatifierBlocks.Map.Info).
iex> StatifierBlocks.Core.Group.sentence(%{})
"Run interruptible steps"