# 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`; `AsyncActionFn` MUST return `Promise`. `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.