Files
suaveplan/openspec/archive/2026-04-19-enterprise-fsm/specs/fsm/spec.md
2026-05-27 23:29:53 +01:00

2.3 KiB

Capability Spec: fsm

Package: @suaveplan/fsm Version: 0.0.0 (genesis) Status: ADDED


ADDED Requirements

FSM-01 — Config validation

validateConfig(config) MUST reject machines with unknown target states, duplicate state ids, or cyclic hierarchical parents. Invalid configs MUST throw FSM.INVALID_CONFIG.

FSM-02 — Transition contract

StateMachine.send(event) MUST run each candidate transition's guards in declared order, halt on the first true, execute the transition's actions, and emit TransitionResult { fromState, toState, event, eventType: FsmEventType }. Guard rejection across all candidates MUST emit FSM.INVALID_TRANSITION.

FSM-03 — Async guards / actions

AsyncGuardFn MUST return Promise<boolean>; AsyncActionFn MUST return Promise<void>. send MUST await them in order. Concurrent send calls MUST be serialised by the machine (FIFO).

FSM-04 — Snapshot / restore

StateMachine.snapshot() MUST return MachineSnapshot serialisable via JSON.stringify. StateMachine.restore(snapshot) MUST restore the machine to that exact state + context. Snapshots from a different config.id MUST be rejected.

FSM-05 — Hierarchical semantics

HierarchicalStateMachine MUST resolve the deepest active leaf on entry. onEntry / onExit MUST fire in outer→inner / inner→outer order respectively.

FSM-06 — Parallel regions

ParallelStateMachine MUST evaluate transitions independently per RegionConfig. SyncPoint MUST block progress until every named region enters the configured state.

FSM-07 — History

HistoryType MUST be 'shallow' | 'deep'. HistoryStateManager MUST return the last active leaf on re-entry for deep, and the last active direct child for shallow. Empty history on onExit-before-onEntry paths MUST emit FSM.HISTORY_EMPTY.

FSM-08 — Deferred events

DeferredEventQueue MUST buffer events per StateDeferConfig and release them when the state exits. Overflow MUST surface as FSM.DEFER_OVERFLOW.

FSM-09 — Visualisation

toDot(config) MUST produce Graphviz DOT representing states + transitions. toMermaid(config) MUST produce Mermaid state-diagram syntax. Both MUST handle hierarchical + parallel configs.

FSM-10 — Observability

send MUST record fsm.transition.duration_ms histogram and fsm.transition.total{outcome} counter.