DocsAPI referenceStatechart

Statechart runtime

The lifecycle kernel and its optional authoring, scheduler, persistence and inspection entry points. Every section below is an importable public package path.

Lifecycle

Start a service, observe snapshots, send events, update input, batch work, and always release the subscription and service.

service.tsts
import { createService } from "@grassroot/statechart";
import { switchMachine } from "@grassroot/ui-machines/switch";
const service = createService(switchMachine, { input: { defaultChecked: false } });
const stop = service.subscribe((snapshot) => console.log(snapshot.value));
service.start();
service.send({ type: "PRESS", reason: "pointer" });
service.setInput({ defaultChecked: true });
service.batch(() => service.send({ type: "RESET" }));
stop();
service.stop();

@grassroot/statechart

Core runtime

12 exports
View source packages/statechart/src/index.ts
DeclarationView source
CommandObjectts
type CommandObject = {
readonly type: string;
readonly [key: string]: JsonValue;
};
Name
Kind
Type
Requirement
type
property
string
required
Name
type
Kind
property
Type
string
Requirement
required

createService

function
DeclarationView source
createServicets
declare function createService<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output = never>(machine: Machine<Input, Value, Context, Event, Command, Output>, options: {
input: Input;
runCommand?: (command: Command, tools: {
send: (event: Event) => void;
signal: AbortSignal;
}) => void | (() => void);
onDiagnostic?: (diagnostic: DiagnosticObject & {
readonly machineId: string;
}) => void;
onError?: (error: ServiceError<Value, Context, Event, Command, Output>) => void;
}): Service<Input, Value, Context, Event, Command, Output>;
Name
Kind
Type
Requirement
machine
parameter
Machine<Input, Value, Context, Event, Command, Output>
required
options
parameter
{ input: Input; runCommand?: (command: Command, tools: { send: (event: Event) => void; signal: AbortSignal; }) => void | (() => void); onDiagnostic?: (diagnostic: DiagnosticObject & { readonly machineId: string; }) => void; onError?: (error: ServiceError<Value, Context, Event, Command, Output>) => void; }
required
return
return value
Service<Input, Value, Context, Event, Command, Output>
n/a
Name
machine
Kind
parameter
Type
Machine<Input, Value, Context, Event, Command, Output>
Requirement
required
Name
options
Kind
parameter
Type
{ input: Input; runCommand?: (command: Command, tools: { send: (event: Event) => void; signal: AbortSignal; }) => void | (() => void); onDiagnostic?: (diagnostic: DiagnosticObject & { readonly machineId: string; }) => void; onError?: (error: ServiceError<Value, Context, Event, Command, Output>) => void; }
Requirement
required
Name
return
Kind
return value
Type
Service<Input, Value, Context, Event, Command, Output>
Requirement
n/a
DeclarationView source
DiagnosticObjectts
type DiagnosticObject = {
readonly code: string;
readonly message: string;
readonly severity: "warning" | "error";
readonly data?: JsonValue;
};
Name
Kind
Type
Requirement
code
property
string
required
data
property
JsonValue
optional
message
property
string
required
severity
property
"warning" | "error"
required
Name
code
Kind
property
Type
string
Requirement
required
Name
data
Kind
property
Type
JsonValue
Requirement
optional
Name
message
Kind
property
Type
string
Requirement
required
Name
severity
Kind
property
Type
"warning" | "error"
Requirement
required
DeclarationView source
EventObjectts
type EventObject = {
readonly type: string;
};
Name
Kind
Type
Requirement
type
property
string
required
Name
type
Kind
property
Type
string
Requirement
required

JsonValue

type

The low-level `@grassroot/statechart` contract, frozen in phase 0 of GRASSROOT_STATECHART_EXECUTION_PLAN.md. The shapes here are lifted verbatim from GRASSROOT_STATECHART_PLATFORM_PLAN.md ("Native statechart model"). Decision records: docs/decisions/statechart-api.md and docs/decisions/statechart-semantics.md. The authoring layer (phase 5) must compile to this contract with identical semantics. This file is types plus one declaration only — no runtime code ships in phase 0. `createService` is implemented in phase 1 (src/service.ts).

DeclarationView source
JsonValuets
type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
readonly [key: string]: JsonValue;
};

Machine

interface
DeclarationView source
Machinets
interface Machine<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject = never, Output = never> {
readonly id: string;
initial(input: Readonly<Input>): Transition<Value, Context, Command, Output>;
transition(state: MachineState<Value, Context, Output>, event: Readonly<Event>, input: Readonly<Input>): Transition<Value, Context, Command, Output>;
sync?(state: MachineState<Value, Context, Output>, previous: Readonly<Input>, next: Readonly<Input>): Transition<Value, Context, Command, Output>;
}
Name
Kind
Type
Requirement
id
property
string
required
initial
method
(input: Readonly<Input>) => Transition<Value, Context, Command, Output>
required
sync
method
((state: MachineState<Value, Context, Output>, previous: Readonly<Input>, next: Readonly<Input>) => Transition<Value, Context, Command, Output>) | undefined
optional
transition
method
(state: MachineState<Value, Context, Output>, event: Readonly<Event>, input: Readonly<Input>) => Transition<Value, Context, Command, Output>
required
Name
id
Kind
property
Type
string
Requirement
required
Name
initial
Kind
method
Type
(input: Readonly<Input>) => Transition<Value, Context, Command, Output>
Requirement
required
Name
sync
Kind
method
Type
((state: MachineState<Value, Context, Output>, previous: Readonly<Input>, next: Readonly<Input>) => Transition<Value, Context, Command, Output>) | undefined
Requirement
optional
Name
transition
Kind
method
Type
(state: MachineState<Value, Context, Output>, event: Readonly<Event>, input: Readonly<Input>) => Transition<Value, Context, Command, Output>
Requirement
required

MachineState

interface
DeclarationView source
MachineStatets
interface MachineState<Value extends StateValue, Context, Output = never> {
readonly value: Value;
readonly context: Readonly<Context>;
readonly output?: Output;
}
Name
Kind
Type
Requirement
context
property
Readonly<Context>
required
output
property
Output
optional
value
property
Value
required
Name
context
Kind
property
Type
Readonly<Context>
Requirement
required
Name
output
Kind
property
Type
Output
Requirement
optional
Name
value
Kind
property
Type
Value
Requirement
required

Service

interface
DeclarationView source
Servicets
interface Service<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output = never> {
start(): void;
stop(): void;
getSnapshot(): Snapshot<Value, Context, Output>;
getInput(): Readonly<Input>;
send(event: Event): Snapshot<Value, Context, Output>;
setInput(next: Input): Snapshot<Value, Context, Output>;
subscribe<Selected>(selector: (snapshot: Snapshot<Value, Context, Output>) => Selected, listener: (value: Selected, previous: Selected) => void, options?: {
equals?: (a: Selected, b: Selected) => boolean;
immediate?: boolean;
}): () => void;
batch<Result>(work: () => Result): Result;
}
Name
Kind
Type
Requirement
batch
method
<Result>(work: () => Result) => Result
required
getInput
method
() => Readonly<Input>
required
getSnapshot
method
() => Snapshot<Value, Context, Output>
required
send
method
(event: Event) => Snapshot<Value, Context, Output>
required
setInput
method
(next: Input) => Snapshot<Value, Context, Output>
required
start
method
() => void
required
stop
method
() => void
required
subscribe
method
<Selected>(selector: (snapshot: Snapshot<Value, Context, Output>) => Selected, listener: (value: Selected, previous: Selected) => void, options?: { equals?: (a: Selected, b: Selected) => boolean; immediate?: boolean; }) => () => void
required
Name
batch
Kind
method
Type
<Result>(work: () => Result) => Result
Requirement
required
Name
getInput
Kind
method
Type
() => Readonly<Input>
Requirement
required
Name
getSnapshot
Kind
method
Type
() => Snapshot<Value, Context, Output>
Requirement
required
Name
send
Kind
method
Type
(event: Event) => Snapshot<Value, Context, Output>
Requirement
required
Name
setInput
Kind
method
Type
(next: Input) => Snapshot<Value, Context, Output>
Requirement
required
Name
start
Kind
method
Type
() => void
Requirement
required
Name
stop
Kind
method
Type
() => void
Requirement
required
Name
subscribe
Kind
method
Type
<Selected>(selector: (snapshot: Snapshot<Value, Context, Output>) => Selected, listener: (value: Selected, previous: Selected) => void, options?: { equals?: (a: Selected, b: Selected) => boolean; immediate?: boolean; }) => () => void
Requirement
required

