Expand description
Runtime/VM for executing compiled ink stories.
The runtime takes a StoryData from the compiler,
links it into an immutable Program, and executes it via Story.
use std::sync::Arc;
use brink_runtime::Step;
let (program, line_tables) = brink_runtime::link(story_data)?;
let mut story: brink_runtime::Story = brink_runtime::Story::new(Arc::new(program), line_tables);
loop {
match story.continue_single()? {
Step::Line(line) => print!("{}", line.text),
Step::Done => {}
Step::Choices(choices) => {
let _ = choices;
// pick a choice...
story.choose(0)?;
}
Step::End => break,
Step::Suspended => break,
}
}no_std + alloc: this crate builds without the standard library when
the default std feature is disabled (see docs/no-std-portability.md).
Re-exports§
pub use debug_control::Breakpoint;pub use debug_control::BreakpointId;pub use debug_control::BreakpointSet;pub use debug_control::DEFAULT_DEBUG_BUDGET;pub use debug_control::DebugRunOutcome;pub use debug_control::DebugStopReason;pub use debug_control::StepMode;pub use debug_control::WatchHit;pub use debug_control::WatchpointObserver;pub use rng::DotNetRng;pub use rng::FastRng;pub use rng::StoryRng;
Modules§
- bench_
counters - Bench-only debug counters for Arc-clone / COW-copy events (issue #821
Workstream B seed,
docs/runtime-bench.md). - debug_
control - Debugger control seam (D8, issue #3186): breakpoints, pause/resume, and
step in/over/out — the part of the debugger epic (#452) that turns the
read-only
crate::DebugSnapshot(D4, #3182) into something that can actually halt and single-step a running story. - debug_
session - Scripted debug sessions (#3247/#3248): the shared verb set the test harness, the CLI debugger and the studio all drive, so there is one definition of “step over” rather than three. Scripted debug sessions — the shared verb set for driving a debugger (issue #3247, extracted here by #3248).
- effect_
trace - Ground-truth effect-atom recorder (issue #870, T2 effects epic,
docs/effects-spec.md). The effects analogue of the oracle: this module records, per executing definition scope, the atomic effects the VM actually performs — cells read, cells written, external kinds called — sobrink-test-harnesscan assert the statically-inferredeffects(def)row (brink-db::ProjectDb::effects) covers every one of them for every def a real run executed. A purely structural inter-row consistency check (caller’s row ⊇ callee’s row) cannot catch an under-report where both rows silently agree on the wrong (too-small) answer — exactly the #866 ref-param-write regression this issue is named for. This is the independent, run-the-bytecode-and-look check that closes that gap. - rng
- Pluggable PRNG for story randomization.
- transcript
- Transcript binary serialization (
.brktformat).
Structs§
- BlockId
- Opaque identifier grouping a run of adjacent content lines.
- Budget
- Caller-supplied cap on a
Speculation’s VM stepping, in place of the runtime’s hardcodedSTEP_LIMIT/LINE_LIMITceilings. - Choice
- A single choice presented to the player.
- Context
View - Routing view implementing
ContextAccessover(&mut World, &mut FlowLocal). - Debug
Choice - A pending choice and the knot it targets.
- Debug
Frame - One call frame, resolved to a knot/stitch path.
- Debug
Global - A global variable and its current value.
- Debug
Local - One named local variable and its current value (
docs/debugger-spec.md§3, D7/#3185). - Debug
Position - Precise execution position: a container index plus the byte offset of the next instruction to execute inside that container’s bytecode.
- Debug
Rng - Story RNG state.
- Debug
Snapshot - A structured, read-only snapshot of the runtime’s current state.
- Debug
Source Location - The result of resolving a
DebugPositionto source via the program’sDebugInfosection (D6,docs/debugger-spec.md§2.2) — seecrate::Program::resolve_debug_position(D9, issue #3187). This is the “program → source” half of the studio’s Location protocol (docs/studio-shell-spec.md§6.1). - Debug
Visit - A visit count for a named knot/stitch.
- Element
- A line’s classification — kind + an open, preset-defined data map
(
docs/prose-dialect-spec.md§7/§3.5b, §3.6, sitting-5 ruling item 8: “the output format bakes no scene-specific fields — element data is an open map produced by conventions and handlers”). Deliberately aStringkind, not a closed enum: the vocabulary belongs to whichever preset or@[element]handler classified the line, never to the runtime. - Externals
Report - Diagnostic record of which externals a
KindTieredHandlerlet through live versus fell back, across the handler’s lifetime. - Fallback
Handler - Default handler that always falls back to the ink function body.
- Flow
Instance - A single independent execution context within a story. The default flow
runs from the root container; named flows can be spawned at arbitrary
entry points via
FlowInstance::new_at. - Flow
Local - Per-flow override layer over the shared
World. - Fragment
- A finalized fragment — structural output parts plus any associated tags.
- Fragment
Ref - A borrowed view of one fragment inside a
Fragmentsstore. - Fragments
- The fragment store: every finalized fragment’s parts laid end to end in ONE arena, addressed by a per-fragment span.
- Frame
Start View - A borrowing view over a pinned frame-start
World: reads are served by reference from the shared&World, writes land in a private per-view overlay that the shared world never sees. - Journal
Event - One input that entered the VM.
- Kind
Tiered Handler - A stackable
ExternalFnHandlerthat tiers externals byPolicyKindbefore delegating to a real handler. - List
Delta - Membership delta for one list-valued global.
- List
Member - One active member of a list value, resolved for host-facing display. See
Program::list_members. - Load
Report - What
Story::load_statecouldn’t apply, so a host can surface it rather than have data silently vanish. Globals whose name no longer exists are dropped (no slot to hold them) and reported here. Visit/turn counts are never dropped — counts for scopes the current program lacks are retained harmlessly (unused until/unless the scope returns), so they aren’t reported except when the miss-path alias lookup (M-3, docs/modules-spec.md §5) still can’t place them — seeunresolved_renamesfor a named scope, oranonymous_states_droppedfor an anonymous one. - Observed
Context - A
ContextAccesswrapper that delegates to an innerContextAccessimplementor (typicallyWorldor theContextViewrouting view) and notifies aWriteObserveron every mutation. - Output
Line - One line of story content, carried inside
Step::Line. - Program
- A linked, ready-to-execute program.
- Recorded
External - One recorded external-function result, captured in call order during a live run.
- Recording
Handler - Wraps an
ExternalFnHandlerand records every inline-Resolvedexternal result into aReplayRecorderduring a live run. - Replay
Handler - Replays recorded external results (
ReplayMode::Recorded). - Replay
Recorder - An append-only, capped log of external results for one flow, plus a replay cursor. Recorded during the live run; consumed in order during replay.
- Resolved
Policy - Fast, id/slot-based resolution of a
WorldPolicyagainst a specificProgram. Built once atWorldcreation viaResolvedPolicy::resolve; consulted on every state access (from F2.2 on) with O(1) lookups — no string matching on the hot path. - Save
State - A persistent, name-keyed snapshot of a story’s game state.
- Session
Journal - One ordered log of every input that entered the VM during a session, plus a
terminal fast-restore
checkpoint. - Snapshot
Frame - One summarized call frame.
- Snapshot
List - Resolved membership of a
List-valued global. - Speculation
- A sandboxed, self-contained speculative run over a story’s current state. See the module docs for the full picture.
- State
Diff - A pure diff between two
StateSnapshots (seediff). - State
Snapshot - A typed, name-resolved snapshot of a session’s game state.
- Stats
- Lightweight counters tracking VM activity over a story’s lifetime.
- Story
- Per-instance mutable state for executing stories.
- Story
Session - A journaling, replayable session wrapping a
Story. - Story
Snapshot - Owned story state that can be detached from a
Programand reattached later. - Value
Iter - A pull iterator over one builtin iterable’s canonical sequence — the
iterate protocol’s machine form:
nextisnext(ref Self): Option[T]with the protocol’s laws structural (the cursor only advances, so every element is yielded exactly once and exhaustion is terminal and sticky by construction). - Visit
Entry - One visit/turn-count entry: a scope id and its count, plus (when the scope
is a named knot/stitch) an advisory author path for human inspection. The
idis the load key;pathis cosmetic. - World
- Shared game state that lives above individual flows.
- World
Policy - Host-facing, name-based declaration of the world/local split.
Enums§
- Commit
Error - Errors from
commit. - Debug
Value - A structured, read-only view of a runtime
Valuefor the debugger’s locals panel (docs/debugger-spec.md§3, D7/#3185). - Divergence
Found - What was found at a divergence point instead of the recorded event.
- Drive
Outcome - Outcome of a single
FlowInstance::drivecall: either the drive reached a terminal step, or it paused on a deferred external mid-drive. Both variants carry everyStepproduced during this call — forAwaitingExternal, that’s the (possibly empty) run ofStep::Lineproduced before the pause; forTerminal, the terminal step is always the last element (seeFlowInstance::drive). - Eval
Context - Which evaluation regime a
KindTieredHandleris gating for. - Event
Kind - The kind + payload of a
JournalEvent. - Exec
Mode - The dev/prod execution mode (NS-A4,
docs/stdlib-spec.md§4b, ruled 2026-07-18): the knob that decides WHERE execution stops on an unordered comparand — never WHAT values are fabricated. - External
Replay Mode - How replay obtains external values.
- External
Result - Result of an external function handler call.
- Fail
Reason - Why replay stopped without diverging.
- Function
Eval - Outcome of an engine→ink function evaluation
([
FlowInstance::begin_function_eval] /resume_function_eval). - Locale
Mode - Controls how missing scopes are handled when applying a locale overlay.
- Mode
- Execution mode of a
FlowLocal, baked in at construction/fork time and read byContextViewto decide how it routes every unit. - Output
Part - A part of accumulated output.
- Policy
Error - Errors resolving a
WorldPolicyagainst aProgram’s symbol table. - Policy
Kind - The effect category a
KindTieredHandlergates on. Plain data — the consumer maps its own (richer) external classification onto this two-way split. - RanOut
OfContent Cause - Why execution ran out of content — the call-stack shape C#’s
Story.Continue()inspects to pick one of four messages (Story.cs, theAddErrorcalls guarding the “ran out of content” branch: it checkscallStack.CanPop(PushPopType.Tunnel), then.CanPop(PushPopType.Function), then!callStack.canPop, with a final backstop for none of the above). - Replay
Mode - How a replay obtains external values. Whole-flow granularity.
- Replay
Outcome - Outcome of replaying a journal prefix against a program.
- Replay
Warning - A non-fatal replay observation.
- Runtime
Error - Errors that can occur during story linking or execution.
- Runtime
Warning - A non-fatal condition the VM reported while a story was running (issue #3354, RULED 2026-09-01 option C).
- Scope
- Where a unit of story-state lives: the shared
Worldor a flow’s privateFlowLocal. - Session
Error - Errors from session-level operations (distinct from VM
RuntimeErrors, which are wrapped). - Snapshot
Status - Session execution status, serde-friendly.
- Speculation
Step - Outcome of a single
Speculation::advancecall. - Step
- A single step of story output from [
Story::continue_single]. - Step
Outcome - Outcome of a single [
FlowInstance::advance] step. - Story
Status - The current execution status of a story.
Constants§
- RECORDING_
CAP - Upper bound on recorded externals per flow (unbounded-growth guard). Beyond
it,
ReplayRecorder::recorddrops the result and replay falls through to the ink fallback body for the uncovered tail. - RUNTIME_
WARNING_ CAP - How many
RuntimeWarnings one flow accumulates between drains before it stops recording them. - SAVE_
FORMAT_ VERSION - Current
SaveStateformat version. Bump when the format changes (independent of the story’s own content);versionlets a loader migrate. - SESSION_
JOURNAL_ CAP - Upper bound on journal events (unbounded-growth guard, mirroring
RECORDING_CAP). Beyond it, appends are dropped andSessionJournal::truncatedis set — the journal degrades honestly and restore falls back to the embeddedcheckpoint. - SESSION_
JOURNAL_ VERSION - Current
SessionJournalformat version.
Traits§
- Context
Access - Trait for accessing and mutating story execution state.
- External
FnHandler - Trait for handling external function calls from ink.
- Write
Observer - Observer for state mutations during story execution.
Functions§
- apply_
locale - Apply a locale overlay to a set of base line tables.
- commit
- Fold a forked child’s own-layer overrides back into its parent’s,
making the child’s writes visible through
parent(and, transitively, anythingparentitself chains to or is later written through). - diff
- Pure diff of two snapshots.
ais “before”,bis “after”. - link
- Link a
StoryDatainto an executableProgram. - load_
state - Reconcile a
SaveStateinto a flow’s context, returning aLoadReportof anything that couldn’t be applied. Globals are matched by name; visit/turn counts by id. Tolerant of story patches: unknown globals are reported, scopes the program no longer has retain their saved counts harmlessly in the live context. Note one deliberate change from the pre-F6.1bStorymethods: such stale entries are not re-emitted by a subsequentsave_state(which enumerates the current program’s containers, not the live maps) — ghost counts from older program versions no longer round-trip through saves indefinitely. - save_
state - Capture a flow’s game state as a durable, name-keyed
SaveState. Does not capture execution position — see the module docs.
Type Aliases§
- Drained
Line - One line handed out by
Story::debug_drain_buffered_lines: text, tags, and its source location (W7/#3300 provenance — same field the production road’sOutputLine::sourcecarries).