Runtime
JourneyRuntime (src/core/runtime.ts) is the single class that owns changing state. No
controller-per-concern layer sits between this state and the operation changing it: a lifecycle
control, context update, navigation, or graph send updates runtime state and publishes a new
snapshot at its defined boundaries.
Runtime state
Section titled “Runtime state”The runtime owns:
- lifecycle
statusand the recorded terminaloutcome; - the
timelinearray, its pointercurrentIndex(-1while idle), and per-step visit counts; - the current
contextvalue; - current-entry async state and the pending-transition record (
working,leaving,entering); - the raised-event FIFO queue;
- a generation counter and a one-shot restore seed;
- plugin APIs, snapshot derivers, and dispose callbacks.
The generation counter
Section titled “The generation counter”Terminate, restart, and dispose increment a generation counter. Every async continuation — awaited navigation work, hook chains, raised-event draining — captures the generation it started under and bails out when the counter has moved on, so stale continuations cannot settle a newer run.
Initial entry and restore
Section titled “Initial entry and restore”start() moves idle to running and enters the initial step: no onLeave runs, from is
null, and stepEnter reports direction: "jump".
When the machine was created with the persist option and a resumable record existed in storage,
the factory hands the runtime a one-shot restore seed. The first start() then seeds context,
timeline, and pointer from the record and re-enters the persisted current step instead of the
first/initial one. Visit counts are reconstructed from the restored timeline, so the re-entered
step reports isFirstTimeVisit: false. The seed is consumed on first use: restart() always
begins a fresh run at the first/initial step (or startAt). An explicit startAt option wins over
a persisted record. See Persistence for the record validity rules.
Lifecycle and context changes
Section titled “Lifecycle and context changes”Controls update status directly and publish a snapshot plus statusChange. Context updates replace
context synchronously and publish a snapshot plus contextChange.
Pause, complete, and normal navigation reject while a hook chain is pending. Terminate deliberately wins: it invalidates pending work and clears raised events. Restart is available only after complete or terminate and rebuilds the initial run state.
Raised events
Section titled “Raised events”Hook raise(event) appends to a graph-only FIFO. The runtime starts draining only after the current
transition settles. One cascade is capped at MAX_RAISED_EVENTS (25); exceeding it drops the queue
and emits an error event with phase raise.
Timeouts
Section titled “Timeouts”defaultTimeoutMs wraps navigation run and each hook promise. A work timeout blocks movement and
returns reason: "error"; a post-commit hook timeout surfaces as the destination step’s async
error.