ServiceError

interface
DeclarationView source
ServiceErrorts
interface ServiceError<Value extends StateValue, Context, Event, Command, Output = never> {
readonly phase: "start" | "transition" | "sync" | "diagnostic" | "command";
readonly cause: unknown;
readonly machineId: string;
readonly snapshot: Snapshot<Value, Context, Output>;
readonly event?: Event;
readonly diagnostic?: DiagnosticObject;
readonly command?: Command;
}
Name
Kind
Type
Requirement
cause
property
unknown
required
command
property
Command
optional
diagnostic
property
DiagnosticObject
optional
event
property
Event
optional
machineId
property
string
required
phase
property
"start" | "transition" | "sync" | "diagnostic" | "command"
required
snapshot
property
Snapshot<Value, Context, Output>
required
Name
cause
Kind
property
Type
unknown
Requirement
required
Name
command
Kind
property
Type
Command
Requirement
optional
Name
diagnostic
Kind
property
Type
DiagnosticObject
Requirement
optional
Name
event
Kind
property
Type
Event
Requirement
optional
Name
machineId
Kind
property
Type
string
Requirement
required
Name
phase
Kind
property
Type
"start" | "transition" | "sync" | "diagnostic" | "command"
Requirement
required
Name
snapshot
Kind
property
Type
Snapshot<Value, Context, Output>
Requirement
required

Snapshot

interface
DeclarationView source
Snapshotts
interface Snapshot<Value extends StateValue, Context, Output = never> {
readonly value: Value;
readonly context: Readonly<Context>;
readonly version: number;
readonly status: "idle" | "active" | "done" | "stopped" | "error";
readonly output?: Output;
readonly error?: unknown;
}
Name
Kind
Type
Requirement
context
property
Readonly<Context>
required
error
property
unknown
optional
output
property
Output
optional
status
property
"idle" | "active" | "done" | "stopped" | "error"
required
value
property
Value
required
version
property
number
required
Name
context
Kind
property
Type
Readonly<Context>
Requirement
required
Name
error
Kind
property
Type
unknown
Requirement
optional
Name
output
Kind
property
Type
Output
Requirement
optional
Name
status
Kind
property
Type
"idle" | "active" | "done" | "stopped" | "error"
Requirement
required
Name
value
Kind
property
Type
Value
Requirement
required
Name
version
Kind
property
Type
number
Requirement
required

StateValue

type
DeclarationView source
StateValuets
type StateValue = string | {
readonly [region: string]: StateValue;
};

Transition

interface
DeclarationView source
Transitionts
interface Transition<Value extends StateValue, Context, Command extends CommandObject, Output = never> {
readonly state: MachineState<Value, Context, Output>;
readonly commands?: readonly Command[];
readonly diagnostics?: readonly DiagnosticObject[];
}
Name
Kind
Type
Requirement
commands
property
readonly Command[]
optional
diagnostics
property
readonly DiagnosticObject[]
optional
state
property
MachineState<Value, Context, Output>
required
Name
commands
Kind
property
Type
readonly Command[]
Requirement
optional
Name
diagnostics
Kind
property
Type
readonly DiagnosticObject[]
Requirement
optional
Name
state
Kind
property
Type
MachineState<Value, Context, Output>
Requirement
required

@grassroot/statechart/authoring

authoring

23 exports
View source packages/statechart/src/authoring/index.ts

Action

type
DeclarationView source
Actionts
type Action<C, E, I, Cmd extends CommandObject> = AssignAction<C, E, I> | CommandAction<C, E, I, Cmd> | BindingAction<any, C, E, I, Cmd>;

ActionArgs

type
DeclarationView source
ActionArgsts
type ActionArgs<C, E, I> = {
readonly context: C;
readonly event: E;
readonly input: I;
};
Name
Kind
Type
Requirement
context
property
C
required
event
property
E
required
input
property
I
required
Name
context
Kind
property
Type
C
Requirement
required
Name
event
Kind
property
Type
E
Requirement
required
Name
input
Kind
property
Type
I
Requirement
required

assign

function
DeclarationView source
assignts
declare function assign<C, E, I>(fn: (args: ActionArgs<C, E, I>) => Partial<C>): AssignAction<C, E, I>;
Name
Kind
Type
Requirement
fn
parameter
(args: ActionArgs<C, E, I>) => Partial<C>
required
return
return value
AssignAction<C, E, I>
n/a
Name
fn
Kind
parameter
Type
(args: ActionArgs<C, E, I>) => Partial<C>
Requirement
required
Name
return
Kind
return value
Type
AssignAction<C, E, I>
Requirement
n/a

AssignAction

interface
DeclarationView source
AssignActionts
interface AssignAction<C, E, I> {
readonly __kind: "assign";
readonly fn: (args: ActionArgs<C, E, I>) => Partial<C>;
}
Name
Kind
Type
Requirement
__kind
property
"assign"
required
fn
property
(args: ActionArgs<C, E, I>) => Partial<C>
required
Name
__kind
Kind
property
Type
"assign"
Requirement
required
Name
fn
Kind
property
Type
(args: ActionArgs<C, E, I>) => Partial<C>
Requirement
required

bindable

function

One binding = one controlled/uncontrolled field (S12). Two storage shapes: - context-backed (no `stateFor`/`valueOf`): committed value lives in `context[<binding key>]`. - state-backed (`stateFor`/`valueOf` provided): committed value IS the state value; `stateFor` maps a proposed value to a state name, `valueOf` maps a state name back to the binding's value type. The binding's key comes from where it is placed in `defineMachine`'s `bindings` map — `bindable()` itself is unnamed, `toMachine` resolves the name from that map by identity.

DeclarationView source
bindablets
declare function bindable<V, C = unknown, E = unknown, I = unknown>(options: BindableOptions<V>): BindableSpec<V, C, E, I>;
Name
Kind
Type
Requirement
options
parameter
BindableOptions<V>
required
return
return value
BindableSpec<V, C, E, I>
n/a
Name
options
Kind
parameter
Type
BindableOptions<V>
Requirement
required
Name
return
Kind
return value
Type
BindableSpec<V, C, E, I>
Requirement
n/a
DeclarationView source
BindableOptionsts
type BindableOptions<V> = ContextBackedBindableOptions | StateBackedBindableOptions<V>;

BindableSpec

