aifsmjs 0.5.6 → 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fsm/types.ts","../src/fsm/definition.ts","../src/fsm/runtime.ts"],"names":[],"mappings":"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","file":"chunk-LG2AH5X6.js","sourcesContent":["// All public types live here so AI agents and humans can read the entire\n// public surface in one file.\n\nexport type Effect = Readonly<{ type: string; payload?: unknown }>;\n\nexport type Enqueuer = Readonly<{\n effect: (type: string, payload?: unknown) => void;\n}>;\n\nexport type GuardArgs<Ctx, Evt> = Readonly<{\n context: Ctx;\n event: Evt;\n /**\n * Optional guard registry, threaded by `evalGuard` so combinators can resolve\n * string refs nested inside `and / or / not`. Inline user guards may safely\n * ignore this field — it is `undefined` when guards are evaluated outside of\n * `evalGuard` (e.g. in unit tests calling the function directly).\n */\n guards?: Readonly<Record<string, Guard<Ctx, Evt>>>;\n /**\n * Current state value, threaded by `evalGuard` from the live snapshot. Used\n * by the `stateIn` combinator. `undefined` when guards are called outside of\n * a lifecycle evaluation.\n */\n value?: string;\n}>;\n\nexport type Guard<Ctx, Evt> = (args: GuardArgs<Ctx, Evt>) => boolean;\n\nexport type Action<Ctx, Evt> = (args: {\n context: Ctx;\n event: Evt;\n enqueue: Enqueuer;\n}) => Partial<Ctx> | void;\n\nexport type EffectHandler<Ctx, Evt> = (\n effect: Effect,\n args: { context: Ctx; event: Evt; signal: AbortSignal },\n) => void | Promise<void>;\n\nexport type GuardRef<Ctx, Evt> = string | Guard<Ctx, Evt>;\nexport type ActionRef<Ctx, Evt> = string | Action<Ctx, Evt>;\n\nexport type TransitionDef<Ctx, Evt, States extends string> = Readonly<{\n target?: States;\n guard?: GuardRef<Ctx, Evt>;\n actions?: readonly ActionRef<Ctx, Evt>[];\n}>;\n\n/**\n * A single transition as written in a `StateDef.on` map. Either the full\n * {@link TransitionDef} object form, or the string shorthand `\"targetState\"`\n * (à la XState) which the resolver normalizes to `{ target: \"targetState\" }`\n * before processing. The shorthand carries no guard or actions.\n *\n * @since 0.5.3\n */\nexport type TransitionConfig<Ctx, Evt, States extends string> =\n | States\n | TransitionDef<Ctx, Evt, States>;\n\n/**\n * @experimental v0.3.0\n *\n * A nested machine definition attachable to StateDef.sub. The type parameters\n * are independent from the parent machine's <Ctx, Evt, States>; sub-machines\n * may have entirely unrelated context and event shapes.\n *\n * This is an alias for MachineDef — sub-machines have the same definition\n * shape as top-level machines. The relationship is purely lifecycle:\n * a sub-machine instance is created when its parent state becomes active\n * and disposed when the parent state exits.\n */\nexport type SubMachineDef<\n SubCtx,\n SubEvt extends { type: string },\n SubStates extends string,\n> = MachineDef<SubCtx, SubEvt, SubStates>;\n\nexport type StateDef<Ctx, Evt, States extends string> = Readonly<{\n on?: Readonly<\n Record<\n string,\n TransitionConfig<Ctx, Evt, States> | readonly TransitionConfig<Ctx, Evt, States>[]\n >\n >;\n entry?: readonly ActionRef<Ctx, Evt>[];\n exit?: readonly ActionRef<Ctx, Evt>[];\n final?: boolean;\n /**\n * Optional sub-machine. When the runtime enters a state with `sub`,\n * the sub-machine is lazily instantiated; when it exits, the sub-machine\n * is disposed. See STABILITY.md for the experimental contract.\n *\n * The generic parameters are erased to `any` because sub-machine type\n * parameters are intentionally independent from the parent's `Ctx` / `Evt`\n * / `States`. `MachineDef`'s generics are invariant (guards / actions\n * consume them), so the storage position must use `any` rather than\n * `unknown`. Caller narrows via `runtime.subRuntime() as Runtime<...>`.\n *\n * @experimental since 0.3.0\n */\n // biome-ignore lint/suspicious/noExplicitAny: see JSDoc — invariant generic escape hatch\n sub?: MachineDef<any, any, any>;\n /**\n * Implementations for `sub`. Ignored if `sub` is absent. Defaults to `{}`\n * (sub-machine must rely on inline guards / actions / effects only).\n *\n * @experimental since 0.3.0\n */\n // biome-ignore lint/suspicious/noExplicitAny: same reason as `sub` above\n subImpl?: Implementations<any, any>;\n}>;\n\nexport type MachineDef<Ctx, Evt extends { type: string }, States extends string> = Readonly<{\n id: string;\n initial: States;\n context: Ctx;\n states: Readonly<Record<States, StateDef<Ctx, Evt, States>>>;\n}>;\n\n/**\n * Input shape accepted by `defineMachine` / `setup().defineMachine`. Identical\n * to {@link MachineDef} except `context` is **optional** — when omitted it\n * defaults to `{}` (paired with the `Ctx = Record<string, never>` default type\n * parameter). The returned value is always a fully-normalized\n * {@link MachineDef} with `context` present, so downstream consumers are\n * unaffected.\n *\n * @since 0.5.3\n */\nexport type MachineConfig<Ctx, Evt extends { type: string }, States extends string> = Readonly<{\n id: string;\n initial: States;\n states: Readonly<Record<States, StateDef<Ctx, Evt, States>>>;\n}> &\n // `context` may be omitted only when `Ctx` has no required properties (e.g. the\n // default `Record<string, never>`). If `Ctx` has required fields it must be\n // supplied, so omitting it can't silently default to `{}` and crash at runtime.\n (Record<string, never> extends Ctx ? { readonly context?: Ctx } : { readonly context: Ctx });\n\nexport type Snapshot<Ctx, States extends string> = Readonly<{\n value: States;\n context: Ctx;\n status: \"active\" | \"final\";\n}>;\n\nexport type Implementations<Ctx, Evt> = Readonly<{\n guards?: Readonly<Record<string, Guard<Ctx, Evt>>>;\n actions?: Readonly<Record<string, Action<Ctx, Evt>>>;\n effects?: Readonly<Record<string, EffectHandler<Ctx, Evt>>>;\n}>;\n\nexport type StepResult<Ctx, States extends string> = Readonly<{\n snapshot: Snapshot<Ctx, States>;\n effects: readonly Effect[];\n changed: boolean;\n}>;\n\n/**\n * Sentinel event type that `Runtime.reset()` synthesises when the caller does\n * not pass an explicit event. Middleware receives it through\n * `MiddlewareContext.event`. Exposed so user code can discriminate.\n */\nexport const RESET_EVENT_TYPE = \"@@aifsmjs/RESET\" as const;\nexport type ResetEvent = Readonly<{ type: typeof RESET_EVENT_TYPE }>;\n\nexport type MiddlewareContext<Ctx, Evt, States extends string> = Readonly<{\n prev: Snapshot<Ctx, States>;\n next: Snapshot<Ctx, States>;\n /**\n * The triggering event. May be the user's `Evt` (from `send()` or an\n * explicit `reset(event)`) or the `ResetEvent` sentinel emitted by a\n * `reset()` with no event argument.\n */\n event: Evt | ResetEvent;\n effects: readonly Effect[];\n changed: boolean;\n}>;\n\nexport type Middleware<Ctx, Evt, States extends string> = (\n ctx: MiddlewareContext<Ctx, Evt, States>,\n next: () => void,\n) => void;\n\n/**\n * Payload of the `'transition'` runtime event — emitted after each `send()` or\n * `reset()` that actually changed the snapshot value.\n */\nexport type RuntimeTransitionEvent<Ctx, Evt, States extends string> = Readonly<{\n prev: Snapshot<Ctx, States>;\n next: Snapshot<Ctx, States>;\n event: Evt | ResetEvent;\n effects: readonly Effect[];\n changed: boolean;\n}>;\n\n/**\n * Payload of the `'error'` runtime event — currently emitted for async effect\n * handler rejections (which would otherwise become unhandled). Synchronous\n * throws from effect handlers and middleware still propagate to the caller of\n * `send()` / `reset()`.\n */\nexport type RuntimeErrorEvent<Evt> = Readonly<{\n error: unknown;\n event: Evt | ResetEvent | undefined;\n}>;\n\nexport type RuntimeEventMap<Ctx, Evt, States extends string> = {\n transition: RuntimeTransitionEvent<Ctx, Evt, States>;\n error: RuntimeErrorEvent<Evt>;\n dispose: void;\n};\n\nexport interface Runtime<Ctx, Evt extends { type: string }, States extends string> {\n getSnapshot(): Snapshot<Ctx, States>;\n /** Alias for `getSnapshot()`. */\n snapshot(): Snapshot<Ctx, States>;\n send(event: Evt): Snapshot<Ctx, States>;\n /**\n * Predict whether sending `event` would fire a transition. Reuses\n * `resolveTransitions` + `evalGuard` without applying any actions. Guards\n * are expected to be pure; `can` then matches `send` for the same input.\n */\n can(event: Evt): boolean;\n subscribe(listener: (snap: Snapshot<Ctx, States>) => void): () => void;\n /**\n * EventTarget-like typed listener API. Returns an unsubscribe function.\n * `options.signal` removes the listener when aborted; `options.once`\n * removes the listener after the first invocation. After `dispose()`,\n * `on()` is a no-op and returns a no-op unsubscribe.\n */\n on<K extends keyof RuntimeEventMap<Ctx, Evt, States>>(\n type: K,\n listener: (payload: RuntimeEventMap<Ctx, Evt, States>[K]) => void,\n options?: { signal?: AbortSignal; once?: boolean },\n ): () => void;\n /**\n * Re-initialise the runtime to the definition's initial snapshot. Triggers\n * subscribers but does NOT run entry actions (reset = re-birth, not\n * \"transition into initial\"). Throws RuntimeDisposedError if disposed.\n * If an `event` is supplied, middleware sees it as the trigger; otherwise\n * a sentinel `{ type: \"@@aifsmjs/RESET\" }` is synthesised.\n */\n reset(event?: Evt): Snapshot<Ctx, States>;\n /**\n * Tear down: abort the internal AbortController (effect handlers see signal\n * fire), clear listeners, and mark this runtime as disposed. Subsequent\n * send()/reset() calls throw RuntimeDisposedError. Idempotent.\n */\n dispose(): void;\n /**\n * True after `dispose()` has been called.\n */\n readonly disposed: boolean;\n /**\n * AbortSignal scoped to this runtime's lifetime. Fires once on dispose().\n * Threaded to every EffectHandler invocation; external integrations\n * (e.g. component teardown) can also attach `signal.addEventListener(\"abort\", ...)`.\n */\n readonly signal: AbortSignal;\n /**\n * @experimental v0.3.0\n *\n * Returns the currently active sub-Runtime for the current parent state,\n * or undefined if:\n * - the current state has no `sub` definition, OR\n * - the sub-Runtime failed to initialise (SubMachineError was thrown\n * from `send()` / `reset()` / `createRuntime` per the spec contract),\n * OR\n * - the parent runtime has been disposed.\n *\n * The returned Runtime is typed at the loosest sub-machine signature.\n * Caller casts to the concrete sub type.\n *\n * Re-entry: when the parent leaves and re-enters a state with `sub`, a\n * fresh sub-Runtime is constructed. Previous sub-Runtime references held\n * by the caller are stale and MUST NOT be used (disposed).\n */\n subRuntime(): Runtime<unknown, { type: string }, string> | undefined;\n /**\n * Semantic sugar for `runtime.on('transition', handler, opts)`. Returns\n * the same unsubscribe function. Sharing the same listener Set with\n * `on('transition', ...)` means registration order determines invocation\n * order across both APIs.\n *\n * @since 0.3.0\n */\n onTransition(\n handler: (payload: RuntimeTransitionEvent<Ctx, Evt, States>) => void,\n options?: { signal?: AbortSignal; once?: boolean },\n ): () => void;\n}\n\nexport type RuntimeOptions<Ctx, Evt, States extends string> = Readonly<{\n middleware?: readonly Middleware<Ctx, Evt, States>[];\n /**\n * If false, do not dispatch effects through the effect handler map.\n * Useful for replay / dry-run modes. Defaults to true.\n */\n dispatchEffects?: boolean;\n}>;\n","import { isAsyncGuardFn } from \"./evaluator.js\";\nimport { normalizeTransitions } from \"./resolver.js\";\nimport { createRuntime } from \"./runtime.js\";\nimport { freezeSnapshot } from \"./snapshot.js\";\nimport type {\n Implementations,\n MachineConfig,\n MachineDef,\n Runtime,\n RuntimeOptions,\n Snapshot,\n StateDef,\n} from \"./types.js\";\n\nexport class InvalidDefinitionError extends Error {\n constructor(message: string) {\n super(`aifsmjs: ${message}`);\n this.name = \"InvalidDefinitionError\";\n }\n}\n\nfunction validateDefinition<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n // Cycle guard: subs may reference each other (or themselves) by object\n // identity. We validate each distinct definition object at most once so a\n // self/mutually-referential sub graph terminates instead of recursing\n // forever (C2). Seeded by the public entry points below.\n seen: WeakSet<object> = new WeakSet(),\n): void {\n if (!def.id || typeof def.id !== \"string\") {\n throw new InvalidDefinitionError(\"definition must have a non-empty string `id`\");\n }\n /* v8 ignore next 3 — additional safety: TS prevents non-object `states`; this guards untyped JS callers. */\n if (!def.states || typeof def.states !== \"object\") {\n throw new InvalidDefinitionError(\"definition must have a `states` object\");\n }\n const stateKeys = Object.keys(def.states) as States[];\n if (stateKeys.length === 0) {\n throw new InvalidDefinitionError(\"`states` must declare at least one state\");\n }\n if (!def.initial || !stateKeys.includes(def.initial)) {\n throw new InvalidDefinitionError(\n `\\`initial\\` \"${String(def.initial)}\" is not declared in states (${stateKeys.join(\", \")})`,\n );\n }\n for (const [stateName, stateDef] of Object.entries(def.states) as [\n States,\n (typeof def.states)[States],\n ][]) {\n // §4 sub-shape check + deep recursion (C2). The shallow shape check rejects\n // a malformed sub; recursing validateDefinition into the sub then rejects an\n // unknown transition target or a declared-async guard at construction\n // instead of leaving it to blow up at child.send(). Closes the FSM-07 sub\n // async-guard discrepancy (same root). The cycle guard makes this safe for\n // self/mutually-referential subs.\n if (stateDef.sub !== undefined) {\n const sub = stateDef.sub;\n const subStates = (sub as { states?: unknown }).states;\n const subInitial = (sub as { initial?: unknown }).initial;\n if (\n typeof sub !== \"object\" ||\n sub === null ||\n typeof subStates !== \"object\" ||\n subStates === null ||\n typeof subInitial !== \"string\" ||\n // initial must name one of the sub's own states — otherwise the child\n // boots pointing at a non-existent state and no-ops forever (FSM-S-02).\n !Object.hasOwn(subStates as object, subInitial)\n ) {\n throw new InvalidDefinitionError(\n `state \"${stateName}\".sub is not a valid sub-machine definition (missing states or initial)`,\n );\n }\n // Recurse — but only once per distinct sub object (cycle guard).\n if (!seen.has(sub as object)) {\n seen.add(sub as object);\n validateDefinition(sub as MachineDef<unknown, { type: string }, string>, seen);\n }\n }\n if (!stateDef.on) continue;\n for (const [evtType, entry] of Object.entries(stateDef.on)) {\n const transitions = normalizeTransitions(entry);\n for (const t of transitions) {\n if (t.target !== undefined && !stateKeys.includes(t.target)) {\n throw new InvalidDefinitionError(\n `transition ${stateName} -[${evtType}]-> \"${String(t.target)}\" targets an unknown state`,\n );\n }\n if (t.guard !== undefined && isAsyncGuardFn(t.guard)) {\n throw new InvalidDefinitionError(\n `transition ${stateName} -[${evtType}]-> uses an async guard. Guards must be sync; move I/O into an effect.`,\n );\n }\n }\n }\n }\n}\n\n/**\n * Validate a machine definition shape and return it. When `context` is\n * provided the same reference is returned; when it is omitted a shallow copy\n * with `context: {}` is returned. Validation is intentionally shallow.\n *\n * Two call forms:\n *\n * defineMachine<Ctx, Evt, States>({ ... })\n * Explicit generics. Use when you need full control (e.g. union event\n * types). Required because TypeScript cannot otherwise infer `Evt`.\n *\n * setup<Ctx, Evt>().defineMachine({ ... })\n * Curried form. Lets `States` be inferred from `keyof states`, so you\n * can omit it. Recommended for typical usage.\n */\nexport function defineMachine<\n Ctx = Record<string, never>,\n Evt extends { type: string } = { type: string },\n States extends string = string,\n>(def: MachineConfig<Ctx, Evt, States>): MachineDef<Ctx, Evt, States> {\n const normalized = (!(\"context\" in def) ? { ...def, context: {} as Ctx } : def) as MachineDef<\n Ctx,\n Evt,\n States\n >;\n validateDefinition(normalized);\n return normalized;\n}\n\n/**\n * Curried builder so `States` can be inferred from `keyof states` without\n * `initial` collapsing it to a single literal. Pass `Ctx` and `Evt` as the\n * type arguments; pass the def to the returned `defineMachine`.\n *\n * const machine = setup<MyCtx, MyEvt>().defineMachine({\n * id: \"m\",\n * initial: \"a\",\n * context: { ... },\n * states: { a: {...}, b: {...} }, // States inferred as \"a\" | \"b\"\n * });\n */\nexport function setup<\n Ctx = Record<string, never>,\n Evt extends { type: string } = { type: string },\n>(): {\n defineMachine: <const States extends string>(\n def: Readonly<{\n id: string;\n initial: NoInfer<States>;\n states: Readonly<Record<States, StateDef<Ctx, Evt, States>>>;\n }> &\n (Record<string, never> extends Ctx ? { readonly context?: Ctx } : { readonly context: Ctx }),\n ) => MachineDef<Ctx, Evt, States>;\n} {\n return {\n defineMachine: <const States extends string>(\n def: Readonly<{\n id: string;\n initial: NoInfer<States>;\n states: Readonly<Record<States, StateDef<Ctx, Evt, States>>>;\n }> &\n (Record<string, never> extends Ctx\n ? { readonly context?: Ctx }\n : { readonly context: Ctx }),\n ) => {\n const cast = (!(\"context\" in def)\n ? { ...def, context: {} as Ctx }\n : def) as unknown as MachineDef<Ctx, Evt, States>;\n validateDefinition(cast);\n return cast;\n },\n };\n}\n\n/**\n * Build the initial snapshot for a machine.\n */\nexport function initialSnapshot<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n): Snapshot<Ctx, States> {\n const isFinal = def.states[def.initial]?.final === true;\n return freezeSnapshot({\n value: def.initial,\n context: def.context,\n status: isFinal ? (\"final\" as const) : (\"active\" as const),\n });\n}\n\n/**\n * Convenience factory that composes `defineMachine` and `createRuntime` in\n * one call for the common case where you do not need to keep the machine\n * definition around for serialization or sharing.\n *\n * For type inference over `States` from `keyof states`, prefer\n * `setup<Ctx, Evt>().defineMachine(...)` then pass the result to\n * `createRuntime` separately. `createMachine` is the spec-style entry point\n * documented in the ai*js ecosystem review.\n */\nexport function createMachine<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n opts?: RuntimeOptions<Ctx, Evt, States>,\n): Runtime<Ctx, Evt, States> {\n return createRuntime(defineMachine(def), impl, opts ?? {});\n}\n","import { initialSnapshot } from \"./definition.js\";\nimport { evalGuard, isThenable } from \"./evaluator.js\";\nimport { step } from \"./lifecycle.js\";\nimport { normalizeTransitions } from \"./resolver.js\";\nimport { deepFreeze } from \"./snapshot.js\";\nimport {\n type Effect,\n type Implementations,\n type MachineDef,\n type Middleware,\n RESET_EVENT_TYPE,\n type ResetEvent,\n type Runtime,\n type RuntimeEventMap,\n type RuntimeOptions,\n type RuntimeTransitionEvent,\n type Snapshot,\n} from \"./types.js\";\n\nexport class RuntimeDisposedError extends Error {\n constructor() {\n super(\"aifsmjs: runtime has been disposed; send()/reset() are not allowed\");\n this.name = \"RuntimeDisposedError\";\n }\n}\n\n/**\n * Thrown by `send()` / `reset()` when a sub-machine init or dispose throws.\n *\n * Invariants:\n * - `phase: \"init\"` — child constructor threw. Parent snapshot was rolled\n * back to `prev`; no middleware ran; no `'transition'` emitted; no effects.\n * - `phase: \"dispose\"` — previous child's `dispose()` threw during transition.\n * Parent snapshot was rolled back to `prev`; child reference is cleared.\n * - Never thrown from `runtime.dispose()` cascade (never-throws contract).\n *\n * @since 0.3.0\n */\nexport class SubMachineError extends Error {\n readonly parentState: string;\n readonly phase: \"init\" | \"dispose\";\n override readonly cause: unknown;\n\n constructor(parentState: string, phase: \"init\" | \"dispose\", cause: unknown) {\n super(`aifsmjs: sub-machine ${phase} failed at parent state \"${parentState}\"`, { cause });\n this.name = \"SubMachineError\";\n this.parentState = parentState;\n this.phase = phase;\n this.cause = cause; // belt-and-suspenders: legacy bundlers ignore ES2022 cause option\n }\n}\n\nconst RESET_EVENT: ResetEvent = Object.freeze({ type: RESET_EVENT_TYPE });\n\nfunction composeMiddleware<Ctx, Evt, States extends string>(\n middleware: readonly Middleware<Ctx, Evt, States>[],\n): Middleware<Ctx, Evt, States> {\n return (ctx, finalNext) => {\n let index = -1;\n const dispatch = (i: number): void => {\n if (i <= index) throw new Error(\"aifsmjs: next() called multiple times in middleware\");\n index = i;\n const fn = middleware[i];\n if (!fn) {\n finalNext();\n return;\n }\n fn(ctx, () => dispatch(i + 1));\n };\n dispatch(0);\n };\n}\n\n/**\n * Build a thin stateful runtime around a machine. `send()` calls `step()`,\n * runs the read-only middleware pipeline, dispatches effects, and notifies\n * subscribers. The runtime owns an `AbortController`; `dispose()` aborts it\n * and clears all state.\n */\nexport function createRuntime<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n opts: RuntimeOptions<Ctx, Evt, States> = {},\n): Runtime<Ctx, Evt, States> {\n let snapshot: Snapshot<Ctx, States> = initialSnapshot(def);\n const listeners = new Set<(snap: Snapshot<Ctx, States>) => void>();\n const middlewareChain =\n opts.middleware && opts.middleware.length > 0 ? composeMiddleware(opts.middleware) : undefined;\n const shouldDispatch = opts.dispatchEffects !== false;\n const controller = new AbortController();\n let disposed = false;\n // §3.1 sub-machine state. childRuntime is the live child; childAbortCleanup\n // detaches the parent-abort listener attached by wireChildAbort. Both are\n // cleared together whenever the child is replaced or disposed (P1-3 fix).\n let childRuntime: Runtime<unknown, { type: string }, string> | undefined;\n let childAbortCleanup: (() => void) | undefined;\n\n type EventListeners = {\n [K in keyof RuntimeEventMap<Ctx, Evt, States>]: Set<\n (payload: RuntimeEventMap<Ctx, Evt, States>[K]) => void\n >;\n };\n const eventListeners: EventListeners = {\n transition: new Set(),\n error: new Set(),\n dispose: new Set(),\n };\n const externalAbortCleanups = new Set<() => void>();\n\n function emit<K extends keyof RuntimeEventMap<Ctx, Evt, States>>(\n type: K,\n payload: RuntimeEventMap<Ctx, Evt, States>[K],\n ): void {\n // Snapshot-before-iterate (family canonical, aieventjs .slice()): a\n // listener that subscribes/unsubscribes another during dispatch must not\n // mutate the set being walked. One array alloc per emit, matching the\n // family's accepted cost (FAM-S-03).\n for (const fn of Array.from(eventListeners[type])) fn(payload);\n }\n\n function notify(committed?: Snapshot<Ctx, States>) {\n const captured = committed ?? snapshot;\n // Snapshot-before-iterate, as above (FAM-S-03).\n for (const l of Array.from(listeners)) l(captured);\n }\n\n function runMiddleware(\n prev: Snapshot<Ctx, States>,\n event: Evt | ResetEvent,\n effects: readonly Effect[],\n changed: boolean,\n ) {\n if (!middlewareChain) return;\n middlewareChain(deepFreeze({ prev, next: snapshot, event, effects, changed }), () => {});\n }\n\n function dispatchEffects(effects: readonly Effect[], context: Ctx, event: Evt): void {\n if (!impl.effects || effects.length === 0) return;\n for (const eff of effects) {\n const handler = impl.effects[eff.type];\n if (!handler) continue;\n const r = handler(eff, { context, event, signal: controller.signal });\n // isThenable (not instanceof Promise) so cross-realm Promises and\n // user-defined PromiseLike results also have their rejections routed to\n // the 'error' channel; Promise.resolve() normalises them (FSM-B-03).\n if (isThenable(r)) {\n Promise.resolve(r).catch((err: unknown) => {\n emit(\"error\", { error: err, event });\n });\n }\n }\n }\n\n // §3.1 Attach one-shot abort listener: parent dispose → child.dispose().\n // Returns a cleanup fn that detaches the listener; caller stores it in\n // `childAbortCleanup` and invokes when the child is replaced/disposed\n // (P1-3 fix: prevent stale listeners accumulating on the parent signal).\n function wireChildAbort(child: Runtime<unknown, { type: string }, string>): () => void {\n /* v8 ignore next 7 — parent may already be aborted in edge cases; dispose still runs */\n if (controller.signal.aborted) {\n try {\n child.dispose();\n } catch {\n /* swallow */\n }\n return () => {};\n }\n /* v8 ignore next 7 — defensive: dispose() pre-cleans this listener and\n disposes the child manually before calling controller.abort(), so\n onAbort fires only if external code aborts the controller bypassing\n dispose(). Internal-only controller has no such external path today. */\n const onAbort = () => {\n try {\n child.dispose();\n } catch {\n /* swallow */\n }\n };\n controller.signal.addEventListener(\"abort\", onAbort, { once: true });\n return () => controller.signal.removeEventListener(\"abort\", onAbort);\n }\n\n // §3.1 Instantiate the child for `stateValue` (which must have a `sub`) and\n // wire its parent-abort listener, committing both to childRuntime /\n // childAbortCleanup. Throws SubMachineError(phase: \"init\") on failure; the\n // caller must NOT commit the parent snapshot on throw. Single source of the\n // init+wire sequence shared by applySubLifecycle, reset(), and bootstrap\n // (FSM-C-01) — keeps the most failure-sensitive path in one place.\n function initChildFor(stateValue: States): void {\n const stateDef = def.states[stateValue];\n const sub = stateDef?.sub;\n /* v8 ignore next 2 — callers only invoke this after checking stateDef.sub\n is defined; the guard documents that precondition and is never taken. */\n if (sub === undefined) return;\n let newChild: Runtime<unknown, { type: string }, string>;\n try {\n newChild = createRuntime(sub, stateDef.subImpl ?? {});\n } catch (cause) {\n throw new SubMachineError(stateValue as string, \"init\", cause);\n }\n childRuntime = newChild;\n childAbortCleanup = wireChildAbort(newChild);\n }\n\n // §3.3 Re-resolve guards to find the chosen transition and determine\n // whether it is external (has a `target`). Replaces the v0.3.0 dev\n // hasSelfTargetMarker heuristic that over-reported when an event had both\n // internal (no-target) and self-target (target === value) candidates\n // (P1-2 fix). Cost: one extra guard evaluation pass per same-value event.\n function findChosenIsExternal(value: States, event: Evt, context: Ctx): boolean {\n const state = def.states[value];\n if (!state?.on) return false;\n const list = normalizeTransitions(state.on[event.type]);\n if (list.length === 0) return false;\n for (const t of list) {\n if (!t.guard || evalGuard(t.guard, context, event, impl, value)) {\n return t.target !== undefined;\n }\n }\n /* v8 ignore next — defensive: caller only invokes when step() returned\n changed=true, which guarantees a matching guard exists in the same\n candidate list. The for-loop above always returns before this line. */\n return false;\n }\n\n // §3.1 Dispose old child and/or init new child. Throws SubMachineError on failure.\n // Caller must NOT commit snapshot on throw.\n function applySubLifecycle(prevValue: States, nextValue: States): void {\n const prevStateDef = def.states[prevValue];\n const nextStateDef = def.states[nextValue];\n if (prevStateDef?.sub !== undefined && childRuntime !== undefined) {\n const child = childRuntime;\n childRuntime = undefined;\n childAbortCleanup?.();\n childAbortCleanup = undefined;\n try {\n child.dispose();\n } catch (cause) {\n throw new SubMachineError(prevValue as string, \"dispose\", cause);\n }\n }\n if (nextStateDef?.sub !== undefined) {\n initChildFor(nextValue);\n }\n }\n\n function send(event: Evt): Snapshot<Ctx, States> {\n if (disposed) throw new RuntimeDisposedError();\n const prev = snapshot;\n const result = step(def, prev, event, impl);\n const isExternal =\n result.changed &&\n (prev.value !== result.snapshot.value ||\n findChosenIsExternal(prev.value, event, prev.context));\n // Sub lifecycle BEFORE snapshot commit (§3.4); throws SubMachineError on failure → no commit\n if (result.changed && isExternal) applySubLifecycle(prev.value, result.snapshot.value);\n snapshot = result.snapshot;\n const committed = result.snapshot;\n runMiddleware(prev, event, result.effects, result.changed);\n if (shouldDispatch) dispatchEffects(result.effects, committed.context, event);\n if (result.changed) {\n notify(committed);\n emit(\"transition\", {\n prev,\n next: committed,\n event,\n effects: result.effects,\n changed: true,\n } as RuntimeTransitionEvent<Ctx, Evt, States>);\n }\n return snapshot;\n }\n\n function reset(event?: Evt): Snapshot<Ctx, States> {\n if (disposed) throw new RuntimeDisposedError();\n const prev = snapshot;\n const nextSnap = initialSnapshot(def);\n const changed = prev.value !== nextSnap.value;\n // Dispose current child (§3.5)\n if (childRuntime) {\n const child = childRuntime;\n childRuntime = undefined;\n childAbortCleanup?.();\n childAbortCleanup = undefined;\n try {\n child.dispose();\n } catch (cause) {\n throw new SubMachineError(prev.value as string, \"dispose\", cause);\n }\n }\n // Init child for new initial state if it has sub (§3.5)\n const initStateDef = def.states[nextSnap.value];\n if (initStateDef?.sub) {\n initChildFor(nextSnap.value);\n }\n snapshot = nextSnap;\n // Capture the committed snapshot before notify()/emit so a subscriber that\n // re-entrantly send()s (which advances the mutable `snapshot`) cannot\n // corrupt this reset's payload — mirrors send()'s 0.2.0 fix (FSM-B-01).\n const committed = nextSnap;\n const triggerEvent: Evt | ResetEvent = event ?? RESET_EVENT;\n runMiddleware(prev, triggerEvent, [], changed);\n if (changed) {\n notify(committed);\n emit(\"transition\", {\n prev,\n next: committed,\n event: triggerEvent,\n effects: [],\n changed: true,\n } as RuntimeTransitionEvent<Ctx, Evt, States>);\n }\n // Return the live snapshot (consistent with send()): under a re-entrant\n // send() from a subscriber, this reflects the latest committed state. Only\n // the emitted payload above is pinned to this reset's own outcome.\n return snapshot;\n }\n\n function can(event: Evt): boolean {\n if (disposed || snapshot.status === \"final\") return false;\n const state = def.states[snapshot.value];\n /* v8 ignore next — defensive: snapshot.value always corresponds to a declared state. */\n if (!state) return false;\n const list = normalizeTransitions(state.on?.[event.type]);\n if (list.length === 0) return false;\n for (const t of list) {\n if (!t.guard) return true;\n if (evalGuard(t.guard, snapshot.context, event, impl, snapshot.value)) return true;\n }\n return false;\n }\n\n function on<K extends keyof RuntimeEventMap<Ctx, Evt, States>>(\n type: K,\n listener: (payload: RuntimeEventMap<Ctx, Evt, States>[K]) => void,\n options?: { signal?: AbortSignal; once?: boolean },\n ): () => void {\n if (disposed || options?.signal?.aborted) return () => {};\n const target = eventListeners[type];\n let detachAbort: (() => void) | undefined;\n // Full teardown shared by the once-wrapper, the abort handler, and the\n // returned unsubscribe so every path detaches the abort listener too — a\n // once-handler that also passed a { signal } previously left the abort\n // listener attached until dispose()/abort (memory leak).\n const cleanup = (): void => {\n target.delete(wrapped);\n if (detachAbort) {\n detachAbort();\n externalAbortCleanups.delete(detachAbort);\n }\n };\n let wrapped: (payload: RuntimeEventMap<Ctx, Evt, States>[K]) => void = listener;\n if (options?.once) {\n wrapped = (payload) => {\n cleanup();\n listener(payload);\n };\n }\n target.add(wrapped);\n const signal = options?.signal;\n if (signal) {\n const onAbort = () => cleanup();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n detachAbort = () => signal.removeEventListener(\"abort\", onAbort);\n externalAbortCleanups.add(detachAbort);\n }\n return cleanup;\n }\n\n function dispose(): void {\n if (disposed) return;\n disposed = true;\n // Cascade child dispose; swallow exceptions (dispose contract) (§3.6)\n if (childRuntime) {\n childAbortCleanup?.();\n childAbortCleanup = undefined;\n try {\n childRuntime.dispose();\n } catch {\n /* swallow */\n }\n childRuntime = undefined;\n }\n controller.abort();\n listeners.clear();\n // §3.6 dispose() is contractually never-throws + idempotent (README:65,\n // STABILITY.md:22). emit('dispose') runs user listeners; a throwing one\n // must neither escape dispose() nor abort the remaining teardown (which\n // would leak external-signal abort listeners, since a second dispose()\n // short-circuits on `if (disposed) return`). The try/finally guarantees\n // the listener-set clear + externalAbortCleanups loop ALWAYS run, mirroring\n // the defensiveness of the child-dispose cascade above.\n try {\n emit(\"dispose\", undefined as RuntimeEventMap<Ctx, Evt, States>[\"dispose\"]);\n } catch {\n /* swallow — never-throws contract */\n } finally {\n for (const set of Object.values(eventListeners)) set.clear();\n for (const cleanup of externalAbortCleanups) cleanup();\n externalAbortCleanups.clear();\n }\n }\n\n const runtime: Runtime<Ctx, Evt, States> = {\n getSnapshot: () => snapshot,\n snapshot: () => snapshot,\n send,\n can,\n reset,\n dispose,\n on,\n get disposed() {\n return disposed;\n },\n get signal() {\n return controller.signal;\n },\n subscribe(listener) {\n if (disposed) return () => {};\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n subRuntime: () => childRuntime,\n onTransition: (handler, options) => on(\"transition\", handler, options),\n };\n\n // §2 Bootstrap: if initial state has sub, instantiate child BEFORE returning.\n // Failure throws SubMachineError(initialState, \"init\", cause).\n const bootStateDef = def.states[snapshot.value];\n if (bootStateDef?.sub) {\n initChildFor(snapshot.value);\n }\n\n return runtime;\n}\n"]}
@@ -13,7 +13,7 @@ var InvalidDefinitionError = class extends Error {
13
13
  this.name = "InvalidDefinitionError";
14
14
  }
