Initial Commit
This commit is contained in:
67
openspec/archive/2026-04-19-enterprise-fsm/proposal.md
Normal file
67
openspec/archive/2026-04-19-enterprise-fsm/proposal.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# OpenSpec Change: enterprise-fsm
|
||||
|
||||
- **Change ID**: enterprise-fsm
|
||||
- **Package**: `@suaveplan/fsm`
|
||||
- **Category**: universal
|
||||
- **Target path**: `universal/control-flow/fsm`
|
||||
- **Status**: PROPOSED
|
||||
- **Date**: 2026-04-19
|
||||
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/fsm.md`
|
||||
|
||||
## Summary
|
||||
|
||||
Finite state machine with hierarchical, parallel, and history-state extensions, deferred-event queue, transition guards/actions (sync + async), snapshot/restore, lifecycle listener API, declarative transition hooks, DOT/Mermaid visualisers, and exhaustive config validation. Shape-compatible with XState-lite state configurations but zero-dependency.
|
||||
|
||||
## Current-state audit (genesis)
|
||||
|
||||
Package does not exist yet — fresh build.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Workspace: `@suaveplan/error`, `@suaveplan/events`, `@suaveplan/types`
|
||||
- External (via catalog): `zod`, `tslib`, `@opentelemetry/api`
|
||||
- Dev (via catalog): `vitest`, `@vitest/coverage-istanbul`, `fast-check`, `mitata`
|
||||
|
||||
## Preserved public surface
|
||||
|
||||
### Core FSM
|
||||
|
||||
- `createMachine`, `StateMachine`
|
||||
- Types: `ActionFn`, `AsyncActionFn`, `AsyncGuardFn`, `CompletedTransition`, `FsmError`, `FsmErrorCode`, `FsmEventType`, `FsmListenerMap`, `GuardFn`, `LifecycleListener`, `MachineConfig`, `MachineSnapshot`, `StateConfig`, `TransitionDefinition`, `TransitionInfo`, `TransitionListener`, `TransitionResult`
|
||||
- Hooks: `FsmHookMap`, `FsmTransitionHookData`, `FsmTransitioningHandler`
|
||||
|
||||
### Utilities
|
||||
|
||||
- `buildTransitionIndex`, `createFsmError`, `validateConfig`
|
||||
|
||||
### Hierarchical
|
||||
|
||||
- `createHierarchicalMachine`, `HierarchicalStateMachine`, `HierarchicalConfig`, `HierarchicalStateNode`, `HierarchicalTransition`, `HierarchicalTransitionResult`
|
||||
|
||||
### History
|
||||
|
||||
- `createHistoryManager`, `HistoryStateManager`, `HistoryEntry`, `HistoryStateConfig`, `HistoryType`
|
||||
|
||||
### Parallel
|
||||
|
||||
- `createParallelMachine`, `ParallelStateMachine`, `ParallelConfig`, `ParallelState`, `ParallelTransitionResult`, `RegionConfig`, `RegionTransition`, `SyncPoint`
|
||||
|
||||
### Deferred queue
|
||||
|
||||
- `createDeferredQueue`, `DeferredEventQueue`, `DeferredEvent`, `DeferredQueueConfig`, `StateDeferConfig`
|
||||
|
||||
### Visualisation
|
||||
|
||||
- `toDot`, `toMermaid`, `VisualizerOptions`
|
||||
|
||||
## New genesis additions
|
||||
|
||||
- Codes: `FSM.INVALID_CONFIG`, `FSM.INVALID_TRANSITION`, `FSM.GUARD_REJECTED`, `FSM.HISTORY_EMPTY`, `FSM.DEFER_OVERFLOW`.
|
||||
- Zod schemas for every config input.
|
||||
- OTel histograms `fsm.transition.duration_ms`, counter `fsm.transition.total{outcome}`.
|
||||
- Property tests: config round-trip via snapshot/restore, parallel-region determinism under identical event order.
|
||||
|
||||
## Impact
|
||||
|
||||
- Adds one new package: `universal/control-flow/fsm`
|
||||
- Adds one new spec capability: `fsm`
|
||||
49
openspec/archive/2026-04-19-enterprise-fsm/specs/fsm/spec.md
Normal file
49
openspec/archive/2026-04-19-enterprise-fsm/specs/fsm/spec.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# 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.
|
||||
47
openspec/archive/2026-04-19-enterprise-fsm/tasks.md
Normal file
47
openspec/archive/2026-04-19-enterprise-fsm/tasks.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Tasks: enterprise-fsm
|
||||
|
||||
## 1. Scaffold
|
||||
|
||||
- [x] 1.1 `universal/control-flow/fsm/`; 100/100/100/100; guard tests; CLAUDE/README/FOLDERS.
|
||||
|
||||
## 2. Errors + schemas
|
||||
|
||||
- [x] 2.1 `src/fsm-utils.ts` — `createFsmError`, validation helpers.
|
||||
- [x] 2.2 Zod schemas for `MachineConfig`, `StateConfig`, `TransitionDefinition`.
|
||||
|
||||
## 3. Core FSM
|
||||
|
||||
- [x] 3.1 `src/fsm.types.ts` — full type surface.
|
||||
- [x] 3.2 `src/fsm.ts` — `createMachine`, `StateMachine` with listener API, sync/async guards + actions, snapshot/restore.
|
||||
- [x] 3.3 `src/fsm-hooks.ts` — hook map + handler signatures.
|
||||
- [x] 3.4 OTel histogram + counter.
|
||||
|
||||
## 4. Hierarchical
|
||||
|
||||
- [x] 4.1 `src/hierarchy/hierarchical-fsm.ts`.
|
||||
|
||||
## 5. Parallel regions
|
||||
|
||||
- [x] 5.1 `src/parallel/parallel-fsm.ts` with sync points.
|
||||
|
||||
## 6. History states
|
||||
|
||||
- [x] 6.1 `src/history/history-state.ts` — shallow + deep history.
|
||||
|
||||
## 7. Deferred events
|
||||
|
||||
- [x] 7.1 `src/deferred/deferred-queue.ts` — bounded queue with drop-oldest/drop-newest policy.
|
||||
|
||||
## 8. Visualisation
|
||||
|
||||
- [x] 8.1 `src/visualization/fsm-visualizer.ts` — DOT + Mermaid.
|
||||
|
||||
## 9. Docs / barrel / subpath exports / README
|
||||
|
||||
## 10. Benchmarks
|
||||
|
||||
- [x] 10.1 `transition.bench.ts` at 10 / 100 / 1 000 state configurations.
|
||||
|
||||
## 11. Ship gate
|
||||
|
||||
- [x] 11.1 Verification sequence; fold + archive.
|
||||
Reference in New Issue
Block a user