interface
DeclarationView source
BindableSpects
interface BindableSpec<V, C, E, I> {
readonly __kind: "bindable";
readonly prop: string;
readonly defaultProp: string;
readonly stateFor?: (value: V) => string;
readonly valueOf?: (state: string) => V;
set<Cmd extends CommandObject>(fn: (args: ActionArgs<C, E, I> & {
readonly current: V;
}) => V, requestFactory: (value: V, context: C, event: E) => Cmd): BindingSetAction<V, C, E, I, Cmd>;
reset(): BindingResetAction<V, C, E, I>;
}
Name
Kind
Type
Requirement
__kind
property
"bindable"
required
defaultProp
property
string
required
prop
property
string
required
reset
method
() => BindingResetAction<V, C, E, I>
required
set
method
<Cmd extends CommandObject>(fn: (args: ActionArgs<C, E, I> & { readonly current: V; }) => V, requestFactory: (value: V, context: C, event: E) => Cmd) => BindingSetAction<V, C, E, I, Cmd>
required
stateFor
property
(value: V) => string
optional
valueOf
property
(state: string) => V
optional
Name
__kind
Kind
property
Type
"bindable"
Requirement
required
Name
defaultProp
Kind
property
Type
string
Requirement
required
Name
prop
Kind
property
Type
string
Requirement
required
Name
reset
Kind
method
Type
() => BindingResetAction<V, C, E, I>
Requirement
required
Name
set
Kind
method
Type
<Cmd extends CommandObject>(fn: (args: ActionArgs<C, E, I> & { readonly current: V; }) => V, requestFactory: (value: V, context: C, event: E) => Cmd) => BindingSetAction<V, C, E, I, Cmd>
Requirement
required
Name
stateFor
Kind
property
Type
(value: V) => string
Requirement
optional
Name
valueOf
Kind
property
Type
(state: string) => V
Requirement
optional
DeclarationView source
BindingActionts
type BindingAction<V, C, E, I, Cmd extends CommandObject> = BindingSetAction<V, C, E, I, Cmd> | BindingResetAction<V, C, E, I>;

BindingResetAction

interface
DeclarationView source
BindingResetActionts
interface BindingResetAction<V, C, E, I> {
readonly __kind: "binding";
readonly op: "reset";
readonly binding: BindableSpec<V, C, E, I>;
}
Name
Kind
Type
Requirement
__kind
property
"binding"
required
binding
property
BindableSpec<V, C, E, I>
required
op
property
"reset"
required
Name
__kind
Kind
property
Type
"binding"
Requirement
required
Name
binding
Kind
property
Type
BindableSpec<V, C, E, I>
Requirement
required
Name
op
Kind
property
Type
"reset"
Requirement
required

BindingSetAction

interface

Deviation from the addendum, reported verbatim in the phase-5 return: the addendum's `binding.set(fn, requestFactory)` types `fn` as `({ context, event, input }) => V` and `requestFactory` as `(value, ctx) => CommandObject`. Neither signature can express the Switch fixture, which (a) toggles off the *current bound value* (state-backed — not present in `context` at all) and (b) puts `event.reason` (not anything derived from `context`) into the emitted command. Both are required for N4 trace-identity with the handwritten machine, so this layer extends both signatures additively: `fn` gains a `current` field (the binding's current resolved value, via `valueOf`/context lookup) and `requestFactory` gains a trailing `event` parameter. Existing two-arg callers are unaffected — extra fields/args are additive.

DeclarationView source
BindingSetActionts
interface BindingSetAction<V, C, E, I, Cmd extends CommandObject> {
readonly __kind: "binding";
readonly op: "set";
readonly binding: BindableSpec<V, C, E, I>;
readonly fn: (args: ActionArgs<C, E, I> & {
readonly current: V;
}) => V;
readonly requestFactory: (value: V, context: C, event: E) => Cmd;
}
Name
Kind
Type
Requirement
__kind
property
"binding"
required
binding
property
BindableSpec<V, C, E, I>
required
fn
property
(args: ActionArgs<C, E, I> & { readonly current: V; }) => V
required
op
property
"set"
required
requestFactory
property
(value: V, context: C, event: E) => Cmd
required
Name
__kind
Kind
property
Type
"binding"
Requirement
required
Name
binding
Kind
property
Type
BindableSpec<V, C, E, I>
Requirement
required
Name
fn
Kind
property
Type
(args: ActionArgs<C, E, I> & { readonly current: V; }) => V
Requirement
required
Name
op
Kind
property
Type
"set"
Requirement
required
Name
requestFactory
Kind
property
Type
(value: V, context: C, event: E) => Cmd
Requirement
required

Candidate

interface
DeclarationView source
Candidatets
interface Candidate<I, C, E extends EventObject, Cmd extends CommandObject> {
readonly guard?: (args: ActionArgs<C, E, I>) => boolean;
readonly target?: string;
readonly actions?: readonly Action<C, E, I, Cmd>[];
}
Name
Kind
Type
Requirement
actions
property
readonly Action<C, E, I, Cmd>[]
optional
guard
property
(args: ActionArgs<C, E, I>) => boolean
optional
target
property
string
optional
Name
actions
Kind
property
Type
readonly Action<C, E, I, Cmd>[]
Requirement
optional
Name
guard
Kind
property
Type
(args: ActionArgs<C, E, I>) => boolean
Requirement
optional
Name
target
Kind
property
Type
string
Requirement
optional
DeclarationView source
CANDIDATE_KEYSts
export declare const CANDIDATE_KEYS: ReadonlySet<string>;

candidateList

function

The one place a candidate entry (single or array) is normalized to a list.

DeclarationView source
candidateListts
declare function candidateList<I, C, E extends EventObject, Cmd extends CommandObject>(entry: Candidate<I, C, E, Cmd> | readonly Candidate<I, C, E, Cmd>[]): readonly Candidate<I, C, E, Cmd>[];
Name
Kind
Type
Requirement
entry
parameter
Candidate<I, C, E, Cmd> | readonly Candidate<I, C, E, Cmd>[]
required
return
return value
readonly Candidate<I, C, E, Cmd>[]
n/a
Name
entry
Kind
parameter
Type
Candidate<I, C, E, Cmd> | readonly Candidate<I, C, E, Cmd>[]
Requirement
required
Name
return
Kind
return value
Type
readonly Candidate<I, C, E, Cmd>[]
Requirement
n/a