15
15
  };
16
- function validateDefinition(def) {
16
+ function validateDefinition(def, seen = /* @__PURE__ */ new WeakSet()) {
17
17
  if (!def.id || typeof def.id !== "string") {
18
18
  throw new InvalidDefinitionError("definition must have a non-empty string `id`");
19
19
  }
@@ -41,6 +41,10 @@ function validateDefinition(def) {
41
41
  `state "${stateName}".sub is not a valid sub-machine definition (missing states or initial)`
42
42
  );
43
43
  }
44
+ if (!seen.has(sub)) {
45
+ seen.add(sub);
46
+ validateDefinition(sub, seen);
47
+ }
44
48
  }
45
49
  if (!stateDef.on) continue;
46
50
  for (const [evtType, entry] of Object.entries(stateDef.on)) {
@@ -336,10 +340,14 @@ function createRuntime(def, impl, opts = {}) {
336
340
  }
337
341
  controller.abort();
338
342
  listeners.clear();
339
- emit("dispose", void 0);
340
- for (const set of Object.values(eventListeners)) set.clear();
341
- for (const cleanup of externalAbortCleanups) cleanup();
342
- externalAbortCleanups.clear();
343
+ try {
344
+ emit("dispose", void 0);
345
+ } catch {
346
+ } finally {
347
+ for (const set of Object.values(eventListeners)) set.clear();
348
+ for (const cleanup of externalAbortCleanups) cleanup();
349
+ externalAbortCleanups.clear();
350
+ }
343
351
  }
