REFERENCE

Runtime events

The named events Anglish spaces emit and consume — the substrate of declarative flow.

Anglish spaces communicate through named runtime events rather than function call chains. An event is a %name emitted by a task or space-native trigger; declarations bind tasks to events using vibe lines.

This is the substrate that makes the contract enforceable: every flow is observable, every transition is named, and the compiler can verify that all referenced events are produced somewhere.

Lifecycle events

Every space participates in a small set of lifecycle events:

  • %onEnter — the space has been entered (a UI panel gained focus, an IO stream opened, a data store mounted).
  • %onExit — the space is shutting down or losing focus. A natural place to emit $rotateLogs or flush buffers.
  • %onError — something went wrong. The space’s vibe block typically delegates to a recovery task.

In a :UI space, %onEnter is what fires when a panel becomes active. In :IO, it fires when a connection opens. In :DATA, it fires when the dataspace is first read or written in a session.

Submission and update events

UI spaces add a small vocabulary for user-driven flow:

  • %onSubmit — a form has been submitted.
  • %onChange — an input value has changed.
  • %dataUpdated — emitted by a :DATA space when the contents at a path change.
@userSettings:UI
>>> Bind fields to %profileData.
>>> When %onEnter, trigger $ui_reader(out=%profileData).
>>> When %onSubmit, delegate to $validateProfile.
>>> On %onError from $validateProfile, send %profileErrors to $ui_writer.

Each binding (When %X, trigger Y; On %X, delegate to Y) is an explicit edge in the runtime graph.

Stream events

:IO spaces emit stream events as data flows:

  • %sensorUpdate — a new value arrived from a sensor or stream.
  • %signalUpdate — generic stream tick for actuator or signal-emitting devices.
@camFeed:IO
>>> On %onEnter, trigger $io_reader(out=%jpgFrameStream).
>>> Each %sensorUpdate delegates to $decodeFrame(in=%jpgFrameStream).

:IO spaces are stateless between events; if you need to retain state, route through a :DATA space.

Outcome events

Tasks that produce a result emit named outcome events. The convention is %X{Success|Failure} or %X{Result|Error}:

  • %saveSuccess / %saveFailure — the persistence task completed.
  • %orderSuccess / %orderFailed — order placement returned.
  • %validationErrors — validation surfaced one or more issues.
  • %rotationEvent — log rotation completed.

Outcome events are how composed spaces hear back from imported tasks without the parent needing to peek inside them.

Author-defined events

Every event is just a %name. Authors are encouraged to introduce domain-specific events whose names read clearly in vibe prose: %inventoryLow, %deviceResetCmd, %ticketEscalated. The compiler’s only requirement is that every consumed event is produced somewhere — referenced events must resolve, just like any other identifier.

Why events, not return values

Two reasons.

Reviewability. A function call chain hides flow inside the bodies of the functions. An event flow surfaces it: every transition is a line you can read in a vibe block. A reviewer can re-read the contract and know what runs after what.

Locality of change. Adding a new consumer of %saveSuccess does not require modifying the producer. Late binding is the default, not an opt-in.