The shared build-time validation core. Everything returned here is rejected by BOTH `toMachine` (throws) and `compileMachine` (throws with the compiler's `{ok, errors}` wording). Compiler-only lints (dead candidates, unreachable states) stay in the compiler package.

DeclarationView source
collectDefinitionIssuests
declare function collectDefinitionIssues(definition: MachineDefinition<any, any, any, any, any>): readonly DefinitionIssue[];
Name
Kind
Type
Requirement
definition
parameter
MachineDefinition<any, any, any, any, any>
required
return
return value
readonly DefinitionIssue[]
n/a
Name
definition
Kind
parameter
Type
MachineDefinition<any, any, any, any, any>
Requirement
required
Name
return
Kind
return value
Type
readonly DefinitionIssue[]
Requirement
n/a

command

function
DeclarationView source
commandts
declare function command<C, E, I, Cmd extends CommandObject>(fn: (args: ActionArgs<C, E, I>) => Cmd): CommandAction<C, E, I, Cmd>;
Name
Kind
Type
Requirement
fn
parameter
(args: ActionArgs<C, E, I>) => Cmd
required
return
return value
CommandAction<C, E, I, Cmd>
n/a
Name
fn
Kind
parameter
Type
(args: ActionArgs<C, E, I>) => Cmd
Requirement
required
Name
return
Kind
return value
Type
CommandAction<C, E, I, Cmd>
Requirement
n/a

CommandAction

interface
DeclarationView source
CommandActionts
interface CommandAction<C, E, I, Cmd extends CommandObject> {
readonly __kind: "command";
readonly fn: (args: ActionArgs<C, E, I>) => Cmd;
}
Name
Kind
Type
Requirement
__kind
property
"command"
required
fn
property
(args: ActionArgs<C, E, I>) => Cmd
required
Name
__kind
Kind
property
Type
"command"
Requirement
required
Name
fn
Kind
property
Type
(args: ActionArgs<C, E, I>) => Cmd
Requirement
required

defineMachine

function

Typed authoring entry point. Unknown top-level, per-state and per-candidate keys are rejected both at the type level (TypeScript's excess-property check on the object literal argument) and here at runtime, so a definition that reaches a consumer through a non-literal path (spread, `as`, JS caller) still fails loudly instead of silently accepting an unsupported extension (nested/parallel states, history, entry/exit, etc. — see the addendum's "Not needed" list).

DeclarationView source
defineMachinets
declare function defineMachine<I, V extends StateValue, C, E extends EventObject, Cmd extends CommandObject = never>(definition: MachineDefinition<I, V, C, E, Cmd>): MachineDefinition<I, V, C, E, Cmd>;
Name
Kind
Type
Requirement
definition
parameter
MachineDefinition<I, V, C, E, Cmd>
required
return
return value
MachineDefinition<I, V, C, E, Cmd>
n/a
Name
definition
Kind
parameter
Type
MachineDefinition<I, V, C, E, Cmd>
Requirement
required
Name
return
Kind
return value
Type
MachineDefinition<I, V, C, E, Cmd>
Requirement
n/a

DefinitionIssue

interface
DeclarationView source
DefinitionIssuets
interface DefinitionIssue {
readonly code: string;
readonly message: string;
readonly path: string;
}
Name
Kind
Type
Requirement
code
property
string
required
message
property
string
required
path
property
string
required
Name
code
Kind
property
Type
string
Requirement
required
Name
message
Kind
property
Type
string
Requirement
required
Name
path
Kind
property
Type
string
Requirement
required

MACHINE_KEYS

value
DeclarationView source
MACHINE_KEYSts
export declare const MACHINE_KEYS: ReadonlySet<string>;

MachineDefinition

interface
DeclarationView source
MachineDefinitionts
interface MachineDefinition<I, V extends StateValue, C, E extends EventObject, Cmd extends CommandObject = never> {
readonly id: string;
readonly types?: {
readonly input: I;
readonly context: C;
readonly events: E;
readonly commands: Cmd;
};
readonly bindings?: Readonly<Record<string, BindableSpec<any, C, E, I>>>;
readonly context: (args: {
readonly input: I;
readonly bindings: Readonly<Record<string, unknown>>;
}) => C;
readonly initial: string | ((args: {
readonly input: I;
}) => string);
readonly states: Readonly<Record<string, StateDefinition<I, C, E, Cmd>>>;
}
Name
Kind
Type
Requirement
bindings
property
Readonly<Record<string, BindableSpec<any, C, E, I>>>
optional
context
property
(args: { readonly input: I; readonly bindings: Readonly<Record<string, unknown>>; }) => C
required
id
property
string
required
initial
property
string | ((args: { readonly input: I; }) => string)
required
states
property
Readonly<Record<string, StateDefinition<I, C, E, Cmd>>>
required
types
property
{ readonly input: I; readonly context: C; readonly events: E; readonly commands: Cmd; }
optional
Name
bindings
Kind
property
Type
Readonly<Record<string, BindableSpec<any, C, E, I>>>
Requirement
optional
Name
context
Kind
property
Type
(args: { readonly input: I; readonly bindings: Readonly<Record<string, unknown>>; }) => C
Requirement
required
Name
id
Kind
property
Type
string
Requirement
required
Name
initial
Kind
property
Type
string | ((args: { readonly input: I; }) => string)
Requirement
required
Name
states
Kind
property
Type
Readonly<Record<string, StateDefinition<I, C, E, Cmd>>>
Requirement
required
Name
types
Kind
property
Type
{ readonly input: I; readonly context: C; readonly events: E; readonly commands: Cmd; }
Requirement
optional

STATE_KEYS

value
DeclarationView source
STATE_KEYSts
export declare const STATE_KEYS: ReadonlySet<string>;

StateDefinition

interface
DeclarationView source
StateDefinitionts
interface StateDefinition<I, C, E extends EventObject, Cmd extends CommandObject> {
readonly on?: Readonly<Record<string, Candidate<I, C, E, Cmd> | readonly Candidate<I, C, E, Cmd>[]>>;
}
Name
Kind
Type
Requirement
on
property
Readonly<Record<string, Candidate<I, C, E, Cmd> | readonly Candidate<I, C, E, Cmd>[]>>
optional
Name
on
Kind
property
Type
Readonly<Record<string, Candidate<I, C, E, Cmd> | readonly Candidate<I, C, E, Cmd>[]>>
Requirement
optional

toMachine

function

The tree-shakable one-time normalizer: authored definition → low-level `Machine`. Implements N1–N4 from docs/decisions/statechart-api.md.

DeclarationView source
toMachinets
declare function toMachine<I, V extends StateValue, C, E extends EventObject, Cmd extends CommandObject = never>(definition: MachineDefinition<I, V, C, E, Cmd>): Machine<I, V, C, E, Cmd>;
Name
Kind
Type
Requirement
definition
parameter
MachineDefinition<I, V, C, E, Cmd>
required
return
return value
Machine<I, V, C, E, Cmd>
n/a
Name
definition
Kind
parameter
Type
MachineDefinition<I, V, C, E, Cmd>
Requirement
required
Name
return
Kind
return value
Type
Machine<I, V, C, E, Cmd>
Requirement
n/a

@grassroot/statechart/inspect

inspect

16 exports
View source packages/statechart/src/inspect/index.ts

attachInspector

function
DeclarationView source
attachInspectorts
declare function attachInspector<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machineId: string, emit: (record: InspectorRecord) => void, inspectorOptions?: InspectorOptions): () => void;
Name
Kind
Type
Requirement
service
parameter
Service<Input, Value, Context, Event, Command, Output>
required
machineId
parameter
string
required
emit
parameter
(record: InspectorRecord) => void
required
inspectorOptions
parameter
InspectorOptions
optional
return
return value
() => void
n/a
Name
service
Kind
parameter
Type
Service<Input, Value, Context, Event, Command, Output>
Requirement
required
Name
machineId
Kind
parameter
Type
string
Requirement
required
Name
emit
Kind
parameter
Type
(record: InspectorRecord) => void
Requirement
required
Name
inspectorOptions
Kind
parameter
Type
InspectorOptions
Requirement
optional
Name
return
Kind
return value
Type
() => void
Requirement
n/a

Attach protocol-v2 observation to an already-created service. This post-construction path cannot observe commands or diagnostics, so its transition records contain empty arrays for those fields. Callers that own service construction can wrap those option channels separately.

DeclarationView source
attachInspectorV2ts
declare function attachInspectorV2<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, meta: {
readonly serviceId: string;
readonly machineId: string;
}, emit: (record: InspectorRecordV2) => void, options?: {
readonly now?: () => number;
}): () => void;
Name
Kind
Type
Requirement
service
parameter
Service<Input, Value, Context, Event, Command, Output>
required
meta
parameter
{ readonly serviceId: string; readonly machineId: string; }
required
emit
parameter
(record: InspectorRecordV2) => void
required
options
parameter
{ readonly now?: () => number; }
optional
return
return value
() => void
n/a
Name
service
Kind
parameter
Type
Service<Input, Value, Context, Event, Command, Output>
Requirement
required
Name
meta
Kind
parameter
Type
{ readonly serviceId: string; readonly machineId: string; }
Requirement
required
Name
emit
Kind
parameter
Type
(record: InspectorRecordV2) => void
Requirement
required
Name
options
Kind
parameter
Type
{ readonly now?: () => number; }
Requirement
optional
Name
return
Kind
return value
Type
() => void
Requirement
n/a

DevtoolsHook

interface
DeclarationView source
DevtoolsHookts
interface DevtoolsHook extends DevtoolsRegistrationHook {
unregister(serviceId: string): void;
list(): readonly DevtoolsServiceMeta[];
subscribe(listener: (meta: DevtoolsServiceMeta, record: InspectorRecordV2) => void): () => void;
}
Name
Kind
Type
Requirement
list
method
() => readonly DevtoolsServiceMeta[]
required
subscribe
method
(listener: (meta: DevtoolsServiceMeta, record: InspectorRecordV2) => void) => () => void
required
unregister
method
(serviceId: string) => void
required
Name
list
Kind
method
Type
() => readonly DevtoolsServiceMeta[]
Requirement
required
Name
subscribe
Kind
method
Type
(listener: (meta: DevtoolsServiceMeta, record: InspectorRecordV2) => void) => () => void
Requirement
required
Name
unregister
Kind
method
Type
(serviceId: string) => void
Requirement
required

Minimal hook surface needed by framework adapters during registration.