344
352
  const runtime = {
345
353
  getSnapshot: () => snapshot,
@@ -380,5 +388,5 @@ exports.createRuntime = createRuntime;
380
388
  exports.defineMachine = defineMachine;
381
389
  exports.initialSnapshot = initialSnapshot;
382
390
  exports.setup = setup;
383
- //# sourceMappingURL=chunk-2MME5V4F.cjs.map
384
- //# sourceMappingURL=chunk-2MME5V4F.cjs.map
391
+ //# sourceMappingURL=chunk-TPCDOVU4.cjs.map
392
+ //# sourceMappingURL=chunk-TPCDOVU4.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fsm/types.ts","../src/fsm/definition.ts","../src/fsm/runtime.ts"],"names":["normalizeTransitions","isAsyncGuardFn","freezeSnapshot","deepFreeze","isThenable","evalGuard","step"],"mappings":"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","file":"chunk-TPCDOVU4.cjs","sourcesContent":["// All public types live here so AI agents and humans can read the entire\n// public surface in one file.\n\nexport type Effect = Readonly<{ type: string; payload?: unknown }>;\n\nexport type Enqueuer = Readonly<{\n effect: (type: string, payload?: unknown) => void;\n}>;\n\nexport type GuardArgs<Ctx, Evt> = Readonly<{\n context: Ctx;\n event: Evt;\n /**\n * Optional guard registry, threaded by `evalGuard` so combinators can resolve\n * string refs nested inside `and / or / not`. Inline user guards may safely\n * ignore this field — it is `undefined` when guards are evaluated outside of\n * `evalGuard` (e.g. in unit tests calling the function directly).\n */\n guards?: Readonly<Record<string, Guard<Ctx, Evt>>>;\n /**\n * Current state value, threaded by `evalGuard` from the live snapshot. Used\n * by the `stateIn` combinator. `undefined` when guards are called outside of\n * a lifecycle evaluation.\n */\n value?: string;\n}>;\n\nexport type Guard<Ctx, Evt> = (args: GuardArgs<Ctx, Evt>) => boolean;\n\nexport type Action<Ctx, Evt> = (args: {\n context: Ctx;\n event: Evt;\n enqueue: Enqueuer;\n}) => Partial<Ctx> | void;\n\nexport type EffectHandler<Ctx, Evt> = (\n effect: Effect,\n args: { context: Ctx; event: Evt; signal: AbortSignal },\n) => void | Promise<void>;\n\nexport type GuardRef<Ctx, Evt> = string | Guard<Ctx, Evt>;\nexport type ActionRef<Ctx, Evt> = string | Action<Ctx, Evt>;\n\nexport type TransitionDef<Ctx, Evt, States extends string> = Readonly<{\n target?: States;\n guard?: GuardRef<Ctx, Evt>;\n actions?: readonly ActionRef<Ctx, Evt>[];\n}>;\n\n/**\n * A single transition as written in a `StateDef.on` map. Either the full\n * {@link TransitionDef} object form, or the string shorthand `\"targetState\"`\n * (à la XState) which the resolver normalizes to `{ target: \"targetState\" }`\n * before processing. The shorthand carries no guard or actions.\n *\n * @since 0.5.3\n */\nexport type TransitionConfig<Ctx, Evt, States extends string> =\n | States\n | TransitionDef<Ctx, Evt, States>;\n\n/**\n * @experimental v0.3.0\n *\n * A nested machine definition attachable to StateDef.sub. The type parameters\n * are independent from the parent machine's <Ctx, Evt, States>; sub-machines\n * may have entirely unrelated context and event shapes.\n *\n * This is an alias for MachineDef — sub-machines have the same definition\n * shape as top-level machines. The relationship is purely lifecycle:\n * a sub-machine instance is created when its parent state becomes active\n * and disposed when the parent state exits.\n */\nexport type SubMachineDef<\n SubCtx,\n SubEvt extends { type: string },\n SubStates extends string,\n> = MachineDef<SubCtx, SubEvt, SubStates>;\n\nexport type StateDef<Ctx, Evt, States extends string> = Readonly<{\n on?: Readonly<\n Record<\n string,\n TransitionConfig<Ctx, Evt, States> | readonly TransitionConfig<Ctx, Evt, States>[]\n >\n >;\n entry?: readonly ActionRef<Ctx, Evt>[];\n exit?: readonly ActionRef<Ctx, Evt>[];\n final?: boolean;\n /**\n * Optional sub-machine. When the runtime enters a state with `sub`,\n * the sub-machine is lazily instantiated; when it exits, the sub-machine\n * is disposed. See STABILITY.md for the experimental contract.\n *\n * The generic parameters are erased to `any` because sub-machine type\n * parameters are intentionally independent from the parent's `Ctx` / `Evt`\n * / `States`. `MachineDef`'s generics are invariant (guards / actions\n * consume them), so the storage position must use `any` rather than\n * `unknown`. Caller narrows via `runtime.subRuntime() as Runtime<...>`.\n *\n * @experimental since 0.3.0\n */\n // biome-ignore lint/suspicious/noExplicitAny: see JSDoc — invariant generic escape hatch\n sub?: MachineDef<any, any, any>;\n /**\n * Implementations for `sub`. Ignored if `sub` is absent. Defaults to `{}`\n * (sub-machine must rely on inline guards / actions / effects only).\n *\n * @experimental since 0.3.0\n */\n // biome-ignore lint/suspicious/noExplicitAny: same reason as `sub` above\n subImpl?: Implementations<any, any>;\n}>;\n\nexport type MachineDef<Ctx, Evt extends { type: string }, States extends string> = Readonly<{\n id: string;\n initial: States;\n context: Ctx;\n states: Readonly<Record<States, StateDef<Ctx, Evt, States>>>;\n}>;\n\n/**\n * Input shape accepted by `defineMachine` / `setup().defineMachine`. Identical\n * to {@link MachineDef} except `context` is **optional** — when omitted it\n * defaults to `{}` (paired with the `Ctx = Record<string, never>` default type\n * parameter). The returned value is always a fully-normalized\n * {@link MachineDef} with `context` present, so downstream consumers are\n * unaffected.\n *\n * @since 0.5.3\n */\nexport type MachineConfig<Ctx, Evt extends { type: string }, States extends string> = Readonly<{\n id: string;\n initial: States;\n states: Readonly<Record<States, StateDef<Ctx, Evt, States>>>;\n}> &\n // `context` may be omitted only when `Ctx` has no required properties (e.g. the\n // default `Record<string, never>`). If `Ctx` has required fields it must be\n // supplied, so omitting it can't silently default to `{}` and crash at runtime.\n (Record<string, never> extends Ctx ? { readonly context?: Ctx } : { readonly context: Ctx });\n\nexport type Snapshot<Ctx, States extends string> = Readonly<{\n value: States;\n context: Ctx;\n status: \"active\" | \"final\";\n}>;\n\nexport type Implementations<Ctx, Evt> = Readonly<{\n guards?: Readonly<Record<string, Guard<Ctx, Evt>>>;\n actions?: Readonly<Record<string, Action<Ctx, Evt>>>;\n effects?: Readonly<Record<string, EffectHandler<Ctx, Evt>>>;\n}>;\n\nexport type StepResult<Ctx, States extends string> = Readonly<{\n snapshot: Snapshot<Ctx, States>;\n effects: readonly Effect[];\n changed: boolean;\n}>;\n\n/**\n * Sentinel event type that `Runtime.reset()` synthesises when the caller does\n * not pass an explicit event. Middleware receives it through\n * `MiddlewareContext.event`. Exposed so user code can discriminate.\n */\nexport const RESET_EVENT_TYPE = \"@@aifsmjs/RESET\" as const;\nexport type ResetEvent = Readonly<{ type: typeof RESET_EVENT_TYPE }>;\n\nexport type MiddlewareContext<Ctx, Evt, States extends string> = Readonly<{\n prev: Snapshot<Ctx, States>;\n next: Snapshot<Ctx, States>;\n /**\n * The triggering event. May be the user's `Evt` (from `send()` or an\n * explicit `reset(event)`) or the `ResetEvent` sentinel emitted by a\n * `reset()` with no event argument.\n */\n event: Evt | ResetEvent;\n effects: readonly Effect[];\n changed: boolean;\n}>;\n\nexport type Middleware<Ctx, Evt, States extends string> = (\n ctx: MiddlewareContext<Ctx, Evt, States>,\n next: () => void,\n) => void;\n\n/**\n * Payload of the `'transition'` runtime event — emitted after each `send()` or\n * `reset()` that actually changed the snapshot value.\n */\nexport type RuntimeTransitionEvent<Ctx, Evt, States extends string> = Readonly<{\n prev: Snapshot<Ctx, States>;\n next: Snapshot<Ctx, States>;\n event: Evt | ResetEvent;\n effects: readonly Effect[];\n changed: boolean;\n}>;\n\n/**\n * Payload of the `'error'` runtime event — currently emitted for async effect\n * handler rejections (which would otherwise become unhandled). Synchronous\n * throws from effect handlers and middleware still propagate to the caller of\n * `send()` / `reset()`.\n */\nexport type RuntimeErrorEvent<Evt> = Readonly<{\n error: unknown;\n event: Evt | ResetEvent | undefined;\n}>;\n\nexport type RuntimeEventMap<Ctx, Evt, States extends string> = {\n transition: RuntimeTransitionEvent<Ctx, Evt, States>;\n error: RuntimeErrorEvent<Evt>;\n dispose: void;\n};\n\nexport interface Runtime<Ctx, Evt extends { type: string }, States extends string> {\n getSnapshot(): Snapshot<Ctx, States>;\n /** Alias for `getSnapshot()`. */\n snapshot(): Snapshot<Ctx, States>;\n send(event: Evt): Snapshot<Ctx, States>;\n /**\n * Predict whether sending `event` would fire a transition. Reuses\n * `resolveTransitions` + `evalGuard` without applying any actions. Guards\n * are expected to be pure; `can` then matches `send` for the same input.\n */\n can(event: Evt): boolean;\n subscribe(listener: (snap: Snapshot<Ctx, States>) => void): () => void;\n /**\n * EventTarget-like typed listener API. Returns an unsubscribe function.\n * `options.signal` removes the listener when aborted; `options.once`\n * removes the listener after the first invocation. After `dispose()`,\n * `on()` is a no-op and returns a no-op unsubscribe.\n */\n on<K extends keyof RuntimeEventMap<Ctx, Evt, States>>(\n type: K,\n listener: (payload: RuntimeEventMap<Ctx, Evt, States>[K]) => void,\n options?: { signal?: AbortSignal; once?: boolean },\n ): () => void;\n /**\n * Re-initialise the runtime to the definition's initial snapshot. Triggers\n * subscribers but does NOT run entry actions (reset = re-birth, not\n * \"transition into initial\"). Throws RuntimeDisposedError if disposed.\n * If an `event` is supplied, middleware sees it as the trigger; otherwise\n * a sentinel `{ type: \"@@aifsmjs/RESET\" }` is synthesised.\n */\n reset(event?: Evt): Snapshot<Ctx, States>;\n /**\n * Tear down: abort the internal AbortController (effect handlers see signal\n * fire), clear listeners, and mark this runtime as disposed. Subsequent\n * send()/reset() calls throw RuntimeDisposedError. Idempotent.\n */\n dispose(): void;\n /**\n * True after `dispose()` has been called.\n */\n readonly disposed: boolean;\n /**\n * AbortSignal scoped to this runtime's lifetime. Fires once on dispose().\n * Threaded to every EffectHandler invocation; external integrations\n * (e.g. component teardown) can also attach `signal.addEventListener(\"abort\", ...)`.\n */\n readonly signal: AbortSignal;\n /**\n * @experimental v0.3.0\n *\n * Returns the currently active sub-Runtime for the current parent state,\n * or undefined if:\n * - the current state has no `sub` definition, OR\n * - the sub-Runtime failed to initialise (SubMachineError was thrown\n * from `send()` / `reset()` / `createRuntime` per the spec contract),\n * OR\n * - the parent runtime has been disposed.\n *\n * The returned Runtime is typed at the loosest sub-machine signature.\n * Caller casts to the concrete sub type.\n *\n * Re-entry: when the parent leaves and re-enters a state with `sub`, a\n * fresh sub-Runtime is constructed. Previous sub-Runtime references held\n * by the caller are stale and MUST NOT be used (disposed).\n */\n subRuntime(): Runtime<unknown, { type: string }, string> | undefined;\n /**\n * Semantic sugar for `runtime.on('transition', handler, opts)`. Returns\n * the same unsubscribe function. Sharing the same listener Set with\n * `on('transition', ...)` means registration order determines invocation\n * order across both APIs.\n *\n * @since 0.3.0\n */\n onTransition(\n handler: (payload: RuntimeTransitionEvent<Ctx, Evt, States>) => void,\n options?: { signal?: AbortSignal; once?: boolean },\n ): () => void;\n}\n\nexport type RuntimeOptions<Ctx, Evt, States extends string> = Readonly<{\n middleware?: readonly Middleware<Ctx, Evt, States>[];\n /**\n * If false, do not dispatch effects through the effect handler map.\n * Useful for replay / dry-run modes. Defaults to true.\n */\n dispatchEffects?: boolean;\n}>;\n","import { isAsyncGuardFn } from \"./evaluator.js\";\nimport { normalizeTransitions } from \"./resolver.js\";\nimport { createRuntime } from \"./runtime.js\";\nimport { freezeSnapshot } from \"./snapshot.js\";\nimport type {\n Implementations,\n MachineConfig,\n MachineDef,\n Runtime,\n RuntimeOptions,\n Snapshot,\n StateDef,\n} from \"./types.js\";\n\nexport class InvalidDefinitionError extends Error {\n constructor(message: string) {\n super(`aifsmjs: ${message}`);\n this.name = \"InvalidDefinitionError\";\n }\n}\n\nfunction validateDefinition<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n // Cycle guard: subs may reference each other (or themselves) by object\n // identity. We validate each distinct definition object at most once so a\n // self/mutually-referential sub graph terminates instead of recursing\n // forever (C2). Seeded by the public entry points below.\n seen: WeakSet<object> = new WeakSet(),\n): void {\n if (!def.id || typeof def.id !== \"string\") {\n throw new InvalidDefinitionError(\"definition must have a non-empty string `id`\");\n }\n /* v8 ignore next 3 — additional safety: TS prevents non-object `states`; this guards untyped JS callers. */\n if (!def.states || typeof def.states !== \"object\") {\n throw new InvalidDefinitionError(\"definition must have a `states` object\");\n }\n const stateKeys = Object.keys(def.states) as States[];\n if (stateKeys.length === 0) {\n throw new InvalidDefinitionError(\"`states` must declare at least one state\");\n }\n if (!def.initial || !stateKeys.includes(def.initial)) {\n throw new InvalidDefinitionError(\n `\\`initial\\` \"${String(def.initial)}\" is not declared in states (${stateKeys.join(\", \")})`,\n );\n }\n for (const [stateName, stateDef] of Object.entries(def.states) as [\n States,\n (typeof def.states)[States],\n ][]) {\n // §4 sub-shape check + deep recursion (C2). The shallow shape check rejects\n // a malformed sub; recursing validateDefinition into the sub then rejects an\n // unknown transition target or a declared-async guard at construction\n // instead of leaving it to blow up at child.send(). Closes the FSM-07 sub\n // async-guard discrepancy (same root). The cycle guard makes this safe for\n // self/mutually-referential subs.\n if (stateDef.sub !== undefined) {\n const sub = stateDef.sub;\n const subStates = (sub as { states?: unknown }).states;\n const subInitial = (sub as { initial?: unknown }).initial;\n if (\n typeof sub !== \"object\" ||\n sub === null ||\n typeof subStates !== \"object\" ||\n subStates === null ||\n typeof subInitial !== \"string\" ||\n // initial must name one of the sub's own states — otherwise the child\n // boots pointing at a non-existent state and no-ops forever (FSM-S-02).\n !Object.hasOwn(subStates as object, subInitial)\n ) {\n throw new InvalidDefinitionError(\n `state \"${stateName}\".sub is not a valid sub-machine definition (missing states or initial)`,\n );\n }\n // Recurse — but only once per distinct sub object (cycle guard).\n if (!seen.has(sub as object)) {\n seen.add(sub as object);\n validateDefinition(sub as MachineDef<unknown, { type: string }, string>, seen);\n }\n }\n if (!stateDef.on) continue;\n for (const [evtType, entry] of Object.entries(stateDef.on)) {\n const transitions = normalizeTransitions(entry);\n for (const t of transitions) {\n if (t.target !== undefined && !stateKeys.includes(t.target)) {\n throw new InvalidDefinitionError(\n `transition ${stateName} -[${evtType}]-> \"${String(t.target)}\" targets an unknown state`,\n );\n }\n if (t.guard !== undefined && isAsyncGuardFn(t.guard)) {\n throw new InvalidDefinitionError(\n `transition ${stateName} -[${evtType}]-> uses an async guard. Guards must be sync; move I/O into an effect.`,\n );\n }\n }\n }\n }\n}\n\n/**\n * Validate a machine definition shape and return it. When `context` is\n * provided the same reference is returned; when it is omitted a shallow copy\n * with `context: {}` is returned. Validation is intentionally shallow.\n *\n * Two call forms:\n *\n * defineMachine<Ctx, Evt, States>({ ... })\n * Explicit generics. Use when you need full control (e.g. union event\n * types). Required because TypeScript cannot otherwise infer `Evt`.\n *\n * setup<Ctx, Evt>().defineMachine({ ... })\n * Curried form. Lets `States` be inferred from `keyof states`, so you\n * can omit it. Recommended for typical usage.\n */\nexport function defineMachine<\n Ctx = Record<string, never>,\n Evt extends { type: string } = { type: string },\n States extends string = string,\n>(def: MachineConfig<Ctx, Evt, States>): MachineDef<Ctx, Evt, States> {\n const normalized = (!(\"context\" in def) ? { ...def, context: {} as Ctx } : def) as MachineDef<\n Ctx,\n Evt,\n States\n >;\n validateDefinition(normalized);\n return normalized;\n}\n\n/**\n * Curried builder so `States` can be inferred from `keyof states` without\n * `initial` collapsing it to a single literal. Pass `Ctx` and `Evt` as the\n * type arguments; pass the def to the returned `defineMachine`.\n *\n * const machine = setup<MyCtx, MyEvt>().defineMachine({\n * id: \"m\",\n * initial: \"a\",\n * context: { ... },\n * states: { a: {...}, b: {...} }, // States inferred as \"a\" | \"b\"\n * });\n */\nexport function setup<\n Ctx = Record<string, never>,\n Evt extends { type: string } = { type: string },\n>(): {\n defineMachine: <const States extends string>(\n def: Readonly<{\n id: string;\n initial: NoInfer<States>;\n states: Readonly<Record<States, StateDef<Ctx, Evt, States>>>;\n }> &\n (Record<string, never> extends Ctx ? { readonly context?: Ctx } : { readonly context: Ctx }),\n ) => MachineDef<Ctx, Evt, States>;\n} {\n return {\n defineMachine: <const States extends string>(\n def: Readonly<{\n id: string;\n initial: NoInfer<States>;\n states: Readonly<Record<States, StateDef<Ctx, Evt, States>>>;\n }> &\n (Record<string, never> extends Ctx\n ? { readonly context?: Ctx }\n : { readonly context: Ctx }),\n ) => {\n const cast = (!(\"context\" in def)\n ? { ...def, context: {} as Ctx }\n : def) as unknown as MachineDef<Ctx, Evt, States>;\n validateDefinition(cast);\n return cast;\n },\n };\n}\n\n/**\n * Build the initial snapshot for a machine.\n */\nexport function initialSnapshot<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n): Snapshot<Ctx, States> {\n const isFinal = def.states[def.initial]?.final === true;\n return freezeSnapshot({\n value: def.initial,\n context: def.context,\n status: isFinal ? (\"final\" as const) : (\"active\" as const),\n });\n}\n\n/**\n * Convenience factory that composes `defineMachine` and `createRuntime` in\n * one call for the common case where you do not need to keep the machine\n * definition around for serialization or sharing.\n *\n * For type inference over `States` from `keyof states`, prefer\n * `setup<Ctx, Evt>().defineMachine(...)` then pass the result to\n * `createRuntime` separately. `createMachine` is the spec-style entry point\n * documented in the ai*js ecosystem review.\n */\nexport function createMachine<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n opts?: RuntimeOptions<Ctx, Evt, States>,\n): Runtime<Ctx, Evt, States> {\n return createRuntime(defineMachine(def), impl, opts ?? {});\n}\n","import { initialSnapshot } from \"./definition.js\";\nimport { evalGuard, isThenable } from \"./evaluator.js\";\nimport { step } from \"./lifecycle.js\";\nimport { normalizeTransitions } from \"./resolver.js\";\nimport { deepFreeze } from \"./snapshot.js\";\nimport {\n type Effect,\n type Implementations,\n type MachineDef,\n type Middleware,\n RESET_EVENT_TYPE,\n type ResetEvent,\n type Runtime,\n type RuntimeEventMap,\n type RuntimeOptions,\n type RuntimeTransitionEvent,\n type Snapshot,\n} from \"./types.js\";\n\nexport class RuntimeDisposedError extends Error {\n constructor() {\n super(\"aifsmjs: runtime has been disposed; send()/reset() are not allowed\");\n this.name = \"RuntimeDisposedError\";\n }\n}\n\n/**\n * Thrown by `send()` / `reset()` when a sub-machine init or dispose throws.\n *\n * Invariants:\n * - `phase: \"init\"` — child constructor threw. Parent snapshot was rolled\n * back to `prev`; no middleware ran; no `'transition'` emitted; no effects.\n * - `phase: \"dispose\"` — previous child's `dispose()` threw during transition.\n * Parent snapshot was rolled back to `prev`; child reference is cleared.\n * - Never thrown from `runtime.dispose()` cascade (never-throws contract).\n *\n * @since 0.3.0\n */\nexport class SubMachineError extends Error {\n readonly parentState: string;\n readonly phase: \"init\" | \"dispose\";\n override readonly cause: unknown;\n\n constructor(parentState: string, phase: \"init\" | \"dispose\", cause: unknown) {\n super(`aifsmjs: sub-machine ${phase} failed at parent state \"${parentState}\"`, { cause });\n this.name = \"SubMachineError\";\n this.parentState = parentState;\n this.phase = phase;\n this.cause = cause; // belt-and-suspenders: legacy bundlers ignore ES2022 cause option\n }\n}\n\nconst RESET_EVENT: ResetEvent = Object.freeze({ type: RESET_EVENT_TYPE });\n\nfunction composeMiddleware<Ctx, Evt, States extends string>(\n middleware: readonly Middleware<Ctx, Evt, States>[],\n): Middleware<Ctx, Evt, States> {\n return (ctx, finalNext) => {\n let index = -1;\n const dispatch = (i: number): void => {\n if (i <= index) throw new Error(\"aifsmjs: next() called multiple times in middleware\");\n index = i;\n const fn = middleware[i];\n if (!fn) {\n finalNext();\n return;\n }\n fn(ctx, () => dispatch(i + 1));\n };\n dispatch(0);\n };\n}\n\n/**\n * Build a thin stateful runtime around a machine. `send()` calls `step()`,\n * runs the read-only middleware pipeline, dispatches effects, and notifies\n * subscribers. The runtime owns an `AbortController`; `dispose()` aborts it\n * and clears all state.\n */\nexport function createRuntime<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n opts: RuntimeOptions<Ctx, Evt, States> = {},\n): Runtime<Ctx, Evt, States> {\n let snapshot: Snapshot<Ctx, States> = initialSnapshot(def);\n const listeners = new Set<(snap: Snapshot<Ctx, States>) => void>();\n const middlewareChain =\n opts.middleware && opts.middleware.length > 0 ? composeMiddleware(opts.middleware) : undefined;\n const shouldDispatch = opts.dispatchEffects !== false;\n const controller = new AbortController();\n let disposed = false;\n // §3.1 sub-machine state. childRuntime is the live child; childAbortCleanup\n // detaches the parent-abort listener attached by wireChildAbort. Both are\n // cleared together whenever the child is replaced or disposed (P1-3 fix).\n let childRuntime: Runtime<unknown, { type: string }, string> | undefined;\n let childAbortCleanup: (() => void) | undefined;\n\n type EventListeners = {\n [K in keyof RuntimeEventMap<Ctx, Evt, States>]: Set<\n (payload: RuntimeEventMap<Ctx, Evt, States>[K]) => void\n >;\n };\n const eventListeners: EventListeners = {\n transition: new Set(),\n error: new Set(),\n dispose: new Set(),\n };\n const externalAbortCleanups = new Set<() => void>();\n\n function emit<K extends keyof RuntimeEventMap<Ctx, Evt, States>>(\n type: K,\n payload: RuntimeEventMap<Ctx, Evt, States>[K],\n ): void {\n // Snapshot-before-iterate (family canonical, aieventjs .slice()): a\n // listener that subscribes/unsubscribes another during dispatch must not\n // mutate the set being walked. One array alloc per emit, matching the\n // family's accepted cost (FAM-S-03).\n for (const fn of Array.from(eventListeners[type])) fn(payload);\n }\n\n function notify(committed?: Snapshot<Ctx, States>) {\n const captured = committed ?? snapshot;\n // Snapshot-before-iterate, as above (FAM-S-03).\n for (const l of Array.from(listeners)) l(captured);\n }\n\n function runMiddleware(\n prev: Snapshot<Ctx, States>,\n event: Evt | ResetEvent,\n effects: readonly Effect[],\n changed: boolean,\n ) {\n if (!middlewareChain) return;\n middlewareChain(deepFreeze({ prev, next: snapshot, event, effects, changed }), () => {});\n }\n\n function dispatchEffects(effects: readonly Effect[], context: Ctx, event: Evt): void {\n if (!impl.effects || effects.length === 0) return;\n for (const eff of effects) {\n const handler = impl.effects[eff.type];\n if (!handler) continue;\n const r = handler(eff, { context, event, signal: controller.signal });\n // isThenable (not instanceof Promise) so cross-realm Promises and\n // user-defined PromiseLike results also have their rejections routed to\n // the 'error' channel; Promise.resolve() normalises them (FSM-B-03).\n if (isThenable(r)) {\n Promise.resolve(r).catch((err: unknown) => {\n emit(\"error\", { error: err, event });\n });\n }\n }\n }\n\n // §3.1 Attach one-shot abort listener: parent dispose → child.dispose().\n // Returns a cleanup fn that detaches the listener; caller stores it in\n // `childAbortCleanup` and invokes when the child is replaced/disposed\n // (P1-3 fix: prevent stale listeners accumulating on the parent signal).\n function wireChildAbort(child: Runtime<unknown, { type: string }, string>): () => void {\n /* v8 ignore next 7 — parent may already be aborted in edge cases; dispose still runs */\n if (controller.signal.aborted) {\n try {\n child.dispose();\n } catch {\n /* swallow */\n }\n return () => {};\n }\n /* v8 ignore next 7 — defensive: dispose() pre-cleans this listener and\n disposes the child manually before calling controller.abort(), so\n onAbort fires only if external code aborts the controller bypassing\n dispose(). Internal-only controller has no such external path today. */\n const onAbort = () => {\n try {\n child.dispose();\n } catch {\n /* swallow */\n }\n };\n controller.signal.addEventListener(\"abort\", onAbort, { once: true });\n return () => controller.signal.removeEventListener(\"abort\", onAbort);\n }\n\n // §3.1 Instantiate the child for `stateValue` (which must have a `sub`) and\n // wire its parent-abort listener, committing both to childRuntime /\n // childAbortCleanup. Throws SubMachineError(phase: \"init\") on failure; the\n // caller must NOT commit the parent snapshot on throw. Single source of the\n // init+wire sequence shared by applySubLifecycle, reset(), and bootstrap\n // (FSM-C-01) — keeps the most failure-sensitive path in one place.\n function initChildFor(stateValue: States): void {\n const stateDef = def.states[stateValue];\n const sub = stateDef?.sub;\n /* v8 ignore next 2 — callers only invoke this after checking stateDef.sub\n is defined; the guard documents that precondition and is never taken. */\n if (sub === undefined) return;\n let newChild: Runtime<unknown, { type: string }, string>;\n try {\n newChild = createRuntime(sub, stateDef.subImpl ?? {});\n } catch (cause) {\n throw new SubMachineError(stateValue as string, \"init\", cause);\n }\n childRuntime = newChild;\n childAbortCleanup = wireChildAbort(newChild);\n }\n\n // §3.3 Re-resolve guards to find the chosen transition and determine\n // whether it is external (has a `target`). Replaces the v0.3.0 dev\n // hasSelfTargetMarker heuristic that over-reported when an event had both\n // internal (no-target) and self-target (target === value) candidates\n // (P1-2 fix). Cost: one extra guard evaluation pass per same-value event.\n function findChosenIsExternal(value: States, event: Evt, context: Ctx): boolean {\n const state = def.states[value];\n if (!state?.on) return false;\n const list = normalizeTransitions(state.on[event.type]);\n if (list.length === 0) return false;\n for (const t of list) {\n if (!t.guard || evalGuard(t.guard, context, event, impl, value)) {\n return t.target !== undefined;\n }\n }\n /* v8 ignore next — defensive: caller only invokes when step() returned\n changed=true, which guarantees a matching guard exists in the same\n candidate list. The for-loop above always returns before this line. */\n return false;\n }\n\n // §3.1 Dispose old child and/or init new child. Throws SubMachineError on failure.\n // Caller must NOT commit snapshot on throw.\n function applySubLifecycle(prevValue: States, nextValue: States): void {\n const prevStateDef = def.states[prevValue];\n const nextStateDef = def.states[nextValue];\n if (prevStateDef?.sub !== undefined && childRuntime !== undefined) {\n const child = childRuntime;\n childRuntime = undefined;\n childAbortCleanup?.();\n childAbortCleanup = undefined;\n try {\n child.dispose();\n } catch (cause) {\n throw new SubMachineError(prevValue as string, \"dispose\", cause);\n }\n }\n if (nextStateDef?.sub !== undefined) {\n initChildFor(nextValue);\n }\n }\n\n function send(event: Evt): Snapshot<Ctx, States> {\n if (disposed) throw new RuntimeDisposedError();\n const prev = snapshot;\n const result = step(def, prev, event, impl);\n const isExternal =\n result.changed &&\n (prev.value !== result.snapshot.value ||\n findChosenIsExternal(prev.value, event, prev.context));\n // Sub lifecycle BEFORE snapshot commit (§3.4); throws SubMachineError on failure → no commit\n if (result.changed && isExternal) applySubLifecycle(prev.value, result.snapshot.value);\n snapshot = result.snapshot;\n const committed = result.snapshot;\n runMiddleware(prev, event, result.effects, result.changed);\n if (shouldDispatch) dispatchEffects(result.effects, committed.context, event);\n if (result.changed) {\n notify(committed);\n emit(\"transition\", {\n prev,\n next: committed,\n event,\n effects: result.effects,\n changed: true,\n } as RuntimeTransitionEvent<Ctx, Evt, States>);\n }\n return snapshot;\n }\n\n function reset(event?: Evt): Snapshot<Ctx, States> {\n if (disposed) throw new RuntimeDisposedError();\n const prev = snapshot;\n const nextSnap = initialSnapshot(def);\n const changed = prev.value !== nextSnap.value;\n // Dispose current child (§3.5)\n if (childRuntime) {\n const child = childRuntime;\n childRuntime = undefined;\n childAbortCleanup?.();\n childAbortCleanup = undefined;\n try {\n child.dispose();\n } catch (cause) {\n throw new SubMachineError(prev.value as string, \"dispose\", cause);\n }\n }\n // Init child for new initial state if it has sub (§3.5)\n const initStateDef = def.states[nextSnap.value];\n if (initStateDef?.sub) {\n initChildFor(nextSnap.value);\n }\n snapshot = nextSnap;\n // Capture the committed snapshot before notify()/emit so a subscriber that\n // re-entrantly send()s (which advances the mutable `snapshot`) cannot\n // corrupt this reset's payload — mirrors send()'s 0.2.0 fix (FSM-B-01).\n const committed = nextSnap;\n const triggerEvent: Evt | ResetEvent = event ?? RESET_EVENT;\n runMiddleware(prev, triggerEvent, [], changed);\n if (changed) {\n notify(committed);\n emit(\"transition\", {\n prev,\n next: committed,\n event: triggerEvent,\n effects: [],\n changed: true,\n } as RuntimeTransitionEvent<Ctx, Evt, States>);\n }\n // Return the live snapshot (consistent with send()): under a re-entrant\n // send() from a subscriber, this reflects the latest committed state. Only\n // the emitted payload above is pinned to this reset's own outcome.\n return snapshot;\n }\n\n function can(event: Evt): boolean {\n if (disposed || snapshot.status === \"final\") return false;\n const state = def.states[snapshot.value];\n /* v8 ignore next — defensive: snapshot.value always corresponds to a declared state. */\n if (!state) return false;\n const list = normalizeTransitions(state.on?.[event.type]);\n if (list.length === 0) return false;\n for (const t of list) {\n if (!t.guard) return true;\n if (evalGuard(t.guard, snapshot.context, event, impl, snapshot.value)) return true;\n }\n return false;\n }\n\n function on<K extends keyof RuntimeEventMap<Ctx, Evt, States>>(\n type: K,\n listener: (payload: RuntimeEventMap<Ctx, Evt, States>[K]) => void,\n options?: { signal?: AbortSignal; once?: boolean },\n ): () => void {\n if (disposed || options?.signal?.aborted) return () => {};\n const target = eventListeners[type];\n let detachAbort: (() => void) | undefined;\n // Full teardown shared by the once-wrapper, the abort handler, and the\n // returned unsubscribe so every path detaches the abort listener too — a\n // once-handler that also passed a { signal } previously left the abort\n // listener attached until dispose()/abort (memory leak).\n const cleanup = (): void => {\n target.delete(wrapped);\n if (detachAbort) {\n detachAbort();\n externalAbortCleanups.delete(detachAbort);\n }\n };\n let wrapped: (payload: RuntimeEventMap<Ctx, Evt, States>[K]) => void = listener;\n if (options?.once) {\n wrapped = (payload) => {\n cleanup();\n listener(payload);\n };\n }\n target.add(wrapped);\n const signal = options?.signal;\n if (signal) {\n const onAbort = () => cleanup();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n detachAbort = () => signal.removeEventListener(\"abort\", onAbort);\n externalAbortCleanups.add(detachAbort);\n }\n return cleanup;\n }\n\n function dispose(): void {\n if (disposed) return;\n disposed = true;\n // Cascade child dispose; swallow exceptions (dispose contract) (§3.6)\n if (childRuntime) {\n childAbortCleanup?.();\n childAbortCleanup = undefined;\n try {\n childRuntime.dispose();\n } catch {\n /* swallow */\n }\n childRuntime = undefined;\n }\n controller.abort();\n listeners.clear();\n // §3.6 dispose() is contractually never-throws + idempotent (README:65,\n // STABILITY.md:22). emit('dispose') runs user listeners; a throwing one\n // must neither escape dispose() nor abort the remaining teardown (which\n // would leak external-signal abort listeners, since a second dispose()\n // short-circuits on `if (disposed) return`). The try/finally guarantees\n // the listener-set clear + externalAbortCleanups loop ALWAYS run, mirroring\n // the defensiveness of the child-dispose cascade above.\n try {\n emit(\"dispose\", undefined as RuntimeEventMap<Ctx, Evt, States>[\"dispose\"]);\n } catch {\n /* swallow — never-throws contract */\n } finally {\n for (const set of Object.values(eventListeners)) set.clear();\n for (const cleanup of externalAbortCleanups) cleanup();\n externalAbortCleanups.clear();\n }\n }\n\n const runtime: Runtime<Ctx, Evt, States> = {\n getSnapshot: () => snapshot,\n snapshot: () => snapshot,\n send,\n can,\n reset,\n dispose,\n on,\n get disposed() {\n return disposed;\n },\n get signal() {\n return controller.signal;\n },\n subscribe(listener) {\n if (disposed) return () => {};\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n subRuntime: () => childRuntime,\n onTransition: (handler, options) => on(\"transition\", handler, options),\n };\n\n // §2 Bootstrap: if initial state has sub, instantiate child BEFORE returning.\n // Failure throws SubMachineError(initialState, \"init\", cause).\n const bootStateDef = def.states[snapshot.value];\n if (bootStateDef?.sub) {\n initChildFor(snapshot.value);\n }\n\n return runtime;\n}\n"]}
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunk2MME5V4F_cjs = require('./chunk-2MME5V4F.cjs');
3
+ var chunkTPCDOVU4_cjs = require('./chunk-TPCDOVU4.cjs');
4
4
  var chunkI354FONA_cjs = require('./chunk-I354FONA.cjs');
5
5
  require('./chunk-3B2USJ3H.cjs');
6
6
  var chunkCDK25FTD_cjs = require('./chunk-CDK25FTD.cjs');
@@ -10,39 +10,39 @@ require('./chunk-Q7SFCCGT.cjs');
10
10
 
11
11
  Object.defineProperty(exports, "InvalidDefinitionError", {
12
12
  enumerable: true,
13
- get: function () { return chunk2MME5V4F_cjs.InvalidDefinitionError; }
13
+ get: function () { return chunkTPCDOVU4_cjs.InvalidDefinitionError; }
14
14
  });
15
15
  Object.defineProperty(exports, "RESET_EVENT_TYPE", {
16
16
  enumerable: true,
17
- get: function () { return chunk2MME5V4F_cjs.RESET_EVENT_TYPE; }
17
+ get: function () { return chunkTPCDOVU4_cjs.RESET_EVENT_TYPE; }
18
18
  });
19
19
  Object.defineProperty(exports, "RuntimeDisposedError", {
20
20
  enumerable: true,
21
- get: function () { return chunk2MME5V4F_cjs.RuntimeDisposedError; }
21
+ get: function () { return chunkTPCDOVU4_cjs.RuntimeDisposedError; }
22
22
  });
23
23
  Object.defineProperty(exports, "SubMachineError", {
24
24
  enumerable: true,
25
- get: function () { return chunk2MME5V4F_cjs.SubMachineError; }
25
+ get: function () { return chunkTPCDOVU4_cjs.SubMachineError; }
26
26
  });
27
27
  Object.defineProperty(exports, "createMachine", {
28
28
  enumerable: true,
29
- get: function () { return chunk2MME5V4F_cjs.createMachine; }
29
+ get: function () { return chunkTPCDOVU4_cjs.createMachine; }
30
30
  });
31
31
  Object.defineProperty(exports, "createRuntime", {
32
32
  enumerable: true,
33
- get: function () { return chunk2MME5V4F_cjs.createRuntime; }
33
+ get: function () { return chunkTPCDOVU4_cjs.createRuntime; }
34
34
  });
35
35
  Object.defineProperty(exports, "defineMachine", {
36
36
  enumerable: true,
37
- get: function () { return chunk2MME5V4F_cjs.defineMachine; }
37
+ get: function () { return chunkTPCDOVU4_cjs.defineMachine; }
38
38
  });
39
39
  Object.defineProperty(exports, "initialSnapshot", {
40
40
  enumerable: true,
41
- get: function () { return chunk2MME5V4F_cjs.initialSnapshot; }
41
+ get: function () { return chunkTPCDOVU4_cjs.initialSnapshot; }
42
42
  });
43
43
  Object.defineProperty(exports, "setup", {
44
44
  enumerable: true,
45
- get: function () { return chunk2MME5V4F_cjs.setup; }
45
+ get: function () { return chunkTPCDOVU4_cjs.setup; }
46
46
  });
47
47
  Object.defineProperty(exports, "UnknownActionError", {
48
48
  enumerable: true,
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { InvalidDefinitionError, RESET_EVENT_TYPE, RuntimeDisposedError, SubMachineError, createMachine, createRuntime, defineMachine, initialSnapshot, setup } from './chunk-VZCSHTOI.js';
1
+ export { InvalidDefinitionError, RESET_EVENT_TYPE, RuntimeDisposedError, SubMachineError, createMachine, createRuntime, defineMachine, initialSnapshot, setup } from './chunk-LG2AH5X6.js';
2
2
  export { UnknownActionError, assign, createSnapshot, deepFreeze, freezeSnapshot, mergeContext, normalizeTransition, normalizeTransitions, resolveTransitions, step } from './chunk-ZLQ7HZCE.js';
3
3
  import './chunk-JKZAOPQC.js';
4
4
  export { AsyncGuardError, UnknownGuardError, evalGuard, isAsyncGuardFn, resolveGuard } from './chunk-A7U7QQL5.js';
@@ -1,12 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunk2MME5V4F_cjs = require('../chunk-2MME5V4F.cjs');
3
+ var chunkTPCDOVU4_cjs = require('../chunk-TPCDOVU4.cjs');
4
4
  var chunkFHTQ7LSQ_cjs = require('../chunk-FHTQ7LSQ.cjs');
5
5
  var chunkI354FONA_cjs = require('../chunk-I354FONA.cjs');
6
6
  require('../chunk-3B2USJ3H.cjs');
7
7
  require('../chunk-CDK25FTD.cjs');
8
8
  var chunkQ7SFCCGT_cjs = require('../chunk-Q7SFCCGT.cjs');
9
9
  var fc2 = require('fast-check');
10
+ var util = require('util');
10
11
 
11
12
  function _interopNamespace(e) {
12
13
  if (e && e.__esModule) return e;
@@ -80,6 +81,7 @@ var properties_exports = {};
80
81
  chunkQ7SFCCGT_cjs.__export(properties_exports, {
81
82
  assertAll: () => assertAll,
82
83
  assignDoesNotMutate: () => assignDoesNotMutate,
84
+ contextEquals: () => contextEquals,
83
85
  guardsFalseNoTransition: () => guardsFalseNoTransition,
84
86
  reachableStatesSubsetDeclared: () => reachableStatesSubsetDeclared,
85
87
  replayEqualsFold: () => replayEqualsFold,
@@ -93,10 +95,13 @@ function buildAssertOpts(opts) {
93
95
  if (opts?.verbose) out.verbose = true;
94
96
  return out;
95
97
  }
98
+ function contextEquals(a, b) {
99
+ return util.isDeepStrictEqual(a, b);
100
+ }
96
101
  function snapshotAlwaysFrozen(def, impl, eventArbitraries, opts) {
97
102
  fc2__namespace.assert(
98
103
  fc2__namespace.property(commandsFromMachine(def, impl, eventArbitraries), (cmds) => {
99
- const real = chunk2MME5V4F_cjs.createRuntime(def, impl);
104
+ const real = chunkTPCDOVU4_cjs.createRuntime(def, impl);
100
105
  const model = initialModel(def);
101
106
  fc2__namespace.modelRun(() => ({ model, real }), cmds);
102
107
  return Object.isFrozen(real.getSnapshot());
@@ -107,7 +112,7 @@ function snapshotAlwaysFrozen(def, impl, eventArbitraries, opts) {
107
112
  function unknownEventNoOp(def, impl, unknownType, opts) {
108
113
  fc2__namespace.assert(
109
114
  fc2__namespace.property(fc2__namespace.constant(unknownType), (t) => {
110
- const initial = chunk2MME5V4F_cjs.initialSnapshot(def);
115
+ const initial = chunkTPCDOVU4_cjs.initialSnapshot(def);
111
116
  const result = chunkI354FONA_cjs.step(def, initial, { type: t }, impl);
112
117
  return result.changed === false && result.snapshot === initial && result.effects.length === 0;
113
118
  }),
@@ -118,7 +123,7 @@ function reachableStatesSubsetDeclared(def, impl, eventArbitraries, opts) {
118
123
  const declared = new Set(Object.keys(def.states));
119
124
  fc2__namespace.assert(
120
125
  fc2__namespace.property(commandsFromMachine(def, impl, eventArbitraries), (cmds) => {
121
- const real = chunk2MME5V4F_cjs.createRuntime(def, impl);
126
+ const real = chunkTPCDOVU4_cjs.createRuntime(def, impl);
122
127
  const model = initialModel(def);
123
128
  fc2__namespace.modelRun(() => ({ model, real }), cmds);
124
129
  for (const s of model.reached) {
@@ -133,11 +138,11 @@ function replayEqualsFold(def, impl, eventArbitraries, opts) {
133
138
  const eventArb = fc2__namespace.oneof(...Object.values(eventArbitraries));
134
139
  fc2__namespace.assert(
135
140
  fc2__namespace.property(fc2__namespace.array(eventArb, { maxLength: 32 }), (events) => {
136
- const real = chunk2MME5V4F_cjs.createRuntime(def, impl, { dispatchEffects: false });
141
+ const real = chunkTPCDOVU4_cjs.createRuntime(def, impl, { dispatchEffects: false });
137
142
  for (const e of events) real.send(e);
138
143
  const live = real.getSnapshot();
139
- const replayed = chunkFHTQ7LSQ_cjs.replay(chunk2MME5V4F_cjs.initialSnapshot(def), events, def, impl).snapshot;
140
- return live.value === replayed.value && JSON.stringify(live.context) === JSON.stringify(replayed.context);
144
+ const replayed = chunkFHTQ7LSQ_cjs.replay(chunkTPCDOVU4_cjs.initialSnapshot(def), events, def, impl).snapshot;
145
+ return live.value === replayed.value && contextEquals(live.context, replayed.context);
141
146
  }),
142
147
  buildAssertOpts(opts)
143
148
  );
@@ -161,7 +166,7 @@ function guardsFalseNoTransition(def, impl, eventArbitraries, opts) {
161
166
  fc2__namespace.property(
162
167
  fc2__namespace.array(fc2__namespace.oneof(...Object.values(eventArbitraries)), { maxLength: 16 }),
163
168
  (events) => {
164
- let snap = chunk2MME5V4F_cjs.initialSnapshot(def);
169
+ let snap = chunkTPCDOVU4_cjs.initialSnapshot(def);
165
170
  for (const e of events) {
166
171
  const fullyGuarded = isFullyGuarded(snap.value, e.type);
167
172
  const r = chunkI354FONA_cjs.step(def, snap, e, blockedImpl);
@@ -182,11 +187,11 @@ function assignDoesNotMutate(def, impl, eventArbitraries, opts) {
182
187
  fc2__namespace.property(
183
188
  fc2__namespace.array(fc2__namespace.oneof(...Object.values(eventArbitraries)), { maxLength: 16 }),
184
189
  (events) => {
185
- let snap = chunk2MME5V4F_cjs.initialSnapshot(def);
190
+ let snap = chunkTPCDOVU4_cjs.initialSnapshot(def);
186
191
  for (const e of events) {
187
- const beforeCtxSerialised = JSON.stringify(snap.context);
192
+ const beforeCtx = structuredClone(snap.context);
188
193
  chunkI354FONA_cjs.step(def, snap, e, impl);
189
- if (JSON.stringify(snap.context) !== beforeCtxSerialised) return false;
194
+ if (!contextEquals(snap.context, beforeCtx)) return false;
190
195
  snap = chunkI354FONA_cjs.step(def, snap, e, impl).snapshot;
191
196
  }
192
197
  return true;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/pbt/commands.ts","../../src/pbt/properties.ts","../../src/pbt/index.ts"],"names":["step","fc","__export","fc2","createRuntime","initialSnapshot","replay","normalizeTransitions","mergeContext"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBO,SAAS,aACd,GAAA,EACuB;AACvB,EAAA,OAAO;AAAA,IACL,OAAO,GAAA,CAAI,OAAA;AAAA,IACX,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,QAAQ,GAAA,CAAI,MAAA,CAAO,IAAI,OAAO,CAAA,EAAG,QAAQ,OAAA,GAAU,QAAA;AAAA,IACnD,yBAAS,IAAI,GAAA,CAAI,CAAC,GAAA,CAAI,OAAO,CAAC;AAAA,GAChC;AACF;AAEA,IAAM,cAAN,MAEA;AAAA,EACE,WAAA,CACmB,KAAA,EACA,GAAA,EACA,IAAA,EACjB;AAHiB,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAChB;AAAA,EAHgB,KAAA;AAAA,EACA,GAAA;AAAA,EACA,IAAA;AAAA,EAGnB,MAAM,EAAA,EAA8C;AAElD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,GAAA,CAAI,GAA0B,CAAA,EAAoC;AAChE,IAAA,MAAM,MAAA,GAAgC,EAAE,WAAA,EAAY;AACpD,IAAA,CAAA,CAAE,IAAA,CAAK,KAAK,KAAK,CAAA;AACjB,IAAA,MAAM,KAAA,GAAQ,EAAE,WAAA,EAAY;AAE5B,IAAA,MAAM,SAAA,GAAYA,uBAAK,IAAA,CAAK,GAAA,EAAK,QAAQ,IAAA,CAAK,KAAA,EAAO,KAAK,IAAI,CAAA;AAI9D,IAAA,IAAI,SAAA,CAAU,QAAA,CAAS,KAAA,KAAU,KAAA,CAAM,KAAA,EAAO;AAC5C,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,qDAAA,EAAmD,MAAA,CAAO,SAAA,CAAU,QAAA,CAAS,KAAK,CAAC,CAAA,wBAAA,EAA2B,MAAA,CAAO,KAAA,CAAM,KAAK,CAAC,CAAA,QAAA,EAAW,IAAA,CAAK,UAAU,CAAA;AAAA,OAC7J;AAAA,IACF;AAGA,IAAA,CAAA,CAAE,QAAQ,KAAA,CAAM,KAAA;AAChB,IAAA,CAAA,CAAE,UAAU,KAAA,CAAM,OAAA;AAClB,IAAA,CAAA,CAAE,SAAS,KAAA,CAAM,MAAA;AACjB,IAAA,CAAA,CAAE,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA;AAAA,EAC3B;AAAA,EAEA,QAAA,GAAmB;AACjB,IAAA,OAAO,CAAA,KAAA,EAAQ,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,KAAK,CAAC,CAAA,CAAA,CAAA;AAAA,EAC3C;AACF,CAAA;AAWO,SAAS,mBAAA,CACd,GAAA,EACA,IAAA,EACA,gBAAA,EACsD;AACtD,EAAA,MAAM,OAAqD,EAAC;AAC5D,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,MAAA,CAAO,gBAAgB,CAAA,EAAG;AACjD,IAAA,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,CAAC,KAAA,KAAU,IAAI,WAAA,CAAY,KAAA,EAAO,GAAA,EAAK,IAAI,CAAC,CAAC,CAAA;AAAA,EACjE;AACA,EAAA,OAAUC,cAAA,CAAA,QAAA,CAAS,IAAA,EAAM,EAAE,IAAA,EAAM,MAAM,CAAA;AACzC;;;AChGA,IAAA,kBAAA,GAAA,EAAA;AAAAC,0BAAA,CAAA,kBAAA,EAAA;AAAA,EAAA,SAAA,EAAA,MAAA,SAAA;AAAA,EAAA,mBAAA,EAAA,MAAA,mBAAA;AAAA,EAAA,uBAAA,EAAA,MAAA,uBAAA;AAAA,EAAA,6BAAA,EAAA,MAAA,6BAAA;AAAA,EAAA,gBAAA,EAAA,MAAA,gBAAA;AAAA,EAAA,oBAAA,EAAA,MAAA,oBAAA;AAAA,EAAA,gBAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AAqBA,SAAS,gBAAgB,IAAA,EAAsD;AAC7E,EAAA,MAAM,MAA8B,EAAC;AACrC,EAAA,IAAI,IAAA,EAAM,OAAA,KAAY,MAAA,EAAW,GAAA,CAAI,UAAU,IAAA,CAAK,OAAA;AACpD,EAAA,IAAI,IAAA,EAAM,IAAA,KAAS,MAAA,EAAW,GAAA,CAAI,OAAO,IAAA,CAAK,IAAA;AAC9C,EAAA,IAAI,IAAA,EAAM,OAAA,EAAS,GAAA,CAAI,OAAA,GAAU,IAAA;AACjC,EAAA,OAAO,GAAA;AACT;AAMO,SAAS,oBAAA,CACd,GAAA,EACA,IAAA,EACA,gBAAA,EACA,IAAA,EACM;AACN,EAAGC,cAAA,CAAA,MAAA;AAAA,IACEA,wBAAS,mBAAA,CAAoB,GAAA,EAAK,MAAM,gBAAgB,CAAA,EAAG,CAAC,IAAA,KAAS;AACtE,MAAA,MAAM,IAAA,GAAOC,+BAAA,CAAc,GAAA,EAAK,IAAI,CAAA;AACpC,MAAA,MAAM,KAAA,GAA+B,aAAa,GAAG,CAAA;AACrD,MAAGD,wBAAS,OAAO,EAAE,KAAA,EAAO,IAAA,KAAS,IAAI,CAAA;AACzC,MAAA,OAAO,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,WAAA,EAAa,CAAA;AAAA,IAC3C,CAAC,CAAA;AAAA,IACD,gBAAgB,IAAI;AAAA,GACtB;AACF;AAMO,SAAS,gBAAA,CACd,GAAA,EACA,IAAA,EACA,WAAA,EACA,IAAA,EACM;AACN,EAAGA,cAAA,CAAA,MAAA;AAAA,IACEA,cAAA,CAAA,QAAA,CAAYA,cAAA,CAAA,QAAA,CAAS,WAAW,CAAA,EAAG,CAAC,CAAA,KAAM;AAC3C,MAAA,MAAM,OAAA,GAAUE,kCAAgB,GAAG,CAAA;AACnC,MAAA,MAAM,MAAA,GAASL,uBAAK,GAAA,EAAK,OAAA,EAAS,EAAE,IAAA,EAAM,CAAA,IAAuB,IAAI,CAAA;AACrE,MAAA,OAAO,MAAA,CAAO,YAAY,KAAA,IAAS,MAAA,CAAO,aAAa,OAAA,IAAW,MAAA,CAAO,QAAQ,MAAA,KAAW,CAAA;AAAA,IAC9F,CAAC,CAAA;AAAA,IACD,gBAAgB,IAAI;AAAA,GACtB;AACF;AAMO,SAAS,6BAAA,CAKd,GAAA,EACA,IAAA,EACA,gBAAA,EACA,IAAA,EACM;AACN,EAAA,MAAM,WAAW,IAAI,GAAA,CAAY,OAAO,IAAA,CAAK,GAAA,CAAI,MAAM,CAAC,CAAA;AACxD,EAAGG,cAAA,CAAA,MAAA;AAAA,IACEA,wBAAS,mBAAA,CAAoB,GAAA,EAAK,MAAM,gBAAgB,CAAA,EAAG,CAAC,IAAA,KAAS;AACtE,MAAA,MAAM,IAAA,GAAOC,+BAAA,CAAc,GAAA,EAAK,IAAI,CAAA;AACpC,MAAA,MAAM,KAAA,GAA+B,aAAa,GAAG,CAAA;AACrD,MAAGD,wBAAS,OAAO,EAAE,KAAA,EAAO,IAAA,KAAS,IAAI,CAAA;AACzC,MAAA,KAAA,MAAW,CAAA,IAAK,MAAM,OAAA,EAAwB;AAE5C,QAAA,IAAI,CAAC,QAAA,CAAS,GAAA,CAAI,CAAC,GAAG,OAAO,KAAA;AAAA,MAC/B;AACA,MAAA,OAAO,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,WAAA,GAAc,KAAK,CAAA;AAAA,IAC9C,CAAC,CAAA;AAAA,IACD,gBAAgB,IAAI;AAAA,GACtB;AACF;AAOO,SAAS,gBAAA,CACd,GAAA,EACA,IAAA,EACA,gBAAA,EACA,IAAA,EACM;AACN,EAAA,MAAM,WAAcA,cAAA,CAAA,KAAA,CAAM,GAAG,MAAA,CAAO,MAAA,CAAO,gBAAgB,CAAC,CAAA;AAC5D,EAAGA,cAAA,CAAA,MAAA;AAAA,IACEA,cAAA,CAAA,QAAA,CAAYA,qBAAM,QAAA,EAAU,EAAE,WAAW,EAAA,EAAI,CAAA,EAAG,CAAC,MAAA,KAAW;AAC7D,MAAA,MAAM,OAAOC,+BAAA,CAAc,GAAA,EAAK,MAAM,EAAE,eAAA,EAAiB,OAAO,CAAA;AAChE,MAAA,KAAA,MAAW,CAAA,IAAK,MAAA,EAAQ,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACnC,MAAA,MAAM,IAAA,GAAO,KAAK,WAAA,EAAY;AAC9B,MAAA,MAAM,QAAA,GAAWE,yBAAOD,iCAAA,CAAgB,GAAG,GAAG,MAAA,EAAQ,GAAA,EAAK,IAAI,CAAA,CAAE,QAAA;AACjE,MAAA,OACE,IAAA,CAAK,KAAA,KAAU,QAAA,CAAS,KAAA,IACxB,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,OAAO,CAAA;AAAA,IAEpE,CAAC,CAAA;AAAA,IACD,gBAAgB,IAAI;AAAA,GACtB;AACF;AAaO,SAAS,uBAAA,CACd,GAAA,EACA,IAAA,EACA,gBAAA,EACA,IAAA,EACM;AACN,EAAA,MAAM,gBAAgB,IAAI,KAAA;AAAA,IACxB,EAAC;AAAA,IACD;AAAA,MACE,GAAA,EAAK,MAAM,MAAM;AAAA;AACnB,GACF;AACA,EAAA,MAAM,WAAA,GAAyC;AAAA,IAC7C,GAAG,IAAA;AAAA,IACH,MAAA,EAAQ;AAAA,GACV;AAIA,EAAA,MAAM,cAAA,GAAiB,CAAC,KAAA,EAAe,SAAA,KAA+B;AACpE,IAAA,MAAM,UAAA,GAAaE,uCAAqB,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,EAAG,EAAA,GAAK,SAAS,CAAC,CAAA;AAC1E,IAAA,OAAO,UAAA,CAAW,SAAS,CAAA,IAAK,UAAA,CAAW,MAAM,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,KAAU,MAAS,CAAA;AAAA,EAC/E,CAAA;AACA,EAAGJ,cAAA,CAAA,MAAA;AAAA,IACEA,cAAA,CAAA,QAAA;AAAA,MACEA,cAAA,CAAA,KAAA,CAASA,cAAA,CAAA,KAAA,CAAM,GAAG,MAAA,CAAO,MAAA,CAAO,gBAAgB,CAAC,CAAA,EAAG,EAAE,SAAA,EAAW,EAAA,EAAI,CAAA;AAAA,MACxE,CAAC,MAAA,KAAW;AACV,QAAA,IAAI,IAAA,GAAOE,kCAAgB,GAAG,CAAA;AAC9B,QAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,UAAA,MAAM,YAAA,GAAe,cAAA,CAAe,IAAA,CAAK,KAAA,EAAO,EAAE,IAAI,CAAA;AACtD,UAAA,MAAM,CAAA,GAAIL,sBAAA,CAAK,GAAA,EAAK,IAAA,EAAM,GAAG,WAAW,CAAA;AAIxC,UAAA,IAAI,YAAA,IAAgB,CAAA,CAAE,OAAA,KAAY,KAAA,EAAO,OAAO,KAAA;AAChD,UAAA,IAAA,GAAO,CAAA,CAAE,QAAA;AAAA,QACX;AACA,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,KACF;AAAA,IACA,gBAAgB,IAAI;AAAA,GACtB;AACF;AAOO,SAAS,mBAAA,CACd,GAAA,EACA,IAAA,EACA,gBAAA,EACA,IAAA,EACM;AAEN,EAAA,MAAM,KAAA,GAAQ,EAAE,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AAC3B,EAAA,MAAM,SAASQ,8BAAA,CAAa,KAAA,EAAO,EAAE,CAAA,EAAG,GAAG,CAAA;AAE3C,EAAA,IAAI,MAAA,KAAW,KAAA,EAAO,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAE7F,EAAGL,cAAA,CAAA,MAAA;AAAA,IACEA,cAAA,CAAA,QAAA;AAAA,MACEA,cAAA,CAAA,KAAA,CAASA,cAAA,CAAA,KAAA,CAAM,GAAG,MAAA,CAAO,MAAA,CAAO,gBAAgB,CAAC,CAAA,EAAG,EAAE,SAAA,EAAW,EAAA,EAAI,CAAA;AAAA,MACxE,CAAC,MAAA,KAAW;AACV,QAAA,IAAI,IAAA,GAAOE,kCAAgB,GAAG,CAAA;AAC9B,QAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,UAAA,MAAM,mBAAA,GAAsB,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AACvD,UAAAL,sBAAA,CAAK,GAAA,EAAK,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA;AAEvB,UAAA,IAAI,KAAK,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA,KAAM,qBAAqB,OAAO,KAAA;AAEjE,UAAA,IAAA,GAAOA,sBAAA,CAAK,GAAA,EAAK,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,CAAE,QAAA;AAAA,QAClC;AACA,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,KACF;AAAA,IACA,gBAAgB,IAAI;AAAA,GACtB;AACF;AAMO,SAAS,SAAA,CACd,GAAA,EACA,IAAA,EACA,gBAAA,EACA,IAAA,EACM;AACN,EAAA,oBAAA,CAAqB,GAAA,EAAK,IAAA,EAAM,gBAAA,EAAkB,IAAI,CAAA;AACtD,EAAA,gBAAA,CAAiB,GAAA,EAAK,IAAA,EAAM,IAAA,EAAM,gBAAA,IAAoB,uBAAuB,IAAI,CAAA;AACjF,EAAA,6BAAA,CAA8B,GAAA,EAAK,IAAA,EAAM,gBAAA,EAAkB,IAAI,CAAA;AAC/D,EAAA,gBAAA,CAAiB,GAAA,EAAK,IAAA,EAAM,gBAAA,EAAkB,IAAI,CAAA;AAClD,EAAA,uBAAA,CAAwB,GAAA,EAAK,IAAA,EAAM,gBAAA,EAAkB,IAAI,CAAA;AACzD,EAAA,mBAAA,CAAoB,GAAA,EAAK,IAAA,EAAM,gBAAA,EAAkB,IAAI,CAAA;AACvD;;;ACpNO,IAAM,UAAA,GAAa","file":"index.cjs","sourcesContent":["import * as fc from \"fast-check\";\nimport { step } from \"../fsm/lifecycle.js\";\nimport type { Implementations, MachineDef, Runtime, Snapshot } from \"../fsm/types.js\";\n\n/**\n * Pure-model representation of an FSM run, used by `fc.commands`.\n * `reached` tracks every state visited so generic properties can check\n * containment without re-running.\n */\nexport type FsmModel<Ctx, States extends string> = {\n value: States;\n context: Ctx;\n status: \"active\" | \"final\";\n reached: Set<States>;\n};\n\nexport type EventArbitraries<Evt extends { type: string }> = Readonly<\n Record<string, fc.Arbitrary<Evt>>\n>;\n\nexport type FsmCommand<Ctx, Evt extends { type: string }, States extends string> = fc.Command<\n FsmModel<Ctx, States>,\n Runtime<Ctx, Evt, States>\n>;\n\nexport function initialModel<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n): FsmModel<Ctx, States> {\n return {\n value: def.initial,\n context: def.context,\n status: def.states[def.initial]?.final ? \"final\" : \"active\",\n reached: new Set([def.initial]),\n };\n}\n\nclass SendCommand<Ctx, Evt extends { type: string }, States extends string>\n implements FsmCommand<Ctx, Evt, States>\n{\n constructor(\n private readonly event: Evt,\n private readonly def: MachineDef<Ctx, Evt, States>,\n private readonly impl: Implementations<Ctx, Evt>,\n ) {}\n\n check(_m: Readonly<FsmModel<Ctx, States>>): boolean {\n // Every event is always applicable; invariants are asserted in run().\n return true;\n }\n\n run(m: FsmModel<Ctx, States>, r: Runtime<Ctx, Evt, States>): void {\n const before: Snapshot<Ctx, States> = r.getSnapshot();\n r.send(this.event);\n const after = r.getSnapshot();\n\n const predicted = step(this.def, before, this.event, this.impl);\n\n /* v8 ignore start — invariant guard: fires only when the live runtime\n diverges from the pure step() prediction, i.e. an internal bug. */\n if (predicted.snapshot.value !== after.value) {\n throw new Error(\n `aifsmjs/pbt: determinism violation — predicted \"${String(predicted.snapshot.value)}\" but runtime returned \"${String(after.value)}\" after ${this.toString()}`,\n );\n }\n /* v8 ignore stop */\n\n m.value = after.value;\n m.context = after.context as Ctx;\n m.status = after.status;\n m.reached.add(after.value);\n }\n\n toString(): string {\n return `send(${JSON.stringify(this.event)})`;\n }\n}\n\n/**\n * Build an `fc.Arbitrary` of FSM command sequences. Each command pulls one\n * event from the user-supplied arbitrary map and, when run, asserts that the\n * pure `step()` prediction matches the runtime's observable outcome.\n *\n * Pair this arbitrary with `fc.property(...)` inside a `fc.assert(...)` call,\n * or use the helpers in `aifsmjs/pbt` properties to get the six generic\n * invariants for free.\n */\nexport function commandsFromMachine<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n): fc.Arbitrary<Iterable<FsmCommand<Ctx, Evt, States>>> {\n const arbs: fc.Arbitrary<FsmCommand<Ctx, Evt, States>>[] = [];\n for (const arb of Object.values(eventArbitraries)) {\n arbs.push(arb.map((event) => new SendCommand(event, def, impl)));\n }\n return fc.commands(arbs, { size: \"+1\" });\n}\n","import * as fc from \"fast-check\";\nimport { initialSnapshot } from \"../fsm/definition.js\";\nimport { step } from \"../fsm/lifecycle.js\";\nimport { normalizeTransitions } from \"../fsm/resolver.js\";\nimport { createRuntime } from \"../fsm/runtime.js\";\nimport type { Guard, Implementations, MachineDef } from \"../fsm/types.js\";\nimport { mergeContext } from \"../fsm/updater.js\";\nimport { replay } from \"../replay/index.js\";\nimport {\n type EventArbitraries,\n type FsmModel,\n commandsFromMachine,\n initialModel,\n} from \"./commands.js\";\n\nexport type AssertOpts = Readonly<{\n numRuns?: number;\n seed?: number;\n verbose?: boolean;\n}>;\n\nfunction buildAssertOpts(opts: AssertOpts | undefined): fc.Parameters<unknown> {\n const out: fc.Parameters<unknown> = {};\n if (opts?.numRuns !== undefined) out.numRuns = opts.numRuns;\n if (opts?.seed !== undefined) out.seed = opts.seed;\n if (opts?.verbose) out.verbose = true;\n return out;\n}\n\n/**\n * #1 snapshotAlwaysFrozen — after any event sequence the live snapshot remains\n * frozen at the top level.\n */\nexport function snapshotAlwaysFrozen<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n fc.assert(\n fc.property(commandsFromMachine(def, impl, eventArbitraries), (cmds) => {\n const real = createRuntime(def, impl);\n const model: FsmModel<Ctx, States> = initialModel(def);\n fc.modelRun(() => ({ model, real }), cmds);\n return Object.isFrozen(real.getSnapshot());\n }),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #2 unknownEventNoOp — sending an event whose `type` is not declared in any\n * state's `on` map never changes the snapshot.\n */\nexport function unknownEventNoOp<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n unknownType: string,\n opts?: AssertOpts,\n): void {\n fc.assert(\n fc.property(fc.constant(unknownType), (t) => {\n const initial = initialSnapshot(def);\n const result = step(def, initial, { type: t } as unknown as Evt, impl);\n return result.changed === false && result.snapshot === initial && result.effects.length === 0;\n }),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #3 reachableStatesSubsetDeclared — every state visited during a run belongs\n * to `def.states`.\n */\nexport function reachableStatesSubsetDeclared<\n Ctx,\n Evt extends { type: string },\n States extends string,\n>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n const declared = new Set<string>(Object.keys(def.states));\n fc.assert(\n fc.property(commandsFromMachine(def, impl, eventArbitraries), (cmds) => {\n const real = createRuntime(def, impl);\n const model: FsmModel<Ctx, States> = initialModel(def);\n fc.modelRun(() => ({ model, real }), cmds);\n for (const s of model.reached as Set<string>) {\n /* v8 ignore next — property failure branch; an unreachable state would indicate a bug. */\n if (!declared.has(s)) return false;\n }\n return declared.has(real.getSnapshot().value);\n }),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #4 replayEqualsFold — `replay(initial, log)` produces the same final state\n * as a live runtime fed the same events. Effects dispatched by the runtime are\n * ignored; the comparison is on `{ value, context }`.\n */\nexport function replayEqualsFold<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n const eventArb = fc.oneof(...Object.values(eventArbitraries));\n fc.assert(\n fc.property(fc.array(eventArb, { maxLength: 32 }), (events) => {\n const real = createRuntime(def, impl, { dispatchEffects: false });\n for (const e of events) real.send(e);\n const live = real.getSnapshot();\n const replayed = replay(initialSnapshot(def), events, def, impl).snapshot;\n return (\n live.value === replayed.value &&\n JSON.stringify(live.context) === JSON.stringify(replayed.context)\n );\n }),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #5 guardsFalseNoTransition — when every candidate transition for the current\n * (state, event) pair carries a guard and every guard returns `false`, the\n * snapshot is unchanged (`changed === false`).\n *\n * Implementation: synthesise an impl that forces every guard to `false`, then\n * for each step whose candidate list is fully guarded, assert the step did not\n * change state. Steps with an unguarded fallback candidate (which fires even\n * when all guards are false) are skipped — the README claim is specifically\n * about the all-guards-false case.\n */\nexport function guardsFalseNoTransition<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n const blockedGuards = new Proxy(\n {},\n {\n get: () => () => false,\n },\n ) as Readonly<Record<string, Guard<Ctx, Evt>>>;\n const blockedImpl: Implementations<Ctx, Evt> = {\n ...impl,\n guards: blockedGuards,\n };\n // True when every candidate transition for (value, eventType) carries a\n // guard — i.e. blocking all guards leaves no unconditional fallback, so a\n // correct step() must report changed === false.\n const isFullyGuarded = (value: States, eventType: string): boolean => {\n const candidates = normalizeTransitions(def.states[value]?.on?.[eventType]);\n return candidates.length > 0 && candidates.every((t) => t.guard !== undefined);\n };\n fc.assert(\n fc.property(\n fc.array(fc.oneof(...Object.values(eventArbitraries)), { maxLength: 16 }),\n (events) => {\n let snap = initialSnapshot(def);\n for (const e of events) {\n const fullyGuarded = isFullyGuarded(snap.value, e.type);\n const r = step(def, snap, e, blockedImpl);\n // The named invariant: all guards false + no unconditional fallback\n // ⇒ no transition. Without this assertion the property was vacuous\n // (it only failed if step() threw).\n if (fullyGuarded && r.changed !== false) return false;\n snap = r.snapshot;\n }\n return true;\n },\n ),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #6 assignDoesNotMutate — running an `assign`-style action never mutates the\n * previous context object. Verified by deep-equality check on a snapshot taken\n * before each event.\n */\nexport function assignDoesNotMutate<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n // Quick sanity guard: mergeContext is the only context mutator used by step.\n const dummy = { a: 1, b: 2 };\n const merged = mergeContext(dummy, { b: 3 });\n /* v8 ignore next — invariant guard; mergeContext returning the same ref would mean unit tests have already broken. */\n if (merged === dummy) throw new Error(\"aifsmjs/pbt: mergeContext returned the same reference\");\n\n fc.assert(\n fc.property(\n fc.array(fc.oneof(...Object.values(eventArbitraries)), { maxLength: 16 }),\n (events) => {\n let snap = initialSnapshot(def);\n for (const e of events) {\n const beforeCtxSerialised = JSON.stringify(snap.context);\n step(def, snap, e, impl);\n /* v8 ignore next — property failure branch; step() mutating snap.context would indicate a bug. */\n if (JSON.stringify(snap.context) !== beforeCtxSerialised) return false;\n // Continue with the actual result for subsequent events\n snap = step(def, snap, e, impl).snapshot;\n }\n return true;\n },\n ),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * Assert every generic property in one call. Use this when you don't need\n * fine-grained control over per-property options.\n */\nexport function assertAll<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts & { unknownEventType?: string },\n): void {\n snapshotAlwaysFrozen(def, impl, eventArbitraries, opts);\n unknownEventNoOp(def, impl, opts?.unknownEventType ?? \"__AIFSMJS_UNKNOWN__\", opts);\n reachableStatesSubsetDeclared(def, impl, eventArbitraries, opts);\n replayEqualsFold(def, impl, eventArbitraries, opts);\n guardsFalseNoTransition(def, impl, eventArbitraries, opts);\n assignDoesNotMutate(def, impl, eventArbitraries, opts);\n}\n","export {\n commandsFromMachine,\n initialModel,\n type EventArbitraries,\n type FsmCommand,\n type FsmModel,\n} from \"./commands.js\";\n\nexport {\n assertAll,\n assignDoesNotMutate,\n guardsFalseNoTransition,\n reachableStatesSubsetDeclared,\n replayEqualsFold,\n snapshotAlwaysFrozen,\n unknownEventNoOp,\n type AssertOpts,\n} from \"./properties.js\";\n\n// Convenience namespace mirroring the README:\n// import { properties } from \"aifsmjs/pbt\"\n// properties.snapshotAlwaysFrozen(...)\nimport * as propertiesModule from \"./properties.js\";\nexport const properties = propertiesModule;\n"]}
1
+ {"version":3,"sources":["../../src/pbt/commands.ts","../../src/pbt/properties.ts","../../src/pbt/index.ts"],"names":["step","fc","__export","isDeepStrictEqual","fc2","createRuntime","initialSnapshot","replay","normalizeTransitions","mergeContext"],"mappings":"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","file":"index.cjs","sourcesContent":["import * as fc from \"fast-check\";\nimport { step } from \"../fsm/lifecycle.js\";\nimport type { Implementations, MachineDef, Runtime, Snapshot } from \"../fsm/types.js\";\n\n/**\n * Pure-model representation of an FSM run, used by `fc.commands`.\n * `reached` tracks every state visited so generic properties can check\n * containment without re-running.\n */\nexport type FsmModel<Ctx, States extends string> = {\n value: States;\n context: Ctx;\n status: \"active\" | \"final\";\n reached: Set<States>;\n};\n\nexport type EventArbitraries<Evt extends { type: string }> = Readonly<\n Record<string, fc.Arbitrary<Evt>>\n>;\n\nexport type FsmCommand<Ctx, Evt extends { type: string }, States extends string> = fc.Command<\n FsmModel<Ctx, States>,\n Runtime<Ctx, Evt, States>\n>;\n\nexport function initialModel<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n): FsmModel<Ctx, States> {\n return {\n value: def.initial,\n context: def.context,\n status: def.states[def.initial]?.final ? \"final\" : \"active\",\n reached: new Set([def.initial]),\n };\n}\n\nclass SendCommand<Ctx, Evt extends { type: string }, States extends string>\n implements FsmCommand<Ctx, Evt, States>\n{\n constructor(\n private readonly event: Evt,\n private readonly def: MachineDef<Ctx, Evt, States>,\n private readonly impl: Implementations<Ctx, Evt>,\n ) {}\n\n check(_m: Readonly<FsmModel<Ctx, States>>): boolean {\n // Every event is always applicable; invariants are asserted in run().\n return true;\n }\n\n run(m: FsmModel<Ctx, States>, r: Runtime<Ctx, Evt, States>): void {\n const before: Snapshot<Ctx, States> = r.getSnapshot();\n r.send(this.event);\n const after = r.getSnapshot();\n\n const predicted = step(this.def, before, this.event, this.impl);\n\n /* v8 ignore start — invariant guard: fires only when the live runtime\n diverges from the pure step() prediction, i.e. an internal bug. */\n if (predicted.snapshot.value !== after.value) {\n throw new Error(\n `aifsmjs/pbt: determinism violation — predicted \"${String(predicted.snapshot.value)}\" but runtime returned \"${String(after.value)}\" after ${this.toString()}`,\n );\n }\n /* v8 ignore stop */\n\n m.value = after.value;\n m.context = after.context as Ctx;\n m.status = after.status;\n m.reached.add(after.value);\n }\n\n toString(): string {\n return `send(${JSON.stringify(this.event)})`;\n }\n}\n\n/**\n * Build an `fc.Arbitrary` of FSM command sequences. Each command pulls one\n * event from the user-supplied arbitrary map and, when run, asserts that the\n * pure `step()` prediction matches the runtime's observable outcome.\n *\n * Pair this arbitrary with `fc.property(...)` inside a `fc.assert(...)` call,\n * or use the helpers in `aifsmjs/pbt` properties to get the six generic\n * invariants for free.\n */\nexport function commandsFromMachine<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n): fc.Arbitrary<Iterable<FsmCommand<Ctx, Evt, States>>> {\n const arbs: fc.Arbitrary<FsmCommand<Ctx, Evt, States>>[] = [];\n for (const arb of Object.values(eventArbitraries)) {\n arbs.push(arb.map((event) => new SendCommand(event, def, impl)));\n }\n return fc.commands(arbs, { size: \"+1\" });\n}\n","import { isDeepStrictEqual } from \"node:util\";\nimport * as fc from \"fast-check\";\nimport { initialSnapshot } from \"../fsm/definition.js\";\nimport { step } from \"../fsm/lifecycle.js\";\nimport { normalizeTransitions } from \"../fsm/resolver.js\";\nimport { createRuntime } from \"../fsm/runtime.js\";\nimport type { Guard, Implementations, MachineDef } from \"../fsm/types.js\";\nimport { mergeContext } from \"../fsm/updater.js\";\nimport { replay } from \"../replay/index.js\";\nimport {\n type EventArbitraries,\n type FsmModel,\n commandsFromMachine,\n initialModel,\n} from \"./commands.js\";\n\nexport type AssertOpts = Readonly<{\n numRuns?: number;\n seed?: number;\n verbose?: boolean;\n}>;\n\nfunction buildAssertOpts(opts: AssertOpts | undefined): fc.Parameters<unknown> {\n const out: fc.Parameters<unknown> = {};\n if (opts?.numRuns !== undefined) out.numRuns = opts.numRuns;\n if (opts?.seed !== undefined) out.seed = opts.seed;\n if (opts?.verbose) out.verbose = true;\n return out;\n}\n\n/**\n * Structural deep-equality for two context values (C3). Backed by `node:util`\n * `isDeepStrictEqual`, replacing the previous `JSON.stringify(a) === JSON.stringify(b)`\n * oracle which was unsound:\n *\n * - key-order-sensitive → false-FAIL on `{a:1,b:2}` vs `{b:2,a:1}`;\n * - drops undefined keys → false-PASS on `{v:undefined,w:1}` vs `{w:1}`;\n * - lossy for `Map`/`Set`/`Date` (all serialise to `{}` or an ISO string);\n * - throws on `BigInt`.\n *\n * `isDeepStrictEqual` distinguishes present-but-undefined from absent keys,\n * compares `Map`/`Set`/`Date` by contents, and tolerates `BigInt` — exactly\n * the verdicts a context-equality oracle for PBT requires. No new dependency\n * (Node built-in; the package already targets Node >=18).\n */\nexport function contextEquals(a: unknown, b: unknown): boolean {\n return isDeepStrictEqual(a, b);\n}\n\n/**\n * #1 snapshotAlwaysFrozen — after any event sequence the live snapshot remains\n * frozen at the top level.\n */\nexport function snapshotAlwaysFrozen<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n fc.assert(\n fc.property(commandsFromMachine(def, impl, eventArbitraries), (cmds) => {\n const real = createRuntime(def, impl);\n const model: FsmModel<Ctx, States> = initialModel(def);\n fc.modelRun(() => ({ model, real }), cmds);\n return Object.isFrozen(real.getSnapshot());\n }),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #2 unknownEventNoOp — sending an event whose `type` is not declared in any\n * state's `on` map never changes the snapshot.\n */\nexport function unknownEventNoOp<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n unknownType: string,\n opts?: AssertOpts,\n): void {\n fc.assert(\n fc.property(fc.constant(unknownType), (t) => {\n const initial = initialSnapshot(def);\n const result = step(def, initial, { type: t } as unknown as Evt, impl);\n return result.changed === false && result.snapshot === initial && result.effects.length === 0;\n }),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #3 reachableStatesSubsetDeclared — every state visited during a run belongs\n * to `def.states`.\n */\nexport function reachableStatesSubsetDeclared<\n Ctx,\n Evt extends { type: string },\n States extends string,\n>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n const declared = new Set<string>(Object.keys(def.states));\n fc.assert(\n fc.property(commandsFromMachine(def, impl, eventArbitraries), (cmds) => {\n const real = createRuntime(def, impl);\n const model: FsmModel<Ctx, States> = initialModel(def);\n fc.modelRun(() => ({ model, real }), cmds);\n for (const s of model.reached as Set<string>) {\n /* v8 ignore next — property failure branch; an unreachable state would indicate a bug. */\n if (!declared.has(s)) return false;\n }\n return declared.has(real.getSnapshot().value);\n }),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #4 replayEqualsFold — `replay(initial, log)` produces the same final state\n * as a live runtime fed the same events. Effects dispatched by the runtime are\n * ignored; the comparison is on `{ value, context }`.\n */\nexport function replayEqualsFold<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n const eventArb = fc.oneof(...Object.values(eventArbitraries));\n fc.assert(\n fc.property(fc.array(eventArb, { maxLength: 32 }), (events) => {\n const real = createRuntime(def, impl, { dispatchEffects: false });\n for (const e of events) real.send(e);\n const live = real.getSnapshot();\n const replayed = replay(initialSnapshot(def), events, def, impl).snapshot;\n return live.value === replayed.value && contextEquals(live.context, replayed.context);\n }),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #5 guardsFalseNoTransition — when every candidate transition for the current\n * (state, event) pair carries a guard and every guard returns `false`, the\n * snapshot is unchanged (`changed === false`).\n *\n * Implementation: synthesise an impl that forces every guard to `false`, then\n * for each step whose candidate list is fully guarded, assert the step did not\n * change state. Steps with an unguarded fallback candidate (which fires even\n * when all guards are false) are skipped — the README claim is specifically\n * about the all-guards-false case.\n */\nexport function guardsFalseNoTransition<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n const blockedGuards = new Proxy(\n {},\n {\n get: () => () => false,\n },\n ) as Readonly<Record<string, Guard<Ctx, Evt>>>;\n const blockedImpl: Implementations<Ctx, Evt> = {\n ...impl,\n guards: blockedGuards,\n };\n // True when every candidate transition for (value, eventType) carries a\n // guard — i.e. blocking all guards leaves no unconditional fallback, so a\n // correct step() must report changed === false.\n const isFullyGuarded = (value: States, eventType: string): boolean => {\n const candidates = normalizeTransitions(def.states[value]?.on?.[eventType]);\n return candidates.length > 0 && candidates.every((t) => t.guard !== undefined);\n };\n fc.assert(\n fc.property(\n fc.array(fc.oneof(...Object.values(eventArbitraries)), { maxLength: 16 }),\n (events) => {\n let snap = initialSnapshot(def);\n for (const e of events) {\n const fullyGuarded = isFullyGuarded(snap.value, e.type);\n const r = step(def, snap, e, blockedImpl);\n // The named invariant: all guards false + no unconditional fallback\n // ⇒ no transition. Without this assertion the property was vacuous\n // (it only failed if step() threw).\n if (fullyGuarded && r.changed !== false) return false;\n snap = r.snapshot;\n }\n return true;\n },\n ),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * #6 assignDoesNotMutate — running an `assign`-style action never mutates the\n * previous context object. Verified by deep-equality check on a snapshot taken\n * before each event.\n */\nexport function assignDoesNotMutate<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts,\n): void {\n // Quick sanity guard: mergeContext is the only context mutator used by step.\n const dummy = { a: 1, b: 2 };\n const merged = mergeContext(dummy, { b: 3 });\n /* v8 ignore next — invariant guard; mergeContext returning the same ref would mean unit tests have already broken. */\n if (merged === dummy) throw new Error(\"aifsmjs/pbt: mergeContext returned the same reference\");\n\n fc.assert(\n fc.property(\n fc.array(fc.oneof(...Object.values(eventArbitraries)), { maxLength: 16 }),\n (events) => {\n let snap = initialSnapshot(def);\n for (const e of events) {\n // Structural snapshot of the pre-step context (C3). structuredClone +\n // contextEquals replaces the old JSON.stringify round-trip, which was\n // lossy for Map/Set/Date and threw on BigInt. structuredClone produces\n // an independent copy so a subsequent in-place mutation by step() is\n // detectable by deep comparison.\n const beforeCtx = structuredClone(snap.context);\n step(def, snap, e, impl);\n /* v8 ignore next — property failure branch; step() mutating snap.context would indicate a bug. */\n if (!contextEquals(snap.context, beforeCtx)) return false;\n // Continue with the actual result for subsequent events\n snap = step(def, snap, e, impl).snapshot;\n }\n return true;\n },\n ),\n buildAssertOpts(opts),\n );\n}\n\n/**\n * Assert every generic property in one call. Use this when you don't need\n * fine-grained control over per-property options.\n */\nexport function assertAll<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n eventArbitraries: EventArbitraries<Evt>,\n opts?: AssertOpts & { unknownEventType?: string },\n): void {\n snapshotAlwaysFrozen(def, impl, eventArbitraries, opts);\n unknownEventNoOp(def, impl, opts?.unknownEventType ?? \"__AIFSMJS_UNKNOWN__\", opts);\n reachableStatesSubsetDeclared(def, impl, eventArbitraries, opts);\n replayEqualsFold(def, impl, eventArbitraries, opts);\n guardsFalseNoTransition(def, impl, eventArbitraries, opts);\n assignDoesNotMutate(def, impl, eventArbitraries, opts);\n}\n","export {\n commandsFromMachine,\n initialModel,\n type EventArbitraries,\n type FsmCommand,\n type FsmModel,\n} from \"./commands.js\";\n\nexport {\n assertAll,\n assignDoesNotMutate,\n guardsFalseNoTransition,\n reachableStatesSubsetDeclared,\n replayEqualsFold,\n snapshotAlwaysFrozen,\n unknownEventNoOp,\n type AssertOpts,\n} from \"./properties.js\";\n\n// Convenience namespace mirroring the README:\n// import { properties } from \"aifsmjs/pbt\"\n// properties.snapshotAlwaysFrozen(...)\nimport * as propertiesModule from \"./properties.js\";\nexport const properties = propertiesModule;\n"]}
@@ -39,6 +39,22 @@ type AssertOpts = Readonly<{
39
39
  seed?: number;
40
40
  verbose?: boolean;
41
41
  }>;
42
+ /**
43
+ * Structural deep-equality for two context values (C3). Backed by `node:util`
44
+ * `isDeepStrictEqual`, replacing the previous `JSON.stringify(a) === JSON.stringify(b)`
45
+ * oracle which was unsound:
46
+ *
47
+ * - key-order-sensitive → false-FAIL on `{a:1,b:2}` vs `{b:2,a:1}`;
48
+ * - drops undefined keys → false-PASS on `{v:undefined,w:1}` vs `{w:1}`;
49
+ * - lossy for `Map`/`Set`/`Date` (all serialise to `{}` or an ISO string);
50
+ * - throws on `BigInt`.
51
+ *
52
+ * `isDeepStrictEqual` distinguishes present-but-undefined from absent keys,
53
+ * compares `Map`/`Set`/`Date` by contents, and tolerates `BigInt` — exactly
54
+ * the verdicts a context-equality oracle for PBT requires. No new dependency
55
+ * (Node built-in; the package already targets Node >=18).
56
+ */
57
+ declare function contextEquals(a: unknown, b: unknown): boolean;
42
58
  /**
43
59
  * #1 snapshotAlwaysFrozen — after any event sequence the live snapshot remains
44
60
  * frozen at the top level.
@@ -103,13 +119,14 @@ declare function assertAll<Ctx, Evt extends {
103
119
  type propertiesModule_AssertOpts = AssertOpts;
104
120
  declare const propertiesModule_assertAll: typeof assertAll;
105
121
  declare const propertiesModule_assignDoesNotMutate: typeof assignDoesNotMutate;
122
+ declare const propertiesModule_contextEquals: typeof contextEquals;
106
123
  declare const propertiesModule_guardsFalseNoTransition: typeof guardsFalseNoTransition;
107
124
  declare const propertiesModule_reachableStatesSubsetDeclared: typeof reachableStatesSubsetDeclared;
108
125
  declare const propertiesModule_replayEqualsFold: typeof replayEqualsFold;
109
126
  declare const propertiesModule_snapshotAlwaysFrozen: typeof snapshotAlwaysFrozen;
110
127
  declare const propertiesModule_unknownEventNoOp: typeof unknownEventNoOp;
111
128
  declare namespace propertiesModule {
112
- export { type propertiesModule_AssertOpts as AssertOpts, propertiesModule_assertAll as assertAll, propertiesModule_assignDoesNotMutate as assignDoesNotMutate, propertiesModule_guardsFalseNoTransition as guardsFalseNoTransition, propertiesModule_reachableStatesSubsetDeclared as reachableStatesSubsetDeclared, propertiesModule_replayEqualsFold as replayEqualsFold, propertiesModule_snapshotAlwaysFrozen as snapshotAlwaysFrozen, propertiesModule_unknownEventNoOp as unknownEventNoOp };
129
+ export { type propertiesModule_AssertOpts as AssertOpts, propertiesModule_assertAll as assertAll, propertiesModule_assignDoesNotMutate as assignDoesNotMutate, propertiesModule_contextEquals as contextEquals, propertiesModule_guardsFalseNoTransition as guardsFalseNoTransition, propertiesModule_reachableStatesSubsetDeclared as reachableStatesSubsetDeclared, propertiesModule_replayEqualsFold as replayEqualsFold, propertiesModule_snapshotAlwaysFrozen as snapshotAlwaysFrozen, propertiesModule_unknownEventNoOp as unknownEventNoOp };
113
130
  }
114
131
 
115
132
  declare const properties: typeof propertiesModule;