Event handling has four distinct stages: admission, selection, conflict resolution, and disposition. A valid event may be refused without being an error. A malformed event fails before selection. A handled event advances only after its complete macrostep commits.
Admit authored events once
An authored external event crosses the kernel boundary as an encoded envelope containing its tag and encoded fields. Admission first identifies the tag.
- A known authored tag is decoded through that event's Schema exactly once.
- A known tag with invalid fields fails with
MalformedEventbefore transition selection. - An unknown but otherwise valid tag finishes as an unhandled event.
- A reserved interpreter tag is rejected at the public send boundary.
Guards, updates, raises, and payload producers receive the decoded domain event, not an untyped reconstruction of the wire envelope. The originally encoded envelope remains the persistence authority. This keeps domain use typed while preserving the exact admitted bytes for a durable timeline.
Malformed admission runs no chart binding, publishes no snapshot, advances no sequence, and appends no timeline entry. The failure direction is part of the boundary: decoding must happen before any semantic work that could be mistaken for a committed response.
Synthetic completion and lifecycle stimuli belong to the interpreter. They do not pass through the authored event decoder. Authored content emitted by an activity or child remains authored content and is decoded at its own admission.
Select from leaves toward ancestors
For an admitted event, selection examines active atomic and final states in document order. It starts at each active leaf and walks toward the root. The first enabled matching transition found on that path represents that leaf.
This gives a descendant state the first opportunity to interpret an event. Only when the descendant has no enabled match does the event bubble to an ancestor. A guard that evaluates false does not consume the event; selection continues up the ancestor chain.
Send Probe first, then block the child and send it again to watch the same tag
reach the ancestor. Refuse has no active listener, so its valid send reports
non-handling.
Starting the event selection chart…
Transitions on one source are also examined in authored document order. Exact tags and the wildcard do not have separate priority classes. If a wildcard is authored before an exact-tag transition on the same state, the wildcard wins. Moving a transition in source can therefore change behavior even when every transition value is otherwise unchanged.
Eventless selection is a separate pass. Event transitions are not considered while selecting eventless work, and eventless transitions are not considered for an event dispatch. During an eventless microstep there is no current event. Producers and guards must not inherit an earlier event implicitly.
Evaluate guards against the selection snapshot
A guard runs during selection, before the candidate microstep has executed any exit, transition, or entry action. It observes the current event and the snapshot as modified by earlier microsteps in the same macrostep, but it does not observe actions from the microstep it is deciding.
This timing prevents a candidate transition from making itself eligible by its own actions. It also permits a state update in one microstep to enable an eventless transition in the next microstep. The boundary between those cases is the microstep boundary, not the outer macrostep boundary.
Selection yields at most one candidate per active leaf. Parallel regions may therefore propose transitions for the same event. Those proposals must pass conflict resolution before any action runs.
Resolve conflicts by geometry
Two transitions conflict when their computed exit sets intersect. They cannot both be taken because each claims authority over at least one of the same active states.
Resolution follows two laws:
- a transition from a descendant source preempts a transition from its ancestor; and
- otherwise, the transition proposed by the earlier active leaf in document order wins.
The result is a conflict-free set of transitions for one microstep. Exit sets are computed before actions, so effects cannot retroactively change which transitions won.
A targetless transition has an empty exit set. It does not conflict with geometric transitions selected elsewhere. It may consume an event and perform actions while leaving configuration unchanged. Because it is selected on the descendant path, it can also shield that event from an ancestor handler without causing exit and re-entry.
Distinguish refusal from failure
If a valid external event selects no transition, the pure fold succeeds with
an Unhandled outcome. The snapshot is unchanged, the sequence does not
advance, and no macrostep is appended. An engine reports that successful
non-handling disposition to the sender as Refused.
Refusal is not a malformed input, a thrown defect, or a terminal chart state. It means the event was admissible but the current configuration assigned it no enabled transition. The instance remains available for later events.
Raised internal events have a different delivery contract. A raised event that selects no transition is dropped silently while the enclosing macrostep continues. It does not create a separate refusal result because there is no external sender waiting for a delivery decision.
Completion events also use ordinary transition selection, but their authored listeners are tied to the state, activity, timer, or child that can produce them. Hand-authoring reserved completion strings bypasses that checked relationship and fails checked authoring validation.
Keep admission and refusal distinct
This page owns the two outcomes at the admission and selection boundary:
| Outcome | Meaning | Commit effect | | ----------------------- | -------------------------------------------------------------------- | ------------------------------------ | | Refused | The valid event selected no transition in the current configuration. | No sequence advance and no new step. | | Typed admission failure | The event violated a declared or reserved boundary. | No chart work and no commit. |
The Diagnostics page owns the full four-way disposition doctrine.