DeclarationView source
DevtoolsRegistrationHookts
interface DevtoolsRegistrationHook {
readonly hookVersion: number;
register<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machine: Machine<Input, Value, Context, Event, Command, Output>, meta: Omit<DevtoolsServiceMeta, "mountedAt">): () => void;
}
Name
Kind
Type
Requirement
hookVersion
property
number
required
register
method
<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machine: Machine<Input, Value, Context, Event, Command, Output>, meta: Omit<DevtoolsServiceMeta, "mountedAt">) => () => void
required
Name
hookVersion
Kind
property
Type
number
Requirement
required
Name
register
Kind
method
Type
<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machine: Machine<Input, Value, Context, Event, Command, Output>, meta: Omit<DevtoolsServiceMeta, "mountedAt">) => () => void
Requirement
required
DeclarationView source
DevtoolsServiceMetats
interface DevtoolsServiceMeta {
readonly serviceId: string;
readonly machineId: string;
readonly componentKey: string;
readonly framework: "react" | "vue" | "solid" | "svelte" | "angular" | "vanilla";
readonly scopeSeed: string;
readonly mountedAt: number;
}
Name
Kind
Type
Requirement
componentKey
property
string
required
framework
property
"react" | "vue" | "solid" | "svelte" | "angular" | "vanilla"
required
machineId
property
string
required
mountedAt
property
number
required
scopeSeed
property
string
required
serviceId
property
string
required
Name
componentKey
Kind
property
Type
string
Requirement
required
Name
framework
Kind
property
Type
"react" | "vue" | "solid" | "svelte" | "angular" | "vanilla"
Requirement
required
Name
machineId
Kind
property
Type
string
Requirement
required
Name
mountedAt
Kind
property
Type
number
Requirement
required
Name
scopeSeed
Kind
property
Type
string
Requirement
required
Name
serviceId
Kind
property
Type
string
Requirement
required
DeclarationView source
HOOK_GLOBAL_KEYts
export declare const HOOK_GLOBAL_KEY: "__GRASSROOT_DEVTOOLS_HOOK__";

HOOK_VERSION

value
DeclarationView source
HOOK_VERSIONts
export declare const HOOK_VERSION: 1;
DeclarationView source
INSPECTOR_PROTOCOL_VERSIONts
export declare const INSPECTOR_PROTOCOL_VERSION: 1;
DeclarationView source
INSPECTOR_PROTOCOL_VERSION_2ts
export declare const INSPECTOR_PROTOCOL_VERSION_2: 2;

InspectorOptions

interface
DeclarationView source
InspectorOptionsts
interface InspectorOptions {
now?: () => number;
}
Name
Kind
Type
Requirement
now
property
() => number
optional
Name
now
Kind
property
Type
() => number
Requirement
optional
DeclarationView source
InspectorRecordts
type InspectorRecord = {
protocol: 1;
kind: "snapshot";
machineId: string;
version: number;
status: string;
value: StateValue;
at: number;
} | {
protocol: 1;
kind: "command";
machineId: string;
command: CommandObject;
at: number;
} | {
protocol: 1;
kind: "diagnostic";
machineId: string;
diagnostic: DiagnosticObject;
at: number;
} | {
protocol: 1;
kind: "error";
machineId: string;
phase: string;
at: number;
};
DeclarationView source
InspectorRecordV2ts
type InspectorRecordV2 = (RecordBase & {
readonly kind: "snapshot";
readonly version: number;
readonly status: Snapshot<any, any, any>["status"];
readonly value: StateValue;
readonly context: unknown;
}) | (RecordBase & {
readonly kind: "event";
readonly event: EventObject;
readonly queuePosition: number;
readonly source: "external" | "command" | "scheduled";
}) | (RecordBase & {
readonly kind: "transition";
readonly from: StateValue;
readonly to: StateValue;
readonly event: EventObject;
readonly commands: readonly CommandObject[];
readonly diagnostics: readonly DiagnosticObject[];
readonly durationMs: number;
}) | (RecordBase & {
readonly kind: "input";
readonly prev: unknown;
readonly next: unknown;
}) | (RecordBase & {
readonly kind: "lifecycle";
readonly phase: "start" | "stop";
}) | (RecordBase & {
readonly kind: "command";
readonly command: CommandObject;
}) | (RecordBase & {
readonly kind: "diagnostic";
readonly diagnostic: DiagnosticObject;
}) | (RecordBase & {
readonly kind: "error";
readonly phase: string;
});

RedactHook

type
DeclarationView source
RedactHookts
type RedactHook = (path: readonly (string | number)[], value: unknown) => JsonValue | undefined;

registerWithHook

function
DeclarationView source
registerWithHookts
declare function registerWithHook<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machine: Machine<Input, Value, Context, Event, Command, Output>, meta: Omit<DevtoolsServiceMeta, "mountedAt">): (() => void) | undefined;
Name
Kind
Type
Requirement
service
parameter
Service<Input, Value, Context, Event, Command, Output>
required
machine
parameter
Machine<Input, Value, Context, Event, Command, Output>
required
meta
parameter
Omit<DevtoolsServiceMeta, "mountedAt">
required
return
return value
(() => void) | undefined
n/a
Name
service
Kind
parameter
Type
Service<Input, Value, Context, Event, Command, Output>
Requirement
required
Name
machine
Kind
parameter
Type
Machine<Input, Value, Context, Event, Command, Output>
Requirement
required
Name
meta
Kind
parameter
Type
Omit<DevtoolsServiceMeta, "mountedAt">
Requirement
required
Name
return
Kind
return value
Type
(() => void) | undefined
Requirement
n/a

serializeContext

function

Convert arbitrary context to JSON-safe data without ever throwing.

DeclarationView source
serializeContextts
declare function serializeContext(context: unknown, redact?: RedactHook): JsonValue;
Name
Kind
Type
Requirement
context
parameter
unknown
required
redact
parameter
RedactHook
optional
return
return value
JsonValue
n/a
Name
context
Kind
parameter
Type
unknown
Requirement
required
Name
redact
Kind
parameter
Type
RedactHook
Requirement
optional
Name
return
Kind
return value
Type
JsonValue
Requirement
n/a

withInspector

function
DeclarationView source
withInspectorts
declare function withInspector<Opts extends ServiceOptionsConstraint>(machineId: string, options: Opts, emit: (record: InspectorRecord) => void, inspectorOptions?: InspectorOptions): Opts;
Name
Kind
Type
Requirement
machineId
parameter
string
required
options
parameter
Opts
required
emit
parameter
(record: InspectorRecord) => void
required
inspectorOptions
parameter
InspectorOptions
optional
return
return value
Opts
n/a
Name
machineId
Kind
parameter
Type
string
Requirement
required
Name
options
Kind
parameter
Type
Opts
Requirement
required
Name
emit
Kind
parameter
Type
(record: InspectorRecord) => void
Requirement
required
Name
inspectorOptions
Kind
parameter
Type
InspectorOptions
Requirement
optional
Name
return
Kind
return value
Type
Opts
Requirement
n/a

@grassroot/statechart/inspect/register

inspect/register

5 exports
View source packages/statechart/src/inspect/register.ts

Minimal hook surface needed by framework adapters during registration.

DeclarationView source
DevtoolsRegistrationHookts
interface DevtoolsRegistrationHook {
readonly hookVersion: number;
register<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machine: Machine<Input, Value, Context, Event, Command, Output>, meta: Omit<DevtoolsServiceMeta, "mountedAt">): () => void;
}
Name
Kind
Type
Requirement
hookVersion
property
number
required
register
method
<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machine: Machine<Input, Value, Context, Event, Command, Output>, meta: Omit<DevtoolsServiceMeta, "mountedAt">) => () => void
required
Name
hookVersion
Kind
property
Type
number
Requirement
required
Name
register
Kind
method
Type
<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machine: Machine<Input, Value, Context, Event, Command, Output>, meta: Omit<DevtoolsServiceMeta, "mountedAt">) => () => void
Requirement
required
DeclarationView source
DevtoolsServiceMetats
interface DevtoolsServiceMeta {
readonly serviceId: string;
readonly machineId: string;
readonly componentKey: string;
readonly framework: "react" | "vue" | "solid" | "svelte" | "angular" | "vanilla";
readonly scopeSeed: string;
readonly mountedAt: number;
}
Name
Kind
Type
Requirement
componentKey
property
string
required
framework
property
"react" | "vue" | "solid" | "svelte" | "angular" | "vanilla"
required
machineId
property
string
required
mountedAt
property
number
required
scopeSeed
property
string
required
serviceId
property
string
required
Name
componentKey
Kind
property
Type
string
Requirement
required
Name
framework
Kind
property
Type
"react" | "vue" | "solid" | "svelte" | "angular" | "vanilla"
Requirement
required
Name
machineId
Kind
property
Type
string
Requirement
required
Name
mountedAt
Kind
property
Type
number
Requirement
required
Name
scopeSeed
Kind
property
Type
string
Requirement
required
Name
serviceId
Kind
property
Type
string
Requirement
required
DeclarationView source
HOOK_GLOBAL_KEYts
export declare const HOOK_GLOBAL_KEY: "__GRASSROOT_DEVTOOLS_HOOK__";

HOOK_VERSION

value
DeclarationView source
HOOK_VERSIONts
export declare const HOOK_VERSION: 1;

registerWithHook

function
DeclarationView source
registerWithHookts
declare function registerWithHook<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output>(service: Service<Input, Value, Context, Event, Command, Output>, machine: Machine<Input, Value, Context, Event, Command, Output>, meta: Omit<DevtoolsServiceMeta, "mountedAt">): (() => void) | undefined;
Name
Kind
Type
Requirement
service
parameter
Service<Input, Value, Context, Event, Command, Output>
required
machine
parameter
Machine<Input, Value, Context, Event, Command, Output>
required
meta
parameter
Omit<DevtoolsServiceMeta, "mountedAt">
required
return
return value
(() => void) | undefined
n/a
Name
service
Kind
parameter
Type
Service<Input, Value, Context, Event, Command, Output>
Requirement
required
Name
machine
Kind
parameter
Type
Machine<Input, Value, Context, Event, Command, Output>
Requirement
required
Name
meta
Kind
parameter
Type
Omit<DevtoolsServiceMeta, "mountedAt">
Requirement
required
Name
return
Kind
return value
Type
(() => void) | undefined
Requirement
n/a

@grassroot/statechart/persist

persist

6 exports
View source packages/statechart/src/persist/index.ts

v1 → v2 migration (DR-2). v1 had no `output` field; a v1 payload migrates by re-stamping the schema. Throws on payloads that are not v1-shaped enough to migrate (schema !== 1).

DeclarationView source
migratePersistedSnapshotts
declare function migratePersistedSnapshot(data: unknown): PersistedSnapshot;
Name
Kind
Type
Requirement
data
parameter
unknown
required
return
return value
PersistedSnapshot
n/a
Name
data
Kind
parameter
Type
unknown
Requirement
required
Name
return
Kind
return value
Type
PersistedSnapshot
Requirement
n/a

PersistedSnapshot

interface
DeclarationView source
PersistedSnapshotts
interface PersistedSnapshot {
readonly schema: typeof SNAPSHOT_SCHEMA_VERSION;
readonly machineId: string;
readonly value: StateValue;
readonly context: JsonValue;
readonly version: number;
readonly status: "idle" | "active" | "done" | "stopped" | "error";
readonly output?: JsonValue;
}
Name
Kind
Type
Requirement
context
property
JsonValue
required
machineId
property
string
required
output
property
JsonValue
optional
schema
property
typeof SNAPSHOT_SCHEMA_VERSION
required
status
property
"idle" | "active" | "done" | "stopped" | "error"
required
value
property
StateValue
required
version
property
number
required
Name
context
Kind
property
Type
JsonValue
Requirement
required
Name
machineId
Kind
property
Type
string
Requirement
required
Name
output
Kind
property
Type
JsonValue
Requirement
optional
Name
schema
Kind
property
Type
typeof SNAPSHOT_SCHEMA_VERSION
Requirement
required
Name
status
Kind
property
Type
"idle" | "active" | "done" | "stopped" | "error"
Requirement
required
Name
value
Kind
property
Type
StateValue
Requirement
required
Name
version
Kind
property
Type
number
Requirement
required

restoreService

function
DeclarationView source
restoreServicets
declare function restoreService(): never;
Name
Kind
Type
Requirement
return
return value
never
n/a
Name
return
Kind
return value
Type
never
Requirement
n/a
DeclarationView source
serializeSnapshotts
declare function serializeSnapshot(machineId: string, snapshot: Snapshot<any, any, any>): PersistedSnapshot;
Name
Kind
Type
Requirement
machineId
parameter
string
required
snapshot
parameter
Snapshot<any, any, any>
required
return
return value
PersistedSnapshot
n/a
Name
machineId
Kind
parameter
Type
string
Requirement
required
Name
snapshot
Kind
parameter
Type
Snapshot<any, any, any>
Requirement
required
Name
return
Kind
return value
Type
PersistedSnapshot
Requirement
n/a
DeclarationView source
SNAPSHOT_SCHEMA_VERSIONts
export declare const SNAPSHOT_SCHEMA_VERSION: 2;
DeclarationView source
validatePersistedSnapshotts
declare function validatePersistedSnapshot(machineId: string, data: unknown): {
ok: true;
snapshot: PersistedSnapshot;
} | {
ok: false;
reason: "schema-version-mismatch" | "machine-mismatch" | "malformed";
detail: string;
};
Name
Kind
Type
Requirement
machineId
parameter
string
required
data
parameter
unknown
required
return
return value
{ ok: true; snapshot: PersistedSnapshot; } | { ok: false; reason: "schema-version-mismatch" | "machine-mismatch" | "malformed"; detail: string; }
n/a
Name
machineId
Kind
parameter
Type
string
Requirement
required
Name
data
Kind
parameter
Type
unknown
Requirement
required
Name
return
Kind
return value
Type
{ ok: true; snapshot: PersistedSnapshot; } | { ok: false; reason: "schema-version-mismatch" | "machine-mismatch" | "malformed"; detail: string; }
Requirement
n/a

@grassroot/statechart/scheduler

scheduler

12 exports
View source packages/statechart/src/scheduler/index.ts

Reserved command: cancel the pending timer under `key`; no-op if absent.

DeclarationView source
CancelCommandts
type CancelCommand = {
readonly type: "statechart.cancel";
readonly key: string;
};
Name
Kind
Type
Requirement
key
property
string
required
type
property
"statechart.cancel"
required
Name
key
Kind
property
Type
string
Requirement
required
Name
type
Kind
property
Type
"statechart.cancel"
Requirement
required
DeclarationView source
createNativeSchedulerts
declare function createNativeScheduler(): Scheduler;
Name
Kind
Type
Requirement
return
return value
Scheduler
n/a
Name
return
Kind
return value
Type
Scheduler
Requirement
n/a

Decorate `next` with scheduled-event support. Keys are scoped to this runner instance (one runner = one service): a same-key `schedule` replaces the pending timer, `cancel` clears it (no-op when absent), and a fired timer delivers its event through the ordinary `send` given to the command that scheduled it — joining the FIFO queue as an external event (S1). Every scheduling command's `AbortSignal` gets an abort listener that clears its timer; `stop()`/error (S4/S5) aborts every pending timer for the service, and the runner never calls `send` after abort.

DeclarationView source
createScheduledEventRunnerts
declare function createScheduledEventRunner<Command extends CommandObject, Event extends EventObject>(scheduler: Scheduler, next?: RunCommand<Command, Event>): RunCommand<Command | ScheduledEventCommand<Event>, Event>;
Name
Kind
Type
Requirement
scheduler
parameter
Scheduler
required
next
parameter
RunCommand<Command, Event>
optional
return
return value
RunCommand<Command | ScheduledEventCommand<Event>, Event>
n/a
Name
scheduler
Kind
parameter
Type
Scheduler
Requirement
required
Name
next
Kind
parameter
Type
RunCommand<Command, Event>
Requirement
optional
Name
return
Kind
return value
Type
RunCommand<Command | ScheduledEventCommand<Event>, Event>
Requirement
n/a
DeclarationView source
createVirtualSchedulerts
declare function createVirtualScheduler(): VirtualScheduler;
Name
Kind
Type
Requirement
return
return value
VirtualScheduler
n/a
Name
return
Kind
return value
Type
VirtualScheduler
Requirement
n/a

RunCommand

type

`runCommand`-compatible function shape (same signature as `createService`'s `options.runCommand`).

DeclarationView source
RunCommandts
type RunCommand<Command extends CommandObject, Event extends EventObject> = (command: Command, tools: RunCommandTools<Event>) => void | (() => void);

RunCommandTools

interface

`runCommand`-compatible tools, matching `createService`'s option shape.

DeclarationView source
RunCommandToolsts
interface RunCommandTools<Event extends EventObject> {
readonly send: (event: Event) => void;
readonly signal: AbortSignal;
}
Name
Kind
Type
Requirement
send
property
(event: Event) => void
required
signal
property
AbortSignal
required
Name
send
Kind
property
Type
(event: Event) => void
Requirement
required
Name
signal
Kind
property
Type
AbortSignal
Requirement
required

S13 — scheduled events (docs/decisions/statechart-semantics.md). `createScheduledEventRunner` is a `runCommand` decorator: it interprets two reserved command shapes over the given `Scheduler` and forwards every other command to `next` (the component's own runner) unchanged, with the same `tools`. Reserved command: schedule `send(event)` after `delayMs`. Same-key scheduling replaces the pending timer (cancel-then-schedule).

DeclarationView source
ScheduleCommandts
type ScheduleCommand<Event extends EventObject = EventObject> = {
readonly type: "statechart.schedule";
readonly key: string;
readonly event: Event;
readonly delayMs: number;
};
Name
Kind
Type
Requirement
delayMs
property
number
required
event
property
Event
required
key
property
string
required
type
property
"statechart.schedule"
required
Name
delayMs
Kind
property
Type
number
Requirement
required
Name
event
Kind
property
Type
Event
Requirement
required
Name
key
Kind
property
Type
string
Requirement
required
Name
type
Kind
property
Type
"statechart.schedule"
Requirement
required

Union of the two reserved command shapes this runner interprets.

DeclarationView source
ScheduledEventCommandts
type ScheduledEventCommand<Event extends EventObject = EventObject> = ScheduleCommand<Event> | CancelCommand;

Scheduler

interface
DeclarationView source
Schedulerts
interface Scheduler {
now(): number;
setTimeout(callback: () => void, delayMs: number): SchedulerHandle;
clearTimeout(handle: SchedulerHandle): void;
}
Name
Kind
Type
Requirement
clearTimeout
method
(handle: SchedulerHandle) => void
required
now
method
() => number
required
setTimeout
method
(callback: () => void, delayMs: number) => SchedulerHandle
required
Name
clearTimeout
Kind
method
Type
(handle: SchedulerHandle) => void
Requirement
required
Name
now
Kind
method
Type
() => number
Requirement
required
Name
setTimeout
Kind
method
Type
(callback: () => void, delayMs: number) => SchedulerHandle
Requirement
required
DeclarationView source
SchedulerHandlets
type SchedulerHandle = {
readonly __brand: "SchedulerHandle";
};
Name
Kind
Type
Requirement
__brand
property
"SchedulerHandle"
required
Name
__brand
Kind
property
Type
"SchedulerHandle"
Requirement
required
DeclarationView source
VIRTUAL_SCHEDULER_MAX_TASKS_PER_RUNts
export declare const VIRTUAL_SCHEDULER_MAX_TASKS_PER_RUN: 10000;

VirtualScheduler

interface
DeclarationView source
VirtualSchedulerts
interface VirtualScheduler extends Scheduler {
advance(byMs: number): void;
flush(): void;
pendingCount(): number;
}
Name
Kind
Type
Requirement
advance
method
(byMs: number) => void
required
flush
method
() => void
required
pendingCount
method
() => number
required
Name
advance
Kind
method
Type
(byMs: number) => void
Requirement
required
Name
flush
Kind
method
Type
() => void
Requirement
required
Name
pendingCount
Kind
method
Type
() => number
Requirement
required

@grassroot/statechart/service

service

1 exports
View source packages/statechart/src/service.ts

createService

function
DeclarationView source
createServicets
declare function createService<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output = never>(machine: Machine<Input, Value, Context, Event, Command, Output>, options: {
input: Input;
runCommand?: (command: Command, tools: {
send: (event: Event) => void;
signal: AbortSignal;
}) => void | (() => void);
onDiagnostic?: (diagnostic: DiagnosticObject & {
readonly machineId: string;
}) => void;
onError?: (error: ServiceError<Value, Context, Event, Command, Output>) => void;
}): Service<Input, Value, Context, Event, Command, Output>;
Name
Kind
Type
Requirement
machine
parameter
Machine<Input, Value, Context, Event, Command, Output>
required
options
parameter
{ input: Input; runCommand?: (command: Command, tools: { send: (event: Event) => void; signal: AbortSignal; }) => void | (() => void); onDiagnostic?: (diagnostic: DiagnosticObject & { readonly machineId: string; }) => void; onError?: (error: ServiceError<Value, Context, Event, Command, Output>) => void; }
required
return
return value
Service<Input, Value, Context, Event, Command, Output>
n/a
Name
machine
Kind
parameter
Type
Machine<Input, Value, Context, Event, Command, Output>
Requirement
required
Name
options
Kind
parameter
Type
{ input: Input; runCommand?: (command: Command, tools: { send: (event: Event) => void; signal: AbortSignal; }) => void | (() => void); onDiagnostic?: (diagnostic: DiagnosticObject & { readonly machineId: string; }) => void; onError?: (error: ServiceError<Value, Context, Event, Command, Output>) => void; }
Requirement
required
Name
return
Kind
return value
Type
Service<Input, Value, Context, Event, Command, Output>
Requirement
n/a

@grassroot/statechart/types

types

11 exports
View source packages/statechart/src/types.ts
DeclarationView source
CommandObjectts
type CommandObject = {
readonly type: string;
readonly [key: string]: JsonValue;
};
Name
Kind
Type
Requirement
type
property
string
required
Name
type
Kind
property
Type
string
Requirement
required
DeclarationView source
DiagnosticObjectts
type DiagnosticObject = {
readonly code: string;
readonly message: string;
readonly severity: "warning" | "error";
readonly data?: JsonValue;
};
Name
Kind
Type
Requirement
code
property
string
required
data
property
JsonValue
optional
message
property
string
required
severity
property
"warning" | "error"
required
Name
code
Kind
property
Type
string
Requirement
required
Name
data
Kind
property
Type
JsonValue
Requirement
optional
Name
message
Kind
property
Type
string
Requirement
required
Name
severity
Kind
property
Type
"warning" | "error"
Requirement
required
DeclarationView source
EventObjectts
type EventObject = {
readonly type: string;
};
Name
Kind
Type
Requirement
type
property
string
required
Name
type
Kind
property
Type
string
Requirement
required

JsonValue

type

The low-level `@grassroot/statechart` contract, frozen in phase 0 of GRASSROOT_STATECHART_EXECUTION_PLAN.md. The shapes here are lifted verbatim from GRASSROOT_STATECHART_PLATFORM_PLAN.md ("Native statechart model"). Decision records: docs/decisions/statechart-api.md and docs/decisions/statechart-semantics.md. The authoring layer (phase 5) must compile to this contract with identical semantics. This file is types plus one declaration only — no runtime code ships in phase 0. `createService` is implemented in phase 1 (src/service.ts).

DeclarationView source
JsonValuets
type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
readonly [key: string]: JsonValue;
};

Machine

interface
DeclarationView source
Machinets
interface Machine<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject = never, Output = never> {
readonly id: string;
initial(input: Readonly<Input>): Transition<Value, Context, Command, Output>;
transition(state: MachineState<Value, Context, Output>, event: Readonly<Event>, input: Readonly<Input>): Transition<Value, Context, Command, Output>;
sync?(state: MachineState<Value, Context, Output>, previous: Readonly<Input>, next: Readonly<Input>): Transition<Value, Context, Command, Output>;
}
Name
Kind
Type
Requirement
id
property
string
required
initial
method
(input: Readonly<Input>) => Transition<Value, Context, Command, Output>
required
sync
method
((state: MachineState<Value, Context, Output>, previous: Readonly<Input>, next: Readonly<Input>) => Transition<Value, Context, Command, Output>) | undefined
optional
transition
method
(state: MachineState<Value, Context, Output>, event: Readonly<Event>, input: Readonly<Input>) => Transition<Value, Context, Command, Output>
required
Name
id
Kind
property
Type
string
Requirement
required
Name
initial
Kind
method
Type
(input: Readonly<Input>) => Transition<Value, Context, Command, Output>
Requirement
required
Name
sync
Kind
method
Type
((state: MachineState<Value, Context, Output>, previous: Readonly<Input>, next: Readonly<Input>) => Transition<Value, Context, Command, Output>) | undefined
Requirement
optional
Name
transition
Kind
method
Type
(state: MachineState<Value, Context, Output>, event: Readonly<Event>, input: Readonly<Input>) => Transition<Value, Context, Command, Output>
Requirement
required

MachineState

interface
DeclarationView source
MachineStatets
interface MachineState<Value extends StateValue, Context, Output = never> {
readonly value: Value;
readonly context: Readonly<Context>;
readonly output?: Output;
}
Name
Kind
Type
Requirement
context
property
Readonly<Context>
required
output
property
Output
optional
value
property
Value
required
Name
context
Kind
property
Type
Readonly<Context>
Requirement
required
Name
output
Kind
property
Type
Output
Requirement
optional
Name
value
Kind
property
Type
Value
Requirement
required

Service

interface
DeclarationView source
Servicets
interface Service<Input, Value extends StateValue, Context, Event extends EventObject, Command extends CommandObject, Output = never> {
start(): void;
stop(): void;
getSnapshot(): Snapshot<Value, Context, Output>;
getInput(): Readonly<Input>;
send(event: Event): Snapshot<Value, Context, Output>;
setInput(next: Input): Snapshot<Value, Context, Output>;
subscribe<Selected>(selector: (snapshot: Snapshot<Value, Context, Output>) => Selected, listener: (value: Selected, previous: Selected) => void, options?: {
equals?: (a: Selected, b: Selected) => boolean;
immediate?: boolean;
}): () => void;
batch<Result>(work: () => Result): Result;
}
Name
Kind
Type
Requirement
batch
method
<Result>(work: () => Result) => Result
required
getInput
method
() => Readonly<Input>
required
getSnapshot
method
() => Snapshot<Value, Context, Output>
required
send
method
(event: Event) => Snapshot<Value, Context, Output>
required
setInput
method
(next: Input) => Snapshot<Value, Context, Output>
required
start
method
() => void
required
stop
method
() => void
required
subscribe
method
<Selected>(selector: (snapshot: Snapshot<Value, Context, Output>) => Selected, listener: (value: Selected, previous: Selected) => void, options?: { equals?: (a: Selected, b: Selected) => boolean; immediate?: boolean; }) => () => void
required
Name
batch
Kind
method
Type
<Result>(work: () => Result) => Result
Requirement
required
Name
getInput
Kind
method
Type
() => Readonly<Input>
Requirement
required
Name
getSnapshot
Kind
method
Type
() => Snapshot<Value, Context, Output>
Requirement
required
Name
send
Kind
method
Type
(event: Event) => Snapshot<Value, Context, Output>
Requirement
required
Name
setInput
Kind
method
Type
(next: Input) => Snapshot<Value, Context, Output>
Requirement
required
Name
start
Kind
method
Type
() => void
Requirement
required
Name
stop
Kind
method
Type
() => void
Requirement
required
Name
subscribe
Kind
method
Type
<Selected>(selector: (snapshot: Snapshot<Value, Context, Output>) => Selected, listener: (value: Selected, previous: Selected) => void, options?: { equals?: (a: Selected, b: Selected) => boolean; immediate?: boolean; }) => () => void
Requirement
required

ServiceError

interface
DeclarationView source
ServiceErrorts
interface ServiceError<Value extends StateValue, Context, Event, Command, Output = never> {
readonly phase: "start" | "transition" | "sync" | "diagnostic" | "command";
readonly cause: unknown;
readonly machineId: string;
readonly snapshot: Snapshot<Value, Context, Output>;
readonly event?: Event;
readonly diagnostic?: DiagnosticObject;
readonly command?: Command;
}
Name
Kind
Type
Requirement
cause
property
unknown
required
command
property
Command
optional
diagnostic
property
DiagnosticObject
optional
event
property
Event
optional
machineId
property
string
required
phase
property
"start" | "transition" | "sync" | "diagnostic" | "command"
required
snapshot
property
Snapshot<Value, Context, Output>
required
Name
cause
Kind
property
Type
unknown
Requirement
required
Name
command
Kind
property
Type
Command
Requirement
optional
Name
diagnostic
Kind
property
Type
DiagnosticObject
Requirement
optional
Name
event
Kind
property
Type
Event
Requirement
optional
Name
machineId
Kind
property
Type
string
Requirement
required
Name
phase
Kind
property
Type
"start" | "transition" | "sync" | "diagnostic" | "command"
Requirement
required
Name
snapshot
Kind
property
Type
Snapshot<Value, Context, Output>
Requirement
required

Snapshot

interface
DeclarationView source
Snapshotts
interface Snapshot<Value extends StateValue, Context, Output = never> {
readonly value: Value;
readonly context: Readonly<Context>;
readonly version: number;
readonly status: "idle" | "active" | "done" | "stopped" | "error";
readonly output?: Output;
readonly error?: unknown;
}
Name
Kind
Type
Requirement
context
property
Readonly<Context>
required
error
property
unknown
optional
output
property
Output
optional
status
property
"idle" | "active" | "done" | "stopped" | "error"
required
value
property
Value
required
version
property
number
required
Name
context
Kind
property
Type
Readonly<Context>
Requirement
required
Name
error
Kind
property
Type
unknown
Requirement
optional
Name
output
Kind
property
Type
Output
Requirement
optional
Name
status
Kind
property
Type
"idle" | "active" | "done" | "stopped" | "error"
Requirement
required
Name
value
Kind
property
Type
Value
Requirement
required
Name
version
Kind
property
Type
number
Requirement
required

StateValue

type
DeclarationView source
StateValuets
type StateValue = string | {
readonly [region: string]: StateValue;
};

Transition

interface
DeclarationView source
Transitionts
interface Transition<Value extends StateValue, Context, Command extends CommandObject, Output = never> {
readonly state: MachineState<Value, Context, Output>;
readonly commands?: readonly Command[];
readonly diagnostics?: readonly DiagnosticObject[];
}
Name
Kind
Type
Requirement
commands
property
readonly Command[]
optional
diagnostics
property
readonly DiagnosticObject[]
optional
state
property
MachineState<Value, Context, Output>
required
Name
commands
Kind
property
Type
readonly Command[]
Requirement
optional
Name
diagnostics
Kind
property
Type
readonly DiagnosticObject[]
Requirement
optional
Name
state
Kind
property
Type
MachineState<Value, Context, Output>
Requirement
required