@rotorsoft/act 1.3.0 → 1.4.0
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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/internal/event-sourcing.d.ts +11 -21
- package/dist/@types/internal/event-sourcing.d.ts.map +1 -1
- package/dist/@types/types/action.d.ts +21 -5
- package/dist/@types/types/action.d.ts.map +1 -1
- package/dist/index.cjs +58 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +58 -80
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/signals.ts","../src/act.ts","../src/internal/event-versions.ts","../src/internal/audit.ts","../src/internal/build-classify.ts","../src/internal/close-cycle.ts","../src/internal/correlate-cycle.ts","../src/internal/correlator.ts","../src/internal/drain-cycle.ts","../src/internal/drain-ratio.ts","../src/internal/drain.ts","../src/internal/event-sourcing.ts","../src/internal/tracing.ts","../src/internal/merge.ts","../src/internal/backoff.ts","../src/internal/reactions.ts","../src/internal/settle.ts","../src/builders/act-builder.ts","../src/builders/projection-builder.ts","../src/builders/slice-builder.ts","../src/builders/state-builder.ts","../src/csv.ts"],"sourcesContent":["import { disposeAndExit, log } from \"./ports.js\";\n\n// Resolve the logger lazily inside each handler — calling log() here at\n// module load would register the default ConsoleLogger before user code\n// can inject (port singletons are first-call-wins).\nprocess.once(\"SIGINT\", async (arg?: any) => {\n log().info(arg, \"SIGINT\");\n await disposeAndExit(\"EXIT\");\n});\nprocess.once(\"SIGTERM\", async (arg?: any) => {\n log().info(arg, \"SIGTERM\");\n await disposeAndExit(\"EXIT\");\n});\nprocess.once(\"uncaughtException\", async (arg?: any) => {\n log().error(arg, \"Uncaught Exception\");\n await disposeAndExit(\"ERROR\");\n});\nprocess.once(\"unhandledRejection\", async (arg?: any) => {\n log().error(arg, \"Unhandled Rejection\");\n await disposeAndExit(\"ERROR\");\n});\n","import EventEmitter from \"node:events\";\nimport {\n ALL_LANES,\n type AuditDeps,\n audit,\n buildDrain,\n buildEs,\n buildHandle,\n buildHandleBatch,\n CorrelateCycle,\n classifyRegistry,\n closeCorrelation,\n DrainController,\n type DrainOps,\n defaultCorrelator,\n type EsOps,\n type EventLaneSet,\n type Handle,\n type HandleBatch,\n runCloseCycle,\n SettleLoop,\n scan,\n} from \"./internal/index.js\";\nimport { dispose, log, type Scoped, scoped, store } from \"./ports.js\";\nimport type {\n Actor,\n AsOf,\n AuditCategory,\n AuditFinding,\n AuditOptions,\n BatchHandler,\n BlockedLease,\n CloseResult,\n CloseTarget,\n Committed,\n Correlator,\n Drain,\n DrainOptions,\n EventSink,\n EventSource,\n IAct,\n LaneConfig,\n Lease,\n Logger,\n Query,\n Registry,\n ScanOptions,\n ScanResult,\n Schema,\n SchemaRegister,\n Schemas,\n SettleOptions,\n Snapshot,\n State,\n Store,\n StoreNotification,\n StreamFilter,\n StreamPosition,\n Target,\n} from \"./types/index.js\";\n\n/**\n * @category Orchestrator\n * @see Store\n *\n * Main orchestrator for event-sourced state machines and workflows.\n *\n * It manages the lifecycle of actions, reactions, and event streams, providing APIs for loading state, executing actions, querying events, and draining reactions.\n *\n * ## Usage\n *\n * ```typescript\n * const app = new Act(registry, 100);\n * await app.do(\"increment\", { stream: \"counter1\", actor }, { by: 1 });\n * const snapshot = await app.load(Counter, \"counter1\");\n * await app.drain();\n * ```\n *\n * - Register event listeners with `.on(\"committed\", ...)` and `.on(\"acked\", ...)` to react to lifecycle events.\n * - Use `.query()` to analyze event streams for analytics or debugging.\n *\n * @template TSchemaReg SchemaRegister for state\n * @template TEvents Schemas for events\n * @template TActions Schemas for actions\n * @template TStateMap Map of state names to state schemas\n * @template TActor Actor type extending base Actor\n */\n/**\n * Default LRU cap for the subscribed-streams cache. Apps that mint many\n * dynamic targets (one per aggregate) should override via\n * {@link ActOptions.maxSubscribedStreams} based on expected concurrency.\n */\nexport const DEFAULT_MAX_SUBSCRIBED_STREAMS = 1000;\n\n/**\n * Default debounce window (ms) for `settle()` when neither the per-call\n * `SettleOptions.debounceMs` nor `ActOptions.settleDebounceMs` is set.\n * Coalesces commits in the same tick and small bursts; sub-perceptible\n * latency on the `\"settled\"` signal.\n */\nexport const DEFAULT_SETTLE_DEBOUNCE_MS = 10;\n\n/**\n * Lifecycle events emitted by {@link Act}, mapped to their payload type.\n * Drives the typing of `emit` / `on` / `off` — the event-name argument\n * narrows its payload at the call site.\n */\nexport type ActLifecycleEvents<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n> = {\n committed: Snapshot<TSchemaReg, TEvents>[];\n acked: Lease[];\n blocked: BlockedLease[];\n settled: Drain<TEvents>;\n closed: CloseResult;\n /**\n * A **different process** committed an event to the same backing store.\n *\n * Fires only when the configured store implements\n * {@link Store.notify} and there is at least one registered reaction.\n * The orchestrator uses the same signal internally to wake `settle()`\n * — listeners get the raw payload for SSE fan-out, dashboards, and\n * audit logs.\n *\n * Local commits do *not* fire `notified` (use `committed` for those):\n * stores self-filter their own writes so this channel has a clean\n * cross-process semantic.\n */\n notified: StoreNotification;\n};\n\n/**\n * Options for {@link Act} construction (passed via {@link ActBuilder.build}).\n *\n * @property maxSubscribedStreams - Cap for the LRU set tracking already-\n * subscribed reaction streams. Default: {@link DEFAULT_MAX_SUBSCRIBED_STREAMS}.\n * @property settleDebounceMs - Debounce window (ms) used by `settle()` when\n * the caller doesn't pass `SettleOptions.debounceMs`. Tune this once per\n * Act instance instead of threading the value through every call site.\n * Default: {@link DEFAULT_SETTLE_DEBOUNCE_MS}.\n */\nexport type ActOptions<TLanes extends string = string> = {\n readonly maxSubscribedStreams?: number;\n readonly settleDebounceMs?: number;\n /**\n * Per-Act ports (ACT-501). When set, this Act runs against the\n * provided store + cache instead of the singletons — threaded via\n * AsyncLocalStorage so internals are unchanged. Both are required\n * together (a shared cache across distinct stores would collide on\n * stream keys). Omit for the singleton path.\n */\n readonly scoped?: Scoped;\n /**\n * Correlation-id generator for originating actions (ACT-404). When\n * omitted, Act uses {@link defaultCorrelator}, which produces a\n * readable, time-monotonic-within-window, lowercase id of the form\n * `{state[:4]}-{action[:4]}-{ts}{rnd}` (18 chars).\n *\n * Reactions inherit `reactingTo.meta.correlation` so the chain stays\n * intact — the delegate is only consulted on originating commits and\n * for the close-the-books transaction.\n */\n readonly correlator?: Correlator;\n /** Restrict this process to a subset of declared lanes (ACT-1103). */\n readonly onlyLanes?: ReadonlyArray<TLanes>;\n};\n\nexport class Act<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n TStateMap extends Record<string, Schema> = Record<string, never>,\n TActor extends Actor = Actor,\n> implements IAct<TEvents, TActions, TActor>\n{\n private _emitter = new EventEmitter();\n /** Event names with at least one registered reaction (computed at build time) */\n private readonly _reactive_events: ReadonlySet<string>;\n /** One DrainController per active lane, keyed by lane name. */\n private readonly _drain_controllers: Map<\n string,\n DrainController<TEvents, TActions, TSchemaReg>\n >;\n /** Correlation state machine: lazy init, dynamic-resolver scan, periodic worker. */\n private readonly _correlate: CorrelateCycle<TSchemaReg, TEvents, TActions>;\n /** Debounced correlate→drain catch-up loop. */\n private readonly _settle: SettleLoop<TEvents>;\n /**\n * Disposer for the cross-process notify subscription, set up eagerly\n * during construction. Held as a promise because the subscription\n * itself may be async (the PG adapter checks out a dedicated client\n * and runs `LISTEN` before resolving). Resolves to `undefined` when\n * the store doesn't implement `notify` or there are no registered\n * reactions.\n *\n * **Contract:** the configured store must be injected via\n * {@link store}`(adapter)` *before* calling `act()...build()`. The\n * orchestrator wires notify against whatever store is current at\n * construction time — late injection after build is unsupported.\n */\n private readonly _notify_disposer: Promise<\n (() => void | Promise<void>) | undefined\n >;\n\n /**\n * Emit a lifecycle event. The payload type is inferred from the event name\n * via {@link ActLifecycleEvents}.\n */\n emit<E extends keyof ActLifecycleEvents<TSchemaReg, TEvents, TActions>>(\n event: E,\n args: ActLifecycleEvents<TSchemaReg, TEvents, TActions>[E]\n ): boolean {\n return this._emitter.emit(event, args);\n }\n\n /**\n * Register a listener for a lifecycle event. The listener receives the\n * event-specific payload.\n */\n on<E extends keyof ActLifecycleEvents<TSchemaReg, TEvents, TActions>>(\n event: E,\n listener: (\n args: ActLifecycleEvents<TSchemaReg, TEvents, TActions>[E]\n ) => void\n ): this {\n this._emitter.on(event, listener);\n return this;\n }\n\n /**\n * Remove a previously registered lifecycle listener.\n */\n off<E extends keyof ActLifecycleEvents<TSchemaReg, TEvents, TActions>>(\n event: E,\n listener: (\n args: ActLifecycleEvents<TSchemaReg, TEvents, TActions>[E]\n ) => void\n ): this {\n this._emitter.off(event, listener);\n return this;\n }\n\n /** Batch handlers for static-target projections (target → handler) */\n private readonly _batch_handlers: Map<string, BatchHandler<TEvents>>;\n /** Event-sourcing handlers, optionally wrapped with trace decorators */\n private readonly _es: EsOps;\n /** Correlate/drain pipeline ops, optionally wrapped with trace decorators */\n private readonly _cd: DrainOps<TEvents>;\n /**\n * Event-name → owning state, computed at build time. The duplicate-event\n * guard in merge.ts ensures one event name maps to at most one state, so\n * this lookup is unambiguous. Used by `close()` to pick the right reducer\n * set when seeding a `restart` snapshot in multi-state apps.\n */\n private readonly _event_to_state: ReadonlyMap<string, State<any, any, any>>;\n /**\n * Event-name → lane fan-in for selective arming (ACT-1103). Built by\n * `classifyRegistry` once per build. `\"all\"` means at least one of\n * the event's reactions is a dynamic resolver (lane opaque until\n * runtime); a `Set<string>` lists the static lanes only that event's\n * reactions target.\n */\n private readonly _event_to_lanes: ReadonlyMap<string, EventLaneSet>;\n /**\n * Audit dependency bag (#723). Built once at construction; held as\n * an immutable snapshot of the registry state the audit module\n * needs. Lives in `internal/audit.ts` — this orchestrator never\n * carries audit logic, only the deps + a one-liner that hands them\n * over.\n */\n private readonly _audit_deps: AuditDeps;\n /** Logger resolved at construction time (after user port configuration) */\n private readonly _logger: Logger = log();\n /** Wraps a public-method body so internal `store()`/`cache()` resolve to the\n * per-Act ports (ACT-501). No-op when the Act is unscoped — so the singleton\n * path keeps reading fresh `store()`/`cache()` per call, which matters for\n * tests that dispose and re-seed mid-suite. */\n private readonly _scoped: <T>(fn: () => Promise<T>) => Promise<T>;\n\n /**\n * Correlation-id generator for originating actions. Bound at\n * construction from `options.correlator ?? defaultCorrelator`. The\n * `do()` path passes this into the `_es.action` closure; close-cycle\n * uses it via {@link closeCorrelation}.\n */\n private readonly _correlator: Correlator;\n /** Pre-bound IAct methods reused across drain cycles. Only `do` varies per\n * payload (it captures the triggering event for reactingTo auto-inject). */\n private readonly _bound_do = this.do.bind(this);\n private readonly _bound_load = this.load.bind(this);\n private readonly _bound_query = this.query.bind(this);\n private readonly _bound_query_array = this.query_array.bind(this);\n /** Reaction dispatchers built once and handed to runDrainCycle each cycle. */\n private readonly _handle: Handle<TEvents>;\n private readonly _handle_batch: HandleBatch<TEvents>;\n /** Declared drain lanes (ACT-1103). */\n private readonly _lanes: ReadonlyArray<LaneConfig>;\n\n /** Drain lanes declared via `.withLane(...)`. Implicit default not included. */\n get lanes(): ReadonlyArray<LaneConfig> {\n return this._lanes;\n }\n\n /**\n * Create a new Act orchestrator. Prefer the {@link act} builder over\n * direct construction — `act()...build()` wires the registry, merges\n * partial states, and collects batch handlers from registered slices\n * and projections in one pass.\n *\n * @param registry Schemas for every event and action across registered states\n * @param _states Merged map of state name → state definition\n * @param batchHandlers Static-target projection batch handlers (target → handler)\n * @param options Tuning knobs — see {@link ActOptions}\n * @param lanes Declared drain lanes (ACT-1103). The builder collects\n * these from `.withLane(...)` calls. Slice 1 records them on the\n * instance; later slices fan out one `DrainController` per lane.\n */\n constructor(\n public readonly registry: Registry<TSchemaReg, TEvents, TActions>,\n private readonly _states: Map<string, State<any, any, any>> = new Map(),\n batchHandlers: Map<string, BatchHandler<any>> = new Map(),\n options: ActOptions = {},\n lanes: ReadonlyArray<LaneConfig> = []\n ) {\n this._batch_handlers = batchHandlers;\n this._lanes = lanes;\n if (options.onlyLanes && options.onlyLanes.length > 0) {\n const declared = new Set<string>([\n \"default\",\n ...lanes.map((l) => l.name),\n ]);\n const unknown = options.onlyLanes.filter((l) => !declared.has(l));\n if (unknown.length > 0)\n throw new Error(\n `ActOptions.onlyLanes references undeclared lane(s): ${unknown\n .map((l) => `\"${l}\"`)\n .join(\", \")}`\n );\n }\n this._scoped = options.scoped\n ? (fn) => scoped.run(options.scoped!, fn)\n : (fn) => fn();\n this._correlator = options.correlator ?? defaultCorrelator;\n this._es = buildEs(this._logger, this._correlator);\n this._cd = buildDrain<TEvents>(this._logger);\n this._handle = buildHandle<TEvents, TActions, TActor>({\n logger: this._logger,\n boundDo: this._bound_do,\n boundLoad: this._bound_load,\n boundQuery: this._bound_query,\n boundQueryArray: this._bound_query_array,\n });\n this._handle_batch = buildHandleBatch<TEvents>(this._logger);\n\n const {\n staticTargets,\n hasDynamicResolvers,\n reactiveEvents,\n eventToState,\n eventToLanes,\n } = classifyRegistry(this.registry, this._states);\n this._reactive_events = reactiveEvents;\n this._event_to_state = eventToState;\n this._event_to_lanes = eventToLanes;\n\n // Build one DrainController per active lane (ACT-1103). The implicit\n // \"default\" lane is always present unless onlyLanes excludes it. Each\n // controller filters its claim() by its lane name; the legacy\n // single-controller path is the active set === { \"default\" } case\n // with `lane: undefined` deps so claim() doesn't filter (preserves\n // pre-1103 SQL planner behavior for apps that never call withLane).\n const allLanes = [\"default\", ...lanes.map((l) => l.name)];\n const onlySet =\n options.onlyLanes && options.onlyLanes.length > 0\n ? new Set<string>(options.onlyLanes as readonly string[])\n : undefined;\n const activeLanes = onlySet\n ? allLanes.filter((n) => onlySet.has(n))\n : allLanes;\n const singleDefaultLane =\n activeLanes.length === 1 && activeLanes[0] === \"default\";\n this._drain_controllers = new Map();\n for (const name of activeLanes) {\n const cfg = lanes.find((l) => l.name === name);\n const controller = new DrainController({\n logger: this._logger,\n ops: this._cd,\n registry: this.registry,\n batchHandlers: this._batch_handlers,\n handle: this._handle,\n handleBatch: this._handle_batch,\n onAcked: (acked) => this.emit(\"acked\", acked),\n onBlocked: (blocked) => this.emit(\"blocked\", blocked),\n // Pass lane only when a true per-lane controller is active.\n // The all-lanes (single default) case keeps lane=undefined so\n // adapter SQL collapses to the pre-1103 shape.\n lane: singleDefaultLane ? undefined : name,\n defaults: cfg && {\n streamLimit: cfg.streamLimit,\n leaseMillis: cfg.leaseMillis,\n },\n });\n // Auto-start a per-lane worker when the operator declared a\n // cycleMs — the intent of `withLane({cycleMs: 100})` is \"drive\n // this lane every 100 ms,\" independent of the Act-level settle\n // loop. unref()'d so the timer doesn't keep the process alive.\n if (cfg?.cycleMs !== undefined) controller.start(cfg.cycleMs);\n this._drain_controllers.set(name, controller);\n }\n\n // Audit deps bag (#723). Snapshotted after registry classification +\n // drain-controller build so the audit module sees the finalized lane\n // set. Held as an immutable bag — the orchestrator never carries\n // audit logic itself, only this typed contract.\n this._audit_deps = {\n store,\n logger: this._logger,\n event_to_state: eventToState,\n states: this._states,\n known_events: new Set(eventToState.keys()),\n declared_lanes: new Set(this._drain_controllers.keys()),\n routed_events: new Set(eventToLanes.keys()),\n };\n\n this._correlate = new CorrelateCycle(\n this.registry,\n staticTargets,\n hasDynamicResolvers,\n this._cd,\n options.maxSubscribedStreams ?? DEFAULT_MAX_SUBSCRIBED_STREAMS,\n // Cold start: assume drain is needed (historical events may need processing)\n () => {\n if (this._reactive_events.size > 0) this._armAll();\n }\n );\n this._settle = new SettleLoop<TEvents>(\n {\n logger: this._logger,\n init: () => this._correlate.init(),\n checkpoint: () => this._correlate.checkpoint,\n correlate: (q) => this.correlate(q),\n drain: (o) => this.drain(o),\n onSettled: (drain) => this.emit(\"settled\", drain),\n },\n options.settleDebounceMs ?? DEFAULT_SETTLE_DEBOUNCE_MS\n );\n\n // Auto-wire cross-process notify when the store supports it. Bound at\n // construction time — late `store(adapter)` injection after build won't\n // take effect. Scoped Acts bind against their own store.\n this._notify_disposer = this._wireNotify(options.scoped?.store ?? store());\n\n dispose(() => this.shutdown());\n }\n\n /** True after the first `shutdown()` call. Guards idempotency. */\n private _shutdown_promise: Promise<void> | undefined;\n\n /**\n * Per-instance teardown: remove lifecycle listeners, stop the\n * correlation worker, cancel any pending settle cycle, and tear\n * down the cross-process notify subscription.\n *\n * Idempotent — repeated calls return the same promise. Registered\n * automatically with the global `dispose()` registry at construction,\n * so process-wide `dispose()()` covers it; test helpers (or operators\n * that mint short-lived Acts) call it explicitly for prompt cleanup.\n */\n shutdown(): Promise<void> {\n if (!this._shutdown_promise) {\n this._shutdown_promise = (async () => {\n this._emitter.removeAllListeners();\n this.stop_correlations();\n this.stop_settling();\n for (const c of this._drain_controllers.values()) c.stop();\n // `_wireNotify` swallows subscription errors and resolves to\n // `undefined`, so this promise never rejects.\n const disposer = await this._notify_disposer;\n if (disposer) await disposer();\n })();\n }\n return this._shutdown_promise;\n }\n\n /**\n * Subscribe to {@link Store.notify} when both the store and the\n * registry support it. Returns the disposer (or `undefined` when no\n * subscription was made). Errors during subscription are logged but\n * never thrown — `notify` is a hint, not a contract.\n */\n private async _wireNotify(\n s: Store\n ): Promise<(() => void | Promise<void>) | undefined> {\n if (this._reactive_events.size === 0) return undefined;\n if (!s.notify) return undefined;\n try {\n return await s.notify((notification) => {\n // Generic concerns (lifecycle emit, drain wakeup, listener\n // error containment) live here so adapters only have to\n // handle their own wire format. Errors in user-registered\n // `notified` listeners or in our own bookkeeping are logged\n // and swallowed — the store's listener stays alive.\n try {\n this.emit(\"notified\", notification);\n // Wake once per commit when at least one event has a local\n // reaction. Avoids spurious wake-ups for remote commits\n // belonging to bounded contexts this process doesn't react to.\n // ACT-1103: selective arming via the shared helper — only the\n // lanes whose reactions match the notified events.\n const armed = this._armForEventNames(\n notification.events.map((e) => e.name)\n );\n if (armed) this._settle.schedule({ debounceMs: 0 });\n } catch (err) {\n this._logger.error(err, \"notified handler threw\");\n }\n });\n } catch (err) {\n this._logger.error(err, \"Store.notify subscription failed\");\n return undefined;\n }\n }\n\n /**\n * Executes an action on a state instance, committing resulting events.\n *\n * This is the primary method for modifying state. It:\n * 1. Validates the action payload against the schema\n * 2. Loads the current state snapshot\n * 3. Checks invariants (business rules)\n * 4. Executes the action handler to generate events\n * 5. Applies events to create new state\n * 6. Commits events to the store with optimistic concurrency control\n *\n * @template TKey - Action name from registered actions\n * @param action - The name of the action to execute\n * @param target - Target specification with stream ID and actor context\n * @param payload - Action payload matching the action's schema\n * @param reactingTo - Optional event that triggered this action (for correlation)\n * @param skipValidation - Skip schema validation (use carefully, for performance)\n * @returns Array of snapshots for all affected states (usually one)\n *\n * @throws {ValidationError} If payload doesn't match action schema\n * @throws {InvariantError} If business rules are violated\n * @throws {ConcurrencyError} If another process modified the stream\n *\n * @example Basic action execution\n * ```typescript\n * const snapshots = await app.do(\n * \"increment\",\n * {\n * stream: \"counter-1\",\n * actor: { id: \"user1\", name: \"Alice\" }\n * },\n * { by: 5 }\n * );\n *\n * console.log(snapshots[0].state.count); // Current count after increment\n * ```\n *\n * @example With error handling\n * ```typescript\n * try {\n * await app.do(\n * \"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Business rule violated:\", error.description);\n * } else if (error instanceof ConcurrencyError) {\n * console.error(\"Concurrent modification detected, retry...\");\n * } else if (error instanceof ValidationError) {\n * console.error(\"Invalid payload:\", error.details);\n * }\n * }\n * ```\n *\n * @example Reaction triggering another action (reactingTo auto-injected)\n * ```typescript\n * const app = act()\n * .withState(Order)\n * .withState(Inventory)\n * .on(\"OrderPlaced\")\n * .do(async function reduceInventory(event, _stream, app) {\n * // Inside reaction handlers, reactingTo is auto-injected when omitted.\n * // The triggering event is used by default, maintaining the correlation chain.\n * await app.do(\n * \"reduceStock\",\n * { stream: \"inventory-1\", actor: { id: \"sys\", name: \"system\" } },\n * { amount: event.data.items.length }\n * );\n * // To use a different correlation, pass reactingTo explicitly:\n * // await app.do(\"reduceStock\", target, payload, customEvent);\n * })\n * .to(\"inventory-1\")\n * .build();\n * ```\n *\n * @see {@link Target} for target structure\n * @see {@link Snapshot} for return value structure\n * @see {@link ValidationError}, {@link InvariantError}, {@link ConcurrencyError}\n */\n async do<TKey extends keyof TActions>(\n action: TKey,\n target: Target<TActor>,\n payload: Readonly<TActions[TKey]>,\n reactingTo?: Committed<TEvents, string & keyof TEvents>,\n skipValidation = false\n ) {\n return this._scoped(async () => {\n const snapshots = await this._es.action(\n this.registry.actions[action],\n action,\n target,\n payload,\n reactingTo,\n skipValidation\n );\n // Arm the drain when any committed event has reactions (ACT-1103:\n // arm only the lanes whose reactions match — events whose reactions\n // are all statically lane-resolved arm a subset; events with at\n // least one dynamic resolver fall back to _armAll via the \"all\"\n // sentinel).\n if (this._reactive_events.size > 0)\n // Snapshots produced by `action()` always carry their committed\n // event — the optional `event?` on the type is for load()\n // snapshots, which don't reach this path.\n this._armForEventNames(\n snapshots.map((s) => (s.event as { name: string }).name)\n );\n this.emit(\"committed\", snapshots as Snapshot<TSchemaReg, TEvents>[]);\n return snapshots;\n });\n }\n\n /**\n * Loads the current state snapshot for a specific stream.\n *\n * Reconstructs the current state by replaying events from the event store.\n * Uses snapshots when available to optimize loading performance.\n *\n * Accepts either a State definition object or a state name string. When\n * using a string, the merged state (from partial states registered via\n * `.withState()`) is resolved by name.\n *\n * @template TNewState - State schema type\n * @template TNewEvents - Event schemas type\n * @template TNewActions - Action schemas type\n * @param state - The state definition or state name to load\n * @param stream - The stream ID (state instance identifier)\n * @param callback - Optional callback invoked with the loaded snapshot\n * @returns The current state snapshot for the stream\n *\n * @example Load by state definition\n * ```typescript\n * const snapshot = await app.load(Counter, \"counter-1\");\n * console.log(snapshot.state.count); // Current count\n * console.log(snapshot.patches); // Events since last snapshot\n * ```\n *\n * @example Load by state name (useful with partial states)\n * ```typescript\n * const snapshot = await app.load(\"Ticket\", \"ticket-123\");\n * console.log(snapshot.state.title); // Merged state from all partials\n * ```\n *\n * @example Load multiple states\n * ```typescript\n * const [user, account] = await Promise.all([\n * app.load(User, \"user-123\"),\n * app.load(BankAccount, \"account-456\")\n * ]);\n * ```\n *\n * @see {@link Snapshot} for snapshot structure\n */\n async load<\n TNewState extends Schema,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n >(\n state: State<TNewState, TNewEvents, TNewActions>,\n stream: string,\n callback?: (snapshot: Snapshot<TNewState, TNewEvents>) => void,\n asOf?: AsOf\n ): Promise<Snapshot<TNewState, TNewEvents>>;\n async load<TKey extends keyof TStateMap & string>(\n name: TKey,\n stream: string,\n callback?: (snapshot: Snapshot<TStateMap[TKey], TEvents>) => void,\n asOf?: AsOf\n ): Promise<Snapshot<TStateMap[TKey], TEvents>>;\n async load<TNewState extends Schema>(\n stateOrName: State<TNewState, any, any> | string,\n stream: string,\n callback?: (snapshot: Snapshot<any, any>) => void,\n asOf?: AsOf\n ): Promise<Snapshot<any, any>> {\n return this._scoped(async () => {\n let merged: State<any, any, any>;\n if (typeof stateOrName === \"string\") {\n const found = this._states.get(stateOrName);\n if (!found) throw new Error(`State \"${stateOrName}\" not found`);\n merged = found;\n } else {\n merged = this._states.get(stateOrName.name) || stateOrName;\n }\n return await this._es.load(merged, stream, callback, asOf);\n });\n }\n\n /**\n * Queries the event store for events matching a filter.\n *\n * Use this for analyzing event streams, generating reports, or debugging.\n * The callback is invoked for each matching event, and the method returns\n * summary information (first event, last event, total count).\n *\n * For small result sets, consider using {@link query_array} instead.\n *\n * @param query - Filter criteria — see {@link Query} for available fields\n * (`stream`, `name`, `after`, `before`, `created_after`, `created_before`,\n * `limit`, `with_snaps`, `stream_exact`)\n * @param callback - Optional callback invoked for each matching event\n * @returns Object with first event, last event, and total count\n *\n * @example Query all events for a stream\n * ```typescript\n * const { first, last, count } = await app.query(\n * { stream: \"counter-1\" },\n * (event) => console.log(event.name, event.data)\n * );\n * console.log(`Found ${count} events from ${first?.id} to ${last?.id}`);\n * ```\n *\n * @example Query specific event types\n * ```typescript\n * const { count } = await app.query(\n * { name: \"UserCreated\", limit: 100 },\n * (event) => {\n * console.log(\"User created:\", event.data.email);\n * }\n * );\n * ```\n *\n * @example Query events in time range\n * ```typescript\n * const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);\n * const { count } = await app.query({\n * created_after: yesterday,\n * stream: \"user-123\"\n * });\n * console.log(`User had ${count} events in last 24 hours`);\n * ```\n *\n * @see {@link query_array} for loading events into memory\n */\n async query(\n query: Query,\n callback?: (event: Committed<TEvents, keyof TEvents>) => void\n ): Promise<{\n first?: Committed<TEvents, keyof TEvents>;\n last?: Committed<TEvents, keyof TEvents>;\n count: number;\n }> {\n return this._scoped(async () => {\n let first: Committed<TEvents, keyof TEvents> | undefined;\n let last: Committed<TEvents, keyof TEvents> | undefined;\n const count = await store().query<TEvents>((e) => {\n if (!first) first = e;\n last = e;\n callback?.(e);\n }, query);\n return { first, last, count };\n });\n }\n\n /**\n * Queries the event store and returns all matching events in memory.\n *\n * **Use with caution** - this loads all results into memory. For large result sets,\n * use {@link query} with a callback instead to process events incrementally.\n *\n * @param query - The query filter (same as {@link query})\n * @returns Array of all matching events\n *\n * @example Load all events for a stream\n * ```typescript\n * const events = await app.query_array({ stream: \"counter-1\" });\n * console.log(`Loaded ${events.length} events`);\n * events.forEach(event => console.log(event.name, event.data));\n * ```\n *\n * @example Get recent events\n * ```typescript\n * const recent = await app.query_array({\n * stream: \"user-123\",\n * limit: 10\n * });\n * ```\n *\n * @see {@link query} for large result sets\n */\n async query_array(\n query: Query\n ): Promise<Committed<TEvents, keyof TEvents>[]> {\n return this._scoped(async () => {\n const events: Committed<TEvents, keyof TEvents>[] = [];\n await store().query<TEvents>((e) => events.push(e), query);\n return events;\n });\n }\n\n /**\n * Processes pending reactions by draining uncommitted events from the event store.\n *\n * Runs a single drain cycle:\n * 1. Polls the store for streams with uncommitted events\n * 2. Leases streams to prevent concurrent processing\n * 3. Fetches events for each leased stream\n * 4. Executes matching reaction handlers\n * 5. Acknowledges successful reactions or blocks failing ones\n *\n * Drain uses a dual-frontier strategy to balance processing of new streams (lagging)\n * vs active streams (leading). The ratio adapts based on event pressure.\n *\n * Call `correlate()` before `drain()` to discover target streams. For a higher-level\n * API that handles debouncing, correlation, and signaling automatically, use {@link settle}.\n *\n * @param options - Drain configuration — see {@link DrainOptions} for fields\n * (`streamLimit`, `eventLimit`, `leaseMillis`).\n * @returns Drain statistics with fetched, leased, acked, and blocked counts\n *\n * @example In tests and scripts\n * ```typescript\n * await app.do(\"createUser\", target, payload);\n * await app.correlate();\n * await app.drain();\n * ```\n *\n * @example In production, prefer settle()\n * ```typescript\n * await app.do(\"CreateItem\", target, input);\n * app.settle(); // debounced correlate→drain, emits \"settled\"\n * ```\n *\n * @see {@link settle} for debounced correlate→drain with lifecycle events\n * @see {@link correlate} for dynamic stream discovery\n * @see {@link start_correlations} for automatic correlation\n */\n async drain(options: DrainOptions = {}): Promise<Drain<TEvents>> {\n return this._scoped(() => this._drainAll(options));\n }\n\n /** Arm every active lane controller (ACT-1103). */\n private _armAll(): void {\n for (const c of this._drain_controllers.values()) c.arm();\n }\n\n /**\n * Arm only the lane controllers whose reactions match the supplied\n * event names (ACT-1103 selective arming). Events with any dynamic\n * resolver fall back to `_armAll()` via the `\"all\"` sentinel — the\n * resolver's lane isn't known until correlate runs the function.\n * Events with no reactions are skipped; `_event_to_lanes` doesn't\n * carry them. Returns true when any controller was armed (used by\n * the notify handler to decide whether to schedule a settle).\n */\n private _armForEventNames(names: Iterable<string>): boolean {\n const to_arm = new Set<string>();\n for (const name of names) {\n const set = this._event_to_lanes.get(name);\n if (set === undefined) continue;\n if (set === ALL_LANES) {\n this._armAll();\n return true;\n }\n for (const lane of set) to_arm.add(lane);\n }\n if (to_arm.size === 0) return false;\n for (const lane of to_arm) this._drain_controllers.get(lane)?.arm();\n return true;\n }\n\n /** Drain every active lane controller in parallel and aggregate.\n *\n * Parallel — not sequential — so a slow lane's in-flight handler does\n * not block a fast lane's claim/dispatch/ack cycle. Each controller's\n * `claim()` is independent (filtered by lane); the store's\n * `SKIP LOCKED` keeps cross-controller races safe. Lifecycle events\n * (`acked`, `blocked`) may interleave by lane — listeners filter via\n * `lease.lane`. */\n private async _drainAll(options: DrainOptions): Promise<Drain<TEvents>> {\n const results = await Promise.all(\n [...this._drain_controllers.values()].map((c) => c.drain(options))\n );\n const fetched: Drain<TEvents>[\"fetched\"] = [];\n const leased: Lease[] = [];\n const acked: Lease[] = [];\n const blocked: BlockedLease[] = [];\n for (const r of results) {\n fetched.push(...r.fetched);\n leased.push(...r.leased);\n acked.push(...r.acked);\n blocked.push(...r.blocked);\n }\n return { fetched, leased, acked, blocked };\n }\n\n /**\n * Discovers and registers new streams dynamically based on reaction resolvers.\n *\n * Correlation enables \"dynamic reactions\" where target streams are determined at runtime\n * based on event content. For example, you might create a stats stream for each user\n * when they perform certain actions.\n *\n * This method scans events matching the query and identifies new target streams based\n * on reaction resolvers. It then registers these streams so they'll be picked up by\n * the next drain cycle.\n *\n * @param query - Query filter to scan for new correlations\n * @param query - Scan filter — see {@link Query} for fields (typically\n * `{ after: <event-id>, limit: <count> }`)\n * @returns Object with newly leased streams and last scanned event ID\n *\n * @example Manual correlation\n * ```typescript\n * // Scan for new streams\n * const { leased, last_id } = await app.correlate({ after: 0, limit: 100 });\n * console.log(`Found ${leased.length} new streams`);\n *\n * // Save last_id for next scan\n * await saveCheckpoint(last_id);\n * ```\n *\n * @example Dynamic stream creation\n * ```typescript\n * const app = act()\n * .withState(User)\n * .withState(UserStats)\n * .on(\"UserLoggedIn\")\n * .do(async (event) => [\"incrementLoginCount\", {}])\n * .to((event) => ({\n * target: `stats-${event.stream}` // Dynamic target per user\n * }))\n * .build();\n *\n * // Discover stats streams as users log in\n * await app.correlate();\n * ```\n *\n * @see {@link start_correlations} for automatic periodic correlation\n * @see {@link stop_correlations} to stop automatic correlation\n */\n async correlate(\n query: Query = { after: -1, limit: 10 }\n ): Promise<{ subscribed: number; last_id: number }> {\n return this._scoped(() => this._correlate.correlate(query));\n }\n\n /**\n * Starts automatic periodic correlation worker for discovering new streams.\n *\n * The correlation worker runs in the background, scanning for new events and identifying\n * new target streams based on reaction resolvers. It maintains a sliding window that\n * advances with each scan, ensuring all events are eventually correlated.\n *\n * This is useful for dynamic stream creation patterns where you don't know all streams\n * upfront - they're discovered as events arrive.\n *\n * **Note:** Only one correlation worker can run at a time per Act instance.\n *\n * @param query - Query filter for correlation scans — see {@link Query}\n * (typically `{ after: -1, limit: 100 }`)\n * @param frequency - Correlation frequency in milliseconds (default: 10000)\n * @param callback - Optional callback invoked with newly discovered streams\n * @returns `true` if worker started, `false` if already running\n *\n * @example Start automatic correlation\n * ```typescript\n * // Start correlation worker scanning every 5 seconds\n * app.start_correlations(\n * { after: 0, limit: 100 },\n * 5000,\n * (leased) => {\n * console.log(`Discovered ${leased.length} new streams`);\n * }\n * );\n *\n * // Later, stop it\n * app.stop_correlations();\n * ```\n *\n * @example With checkpoint persistence\n * ```typescript\n * // Load last checkpoint\n * const lastId = await loadCheckpoint();\n *\n * app.start_correlations(\n * { after: lastId, limit: 100 },\n * 10000,\n * async (leased) => {\n * // Save checkpoint for next restart\n * if (leased.length) {\n * const maxId = Math.max(...leased.map(l => l.at));\n * await saveCheckpoint(maxId);\n * }\n * }\n * );\n * ```\n *\n * @see {@link correlate} for manual one-time correlation\n * @see {@link stop_correlations} to stop the worker\n */\n start_correlations(\n query: Query = {},\n frequency = 10_000,\n callback?: (subscribed: number) => void\n ): boolean {\n return this._correlate.startPolling(query, frequency, callback);\n }\n\n /**\n * Stops the automatic correlation worker.\n *\n * Call this to stop the background correlation worker started by {@link start_correlations}.\n * This is automatically called when the Act instance is disposed.\n *\n * @example\n * ```typescript\n * // Start correlation\n * app.start_correlations();\n *\n * // Later, stop it\n * app.stop_correlations();\n * ```\n *\n * @see {@link start_correlations}\n */\n stop_correlations() {\n this._correlate.stopPolling();\n }\n\n /**\n * Cancels any pending or active settle cycle.\n *\n * @see {@link settle}\n */\n stop_settling() {\n this._settle.stop();\n }\n\n /**\n * Reset reaction stream watermarks and request a drain on the next\n * `drain()` / `settle()` cycle.\n *\n * Use this to replay events through projections (or other reaction targets)\n * after changing handler logic. Equivalent to calling `store().reset(streams)`\n * directly, but also raises the orchestrator's internal \"needs drain\" flag —\n * `store().reset(...)` alone leaves the flag untouched, so a settled app\n * would short-circuit and skip the replay.\n *\n * Pair with `app.settle()` (or a single `app.drain()` for small streams).\n * `settle()` loops correlate→drain until no progress is made, so one call\n * fully catches up paginated streams without forcing callers to roll\n * their own loop.\n *\n * @param streams - Reaction target streams (e.g., projection names) to reset\n * @returns Count of streams that were actually reset\n *\n * @example Rebuild a projection (production)\n * ```typescript\n * await app.reset([\"my-projection\"]);\n * app.settle({ eventLimit: 1000 }); // emits \"settled\" when fully replayed\n * ```\n *\n * @example Rebuild a projection (tests / scripts)\n * ```typescript\n * await app.reset([\"my-projection\"]);\n * await app.drain({ eventLimit: 1000 }); // small streams: one pass is enough\n * ```\n *\n * @see {@link Store.reset} for the underlying store primitive\n * @see {@link settle} for the debounced full-catch-up loop\n */\n async reset(input: string[] | StreamFilter): Promise<number> {\n return this._scoped(async () => {\n const count = await store().reset(input);\n if (count > 0 && this._reactive_events.size > 0) this._armAll();\n return count;\n });\n }\n\n /**\n * Clear the blocked flag on streams without replaying their history.\n *\n * Use this to recover from a poison message after fixing the\n * underlying issue — the stream resumes from the next event after the\n * last successful ack, not from the beginning. Compare with\n * {@link reset}, which rebuilds from event 0 (suitable for projection\n * rebuilds, wrong for \"I fixed the bug, please retry\").\n *\n * Wraps `store().unblock(streams)` and raises the orchestrator's\n * internal \"needs drain\" flag so a settled app picks up the now-free\n * streams on the next cycle. Equivalent to calling `store().unblock(...)`\n * directly, but `store().unblock(...)` alone leaves the flag\n * untouched.\n *\n * @param streams - Stream names to unblock\n * @returns Count of streams that were actually flipped (were blocked)\n *\n * @example Recover from a 4xx webhook after fixing the bug\n * ```typescript\n * await app.unblock([\"webhooks-out-customer-42\"]);\n * // The stream resumes from the next event, not from zero.\n * ```\n *\n * @see {@link Store.unblock} for the underlying store primitive\n * @see {@link reset} for the rebuild-from-zero alternative\n */\n async unblock(input: string[] | StreamFilter): Promise<number> {\n return this._scoped(async () => {\n const count = await store().unblock(input);\n if (count > 0 && this._reactive_events.size > 0) this._armAll();\n return count;\n });\n }\n\n /**\n * Atomically wipe the store and rebuild it from an async stream of\n * committed events. The framework owns iteration, validation,\n * `drop_snapshots` filtering, `on_progress`, and the per-call\n * `old → new` causation remap; the adapter's {@link Store.restore}\n * driver supplies the transaction lifecycle and per-event insert.\n *\n * Throws if the adapter has no restore capability. Throws on the\n * first invalid event (negative version, malformed `created`) with\n * the running index in the message; atomic transaction rollback in\n * the adapter means a failing restore leaves the store byte-for-byte\n * unchanged.\n *\n * @param source - Async stream of events in target order. Streamed\n * rather than buffered so multi-million-event backups don't OOM.\n * Each event's original `id` is used as a causation lookup key but\n * never written through — adapters renumber densely.\n * @param opts - {@link ScanOptions}. `drop_snapshots` skips\n * `__snapshot__` events (counted in the result); `on_progress`\n * fires once per event.\n * @returns {@link ScanResult} with `kept`, `duration_ms`, and\n * `dropped` per-category counters.\n *\n * @example Round-trip a CSV backup\n * ```typescript\n * async function* parseCsv(blob: string) {\n * for (const line of blob.split(\"\\n\").slice(1)) {\n * const [id, name, data, stream, version, created, meta] = parse(line);\n * yield {\n * id: +id, name, data: JSON.parse(data), stream,\n * version: +version, created: new Date(created),\n * meta: JSON.parse(meta),\n * };\n * }\n * }\n * const result = await app.restore(parseCsv(csvBlob), {});\n * console.log(`Restored ${result.kept} events in ${result.duration_ms}ms`);\n * await cache().clear(); // operator's responsibility\n * ```\n *\n * @see {@link Store.restore} for the underlying driver-pattern primitive.\n */\n async restore(\n source: EventSource,\n opts: ScanOptions = {},\n sink?: EventSink\n ): Promise<ScanResult> {\n return this._scoped(async () => {\n const started = Date.now();\n // Dry-run: walk the source via scan without touching any sink\n // — same scan loop, no callback, no transaction, no capability\n // check. Returns the counts a destructive restore would land.\n if (opts.dry_run) {\n const partial = await scan(source, opts);\n return { ...partial, duration_ms: Date.now() - started };\n }\n // Default sink is the singleton store. Explicit `sink` lets\n // callers route to a different EventSink (another adapter, a\n // CsvFile, etc.) without binding the singleton.\n const target: EventSink =\n sink ??\n (() => {\n const s = store();\n if (!s.restore) throw new Error(\"adapter has no restore capability\");\n return s as EventSink;\n })();\n let kept = 0;\n let dropped = { closed_streams: 0, snapshots: 0, empty_streams: 0 };\n await target.restore(async (callback) => {\n const partial = await scan(source, opts, callback);\n kept = partial.kept;\n dropped = partial.dropped;\n });\n return { kept, dropped, duration_ms: Date.now() - started };\n });\n }\n\n /**\n * Return every currently-blocked stream position. Convenience wrapper\n * around `store().query_streams(cb, { blocked: true })` for the common\n * \"show me what's broken\" operational query.\n *\n * Results are ordered by stream name, paginated by `limit` (default\n * 100). Pass `after` to fetch the next page (keyset cursor on the\n * stream name). For richer queries — including blocked + source\n * filters, or full unblocked introspection — drop to\n * `store().query_streams(...)` directly.\n *\n * @returns Array of {@link StreamPosition} for currently-blocked streams.\n *\n * @example Discover and recover\n * ```typescript\n * const blocked = await app.blocked_streams();\n * console.table(blocked.map(({ stream, retry, error }) => ({ stream, retry, error })));\n *\n * // Operator investigates, then bulk-unblocks the family:\n * await app.unblock({ stream: \"^webhooks-out-\" });\n * ```\n */\n async blocked_streams(options?: {\n after?: string;\n limit?: number;\n }): Promise<StreamPosition[]> {\n return this._scoped(async () => {\n const positions: StreamPosition[] = [];\n await store().query_streams(\n (p) => {\n positions.push(p);\n },\n { blocked: true, after: options?.after, limit: options?.limit }\n );\n return positions;\n });\n }\n\n /**\n * Operator-driven store audit (#723).\n *\n * Walks the connected store and yields per-category findings —\n * each tagged with the remediation it suggests. Same operator-\n * driven category as `app.close()` / `app.reset()` /\n * `app.unblock()` / `app.blocked_streams()`: never auto-invoked by\n * the framework; the operator decides when to run it (CI gate,\n * scheduled job, ad-hoc forensics) and what to do with the\n * findings.\n *\n * Categories are independent — pass a subset to scope the work,\n * or omit to run everything:\n *\n * ```typescript\n * // Targeted: schema drift + deprecated-event load only\n * for await (const f of app.audit([\"schema\", \"deprecated-load\"], {\n * query: { created_after: lastScan },\n * thresholds: { deprecatedLoadShareMin: 0.10 },\n * })) {\n * await escalate(f);\n * }\n *\n * // Full audit, default thresholds\n * for await (const f of app.audit()) console.log(f);\n * ```\n *\n * Returns an `AsyncIterable` so callers can `break` early — the\n * underlying store paginations respect the iterator protocol and\n * stop cleanly. Each finding is emitted independently, so\n * pipelining into Slack / persistence / further analysis works\n * without buffering the full report in memory.\n *\n * Findings shape — see {@link AuditFinding}. The discriminated\n * union carries enough context for the operator to act on each\n * finding directly: stream id, event id, recommendation hints.\n *\n * @param categories - Subset of categories to run (default: all).\n * @param options - Query window + per-category thresholds.\n * @returns Async iterable of {@link AuditFinding}.\n */\n audit(\n categories?: AuditCategory[],\n options?: AuditOptions\n ): AsyncIterable<AuditFinding> {\n return audit(this._audit_deps, categories, options);\n }\n\n /**\n * Bulk-update scheduling priority for streams matching `filter`.\n *\n * Operator-grade override of the `claim()` lagging-frontier\n * ordering (ACT-102). Useful when a long-running replay needs to\n * jump ahead of other lagging streams, or when a no-longer-urgent\n * job should yield slots back to the rest. Build-time priorities\n * (set via the resolver's `priority` field) are subject to a\n * `max()` invariant across reactions; this API ignores that and\n * sets the priority outright on every matching row.\n *\n * Filter shape mirrors {@link query} / {@link Store.query_streams}:\n * `stream` / `source` are regex by default, exact with the\n * `*_exact` flags; `blocked` restricts to blocked or unblocked\n * rows. **An empty filter (`{}`) updates every registered stream.**\n *\n * @param filter - Selection criteria (regex by default).\n * @param priority - New priority value. Set as-is — no clamp.\n * @returns Count of streams whose priority changed.\n *\n * @example Boost a specific projection mid-replay\n * ```typescript\n * await app.prioritize({ stream: \"^proj-orders$\", stream_exact: false }, 10);\n * ```\n *\n * @example Drop all audit projections to background\n * ```typescript\n * await app.prioritize({ source: \"^audit-\" }, -5);\n * ```\n *\n * @example Reset everyone to default\n * ```typescript\n * await app.prioritize({}, 0);\n * ```\n *\n * @see {@link Store.prioritize} for the underlying primitive\n * @see {@link claim} for how priority biases scheduling\n */\n async prioritize(filter: StreamFilter, priority: number): Promise<number> {\n return this._scoped(() => store().prioritize(filter, priority));\n }\n\n /**\n * Close the books — guard, archive, truncate, and optionally restart streams.\n *\n * Safely removes historical events from the operational store:\n *\n * 1. **Correlate** — discover pending reaction targets\n * 2. **Safety check** — skip streams with pending reactions (skipped when no reactive events)\n * 3. **Guard** — commit `__tombstone__` with `expectedVersion` to block concurrent writes\n * 4. **Load state** — for streams in `snapshots`, load final state while guarded (no races)\n * 5. **Archive** — user callback per stream (abort-all on failure, streams are guarded)\n * 6. **Truncate + seed** — atomic: delete all events, insert `__snapshot__` or `__tombstone__`\n * 7. **Cache** — invalidate (tombstoned) or warm (restarted)\n * 8. **Emit \"closed\"** — lifecycle event with results\n *\n * @param targets - Per-stream close options (stream, restart?, archive?)\n * @returns `{ truncated: TruncateResult, skipped: string[] }`\n *\n * @example Archive and close\n * ```typescript\n * await app.close([\n * { stream: \"order-123\", archive: async () => { await archiveToS3(\"order-123\"); } },\n * { stream: \"order-456\" },\n * ]);\n * ```\n *\n * @example Close with restart (state loaded automatically after guard)\n * ```typescript\n * await app.close([\n * { stream: \"counter-1\", restart: true },\n * { stream: \"counter-2\" }, // tombstoned\n * ]);\n * ```\n */\n async close(targets: CloseTarget[]): Promise<CloseResult> {\n if (!targets.length) return { truncated: new Map(), skipped: [] };\n\n return this._scoped(async () => {\n // Correlate first so dynamic reaction targets are discovered before\n // the safety check examines subscription positions.\n await this.correlate({ limit: 1000 });\n\n // Synthesize an actor for the close transaction so user-supplied\n // correlators can still tag tenant context / trace ids.\n const closeActor = { id: \"$close\", name: \"close\" };\n const result = await runCloseCycle(targets, {\n reactiveEventsSize: this._reactive_events.size,\n eventToState: this._event_to_state,\n load: this._es.load,\n tombstone: this._es.tombstone,\n logger: this._logger,\n correlation: closeCorrelation(this._correlator, closeActor),\n });\n\n this.emit(\"closed\", result);\n return result;\n });\n }\n\n /**\n * Debounced, non-blocking correlate→drain cycle.\n *\n * Call this after `app.do()` (or `app.reset()`) to schedule a background\n * drain. Multiple rapid calls within the debounce window are coalesced\n * into a single cycle. Runs correlate→drain in a loop until a pass makes\n * no progress — no new subscriptions, no acks, no blocks — then emits\n * the `\"settled\"` lifecycle event. This means a single `settle()` call\n * fully catches up paginated streams (e.g. after `reset()` on a long\n * projection) without forcing callers to loop.\n *\n * @param options - Settle configuration — see {@link SettleOptions} for fields:\n * `debounceMs` (default 10), `correlate` (default `{ after: -1, limit: 100 }`),\n * `maxPasses` (default `Infinity` — kill-switch for runaway loops),\n * `streamLimit` (default 10), `eventLimit` (default 10),\n * `leaseMillis` (default 10000).\n *\n * @example API mutations\n * ```typescript\n * await app.do(\"CreateItem\", target, input);\n * app.settle(); // non-blocking, returns immediately\n *\n * app.on(\"settled\", (drain) => {\n * // notify SSE clients, invalidate caches, etc.\n * });\n * ```\n *\n * @see {@link drain} for single synchronous drain cycles\n * @see {@link correlate} for manual correlation\n */\n settle(options: SettleOptions = {}): void {\n this._settle.schedule(options);\n }\n}\n","/**\n * @module event-versions\n * @category Internal\n *\n * Auto-deprecation of legacy event versions via the `_v<digits>` naming\n * convention (ACT-403).\n *\n * Act's schema-evolution pattern keeps the old and new event names alive\n * forever — the old name on the read path (reducers), the new on the write\n * path (emissions). This module reads the convention to identify legacy\n * versions automatically; the framework then enforces \"emit only the\n * current version\" at build time and warns at runtime for dynamic emits.\n *\n * Convention pin: only `_v<digits>` with digits ≥ 2 counts as a version\n * suffix. `Foo_v1` is just a literal event name (the base `Foo` is\n * implicitly v1). Pinning here keeps the contract surface small.\n *\n * @internal\n */\n\nconst VERSION_SUFFIX = /^(.+?)_v(\\d+)$/;\n\ntype Versioned = { version: number; name: string };\n\n/**\n * Splits an event name into (base, version). Names without a `_v<n≥2>`\n * suffix are returned as (name, 1) — the base is its own implicit v1.\n */\nfunction parse(name: string): { base: string; version: number } {\n const m = name.match(VERSION_SUFFIX);\n if (m) {\n const v = Number.parseInt(m[2], 10);\n if (v >= 2) return { base: m[1], version: v };\n }\n return { base: name, version: 1 };\n}\n\n/**\n * Returns the set of event names that are deprecated by virtue of having\n * a higher-numbered sibling in the registry. The highest version in each\n * group is the current version; every lower version is deprecated.\n *\n * Gaps are allowed: `{Foo, Foo_v3}` → `Foo` is deprecated, `Foo_v3` is\n * current. The framework picks the max regardless of contiguity.\n *\n * Single-version groups (no siblings) yield no deprecations.\n *\n * @internal\n */\nexport function deprecatedEventNames(names: Iterable<string>): Set<string> {\n const groups = new Map<string, Versioned[]>();\n for (const name of names) {\n const { base, version } = parse(name);\n const list = groups.get(base);\n if (list) list.push({ version, name });\n else groups.set(base, [{ version, name }]);\n }\n const deprecated = new Set<string>();\n for (const list of groups.values()) {\n if (list.length < 2) continue;\n list.sort((a, b) => b.version - a.version); // descending\n // index 0 is current; the rest are deprecated\n for (let i = 1; i < list.length; i++) deprecated.add(list[i].name);\n }\n return deprecated;\n}\n\n/**\n * Given a deprecated event name and the full set of event names in its\n * registry, returns the current (highest-version) sibling. Used to build\n * actionable error messages — \"use `Foo_v3` instead.\"\n *\n * Returns `undefined` if the event has no higher-versioned sibling (which\n * means the caller's classification is stale or wrong).\n *\n * @internal\n */\nexport function currentVersionOf(\n deprecatedName: string,\n allNames: Iterable<string>\n): string | undefined {\n const target = parse(deprecatedName);\n let highest: Versioned | undefined;\n for (const name of allNames) {\n const { base, version } = parse(name);\n if (base !== target.base) continue;\n if (!highest || version > highest.version) highest = { version, name };\n }\n return highest && highest.version > target.version ? highest.name : undefined;\n}\n","/**\n * @module audit\n * @category Internal\n *\n * Operator-driven store audit (#723).\n *\n * Walks the connected store and yields per-category {@link AuditFinding}s.\n * Each category answers a different \"what should I do with this store?\"\n * question and pairs with a remediation:\n *\n * - `schema` → fix the data model (poison events, unknown names)\n * - `close-candidate` → `app.close([...])`\n * - `restart-candidate` → `app.close([{stream, restart:true}, …])`\n * - `deprecated-load` → `app.close([...])` on the heaviest carriers\n * - `reaction-health` → `app.unblock(...)` / `app.reset(...)`\n * - `snapshot-drift` → manual `load({snap:true})` or wait for policy\n * - `routing-health` → restart-with-new-config to re-lane\n * - `correlation-gaps` → fix upstream correlator misconfig\n * - `clock-anomalies` → infra remediation (clock skew)\n *\n * ## Single-scan multiplex (efficiency contract)\n *\n * Earlier draft had each category run its own `store.query(...)`,\n * which meant N requested categories → N table walks. Bad for large\n * stores. Refactored to a pass-based design: each category is a\n * factory that returns an {@link AuditPass} with optional per-row\n * callbacks (`onEvent` / `onStream` / `onStat`) and a `finalize` hook\n * for any second-pass work. The dispatcher determines the UNION of\n * required data sources, runs each *once*, and broadcasts each row\n * to all interested passes. Worst case: three scans total (events,\n * streams, stats) regardless of how many categories the operator\n * requested. Most categories also share state — close-candidate and\n * restart-candidate both consume the same `onStat` stream; schema,\n * correlation-gaps, and clock-anomalies all hang off the same\n * `onEvent` broadcast.\n *\n * Categories that need follow-up work (snapshot-drift's per-stream\n * snapshot lookup, correlation-gaps' orphan-id check after collecting\n * ids) do that in their `finalize` hook with their own targeted store\n * calls — keeps the shared scan path minimal.\n *\n * Isolated from orchestration internals — `act.ts` builds the\n * {@link AuditDeps} bag at `.build()` time and hands it here via\n * a one-liner. The audit module never reaches into\n * `internal/{event-sourcing,drain-cycle,settle,close-cycle}.ts`; it\n * only reads through the deps interface and the public `Store`\n * surface. Same shape as `act-tck` within the workspace — a peer of\n * orchestration, not entangled with its private mechanics.\n *\n * @internal\n */\n\nimport type {\n AuditCategory,\n AuditFinding,\n AuditOptions,\n Committed,\n Logger,\n Schemas,\n State,\n Store,\n StreamPosition,\n StreamStats,\n} from \"../types/index.js\";\nimport { currentVersionOf, deprecatedEventNames } from \"./event-versions.js\";\n\n/**\n * Snapshot of orchestrator state the audit reads. Built once at\n * `app.build()`; the audit treats it as immutable for the duration\n * of a call. The orchestrator never passes its own private maps in\n * directly — this bag is the abstraction boundary so a future\n * orchestration refactor can't accidentally entangle with audit\n * logic.\n */\nexport type AuditDeps = {\n readonly store: () => Store;\n readonly logger: Logger;\n /** event-name → state that registers it (for schema validation). */\n readonly event_to_state: ReadonlyMap<string, State<any, any, any>>;\n /** state-name → state (for snapshot-supported check on restart-candidate). */\n readonly states: ReadonlyMap<string, State<any, any, any>>;\n /** All event names the registry knows (for unknown-name detection). */\n readonly known_events: ReadonlySet<string>;\n /** Declared drain lanes (for routing-health unknown-lane). */\n readonly declared_lanes: ReadonlySet<string>;\n /**\n * Event names that the registry has at least one reaction for —\n * used by routing-health to detect \"registered but unrouted\"\n * events. Normalized down from the internal `eventToLanes` map\n * (which carries lane-set details audit doesn't need).\n */\n readonly routed_events: ReadonlySet<string>;\n};\n\n/**\n * Defaults applied when the operator doesn't override via\n * {@link AuditOptions.thresholds}. Values land where most workloads\n * find them operationally useful — operators can tune per call.\n */\nconst DEFAULTS = {\n idle_days: 90,\n restart_min: 10_000,\n stuck_minutes: 30,\n deprecated_min: 0.1,\n drift_min: 500,\n near_block: 3,\n};\n\nconst ALL_CATEGORIES = [\n \"schema\",\n \"close-candidate\",\n \"restart-candidate\",\n \"deprecated-load\",\n \"reaction-health\",\n \"snapshot-drift\",\n \"routing-health\",\n \"correlation-gaps\",\n \"clock-anomalies\",\n] as const satisfies readonly AuditCategory[];\n\n/**\n * A single audit category, expressed as a stream-consumer:\n *\n * - `onEvent` / `onStream` / `onStat` are called by the dispatcher\n * during the shared scans. Each is optional; the dispatcher uses\n * the presence/absence to decide which scans to run.\n * - `finalize` runs after all shared scans complete. Categories that\n * need targeted follow-up store calls (snapshot-drift fetches the\n * last `__snapshot__` per drifted stream; correlation-gaps cross-\n * checks causations against the collected id set) do that here.\n * - `drain` is called last and returns the accumulated findings.\n */\ntype AuditPass = {\n category: AuditCategory;\n onEvent?: (e: Committed<Schemas, string>) => void;\n onStream?: (p: StreamPosition) => void;\n onStat?: (stream: string, s: StreamStats<Schemas>) => void;\n finalize?: (deps: AuditDeps) => Promise<void>;\n drain: () => AuditFinding[];\n};\n\ntype PassFactory = (deps: AuditDeps, options: AuditOptions) => AuditPass;\n\n/**\n * Top-level audit dispatcher. Single-scan multiplex: each requested\n * category contributes a `AuditPass`, the dispatcher determines the\n * union of required data sources (events / streams / stats), runs\n * each once, broadcasts rows, and yields per-category findings in\n * the order the categories were requested.\n *\n * Callers can `break` the iteration early — the underlying scan\n * loops have already completed by the time yield starts, so early\n * break only saves the iteration over already-collected findings.\n * (Per-row early termination during a scan isn't feasible without\n * coordination across passes; the audit is bounded by `options.query`\n * scoping rather than mid-scan cancellation.)\n */\nexport async function* audit(\n deps: AuditDeps,\n categories?: AuditCategory[],\n options: AuditOptions = {}\n): AsyncIterable<AuditFinding> {\n const requested = new Set<AuditCategory>(categories ?? [...ALL_CATEGORIES]);\n // Preserve a deterministic category order (matches ALL_CATEGORIES\n // declaration) so output ordering doesn't depend on the order\n // operators list categories in their call.\n const orderedCategories = ALL_CATEGORIES.filter((c) => requested.has(c));\n const passes: AuditPass[] = orderedCategories.map((c) =>\n PASS_FACTORIES[c](deps, options)\n );\n\n // Determine scan needs. `some(...)` short-circuits — three trivial\n // walks at worst.\n const needStats = passes.some((p) => p.onStat !== undefined);\n const needStreams = passes.some((p) => p.onStream !== undefined);\n const needEvents = passes.some((p) => p.onEvent !== undefined);\n\n if (needStats) {\n const stats = await deps\n .store()\n .query_stats<Schemas>({}, { count: true, names: true });\n for (const [stream, s] of stats) {\n for (const p of passes) p.onStat?.(stream, s);\n }\n }\n\n if (needStreams) {\n await deps.store().query_streams((pos) => {\n for (const p of passes) p.onStream?.(pos);\n });\n }\n\n if (needEvents) {\n await deps.store().query<Schemas>((event) => {\n for (const p of passes) p.onEvent?.(event);\n }, options.query);\n }\n\n // Async post-processing (per-stream queries, second-pass orphan\n // detection). Serial to avoid pool contention; categories are\n // independent so order doesn't matter semantically.\n for (const p of passes) await p.finalize?.(deps);\n\n // Yield findings in requested-category order.\n for (const p of passes) {\n for (const f of p.drain()) yield f;\n }\n}\n\n// =================== Pass factories ===================\n//\n// Each category is implemented as a closure-bound `AuditPass`. The\n// factory captures `deps` + relevant options + a `findings` array;\n// the returned pass exposes the per-row hooks the dispatcher calls.\n//\n// All findings are accumulated in a per-pass `findings` buffer and\n// returned from `drain()`. No yield-during-scan — that would couple\n// the pass to async iteration semantics and prevent the shared-scan\n// multiplexing.\n\n/**\n * `schema` — every event in the audit window is parsed against the\n * Zod schema the registry currently declares for its name. Two\n * failure modes: `unknown_event_name` (event sits on disk, registry\n * has no entry) and `schema_validation_failed` (event matches a\n * known name but fails the current Zod schema).\n */\nconst makeSchemaPass: PassFactory = (deps) => {\n const findings: AuditFinding[] = [];\n return {\n category: \"schema\",\n onEvent(event) {\n const name = String(event.name);\n const state = deps.event_to_state.get(name);\n if (!state) {\n // Skip framework markers — they're not user-declared.\n if (name.startsWith(\"__\")) return;\n findings.push({\n category: \"schema\",\n stream: event.stream,\n event_id: event.id,\n name,\n reason: \"unknown_event_name\",\n });\n return;\n }\n const schema = state.events[name];\n const parsed = schema.safeParse(event.data);\n if (!parsed.success) {\n findings.push({\n category: \"schema\",\n stream: event.stream,\n event_id: event.id,\n name,\n reason: \"schema_validation_failed\",\n zod_error: parsed.error,\n });\n }\n },\n drain: () => findings,\n };\n};\n\n/**\n * `deprecated-load` — workspace-wide event-name histogram classified\n * by the framework's `_v<digits>` rule. Built from the shared `onStat`\n * stream — accumulates per-name + per-stream totals in memory, then\n * emits one finding per deprecated event above the threshold during\n * `drain`.\n */\nconst makeDeprecatedLoadPass: PassFactory = (deps, options) => {\n const share_min =\n options.thresholds?.deprecated_min ?? DEFAULTS.deprecated_min;\n const totals = new Map<string, number>();\n const perStream = new Map<string, Map<string, number>>();\n return {\n category: \"deprecated-load\",\n onStat(stream, { names }) {\n // Contract: query_stats was called with `{names: true}`,\n // so adapter populates `names` with positive integer counts.\n // No runtime fallback needed.\n for (const [name, count] of Object.entries(names!)) {\n totals.set(name, (totals.get(name) ?? 0) + count!);\n let m = perStream.get(name);\n if (!m) {\n m = new Map();\n perStream.set(name, m);\n }\n m.set(stream, count!);\n }\n },\n drain() {\n const findings: AuditFinding[] = [];\n const grand = [...totals.values()].reduce((s, n) => s + n, 0);\n if (grand === 0) return findings;\n // Registry-driven deprecation classification (not on-disk-driven).\n const deprecated = deprecatedEventNames(deps.known_events);\n const sorted = [...deprecated]\n .map((name) => ({ name, count: totals.get(name) ?? 0 }))\n .sort((a, b) => b.count - a.count);\n for (const { name, count } of sorted) {\n if (count === 0) continue;\n if (count / grand < share_min) continue;\n // Contract: `deprecatedEventNames(registry)` only returns names\n // that have a higher version in the same family, so\n // `currentVersionOf(name, registry)` is guaranteed defined.\n const currentVersion = currentVersionOf(name, deps.known_events)!;\n // perStream is populated in lockstep with totals — name is guaranteed present.\n const topStreams = [...perStream.get(name)!.entries()]\n .map(([stream, c]) => ({ stream, count: c }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n findings.push({\n category: \"deprecated-load\",\n name,\n current_version: currentVersion,\n total: count,\n top_streams: topStreams,\n });\n }\n return findings;\n },\n };\n};\n\n/**\n * `close-candidate` — flags streams ripe for `app.close(...)`. Two\n * flavours: `idle` (head older than `idleDays`) and `terminal` (head\n * event name in operator-supplied `terminalEvents` list). Each\n * finding carries `restartSupported` (state has `.snap()`).\n */\nconst makeCloseCandidatePass: PassFactory = (deps, options) => {\n const idle_days = options.thresholds?.idle_days ?? DEFAULTS.idle_days;\n const terminal_events = new Set(options.thresholds?.terminal_events ?? []);\n const idle_cutoff = Date.now() - idle_days * 24 * 60 * 60 * 1000;\n const findings: AuditFinding[] = [];\n return {\n category: \"close-candidate\",\n onStat(stream, { head }) {\n const head_name = String(head.name);\n if (head_name.startsWith(\"__\")) return; // already-closed or mid-truncate\n // All in-tree adapters return `created` as Date; the Date\n // constructor passes Date instances through unchanged, so a\n // single call shape works regardless.\n const head_time = head.created.getTime();\n const is_idle = head_time < idle_cutoff;\n const is_terminal = terminal_events.has(head_name);\n if (!is_idle && !is_terminal) return;\n findings.push({\n category: \"close-candidate\",\n stream,\n last_event_at: head.created.toISOString(),\n reason: is_terminal ? \"terminal\" : \"idle\",\n idle_days: is_idle\n ? Math.floor((Date.now() - head_time) / (24 * 60 * 60 * 1000))\n : undefined,\n restart_supported: restartIsSupported(deps, head_name),\n });\n },\n drain: () => findings,\n };\n};\n\n/**\n * `restart-candidate` — streams above `eventCountForRestart` whose\n * state declares `.snap()`. Reads from the shared `onStat` stream.\n */\nconst makeRestartCandidatePass: PassFactory = (deps, options) => {\n const threshold = options.thresholds?.restart_min ?? DEFAULTS.restart_min;\n const findings: AuditFinding[] = [];\n return {\n category: \"restart-candidate\",\n onStat(stream, { head, count, names }) {\n // `count` / `names` always populated — query_stats is called\n // with both flags set; adapters keep them present together.\n if (count! < threshold) return;\n const head_name = String(head.name);\n if (head_name.startsWith(\"__\")) return;\n if (!restartIsSupported(deps, head_name)) return;\n findings.push({\n category: \"restart-candidate\",\n stream,\n count: count!,\n // names map is sparse — `__snapshot__` key absent when the\n // stream has never been snapshotted (a common case for the\n // restart-candidate signal).\n snaps: names![\"__snapshot__\"] ?? 0,\n });\n },\n drain: () => findings,\n };\n};\n\n/**\n * `reaction-health` — surfaces blocked / near-block / stuck-backoff\n * streams. Reads from the shared `onStream` stream-positions\n * broadcast.\n */\nconst makeReactionHealthPass: PassFactory = (_deps, options) => {\n const near_block = options.thresholds?.near_block ?? DEFAULTS.near_block;\n const stuck_minutes =\n options.thresholds?.stuck_minutes ?? DEFAULTS.stuck_minutes;\n const stuck_cutoff = Date.now() - stuck_minutes * 60 * 1000;\n const findings: AuditFinding[] = [];\n return {\n category: \"reaction-health\",\n onStream(p) {\n if (p.blocked) {\n findings.push({\n category: \"reaction-health\",\n stream: p.stream,\n status: \"blocked\",\n retry: p.retry,\n reason: p.error || \"blocked without recorded error\",\n });\n return;\n }\n if (p.retry >= near_block) {\n findings.push({\n category: \"reaction-health\",\n stream: p.stream,\n status: \"near-block\",\n retry: p.retry,\n reason: `retry ${p.retry} ≥ near-block threshold ${near_block}`,\n });\n return;\n }\n if (\n p.leased_by &&\n p.leased_until &&\n p.leased_until.getTime() < stuck_cutoff\n ) {\n const minutes = Math.floor(\n (Date.now() - p.leased_until.getTime()) / (60 * 1000)\n );\n findings.push({\n category: \"reaction-health\",\n stream: p.stream,\n status: \"stuck-backoff\",\n retry: p.retry,\n reason: `lease expired ${minutes}m ago without release`,\n });\n }\n },\n drain: () => findings,\n };\n};\n\n/**\n * `snapshot-drift` — buffers candidate streams from the shared\n * `onStat` pass (skipping non-snap states + tombstoned heads), then\n * does targeted per-stream lookups in `finalize` to find the last\n * `__snapshot__` event id and count events past it.\n */\nconst makeSnapshotDriftPass: PassFactory = (deps, options) => {\n const drift_min = options.thresholds?.drift_min ?? DEFAULTS.drift_min;\n // Streams the workspace pass identifies as drift candidates —\n // resolved in finalize with per-stream queries.\n const candidates: Array<{\n stream: string;\n total: number;\n snaps: number;\n }> = [];\n const findings: AuditFinding[] = [];\n return {\n category: \"snapshot-drift\",\n onStat(stream, { head, count, names }) {\n // restartIsSupported() already filters out framework markers\n // (__snapshot__, __tombstone__) — neither name appears in any\n // user state's events map, so the snap check rejects them.\n if (!restartIsSupported(deps, String(head.name))) return;\n if (count! < drift_min) return; // upper-bound short-circuit\n candidates.push({\n stream,\n total: count!,\n snaps: names![\"__snapshot__\"] ?? 0,\n });\n },\n async finalize(deps) {\n for (const { stream, total, snaps } of candidates) {\n let events_since_snap = total;\n let snap_at: number | undefined;\n if (snaps > 0) {\n const collected: Array<{ id: number }> = [];\n await deps.store().query(\n (e) => {\n collected.push({ id: e.id });\n },\n {\n stream,\n stream_exact: true,\n names: [\"__snapshot__\"],\n backward: true,\n limit: 1,\n with_snaps: true,\n }\n );\n // snaps > 0 means at least one `__snapshot__` event sits on\n // this stream — the backward-walk above must surface it.\n snap_at = collected[0]!.id;\n let after = 0;\n await deps.store().query(\n () => {\n after++;\n },\n { stream, stream_exact: true, after: snap_at }\n );\n events_since_snap = after;\n }\n if (events_since_snap < drift_min) continue;\n findings.push({\n category: \"snapshot-drift\",\n stream,\n events_since_snap,\n snap_at,\n });\n }\n },\n drain: () => findings,\n };\n};\n\n/**\n * `routing-health` — `unknown-lane` from the streams-table pass +\n * `unrouted` from the stats pass. Reads from BOTH shared streams.\n */\nconst makeRoutingHealthPass: PassFactory = (deps) => {\n const findings: AuditFinding[] = [];\n const seenEventNames = new Set<string>();\n return {\n category: \"routing-health\",\n onStream(p) {\n if (!p.lane) return; // default lane — never an unknown-lane finding\n if (deps.declared_lanes.has(p.lane)) return;\n findings.push({\n category: \"routing-health\",\n stream: p.stream,\n reason: \"unknown-lane\",\n lane: p.lane,\n });\n },\n onStat(_stream, { names }) {\n for (const name of Object.keys(names!)) {\n seenEventNames.add(name);\n }\n },\n finalize() {\n for (const name of seenEventNames) {\n if (name.startsWith(\"__\")) continue;\n if (deps.routed_events.has(name)) continue;\n findings.push({\n category: \"routing-health\",\n stream: \"*\",\n reason: \"unrouted\",\n });\n }\n return Promise.resolve();\n },\n drain: () => findings,\n };\n};\n\n/**\n * `correlation-gaps` — collects ids + parent_ids during the shared\n * event pass; flags orphans in `drain`. No second store walk — the\n * id-set + the (id, parent) buffer are both populated in one pass.\n */\nconst makeCorrelationGapsPass: PassFactory = () => {\n const seenIds = new Set<number>();\n const checks: Array<{ stream: string; id: number; parentId: number }> = [];\n return {\n category: \"correlation-gaps\",\n onEvent(e) {\n seenIds.add(e.id);\n const causation = (e.meta as Record<string, unknown> | undefined)\n ?.causation as { event?: { id?: number } } | undefined;\n const parentId = causation?.event?.id;\n if (parentId !== undefined) {\n checks.push({ stream: e.stream, id: e.id, parentId });\n }\n },\n drain() {\n const findings: AuditFinding[] = [];\n for (const { stream, id, parentId } of checks) {\n if (!seenIds.has(parentId)) {\n findings.push({\n category: \"correlation-gaps\",\n stream,\n event_id: id,\n reason: \"orphan-parent\",\n });\n }\n }\n return findings;\n },\n };\n};\n\n/**\n * `clock-anomalies` — flags future timestamps + per-stream out-of-\n * order `created`. Single pass, per-stream \"last seen\" state in a\n * Map. Cheap.\n */\nconst makeClockAnomaliesPass: PassFactory = () => {\n const findings: AuditFinding[] = [];\n const lastPerStream = new Map<string, number>();\n return {\n category: \"clock-anomalies\",\n onEvent(e) {\n // `created` is a Date instance per the Store contract.\n const created = e.created.getTime();\n if (created > Date.now()) {\n findings.push({\n category: \"clock-anomalies\",\n stream: e.stream,\n event_id: e.id,\n reason: \"future-created\",\n });\n }\n const prev = lastPerStream.get(e.stream);\n if (prev !== undefined && created < prev) {\n findings.push({\n category: \"clock-anomalies\",\n stream: e.stream,\n event_id: e.id,\n reason: \"out-of-order\",\n });\n }\n lastPerStream.set(e.stream, created);\n },\n drain: () => findings,\n };\n};\n\n/** Does the stream's owning state declare a `.snap()` reducer? */\nfunction restartIsSupported(deps: AuditDeps, headEventName: string): boolean {\n const state = deps.event_to_state.get(headEventName);\n return state?.snap !== undefined;\n}\n\n/** Factory registry — pass-creation indexed by category name. */\nconst PASS_FACTORIES: Record<AuditCategory, PassFactory> = {\n schema: makeSchemaPass,\n \"deprecated-load\": makeDeprecatedLoadPass,\n \"close-candidate\": makeCloseCandidatePass,\n \"restart-candidate\": makeRestartCandidatePass,\n \"reaction-health\": makeReactionHealthPass,\n \"snapshot-drift\": makeSnapshotDriftPass,\n \"routing-health\": makeRoutingHealthPass,\n \"correlation-gaps\": makeCorrelationGapsPass,\n \"clock-anomalies\": makeClockAnomaliesPass,\n};\n","/**\n * @module build-classify\n * @category Internal\n *\n * Build-time classification of the registry + state map. The Act constructor\n * needs four pre-computed inputs to wire its runtime subsystems:\n *\n * - `staticTargets` — known-up-front reaction targets (statics get\n * subscribed once at init; dynamics scan per event)\n * - `hasDynamicResolvers` — short-circuit flag for `correlate()`\n * - `reactiveEvents` — event names with at least one reaction (drives\n * the drain skip-flag in `do()` and `reset()`)\n * - `eventToState` — event-name → owning state, for `close({restart})`\n * seed loading in multi-state apps\n *\n * Pure function — single pass over events + states, fully testable without\n * instantiating Act.\n *\n * @internal\n */\n\nimport type {\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport type { StaticTarget } from \"./correlate-cycle.js\";\n\n/**\n * Classification result. Returned by {@link classifyRegistry}; consumed\n * piecewise by Act's constructor.\n *\n * @internal\n */\n/**\n * Sentinel for \"any reaction on this event has a dynamic resolver, so\n * the lane is opaque until correlate runs the function — arm every\n * controller.\" A Symbol rather than a string literal so it can't\n * collide with a user-declared lane named `\"all\"`.\n *\n * @internal\n */\nexport const ALL_LANES: unique symbol = Symbol(\"act-1103/all-lanes\");\n\n/**\n * Per-event lane fan-in (ACT-1103). For events whose every reaction\n * has a static resolver, the value is the union of those reactions'\n * declared lanes — `do()` arms only those controllers on commit. For\n * events with at least one dynamic resolver, the value is\n * {@link ALL_LANES}; `do()` falls back to arming every controller.\n *\n * @internal\n */\nexport type EventLaneSet = ReadonlySet<string> | typeof ALL_LANES;\n\nexport type Classification = {\n readonly staticTargets: StaticTarget[];\n readonly hasDynamicResolvers: boolean;\n readonly reactiveEvents: ReadonlySet<string>;\n readonly eventToState: ReadonlyMap<string, State<any, any, any>>;\n readonly eventToLanes: ReadonlyMap<string, EventLaneSet>;\n};\n\n/**\n * Walk the registry once to collect static reaction targets, the dynamic-\n * resolvers flag, the set of reactive event names, and the event-to-state\n * map. Static targets are deduplicated by (target, source) — two reactions\n * routing to the same projection produce one subscription.\n *\n * @internal\n */\nexport function classifyRegistry<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(\n registry: Registry<TSchemaReg, TEvents, TActions>,\n states: ReadonlyMap<string, State<Schema, any, any>>\n): Classification {\n const statics = new Map<string, StaticTarget>();\n const reactiveEvents = new Set<string>();\n const eventToLanes = new Map<string, EventLaneSet>();\n let hasDynamicResolvers = false;\n\n for (const [name, register] of Object.entries(registry.events)) {\n if (register.reactions.size > 0) reactiveEvents.add(name);\n for (const reaction of register.reactions.values()) {\n if (typeof reaction.resolver === \"function\") {\n hasDynamicResolvers = true;\n // Dynamic resolver — lane is opaque until runtime. Mark the\n // event as wildcard so `do()` falls back to arming every\n // controller for any commit of it.\n eventToLanes.set(name, ALL_LANES);\n } else {\n const { target, source, priority = 0, lane } = reaction.resolver;\n const lane_name = lane ?? \"default\";\n const existing_lanes = eventToLanes.get(name);\n if (existing_lanes !== ALL_LANES) {\n const set =\n (existing_lanes as Set<string> | undefined) ?? new Set<string>();\n set.add(lane_name);\n eventToLanes.set(name, set);\n }\n const key = `${target}|${source ?? \"\"}`;\n const existing = statics.get(key);\n if (!existing) {\n statics.set(key, { stream: target, source, priority, lane });\n } else {\n // ACT-1103: lanes don't merge — disagreement is a config error.\n if ((existing.lane ?? undefined) !== (lane ?? undefined))\n throw new Error(\n `Stream \"${target}\" has conflicting lane assignments ` +\n `(\"${existing.lane ?? \"default\"}\" vs \"${lane ?? \"default\"}\")`\n );\n if (priority > (existing.priority as number)) {\n // Multiple reactions with the same (target, source) — keep\n // the max priority so the highest-priority registrant sets\n // the scheduling lane (mirrors subscribe-side semantics).\n // `existing.priority` is always defined here since we always\n // set it when inserting, but the StaticTarget type marks it\n // optional for backwards compat with external consumers.\n statics.set(key, { ...existing, priority });\n }\n }\n }\n }\n }\n\n // Event-name → owning state. Duplicate event names are rejected at\n // registration time (merge.ts), so each entry is unambiguous.\n const eventToState = new Map<string, State<any, any, any>>();\n for (const merged of states.values()) {\n for (const eventName of Object.keys(merged.events)) {\n eventToState.set(eventName, merged);\n }\n }\n\n return {\n staticTargets: [...statics.values()],\n hasDynamicResolvers,\n reactiveEvents,\n eventToState,\n eventToLanes,\n };\n}\n","/**\n * @module close-cycle\n * @category Internal\n *\n * Pure orchestration of the close-the-books flow: scan stream heads,\n * partition by reaction safety, guard with tombstones, optionally seed\n * restart state, run user archive callbacks, atomically truncate, and\n * update the cache.\n *\n * The Act orchestrator owns lifecycle (correlate gate, emit(\"closed\")) and\n * the registry-derived inputs (reactive-event count, event→state map). All\n * sequential phase work between those state touches lives here.\n *\n * @internal\n */\n\nimport { cache, SNAP_EVENT, store, TOMBSTONE_EVENT } from \"../ports.js\";\nimport type {\n CloseResult,\n CloseTarget,\n Logger,\n Schema,\n State,\n} from \"../types/index.js\";\nimport type { EsOps } from \"./event-sourcing.js\";\n\n/**\n * Dependencies the close cycle needs from the Act orchestrator. Decoupled\n * from `Act` itself so the cycle can be exercised from tests in isolation.\n *\n * @internal\n */\nexport type CloseCycleDeps = {\n readonly reactiveEventsSize: number;\n readonly eventToState: ReadonlyMap<string, State<any, any, any>>;\n readonly load: EsOps[\"load\"];\n readonly tombstone: EsOps[\"tombstone\"];\n readonly logger: Logger;\n /**\n * Correlation id for the close transaction. Caller (`Act.close`)\n * computes this via the configured {@link Correlator}, so close\n * commits share the user's chosen id scheme instead of stamping a\n * UUID.\n */\n readonly correlation: string;\n};\n\n/**\n * Per-stream scan result: latest non-tombstone domain event metadata.\n * `lastEventName` is always defined — the scan filters tombstones in the\n * callback and queries without `with_snaps`, so any event reaching the\n * callback is a domain event whose name we capture alongside id/version.\n */\ntype StreamHead = {\n readonly maxId: number;\n readonly version: number;\n readonly lastEventName: string;\n};\n\n/**\n * Run the full close cycle for the given targets. Caller owns the\n * lifecycle event emission.\n *\n * @internal\n */\nexport async function runCloseCycle(\n targets: CloseTarget[],\n deps: CloseCycleDeps\n): Promise<CloseResult> {\n // Caller (Act.close) filters empty targets; runCloseCycle assumes at\n // least one target.\n const targetMap = new Map(targets.map((t) => [t.stream, t]));\n const streams = [...targetMap.keys()];\n const skipped: string[] = [];\n\n // 1. Scan: find the latest non-tombstone event per stream\n const streamInfo = await scanStreamHeads(streams);\n\n // 2. Partition: skip streams with pending reactions in flight\n const safe = await partitionBySafety(\n streamInfo,\n deps.reactiveEventsSize,\n skipped\n );\n if (!safe.length) return { truncated: new Map(), skipped };\n\n // 3. Guard: commit a tombstone with expectedVersion per safe stream.\n // Correlation comes from the orchestrator's configured correlator so\n // close commits share the app's id scheme — see ACT-404.\n const { guarded, guardEvents } = await guardWithTombstones(\n safe,\n streamInfo,\n deps.correlation,\n deps.tombstone,\n skipped\n );\n if (!guarded.length) return { truncated: new Map(), skipped };\n\n // 4. Seed: load final state for restart targets through the owning state\n const seedStates = await loadRestartSeeds(\n guarded,\n targetMap,\n streamInfo,\n deps.eventToState,\n deps.load,\n deps.logger\n );\n\n // 5. Archive: user-provided per-stream callback while guarded\n await runArchiveCallbacks(guarded, targetMap);\n\n // 6. Truncate + seed: atomic per-store transaction\n const truncated = await truncateAndWarmCache(\n guarded,\n seedStates,\n guardEvents,\n deps.correlation\n );\n\n return { truncated, skipped };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 1 — scan stream heads\n// ---------------------------------------------------------------------------\n\nasync function scanStreamHeads(\n streams: string[]\n): Promise<Map<string, StreamHead>> {\n // One round trip: query_stats returns the latest non-snap event per\n // stream (heads-only cheap path, indexed). Streams whose latest non-snap\n // event is a tombstone are filtered out in the loop — we don't want to\n // re-tombstone an already-closed stream. Streams with no events (or\n // only snap/tombstone events filtered out) are absent from the result\n // map entirely.\n const stats = await store().query_stats(streams, {\n exclude: [SNAP_EVENT],\n });\n const out = new Map<string, StreamHead>();\n for (const [stream, { head }] of stats) {\n if (head.name === TOMBSTONE_EVENT) continue;\n out.set(stream, {\n maxId: head.id,\n version: head.version,\n lastEventName: head.name as string,\n });\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2 — partition by safety\n// ---------------------------------------------------------------------------\n\nasync function partitionBySafety(\n streamInfo: Map<string, StreamHead>,\n reactiveEventsSize: number,\n skipped: string[]\n): Promise<string[]> {\n if (reactiveEventsSize === 0) return [...streamInfo.keys()];\n\n // Read-only probe: query_streams returns subscription positions without\n // leasing or mutating retry state.\n const pendingSet = new Set<string>();\n await store().query_streams((position) => {\n const sourceRe = position.source ? RegExp(position.source) : undefined;\n for (const [stream, info] of streamInfo) {\n if ((!sourceRe || sourceRe.test(stream)) && position.at < info.maxId) {\n pendingSet.add(stream);\n }\n }\n });\n\n const safe: string[] = [];\n for (const [stream] of streamInfo) {\n if (pendingSet.has(stream)) skipped.push(stream);\n else safe.push(stream);\n }\n return safe;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 3 — guard with tombstones\n// ---------------------------------------------------------------------------\n\nasync function guardWithTombstones(\n safe: string[],\n streamInfo: Map<string, StreamHead>,\n correlation: string,\n tombstone: EsOps[\"tombstone\"],\n skipped: string[]\n): Promise<{\n guarded: string[];\n guardEvents: Map<string, { id: number; stream: string }>;\n}> {\n const guarded: string[] = [];\n const guardEvents = new Map<string, { id: number; stream: string }>();\n await Promise.all(\n safe.map(async (stream) => {\n const info = streamInfo.get(stream)!;\n const committed = await tombstone(stream, info.version, correlation);\n if (committed) {\n guarded.push(stream);\n guardEvents.set(stream, { id: committed.id, stream });\n } else {\n // ConcurrencyError → another writer beat the guard\n skipped.push(stream);\n }\n })\n );\n return { guarded, guardEvents };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 4 — load restart seeds\n// ---------------------------------------------------------------------------\n\nasync function loadRestartSeeds(\n guarded: string[],\n targetMap: Map<string, CloseTarget>,\n streamInfo: Map<string, StreamHead>,\n eventToState: ReadonlyMap<string, State<any, any, any>>,\n load: EsOps[\"load\"],\n logger: Logger\n): Promise<Map<string, Schema>> {\n const seedStates = new Map<string, Schema>();\n await Promise.all(\n guarded\n .filter((s) => targetMap.get(s)?.restart)\n .map(async (stream) => {\n // streamInfo entry is guaranteed (guarded ⊆ streamInfo.keys()).\n const lastEventName = streamInfo.get(stream)!.lastEventName;\n const ownerState = eventToState.get(lastEventName);\n if (!ownerState) {\n // No registered state owns the stream's events (deleted state,\n // schema versioning gone wrong, etc.). Tombstone instead of\n // seeding a corrupted snapshot.\n logger.error(\n `Cannot seed restart for \"${stream}\": no registered state owns event \"${lastEventName}\". Stream will be tombstoned instead.`\n );\n return;\n }\n const snap = await load(ownerState, stream);\n seedStates.set(stream, snap.state as Schema);\n })\n );\n return seedStates;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 5 — archive callbacks\n// ---------------------------------------------------------------------------\n\nasync function runArchiveCallbacks(\n guarded: string[],\n targetMap: Map<string, CloseTarget>\n): Promise<void> {\n // Sequential — user callbacks may share resources (S3 client, etc.) and\n // a failure should propagate to the caller without leaving partial state.\n for (const stream of guarded) {\n const archiveFn = targetMap.get(stream)?.archive;\n if (archiveFn) await archiveFn();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Phase 6 — atomic truncate + cache warm\n// ---------------------------------------------------------------------------\n\nasync function truncateAndWarmCache(\n guarded: string[],\n seedStates: Map<string, Schema>,\n guardEvents: Map<string, { id: number; stream: string }>,\n correlation: string\n): Promise<CloseResult[\"truncated\"]> {\n const truncTargets = guarded.map((stream) => {\n const snapshot = seedStates.get(stream);\n const guard = guardEvents.get(stream)!;\n return {\n stream,\n snapshot,\n meta: {\n correlation,\n causation: {\n event: { id: guard.id, name: TOMBSTONE_EVENT, stream: guard.stream },\n },\n },\n };\n });\n const truncated = await store().truncate(truncTargets);\n\n // Cache invalidate / warm — use real event IDs from committed events\n await Promise.all(\n guarded.map(async (stream) => {\n const entry = truncated.get(stream);\n const state = seedStates.get(stream);\n if (state && entry) {\n await cache().set(stream, {\n state,\n version: entry.committed.version,\n event_id: entry.committed.id,\n patches: 0,\n snaps: 1,\n });\n } else {\n await cache().invalidate(stream);\n }\n })\n );\n\n return truncated;\n}\n","/**\n * @module correlate-cycle\n * @category Internal\n *\n * Correlation — the discovery half of the correlate→drain pair. Owns the\n * lazy init (subscribe static targets, read cold-start watermark), the\n * dynamic-resolver scan that registers new streams as events arrive, and\n * the periodic timer that drives background discovery.\n *\n * The Act orchestrator passes registry + classification (which static\n * targets to subscribe, whether any dynamic resolvers exist) at build\n * time; everything past that lives here.\n *\n * @internal\n */\n\nimport { log, store } from \"../ports.js\";\nimport type {\n Query,\n ReactionPayload,\n Registry,\n SchemaRegister,\n Schemas,\n} from \"../types/index.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport { LruSet } from \"./lru-map.js\";\n\n/**\n * Static resolver target collected at build time. Subscribed once during\n * init; never re-evaluated.\n *\n * @property priority - Scheduling priority for the resolved target stream.\n * Combined with peers via `max()` at build time when multiple reactions\n * target the same stream — see `build-classify.ts`.\n *\n * @internal\n */\nexport type StaticTarget = {\n readonly stream: string;\n readonly source?: string;\n readonly priority?: number;\n readonly lane?: string;\n};\n\n/**\n * Drives correlation for one Act instance. Owns the checkpoint, the\n * subscribed-streams LRU, and the periodic timer.\n *\n * @internal\n */\nexport class CorrelateCycle<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n> {\n private _checkpoint = -1;\n private _initialized = false;\n private _timer: ReturnType<typeof setInterval> | undefined = undefined;\n private readonly _subscribed: LruSet<string>;\n\n constructor(\n private readonly registry: Registry<TSchemaReg, TEvents, TActions>,\n private readonly staticTargets: ReadonlyArray<StaticTarget>,\n private readonly hasDynamicResolvers: boolean,\n private readonly cd: DrainOps<TEvents>,\n maxSubscribedStreams: number,\n private readonly onInit?: () => void\n ) {\n this._subscribed = new LruSet(maxSubscribedStreams);\n }\n\n /** Last correlated event id. */\n get checkpoint(): number {\n return this._checkpoint;\n }\n\n /**\n * Initialize correlation state on first call.\n * - Reads max(at) from store as cold-start checkpoint\n * - Subscribes static resolver targets (idempotent upsert)\n * - Populates the subscribed-streams LRU\n * - Fires `onInit` once (Act uses this to flag a cold-start drain)\n */\n async init(): Promise<void> {\n if (this._initialized) return;\n this._initialized = true;\n\n const { watermark } = await store().subscribe([...this.staticTargets]);\n this._checkpoint = watermark;\n this.onInit?.();\n for (const { stream } of this.staticTargets) {\n this._subscribed.add(stream);\n }\n }\n\n /**\n * Discover dynamic-resolver targets in the events past the checkpoint\n * and register any new streams via `cd.subscribe`. Static targets are\n * subscribed at init time, so this only walks dynamic resolvers.\n */\n async correlate(\n query: Query = { after: -1, limit: 10 }\n ): Promise<{ subscribed: number; last_id: number }> {\n await this.init();\n\n // No dynamic resolvers — nothing to discover\n if (!this.hasDynamicResolvers)\n return { subscribed: 0, last_id: this._checkpoint };\n\n // Use checkpoint as floor, allow explicit query.after to override upward\n const after = Math.max(this._checkpoint, query.after || -1);\n const correlated = new Map<\n string,\n {\n source?: string;\n priority: number;\n lane?: string;\n payloads: ReactionPayload<TEvents>[];\n }\n >();\n let last_id = after;\n await store().query<TEvents>(\n (event) => {\n last_id = event.id;\n const register = this.registry.events[event.name];\n // skip events with no registered reactions\n if (register) {\n for (const reaction of register.reactions.values()) {\n // only evaluate dynamic resolvers — statics are subscribed at init\n if (typeof reaction.resolver !== \"function\") continue;\n const resolved = reaction.resolver(event);\n if (resolved && !this._subscribed.has(resolved.target)) {\n const incomingPriority = resolved.priority ?? 0;\n const entry = correlated.get(resolved.target) || {\n source: resolved.source,\n priority: incomingPriority,\n lane: resolved.lane,\n payloads: [],\n };\n // Multiple reactions targeting the same stream within a\n // single correlate scan — keep the max priority so the\n // highest-priority reaction sets the lane (matches the\n // subscribe-side `max()` invariant).\n if (incomingPriority > entry.priority)\n entry.priority = incomingPriority;\n entry.payloads.push({\n ...reaction,\n source: resolved.source,\n event,\n });\n correlated.set(resolved.target, entry);\n }\n }\n }\n },\n { ...query, after }\n );\n\n if (correlated.size) {\n const streams = [...correlated.entries()].map(\n ([stream, { source, priority, lane }]) => ({\n stream,\n source,\n priority,\n lane,\n })\n );\n const { subscribed } = await this.cd.subscribe(streams);\n // Advance checkpoint only after subscribe succeeds\n this._checkpoint = last_id;\n if (subscribed) {\n // Track newly subscribed dynamic targets\n for (const { stream } of streams) {\n this._subscribed.add(stream);\n }\n }\n return { subscribed, last_id };\n }\n // No streams to subscribe — safe to advance\n this._checkpoint = last_id;\n return { subscribed: 0, last_id };\n }\n\n /**\n * Start a periodic correlation worker. Returns false if one is already\n * running. Errors from `correlate()` are routed through `log()` so they\n * land in the configured logger (the timer keeps running on failure).\n */\n startPolling(\n query: Query = {},\n frequency = 10_000,\n callback?: (subscribed: number) => void\n ): boolean {\n if (this._timer) return false;\n\n const limit = query.limit || 100;\n this._timer = setInterval(\n () =>\n this.correlate({ ...query, after: this._checkpoint, limit })\n .then((result) => {\n if (callback && result.subscribed) callback(result.subscribed);\n })\n .catch((err) => log().error(err)),\n frequency\n );\n return true;\n }\n\n /** Stop the periodic correlation worker. Idempotent. */\n stopPolling(): void {\n if (this._timer) {\n clearInterval(this._timer);\n this._timer = undefined;\n }\n }\n}\n","/**\n * @module correlator\n * @category Internal\n *\n * Correlation-id generator and the default implementation (ACT-404).\n *\n * The default produces a readable, time-monotonic-within-window, lowercase\n * id like `coun-incr-lwxk9p3a` — short enough to scan in logs, structured\n * enough to identify the originating state/action, and well-distributed\n * enough that competing-consumer workers don't collide.\n *\n * Apps override via {@link ActOptions.correlator} to plug in any scheme\n * (tenant-prefixed, trace-id-propagated, DB-sequence-backed, etc.).\n *\n * @internal\n */\n\nimport { randomInt } from \"node:crypto\";\nimport type { Actor, Correlator } from \"../types/index.js\";\n\nconst BASE = 36;\nconst SEG_WIDTH = 4;\nconst SEG_SPACE = BASE ** SEG_WIDTH;\n\nfunction seg(n: number): string {\n return n.toString(BASE).padStart(SEG_WIDTH, \"0\");\n}\n\n/**\n * Default {@link Correlator}. Produces ids of the form\n * `{state[:4]}-{action[:4]}-{4 ms}{4 random}` — 18 characters, lowercase\n * base36.\n *\n * - Prefix carries human-meaningful context (state + action) so operators\n * can identify a workflow at a glance in logs and query results.\n * - The 4-character `Date.now() % 36^4` segment wraps every ~28 minutes,\n * long enough that adjacent inserts in a typical workflow share B-tree\n * pages — index locality, not global sortability, is the goal.\n * - The 4-character random tail gives 1.68M values per ms; collision risk\n * across K=100 concurrent workers is roughly K² / 3.4M per ms.\n *\n * Names shorter than 4 chars are used as-is (no padding) so a state named\n * `Tx` produces `tx-...` rather than `tx00-...`.\n */\nexport const defaultCorrelator: Correlator = ({ state, action }) => {\n const s = state.slice(0, SEG_WIDTH).toLowerCase();\n const a = action.slice(0, SEG_WIDTH).toLowerCase();\n const ts = seg(Date.now() % SEG_SPACE);\n const rnd = seg(randomInt(SEG_SPACE));\n return `${s}-${a}-${ts}${rnd}`;\n};\n\n/**\n * Resolves the correlation id for the close-the-books transaction.\n * Close runs outside any user action, so we synthesize a context with\n * sentinel state/action names — visible in the id when overrides aren't\n * configured.\n *\n * @internal\n */\nexport function closeCorrelation(correlator: Correlator, actor: Actor): string {\n return correlator({\n state: \"$close\",\n action: \"close\",\n stream: \"$close\",\n actor,\n });\n}\n","/**\n * @module drain-cycle\n * @category Internal\n *\n * Two layers of the drain pipeline:\n *\n * - {@link runDrainCycle} — pure function for one round-trip of\n * claim → fetch → group → dispatch → ack/block. No orchestrator state.\n * Reusable for property tests and standalone benchmarks.\n *\n * - {@link DrainController} — stateful driver that owns the armed flag,\n * the concurrency lock, and the adaptive lag/lead ratio. Wraps\n * `runDrainCycle` with the lifecycle decisions Act used to make inline.\n *\n * @internal\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type {\n BatchHandler,\n BlockedLease,\n Drain,\n DrainOptions,\n Fetch,\n Lease,\n Logger,\n ReactionPayload,\n Registry,\n SchemaRegister,\n Schemas,\n} from \"../types/index.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport { computeLagLeadRatio } from \"./drain-ratio.js\";\nimport { traceCycle } from \"./tracing.js\";\n\n/**\n * Outcome of processing a single leased stream — produced by Act's `handle`\n * / `handleBatch` dispatchers, consumed by `runDrainCycle` to drive ack/block.\n *\n * @internal\n */\nexport type HandleResult = Readonly<{\n lease: Lease;\n handled: number;\n /**\n * Event id at which the ack would land — the last *successful* event\n * id, or `lease.at` when the batch had no work (empty payloads). Named\n * `acked_at` to pair symmetrically with {@link failed_at} and to keep\n * it visually distinct from `Lease.at` (the pre-cycle watermark — same\n * field name across types but a different semantic).\n */\n acked_at: number;\n error?: string;\n block?: boolean;\n /**\n * Wall-clock timestamp (ms since epoch) at which the next attempt on\n * this stream may run. Populated by `_finalize` only on retry paths\n * where the reaction defined `options.backoff`. Undefined means \"no\n * backoff configured\" — drain re-attempts as soon as the lease expires.\n */\n nextAttemptAt?: number;\n /**\n * Event id that threw, when a handler error occurred. Distinct from\n * {@link acked_at}: `failed_at = acked_at + 1` in dense streams, but\n * adapters with sparse ids give the trace the exact position. Always\n * set on the per-event error path; absent in batch mode (where no\n * single event id can be attributed to the failure).\n */\n failed_at?: number;\n}>;\n\n/**\n * Per-event reaction dispatcher signature (matches `Act.handle`).\n * @internal\n */\nexport type Handle<TEvents extends Schemas> = (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[]\n) => Promise<HandleResult>;\n\n/**\n * Bulk reaction dispatcher signature (matches `Act.handleBatch`).\n * @internal\n */\nexport type HandleBatch<TEvents extends Schemas> = (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[],\n batchHandler: BatchHandler<TEvents>\n) => Promise<HandleResult>;\n\n/**\n * One drain cycle's results. Returned by {@link runDrainCycle}; consumed by\n * `Act.drain()` to update lifecycle state, the lag/lead ratio, and emit the\n * `acked` / `blocked` lifecycle events.\n *\n * @internal\n */\nexport type DrainCycle<TEvents extends Schemas> = {\n readonly leased: Lease[];\n readonly fetched: Fetch<TEvents>;\n readonly handled: HandleResult[];\n readonly acked: Lease[];\n readonly blocked: BlockedLease[];\n};\n\n/**\n * Run one drain cycle: claim streams, fetch their events, dispatch\n * matching reactions, ack the successes, block the retries-exhausted.\n *\n * Returns `undefined` when nothing was claimed — caller can short-circuit\n * the rest of the drain pass.\n *\n * **Deferred streams.** When `isDeferred(stream)` returns `true`, the\n * cycle skips dispatch for that lease — no handle, no ack, no block. The\n * lease holds for `leaseMillis` via the existing claim mechanism, which\n * blocks competing workers from re-attempting during the backoff window\n * and serves as the per-worker pacing timer. Subsequent claims after\n * `leased_until` expires will re-acquire the lease and re-skip until the\n * controller clears the entry.\n *\n * @internal\n */\nexport async function runDrainCycle<\n TEvents extends Schemas,\n TActions extends Schemas,\n TSchemaReg extends SchemaRegister<TActions>,\n>(\n ops: DrainOps<TEvents>,\n registry: Registry<TSchemaReg, TEvents, TActions>,\n batchHandlers: Map<string, BatchHandler<TEvents>>,\n handle: Handle<TEvents>,\n handleBatch: HandleBatch<TEvents>,\n lagging: number,\n leading: number,\n eventLimit: number,\n leaseMillis: number,\n isDeferred?: (stream: string) => boolean,\n lane?: string\n): Promise<DrainCycle<TEvents> | undefined> {\n // Atomically discover and lease streams (competing consumer pattern)\n const leased = await ops.claim(\n lagging,\n leading,\n randomUUID(),\n leaseMillis,\n lane\n );\n if (!leased.length) return undefined;\n\n // Partition out streams whose handler is in a backoff window. We hold\n // their leases (no ack/block) so competing workers can't re-attempt\n // during the configured delay.\n const active = isDeferred\n ? leased.filter((l) => !isDeferred(l.stream))\n : leased;\n if (!active.length) {\n return {\n leased,\n fetched: [],\n handled: [],\n acked: [],\n blocked: [],\n };\n }\n\n // Fetch events for each active leased stream\n const fetched = await ops.fetch(active, eventLimit);\n\n // Build a single index keyed by stream — collapses two passes\n // (payloadsMap build + per-lease fetched.find) into one Map lookup.\n type FetchEntry = (typeof fetched)[number];\n const fetchMap = new Map<\n string,\n { fetch: FetchEntry; payloads: ReactionPayload<TEvents>[] }\n >();\n\n // compute fetch window max event id\n const fetch_window_at = fetched.reduce(\n (max, { at, events }) => Math.max(max, events.at(-1)?.id || at),\n 0\n );\n\n for (const f of fetched) {\n const { stream, events } = f;\n const payloads = events.flatMap((event) => {\n const register = registry.events[event.name];\n if (!register) return [];\n return [...register.reactions.values()]\n .filter((reaction) => {\n const resolved =\n typeof reaction.resolver === \"function\"\n ? reaction.resolver(event)\n : reaction.resolver;\n return resolved && resolved.target === stream;\n })\n .map((reaction) => ({ ...reaction, event }));\n });\n fetchMap.set(stream, { fetch: f, payloads });\n }\n\n const handled = await Promise.all(\n active.map((lease) => {\n // fetch() returns one entry per leased stream — fetchMap.get is\n // always defined here (asserted with `!`).\n const entry = fetchMap.get(lease.stream)!;\n // fast-forward watermark using fetched events or window max\n const at = entry.fetch.events.at(-1)?.id || fetch_window_at;\n const { payloads } = entry;\n const batchHandler = batchHandlers.get(lease.stream);\n if (batchHandler && payloads.length > 0) {\n return handleBatch({ ...lease, at }, payloads, batchHandler);\n }\n return handle({ ...lease, at }, payloads);\n })\n );\n\n // Ack any result that made progress — full success (no error), empty\n // payloads (no work to do, watermark fast-forwards), and partial\n // success (some events processed before the failure). The `error`\n // string is no longer the \"skip ack\" signal; `handled > 0 || !error`\n // is. Partial-success-then-block now lands in both `acked` and\n // `blocked` arrays for the same stream — by design.\n const acked = await ops.ack(\n handled\n .filter((h) => h.handled > 0 || !h.error)\n .map((h) => ({ ...h.lease, at: h.acked_at }))\n );\n\n const blocked = await ops.block(\n handled\n .filter(({ block }) => block)\n .map(({ lease, error }) => ({ ...lease, error: error! }))\n );\n\n return { leased, fetched, handled, acked, blocked };\n}\n\n/**\n * Empty drain result returned when the controller short-circuits (not\n * armed, locked out by a concurrent caller, claim returned nothing,\n * cycle threw).\n *\n * @internal\n */\nconst EMPTY_DRAIN: Drain<Schemas> = {\n fetched: [],\n leased: [],\n acked: [],\n blocked: [],\n};\n\n/**\n * Dependencies the {@link DrainController} needs from the orchestrator.\n * The lifecycle event sinks (`onAcked` / `onBlocked`) are callbacks so\n * this module doesn't reach back into Act's emitter.\n *\n * @internal\n */\nexport type DrainControllerDeps<\n TEvents extends Schemas,\n TActions extends Schemas,\n TSchemaReg extends SchemaRegister<TActions>,\n> = {\n readonly logger: Logger;\n readonly ops: DrainOps<TEvents>;\n readonly registry: Registry<TSchemaReg, TEvents, TActions>;\n readonly batchHandlers: Map<string, BatchHandler<TEvents>>;\n readonly handle: Handle<TEvents>;\n readonly handleBatch: HandleBatch<TEvents>;\n readonly onAcked: (acked: Lease[]) => void;\n readonly onBlocked: (blocked: BlockedLease[]) => void;\n /** Lane this controller drains. Undefined = spans all lanes (legacy single-controller). */\n readonly lane?: string;\n /** Per-lane defaults applied when caller doesn't override via DrainOptions. */\n readonly defaults?: {\n readonly streamLimit?: number;\n readonly eventLimit?: number;\n readonly leaseMillis?: number;\n };\n};\n\n/**\n * Stateful driver around {@link runDrainCycle}. Owns:\n *\n * - `_armed` — has any commit / reset / cold-start signaled work to do?\n * - `_locked` — concurrent-call guard (overlapping `drain()` calls return\n * an empty result instead of running twice)\n * - `_ratio` — adaptive lag-to-lead frontier split, updated per cycle\n *\n * The orchestrator owns commits, lifecycle emission, and `arm()` triggers\n * — the controller owns everything between those edges.\n *\n * @internal\n */\nexport class DrainController<\n TEvents extends Schemas,\n TActions extends Schemas,\n TSchemaReg extends SchemaRegister<TActions>,\n> {\n private _armed = false;\n private _locked = false;\n private _ratio = 0.5;\n /**\n * Per-stream backoff: `stream → nextAttemptAt` (ms since epoch). Set by\n * `_finalize` via `HandleResult.nextAttemptAt`; cleared on successful\n * ack or terminal block. Lives in process memory — per-worker pacing\n * by design (see {@link BackoffOptions} for the multi-worker trade-off).\n */\n private _backoff = new Map<string, number>();\n /** Timer re-arming drain at the earliest pending `nextAttemptAt`. */\n private _backoffTimer: ReturnType<typeof setTimeout> | undefined;\n /** Worker timer (ACT-1103). Set when `start()` is active, undefined otherwise. */\n private _worker: ReturnType<typeof setTimeout> | undefined;\n private _stopped = false;\n\n constructor(\n private readonly deps: DrainControllerDeps<TEvents, TActions, TSchemaReg>\n ) {}\n\n /**\n * Signal that a commit (or reset / cold-start) may have produced work.\n * Subsequent `drain()` calls will run the pipeline; once the pipeline\n * settles to no-progress, the controller disarms itself.\n */\n arm(): void {\n this._armed = true;\n }\n\n /** Read-only flag — true while a commit / reset is unprocessed. */\n get armed(): boolean {\n return this._armed;\n }\n\n /** Returns true when `stream` is currently within a backoff window. */\n private isDeferred = (stream: string): boolean => {\n const next = this._backoff.get(stream);\n return next !== undefined && next > Date.now();\n };\n\n /**\n * Schedule the next drain re-arm at the earliest pending backoff\n * expiry. Called only when the backoff map is non-empty (caller guard).\n * Idempotent — collapses many simultaneously deferred streams into a\n * single timer.\n */\n private scheduleBackoffWake(): void {\n if (this._backoffTimer) clearTimeout(this._backoffTimer);\n let earliest = Number.POSITIVE_INFINITY;\n for (const t of this._backoff.values()) if (t < earliest) earliest = t;\n const delay = Math.max(0, earliest - Date.now());\n this._backoffTimer = setTimeout(() => {\n this._backoffTimer = undefined;\n // Garbage-collect expired entries so the next cycle sees ready\n // streams as active. Drain will be re-triggered by whoever owns the\n // settle loop (or by the next commit). Re-arm here so a debounced\n // settle picks it up.\n const now = Date.now();\n for (const [stream, at] of this._backoff) {\n if (at <= now) this._backoff.delete(stream);\n }\n this._armed = true;\n }, delay);\n // Don't keep the event loop alive solely for backoff timers — letting\n // a process exit during retry pacing is the right default. Safe to call\n // unconditionally: Node's `setTimeout` always returns a Timeout with\n // `unref()`.\n this._backoffTimer.unref();\n }\n\n /** Lane this controller drains (undefined = legacy single-lane span). */\n get lane(): string | undefined {\n return this.deps.lane;\n }\n\n /**\n * Start a per-lane worker that drains at the lane's `cycleMs`\n * cadence (ACT-1103). When armed, the worker calls `drain()` on every\n * tick and re-schedules; when not armed, it still re-schedules at\n * `cycleMs` so a future `arm()` is picked up on the next tick.\n *\n * The setTimeout chain uses `unref()` so it doesn't keep the process\n * alive on its own.\n */\n start(cycleMs: number): void {\n if (this._worker || this._stopped) return;\n // `drain()` swallows its own errors and returns EMPTY_DRAIN, so the\n // tick is exception-free by contract. The post-drain `_stopped`\n // check prevents re-scheduling after `stop()` was called mid-tick;\n // an already-queued timer that fires before `clearTimeout()` lands\n // will run at most one extra drain (drain is idempotent against\n // a non-armed controller and self-disarms when settled).\n const tick = async () => {\n if (this._armed) await this.drain();\n if (this._stopped) return;\n this._worker = setTimeout(tick, cycleMs);\n this._worker.unref();\n };\n this._worker = setTimeout(tick, cycleMs);\n this._worker.unref();\n }\n\n /** Stop the per-lane worker. Idempotent. */\n stop(): void {\n this._stopped = true;\n if (this._worker) {\n clearTimeout(this._worker);\n this._worker = undefined;\n }\n }\n\n /** Run one drain pass. Short-circuits when not armed or already running. */\n async drain(options: DrainOptions = {}): Promise<Drain<TEvents>> {\n if (!this._armed) return EMPTY_DRAIN as Drain<TEvents>;\n if (this._locked) return EMPTY_DRAIN as Drain<TEvents>;\n\n const d = this.deps.defaults ?? {};\n // Per-lane config wins over caller options (ACT-1103). The whole\n // point of `withLane({leaseMillis: 30_000})` is to give the slow\n // lane its own budget — a caller-level drain({leaseMillis}) would\n // erase it. Caller options apply only when the lane didn't pin a\n // value.\n const streamLimit = d.streamLimit ?? options.streamLimit ?? 10;\n const eventLimit = d.eventLimit ?? options.eventLimit ?? 10;\n const leaseMillis = d.leaseMillis ?? options.leaseMillis ?? 10_000;\n\n try {\n this._locked = true;\n const lagging = Math.ceil(streamLimit * this._ratio);\n const leading = streamLimit - lagging;\n\n const cycle = await runDrainCycle(\n this.deps.ops,\n this.deps.registry,\n this.deps.batchHandlers,\n this.deps.handle,\n this.deps.handleBatch,\n lagging,\n leading,\n eventLimit,\n leaseMillis,\n this._backoff.size > 0 ? this.isDeferred : undefined,\n this.deps.lane\n );\n\n if (!cycle) {\n // claim() returned no leases — fully caught up\n this._armed = false;\n return EMPTY_DRAIN as Drain<TEvents>;\n }\n\n const { leased, fetched, handled, acked, blocked } = cycle;\n\n // Cycle-level trace (ACT-1103) — one log line per drain pass:\n // claim + fetch + outcomes folded together so the operator sees\n // a single atomic narrative for each cycle. No-op when the\n // logger isn't at trace level.\n traceCycle(this.deps.logger, leased, fetched, handled, acked, blocked);\n\n // Adapt next cycle's frontier split to where the pressure is.\n this._ratio = computeLagLeadRatio(handled, lagging, leading);\n\n // Refresh per-stream backoff state from this cycle's outcomes.\n // Successful acks and terminal blocks both clear the window;\n // retry-not-block results carry a `nextAttemptAt` set by `_finalize`.\n for (const lease of acked) this._backoff.delete(lease.stream);\n for (const lease of blocked) this._backoff.delete(lease.stream);\n for (const h of handled) {\n if (h.nextAttemptAt !== undefined && !h.block) {\n this._backoff.set(h.lease.stream, h.nextAttemptAt);\n }\n }\n if (this._backoff.size > 0) this.scheduleBackoffWake();\n\n if (acked.length) this.deps.onAcked(acked);\n if (blocked.length) this.deps.onBlocked(blocked);\n\n // Disarm only when fully caught up. Errors keep the flag set so\n // retries flow through the next drain.\n const hasErrors = handled.some(({ error }) => error);\n if (!acked.length && !blocked.length && !hasErrors) this._armed = false;\n\n return { fetched, leased, acked, blocked };\n } catch (error) {\n this.deps.logger.error(error);\n return EMPTY_DRAIN as Drain<TEvents>;\n } finally {\n this._locked = false;\n }\n }\n}\n","/**\n * @module drain-ratio\n * @category Internal\n *\n * Adaptive lag-to-lead ratio for the dual-frontier drain strategy.\n *\n * The orchestrator splits its per-cycle stream budget between two frontiers:\n *\n * - **lagging** — newly subscribed or behind streams catching up.\n * - **leading** — actively-processing streams at the head of the log.\n *\n * After each cycle, this helper looks at how many events were actually\n * handled in each frontier and shifts the next cycle's split toward\n * whichever frontier had the higher per-stream throughput. The result is\n * clamped to `[0.2, 0.8]` so neither frontier can be starved.\n *\n * @internal\n */\n\nimport type { HandleResult } from \"./drain-cycle.js\";\n\n/** Floor / ceiling for the lag-to-lead ratio so neither frontier starves. */\nconst RATIO_MIN = 0.2;\nconst RATIO_MAX = 0.8;\n/** Default ratio when no events were handled in either frontier. */\nconst RATIO_DEFAULT = 0.5;\n\n/**\n * Compute the next lag-to-lead ratio from the cycle's handled events and\n * the frontier sizes used to claim them. Returns `RATIO_DEFAULT` when no\n * progress was made (nothing to base a decision on).\n */\nexport function computeLagLeadRatio(\n handled: ReadonlyArray<HandleResult>,\n lagging: number,\n leading: number\n): number {\n let lagging_handled = 0;\n let leading_handled = 0;\n for (const { lease, handled: count } of handled) {\n if (lease.lagging) lagging_handled += count;\n else leading_handled += count;\n }\n const lagging_avg = lagging > 0 ? lagging_handled / lagging : 0;\n const leading_avg = leading > 0 ? leading_handled / leading : 0;\n const total = lagging_avg + leading_avg;\n if (total === 0) return RATIO_DEFAULT;\n return Math.max(RATIO_MIN, Math.min(RATIO_MAX, lagging_avg / total));\n}\n","/**\n * @module drain\n * @category Internal\n *\n * Pipeline operations consumed by the drain/correlate loop. Each op is a\n * single async step the orchestrator invokes per drain cycle:\n *\n * - `claim` — atomically discover and lock streams for processing\n * - `fetch` — read events for each leased stream\n * - `ack` — release leases for successfully handled streams\n * - `block` — flag leases that exceeded the retry budget\n * - `subscribe` — register newly correlated streams with the store\n *\n * This module exposes only the bare implementations as plain async functions,\n * mirroring the shape of {@link \"event-sourcing\"}. Trace decoration is\n * layered on top in {@link \"tracing\"} and selected by the orchestrator at\n * construction time. No tracing imports here.\n *\n * @internal\n */\n\nimport { store } from \"../ports.js\";\nimport type {\n BlockedLease,\n Committed,\n Fetch,\n Lease,\n Schemas,\n} from \"../types/index.js\";\n\n/** @internal */\nexport interface DrainOps<TEvents extends Schemas> {\n claim: typeof claim;\n fetch: typeof fetch<TEvents>;\n ack: typeof ack;\n block: typeof block;\n subscribe: typeof subscribe;\n}\n\nexport const claim = (\n lagging: number,\n leading: number,\n by: string,\n millis: number,\n lane?: string\n): Promise<Lease[]> => store().claim(lagging, leading, by, millis, lane);\n\nexport async function fetch<TEvents extends Schemas>(\n leased: Lease[],\n eventLimit: number\n): Promise<Fetch<TEvents>> {\n return Promise.all(\n leased.map(async ({ stream, source, at, lagging }) => {\n const events: Committed<TEvents, keyof TEvents>[] = [];\n await store().query<TEvents>((e) => events.push(e), {\n stream: source,\n after: at,\n limit: eventLimit,\n });\n return { stream, source, at, lagging, events } as const;\n })\n );\n}\n\nexport const ack = (leases: Lease[]): Promise<Lease[]> => store().ack(leases);\n\nexport const block = (leases: BlockedLease[]): Promise<BlockedLease[]> =>\n store().block(leases);\n\nexport const subscribe = (\n streams: Array<{\n stream: string;\n source?: string;\n priority?: number;\n lane?: string;\n }>\n): Promise<{ subscribed: number; watermark: number }> =>\n store().subscribe(streams);\n","/**\n * @module event-sourcing\n * @category Internal\n *\n * Pure event-sourcing primitives: `snap` persists state checkpoints, `load`\n * reconstructs state by replaying events through reducers, and `action`\n * validates an action, runs invariants, emits events, and commits them\n * atomically. `tombstone` commits the close-the-books guard with optimistic\n * concurrency.\n *\n * These are the bare implementations — observability is layered on top in\n * {@link \"tracing\"} and wired by the orchestrator at construction time.\n * No tracing imports here, no module-level mutable state.\n *\n * @internal\n */\n\nimport { patch } from \"@rotorsoft/act-patch\";\nimport { cache, log, SNAP_EVENT, store, TOMBSTONE_EVENT } from \"../ports.js\";\nimport {\n ConcurrencyError,\n InvariantError,\n StreamClosedError,\n} from \"../types/errors.js\";\nimport type {\n AsOf,\n Committed,\n Correlator,\n Emitted,\n EventMeta,\n EventSource,\n Query,\n ScanOptions,\n ScanResult,\n Schema,\n Schemas,\n Snapshot,\n State,\n Target,\n} from \"../types/index.js\";\nimport { validate } from \"../utils.js\";\nimport { defaultCorrelator } from \"./correlator.js\";\n\n/**\n * Bridge an {@link EventSource} into an `AsyncIterable<Committed>`\n * with 1-event-in-flight backpressure (ACT-1128). Internal helper\n * for the {@link scan} loop — the producer (`source.query`) awaits\n * a promise that the bridge resolves only when the consumer takes\n * the event from the mailbox, so memory in the bridge is bounded\n * to exactly one event.\n *\n * Downstream realization of backpressure depends on the adapter's\n * `query` implementation. Every in-tree adapter still buffers its\n * full result set internally before calling the callback (e.g.,\n * `pg.query` resolves with `rows[]`); the mailbox-on-top of that\n * adds bounded buffering downstream of the result set. True\n * cursor-based streaming on the adapter side is tracked in #814\n * (ACT-1132).\n *\n * @internal\n */\nexport async function* iterate(\n source: EventSource,\n filter?: Query\n): AsyncIterable<Committed<Schemas, keyof Schemas>> {\n // Wrapping the state in an object prevents TypeScript from\n // narrowing the let-bound `null` initializer through the\n // triple-closure-deep assignment path; behavior is unchanged.\n type WakeFn = () => void;\n const state: {\n slot: Committed<Schemas, keyof Schemas> | null;\n onProduce: WakeFn | null;\n onConsume: WakeFn | null;\n done: boolean;\n error: unknown;\n } = {\n slot: null,\n onProduce: null,\n onConsume: null,\n done: false,\n error: undefined,\n };\n\n const wakeProduce = () => {\n const fn = state.onProduce;\n state.onProduce = null;\n if (fn) fn();\n };\n\n void source\n .query<Schemas>((event) => {\n state.slot = event;\n wakeProduce();\n return new Promise<void>((resolve) => {\n state.onConsume = () => resolve();\n });\n }, filter)\n .then(\n () => {\n state.done = true;\n wakeProduce();\n },\n (err) => {\n state.error = err;\n state.done = true;\n wakeProduce();\n }\n );\n\n while (true) {\n if (state.slot === null && !state.done)\n await new Promise<void>((resolve) => {\n state.onProduce = resolve;\n });\n if (state.error) throw state.error;\n if (state.slot === null) return;\n const event = state.slot;\n state.slot = null;\n const fn = state.onConsume!;\n state.onConsume = null;\n fn();\n yield event;\n }\n}\n\n/**\n * Internal action signature seen by the orchestrator — the {@link Correlator}\n * is bound at `buildEs` time, so callers don't pass it through.\n *\n * @internal\n */\nexport type BoundAction = <\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n>(\n me: State<TState, TEvents, TActions>,\n action: TKey,\n target: Target,\n payload: Readonly<TActions[TKey]>,\n reactingTo?: Committed<Schemas, keyof Schemas>,\n skipValidation?: boolean\n) => Promise<Snapshot<TState, TEvents>[]>;\n\n/** @internal */\nexport interface EsOps {\n snap: typeof snap;\n load: typeof load;\n action: BoundAction;\n tombstone: typeof tombstone;\n}\n\n/**\n * Event sourcing utilities for snapshotting, loading, and committing actions/events.\n * Used internally by Act and state machines.\n */\n\n/**\n * Saves a snapshot of the state to the store.\n *\n * Snapshots are used to optimize state reconstruction for aggregates with long event streams.\n *\n * @template TState The type of state\n * @template TEvents The type of events\n * @param snapshot The snapshot to save\n * @returns Promise that resolves when the snapshot is saved\n *\n * @example\n * await snap(snapshot);\n */\nexport async function snap<TState extends Schema, TEvents extends Schemas>(\n snapshot: Snapshot<TState, TEvents>\n): Promise<void> {\n try {\n const { id, stream, name, meta, version } = snapshot.event!;\n await store().commit(\n stream,\n [{ name: SNAP_EVENT, data: snapshot.state }],\n {\n correlation: meta.correlation,\n causation: { event: { id, name: name as string, stream } },\n },\n version // IMPORTANT! - state events are committed right after the snapshot event\n );\n } catch (error) {\n log().error(error);\n }\n}\n\n/**\n * Commits a tombstone event with optimistic concurrency, returning the\n * committed record on success or `undefined` if the stream moved past\n * `expectedVersion` (concurrent write detected). Other store errors\n * propagate.\n *\n * Used by `close()` to guard a stream while archive/truncate runs:\n * subsequent `action()` calls see the tombstone at head and reject with\n * {@link StreamClosedError} until the close completes.\n *\n * @internal\n */\nexport async function tombstone(\n stream: string,\n expectedVersion: number,\n correlation: string\n): Promise<Committed<Schemas, keyof Schemas> | undefined> {\n try {\n const [committed] = await store().commit(\n stream,\n [{ name: TOMBSTONE_EVENT, data: {} }],\n { correlation, causation: {} },\n expectedVersion\n );\n return committed;\n } catch (error) {\n if (error instanceof ConcurrencyError) return undefined;\n throw error;\n }\n}\n\n/**\n * Per-event blocker check. Categories:\n *\n * - **Negative `version`** — versions are unsigned in the framework\n * contract.\n * - **Malformed `created`** — `event.created` must be a valid Date\n * instance. Restore sources stream parsed events; the orchestrator\n * trusts the caller's iterator did the parsing.\n *\n * Cross-event invariants (duplicate ids, per-stream version gaps) are\n * not the validator's job — DB `UNIQUE(stream, version)` catches\n * duplicates at commit time, and gap detection is a caller-specific\n * policy (partial backups intentionally have gaps).\n *\n * @internal\n */\nfunction isValid(event: Committed<Schemas, keyof Schemas>): boolean {\n if (event.version < 0) return false;\n if (!(event.created instanceof Date) || Number.isNaN(event.created.getTime()))\n return false;\n return true;\n}\n\n/**\n * Scan a restore source event by event. Owns iteration, validation,\n * the `drop_snapshots` filter, the `on_progress` callback, and the\n * causation remap; adapters supply only the per-event insert\n * `callback` via the driver pattern (see {@link Store.restore}).\n *\n * Throws on the first invalid event (negative version, malformed\n * `created`) with the running index in the message.\n *\n * Returns the partial {@link ScanResult} (without `duration_ms`)\n * — {@link Act.restore} wraps the call with its own timing so the\n * duration covers transaction setup and commit, not just iteration.\n *\n * @internal\n */\nexport async function scan(\n source: EventSource,\n opts: ScanOptions = {},\n callback?: (event: Committed<Schemas, keyof Schemas>) => Promise<number>\n): Promise<Omit<ScanResult, \"duration_ms\">> {\n const { drop_snapshots = false, on_progress } = opts;\n const idMap = new Map<number, number>();\n let kept = 0;\n let droppedSnapshots = 0;\n let processed = 0;\n for await (const event of iterate(source)) {\n processed++;\n if (!isValid(event)) throw new Error(`Invalid event at index ${processed}`);\n if (on_progress) on_progress({ processed });\n if (drop_snapshots && event.name === SNAP_EVENT) {\n droppedSnapshots++;\n continue;\n }\n if (!callback) {\n kept++;\n continue;\n }\n // Causation remap — rewrite `meta.causation.event.id` to the new\n // id space if the source pointed at an earlier event's old id.\n let remapped = event;\n const causedBy = event.meta.causation.event?.id;\n if (causedBy !== undefined) {\n const newCausedBy = idMap.get(causedBy);\n if (newCausedBy !== undefined && newCausedBy !== causedBy) {\n remapped = {\n ...event,\n meta: {\n ...event.meta,\n causation: {\n ...event.meta.causation,\n event: { ...event.meta.causation.event!, id: newCausedBy },\n },\n },\n };\n }\n }\n const newId = await callback(remapped);\n idMap.set(event.id, newId);\n kept++;\n }\n return {\n kept,\n dropped: {\n closed_streams: 0,\n snapshots: droppedSnapshots,\n empty_streams: 0,\n },\n };\n}\n\n/**\n * Loads a snapshot of the state from the store by replaying events and applying patches.\n *\n * First checks the cache for a checkpoint, then queries the store for events\n * committed after the cached position. On cache miss, replays from the store\n * (using snapshots if available to avoid full replay).\n *\n * @template TState The type of state\n * @template TEvents The type of events\n * @template TActions The type of actions\n * @param me The state machine definition\n * @param stream The stream (instance) to load\n * @param callback (Optional) Callback to receive the loaded snapshot as it is built\n * @returns The snapshot of the loaded state\n *\n * @example\n * const snapshot = await load(Counter, \"counter1\");\n */\nexport async function load<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(\n me: State<TState, TEvents, TActions>,\n stream: string,\n callback?: (snapshot: Snapshot<TState, TEvents>) => void,\n asOf?: AsOf\n): Promise<Snapshot<TState, TEvents>> {\n const timeTravel = !!asOf && Object.values(asOf).some((v) => v !== undefined);\n const cached = timeTravel ? undefined : await cache().get<TState>(stream);\n const cache_hit = !!cached;\n let state = cached?.state ?? (me.init ? me.init() : ({} as TState));\n let patches = cached?.patches ?? 0;\n let snaps = cached?.snaps ?? 0;\n // version always reflects stream head: starts from the cached version\n // (or -1 for a fresh stream / cache miss), advances per event seen.\n let version = cached?.version ?? -1;\n // replayed counts events processed by THIS load only (snap or patch);\n // distinct from `patches` (the snap-distance accumulator carried over\n // from the cache).\n let replayed = 0;\n let event: Committed<TEvents, string> | undefined;\n\n await store().query(\n (e) => {\n event = e as Committed<TEvents, string>;\n version = e.version;\n if (e.name === SNAP_EVENT) {\n state = e.data as TState;\n snaps++;\n patches = 0;\n replayed++;\n } else if (me.patch[e.name]) {\n state = patch(state, me.patch[e.name](event, state));\n patches++;\n replayed++;\n } else if (e.name !== TOMBSTONE_EVENT) {\n // Unknown event — not in this state's reducer map. Causes:\n // deleted/renamed event in a versioned schema, load() called with\n // the wrong state, or stream contamination. Skipping silently\n // would corrupt replay; warn so the operator can investigate.\n log().warn(\n `Skipping unknown event \"${String(e.name)}\" on stream \"${stream}\" (id=${e.id}) — no reducer in state \"${me.name}\"`\n );\n }\n callback?.({\n event,\n state,\n version,\n patches,\n snaps,\n cache_hit,\n replayed,\n });\n },\n {\n stream,\n stream_exact: true,\n ...(cached ? { after: cached.event_id } : { with_snaps: true, ...asOf }),\n }\n );\n\n // Populate the cache when this load actually processed events. Without\n // this, read-heavy paths (UI loops calling load() many times between\n // commits) miss the cache forever — only action() would ever warm it.\n // No race-protection re-check needed: the cache is a state checkpoint\n // at (version, event_id), and any subsequent load queries past\n // event_id, picks up missed events, and replays — so an \"older\" cache\n // write from a concurrent slower load is self-correcting on next access.\n // Time-travel loads bypass cache entirely and skip this too.\n if (replayed > 0 && !timeTravel && event) {\n await cache().set(stream, {\n state,\n version,\n event_id: event.id,\n patches,\n snaps,\n });\n }\n\n return { event, state, version, patches, snaps, cache_hit, replayed };\n}\n\n/**\n * Executes an action and emits an event to be committed by the store.\n *\n * This function validates the action, applies business invariants, emits events, and commits them to the event store.\n *\n * @template TState The type of state\n * @template TEvents The type of events\n * @template TActions The type of actionSchemas\n * @template TKey The type of action to execute\n * @param me The state machine definition\n * @param action The action to execute\n * @param target The target (stream, actor, etc.)\n * @param payload The payload of the action\n * @param reactingTo (Optional) The event that the action is reacting to\n * @param skipValidation (Optional) Whether to skip validation (not recommended)\n * @returns The snapshot of the committed event\n *\n * @example\n * const snapshot = await action(Counter, \"increment\", { stream: \"counter1\", actor }, { by: 1 });\n */\nexport async function action<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n>(\n me: State<TState, TEvents, TActions>,\n action: TKey,\n target: Target,\n payload: Readonly<TActions[TKey]>,\n reactingTo?: Committed<Schemas, keyof Schemas>,\n skipValidation = false,\n correlator: Correlator = defaultCorrelator\n): Promise<Snapshot<TState, TEvents>[]> {\n const { stream, expectedVersion, actor } = target;\n if (!stream) throw new Error(\"Missing target stream\");\n\n const validated = skipValidation\n ? payload\n : validate(action as string, payload, me.actions[action]);\n\n const snapshot = await load(me, stream);\n if (snapshot.event?.name === TOMBSTONE_EVENT)\n throw new StreamClosedError(stream);\n const expected = expectedVersion ?? snapshot.event?.version;\n\n if (me.given) {\n const invariants = me.given[action] || [];\n invariants.forEach(({ valid, description }) => {\n if (!valid(snapshot.state, actor))\n throw new InvariantError(\n action,\n validated,\n target,\n snapshot,\n description\n );\n });\n }\n\n const result = me.on[action](validated, snapshot, target);\n if (!result) return [snapshot];\n\n // An empty array means no events were emitted\n if (Array.isArray(result) && result.length === 0) {\n return [snapshot];\n }\n\n const tuples = Array.isArray(result[0])\n ? (result as Emitted<TEvents>[]) // array of tuples\n : ([result] as Emitted<TEvents>[]); // single tuple\n\n // ACT-403: warn once per process per event name when a dynamic\n // `.emit((a) => [\"X\", ...])` produces a deprecated event. Static\n // `.emit(\"X\")` is already caught at build time by act-builder; this\n // is the runtime safety net for the dynamic form, which the static\n // checker can't inspect. The `_warned` set lives on the state so\n // multiple Act instances over the same merged state share idempotency.\n const deprecated = (me as { _deprecated?: Set<string> })._deprecated;\n if (deprecated && deprecated.size > 0) {\n const me_ = me as { _warned?: Set<string> };\n const warned = me_._warned ?? (me_._warned = new Set<string>());\n for (const [name] of tuples) {\n const evt = name as string;\n if (deprecated.has(evt) && !warned.has(evt)) {\n warned.add(evt);\n log().warn(\n `Action \"${String(action)}\" emitted deprecated event \"${evt}\". ` +\n `A newer version exists in the registry — update the action's ` +\n `.emit() to target the current version. (warned once per process)`\n );\n }\n }\n }\n\n const emitted = tuples.map(([name, data]) => ({\n name,\n data: skipValidation\n ? data\n : validate(name as string, data, me.events[name]),\n }));\n\n const meta: EventMeta = {\n correlation:\n reactingTo?.meta.correlation ||\n correlator({\n action: action as string,\n state: me.name,\n stream,\n actor: target.actor,\n }),\n causation: {\n action: {\n name: action as string,\n ...target,\n // payload intentionally omitted: it can be large or contain PII,\n // and callers correlate via the correlation id when they need it.\n },\n event: reactingTo\n ? {\n id: reactingTo.id,\n name: reactingTo.name,\n stream: reactingTo.stream,\n }\n : undefined,\n },\n };\n\n let committed: Committed<TEvents, keyof TEvents>[];\n try {\n committed = await store().commit(\n stream,\n emitted,\n meta,\n // Reactions skip optimistic concurrency: they always append against the\n // current head. Stream leasing already serializes concurrent reactions,\n // and forcing version checks here would turn ordinary catch-up into\n // spurious retries.\n reactingTo ? undefined : expected\n );\n } catch (error) {\n // Invalidate cache on concurrency errors — cached state is stale\n if (error instanceof ConcurrencyError) {\n await cache().invalidate(stream);\n }\n throw error;\n }\n\n let { state, patches } = snapshot;\n const snapshots = committed.map((event) => {\n const p = me.patch[event.name](event, state);\n state = patch(state, p);\n patches++;\n // cache_hit / replayed propagate from the initial load — these\n // post-commit snapshots all derive from the same loaded state.\n // version advances per committed event (each is a new stream head).\n return {\n event,\n state,\n version: event.version,\n patches,\n snaps: snapshot.snaps,\n patch: p,\n cache_hit: snapshot.cache_hit,\n replayed: snapshot.replayed,\n };\n });\n\n // fire and forget snaps\n const last = snapshots.at(-1)!;\n const snapped = me.snap?.(last);\n\n // Update cache with post-commit state (reset patches if snapped).\n // Fire-and-forget — log but don't fail the action on cache write errors\n // (e.g., transient network failures in a custom Cache adapter).\n cache()\n .set<TState>(stream, {\n state: last.state,\n version: last.event.version,\n event_id: last.event.id,\n patches: snapped ? 0 : last.patches,\n snaps: snapped ? last.snaps + 1 : last.snaps,\n })\n .catch((err) => log().error(err));\n\n // Persist snap to store for cold-start durability. Fire-and-forget:\n // snap() has its own try/catch that logs failures, so the rejection\n // can never escape — `void` is just to silence the floating-promise\n // lint (action() doesn't await store durability for the snapshot).\n if (snapped) void snap(last);\n\n return snapshots;\n}\n","/**\n * @module tracing\n * @category Internal\n *\n * Centralized observability for the framework's internal pipelines.\n *\n * Trace decorators wrap a bare implementation with `logger.trace(...)` calls\n * at well-defined moments — entry points for {@link \"event-sourcing\"} (`load`,\n * `snap`, `action`) and exit points for the {@link \"drain\"} pipeline (`claim`,\n * `fetch`, `ack`, `block`, `subscribe`). `action` carries both an entry log\n * and a post-commit log to preserve the diagnostic value of the historical\n * mid-function trace points.\n *\n * Output styles:\n * - **Pretty mode** (`config().env !== \"production\"`) — event-sourcing logs\n * show only the colored target body (color carries the operation/phase),\n * drain logs keep a colored caption.\n * - **Plain mode** (production / log aggregators) — every log gets a textual\n * prefix; event-sourcing uses `caption: body`, drain uses `caption body`.\n *\n * The two factories — {@link buildEs} and {@link buildDrain} — let the\n * orchestrator choose bare or traced variants once at `.build()` time based\n * on the configured log level. Outside this module, no other source file\n * imports tracing primitives.\n *\n * @internal\n */\n\nimport { config } from \"../config.js\";\nimport type { AsOf, Correlator, Logger, Schemas } from \"../types/index.js\";\nimport { defaultCorrelator } from \"./correlator.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport * as drain from \"./drain.js\";\nimport type { EsOps } from \"./event-sourcing.js\";\nimport * as es from \"./event-sourcing.js\";\n\ntype AsyncFn = (...args: any[]) => Promise<any>;\n\nconst PRETTY = config().env !== \"production\";\n\n// 256-color codes for distinctive, theme-friendly hues\nconst C_BLUE = \"\\x1b[38;5;39m\"; // vivid sky blue (action)\nconst C_ORANGE = \"\\x1b[38;5;208m\"; // true orange (committed)\nconst C_GREEN = \"\\x1b[38;5;42m\"; // emerald (load)\nconst C_MAGENTA = \"\\x1b[38;5;165m\"; // bright magenta (snap)\nconst C_DRAIN = \"\\x1b[38;5;244m\"; // muted gray for all drain ops\n// load-trace cache marker shades — distinguishable from C_GREEN body color\nconst C_HIT = \"\\x1b[38;5;82m\"; // lime — fast path, blends visually\nconst C_MISS = \"\\x1b[38;5;220m\"; // amber — non-trivial work happened\nconst C_RESET = \"\\x1b[0m\";\n\n/**\n * Format an event-sourcing trace line. Pretty mode renders just the colored\n * body (the color is the cue for which op/phase fired); plain mode prepends\n * `caption: ` so log aggregators stay readable without ANSI.\n */\nconst es_caption = (caption: string, color: string, body: string): string =>\n PRETTY ? `${color}${body}${C_RESET}` : `${caption}: ${body}`;\n\n/**\n * Format a drain-pipeline caption. Drain logs keep a `>>` marker for easy\n * spotting in mixed log streams, plus a `caption` (past tense — every drain\n * trace fires on exit). All drain ops share one color (gray) so the pipeline\n * reads as a single channel; the caption disambiguates the phase. Lane\n * (ACT-1103) is appended in lilac, unwrapped, when set and non-default,\n * so the operator's eye lands on the lane name without parsing per-stream\n * detail. Per-stream `@at/retry` and fetched event lists are muted via\n * {@link dim} so the stream name itself reads loudest.\n */\nconst C_LANE = \"\\x1b[38;5;183m\"; // lilac — distinct from gray drain + drain ops\nconst C_DIM = \"\\x1b[38;5;240m\"; // dim gray — dimmer than C_DRAIN\nconst C_ERR = \"\\x1b[38;5;196m\"; // bright red — block marker\nconst C_STREAM = \"\\x1b[38;5;226m\"; // bright yellow — target stream names in drain/correlate traces\n\n/** Wrap with the muted color when pretty mode is on. Plain in production. */\nconst dim = (text: string): string =>\n PRETTY ? `${C_DIM}${text}${C_RESET}` : text;\n\n/** Wrap with a foreground color when pretty mode is on; bare in production. */\nconst hue = (color: string, text: string): string =>\n PRETTY ? `${color}${text}${C_RESET}` : text;\n\nconst drain_caption = (caption: string, lane?: string): string => {\n const showLane = lane && lane !== \"default\";\n if (PRETTY) {\n const tag = `${C_DRAIN}>> ${caption}${C_RESET}`;\n return showLane ? `${tag} ${C_LANE}${lane}${C_RESET}` : tag;\n }\n return showLane ? `>> ${caption} ${lane}` : `>> ${caption}`;\n};\n\n/**\n * Format the cache hit/miss marker for the load trace. In pretty mode the\n * word is colored (lime for hit, amber for miss) and the surrounding\n * `C_GREEN` body color is restored after — embedded ANSI inside `es_caption`'s\n * outer wrap. Plain mode returns the bare word.\n */\nconst cache_marker = (hit: boolean): string => {\n const word = hit ? \"hit\" : \"miss\";\n if (!PRETTY) return word;\n return `${hit ? C_HIT : C_MISS}${word}${C_RESET}${C_GREEN}`;\n};\n\n/**\n * Format the load stats (`v=N replayed=N snaps=N patches=N`) for the load\n * trace. Muted gray in pretty mode so the cache marker reads as the most\n * important cue; plain mode returns the bare text.\n *\n * - `v` — stream head version (the version of the last event applied)\n * - `replayed` — events processed by THIS load past the cache point\n * - `snaps` — cumulative snapshots taken on this stream\n * - `patches` — events since the last snap (snap-policy accumulator)\n */\nconst stats_marker = (\n version: number,\n replayed: number,\n snaps: number,\n patches: number\n): string => {\n const text = `v=${version} replayed=${replayed} snaps=${snaps} patches=${patches}`;\n if (!PRETTY) return text;\n return `${C_DRAIN}${text}${C_RESET}${C_GREEN}`;\n};\n\n/**\n * Format the as-of marker for time-travel loads. Surfaces the active filter\n * fields (before id, created_before/after timestamps, limit) so an operator\n * can tell at a glance which slice was loaded. Empty `asOf` returns \"\" —\n * non-time-travel loads skip the marker entirely.\n */\nconst as_of_marker = (asOf: AsOf | undefined): string => {\n if (!asOf) return \"\";\n const parts: string[] = [];\n if (asOf.before !== undefined) parts.push(`before=${asOf.before}`);\n if (asOf.created_before !== undefined)\n parts.push(`created_before=${asOf.created_before.toISOString()}`);\n if (asOf.created_after !== undefined)\n parts.push(`created_after=${asOf.created_after.toISOString()}`);\n if (asOf.limit !== undefined) parts.push(`limit=${asOf.limit}`);\n return parts.length ? ` (as-of ${parts.join(\" \")})` : \" (as-of)\";\n};\n\n/**\n * Wraps an async function with optional `exit` and `entry` callbacks. Each\n * callback fires at the corresponding phase; both receive the call args, and\n * `exit` additionally receives the resolved result. Used to layer\n * `logger.trace` calls onto bare ops without changing their signatures.\n *\n * @internal\n */\nconst traced = <F extends AsyncFn>(\n inner: F,\n exit?: (result: Awaited<ReturnType<F>>, ...args: Parameters<F>) => void,\n entry?: (...args: Parameters<F>) => void\n): F =>\n (async (...args: Parameters<F>) => {\n entry?.(...args);\n const result = (await inner(...args)) as Awaited<ReturnType<F>>;\n exit?.(result, ...args);\n return result;\n }) as F;\n\n/**\n * Selects bare or traced event-sourcing handlers. Called once by the\n * orchestrator constructor.\n *\n * @internal\n */\nexport function buildEs(\n logger: Logger,\n correlator: Correlator = defaultCorrelator\n): EsOps {\n // `es.action` takes `correlator` as its last positional arg; the\n // orchestrator never wants to plumb it through every call site, so we\n // bind it once here and present an `EsOps.action` with the original\n // 6-arg signature.\n const boundAction: EsOps[\"action\"] = (\n me,\n actionName,\n target,\n payload,\n reactingTo,\n skipValidation = false\n ) =>\n es.action(\n me,\n actionName,\n target,\n payload,\n reactingTo,\n skipValidation,\n correlator\n );\n if (logger.level !== \"trace\") {\n return {\n snap: es.snap,\n load: es.load,\n action: boundAction,\n tombstone: es.tombstone,\n };\n }\n return {\n snap: traced(es.snap, undefined, (snapshot) => {\n logger.trace(\n es_caption(\n \"snap\",\n C_MAGENTA,\n `${snapshot.event!.stream}@${snapshot.event!.version}`\n )\n );\n }),\n load: traced(es.load, (result, _me, stream, _cb, asOf) => {\n const stats = stats_marker(\n result.version,\n result.replayed,\n result.snaps,\n result.patches\n );\n logger.trace(\n es_caption(\n \"load\",\n C_GREEN,\n `${stream}${as_of_marker(asOf)} ${cache_marker(result.cache_hit)} ${stats}`\n )\n );\n }),\n action: traced(\n boundAction,\n (snapshots, _me, _action, target) => {\n const committed = snapshots.filter((s) => s.event);\n if (committed.length) {\n logger.trace(\n committed.map((s) => s.event!.data),\n es_caption(\n \"committed\",\n C_ORANGE,\n `${target.stream}.${committed.map((s) => s.event!.name).join(\", \")}`\n )\n );\n }\n },\n (_me, action, target, payload) => {\n logger.trace(\n payload as object,\n es_caption(\"action\", C_BLUE, `${target.stream}.${action}`)\n );\n }\n ),\n tombstone: traced(es.tombstone, (committed, stream) => {\n if (committed)\n logger.trace(\n es_caption(\"tombstoned\", C_ORANGE, `${stream}@${committed.version}`)\n );\n }),\n };\n}\n\n/**\n * Selects bare or traced drain-pipeline ops. Called once by the orchestrator\n * constructor.\n *\n * @internal\n */\nexport function buildDrain<TEvents extends Schemas>(\n logger: Logger\n): DrainOps<TEvents> {\n // Cycle-level tracing happens in `DrainController.drain()` via\n // {@link traceCycle} — claim/fetch/ack/block all flow into one log\n // line per cycle to give the operator a single atomic narrative.\n // `subscribe` stays decorated because it's driven from correlate-\n // cycle (not from runDrainCycle) and doesn't fit the cycle shape.\n return {\n claim: drain.claim,\n fetch: drain.fetch,\n ack: drain.ack,\n block: drain.block,\n subscribe:\n logger.level !== \"trace\"\n ? drain.subscribe\n : traced(drain.subscribe, (result, streams) => {\n if (!result.subscribed) return;\n // Caption mirrors `drained`: lane in the caption when the\n // whole batch shares a single non-default lane. Mixed-lane\n // batches (rare — different correlated targets resolving\n // to different lanes in one scan) fall back to per-stream\n // `[lane]` tags, default-lane streams stay bare either way.\n const lanes = new Set(streams.map((s) => s.lane ?? \"default\"));\n const uniformLane = lanes.size === 1 ? streams[0]?.lane : undefined;\n const data = streams\n .map(({ stream, lane }) =>\n uniformLane || !lane || lane === \"default\"\n ? hue(C_STREAM, stream)\n : `${hue(C_STREAM, stream)}${dim(`[${lane}]`)}`\n )\n .join(\" \");\n logger.trace(`${drain_caption(\"correlated\", uniformLane)} ${data}`);\n }),\n };\n}\n\n/**\n * Emit one cycle-level drain trace summarizing what happened in a\n * single `runDrainCycle` pass. Per-stream rendering shape — outcome +\n * post-state anchored on the right:\n *\n * stream<-source [events] ✓ @<acked-at> — full success\n * stream<-source [events] ✗ @<failed-at>/<retry> (error) — total failure → blocked\n * stream<-source [events] ⚠ @<failed-at>/<retry> (error) — total failure → retrying\n * stream<-source [events] ✓ @<acked-at> ✗ @<failed-at>/<retry> (error) — partial then blocked\n * stream<-source [events] ✓ @<acked-at> ⚠ @<failed-at>/<retry> (error) — partial then retrying\n * stream<-source ⊘ @<at>/<retry> — deferred (backoff)\n *\n * Partial-success-then-failure is the dual-outcome case: events\n * 1..K succeeded (watermark advanced to K), event K+1 threw. The\n * trace renders both the lime `✓ @K` and the red/amber `✗`/`⚠ @K+1`\n * on the same line so an operator sees \"we made progress *and* then\n * something broke\" at a glance.\n *\n * Lane prefixes the caption in lilac when non-default. The outcome\n * marker and its adjacent post-state share the marker's color so the\n * eye reads \"outcome + where it landed\" as one unit. Per-stream\n * `[events]` and `(error)` stay dim — secondary context.\n *\n * @internal\n */\nexport function traceCycle<TEvents extends Schemas>(\n logger: Logger,\n leased: ReadonlyArray<{\n readonly stream: string;\n readonly at: number;\n readonly retry: number;\n readonly lane?: string;\n }>,\n fetched: ReadonlyArray<{\n readonly stream: string;\n readonly source?: string;\n readonly events: ReadonlyArray<{\n readonly id: number;\n readonly name: keyof TEvents;\n }>;\n }>,\n handled: ReadonlyArray<{\n readonly lease: { readonly stream: string };\n readonly error?: string;\n readonly block?: boolean;\n readonly failed_at?: number;\n }>,\n acked: ReadonlyArray<{ readonly stream: string; readonly at: number }>,\n blocked: ReadonlyArray<{ readonly stream: string; readonly error: string }>\n): void {\n if (logger.level !== \"trace\" || !leased.length) return;\n const lane = leased[0]?.lane;\n const fetchByStream = new Map(fetched.map((f) => [f.stream, f]));\n const ackedByStream = new Map(acked.map((a) => [a.stream, a.at]));\n const blockedByStream = new Map(blocked.map((b) => [b.stream, b.error]));\n // Handled-with-error stays a single index now: `block` discriminates\n // the marker (✗ vs ⚠); the failure exists independently of whether\n // ack happened.\n const failedByStream = new Map(\n handled.filter((h) => h.error).map((h) => [h.lease.stream, h] as const)\n );\n const detail = leased\n .map(({ stream, at, retry }) => {\n const f = fetchByStream.get(stream);\n // Target stream in yellow so the operator's eye lands on \"which\n // stream did this happen on?\" first; source (the events' origin)\n // stays dim — secondary info.\n const key = f?.source\n ? `${hue(C_STREAM, stream)}${dim(`<-${f.source}`)}`\n : hue(C_STREAM, stream);\n const events =\n f && f.events.length\n ? ` ${dim(\n `[${f.events.map(({ id, name }) => `#${id} ${String(name)}`).join(\", \")}]`\n )}`\n : \"\";\n // Build ack + fail segments independently — both can fire for\n // the same stream in the partial-success-then-failure case.\n const ackedAt = ackedByStream.get(stream);\n const ackPart =\n ackedAt !== undefined\n ? hue(C_HIT, `✓ @${ackedAt}`) // ✓ + new at in lime\n : \"\";\n const failure = failedByStream.get(stream);\n let failPart = \"\";\n if (failure) {\n // Failed event id when known (per-event path), else falls back\n // to lease.at — the post-fetch watermark — for batch-mode\n // total failures where no single event is \"the one.\"\n const failedAt = failure.failed_at ?? at;\n const blockedError = blockedByStream.get(stream);\n if (blockedError !== undefined) {\n failPart = `${hue(C_ERR, `✗ @${failedAt}/${retry}`)} ${dim(`(${blockedError})`)}`;\n } else {\n failPart = `${hue(C_MISS, `⚠ @${failedAt}/${retry}`)} ${dim(`(${failure.error})`)}`;\n }\n }\n let tail: string;\n if (ackPart && failPart) tail = ` ${ackPart} ${failPart}`;\n else if (ackPart) tail = ` ${ackPart}`;\n else if (failPart) tail = ` ${failPart}`;\n else tail = ` ${dim(`⊘ @${at}/${retry}`)}`; // nothing happened\n return `${key}${events}${tail}`;\n })\n .join(\", \");\n logger.trace(`${drain_caption(\"drained\", lane)} ${detail}`);\n}\n","/**\n * @module merge\n * @category Internal\n *\n * Shared utilities for merging partial states and projections across builders.\n * Lives in `internal/` because the symbols are consumed by the builder layer\n * (`act-builder`, `slice-builder`, `projection-builder`) but aren't part of\n * the public package surface.\n *\n * @internal\n */\nimport { ZodObject, type ZodType } from \"zod\";\nimport type { Projection } from \"../builders/projection-builder.js\";\nimport type { Schema, State } from \"../types/index.js\";\n\n/**\n * Unwraps wrapper types (ZodOptional, ZodNullable, ZodDefault, ZodReadonly)\n * to find the base type name, e.g. `z.string().optional()` -> `\"ZodString\"`.\n */\nfunction baseTypeName(zodType: ZodType): string {\n let t: any = zodType;\n while (typeof t.unwrap === \"function\") {\n t = t.unwrap();\n }\n return t.constructor.name;\n}\n\n/**\n * Merges two Zod schemas. If both are ZodObject instances, checks for\n * overlapping shape keys with incompatible base types (throws descriptive\n * error), then merges via `.extend()`. Falls back to keeping existing\n * schema if either is not a ZodObject.\n */\nfunction mergeSchemas(\n existing: ZodType,\n incoming: ZodType,\n stateName: string\n): ZodType {\n if (existing instanceof ZodObject && incoming instanceof ZodObject) {\n const existingShape = existing.shape as Record<string, ZodType>;\n const incomingShape = incoming.shape as Record<string, ZodType>;\n for (const key of Object.keys(incomingShape)) {\n if (key in existingShape) {\n const existingBase = baseTypeName(existingShape[key]);\n const incomingBase = baseTypeName(incomingShape[key]);\n if (existingBase !== incomingBase) {\n throw new Error(\n `Schema conflict in \"${stateName}\": key \"${key}\" has type \"${existingBase}\" but incoming partial declares \"${incomingBase}\"`\n );\n }\n }\n }\n return existing.extend(incomingShape);\n }\n return existing;\n}\n\n/**\n * Merges two init functions by spreading both results together.\n * Each partial only provides its own defaults.\n */\nfunction mergeInits<TState extends Schema>(\n existing: () => Readonly<TState>,\n incoming: () => Readonly<TState>\n): () => Readonly<TState> {\n return () => ({ ...existing(), ...incoming() });\n}\n\n/**\n * Registers a state into a states map and action/event registries,\n * merging with existing same-name states (partial state support).\n */\nexport function registerState(\n state: State<any, any, any>,\n states: Map<string, State<any, any, any>>,\n actions: Record<string, any>,\n events: Record<string, any>\n): void {\n const existing = states.get(state.name);\n if (existing) {\n mergeIntoExisting(state, existing, states, actions, events);\n } else {\n registerNewState(state, states, actions, events);\n }\n}\n\n/**\n * Registers a state for the first time. All action/event names must be unique\n * across the registry; collisions throw.\n */\nfunction registerNewState(\n state: State<any, any, any>,\n states: Map<string, State<any, any, any>>,\n actions: Record<string, any>,\n events: Record<string, any>\n): void {\n states.set(state.name, state);\n for (const name of Object.keys(state.actions)) {\n if (actions[name]) throw new Error(`Duplicate action \"${name}\"`);\n actions[name] = state;\n }\n for (const name of Object.keys(state.events)) {\n if (events[name]) throw new Error(`Duplicate event \"${name}\"`);\n events[name] = { schema: state.events[name], reactions: new Map() };\n }\n}\n\n/**\n * Merges an incoming partial state into an existing same-name state and\n * updates the action/event registries. Splits into four phases:\n * 1. validate no cross-state action/event collisions\n * 2. merge per-event patches (one custom patch per event)\n * 3. build the merged state and replace it in the states map\n * 4. update action→state pointers and register new events\n */\nfunction mergeIntoExisting(\n state: State<any, any, any>,\n existing: State<any, any, any>,\n states: Map<string, State<any, any, any>>,\n actions: Record<string, any>,\n events: Record<string, any>\n): void {\n // 1. Validate no cross-state collisions for actions/events\n for (const name of Object.keys(state.actions)) {\n // Same schema reference means the same partial re-registered via another slice\n if (existing.actions[name] === state.actions[name]) continue;\n if (actions[name]) throw new Error(`Duplicate action \"${name}\"`);\n }\n for (const name of Object.keys(state.events)) {\n // Same schema reference means the same partial re-registered via another slice\n if (existing.events[name] === state.events[name]) continue;\n // Same event name registered in a same-name state partial with a\n // different Zod schema reference — silent contract drift that the\n // type system can't catch (structurally compatible shapes flow\n // through TS even when refinements/enums/literals disagree).\n // Reference identity is the rule: cross-slice event schemas must\n // come from a single shared instance.\n if (existing.events[name]) {\n throw new Error(\n `Event \"${name}\" in state \"${state.name}\" is declared with different Zod schemas across slices. ` +\n `Cross-slice event schemas must reference the same instance — ` +\n `extract a shared schema (e.g. \\`export const ${name} = z.object({ ... })\\` in a shared module) ` +\n `and import it in every slice that declares it.`\n );\n }\n if (events[name]) throw new Error(`Duplicate event \"${name}\"`);\n }\n\n // 2. Merge patches with custom-vs-passthrough resolution\n const mergedPatch = mergePatches(existing.patch, state.patch, state.name);\n\n // 3. Build merged state\n const merged = {\n ...existing,\n state: mergeSchemas(existing.state, state.state, state.name),\n init: mergeInits(existing.init, state.init),\n events: { ...existing.events, ...state.events },\n actions: { ...existing.actions, ...state.actions },\n patch: mergedPatch,\n on: { ...existing.on, ...state.on },\n given: { ...existing.given, ...state.given },\n snap:\n state.snap && existing.snap && state.snap !== existing.snap\n ? (() => {\n throw new Error(\n `Duplicate snap strategy for state \"${state.name}\"`\n );\n })()\n : state.snap || existing.snap,\n };\n states.set(state.name, merged);\n\n // 4. Update action→state pointers; register events not yet seen\n for (const name of Object.keys(merged.actions)) {\n actions[name] = merged;\n }\n for (const name of Object.keys(state.events)) {\n if (events[name]) continue; // already registered, preserve reactions\n events[name] = { schema: state.events[name], reactions: new Map() };\n }\n}\n\n/**\n * Merges two patch maps. Only one custom (non-passthrough) patch per event is\n * allowed; passthroughs always yield to custom reducers, and re-registering\n * the same custom patch (same reference, e.g. across slices) is a no-op.\n */\nfunction mergePatches(\n existing: Record<string, any>,\n incoming: Record<string, any>,\n stateName: string\n): Record<string, any> {\n const merged = { ...existing };\n for (const name of Object.keys(incoming)) {\n const existingP = existing[name];\n const incomingP = incoming[name];\n if (!existingP) {\n merged[name] = incomingP;\n continue;\n }\n const existingIsDefault = existingP._passthrough;\n const incomingIsDefault = incomingP._passthrough;\n if (!existingIsDefault && !incomingIsDefault && existingP !== incomingP) {\n throw new Error(\n `Duplicate custom patch for event \"${name}\" in state \"${stateName}\"`\n );\n }\n // Keep whichever is custom; if both passthrough or existing custom, keep existing\n if (existingIsDefault && !incomingIsDefault) {\n merged[name] = incomingP;\n }\n }\n return merged;\n}\n\n/**\n * Merges reactions from one event register into another. The target is\n * assumed to already contain entries for every event name in the source\n * (e.g., act-builder's `.withSlice()` registers the slice's states first,\n * which seeds the target events). Reaction names collide by `set()`\n * semantics — last write wins.\n */\nexport function mergeEventRegister(\n target: Record<string, { reactions: Map<string, unknown> }>,\n source: Record<string, { reactions: Map<string, unknown> }>\n): void {\n for (const [eventName, sourceReg] of Object.entries(source)) {\n const targetReg = target[eventName];\n if (!targetReg) continue;\n for (const [name, reaction] of sourceReg.reactions) {\n targetReg.reactions.set(name, reaction);\n }\n }\n}\n\n/**\n * Merges a projection's event schemas and reactions into an event registry,\n * deduplicating reaction names by appending \"_p\" on collision.\n */\nexport function mergeProjection(\n proj: Projection<any>,\n events: Record<string, any>\n): void {\n for (const eventName of Object.keys(proj.events)) {\n const projRegister = proj.events[eventName];\n const existing = events[eventName];\n if (!existing) {\n events[eventName] = {\n schema: projRegister.schema,\n reactions: new Map(projRegister.reactions),\n };\n } else {\n for (const [name, reaction] of projRegister.reactions) {\n let key = name;\n while (existing.reactions.has(key)) key = `${key}_p`;\n existing.reactions.set(key, reaction);\n }\n }\n }\n}\n\n// Resolves the event stream as source and target (default)\nexport const _this_ = ({ stream }: { stream: string }) => ({\n source: stream,\n target: stream,\n});\n","/**\n * @module backoff\n * @category Internal\n *\n * Per-reaction retry backoff delay computation. Pure function — keeps\n * `DrainController` and `reactions._finalize` testable in isolation.\n *\n * @internal\n */\n\nimport type { BackoffOptions } from \"../types/reaction.js\";\n\n/**\n * Compute the wall-clock delay (in ms) to wait before the next attempt on\n * a stream whose handler just failed.\n *\n * @param retry - The lease's `retry` counter at finalize time. `0` is the\n * first attempt that failed; `1` is after one retry; etc.\n * @param opts - Per-reaction backoff config. Returns `0` when undefined.\n * @returns Non-negative integer milliseconds. Always `0` when `opts` is\n * undefined or `baseMs <= 0`.\n */\nexport function computeBackoffDelay(\n retry: number,\n opts: BackoffOptions | undefined\n): number {\n if (!opts || opts.baseMs <= 0) return 0;\n const r = Math.max(0, retry);\n let delay: number;\n switch (opts.strategy) {\n case \"fixed\":\n delay = opts.baseMs;\n break;\n case \"linear\":\n delay = opts.baseMs * (r + 1);\n break;\n case \"exponential\":\n delay = opts.baseMs * 2 ** r;\n if (opts.maxMs !== undefined) delay = Math.min(delay, opts.maxMs);\n break;\n }\n if (opts.jitter) delay = delay * (0.5 + Math.random());\n return Math.max(0, Math.floor(delay));\n}\n","/**\n * @module reactions\n * @category Internal\n *\n * Reaction dispatch — what runs inside the drain pipeline once `runDrainCycle`\n * has fetched events for a leased stream. Two shapes:\n *\n * - per-event `handle`: walks payloads sequentially, builds a scoped `IAct`\n * that auto-injects `reactingTo` so handlers don't have to thread it\n * through manually\n * - bulk `handleBatch`: hands every event for a static-target projection to\n * a single batch callback, enabling one-transaction replays\n *\n * Both share `_finalize`, which collapses the retry-vs-block decision and\n * the \"report error only when nothing was handled\" rule.\n *\n * @internal\n */\n\nimport {\n type Actor,\n type BatchHandler,\n type Committed,\n type IAct,\n type Lease,\n type Logger,\n NonRetryableError,\n type ReactionOptions,\n type ReactionPayload,\n type Schemas,\n type Target,\n} from \"../types/index.js\";\nimport { computeBackoffDelay } from \"./backoff.js\";\nimport type { Handle, HandleBatch, HandleResult } from \"./drain-cycle.js\";\n\n/**\n * Dependencies a reaction handler needs from the orchestrator: the logger\n * for retry/error breadcrumbs, plus the bound `IAct` methods that the scoped\n * proxy hands to user reaction code.\n *\n * @internal\n */\nexport type ReactionDeps<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n> = {\n readonly logger: Logger;\n readonly boundDo: IAct<TEvents, TActions, TActor>[\"do\"];\n readonly boundLoad: IAct<TEvents, TActions, TActor>[\"load\"];\n readonly boundQuery: IAct<TEvents, TActions, TActor>[\"query\"];\n readonly boundQueryArray: IAct<TEvents, TActions, TActor>[\"query_array\"];\n};\n\n/**\n * Shared finalization: log the error and decide retry vs. block. The\n * error string is *always* surfaced on the failure path — drain-cycle\n * uses `handled > 0` (not `error` presence) to decide whether to ack\n * the partial progress, so the message can travel for trace + blocked\n * record without affecting the ack/skip choice.\n */\nfunction finalize(\n lease: Lease,\n handled: number,\n at: number,\n error: Error | undefined,\n options: ReactionOptions,\n logger: Logger,\n failed_at?: number\n): HandleResult {\n if (!error) return { lease, handled, acked_at: at };\n logger.error(error);\n // A `NonRetryableError` from the handler short-circuits the retry\n // budget — block on first attempt when the operator has opted in via\n // `blockOnError`. When `blockOnError` is false, the operator has\n // explicitly chosen \"retry forever,\" so we don't override that.\n const nonRetryable = error instanceof NonRetryableError;\n const block =\n options.blockOnError && (nonRetryable || lease.retry >= options.maxRetries);\n if (block)\n logger.error(\n nonRetryable\n ? `Blocking ${lease.stream} on non-retryable error.`\n : `Blocking ${lease.stream} after ${lease.retry} retries.`\n );\n // Backoff applies only on retry paths — successful handles and terminal\n // blocks never defer. `lease.retry` here is the just-failed attempt's\n // counter, so the delay paces the *next* attempt.\n const nextAttemptAt =\n !block && options.backoff\n ? Date.now() + computeBackoffDelay(lease.retry, options.backoff)\n : undefined;\n return {\n lease,\n handled,\n acked_at: at,\n error: error.message,\n block,\n nextAttemptAt,\n failed_at,\n };\n}\n\n/**\n * Builds the per-event reaction dispatcher passed to `runDrainCycle`.\n *\n * The scoped `IAct` proxy auto-injects the triggering event as `reactingTo`\n * when handlers call `do()` without it (#587), keeping the correlation\n * chain by default. The non-do methods are reused across all dispatches —\n * only `do` rebinds per payload because it captures the triggering event.\n *\n * @internal\n */\nexport function buildHandle<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n>(deps: ReactionDeps<TEvents, TActions, TActor>): Handle<TEvents> {\n const { logger, boundDo, boundLoad, boundQuery, boundQueryArray } = deps;\n return async (lease, payloads) => {\n if (payloads.length === 0) return { lease, handled: 0, acked_at: lease.at };\n\n const stream = lease.stream;\n let at = payloads.at(0)!.event.id;\n let handled = 0;\n\n if (lease.retry > 0)\n logger.warn(`Retrying ${stream}@${at} (${lease.retry}).`);\n\n const scopedApp: IAct<TEvents, TActions, TActor> = {\n do: boundDo,\n load: boundLoad,\n query: boundQuery,\n query_array: boundQueryArray,\n };\n\n for (const payload of payloads) {\n const { event, handler } = payload;\n scopedApp.do = <TKey extends keyof TActions & string>(\n action: TKey,\n target: Target<TActor>,\n actionPayload: Readonly<TActions[TKey]>,\n reactingTo?: Committed<Schemas, string>,\n skipValidation?: boolean\n ) =>\n boundDo(\n action,\n target,\n actionPayload,\n (reactingTo ?? event) as Committed<TEvents, string & keyof TEvents>,\n skipValidation\n );\n try {\n await handler(event, stream, scopedApp);\n at = event.id;\n handled++;\n } catch (error) {\n return finalize(\n lease,\n handled,\n at,\n error as Error,\n payload.options,\n logger,\n event.id\n );\n }\n }\n return finalize(lease, handled, at, undefined, payloads[0].options, logger);\n };\n}\n\n/**\n * Builds the bulk reaction dispatcher passed to `runDrainCycle`. All events\n * for a static-target projection are handed to a single callback so the\n * projection can do one transaction per drain (catch-up replays especially).\n *\n * @internal\n */\nexport function buildHandleBatch<TEvents extends Schemas>(\n logger: Logger\n): HandleBatch<TEvents> {\n return async (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[],\n batchHandler: BatchHandler<TEvents>\n ) => {\n const stream = lease.stream;\n const events = payloads.map((p) => p.event);\n const options = payloads[0].options;\n\n if (lease.retry > 0)\n logger.warn(`Retrying batch ${stream}@${events[0].id} (${lease.retry}).`);\n\n try {\n await batchHandler(events, stream);\n return finalize(\n lease,\n events.length,\n events.at(-1)!.id,\n undefined,\n options,\n logger\n );\n } catch (error) {\n return finalize(lease, 0, lease.at, error as Error, options, logger);\n }\n };\n}\n","/**\n * @module settle\n * @category Internal\n *\n * Debounced correlate→drain loop. Sits one level above both correlation\n * and drain: schedule() coalesces rapid callers into a single cycle, then\n * runs correlate+drain in a loop until a pass produces no progress.\n *\n * Owns the debounce timer and the reentrancy flag. Everything else is\n * supplied via the `SettleDeps` callbacks so this module stays free of\n * orchestrator state.\n *\n * @internal\n */\n\nimport type {\n Drain,\n DrainOptions,\n Logger,\n Query,\n Schemas,\n SettleOptions,\n} from \"../types/index.js\";\n\n/**\n * Callbacks the settle loop needs from the orchestrator. Modeled as an\n * input bag so this file doesn't import `Act` (avoids a cycle) and stays\n * independently testable.\n *\n * @internal\n */\nexport type SettleDeps<TEvents extends Schemas> = {\n readonly logger: Logger;\n readonly init: () => Promise<void>;\n readonly checkpoint: () => number;\n readonly correlate: (\n query: Query\n ) => Promise<{ subscribed: number; last_id: number }>;\n readonly drain: (options: DrainOptions) => Promise<Drain<TEvents>>;\n readonly onSettled: (drain: Drain<TEvents>) => void;\n};\n\n/**\n * Drives the debounced correlate→drain catch-up cycle. One instance per\n * Act orchestrator.\n *\n * @internal\n */\nexport class SettleLoop<TEvents extends Schemas> {\n private _timer: ReturnType<typeof setTimeout> | undefined = undefined;\n private _running = false;\n\n constructor(\n private readonly deps: SettleDeps<TEvents>,\n /** Debounce window applied when the caller doesn't override via `SettleOptions.debounceMs`. */\n private readonly defaultDebounceMs: number\n ) {}\n\n /**\n * Schedule a settle pass. Multiple calls inside the debounce window\n * coalesce into one cycle. The cycle runs correlate→drain in a loop\n * until no progress is made (no new subscriptions, no acks, no blocks)\n * or `maxPasses` is reached, then emits the `\"settled\"` lifecycle event\n * via {@link SettleDeps.onSettled}.\n */\n schedule(options: SettleOptions = {}): void {\n const {\n debounceMs = this.defaultDebounceMs,\n correlate: correlateQuery = { after: -1, limit: 100 },\n maxPasses = Infinity,\n ...drainOptions\n } = options;\n\n if (this._timer) clearTimeout(this._timer);\n this._timer = setTimeout(() => {\n this._timer = undefined;\n if (this._running) return;\n this._running = true;\n\n (async () => {\n await this.deps.init();\n let lastDrain: Drain<TEvents> | undefined;\n // Loop correlate→drain until a pass produces no work — this fully\n // catches up paginated streams (e.g. after `reset()` on a long\n // projection) without forcing callers to roll their own loop.\n // `maxPasses` caps runtime in pathological cases.\n for (let i = 0; i < maxPasses; i++) {\n const { subscribed } = await this.deps.correlate({\n ...correlateQuery,\n after: this.deps.checkpoint(),\n });\n lastDrain = await this.deps.drain(drainOptions);\n const made_progress =\n subscribed > 0 ||\n lastDrain.acked.length > 0 ||\n lastDrain.blocked.length > 0;\n if (!made_progress) break;\n }\n if (lastDrain) this.deps.onSettled(lastDrain);\n })()\n .catch((err) => this.deps.logger.error(err))\n .finally(() => {\n this._running = false;\n });\n }, debounceMs);\n }\n\n /** Cancel any pending or active settle cycle. Idempotent. */\n stop(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n","/**\n * @module act-builder\n * @category Builders\n *\n * Fluent builder for composing event-sourced applications.\n */\nimport { Act, type ActOptions } from \"../act.js\";\nimport {\n _this_,\n currentVersionOf,\n deprecatedEventNames,\n mergeEventRegister,\n mergeProjection,\n registerState,\n} from \"../internal/index.js\";\nimport { DEFAULT_LANE, log } from \"../ports.js\";\nimport type {\n Actor,\n BatchHandler,\n Committed,\n EventRegister,\n IAct,\n LaneConfig,\n Reaction,\n ReactionOptions,\n ReactionResolver,\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n Snapshot,\n State,\n} from \"../types/index.js\";\nimport type { Projection } from \"./projection-builder.js\";\nimport type { Slice } from \"./slice-builder.js\";\n\n/**\n * Registers a projection's batch handler against its target stream, throwing\n * if a different handler is already registered for the same target. Two\n * projections silently overwriting each other's batch handlers used to be a\n * latent footgun.\n */\nfunction registerBatchHandler(\n proj: Projection<any>,\n batchHandlers: Map<string, BatchHandler<any>>\n): void {\n if (!proj.batchHandler || !proj.target) return;\n const existing = batchHandlers.get(proj.target);\n if (existing && existing !== proj.batchHandler) {\n throw new Error(`Duplicate batch handler for target \"${proj.target}\"`);\n }\n batchHandlers.set(proj.target, proj.batchHandler);\n}\n\n/**\n * Runtime backstop for slice-declared lane references — rejects\n * static `.to({lane})` entries that aren't in the declared set.\n * Inline reactions are caught at compile time; this only fires for\n * slices built against older type definitions.\n */\nfunction validateLaneReferences(\n registry: Registry<any, any, any>,\n lanes: ReadonlyArray<LaneConfig>\n): void {\n const declared = new Set<string>([DEFAULT_LANE, ...lanes.map((l) => l.name)]);\n for (const [eventName, def] of Object.entries(registry.events)) {\n const entry = def as { reactions: Map<string, Reaction<any, any>> };\n for (const [handlerName, reaction] of entry.reactions) {\n const resolver = reaction.resolver;\n if (typeof resolver === \"function\") continue;\n const lane = (resolver as { lane?: string }).lane;\n if (lane && !declared.has(lane)) {\n throw new Error(\n `Reaction \"${handlerName}\" on \"${eventName}\" targets undeclared lane \"${lane}\". ` +\n `Declared lanes: ${[...declared].map((l) => `\"${l}\"`).join(\", \")}. ` +\n `Add \\`.withLane({ name: \"${lane}\", ... })\\` to act() or correct the .to() declaration.`\n );\n }\n }\n }\n}\n\n/**\n * Fluent builder interface for composing event-sourced applications.\n *\n * Provides a chainable API for:\n * - Registering states via `.withState()`\n * - Registering slices via `.withSlice()`\n * - Registering projections via `.withProjection()`\n * - Locking a custom actor type via `.withActor<TActor>()`\n * - Declaring drain lanes via `.withLane({name, ...})` (ACT-1103)\n * - Defining event reactions via `.on()` → `.do()` → `.to()`\n * - Building the orchestrator via `.build()`\n *\n * @template TSchemaReg - Schema register for states (maps action names to state schemas)\n * @template TEvents - Event schemas (maps event names to event data schemas)\n * @template TActions - Action schemas (maps action names to action payload schemas)\n * @template TStateMap - Map of state names to state schemas\n * @template TActor - Actor type extending base Actor\n * @template TLanes - Union of declared lane names (ACT-1103). Narrowed by\n * `.withLane({name})` calls so `.to({lane})` and `ActOptions.onlyLanes`\n * reject typos at compile time. Starts at `\"default\"`.\n *\n * @see {@link act} for usage examples\n * @see {@link Act} for the built orchestrator API\n */\nexport type ActBuilder<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n TLanes extends string = typeof DEFAULT_LANE,\n> = {\n /**\n * Registers a state definition with the builder.\n *\n * State names, action names, and event names must be unique across the\n * application (partial states with the same name are merged automatically).\n *\n * @throws {Error} If duplicate action or event names are detected\n */\n withState: <\n TNewState extends Schema,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n TNewName extends string = string,\n >(\n state: State<TNewState, TNewEvents, TNewActions, TNewName>\n ) => ActBuilder<\n TSchemaReg & { [K in keyof TNewActions]: TNewState },\n TEvents & TNewEvents,\n TActions & TNewActions,\n TStateMap & { [K in TNewName]: TNewState },\n TActor,\n TLanes\n >;\n /**\n * Registers a slice with the builder.\n *\n * Merges all the slice's states and reactions into the application.\n * State names, action names, and event names must be unique across the\n * application (partial states with the same name are merged automatically).\n *\n * @throws {Error} If duplicate action or event names are detected\n */\n withSlice: <\n TNewSchemaReg extends SchemaRegister<TNewActions>,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n TNewMap extends Record<string, Schema>,\n TNewLanes extends string,\n >(\n slice: Slice<\n TNewSchemaReg,\n TNewEvents,\n TNewActions,\n TNewMap,\n Actor,\n TNewLanes\n >\n ) => ActBuilder<\n TSchemaReg & TNewSchemaReg,\n TEvents & TNewEvents,\n TActions & TNewActions,\n TStateMap & TNewMap,\n TActor,\n TLanes | TNewLanes\n >;\n /**\n * Registers a standalone projection with the builder.\n *\n * The projection's events must be a subset of events already registered\n * via `.withState()` or `.withSlice()`.\n */\n withProjection: <TNewEvents extends Schemas>(\n projection: [Exclude<keyof TNewEvents, keyof TEvents>] extends [never]\n ? Projection<TNewEvents>\n : never\n ) => ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\n /**\n * Locks a custom actor type for this application.\n *\n * This is a pure type-level method — it returns the same builder at\n * runtime but narrows the `TActor` generic so that `app.do()` and\n * reaction dispatchers require the richer actor shape.\n *\n * @template TNewActor - Custom actor type extending base Actor\n * @returns The same builder with `TActor` locked to `TNewActor`\n *\n * @example\n * ```typescript\n * type MyActor = { id: string; name: string; role: string; tenantId: string };\n *\n * const app = act()\n * .withActor<MyActor>()\n * .withState(Counter)\n * .build();\n *\n * // Now app.do() requires MyActor in the target\n * await app.do(\"increment\", {\n * stream: \"counter-1\",\n * actor: { id: \"1\", name: \"Alice\", role: \"admin\", tenantId: \"t1\" }\n * }, { by: 5 });\n * ```\n */\n withActor: <TNewActor extends Actor>() => ActBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TNewActor,\n TLanes\n >;\n /**\n * Declares a drain lane (ACT-1103). Lane name narrows `TLanes` so\n * `.to({lane})` and `ActOptions.onlyLanes` type-check against it.\n *\n * @example\n * ```typescript\n * const app = act()\n * .withState(Counter)\n * .withLane({ name: \"slow\", leaseMillis: 60_000, streamLimit: 5 })\n * .on(\"OrderConfirmed\")\n * .do(deliverWebhook)\n * .to({ target: \"webhooks-out\", lane: \"slow\" })\n * .build();\n * ```\n */\n withLane: <const TConfig extends LaneConfig>(\n config: TConfig\n ) => ActBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes | TConfig[\"name\"]\n >;\n /**\n * Begins defining a reaction to a specific event.\n *\n * Reactions are event handlers that respond to state changes. They can trigger\n * additional actions, update external systems, or perform side effects. Reactions\n * are processed asynchronously during drain cycles.\n *\n * @template TKey - Event name (must be a registered event)\n * @param event - The event name to react to\n * @returns An object with `.do()` method to define the reaction handler\n */\n on: <TKey extends keyof TEvents>(\n event: TKey\n ) => {\n do: (\n handler: (\n event: Committed<TEvents, TKey>,\n stream: string,\n app: IAct<TEvents, TActions, TActor>\n ) => Promise<Snapshot<Schema, TEvents> | void>,\n options?: Partial<ReactionOptions>\n ) => ActBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes\n > & {\n to: (\n resolver: ReactionResolver<TEvents, TKey, TLanes> | string\n ) => ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\n };\n };\n /**\n * Builds and returns the Act orchestrator instance.\n *\n * @param options - Optional runtime overrides (see {@link ActOptions}).\n * `options.onlyLanes` is narrowed to the declared `TLanes` union, so\n * `onlyLanes: [\"typo\"]` is a compile error when the lane wasn't\n * declared via `.withLane(...)`.\n * @returns The Act orchestrator instance\n *\n * @see {@link Act} for available orchestrator methods\n */\n build: (\n options?: ActOptions<TLanes>\n ) => Act<TSchemaReg, TEvents, TActions, TStateMap, TActor>;\n /**\n * The registered event schemas and their reaction maps.\n */\n readonly events: EventRegister<TEvents>;\n};\n\n/* eslint-disable @typescript-eslint/no-empty-object-type -- {} used as generic defaults */\n\n/**\n * Creates a new Act orchestrator builder for composing event-sourced applications.\n *\n * @example Basic application with single state\n * ```typescript\n * const app = act()\n * .withState(Counter)\n * .build();\n * ```\n *\n * @example Application with custom actor type\n * ```typescript\n * type MyActor = { id: string; name: string; role: string };\n *\n * const app = act()\n * .withActor<MyActor>()\n * .withState(Counter)\n * .build();\n * ```\n *\n * @example Application with slices (vertical slice architecture)\n * ```typescript\n * const CounterSlice = slice()\n * .withState(Counter)\n * .on(\"Incremented\")\n * .do(async (event) => { console.log(\"incremented!\"); })\n * .to(\"counter-target\")\n * .build();\n *\n * const app = act()\n * .withSlice(CounterSlice)\n * .build();\n * ```\n *\n *\n * @see {@link ActBuilder} for available builder methods\n * @see {@link Act} for orchestrator API methods\n * @see {@link state} for defining states\n * @see {@link slice} for defining slices\n */\nexport function act<\n // @ts-expect-error empty schema\n TSchemaReg extends SchemaRegister<TActions> = {},\n TEvents extends Schemas = {},\n TActions extends Schemas = {},\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n>(): ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor> {\n // Mutable runtime state — one set of references shared across the entire\n // fluent chain. Each `with*` / `on` call mutates these and returns the\n // same builder cast to the widened generic; type fanout is preserved\n // through the public type signatures, runtime allocation is not.\n const states = new Map<string, State<any, any, any>>();\n const registry: Registry<TSchemaReg, TEvents, TActions> = {\n actions: {} as Registry<TSchemaReg, TEvents, TActions>[\"actions\"],\n events: {} as Registry<TSchemaReg, TEvents, TActions>[\"events\"],\n };\n const pendingProjections: Projection<any>[] = [];\n const batchHandlers = new Map<string, BatchHandler<any>>();\n const lanes: LaneConfig[] = [];\n\n // Set on the first `.build()` call. Lets the same builder produce\n // many Acts (multi-tenant / A-B testing patterns) without re-merging\n // projections or re-logging the deprecation advisory.\n let _built = false;\n\n // ACT-403: auto-deprecation enforcement. Groups each state's events\n // by base name + `_v<digits>`; the highest version is current, all\n // lower ones are deprecated. Stashes the deprecation set on the\n // state so `event-sourcing.ts` can warn at runtime for dynamic\n // emits. Scans static `.emit(\"X\")` markers across every state and\n // throws if any target a deprecated event — the only legitimate use\n // of a deprecated event is on the reduce path. Finally, surfaces a\n // one-line startup advisory so operators can see \"your app has\n // legacy events kept for the read path, here's where they live.\"\n const finalizeDeprecations = () => {\n const deprecationSummary: Array<{\n stateName: string;\n deprecated: string;\n current: string;\n }> = [];\n for (const state of states.values()) {\n const eventNames = Object.keys(state.events);\n const deprecated = deprecatedEventNames(eventNames);\n if (deprecated.size === 0) continue;\n (state as { _deprecated?: Set<string> })._deprecated = deprecated;\n for (const name of deprecated) {\n // `currentVersionOf` is guaranteed non-undefined here — `name`\n // is in `deprecated`, which by construction means a higher-\n // versioned sibling exists in the same group.\n const current = currentVersionOf(name, eventNames) as string;\n deprecationSummary.push({\n stateName: state.name,\n deprecated: name,\n current,\n });\n }\n for (const [actionName, handler] of Object.entries(state.on)) {\n const staticTarget = (handler as { _staticEmit?: string } | undefined)\n ?._staticEmit;\n if (staticTarget && deprecated.has(staticTarget)) {\n const current = currentVersionOf(staticTarget, eventNames);\n throw new Error(\n `Action \"${actionName}\" in state \"${state.name}\" emits deprecated event \"${staticTarget}\". ` +\n `A newer version exists: \"${current}\". Update the .emit() call ` +\n `to target the current version. The reducer (.patch) for ` +\n `\"${staticTarget}\" stays as-is — historical events still need it.`\n );\n }\n }\n }\n if (deprecationSummary.length > 0) {\n const list = deprecationSummary\n .map(\n (d) =>\n `\"${d.deprecated}\" (current: \"${d.current}\", state: \"${d.stateName}\")`\n )\n .join(\", \");\n log().info(\n `Act registered ${deprecationSummary.length} deprecated event(s): ${list}. ` +\n `These are legacy versions kept for the read path. Consider truncating ` +\n `closed streams via app.close() when feasible to reduce historical event load. ` +\n `See docs/docs/architecture/event-schema-evolution.md.`\n );\n }\n };\n\n // The `as` chain on `self` is the type fanout: each fluent method\n // mutates state and returns `self` cast to its post-call generic\n // signature. Internal-only — public types stay narrow.\n const builder: ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor> =\n {\n withState: (state) => {\n registerState(state, states, registry.actions, registry.events);\n return builder as never;\n },\n withSlice: (input) => {\n for (const s of input.states.values()) {\n registerState(s, states, registry.actions, registry.events);\n }\n mergeEventRegister(registry.events, input.events);\n pendingProjections.push(...input.projections);\n for (const sliceLane of input.lanes) {\n const existing = lanes.find((l) => l.name === sliceLane.name);\n if (!existing) {\n lanes.push(sliceLane);\n continue;\n }\n if (\n existing.leaseMillis !== sliceLane.leaseMillis ||\n existing.streamLimit !== sliceLane.streamLimit ||\n existing.cycleMs !== sliceLane.cycleMs\n ) {\n throw new Error(\n `Lane \"${sliceLane.name}\" was already declared with a different config`\n );\n }\n }\n return builder as never;\n },\n withProjection: (proj) => {\n mergeProjection(proj as Projection<any>, registry.events);\n registerBatchHandler(proj as Projection<any>, batchHandlers);\n return builder;\n },\n withActor: <TNewActor extends Actor>() =>\n builder as unknown as ActBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TNewActor\n >,\n withLane: (config) => {\n if (config.name === DEFAULT_LANE)\n throw new Error(`Lane \"${DEFAULT_LANE}\" is reserved`);\n if (lanes.some((l) => l.name === config.name))\n throw new Error(`Lane \"${config.name}\" was already declared`);\n lanes.push(config);\n return builder as never;\n },\n on: <TKey extends keyof TEvents>(event: TKey) => ({\n do: (\n handler: (\n event: Committed<TEvents, TKey>,\n stream: string,\n app: IAct<TEvents, TActions, TActor>\n ) => Promise<Snapshot<Schema, TEvents> | void>,\n options?: Partial<ReactionOptions>\n ) => {\n const reaction: Reaction<TEvents, TKey, TActions, TActor> = {\n handler: handler,\n resolver: _this_,\n options: {\n blockOnError: options?.blockOnError ?? true,\n maxRetries: options?.maxRetries ?? 3,\n backoff: options?.backoff,\n },\n };\n if (!handler.name)\n throw new Error(\n `Reaction handler for \"${String(event)}\" must be a named function`\n );\n // Register once with the default _this_ resolver. If `.to()` is\n // chained next, it patches the same reaction's resolver in place\n // — no second Map.set() round-trip.\n registry.events[event].reactions.set(handler.name, reaction);\n return Object.assign(builder, {\n to(resolver: ReactionResolver<TEvents, TKey> | string) {\n reaction.resolver =\n typeof resolver === \"string\" ? { target: resolver } : resolver;\n return builder;\n },\n });\n },\n }),\n build: (options?: ActOptions) => {\n // One-time finalize: merge pending projections and run the\n // deprecation scan + advisory log exactly once. Calling\n // `.build({scoped: ...})` repeatedly (e.g., per tenant) is\n // supported — see extension-points.md § Scoped ports. Without\n // this guard, `mergeProjection` would re-add reactions to the\n // shared registry on every call (accumulating `_p`/`_p_p`\n // dedupe suffixes), and the deprecation advisory would log on\n // every tenant.\n if (!_built) {\n for (const proj of pendingProjections) {\n mergeProjection(proj, registry.events as Record<string, any>);\n registerBatchHandler(proj, batchHandlers);\n }\n finalizeDeprecations();\n validateLaneReferences(registry, lanes);\n _built = true;\n }\n\n return new Act<TSchemaReg, TEvents, TActions, TStateMap, TActor>(\n registry,\n states,\n batchHandlers,\n options,\n lanes\n );\n },\n events: registry.events,\n };\n return builder;\n}\n","/**\n * @module projection-builder\n * @category Builders\n *\n * Fluent builder for composing projection handlers — read-model updaters\n * that react to events and update external state (databases, caches, etc.).\n *\n * Projections differ from slices: they don't contain states, don't dispatch\n * actions, and are pure side-effect handlers routed to a named stream.\n */\nimport type { ZodType } from \"zod\";\nimport { _this_ } from \"../internal/index.js\";\nimport type {\n BatchHandler,\n Committed,\n EventRegister,\n Reaction,\n ReactionResolver,\n Schema,\n Schemas,\n} from \"../types/index.js\";\n\n/**\n * A self-contained projection grouping read-model update handlers.\n * Projections are composed into an Act orchestrator via `act().withProjection(projection)`.\n *\n * @template TEvents - Event schemas handled by this projection\n */\nexport type Projection<TEvents extends Schemas> = {\n readonly _tag: \"Projection\";\n readonly events: EventRegister<TEvents>;\n readonly target?: string;\n readonly batchHandler?: BatchHandler<TEvents>;\n};\n\n/** Helper: a single-key record mapping an event name to its Zod schema. */\ntype EventEntry<TKey extends string = string, TData extends Schema = Schema> = {\n [P in TKey]: ZodType<TData>;\n};\n\n/** Infer the handler-result type after registering one event. */\ntype DoResult<\n TEvents extends Schemas,\n TKey extends string,\n TData extends Schema,\n TTarget extends string | undefined = undefined,\n> = ProjectionBuilder<TEvents & { [P in TKey]: TData }, TTarget> & {\n to: (\n resolver: ReactionResolver<TEvents & { [P in TKey]: TData }, TKey> | string\n ) => ProjectionBuilder<TEvents & { [P in TKey]: TData }, TTarget>;\n};\n\n/**\n * Fluent builder interface for composing projections.\n *\n * When a static target is provided via `projection(\"target\")`, the builder\n * exposes a `.batch()` method for registering a batch handler that processes\n * all events in a single call.\n *\n * @template TEvents - Event schemas\n * @template TTarget - Static target string or undefined\n */\nexport type ProjectionBuilder<\n TEvents extends Schemas,\n TTarget extends string | undefined = undefined,\n> = {\n /**\n * Begins defining a projection handler for a specific event.\n *\n * Pass a `{ EventName: schema }` record — use shorthand `{ EventName }`\n * when the variable name matches the event name. The key becomes the\n * event name, the value the Zod schema.\n */\n on: <TKey extends string, TData extends Schema>(\n entry: EventEntry<TKey, TData>\n ) => {\n do: (\n handler: (\n event: Committed<TEvents & { [P in TKey]: TData }, TKey>,\n stream: string\n ) => Promise<void>\n ) => DoResult<TEvents, TKey, TData, TTarget>;\n };\n /**\n * Builds and returns the Projection data structure.\n */\n build: () => Projection<TEvents>;\n /**\n * The registered event schemas and their reaction maps.\n */\n readonly events: EventRegister<TEvents>;\n} & (TTarget extends string\n ? {\n /**\n * Registers a batch handler that processes all events in a single call.\n *\n * Only available on projections with a static target (`projection(\"target\")`).\n * The handler receives a discriminated union of all declared events,\n * enabling bulk DB operations in a single transaction.\n *\n * When defined, the batch handler is always called — even for a single event.\n * Individual `.do()` handlers serve as fallback for projections without `.batch()`.\n */\n batch: (handler: BatchHandler<TEvents>) => {\n build: () => Projection<TEvents>;\n };\n }\n : // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n {});\n\n/* eslint-disable @typescript-eslint/no-empty-object-type -- {} used as generic defaults */\n\n/**\n * Creates a new projection builder for composing read-model update handlers.\n *\n * Projections enable separation of read-model concerns from command handling.\n * Each `.on({ Event }).do(handler)` call registers a handler that updates\n * a projection (database table, cache, etc.) in response to events.\n *\n * Pass a target stream name to `projection(\"target\")` so every handler\n * inherits that resolver automatically. Omit it and use per-handler\n * `.to()` when handlers route to different streams.\n *\n * @param target - Optional default target stream for all handlers\n *\n * @example Default target (all handlers routed to \"tickets\")\n * ```typescript\n * const TicketProjection = projection(\"tickets\")\n * .on({ TicketOpened })\n * .do(async ({ stream, data }) => {\n * await db.insert(tickets).values({ id: stream, ...data });\n * })\n * .on({ TicketClosed })\n * .do(async ({ stream, data }) => {\n * await db.update(tickets).set(data).where(eq(tickets.id, stream));\n * })\n * .build();\n * ```\n *\n * @example Per-handler routing\n * ```typescript\n * const MultiProjection = projection()\n * .on({ OrderPlaced })\n * .do(async (event) => { ... })\n * .to(\"orders\")\n * .on({ PaymentReceived })\n * .do(async (event) => { ... })\n * .to(\"payments\")\n * .build();\n * ```\n *\n * @see {@link ProjectionBuilder} for builder methods\n * @see {@link Projection} for the output type\n */\n/**\n * @internal Build the core builder object (shared between overloads). One\n * mutable `events` register threaded through every fluent call; .on()\n * mutates and returns the same builder cast to its widened generic.\n */\nfunction _projection<\n TEvents extends Schemas,\n TTarget extends string | undefined,\n>(target: TTarget): ProjectionBuilder<TEvents, TTarget> {\n const events = {} as EventRegister<TEvents>;\n const defaultResolver: { target: string } | undefined =\n typeof target === \"string\" ? { target } : undefined;\n\n // Mutable runtime bag — typed loosely; the public projection() return\n // type narrows back to the user-facing `ProjectionBuilder<TEvents, TTarget>`.\n\n const base: any = {\n on: <TKey extends string, TData extends Schema>(\n entry: EventEntry<TKey, TData>\n ) => {\n const keys = Object.keys(entry);\n if (keys.length !== 1) throw new Error(\".on() requires exactly one key\");\n const event = keys[0] as TKey;\n const schema = entry[event];\n\n // Register the event schema if not already present\n if (!(event in events)) {\n (events as Record<string, unknown>)[event] = {\n schema,\n reactions: new Map(),\n };\n }\n\n return {\n do: (\n handler: (\n event: Committed<TEvents & { [P in TKey]: TData }, TKey>,\n stream: string\n ) => Promise<void>\n ) => {\n const reaction: Reaction<TEvents & { [P in TKey]: TData }, TKey> = {\n handler: handler,\n resolver: defaultResolver ?? _this_,\n options: {\n blockOnError: true,\n maxRetries: 3,\n },\n };\n const register = (events as Record<string, any>)[event];\n if (!handler.name)\n throw new Error(\n `Projection handler for \"${event}\" must be a named function`\n );\n register.reactions.set(handler.name, reaction);\n\n // Same builder, widened generic — no recursive call.\n const widened = base as unknown as ProjectionBuilder<\n TEvents & { [P in TKey]: TData },\n TTarget\n >;\n return Object.assign(widened, {\n to(\n resolver:\n | ReactionResolver<TEvents & { [P in TKey]: TData }, TKey>\n | string\n ) {\n // Patch the same reaction in place — no second Map.set().\n reaction.resolver =\n typeof resolver === \"string\" ? { target: resolver } : resolver;\n return widened;\n },\n });\n },\n };\n },\n build: () => ({\n _tag: \"Projection\" as const,\n events,\n ...(target !== undefined && { target }),\n }),\n events,\n };\n\n // Add .batch() only for static-target projections\n if (typeof target === \"string\") {\n return Object.assign(base, {\n batch: (handler: BatchHandler<TEvents>) => ({\n build: () => ({\n _tag: \"Projection\" as const,\n events,\n target,\n batchHandler: handler,\n }),\n }),\n }) as ProjectionBuilder<TEvents, TTarget>;\n }\n\n return base as ProjectionBuilder<TEvents, TTarget>;\n}\n\n/**\n * Creates a new projection builder with a static target stream.\n *\n * All handlers inherit the target resolver automatically. Enables `.batch()`\n * for bulk event processing in a single transaction.\n *\n * @param target - Static target stream for all handlers\n */\nexport function projection<TEvents extends Schemas = {}>(\n target: string\n): ProjectionBuilder<TEvents, string>;\n/**\n * Creates a new projection builder without a default target.\n *\n * Use per-handler `.to()` to route events to different streams.\n */\nexport function projection<TEvents extends Schemas = {}>(\n target?: undefined\n): ProjectionBuilder<TEvents, undefined>;\nexport function projection<TEvents extends Schemas = {}>(\n target?: string\n): ProjectionBuilder<TEvents, string | undefined> {\n return _projection<TEvents, string | undefined>(target);\n}\n","/**\n * @module slice-builder\n * @category Builders\n *\n * Fluent builder for composing partial states with scoped reactions into\n * self-contained functional slices (vertical slice architecture).\n */\nimport { _this_, registerState } from \"../internal/index.js\";\nimport { DEFAULT_LANE } from \"../ports.js\";\nimport type {\n Actor,\n Committed,\n EventRegister,\n IAct,\n LaneConfig,\n Reaction,\n ReactionOptions,\n ReactionResolver,\n Schema,\n SchemaRegister,\n Schemas,\n Snapshot,\n State,\n} from \"../types/index.js\";\nimport type { Projection } from \"./projection-builder.js\";\n\n/**\n * A self-contained functional slice grouping partial states with their\n * scoped reactions. Slices are composed into an Act orchestrator via\n * `act().withSlice(slice)`.\n *\n * @template TSchemaReg - Schema register for states\n * @template TEvents - Event schemas from this slice's states\n * @template TActions - Action schemas from this slice's states\n * @template TStateMap - Map of state names to state schemas\n * @template TActor - Actor type extending base Actor\n */\nexport type Slice<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n TLanes extends string = typeof DEFAULT_LANE,\n> = {\n readonly _tag: \"Slice\";\n readonly states: Map<string, State<any, any, any>>;\n readonly events: EventRegister<TEvents>;\n readonly projections: ReadonlyArray<Projection<any>>;\n /**\n * Drain lanes declared on this slice via `.withLane(...)` (ACT-1103).\n * `act().withSlice(slice)` merges these into the Act's lane set so\n * `.to({lane})` is statically checked at the slice's call site against\n * the lanes the slice itself declared.\n */\n readonly lanes: ReadonlyArray<LaneConfig>;\n /** @internal phantom field for type-level state schema tracking */\n readonly _S?: TSchemaReg;\n /** @internal phantom field for type-level state name tracking */\n readonly _M?: TStateMap;\n /** @internal phantom field for type-level actor tracking */\n readonly _TActor?: TActor;\n /** @internal phantom field for type-level lane union tracking */\n readonly _TLanes?: TLanes;\n};\n\n/**\n * Fluent builder interface for composing functional slices.\n *\n * Provides a chainable API for registering states and projections,\n * and defining reactions scoped to the slice's own events.\n *\n * @template TSchemaReg - Schema register for states\n * @template TEvents - Event schemas\n * @template TActions - Action schemas\n * @template TStateMap - Map of state names to state schemas\n * @template TActor - Actor type extending base Actor\n */\nexport type SliceBuilder<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n TLanes extends string = typeof DEFAULT_LANE,\n> = {\n /**\n * Registers a state definition with the slice.\n *\n * Include every state whose actions your reaction handlers need to\n * dispatch. Duplicate registrations (same state in multiple slices)\n * are handled automatically at composition time.\n */\n withState: <\n TNewState extends Schema,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n TNewName extends string = string,\n >(\n state: State<TNewState, TNewEvents, TNewActions, TNewName>\n ) => SliceBuilder<\n TSchemaReg & { [K in keyof TNewActions]: TNewState },\n TEvents & TNewEvents,\n TActions & TNewActions,\n TStateMap & { [K in TNewName]: TNewState },\n TActor,\n TLanes\n >;\n /**\n * Embeds a built Projection within this slice. The projection's events\n * must be a subset of events from states already registered via\n * `.withState()`. Projection handlers preserve their `(event, stream)`\n * signature and do not receive the app interface.\n */\n withProjection: <TNewEvents extends Schemas>(\n projection: [Exclude<keyof TNewEvents, keyof TEvents>] extends [never]\n ? Projection<TNewEvents>\n : never\n ) => SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\n /**\n * Declares a drain lane on this slice (ACT-1103). Merged into the\n * parent Act's lane set by `act().withSlice(slice)`.\n */\n withLane: <const TConfig extends LaneConfig>(\n config: TConfig\n ) => SliceBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes | TConfig[\"name\"]\n >;\n /**\n * Begins defining a reaction scoped to this slice's events.\n */\n on: <TKey extends keyof TEvents>(\n event: TKey\n ) => {\n do: (\n handler: (\n event: Committed<TEvents, TKey>,\n stream: string,\n app: IAct<TEvents, TActions, TActor>\n ) => Promise<Snapshot<Schema, TEvents> | void>,\n options?: Partial<ReactionOptions>\n ) => SliceBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes\n > & {\n to: (\n resolver: ReactionResolver<TEvents, TKey, TLanes> | string\n ) => SliceBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes\n >;\n };\n };\n /**\n * Builds and returns the Slice data structure.\n */\n build: () => Slice<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\n /**\n * The registered event schemas and their reaction maps.\n */\n readonly events: EventRegister<TEvents>;\n};\n\n/* eslint-disable @typescript-eslint/no-empty-object-type -- {} used as generic defaults */\n\n/**\n * Creates a new slice builder for composing partial states with scoped reactions.\n *\n * Slices enable vertical slice architecture by grouping related states and\n * reactions into self-contained feature modules. Reactions defined in a slice\n * are type-scoped to events from that slice's states only.\n *\n * @example Single-state slice with typed dispatch\n * ```typescript\n * const CounterSlice = slice()\n * .withState(Counter)\n * .on(\"Incremented\")\n * .do(async (event, _stream, app) => {\n * await app.do(\"reset\", target, {});\n * })\n * .to(\"counter-target\")\n * .build();\n * ```\n *\n * @example Cross-state dispatch (include both states)\n * ```typescript\n * const CreationSlice = slice()\n * .withState(TicketCreation)\n * .withState(TicketOperations) // handler can dispatch AssignTicket\n * .on(\"TicketOpened\").do(async (event, _stream, app) => {\n * await app.do(\"AssignTicket\", target, payload, event);\n * })\n * .build();\n * ```\n *\n * @see {@link SliceBuilder} for builder methods\n * @see {@link Slice} for the output type\n */\nexport function slice<\n // @ts-expect-error empty schema\n TSchemaReg extends SchemaRegister<TActions> = {},\n TEvents extends Schemas = {},\n TActions extends Schemas = {},\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n>(): SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor> {\n // One mutable state shared across the entire fluent chain. Each\n // `withState` / `withProjection` / `on` call mutates these and returns\n // the same builder cast to the widened generic; type fanout is preserved\n // through the public type signatures, runtime allocation is not.\n const states = new Map<string, State<any, any, any>>();\n const actions: Record<string, any> = {};\n const events = {} as EventRegister<TEvents>;\n const projections: Projection<any>[] = [];\n const lanes: LaneConfig[] = [];\n\n const builder: SliceBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor\n > = {\n withState: (state) => {\n registerState(state, states, actions, events as Record<string, unknown>);\n return builder as never;\n },\n withProjection: (proj) => {\n projections.push(proj as Projection<any>);\n return builder;\n },\n withLane: (config) => {\n if (config.name === DEFAULT_LANE)\n throw new Error(`Lane \"${DEFAULT_LANE}\" is reserved`);\n if (lanes.some((l) => l.name === config.name))\n throw new Error(`Lane \"${config.name}\" was already declared`);\n lanes.push(config);\n return builder as never;\n },\n on: <TKey extends keyof TEvents>(event: TKey) => ({\n do: (\n handler: (\n event: Committed<TEvents, TKey>,\n stream: string,\n app: IAct<TEvents, TActions, TActor>\n ) => Promise<Snapshot<Schema, TEvents> | void>,\n options?: Partial<ReactionOptions>\n ) => {\n const reaction: Reaction<TEvents, TKey, TActions, TActor> = {\n handler: handler,\n resolver: _this_,\n options: {\n blockOnError: options?.blockOnError ?? true,\n maxRetries: options?.maxRetries ?? 3,\n backoff: options?.backoff,\n },\n };\n if (!handler.name)\n throw new Error(\n `Reaction handler for \"${String(event)}\" must be a named function`\n );\n // Register once with the default _this_ resolver. If `.to()` is\n // chained next, it patches the same reaction's resolver in place\n // — no second Map.set() round-trip.\n events[event].reactions.set(handler.name, reaction);\n return Object.assign(builder, {\n to(resolver: ReactionResolver<TEvents, TKey> | string) {\n reaction.resolver =\n typeof resolver === \"string\" ? { target: resolver } : resolver;\n return builder;\n },\n });\n },\n }),\n build: () => ({\n _tag: \"Slice\" as const,\n states,\n events,\n projections,\n lanes,\n }),\n events,\n };\n return builder;\n}\n","/**\n * @module state-builder\n * @category Builders\n *\n * Fluent interface for defining a strongly-typed state machine using Zod schemas.\n */\nimport type { ZodType } from \"zod\";\nimport type {\n ActionHandler,\n GivenHandlers,\n Invariant,\n PassthroughPatchHandler,\n PatchHandlers,\n Schema,\n Schemas,\n Snapshot,\n State,\n ZodTypes,\n} from \"../types/index.js\";\n\n/**\n * Builder interface for defining a state with event sourcing.\n *\n * Provides a fluent API to configure the initial state, event types,\n * and event handlers (reducers) before moving to action configuration.\n *\n * @template TState - State schema type\n * @template TName - State name literal type\n *\n * @see {@link state} for usage examples\n * @see {@link ActionBuilder} for action configuration\n */\nexport type StateBuilder<\n TState extends Schema,\n TName extends string = string,\n> = {\n /**\n * Defines the initial state for new state instances.\n *\n * The init function is called when a new stream is created (first event).\n * It can accept initial data or return a default state.\n *\n * @param init - Function returning the initial state\n * @returns A builder with `.emits()` to declare event types\n *\n * @example\n * ```typescript\n * .init(() => ({ count: 0, created: new Date() }))\n * ```\n *\n * @example With initial data\n * ```typescript\n * .init((data) => ({ ...data, createdAt: new Date() }))\n * ```\n */\n init: (init: () => Readonly<TState>) => {\n /**\n * Declares the event types that this state can emit.\n *\n * Events represent facts that have happened - they should be named in past tense.\n * Each event is defined with a Zod schema for type safety and runtime validation.\n *\n * @template TEvents - Event schemas type\n * @param events - Object mapping event names to Zod schemas\n * @returns An ActionBuilder (with optional `.patch()` to override specific reducers)\n *\n * @example\n * ```typescript\n * .emits({\n * Incremented: z.object({ amount: z.number() }),\n * Decremented: z.object({ amount: z.number() }),\n * Reset: z.object({})\n * })\n * ```\n */\n emits: <TEvents extends Schemas>(\n events: ZodTypes<TEvents>\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- {} avoids string index signature that Record<string, never> would add, keeping keyof A precise\n ) => ActionBuilder<TState, TEvents, {}, TName> & {\n /**\n * Overrides specific event reducers. Events without a custom patch\n * default to passthrough: `({ data }) => data` (event data merges\n * into state).\n *\n * @param patch - Partial map of event names to patch handler functions\n * @returns An ActionBuilder for defining actions\n *\n * @example Only override the events that need custom logic\n * ```typescript\n * .emits({ TicketOpened, TicketClosed, TicketResolved })\n * .patch({\n * TicketOpened: ({ data }) => {\n * const { message, messageId, userId, ...other } = data;\n * return { ...other, userId, messages: { [messageId]: { ... } } };\n * },\n * })\n * // TicketClosed and TicketResolved use passthrough\n * ```\n */\n patch: (\n patch: Partial<PatchHandlers<TState, TEvents>>\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- {} avoids string index signature that Record<string, never> would add, keeping keyof A precise\n ) => ActionBuilder<TState, TEvents, {}, TName>;\n };\n };\n};\n\n/** Helper: a single-key record mapping a state name to its Zod schema. */\ntype StateEntry<\n TKey extends string = string,\n TState extends Schema = Schema,\n> = {\n [P in TKey]: ZodType<TState>;\n};\n\n/** Helper: a single-key record mapping an action name to its Zod schema. */\ntype ActionEntry<\n TKey extends string = string,\n TNewActions extends Schema = Schema,\n> = {\n [P in TKey]: ZodType<TNewActions>;\n};\n\n/**\n * Builder interface for defining actions (commands) on a state.\n *\n * Actions represent user/system intents to modify state. Each action is validated\n * against a schema, can have business rule invariants, and must emit one or more events.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TName - State name literal type\n *\n * @see {@link state} for complete usage examples\n */\nexport type ActionBuilder<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TName extends string = string,\n> = {\n /**\n * Defines an action (command) that can be executed on this state.\n *\n * Actions represent intents to change state - they should be named in imperative form\n * (e.g., \"CreateUser\", \"IncrementCounter\", \"PlaceOrder\"). Actions are validated against\n * their schema and must emit at least one event.\n *\n * Pass a `{ ActionName: schema }` record — use shorthand `{ ActionName }`\n * when the variable name matches the action name. The key becomes the\n * action name, the value the Zod schema.\n *\n * @template TKey - Action name (string literal type)\n * @template TNewActions - Action payload schema type\n * @param entry - Single-key record `{ ActionName: schema }`\n * @returns An object with `.given()` and `.emit()` for further configuration\n *\n * @example Simple action without invariants\n * ```typescript\n * .on({ increment: z.object({ by: z.number() }) })\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * ```\n *\n * @example Action with business rules\n * ```typescript\n * .on({ withdraw: z.object({ amount: z.number() }) })\n * .given([\n * (_, snap) => snap.state.balance >= 0 || \"Account closed\",\n * (_, snap, action) => snap.state.balance >= action.amount || \"Insufficient funds\"\n * ])\n * .emit((action) => [\"Withdrawn\", { amount: action.amount }])\n * ```\n *\n * @example Action with shorthand (variable name matches action name)\n * ```typescript\n * const OpenTicket = z.object({ title: z.string() });\n * .on({ OpenTicket })\n * .emit((action) => [\"TicketOpened\", { title: action.title }])\n * ```\n */\n on: <TKey extends string, TNewActions extends Schema>(\n entry: ActionEntry<TKey, TNewActions>\n ) => {\n /**\n * Adds business rule invariants that must hold before the action can execute.\n *\n * Invariants are checked after loading the current state but before emitting events.\n * Each invariant should return `true` or an error message string. All invariants\n * must pass for the action to succeed.\n *\n * @param rules - Array of invariant functions\n * @returns An object with `.emit()` to finalize the action\n *\n * @example\n * ```typescript\n * .given([\n * (_, snap) => snap.state.status === \"active\" || \"Must be active\",\n * (target, snap) => snap.state.ownerId === target.actor.id || \"Not authorized\"\n * ])\n * ```\n */\n given: (rules: Invariant<TState>[]) => {\n /**\n * Defines the action handler that emits events.\n *\n * The handler receives the action payload and current state snapshot,\n * and must return one or more events to emit. Events are applied to state\n * via the patch handlers defined earlier.\n *\n * Pass a string event name for passthrough: the action payload becomes\n * the event data directly.\n *\n * @param handler - Function that returns events to emit, or event name string for passthrough\n * @returns The ActionBuilder for chaining more actions\n *\n * @example Custom handler\n * ```typescript\n * .emit((action, snapshot) => {\n * const newBalance = snapshot.state.balance + action.amount;\n * return [\"Deposited\", { amount: action.amount, newBalance }];\n * })\n * ```\n *\n * @example Passthrough (action payload = event data)\n * ```typescript\n * .emit(\"TicketAssigned\")\n * ```\n */\n emit: {\n /** Custom handler — receives `(action, snapshot)` and returns one\n * or more `[EventName, data]` tuples (or `undefined`). */\n (\n handler: ActionHandler<\n TState,\n TEvents,\n { [P in TKey]: TNewActions },\n TKey\n >\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName\n >;\n /** Passthrough — the action payload becomes the event data\n * directly. Must reference an event declared in `.emits()`. */\n (\n eventName: keyof TEvents & string\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName\n >;\n };\n };\n /**\n * Defines the action handler that emits events. Same two overloads as\n * the post-`.given()` form above:\n *\n * - **Function** — receives `(action, snapshot)` and returns one or\n * more `[EventName, data]` tuples (or `undefined`).\n * - **String** — passthrough: the action payload becomes the event\n * data directly. Must reference an event declared in `.emits()`.\n *\n * The two overloads are kept separate (rather than merged into a\n * `handler | string` union) so that TS contextual typing of the\n * function alternative isn't degraded by considering the string\n * branch — under the union form `TState` could collapse to its\n * `Schema` constraint inside the callback.\n *\n * @example Passthrough (action payload = event data)\n * ```typescript\n * .emit(\"Incremented\")\n * ```\n *\n * @example Single event\n * ```typescript\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * ```\n *\n * @example Multiple events\n * ```typescript\n * .emit((action) => [\n * [\"Incremented\", { amount: action.by }],\n * [\"LogUpdated\", { message: `Incremented by ${action.by}` }]\n * ])\n * ```\n */\n emit: {\n (\n handler: ActionHandler<\n TState,\n TEvents,\n { [P in TKey]: TNewActions },\n TKey\n >\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName\n >;\n (\n eventName: keyof TEvents & string\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName\n >;\n };\n };\n /**\n * Defines a snapshotting strategy to optimize state reconstruction.\n *\n * Snapshots store the current state at a point in time, allowing faster state loading\n * by avoiding replaying all events from the beginning. The snap function is called\n * after each event is applied and should return `true` when a snapshot should be taken.\n *\n * @param snap - Predicate function that returns true when a snapshot should be taken\n * @returns The ActionBuilder for chaining\n *\n * @example Snapshot every 10 events\n * ```typescript\n * .snap((snapshot) => snapshot.patches >= 10)\n * ```\n *\n * @example Snapshot based on state size\n * ```typescript\n * .snap((snapshot) => {\n * const estimatedSize = JSON.stringify(snapshot.state).length;\n * return estimatedSize > 10000 || snapshot.patches >= 50;\n * })\n * ```\n *\n * @example Time-based snapshotting\n * ```typescript\n * .snap((snapshot) => {\n * const hoursSinceLastSnapshot = snapshot.patches * 0.1; // Estimate\n * return hoursSinceLastSnapshot >= 24;\n * })\n * ```\n */\n snap: (\n snap: (snapshot: Snapshot<TState, TEvents>) => boolean\n ) => ActionBuilder<TState, TEvents, TActions, TName>;\n /**\n * Finalizes and builds the state definition.\n *\n * Call this method after defining all actions, invariants, and patches to create\n * the complete State object that can be registered with Act.\n *\n * @returns The complete strongly-typed State definition\n *\n * @example\n * ```typescript\n * const Counter = state({ Counter: schema })\n * .init(() => ({ count: 0 }))\n * .emits({ Incremented: z.object({ amount: z.number() }) })\n * .patch({ Incremented: ({ data }, state) => ({ count: state.count + data.amount }) })\n * .on({ increment: z.object({ by: z.number() }) })\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * .build(); // Returns State<TState, TEvents, TActions, TName>\n * ```\n */\n build: () => State<TState, TEvents, TActions, TName>;\n};\n\n/**\n * Creates a new state definition with event sourcing capabilities.\n *\n * States are the core building blocks of Act. Each state represents a consistency\n * boundary (aggregate) that processes actions, emits events, and maintains its own\n * state through event patches (reducers). States use event sourcing to maintain a\n * complete audit trail and enable time-travel capabilities.\n *\n * The state builder provides a fluent API for defining:\n * 1. Initial state via `.init()`\n * 2. Event types via `.emits()` — all events default to passthrough (`({ data }) => data`)\n * 3. Custom event reducers via `.patch()` (optional — only for events that need custom logic)\n * 4. Actions (commands) via `.on()` → `.emit()` — pass an event name string for passthrough\n * 5. Business rules (invariants) via `.given()`\n * 6. Snapshotting strategy via `.snap()`\n *\n * @template TState - Zod schema type defining the shape of the state\n * @param entry - Single-key record mapping state name to Zod schema (e.g., `{ Counter: z.object({ count: z.number() }) }`)\n * @returns A StateBuilder instance for fluent API configuration\n *\n * @example Basic counter state (with custom patch)\n * ```typescript\n * import { state } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const Counter = state({ Counter: z.object({ count: z.number() }) })\n * .init(() => ({ count: 0 }))\n * .emits({\n * Incremented: z.object({ amount: z.number() })\n * })\n * .patch({ // optional — only for events needing custom reducers\n * Incremented: ({ data }, state) => ({ count: state.count + data.amount })\n * })\n * .on({ increment: z.object({ by: z.number() }) })\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * .build();\n * ```\n *\n * @example Passthrough state (no custom patch or emit needed)\n * ```typescript\n * const DigitBoard = state({ DigitBoard: z.object({ digit: z.string() }) })\n * .init(() => ({ digit: \"\" }))\n * .emits({ DigitCounted: z.object({ digit: z.string() }) })\n * // no .patch() — passthrough is the default (event data merges into state)\n * .on({ CountDigit: z.object({ digit: z.string() }) })\n * .emit(\"DigitCounted\") // string passthrough — action payload becomes event data\n * .build();\n * ```\n *\n * @example State with multiple events and invariants\n * ```typescript\n * const BankAccount = state({ BankAccount: z.object({\n * balance: z.number(),\n * currency: z.string(),\n * status: z.enum([\"open\", \"closed\"])\n * }) })\n * .init(() => ({ balance: 0, currency: \"USD\", status: \"open\" }))\n * .emits({\n * Deposited: z.object({ amount: z.number() }),\n * Withdrawn: z.object({ amount: z.number() }),\n * Closed: z.object({})\n * })\n * .patch({ // only override events needing custom logic\n * Deposited: ({ data }, state) => ({ balance: state.balance + data.amount }),\n * Withdrawn: ({ data }, state) => ({ balance: state.balance - data.amount }),\n * Closed: () => ({ status: \"closed\", balance: 0 })\n * })\n * .on({ deposit: z.object({ amount: z.number() }) })\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Account must be open\"\n * ])\n * .emit(\"Deposited\") // passthrough — action payload { amount } becomes event data\n * .on({ withdraw: z.object({ amount: z.number() }) })\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Account must be open\",\n * (_, snap, action) =>\n * snap.state.balance >= action.amount || \"Insufficient funds\"\n * ])\n * .emit(\"Withdrawn\")\n * .on({ close: z.object({}) })\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Already closed\",\n * (_, snap) => snap.state.balance === 0 || \"Balance must be zero\"\n * ])\n * .emit(\"Closed\")\n * .build();\n * ```\n *\n * @example State with snapshotting\n * ```typescript\n * const User = state({ User: z.object({\n * name: z.string(),\n * email: z.string(),\n * loginCount: z.number()\n * }) })\n * .init((data) => ({ ...data, loginCount: 0 }))\n * .emits({\n * UserCreated: z.object({ name: z.string(), email: z.string() }),\n * UserLoggedIn: z.object({})\n * })\n * .patch({ // only override events needing custom logic\n * UserLoggedIn: (_, state) => ({ loginCount: state.loginCount + 1 })\n * })\n * // UserCreated uses passthrough — event data merges into state\n * .on({ createUser: z.object({ name: z.string(), email: z.string() }) })\n * .emit(\"UserCreated\") // passthrough\n * .on({ login: z.object({}) })\n * .emit(\"UserLoggedIn\")\n * .snap((snap) => snap.patches >= 10) // Snapshot every 10 events\n * .build();\n * ```\n *\n * @see {@link StateBuilder} for available builder methods\n * @see {@link ActionBuilder} for action configuration methods\n * @see {@link https://rotorsoft.github.io/act-root/docs/intro | Getting Started Guide}\n * @see {@link https://rotorsoft.github.io/act-root/docs/examples/calculator | Calculator Example}\n */\nexport function state<TName extends string, TState extends Schema>(\n entry: StateEntry<TName, TState>\n): StateBuilder<TState, TName> {\n const keys = Object.keys(entry);\n if (keys.length !== 1) throw new Error(\"state() requires exactly one key\");\n const name = keys[0] as TName;\n const stateSchema = (entry as Record<string, ZodType<TState>>)[name];\n return {\n init(init) {\n return {\n emits<TEvents extends Schema>(events: ZodTypes<TEvents>) {\n // Default passthrough patches: event data merges into state\n const defaultPatch = Object.fromEntries(\n Object.keys(events).map((k) => {\n const fn = Object.assign(({ data }: { data: any }) => data, {\n _passthrough: true as const,\n }) satisfies PassthroughPatchHandler;\n return [k, fn];\n })\n ) as unknown as PatchHandlers<TState, TEvents>;\n\n // Build one mutable state object the action_builder threads\n // through every fluent call. patch() (if invoked) just mutates\n // the patch map in place — no re-builder wasted.\n const internal: State<TState, TEvents, Schemas, TName> = {\n events,\n actions: {},\n state: stateSchema,\n name,\n init,\n patch: defaultPatch,\n on: {},\n };\n\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- {} avoids string index signature\n const builder = action_builder<TState, TEvents, {}, TName>(internal);\n\n return Object.assign(builder, {\n patch(customPatch: Partial<PatchHandlers<TState, TEvents>>) {\n Object.assign(internal.patch, customPatch);\n return builder;\n },\n });\n },\n };\n },\n };\n}\n\n/**\n * Internal action-builder. The runtime object is a single mutable bag —\n * each fluent call (`on`, `snap`) mutates it and returns the same builder\n * cast to the widened generic type. Type-level fanout is preserved; the\n * O(N) `{...state}` spreads per call are not.\n *\n * Generics are erased to `Schemas` at runtime — the cast on return narrows\n * back to the call-site's widened types.\n */\nfunction action_builder<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TName extends string = string,\n>(\n state: State<TState, TEvents, TActions, TName>\n): ActionBuilder<TState, TEvents, TActions, TName> {\n // The mutable bag — typed loosely since callers narrow on return.\n const internal = state as unknown as State<TState, TEvents, Schemas, TName>;\n\n const builder: ActionBuilder<TState, TEvents, TActions, TName> = {\n on<TKey extends string, TNewActions extends Schema>(\n entry: ActionEntry<TKey, TNewActions>\n ) {\n const keys = Object.keys(entry);\n if (keys.length !== 1) throw new Error(\".on() requires exactly one key\");\n const action = keys[0] as TKey;\n const schema = entry[action];\n\n if (action in internal.actions)\n throw new Error(`Duplicate action \"${action}\"`);\n\n type MergedActions = TActions & { [P in TKey]: TNewActions };\n (internal.actions as Record<string, ZodType<Schema>>)[action] = schema;\n\n function given(rules: Invariant<TState>[]) {\n internal.given ??= {} as GivenHandlers<TState, Schemas>;\n (internal.given as Record<string, Invariant<TState>[]>)[action] = rules;\n return { emit };\n }\n\n function emit(\n handler:\n | ActionHandler<TState, TEvents, MergedActions, TKey>\n | (keyof TEvents & string)\n ) {\n if (typeof handler === \"string\") {\n const eventName = handler;\n // Tag the synthetic function with the static event name so\n // the act-builder can detect emissions of deprecated events\n // at build time (ACT-403). Dynamic forms — where the\n // returned event name is computed inside the user's\n // function — can't be inspected statically; they're caught\n // by the runtime warning in event-sourcing.ts.\n const emitFn = Object.assign((payload: any) => [eventName, payload], {\n _staticEmit: eventName,\n });\n (internal.on as Record<string, unknown>)[action] = emitFn;\n } else {\n (internal.on as Record<string, unknown>)[action] = handler;\n }\n return builder as unknown as ActionBuilder<\n TState,\n TEvents,\n MergedActions,\n TName\n >;\n }\n\n return { given, emit };\n },\n\n snap(snap: (snapshot: Snapshot<TState, TEvents>) => boolean) {\n internal.snap = snap;\n return builder;\n },\n\n build(): State<TState, TEvents, TActions, TName> {\n return internal as unknown as State<TState, TEvents, TActions, TName>;\n },\n };\n return builder;\n}\n","/**\n * @module csv\n *\n * `CsvFile` — a single class implementing both {@link EventSource}\n * and {@link EventSink} so a CSV file on disk can be either side of\n * a transfer pipeline (ACT-1128 / #788).\n *\n * - As a source: streams one row at a time off a line interface;\n * the awaited per-event callback gives 1-event-in-flight\n * backpressure on reads.\n * - As a sink: serialized `WriteStream.write` await per row,\n * propagating I/O errors through the chunk callback.\n *\n * `commit` / `claim` / `subscribe` and the rest of `Store` are NOT\n * implemented — `CsvFile` is a transfer-only primitive, not a\n * store you'd run an Act app against.\n */\n\nimport { createReadStream, createWriteStream, type WriteStream } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport type {\n Committed,\n EventSink,\n EventSource,\n Query,\n Schemas,\n} from \"./types/action.js\";\n\n/**\n * Construct a {@link CsvFile} from either a filesystem path (for\n * reading and/or writing through the OS) or an in-memory blob (a\n * pre-loaded CSV string, used by the inspector when a CSV arrives\n * over the wire via tRPC).\n *\n * Both modes share the same on-disk format, so the same blob shape\n * can be round-tripped through the transfer pipeline.\n */\nexport type CsvFileOptions = { path: string } | { blob: string };\n\n/**\n * Same column order as the inspector's backup endpoint, kept here\n * so `CsvFile` is round-trip-compatible with existing backups.\n */\nconst CSV_COLUMNS = [\n \"id\",\n \"name\",\n \"data\",\n \"stream\",\n \"version\",\n \"created\",\n \"meta\",\n] as const;\n\nexport class CsvFile implements EventSource, EventSink {\n private readonly path: string | null;\n private readonly blob: string | null;\n\n constructor(options: CsvFileOptions) {\n if (\"path\" in options) {\n this.path = options.path;\n this.blob = null;\n } else {\n this.path = null;\n this.blob = options.blob;\n }\n }\n\n async query<E extends Schemas>(\n callback: (event: Committed<E, keyof E>) => void,\n _filter?: Query\n ): Promise<number> {\n const lines =\n this.blob !== null ? linesFromBlob(this.blob) : linesFromFile(this.path!);\n let count = 0;\n let header: readonly string[] | null = null;\n for await (const line of lines) {\n if (!line.trim()) continue;\n const fields = parseCsvLine(line);\n if (!header) {\n header = fields;\n const expected = CSV_COLUMNS.join(\",\");\n if (header.join(\",\") !== expected)\n throw new Error(`Invalid CSV header. Expected: ${expected}`);\n continue;\n }\n if (fields.length !== CSV_COLUMNS.length)\n throw new Error(\n `Row ${count + 1}: expected ${CSV_COLUMNS.length} fields, got ${fields.length}`\n );\n const event: Committed<E, keyof E> = {\n id: Number.parseInt(fields[0]!, 10),\n name: fields[1]! as keyof E,\n data: JSON.parse(fields[2]!),\n stream: fields[3]!,\n version: Number.parseInt(fields[4]!, 10),\n created: new Date(fields[5]!),\n meta: JSON.parse(fields[6]!),\n };\n await Promise.resolve(callback(event));\n count++;\n }\n if (header === null)\n throw new Error(\"CSV must have a header and at least one row\");\n return count;\n }\n\n async restore(\n driver: (\n callback: (event: Committed<Schemas, keyof Schemas>) => Promise<number>\n ) => Promise<void>\n ): Promise<void> {\n if (this.path === null)\n throw new Error(\n \"CsvFile in blob mode is read-only — provide `path` to write\"\n );\n const writer = createWriteStream(this.path, {\n flags: \"w\",\n encoding: \"utf8\",\n });\n let nextId = 1;\n try {\n await writeLine(writer, CSV_COLUMNS.join(\",\"));\n await driver(async (event) => {\n const id = nextId++;\n const row = [\n String(id),\n csvEscape(event.name as string),\n csvEscape(JSON.stringify(event.data)),\n csvEscape(event.stream),\n String(event.version),\n event.created.toISOString(),\n csvEscape(JSON.stringify(event.meta)),\n ].join(\",\");\n await writeLine(writer, row);\n return id;\n });\n } finally {\n await new Promise<void>((resolve) => writer.end(resolve));\n }\n }\n\n async dispose(): Promise<void> {\n // No-op: `restore` always closes its writer in a `finally`, and\n // blob mode never opens one. The Disposable contract is here to\n // make `CsvFile` interchangeable with `Store` in transfer\n // pipelines, not because the file handle outlives the call.\n }\n}\n\nasync function* linesFromFile(path: string): AsyncIterable<string> {\n const stream = createReadStream(path, { encoding: \"utf8\" });\n const rl = createInterface({\n input: stream,\n crlfDelay: Number.POSITIVE_INFINITY,\n });\n try {\n for await (const line of rl) yield line;\n } finally {\n rl.close();\n stream.close();\n }\n}\n\nasync function* linesFromBlob(blob: string): AsyncIterable<string> {\n let start = 0;\n while (start < blob.length) {\n const nl = blob.indexOf(\"\\n\", start);\n const end = nl === -1 ? blob.length : nl;\n yield blob.slice(start, end);\n start = nl === -1 ? blob.length : nl + 1;\n await Promise.resolve();\n }\n}\n\nfunction parseCsvLine(line: string): string[] {\n const fields: string[] = [];\n let i = 0;\n while (i < line.length) {\n if (line[i] === '\"') {\n let value = \"\";\n i++;\n while (i < line.length) {\n if (line[i] === '\"' && line[i + 1] === '\"') {\n value += '\"';\n i += 2;\n } else if (line[i] === '\"') {\n i++;\n break;\n } else {\n value += line[i++];\n }\n }\n fields.push(value);\n if (line[i] === \",\") i++;\n } else {\n const next = line.indexOf(\",\", i);\n if (next === -1) {\n fields.push(line.slice(i));\n i = line.length;\n } else {\n fields.push(line.slice(i, next));\n i = next + 1;\n }\n }\n }\n return fields;\n}\n\nfunction csvEscape(value: string): string {\n if (/[\",\\n\\r]/.test(value)) return `\"${value.replace(/\"/g, '\"\"')}\"`;\n return value;\n}\n\nfunction writeLine(writer: WriteStream, line: string): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n writer.write(`${line}\\n`, (err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n}\n"],"mappings":"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","names":["state","deps","tombstone","load","snap","state","state","action","state","action","action","block","state","block","action","action","state","config","state","config","state","action","snap"]}
|
|
1
|
+
{"version":3,"sources":["../src/signals.ts","../src/act.ts","../src/internal/event-versions.ts","../src/internal/audit.ts","../src/internal/build-classify.ts","../src/internal/close-cycle.ts","../src/internal/correlate-cycle.ts","../src/internal/correlator.ts","../src/internal/drain-cycle.ts","../src/internal/drain-ratio.ts","../src/internal/drain.ts","../src/internal/event-sourcing.ts","../src/internal/tracing.ts","../src/internal/merge.ts","../src/internal/backoff.ts","../src/internal/reactions.ts","../src/internal/settle.ts","../src/builders/act-builder.ts","../src/builders/projection-builder.ts","../src/builders/slice-builder.ts","../src/builders/state-builder.ts","../src/csv.ts"],"sourcesContent":["import { disposeAndExit, log } from \"./ports.js\";\n\n// Resolve the logger lazily inside each handler — calling log() here at\n// module load would register the default ConsoleLogger before user code\n// can inject (port singletons are first-call-wins).\nprocess.once(\"SIGINT\", async (arg?: any) => {\n log().info(arg, \"SIGINT\");\n await disposeAndExit(\"EXIT\");\n});\nprocess.once(\"SIGTERM\", async (arg?: any) => {\n log().info(arg, \"SIGTERM\");\n await disposeAndExit(\"EXIT\");\n});\nprocess.once(\"uncaughtException\", async (arg?: any) => {\n log().error(arg, \"Uncaught Exception\");\n await disposeAndExit(\"ERROR\");\n});\nprocess.once(\"unhandledRejection\", async (arg?: any) => {\n log().error(arg, \"Unhandled Rejection\");\n await disposeAndExit(\"ERROR\");\n});\n","import EventEmitter from \"node:events\";\nimport {\n ALL_LANES,\n type AuditDeps,\n audit,\n buildDrain,\n buildEs,\n buildHandle,\n buildHandleBatch,\n CorrelateCycle,\n classifyRegistry,\n closeCorrelation,\n DrainController,\n type DrainOps,\n defaultCorrelator,\n type EsOps,\n type EventLaneSet,\n type Handle,\n type HandleBatch,\n runCloseCycle,\n SettleLoop,\n scan,\n} from \"./internal/index.js\";\nimport { dispose, log, type Scoped, scoped, store } from \"./ports.js\";\nimport type {\n Actor,\n AsOf,\n AuditCategory,\n AuditFinding,\n AuditOptions,\n BatchHandler,\n BlockedLease,\n CloseResult,\n CloseTarget,\n Committed,\n Correlator,\n Drain,\n DrainOptions,\n EventSink,\n EventSource,\n IAct,\n LaneConfig,\n Lease,\n Logger,\n Query,\n Registry,\n ScanOptions,\n ScanResult,\n Schema,\n SchemaRegister,\n Schemas,\n SettleOptions,\n Snapshot,\n State,\n Store,\n StoreNotification,\n StreamFilter,\n StreamPosition,\n Target,\n} from \"./types/index.js\";\n\n/**\n * @category Orchestrator\n * @see Store\n *\n * Main orchestrator for event-sourced state machines and workflows.\n *\n * It manages the lifecycle of actions, reactions, and event streams, providing APIs for loading state, executing actions, querying events, and draining reactions.\n *\n * ## Usage\n *\n * ```typescript\n * const app = new Act(registry, 100);\n * await app.do(\"increment\", { stream: \"counter1\", actor }, { by: 1 });\n * const snapshot = await app.load(Counter, \"counter1\");\n * await app.drain();\n * ```\n *\n * - Register event listeners with `.on(\"committed\", ...)` and `.on(\"acked\", ...)` to react to lifecycle events.\n * - Use `.query()` to analyze event streams for analytics or debugging.\n *\n * @template TSchemaReg SchemaRegister for state\n * @template TEvents Schemas for events\n * @template TActions Schemas for actions\n * @template TStateMap Map of state names to state schemas\n * @template TActor Actor type extending base Actor\n */\n/**\n * Default LRU cap for the subscribed-streams cache. Apps that mint many\n * dynamic targets (one per aggregate) should override via\n * {@link ActOptions.maxSubscribedStreams} based on expected concurrency.\n */\nexport const DEFAULT_MAX_SUBSCRIBED_STREAMS = 1000;\n\n/**\n * Default debounce window (ms) for `settle()` when neither the per-call\n * `SettleOptions.debounceMs` nor `ActOptions.settleDebounceMs` is set.\n * Coalesces commits in the same tick and small bursts; sub-perceptible\n * latency on the `\"settled\"` signal.\n */\nexport const DEFAULT_SETTLE_DEBOUNCE_MS = 10;\n\n/**\n * Lifecycle events emitted by {@link Act}, mapped to their payload type.\n * Drives the typing of `emit` / `on` / `off` — the event-name argument\n * narrows its payload at the call site.\n */\nexport type ActLifecycleEvents<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n> = {\n committed: Snapshot<TSchemaReg, TEvents>[];\n acked: Lease[];\n blocked: BlockedLease[];\n settled: Drain<TEvents>;\n closed: CloseResult;\n /**\n * A **different process** committed an event to the same backing store.\n *\n * Fires only when the configured store implements\n * {@link Store.notify} and there is at least one registered reaction.\n * The orchestrator uses the same signal internally to wake `settle()`\n * — listeners get the raw payload for SSE fan-out, dashboards, and\n * audit logs.\n *\n * Local commits do *not* fire `notified` (use `committed` for those):\n * stores self-filter their own writes so this channel has a clean\n * cross-process semantic.\n */\n notified: StoreNotification;\n};\n\n/**\n * Options for {@link Act} construction (passed via {@link ActBuilder.build}).\n *\n * @property maxSubscribedStreams - Cap for the LRU set tracking already-\n * subscribed reaction streams. Default: {@link DEFAULT_MAX_SUBSCRIBED_STREAMS}.\n * @property settleDebounceMs - Debounce window (ms) used by `settle()` when\n * the caller doesn't pass `SettleOptions.debounceMs`. Tune this once per\n * Act instance instead of threading the value through every call site.\n * Default: {@link DEFAULT_SETTLE_DEBOUNCE_MS}.\n */\nexport type ActOptions<TLanes extends string = string> = {\n readonly maxSubscribedStreams?: number;\n readonly settleDebounceMs?: number;\n /**\n * Per-Act ports (ACT-501). When set, this Act runs against the\n * provided store + cache instead of the singletons — threaded via\n * AsyncLocalStorage so internals are unchanged. Both are required\n * together (a shared cache across distinct stores would collide on\n * stream keys). Omit for the singleton path.\n */\n readonly scoped?: Scoped;\n /**\n * Correlation-id generator for originating actions (ACT-404). When\n * omitted, Act uses {@link defaultCorrelator}, which produces a\n * readable, time-monotonic-within-window, lowercase id of the form\n * `{state[:4]}-{action[:4]}-{ts}{rnd}` (18 chars).\n *\n * Reactions inherit `reactingTo.meta.correlation` so the chain stays\n * intact — the delegate is only consulted on originating commits and\n * for the close-the-books transaction.\n */\n readonly correlator?: Correlator;\n /** Restrict this process to a subset of declared lanes (ACT-1103). */\n readonly onlyLanes?: ReadonlyArray<TLanes>;\n};\n\nexport class Act<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n TStateMap extends Record<string, Schema> = Record<string, never>,\n TActor extends Actor = Actor,\n> implements IAct<TEvents, TActions, TActor>\n{\n private _emitter = new EventEmitter();\n /** Event names with at least one registered reaction (computed at build time) */\n private readonly _reactive_events: ReadonlySet<string>;\n /** One DrainController per active lane, keyed by lane name. */\n private readonly _drain_controllers: Map<\n string,\n DrainController<TEvents, TActions, TSchemaReg>\n >;\n /** Correlation state machine: lazy init, dynamic-resolver scan, periodic worker. */\n private readonly _correlate: CorrelateCycle<TSchemaReg, TEvents, TActions>;\n /** Debounced correlate→drain catch-up loop. */\n private readonly _settle: SettleLoop<TEvents>;\n /**\n * Disposer for the cross-process notify subscription, set up eagerly\n * during construction. Held as a promise because the subscription\n * itself may be async (the PG adapter checks out a dedicated client\n * and runs `LISTEN` before resolving). Resolves to `undefined` when\n * the store doesn't implement `notify` or there are no registered\n * reactions.\n *\n * **Contract:** the configured store must be injected via\n * {@link store}`(adapter)` *before* calling `act()...build()`. The\n * orchestrator wires notify against whatever store is current at\n * construction time — late injection after build is unsupported.\n */\n private readonly _notify_disposer: Promise<\n (() => void | Promise<void>) | undefined\n >;\n\n /**\n * Emit a lifecycle event. The payload type is inferred from the event name\n * via {@link ActLifecycleEvents}.\n */\n emit<E extends keyof ActLifecycleEvents<TSchemaReg, TEvents, TActions>>(\n event: E,\n args: ActLifecycleEvents<TSchemaReg, TEvents, TActions>[E]\n ): boolean {\n return this._emitter.emit(event, args);\n }\n\n /**\n * Register a listener for a lifecycle event. The listener receives the\n * event-specific payload.\n */\n on<E extends keyof ActLifecycleEvents<TSchemaReg, TEvents, TActions>>(\n event: E,\n listener: (\n args: ActLifecycleEvents<TSchemaReg, TEvents, TActions>[E]\n ) => void\n ): this {\n this._emitter.on(event, listener);\n return this;\n }\n\n /**\n * Remove a previously registered lifecycle listener.\n */\n off<E extends keyof ActLifecycleEvents<TSchemaReg, TEvents, TActions>>(\n event: E,\n listener: (\n args: ActLifecycleEvents<TSchemaReg, TEvents, TActions>[E]\n ) => void\n ): this {\n this._emitter.off(event, listener);\n return this;\n }\n\n /** Batch handlers for static-target projections (target → handler) */\n private readonly _batch_handlers: Map<string, BatchHandler<TEvents>>;\n /** Event-sourcing handlers, optionally wrapped with trace decorators */\n private readonly _es: EsOps;\n /** Correlate/drain pipeline ops, optionally wrapped with trace decorators */\n private readonly _cd: DrainOps<TEvents>;\n /**\n * Event-name → owning state, computed at build time. The duplicate-event\n * guard in merge.ts ensures one event name maps to at most one state, so\n * this lookup is unambiguous. Used by `close()` to pick the right reducer\n * set when seeding a `restart` snapshot in multi-state apps.\n */\n private readonly _event_to_state: ReadonlyMap<string, State<any, any, any>>;\n /**\n * Event-name → lane fan-in for selective arming (ACT-1103). Built by\n * `classifyRegistry` once per build. `\"all\"` means at least one of\n * the event's reactions is a dynamic resolver (lane opaque until\n * runtime); a `Set<string>` lists the static lanes only that event's\n * reactions target.\n */\n private readonly _event_to_lanes: ReadonlyMap<string, EventLaneSet>;\n /**\n * Audit dependency bag (#723). Built once at construction; held as\n * an immutable snapshot of the registry state the audit module\n * needs. Lives in `internal/audit.ts` — this orchestrator never\n * carries audit logic, only the deps + a one-liner that hands them\n * over.\n */\n private readonly _audit_deps: AuditDeps;\n /** Logger resolved at construction time (after user port configuration) */\n private readonly _logger: Logger = log();\n /** Wraps a public-method body so internal `store()`/`cache()` resolve to the\n * per-Act ports (ACT-501). No-op when the Act is unscoped — so the singleton\n * path keeps reading fresh `store()`/`cache()` per call, which matters for\n * tests that dispose and re-seed mid-suite. */\n private readonly _scoped: <T>(fn: () => Promise<T>) => Promise<T>;\n\n /**\n * Correlation-id generator for originating actions. Bound at\n * construction from `options.correlator ?? defaultCorrelator`. The\n * `do()` path passes this into the `_es.action` closure; close-cycle\n * uses it via {@link closeCorrelation}.\n */\n private readonly _correlator: Correlator;\n /** Pre-bound IAct methods reused across drain cycles. Only `do` varies per\n * payload (it captures the triggering event for reactingTo auto-inject). */\n private readonly _bound_do = this.do.bind(this);\n private readonly _bound_load = this.load.bind(this);\n private readonly _bound_query = this.query.bind(this);\n private readonly _bound_query_array = this.query_array.bind(this);\n /** Reaction dispatchers built once and handed to runDrainCycle each cycle. */\n private readonly _handle: Handle<TEvents>;\n private readonly _handle_batch: HandleBatch<TEvents>;\n /** Declared drain lanes (ACT-1103). */\n private readonly _lanes: ReadonlyArray<LaneConfig>;\n\n /** Drain lanes declared via `.withLane(...)`. Implicit default not included. */\n get lanes(): ReadonlyArray<LaneConfig> {\n return this._lanes;\n }\n\n /**\n * Create a new Act orchestrator. Prefer the {@link act} builder over\n * direct construction — `act()...build()` wires the registry, merges\n * partial states, and collects batch handlers from registered slices\n * and projections in one pass.\n *\n * @param registry Schemas for every event and action across registered states\n * @param _states Merged map of state name → state definition\n * @param batchHandlers Static-target projection batch handlers (target → handler)\n * @param options Tuning knobs — see {@link ActOptions}\n * @param lanes Declared drain lanes (ACT-1103). The builder collects\n * these from `.withLane(...)` calls. Slice 1 records them on the\n * instance; later slices fan out one `DrainController` per lane.\n */\n constructor(\n public readonly registry: Registry<TSchemaReg, TEvents, TActions>,\n private readonly _states: Map<string, State<any, any, any>> = new Map(),\n batchHandlers: Map<string, BatchHandler<any>> = new Map(),\n options: ActOptions = {},\n lanes: ReadonlyArray<LaneConfig> = []\n ) {\n this._batch_handlers = batchHandlers;\n this._lanes = lanes;\n if (options.onlyLanes && options.onlyLanes.length > 0) {\n const declared = new Set<string>([\n \"default\",\n ...lanes.map((l) => l.name),\n ]);\n const unknown = options.onlyLanes.filter((l) => !declared.has(l));\n if (unknown.length > 0)\n throw new Error(\n `ActOptions.onlyLanes references undeclared lane(s): ${unknown\n .map((l) => `\"${l}\"`)\n .join(\", \")}`\n );\n }\n this._scoped = options.scoped\n ? (fn) => scoped.run(options.scoped!, fn)\n : (fn) => fn();\n this._correlator = options.correlator ?? defaultCorrelator;\n this._es = buildEs(this._logger, this._correlator);\n this._cd = buildDrain<TEvents>(this._logger);\n this._handle = buildHandle<TEvents, TActions, TActor>({\n logger: this._logger,\n boundDo: this._bound_do,\n boundLoad: this._bound_load,\n boundQuery: this._bound_query,\n boundQueryArray: this._bound_query_array,\n });\n this._handle_batch = buildHandleBatch<TEvents>(this._logger);\n\n const {\n staticTargets,\n hasDynamicResolvers,\n reactiveEvents,\n eventToState,\n eventToLanes,\n } = classifyRegistry(this.registry, this._states);\n this._reactive_events = reactiveEvents;\n this._event_to_state = eventToState;\n this._event_to_lanes = eventToLanes;\n\n // Build one DrainController per active lane (ACT-1103). The implicit\n // \"default\" lane is always present unless onlyLanes excludes it. Each\n // controller filters its claim() by its lane name; the legacy\n // single-controller path is the active set === { \"default\" } case\n // with `lane: undefined` deps so claim() doesn't filter (preserves\n // pre-1103 SQL planner behavior for apps that never call withLane).\n const allLanes = [\"default\", ...lanes.map((l) => l.name)];\n const onlySet =\n options.onlyLanes && options.onlyLanes.length > 0\n ? new Set<string>(options.onlyLanes as readonly string[])\n : undefined;\n const activeLanes = onlySet\n ? allLanes.filter((n) => onlySet.has(n))\n : allLanes;\n const singleDefaultLane =\n activeLanes.length === 1 && activeLanes[0] === \"default\";\n this._drain_controllers = new Map();\n for (const name of activeLanes) {\n const cfg = lanes.find((l) => l.name === name);\n const controller = new DrainController({\n logger: this._logger,\n ops: this._cd,\n registry: this.registry,\n batchHandlers: this._batch_handlers,\n handle: this._handle,\n handleBatch: this._handle_batch,\n onAcked: (acked) => this.emit(\"acked\", acked),\n onBlocked: (blocked) => this.emit(\"blocked\", blocked),\n // Pass lane only when a true per-lane controller is active.\n // The all-lanes (single default) case keeps lane=undefined so\n // adapter SQL collapses to the pre-1103 shape.\n lane: singleDefaultLane ? undefined : name,\n defaults: cfg && {\n streamLimit: cfg.streamLimit,\n leaseMillis: cfg.leaseMillis,\n },\n });\n // Auto-start a per-lane worker when the operator declared a\n // cycleMs — the intent of `withLane({cycleMs: 100})` is \"drive\n // this lane every 100 ms,\" independent of the Act-level settle\n // loop. unref()'d so the timer doesn't keep the process alive.\n if (cfg?.cycleMs !== undefined) controller.start(cfg.cycleMs);\n this._drain_controllers.set(name, controller);\n }\n\n // Audit deps bag (#723). Snapshotted after registry classification +\n // drain-controller build so the audit module sees the finalized lane\n // set. Held as an immutable bag — the orchestrator never carries\n // audit logic itself, only this typed contract.\n this._audit_deps = {\n store,\n logger: this._logger,\n event_to_state: eventToState,\n states: this._states,\n known_events: new Set(eventToState.keys()),\n declared_lanes: new Set(this._drain_controllers.keys()),\n routed_events: new Set(eventToLanes.keys()),\n };\n\n this._correlate = new CorrelateCycle(\n this.registry,\n staticTargets,\n hasDynamicResolvers,\n this._cd,\n options.maxSubscribedStreams ?? DEFAULT_MAX_SUBSCRIBED_STREAMS,\n // Cold start: assume drain is needed (historical events may need processing)\n () => {\n if (this._reactive_events.size > 0) this._armAll();\n }\n );\n this._settle = new SettleLoop<TEvents>(\n {\n logger: this._logger,\n init: () => this._correlate.init(),\n checkpoint: () => this._correlate.checkpoint,\n correlate: (q) => this.correlate(q),\n drain: (o) => this.drain(o),\n onSettled: (drain) => this.emit(\"settled\", drain),\n },\n options.settleDebounceMs ?? DEFAULT_SETTLE_DEBOUNCE_MS\n );\n\n // Auto-wire cross-process notify when the store supports it. Bound at\n // construction time — late `store(adapter)` injection after build won't\n // take effect. Scoped Acts bind against their own store.\n this._notify_disposer = this._wireNotify(options.scoped?.store ?? store());\n\n dispose(() => this.shutdown());\n }\n\n /** True after the first `shutdown()` call. Guards idempotency. */\n private _shutdown_promise: Promise<void> | undefined;\n\n /**\n * Per-instance teardown: remove lifecycle listeners, stop the\n * correlation worker, cancel any pending settle cycle, and tear\n * down the cross-process notify subscription.\n *\n * Idempotent — repeated calls return the same promise. Registered\n * automatically with the global `dispose()` registry at construction,\n * so process-wide `dispose()()` covers it; test helpers (or operators\n * that mint short-lived Acts) call it explicitly for prompt cleanup.\n */\n shutdown(): Promise<void> {\n if (!this._shutdown_promise) {\n this._shutdown_promise = (async () => {\n this._emitter.removeAllListeners();\n this.stop_correlations();\n this.stop_settling();\n for (const c of this._drain_controllers.values()) c.stop();\n // `_wireNotify` swallows subscription errors and resolves to\n // `undefined`, so this promise never rejects.\n const disposer = await this._notify_disposer;\n if (disposer) await disposer();\n })();\n }\n return this._shutdown_promise;\n }\n\n /**\n * Subscribe to {@link Store.notify} when both the store and the\n * registry support it. Returns the disposer (or `undefined` when no\n * subscription was made). Errors during subscription are logged but\n * never thrown — `notify` is a hint, not a contract.\n */\n private async _wireNotify(\n s: Store\n ): Promise<(() => void | Promise<void>) | undefined> {\n if (this._reactive_events.size === 0) return undefined;\n if (!s.notify) return undefined;\n try {\n return await s.notify((notification) => {\n // Generic concerns (lifecycle emit, drain wakeup, listener\n // error containment) live here so adapters only have to\n // handle their own wire format. Errors in user-registered\n // `notified` listeners or in our own bookkeeping are logged\n // and swallowed — the store's listener stays alive.\n try {\n this.emit(\"notified\", notification);\n // Wake once per commit when at least one event has a local\n // reaction. Avoids spurious wake-ups for remote commits\n // belonging to bounded contexts this process doesn't react to.\n // ACT-1103: selective arming via the shared helper — only the\n // lanes whose reactions match the notified events.\n const armed = this._armForEventNames(\n notification.events.map((e) => e.name)\n );\n if (armed) this._settle.schedule({ debounceMs: 0 });\n } catch (err) {\n this._logger.error(err, \"notified handler threw\");\n }\n });\n } catch (err) {\n this._logger.error(err, \"Store.notify subscription failed\");\n return undefined;\n }\n }\n\n /**\n * Executes an action on a state instance, committing resulting events.\n *\n * This is the primary method for modifying state. It:\n * 1. Validates the action payload against the schema\n * 2. Loads the current state snapshot\n * 3. Checks invariants (business rules)\n * 4. Executes the action handler to generate events\n * 5. Applies events to create new state\n * 6. Commits events to the store with optimistic concurrency control\n *\n * @template TKey - Action name from registered actions\n * @param action - The name of the action to execute\n * @param target - Target specification with stream ID and actor context\n * @param payload - Action payload matching the action's schema\n * @param reactingTo - Optional event that triggered this action (for correlation)\n * @param skipValidation - Skip schema validation (use carefully, for performance)\n * @returns Array of snapshots for all affected states (usually one)\n *\n * @throws {ValidationError} If payload doesn't match action schema\n * @throws {InvariantError} If business rules are violated\n * @throws {ConcurrencyError} If another process modified the stream\n *\n * @example Basic action execution\n * ```typescript\n * const snapshots = await app.do(\n * \"increment\",\n * {\n * stream: \"counter-1\",\n * actor: { id: \"user1\", name: \"Alice\" }\n * },\n * { by: 5 }\n * );\n *\n * console.log(snapshots[0].state.count); // Current count after increment\n * ```\n *\n * @example With error handling\n * ```typescript\n * try {\n * await app.do(\n * \"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Business rule violated:\", error.description);\n * } else if (error instanceof ConcurrencyError) {\n * console.error(\"Concurrent modification detected, retry...\");\n * } else if (error instanceof ValidationError) {\n * console.error(\"Invalid payload:\", error.details);\n * }\n * }\n * ```\n *\n * @example Reaction triggering another action (reactingTo auto-injected)\n * ```typescript\n * const app = act()\n * .withState(Order)\n * .withState(Inventory)\n * .on(\"OrderPlaced\")\n * .do(async function reduceInventory(event, _stream, app) {\n * // Inside reaction handlers, reactingTo is auto-injected when omitted.\n * // The triggering event is used by default, maintaining the correlation chain.\n * await app.do(\n * \"reduceStock\",\n * { stream: \"inventory-1\", actor: { id: \"sys\", name: \"system\" } },\n * { amount: event.data.items.length }\n * );\n * // To use a different correlation, pass reactingTo explicitly:\n * // await app.do(\"reduceStock\", target, payload, customEvent);\n * })\n * .to(\"inventory-1\")\n * .build();\n * ```\n *\n * @see {@link Target} for target structure\n * @see {@link Snapshot} for return value structure\n * @see {@link ValidationError}, {@link InvariantError}, {@link ConcurrencyError}\n */\n async do<TKey extends keyof TActions>(\n action: TKey,\n target: Target<TActor>,\n payload: Readonly<TActions[TKey]>,\n reactingTo?: Committed<TEvents, string & keyof TEvents>,\n skipValidation = false\n ) {\n return this._scoped(async () => {\n const snapshots = await this._es.action(\n this.registry.actions[action],\n action,\n target,\n payload,\n reactingTo,\n skipValidation\n );\n // Arm the drain when any committed event has reactions (ACT-1103:\n // arm only the lanes whose reactions match — events whose reactions\n // are all statically lane-resolved arm a subset; events with at\n // least one dynamic resolver fall back to _armAll via the \"all\"\n // sentinel).\n if (this._reactive_events.size > 0)\n // Snapshots produced by `action()` always carry their committed\n // event — the optional `event?` on the type is for load()\n // snapshots, which don't reach this path.\n this._armForEventNames(\n snapshots.map((s) => (s.event as { name: string }).name)\n );\n this.emit(\"committed\", snapshots as Snapshot<TSchemaReg, TEvents>[]);\n return snapshots;\n });\n }\n\n /**\n * Loads the current state snapshot for a specific stream.\n *\n * Reconstructs the current state by replaying events from the event store.\n * Uses snapshots when available to optimize loading performance.\n *\n * Accepts either a State definition object or a state name string. When\n * using a string, the merged state (from partial states registered via\n * `.withState()`) is resolved by name.\n *\n * @template TNewState - State schema type\n * @template TNewEvents - Event schemas type\n * @template TNewActions - Action schemas type\n * @param state - The state definition or state name to load\n * @param stream - The stream ID (state instance identifier)\n * @param callback - Optional callback invoked with the loaded snapshot\n * @returns The current state snapshot for the stream\n *\n * @example Load by state definition\n * ```typescript\n * const snapshot = await app.load(Counter, \"counter-1\");\n * console.log(snapshot.state.count); // Current count\n * console.log(snapshot.patches); // Events since last snapshot\n * ```\n *\n * @example Load by state name (useful with partial states)\n * ```typescript\n * const snapshot = await app.load(\"Ticket\", \"ticket-123\");\n * console.log(snapshot.state.title); // Merged state from all partials\n * ```\n *\n * @example Load multiple states\n * ```typescript\n * const [user, account] = await Promise.all([\n * app.load(User, \"user-123\"),\n * app.load(BankAccount, \"account-456\")\n * ]);\n * ```\n *\n * @see {@link Snapshot} for snapshot structure\n */\n async load<\n TNewState extends Schema,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n >(\n state: State<TNewState, TNewEvents, TNewActions>,\n stream: string,\n callback?: (snapshot: Snapshot<TNewState, TNewEvents>) => void,\n asOf?: AsOf\n ): Promise<Snapshot<TNewState, TNewEvents>>;\n async load<TKey extends keyof TStateMap & string>(\n name: TKey,\n stream: string,\n callback?: (snapshot: Snapshot<TStateMap[TKey], TEvents>) => void,\n asOf?: AsOf\n ): Promise<Snapshot<TStateMap[TKey], TEvents>>;\n async load<TNewState extends Schema>(\n stateOrName: State<TNewState, any, any> | string,\n stream: string,\n callback?: (snapshot: Snapshot<any, any>) => void,\n asOf?: AsOf\n ): Promise<Snapshot<any, any>> {\n return this._scoped(async () => {\n let merged: State<any, any, any>;\n if (typeof stateOrName === \"string\") {\n const found = this._states.get(stateOrName);\n if (!found) throw new Error(`State \"${stateOrName}\" not found`);\n merged = found;\n } else {\n merged = this._states.get(stateOrName.name) || stateOrName;\n }\n return await this._es.load(merged, stream, callback, asOf);\n });\n }\n\n /**\n * Queries the event store for events matching a filter.\n *\n * Use this for analyzing event streams, generating reports, or debugging.\n * The callback is invoked for each matching event, and the method returns\n * summary information (first event, last event, total count).\n *\n * For small result sets, consider using {@link query_array} instead.\n *\n * @param query - Filter criteria — see {@link Query} for available fields\n * (`stream`, `name`, `after`, `before`, `created_after`, `created_before`,\n * `limit`, `with_snaps`, `stream_exact`)\n * @param callback - Optional callback invoked for each matching event\n * @returns Object with first event, last event, and total count\n *\n * @example Query all events for a stream\n * ```typescript\n * const { first, last, count } = await app.query(\n * { stream: \"counter-1\" },\n * (event) => console.log(event.name, event.data)\n * );\n * console.log(`Found ${count} events from ${first?.id} to ${last?.id}`);\n * ```\n *\n * @example Query specific event types\n * ```typescript\n * const { count } = await app.query(\n * { name: \"UserCreated\", limit: 100 },\n * (event) => {\n * console.log(\"User created:\", event.data.email);\n * }\n * );\n * ```\n *\n * @example Query events in time range\n * ```typescript\n * const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);\n * const { count } = await app.query({\n * created_after: yesterday,\n * stream: \"user-123\"\n * });\n * console.log(`User had ${count} events in last 24 hours`);\n * ```\n *\n * @see {@link query_array} for loading events into memory\n */\n async query(\n query: Query,\n callback?: (event: Committed<TEvents, keyof TEvents>) => void\n ): Promise<{\n first?: Committed<TEvents, keyof TEvents>;\n last?: Committed<TEvents, keyof TEvents>;\n count: number;\n }> {\n return this._scoped(async () => {\n let first: Committed<TEvents, keyof TEvents> | undefined;\n let last: Committed<TEvents, keyof TEvents> | undefined;\n const count = await store().query<TEvents>((e) => {\n if (!first) first = e;\n last = e;\n callback?.(e);\n }, query);\n return { first, last, count };\n });\n }\n\n /**\n * Queries the event store and returns all matching events in memory.\n *\n * **Use with caution** - this loads all results into memory. For large result sets,\n * use {@link query} with a callback instead to process events incrementally.\n *\n * @param query - The query filter (same as {@link query})\n * @returns Array of all matching events\n *\n * @example Load all events for a stream\n * ```typescript\n * const events = await app.query_array({ stream: \"counter-1\" });\n * console.log(`Loaded ${events.length} events`);\n * events.forEach(event => console.log(event.name, event.data));\n * ```\n *\n * @example Get recent events\n * ```typescript\n * const recent = await app.query_array({\n * stream: \"user-123\",\n * limit: 10\n * });\n * ```\n *\n * @see {@link query} for large result sets\n */\n async query_array(\n query: Query\n ): Promise<Committed<TEvents, keyof TEvents>[]> {\n return this._scoped(async () => {\n const events: Committed<TEvents, keyof TEvents>[] = [];\n await store().query<TEvents>((e) => events.push(e), query);\n return events;\n });\n }\n\n /**\n * Processes pending reactions by draining uncommitted events from the event store.\n *\n * Runs a single drain cycle:\n * 1. Polls the store for streams with uncommitted events\n * 2. Leases streams to prevent concurrent processing\n * 3. Fetches events for each leased stream\n * 4. Executes matching reaction handlers\n * 5. Acknowledges successful reactions or blocks failing ones\n *\n * Drain uses a dual-frontier strategy to balance processing of new streams (lagging)\n * vs active streams (leading). The ratio adapts based on event pressure.\n *\n * Call `correlate()` before `drain()` to discover target streams. For a higher-level\n * API that handles debouncing, correlation, and signaling automatically, use {@link settle}.\n *\n * @param options - Drain configuration — see {@link DrainOptions} for fields\n * (`streamLimit`, `eventLimit`, `leaseMillis`).\n * @returns Drain statistics with fetched, leased, acked, and blocked counts\n *\n * @example In tests and scripts\n * ```typescript\n * await app.do(\"createUser\", target, payload);\n * await app.correlate();\n * await app.drain();\n * ```\n *\n * @example In production, prefer settle()\n * ```typescript\n * await app.do(\"CreateItem\", target, input);\n * app.settle(); // debounced correlate→drain, emits \"settled\"\n * ```\n *\n * @see {@link settle} for debounced correlate→drain with lifecycle events\n * @see {@link correlate} for dynamic stream discovery\n * @see {@link start_correlations} for automatic correlation\n */\n async drain(options: DrainOptions = {}): Promise<Drain<TEvents>> {\n return this._scoped(() => this._drainAll(options));\n }\n\n /** Arm every active lane controller (ACT-1103). */\n private _armAll(): void {\n for (const c of this._drain_controllers.values()) c.arm();\n }\n\n /**\n * Arm only the lane controllers whose reactions match the supplied\n * event names (ACT-1103 selective arming). Events with any dynamic\n * resolver fall back to `_armAll()` via the `\"all\"` sentinel — the\n * resolver's lane isn't known until correlate runs the function.\n * Events with no reactions are skipped; `_event_to_lanes` doesn't\n * carry them. Returns true when any controller was armed (used by\n * the notify handler to decide whether to schedule a settle).\n */\n private _armForEventNames(names: Iterable<string>): boolean {\n const to_arm = new Set<string>();\n for (const name of names) {\n const set = this._event_to_lanes.get(name);\n if (set === undefined) continue;\n if (set === ALL_LANES) {\n this._armAll();\n return true;\n }\n for (const lane of set) to_arm.add(lane);\n }\n if (to_arm.size === 0) return false;\n for (const lane of to_arm) this._drain_controllers.get(lane)?.arm();\n return true;\n }\n\n /** Drain every active lane controller in parallel and aggregate.\n *\n * Parallel — not sequential — so a slow lane's in-flight handler does\n * not block a fast lane's claim/dispatch/ack cycle. Each controller's\n * `claim()` is independent (filtered by lane); the store's\n * `SKIP LOCKED` keeps cross-controller races safe. Lifecycle events\n * (`acked`, `blocked`) may interleave by lane — listeners filter via\n * `lease.lane`. */\n private async _drainAll(options: DrainOptions): Promise<Drain<TEvents>> {\n const results = await Promise.all(\n [...this._drain_controllers.values()].map((c) => c.drain(options))\n );\n const fetched: Drain<TEvents>[\"fetched\"] = [];\n const leased: Lease[] = [];\n const acked: Lease[] = [];\n const blocked: BlockedLease[] = [];\n for (const r of results) {\n fetched.push(...r.fetched);\n leased.push(...r.leased);\n acked.push(...r.acked);\n blocked.push(...r.blocked);\n }\n return { fetched, leased, acked, blocked };\n }\n\n /**\n * Discovers and registers new streams dynamically based on reaction resolvers.\n *\n * Correlation enables \"dynamic reactions\" where target streams are determined at runtime\n * based on event content. For example, you might create a stats stream for each user\n * when they perform certain actions.\n *\n * This method scans events matching the query and identifies new target streams based\n * on reaction resolvers. It then registers these streams so they'll be picked up by\n * the next drain cycle.\n *\n * @param query - Query filter to scan for new correlations\n * @param query - Scan filter — see {@link Query} for fields (typically\n * `{ after: <event-id>, limit: <count> }`)\n * @returns Object with newly leased streams and last scanned event ID\n *\n * @example Manual correlation\n * ```typescript\n * // Scan for new streams\n * const { leased, last_id } = await app.correlate({ after: 0, limit: 100 });\n * console.log(`Found ${leased.length} new streams`);\n *\n * // Save last_id for next scan\n * await saveCheckpoint(last_id);\n * ```\n *\n * @example Dynamic stream creation\n * ```typescript\n * const app = act()\n * .withState(User)\n * .withState(UserStats)\n * .on(\"UserLoggedIn\")\n * .do(async (event) => [\"incrementLoginCount\", {}])\n * .to((event) => ({\n * target: `stats-${event.stream}` // Dynamic target per user\n * }))\n * .build();\n *\n * // Discover stats streams as users log in\n * await app.correlate();\n * ```\n *\n * @see {@link start_correlations} for automatic periodic correlation\n * @see {@link stop_correlations} to stop automatic correlation\n */\n async correlate(\n query: Query = { after: -1, limit: 10 }\n ): Promise<{ subscribed: number; last_id: number }> {\n return this._scoped(() => this._correlate.correlate(query));\n }\n\n /**\n * Starts automatic periodic correlation worker for discovering new streams.\n *\n * The correlation worker runs in the background, scanning for new events and identifying\n * new target streams based on reaction resolvers. It maintains a sliding window that\n * advances with each scan, ensuring all events are eventually correlated.\n *\n * This is useful for dynamic stream creation patterns where you don't know all streams\n * upfront - they're discovered as events arrive.\n *\n * **Note:** Only one correlation worker can run at a time per Act instance.\n *\n * @param query - Query filter for correlation scans — see {@link Query}\n * (typically `{ after: -1, limit: 100 }`)\n * @param frequency - Correlation frequency in milliseconds (default: 10000)\n * @param callback - Optional callback invoked with newly discovered streams\n * @returns `true` if worker started, `false` if already running\n *\n * @example Start automatic correlation\n * ```typescript\n * // Start correlation worker scanning every 5 seconds\n * app.start_correlations(\n * { after: 0, limit: 100 },\n * 5000,\n * (leased) => {\n * console.log(`Discovered ${leased.length} new streams`);\n * }\n * );\n *\n * // Later, stop it\n * app.stop_correlations();\n * ```\n *\n * @example With checkpoint persistence\n * ```typescript\n * // Load last checkpoint\n * const lastId = await loadCheckpoint();\n *\n * app.start_correlations(\n * { after: lastId, limit: 100 },\n * 10000,\n * async (leased) => {\n * // Save checkpoint for next restart\n * if (leased.length) {\n * const maxId = Math.max(...leased.map(l => l.at));\n * await saveCheckpoint(maxId);\n * }\n * }\n * );\n * ```\n *\n * @see {@link correlate} for manual one-time correlation\n * @see {@link stop_correlations} to stop the worker\n */\n start_correlations(\n query: Query = {},\n frequency = 10_000,\n callback?: (subscribed: number) => void\n ): boolean {\n return this._correlate.startPolling(query, frequency, callback);\n }\n\n /**\n * Stops the automatic correlation worker.\n *\n * Call this to stop the background correlation worker started by {@link start_correlations}.\n * This is automatically called when the Act instance is disposed.\n *\n * @example\n * ```typescript\n * // Start correlation\n * app.start_correlations();\n *\n * // Later, stop it\n * app.stop_correlations();\n * ```\n *\n * @see {@link start_correlations}\n */\n stop_correlations() {\n this._correlate.stopPolling();\n }\n\n /**\n * Cancels any pending or active settle cycle.\n *\n * @see {@link settle}\n */\n stop_settling() {\n this._settle.stop();\n }\n\n /**\n * Reset reaction stream watermarks and request a drain on the next\n * `drain()` / `settle()` cycle.\n *\n * Use this to replay events through projections (or other reaction targets)\n * after changing handler logic. Equivalent to calling `store().reset(streams)`\n * directly, but also raises the orchestrator's internal \"needs drain\" flag —\n * `store().reset(...)` alone leaves the flag untouched, so a settled app\n * would short-circuit and skip the replay.\n *\n * Pair with `app.settle()` (or a single `app.drain()` for small streams).\n * `settle()` loops correlate→drain until no progress is made, so one call\n * fully catches up paginated streams without forcing callers to roll\n * their own loop.\n *\n * @param streams - Reaction target streams (e.g., projection names) to reset\n * @returns Count of streams that were actually reset\n *\n * @example Rebuild a projection (production)\n * ```typescript\n * await app.reset([\"my-projection\"]);\n * app.settle({ eventLimit: 1000 }); // emits \"settled\" when fully replayed\n * ```\n *\n * @example Rebuild a projection (tests / scripts)\n * ```typescript\n * await app.reset([\"my-projection\"]);\n * await app.drain({ eventLimit: 1000 }); // small streams: one pass is enough\n * ```\n *\n * @see {@link Store.reset} for the underlying store primitive\n * @see {@link settle} for the debounced full-catch-up loop\n */\n async reset(input: string[] | StreamFilter): Promise<number> {\n return this._scoped(async () => {\n const count = await store().reset(input);\n if (count > 0 && this._reactive_events.size > 0) this._armAll();\n return count;\n });\n }\n\n /**\n * Clear the blocked flag on streams without replaying their history.\n *\n * Use this to recover from a poison message after fixing the\n * underlying issue — the stream resumes from the next event after the\n * last successful ack, not from the beginning. Compare with\n * {@link reset}, which rebuilds from event 0 (suitable for projection\n * rebuilds, wrong for \"I fixed the bug, please retry\").\n *\n * Wraps `store().unblock(streams)` and raises the orchestrator's\n * internal \"needs drain\" flag so a settled app picks up the now-free\n * streams on the next cycle. Equivalent to calling `store().unblock(...)`\n * directly, but `store().unblock(...)` alone leaves the flag\n * untouched.\n *\n * @param streams - Stream names to unblock\n * @returns Count of streams that were actually flipped (were blocked)\n *\n * @example Recover from a 4xx webhook after fixing the bug\n * ```typescript\n * await app.unblock([\"webhooks-out-customer-42\"]);\n * // The stream resumes from the next event, not from zero.\n * ```\n *\n * @see {@link Store.unblock} for the underlying store primitive\n * @see {@link reset} for the rebuild-from-zero alternative\n */\n async unblock(input: string[] | StreamFilter): Promise<number> {\n return this._scoped(async () => {\n const count = await store().unblock(input);\n if (count > 0 && this._reactive_events.size > 0) this._armAll();\n return count;\n });\n }\n\n /**\n * Atomically wipe the store and rebuild it from an async stream of\n * committed events. The framework owns iteration, validation,\n * `drop_snapshots` filtering, `on_progress`, and the per-call\n * `old → new` causation remap; the adapter's {@link Store.restore}\n * driver supplies the transaction lifecycle and per-event insert.\n *\n * Throws if the adapter has no restore capability. Throws on the\n * first invalid event (negative version, malformed `created`) with\n * the running index in the message; atomic transaction rollback in\n * the adapter means a failing restore leaves the store byte-for-byte\n * unchanged.\n *\n * @param source - Async stream of events in target order. Streamed\n * rather than buffered so multi-million-event backups don't OOM.\n * Each event's original `id` is used as a causation lookup key but\n * never written through — adapters renumber densely.\n * @param opts - {@link ScanOptions}. `drop_snapshots` skips\n * `__snapshot__` events (counted in the result); `on_progress`\n * fires once per event.\n * @returns {@link ScanResult} with `kept`, `duration_ms`, and\n * `dropped` per-category counters.\n *\n * @example Round-trip a CSV backup\n * ```typescript\n * async function* parseCsv(blob: string) {\n * for (const line of blob.split(\"\\n\").slice(1)) {\n * const [id, name, data, stream, version, created, meta] = parse(line);\n * yield {\n * id: +id, name, data: JSON.parse(data), stream,\n * version: +version, created: new Date(created),\n * meta: JSON.parse(meta),\n * };\n * }\n * }\n * const result = await app.restore(parseCsv(csvBlob), {});\n * console.log(`Restored ${result.kept} events in ${result.duration_ms}ms`);\n * await cache().clear(); // operator's responsibility\n * ```\n *\n * @see {@link Store.restore} for the underlying driver-pattern primitive.\n */\n async restore(\n source: EventSource,\n opts: ScanOptions = {},\n sink?: EventSink\n ): Promise<ScanResult> {\n return this._scoped(async () => {\n const started = Date.now();\n // Dry-run: walk the source via scan without touching any sink\n // — same scan loop, no callback, no transaction, no capability\n // check. Returns the counts a destructive restore would land.\n if (opts.dry_run) {\n const partial = await scan(source, opts);\n return { ...partial, duration_ms: Date.now() - started };\n }\n // Default sink is the singleton store. Explicit `sink` lets\n // callers route to a different EventSink (another adapter, a\n // CsvFile, etc.) without binding the singleton.\n const target: EventSink =\n sink ??\n (() => {\n const s = store();\n if (!s.restore) throw new Error(\"adapter has no restore capability\");\n return s as EventSink;\n })();\n let kept = 0;\n let dropped = { closed_streams: 0, snapshots: 0, empty_streams: 0 };\n await target.restore(async (callback) => {\n const partial = await scan(source, opts, callback);\n kept = partial.kept;\n dropped = partial.dropped;\n });\n return { kept, dropped, duration_ms: Date.now() - started };\n });\n }\n\n /**\n * Return every currently-blocked stream position. Convenience wrapper\n * around `store().query_streams(cb, { blocked: true })` for the common\n * \"show me what's broken\" operational query.\n *\n * Results are ordered by stream name, paginated by `limit` (default\n * 100). Pass `after` to fetch the next page (keyset cursor on the\n * stream name). For richer queries — including blocked + source\n * filters, or full unblocked introspection — drop to\n * `store().query_streams(...)` directly.\n *\n * @returns Array of {@link StreamPosition} for currently-blocked streams.\n *\n * @example Discover and recover\n * ```typescript\n * const blocked = await app.blocked_streams();\n * console.table(blocked.map(({ stream, retry, error }) => ({ stream, retry, error })));\n *\n * // Operator investigates, then bulk-unblocks the family:\n * await app.unblock({ stream: \"^webhooks-out-\" });\n * ```\n */\n async blocked_streams(options?: {\n after?: string;\n limit?: number;\n }): Promise<StreamPosition[]> {\n return this._scoped(async () => {\n const positions: StreamPosition[] = [];\n await store().query_streams(\n (p) => {\n positions.push(p);\n },\n { blocked: true, after: options?.after, limit: options?.limit }\n );\n return positions;\n });\n }\n\n /**\n * Operator-driven store audit (#723).\n *\n * Walks the connected store and yields per-category findings —\n * each tagged with the remediation it suggests. Same operator-\n * driven category as `app.close()` / `app.reset()` /\n * `app.unblock()` / `app.blocked_streams()`: never auto-invoked by\n * the framework; the operator decides when to run it (CI gate,\n * scheduled job, ad-hoc forensics) and what to do with the\n * findings.\n *\n * Categories are independent — pass a subset to scope the work,\n * or omit to run everything:\n *\n * ```typescript\n * // Targeted: schema drift + deprecated-event load only\n * for await (const f of app.audit([\"schema\", \"deprecated-load\"], {\n * query: { created_after: lastScan },\n * thresholds: { deprecatedLoadShareMin: 0.10 },\n * })) {\n * await escalate(f);\n * }\n *\n * // Full audit, default thresholds\n * for await (const f of app.audit()) console.log(f);\n * ```\n *\n * Returns an `AsyncIterable` so callers can `break` early — the\n * underlying store paginations respect the iterator protocol and\n * stop cleanly. Each finding is emitted independently, so\n * pipelining into Slack / persistence / further analysis works\n * without buffering the full report in memory.\n *\n * Findings shape — see {@link AuditFinding}. The discriminated\n * union carries enough context for the operator to act on each\n * finding directly: stream id, event id, recommendation hints.\n *\n * @param categories - Subset of categories to run (default: all).\n * @param options - Query window + per-category thresholds.\n * @returns Async iterable of {@link AuditFinding}.\n */\n audit(\n categories?: AuditCategory[],\n options?: AuditOptions\n ): AsyncIterable<AuditFinding> {\n return audit(this._audit_deps, categories, options);\n }\n\n /**\n * Bulk-update scheduling priority for streams matching `filter`.\n *\n * Operator-grade override of the `claim()` lagging-frontier\n * ordering (ACT-102). Useful when a long-running replay needs to\n * jump ahead of other lagging streams, or when a no-longer-urgent\n * job should yield slots back to the rest. Build-time priorities\n * (set via the resolver's `priority` field) are subject to a\n * `max()` invariant across reactions; this API ignores that and\n * sets the priority outright on every matching row.\n *\n * Filter shape mirrors {@link query} / {@link Store.query_streams}:\n * `stream` / `source` are regex by default, exact with the\n * `*_exact` flags; `blocked` restricts to blocked or unblocked\n * rows. **An empty filter (`{}`) updates every registered stream.**\n *\n * @param filter - Selection criteria (regex by default).\n * @param priority - New priority value. Set as-is — no clamp.\n * @returns Count of streams whose priority changed.\n *\n * @example Boost a specific projection mid-replay\n * ```typescript\n * await app.prioritize({ stream: \"^proj-orders$\", stream_exact: false }, 10);\n * ```\n *\n * @example Drop all audit projections to background\n * ```typescript\n * await app.prioritize({ source: \"^audit-\" }, -5);\n * ```\n *\n * @example Reset everyone to default\n * ```typescript\n * await app.prioritize({}, 0);\n * ```\n *\n * @see {@link Store.prioritize} for the underlying primitive\n * @see {@link claim} for how priority biases scheduling\n */\n async prioritize(filter: StreamFilter, priority: number): Promise<number> {\n return this._scoped(() => store().prioritize(filter, priority));\n }\n\n /**\n * Close the books — guard, archive, truncate, and optionally restart streams.\n *\n * Safely removes historical events from the operational store:\n *\n * 1. **Correlate** — discover pending reaction targets\n * 2. **Safety check** — skip streams with pending reactions (skipped when no reactive events)\n * 3. **Guard** — commit `__tombstone__` with `expectedVersion` to block concurrent writes\n * 4. **Load state** — for streams in `snapshots`, load final state while guarded (no races)\n * 5. **Archive** — user callback per stream (abort-all on failure, streams are guarded)\n * 6. **Truncate + seed** — atomic: delete all events, insert `__snapshot__` or `__tombstone__`\n * 7. **Cache** — invalidate (tombstoned) or warm (restarted)\n * 8. **Emit \"closed\"** — lifecycle event with results\n *\n * @param targets - Per-stream close options (stream, restart?, archive?)\n * @returns `{ truncated: TruncateResult, skipped: string[] }`\n *\n * @example Archive and close\n * ```typescript\n * await app.close([\n * { stream: \"order-123\", archive: async () => { await archiveToS3(\"order-123\"); } },\n * { stream: \"order-456\" },\n * ]);\n * ```\n *\n * @example Close with restart (state loaded automatically after guard)\n * ```typescript\n * await app.close([\n * { stream: \"counter-1\", restart: true },\n * { stream: \"counter-2\" }, // tombstoned\n * ]);\n * ```\n */\n async close(targets: CloseTarget[]): Promise<CloseResult> {\n if (!targets.length) return { truncated: new Map(), skipped: [] };\n\n return this._scoped(async () => {\n // Correlate first so dynamic reaction targets are discovered before\n // the safety check examines subscription positions.\n await this.correlate({ limit: 1000 });\n\n // Synthesize an actor for the close transaction so user-supplied\n // correlators can still tag tenant context / trace ids.\n const closeActor = { id: \"$close\", name: \"close\" };\n const result = await runCloseCycle(targets, {\n reactiveEventsSize: this._reactive_events.size,\n eventToState: this._event_to_state,\n load: this._es.load,\n tombstone: this._es.tombstone,\n logger: this._logger,\n correlation: closeCorrelation(this._correlator, closeActor),\n });\n\n this.emit(\"closed\", result);\n return result;\n });\n }\n\n /**\n * Debounced, non-blocking correlate→drain cycle.\n *\n * Call this after `app.do()` (or `app.reset()`) to schedule a background\n * drain. Multiple rapid calls within the debounce window are coalesced\n * into a single cycle. Runs correlate→drain in a loop until a pass makes\n * no progress — no new subscriptions, no acks, no blocks — then emits\n * the `\"settled\"` lifecycle event. This means a single `settle()` call\n * fully catches up paginated streams (e.g. after `reset()` on a long\n * projection) without forcing callers to loop.\n *\n * @param options - Settle configuration — see {@link SettleOptions} for fields:\n * `debounceMs` (default 10), `correlate` (default `{ after: -1, limit: 100 }`),\n * `maxPasses` (default `Infinity` — kill-switch for runaway loops),\n * `streamLimit` (default 10), `eventLimit` (default 10),\n * `leaseMillis` (default 10000).\n *\n * @example API mutations\n * ```typescript\n * await app.do(\"CreateItem\", target, input);\n * app.settle(); // non-blocking, returns immediately\n *\n * app.on(\"settled\", (drain) => {\n * // notify SSE clients, invalidate caches, etc.\n * });\n * ```\n *\n * @see {@link drain} for single synchronous drain cycles\n * @see {@link correlate} for manual correlation\n */\n settle(options: SettleOptions = {}): void {\n this._settle.schedule(options);\n }\n}\n","/**\n * @module event-versions\n * @category Internal\n *\n * Auto-deprecation of legacy event versions via the `_v<digits>` naming\n * convention (ACT-403).\n *\n * Act's schema-evolution pattern keeps the old and new event names alive\n * forever — the old name on the read path (reducers), the new on the write\n * path (emissions). This module reads the convention to identify legacy\n * versions automatically; the framework then enforces \"emit only the\n * current version\" at build time and warns at runtime for dynamic emits.\n *\n * Convention pin: only `_v<digits>` with digits ≥ 2 counts as a version\n * suffix. `Foo_v1` is just a literal event name (the base `Foo` is\n * implicitly v1). Pinning here keeps the contract surface small.\n *\n * @internal\n */\n\nconst VERSION_SUFFIX = /^(.+?)_v(\\d+)$/;\n\ntype Versioned = { version: number; name: string };\n\n/**\n * Splits an event name into (base, version). Names without a `_v<n≥2>`\n * suffix are returned as (name, 1) — the base is its own implicit v1.\n */\nfunction parse(name: string): { base: string; version: number } {\n const m = name.match(VERSION_SUFFIX);\n if (m) {\n const v = Number.parseInt(m[2], 10);\n if (v >= 2) return { base: m[1], version: v };\n }\n return { base: name, version: 1 };\n}\n\n/**\n * Returns the set of event names that are deprecated by virtue of having\n * a higher-numbered sibling in the registry. The highest version in each\n * group is the current version; every lower version is deprecated.\n *\n * Gaps are allowed: `{Foo, Foo_v3}` → `Foo` is deprecated, `Foo_v3` is\n * current. The framework picks the max regardless of contiguity.\n *\n * Single-version groups (no siblings) yield no deprecations.\n *\n * @internal\n */\nexport function deprecatedEventNames(names: Iterable<string>): Set<string> {\n const groups = new Map<string, Versioned[]>();\n for (const name of names) {\n const { base, version } = parse(name);\n const list = groups.get(base);\n if (list) list.push({ version, name });\n else groups.set(base, [{ version, name }]);\n }\n const deprecated = new Set<string>();\n for (const list of groups.values()) {\n if (list.length < 2) continue;\n list.sort((a, b) => b.version - a.version); // descending\n // index 0 is current; the rest are deprecated\n for (let i = 1; i < list.length; i++) deprecated.add(list[i].name);\n }\n return deprecated;\n}\n\n/**\n * Given a deprecated event name and the full set of event names in its\n * registry, returns the current (highest-version) sibling. Used to build\n * actionable error messages — \"use `Foo_v3` instead.\"\n *\n * Returns `undefined` if the event has no higher-versioned sibling (which\n * means the caller's classification is stale or wrong).\n *\n * @internal\n */\nexport function currentVersionOf(\n deprecatedName: string,\n allNames: Iterable<string>\n): string | undefined {\n const target = parse(deprecatedName);\n let highest: Versioned | undefined;\n for (const name of allNames) {\n const { base, version } = parse(name);\n if (base !== target.base) continue;\n if (!highest || version > highest.version) highest = { version, name };\n }\n return highest && highest.version > target.version ? highest.name : undefined;\n}\n","/**\n * @module audit\n * @category Internal\n *\n * Operator-driven store audit (#723).\n *\n * Walks the connected store and yields per-category {@link AuditFinding}s.\n * Each category answers a different \"what should I do with this store?\"\n * question and pairs with a remediation:\n *\n * - `schema` → fix the data model (poison events, unknown names)\n * - `close-candidate` → `app.close([...])`\n * - `restart-candidate` → `app.close([{stream, restart:true}, …])`\n * - `deprecated-load` → `app.close([...])` on the heaviest carriers\n * - `reaction-health` → `app.unblock(...)` / `app.reset(...)`\n * - `snapshot-drift` → manual `load({snap:true})` or wait for policy\n * - `routing-health` → restart-with-new-config to re-lane\n * - `correlation-gaps` → fix upstream correlator misconfig\n * - `clock-anomalies` → infra remediation (clock skew)\n *\n * ## Single-scan multiplex (efficiency contract)\n *\n * Earlier draft had each category run its own `store.query(...)`,\n * which meant N requested categories → N table walks. Bad for large\n * stores. Refactored to a pass-based design: each category is a\n * factory that returns an {@link AuditPass} with optional per-row\n * callbacks (`onEvent` / `onStream` / `onStat`) and a `finalize` hook\n * for any second-pass work. The dispatcher determines the UNION of\n * required data sources, runs each *once*, and broadcasts each row\n * to all interested passes. Worst case: three scans total (events,\n * streams, stats) regardless of how many categories the operator\n * requested. Most categories also share state — close-candidate and\n * restart-candidate both consume the same `onStat` stream; schema,\n * correlation-gaps, and clock-anomalies all hang off the same\n * `onEvent` broadcast.\n *\n * Categories that need follow-up work (snapshot-drift's per-stream\n * snapshot lookup, correlation-gaps' orphan-id check after collecting\n * ids) do that in their `finalize` hook with their own targeted store\n * calls — keeps the shared scan path minimal.\n *\n * Isolated from orchestration internals — `act.ts` builds the\n * {@link AuditDeps} bag at `.build()` time and hands it here via\n * a one-liner. The audit module never reaches into\n * `internal/{event-sourcing,drain-cycle,settle,close-cycle}.ts`; it\n * only reads through the deps interface and the public `Store`\n * surface. Same shape as `act-tck` within the workspace — a peer of\n * orchestration, not entangled with its private mechanics.\n *\n * @internal\n */\n\nimport type {\n AuditCategory,\n AuditFinding,\n AuditOptions,\n Committed,\n Logger,\n Schemas,\n State,\n Store,\n StreamPosition,\n StreamStats,\n} from \"../types/index.js\";\nimport { currentVersionOf, deprecatedEventNames } from \"./event-versions.js\";\n\n/**\n * Snapshot of orchestrator state the audit reads. Built once at\n * `app.build()`; the audit treats it as immutable for the duration\n * of a call. The orchestrator never passes its own private maps in\n * directly — this bag is the abstraction boundary so a future\n * orchestration refactor can't accidentally entangle with audit\n * logic.\n */\nexport type AuditDeps = {\n readonly store: () => Store;\n readonly logger: Logger;\n /** event-name → state that registers it (for schema validation). */\n readonly event_to_state: ReadonlyMap<string, State<any, any, any>>;\n /** state-name → state (for snapshot-supported check on restart-candidate). */\n readonly states: ReadonlyMap<string, State<any, any, any>>;\n /** All event names the registry knows (for unknown-name detection). */\n readonly known_events: ReadonlySet<string>;\n /** Declared drain lanes (for routing-health unknown-lane). */\n readonly declared_lanes: ReadonlySet<string>;\n /**\n * Event names that the registry has at least one reaction for —\n * used by routing-health to detect \"registered but unrouted\"\n * events. Normalized down from the internal `eventToLanes` map\n * (which carries lane-set details audit doesn't need).\n */\n readonly routed_events: ReadonlySet<string>;\n};\n\n/**\n * Defaults applied when the operator doesn't override via\n * {@link AuditOptions.thresholds}. Values land where most workloads\n * find them operationally useful — operators can tune per call.\n */\nconst DEFAULTS = {\n idle_days: 90,\n restart_min: 10_000,\n stuck_minutes: 30,\n deprecated_min: 0.1,\n drift_min: 500,\n near_block: 3,\n};\n\nconst ALL_CATEGORIES = [\n \"schema\",\n \"close-candidate\",\n \"restart-candidate\",\n \"deprecated-load\",\n \"reaction-health\",\n \"snapshot-drift\",\n \"routing-health\",\n \"correlation-gaps\",\n \"clock-anomalies\",\n] as const satisfies readonly AuditCategory[];\n\n/**\n * A single audit category, expressed as a stream-consumer:\n *\n * - `onEvent` / `onStream` / `onStat` are called by the dispatcher\n * during the shared scans. Each is optional; the dispatcher uses\n * the presence/absence to decide which scans to run.\n * - `finalize` runs after all shared scans complete. Categories that\n * need targeted follow-up store calls (snapshot-drift fetches the\n * last `__snapshot__` per drifted stream; correlation-gaps cross-\n * checks causations against the collected id set) do that here.\n * - `drain` is called last and returns the accumulated findings.\n */\ntype AuditPass = {\n category: AuditCategory;\n onEvent?: (e: Committed<Schemas, string>) => void;\n onStream?: (p: StreamPosition) => void;\n onStat?: (stream: string, s: StreamStats<Schemas>) => void;\n finalize?: (deps: AuditDeps) => Promise<void>;\n drain: () => AuditFinding[];\n};\n\ntype PassFactory = (deps: AuditDeps, options: AuditOptions) => AuditPass;\n\n/**\n * Top-level audit dispatcher. Single-scan multiplex: each requested\n * category contributes a `AuditPass`, the dispatcher determines the\n * union of required data sources (events / streams / stats), runs\n * each once, broadcasts rows, and yields per-category findings in\n * the order the categories were requested.\n *\n * Callers can `break` the iteration early — the underlying scan\n * loops have already completed by the time yield starts, so early\n * break only saves the iteration over already-collected findings.\n * (Per-row early termination during a scan isn't feasible without\n * coordination across passes; the audit is bounded by `options.query`\n * scoping rather than mid-scan cancellation.)\n */\nexport async function* audit(\n deps: AuditDeps,\n categories?: AuditCategory[],\n options: AuditOptions = {}\n): AsyncIterable<AuditFinding> {\n const requested = new Set<AuditCategory>(categories ?? [...ALL_CATEGORIES]);\n // Preserve a deterministic category order (matches ALL_CATEGORIES\n // declaration) so output ordering doesn't depend on the order\n // operators list categories in their call.\n const orderedCategories = ALL_CATEGORIES.filter((c) => requested.has(c));\n const passes: AuditPass[] = orderedCategories.map((c) =>\n PASS_FACTORIES[c](deps, options)\n );\n\n // Determine scan needs. `some(...)` short-circuits — three trivial\n // walks at worst.\n const needStats = passes.some((p) => p.onStat !== undefined);\n const needStreams = passes.some((p) => p.onStream !== undefined);\n const needEvents = passes.some((p) => p.onEvent !== undefined);\n\n if (needStats) {\n const stats = await deps\n .store()\n .query_stats<Schemas>({}, { count: true, names: true });\n for (const [stream, s] of stats) {\n for (const p of passes) p.onStat?.(stream, s);\n }\n }\n\n if (needStreams) {\n await deps.store().query_streams((pos) => {\n for (const p of passes) p.onStream?.(pos);\n });\n }\n\n if (needEvents) {\n await deps.store().query<Schemas>((event) => {\n for (const p of passes) p.onEvent?.(event);\n }, options.query);\n }\n\n // Async post-processing (per-stream queries, second-pass orphan\n // detection). Serial to avoid pool contention; categories are\n // independent so order doesn't matter semantically.\n for (const p of passes) await p.finalize?.(deps);\n\n // Yield findings in requested-category order.\n for (const p of passes) {\n for (const f of p.drain()) yield f;\n }\n}\n\n// =================== Pass factories ===================\n//\n// Each category is implemented as a closure-bound `AuditPass`. The\n// factory captures `deps` + relevant options + a `findings` array;\n// the returned pass exposes the per-row hooks the dispatcher calls.\n//\n// All findings are accumulated in a per-pass `findings` buffer and\n// returned from `drain()`. No yield-during-scan — that would couple\n// the pass to async iteration semantics and prevent the shared-scan\n// multiplexing.\n\n/**\n * `schema` — every event in the audit window is parsed against the\n * Zod schema the registry currently declares for its name. Two\n * failure modes: `unknown_event_name` (event sits on disk, registry\n * has no entry) and `schema_validation_failed` (event matches a\n * known name but fails the current Zod schema).\n */\nconst makeSchemaPass: PassFactory = (deps) => {\n const findings: AuditFinding[] = [];\n return {\n category: \"schema\",\n onEvent(event) {\n const name = String(event.name);\n const state = deps.event_to_state.get(name);\n if (!state) {\n // Skip framework markers — they're not user-declared.\n if (name.startsWith(\"__\")) return;\n findings.push({\n category: \"schema\",\n stream: event.stream,\n event_id: event.id,\n name,\n reason: \"unknown_event_name\",\n });\n return;\n }\n const schema = state.events[name];\n const parsed = schema.safeParse(event.data);\n if (!parsed.success) {\n findings.push({\n category: \"schema\",\n stream: event.stream,\n event_id: event.id,\n name,\n reason: \"schema_validation_failed\",\n zod_error: parsed.error,\n });\n }\n },\n drain: () => findings,\n };\n};\n\n/**\n * `deprecated-load` — workspace-wide event-name histogram classified\n * by the framework's `_v<digits>` rule. Built from the shared `onStat`\n * stream — accumulates per-name + per-stream totals in memory, then\n * emits one finding per deprecated event above the threshold during\n * `drain`.\n */\nconst makeDeprecatedLoadPass: PassFactory = (deps, options) => {\n const share_min =\n options.thresholds?.deprecated_min ?? DEFAULTS.deprecated_min;\n const totals = new Map<string, number>();\n const perStream = new Map<string, Map<string, number>>();\n return {\n category: \"deprecated-load\",\n onStat(stream, { names }) {\n // Contract: query_stats was called with `{names: true}`,\n // so adapter populates `names` with positive integer counts.\n // No runtime fallback needed.\n for (const [name, count] of Object.entries(names!)) {\n totals.set(name, (totals.get(name) ?? 0) + count!);\n let m = perStream.get(name);\n if (!m) {\n m = new Map();\n perStream.set(name, m);\n }\n m.set(stream, count!);\n }\n },\n drain() {\n const findings: AuditFinding[] = [];\n const grand = [...totals.values()].reduce((s, n) => s + n, 0);\n if (grand === 0) return findings;\n // Registry-driven deprecation classification (not on-disk-driven).\n const deprecated = deprecatedEventNames(deps.known_events);\n const sorted = [...deprecated]\n .map((name) => ({ name, count: totals.get(name) ?? 0 }))\n .sort((a, b) => b.count - a.count);\n for (const { name, count } of sorted) {\n if (count === 0) continue;\n if (count / grand < share_min) continue;\n // Contract: `deprecatedEventNames(registry)` only returns names\n // that have a higher version in the same family, so\n // `currentVersionOf(name, registry)` is guaranteed defined.\n const currentVersion = currentVersionOf(name, deps.known_events)!;\n // perStream is populated in lockstep with totals — name is guaranteed present.\n const topStreams = [...perStream.get(name)!.entries()]\n .map(([stream, c]) => ({ stream, count: c }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n findings.push({\n category: \"deprecated-load\",\n name,\n current_version: currentVersion,\n total: count,\n top_streams: topStreams,\n });\n }\n return findings;\n },\n };\n};\n\n/**\n * `close-candidate` — flags streams ripe for `app.close(...)`. Two\n * flavours: `idle` (head older than `idleDays`) and `terminal` (head\n * event name in operator-supplied `terminalEvents` list). Each\n * finding carries `restartSupported` (state has `.snap()`).\n */\nconst makeCloseCandidatePass: PassFactory = (deps, options) => {\n const idle_days = options.thresholds?.idle_days ?? DEFAULTS.idle_days;\n const terminal_events = new Set(options.thresholds?.terminal_events ?? []);\n const idle_cutoff = Date.now() - idle_days * 24 * 60 * 60 * 1000;\n const findings: AuditFinding[] = [];\n return {\n category: \"close-candidate\",\n onStat(stream, { head }) {\n const head_name = String(head.name);\n if (head_name.startsWith(\"__\")) return; // already-closed or mid-truncate\n // All in-tree adapters return `created` as Date; the Date\n // constructor passes Date instances through unchanged, so a\n // single call shape works regardless.\n const head_time = head.created.getTime();\n const is_idle = head_time < idle_cutoff;\n const is_terminal = terminal_events.has(head_name);\n if (!is_idle && !is_terminal) return;\n findings.push({\n category: \"close-candidate\",\n stream,\n last_event_at: head.created.toISOString(),\n reason: is_terminal ? \"terminal\" : \"idle\",\n idle_days: is_idle\n ? Math.floor((Date.now() - head_time) / (24 * 60 * 60 * 1000))\n : undefined,\n restart_supported: restartIsSupported(deps, head_name),\n });\n },\n drain: () => findings,\n };\n};\n\n/**\n * `restart-candidate` — streams above `eventCountForRestart` whose\n * state declares `.snap()`. Reads from the shared `onStat` stream.\n */\nconst makeRestartCandidatePass: PassFactory = (deps, options) => {\n const threshold = options.thresholds?.restart_min ?? DEFAULTS.restart_min;\n const findings: AuditFinding[] = [];\n return {\n category: \"restart-candidate\",\n onStat(stream, { head, count, names }) {\n // `count` / `names` always populated — query_stats is called\n // with both flags set; adapters keep them present together.\n if (count! < threshold) return;\n const head_name = String(head.name);\n if (head_name.startsWith(\"__\")) return;\n if (!restartIsSupported(deps, head_name)) return;\n findings.push({\n category: \"restart-candidate\",\n stream,\n count: count!,\n // names map is sparse — `__snapshot__` key absent when the\n // stream has never been snapshotted (a common case for the\n // restart-candidate signal).\n snaps: names![\"__snapshot__\"] ?? 0,\n });\n },\n drain: () => findings,\n };\n};\n\n/**\n * `reaction-health` — surfaces blocked / near-block / stuck-backoff\n * streams. Reads from the shared `onStream` stream-positions\n * broadcast.\n */\nconst makeReactionHealthPass: PassFactory = (_deps, options) => {\n const near_block = options.thresholds?.near_block ?? DEFAULTS.near_block;\n const stuck_minutes =\n options.thresholds?.stuck_minutes ?? DEFAULTS.stuck_minutes;\n const stuck_cutoff = Date.now() - stuck_minutes * 60 * 1000;\n const findings: AuditFinding[] = [];\n return {\n category: \"reaction-health\",\n onStream(p) {\n if (p.blocked) {\n findings.push({\n category: \"reaction-health\",\n stream: p.stream,\n status: \"blocked\",\n retry: p.retry,\n reason: p.error || \"blocked without recorded error\",\n });\n return;\n }\n if (p.retry >= near_block) {\n findings.push({\n category: \"reaction-health\",\n stream: p.stream,\n status: \"near-block\",\n retry: p.retry,\n reason: `retry ${p.retry} ≥ near-block threshold ${near_block}`,\n });\n return;\n }\n if (\n p.leased_by &&\n p.leased_until &&\n p.leased_until.getTime() < stuck_cutoff\n ) {\n const minutes = Math.floor(\n (Date.now() - p.leased_until.getTime()) / (60 * 1000)\n );\n findings.push({\n category: \"reaction-health\",\n stream: p.stream,\n status: \"stuck-backoff\",\n retry: p.retry,\n reason: `lease expired ${minutes}m ago without release`,\n });\n }\n },\n drain: () => findings,\n };\n};\n\n/**\n * `snapshot-drift` — buffers candidate streams from the shared\n * `onStat` pass (skipping non-snap states + tombstoned heads), then\n * does targeted per-stream lookups in `finalize` to find the last\n * `__snapshot__` event id and count events past it.\n */\nconst makeSnapshotDriftPass: PassFactory = (deps, options) => {\n const drift_min = options.thresholds?.drift_min ?? DEFAULTS.drift_min;\n // Streams the workspace pass identifies as drift candidates —\n // resolved in finalize with per-stream queries.\n const candidates: Array<{\n stream: string;\n total: number;\n snaps: number;\n }> = [];\n const findings: AuditFinding[] = [];\n return {\n category: \"snapshot-drift\",\n onStat(stream, { head, count, names }) {\n // restartIsSupported() already filters out framework markers\n // (__snapshot__, __tombstone__) — neither name appears in any\n // user state's events map, so the snap check rejects them.\n if (!restartIsSupported(deps, String(head.name))) return;\n if (count! < drift_min) return; // upper-bound short-circuit\n candidates.push({\n stream,\n total: count!,\n snaps: names![\"__snapshot__\"] ?? 0,\n });\n },\n async finalize(deps) {\n for (const { stream, total, snaps } of candidates) {\n let events_since_snap = total;\n let snap_at: number | undefined;\n if (snaps > 0) {\n const collected: Array<{ id: number }> = [];\n await deps.store().query(\n (e) => {\n collected.push({ id: e.id });\n },\n {\n stream,\n stream_exact: true,\n names: [\"__snapshot__\"],\n backward: true,\n limit: 1,\n with_snaps: true,\n }\n );\n // snaps > 0 means at least one `__snapshot__` event sits on\n // this stream — the backward-walk above must surface it.\n snap_at = collected[0]!.id;\n let after = 0;\n await deps.store().query(\n () => {\n after++;\n },\n { stream, stream_exact: true, after: snap_at }\n );\n events_since_snap = after;\n }\n if (events_since_snap < drift_min) continue;\n findings.push({\n category: \"snapshot-drift\",\n stream,\n events_since_snap,\n snap_at,\n });\n }\n },\n drain: () => findings,\n };\n};\n\n/**\n * `routing-health` — `unknown-lane` from the streams-table pass +\n * `unrouted` from the stats pass. Reads from BOTH shared streams.\n */\nconst makeRoutingHealthPass: PassFactory = (deps) => {\n const findings: AuditFinding[] = [];\n const seenEventNames = new Set<string>();\n return {\n category: \"routing-health\",\n onStream(p) {\n if (!p.lane) return; // default lane — never an unknown-lane finding\n if (deps.declared_lanes.has(p.lane)) return;\n findings.push({\n category: \"routing-health\",\n stream: p.stream,\n reason: \"unknown-lane\",\n lane: p.lane,\n });\n },\n onStat(_stream, { names }) {\n for (const name of Object.keys(names!)) {\n seenEventNames.add(name);\n }\n },\n finalize() {\n for (const name of seenEventNames) {\n if (name.startsWith(\"__\")) continue;\n if (deps.routed_events.has(name)) continue;\n findings.push({\n category: \"routing-health\",\n stream: \"*\",\n reason: \"unrouted\",\n });\n }\n return Promise.resolve();\n },\n drain: () => findings,\n };\n};\n\n/**\n * `correlation-gaps` — collects ids + parent_ids during the shared\n * event pass; flags orphans in `drain`. No second store walk — the\n * id-set + the (id, parent) buffer are both populated in one pass.\n */\nconst makeCorrelationGapsPass: PassFactory = () => {\n const seenIds = new Set<number>();\n const checks: Array<{ stream: string; id: number; parentId: number }> = [];\n return {\n category: \"correlation-gaps\",\n onEvent(e) {\n seenIds.add(e.id);\n const causation = (e.meta as Record<string, unknown> | undefined)\n ?.causation as { event?: { id?: number } } | undefined;\n const parentId = causation?.event?.id;\n if (parentId !== undefined) {\n checks.push({ stream: e.stream, id: e.id, parentId });\n }\n },\n drain() {\n const findings: AuditFinding[] = [];\n for (const { stream, id, parentId } of checks) {\n if (!seenIds.has(parentId)) {\n findings.push({\n category: \"correlation-gaps\",\n stream,\n event_id: id,\n reason: \"orphan-parent\",\n });\n }\n }\n return findings;\n },\n };\n};\n\n/**\n * `clock-anomalies` — flags future timestamps + per-stream out-of-\n * order `created`. Single pass, per-stream \"last seen\" state in a\n * Map. Cheap.\n */\nconst makeClockAnomaliesPass: PassFactory = () => {\n const findings: AuditFinding[] = [];\n const lastPerStream = new Map<string, number>();\n return {\n category: \"clock-anomalies\",\n onEvent(e) {\n // `created` is a Date instance per the Store contract.\n const created = e.created.getTime();\n if (created > Date.now()) {\n findings.push({\n category: \"clock-anomalies\",\n stream: e.stream,\n event_id: e.id,\n reason: \"future-created\",\n });\n }\n const prev = lastPerStream.get(e.stream);\n if (prev !== undefined && created < prev) {\n findings.push({\n category: \"clock-anomalies\",\n stream: e.stream,\n event_id: e.id,\n reason: \"out-of-order\",\n });\n }\n lastPerStream.set(e.stream, created);\n },\n drain: () => findings,\n };\n};\n\n/** Does the stream's owning state declare a `.snap()` reducer? */\nfunction restartIsSupported(deps: AuditDeps, headEventName: string): boolean {\n const state = deps.event_to_state.get(headEventName);\n return state?.snap !== undefined;\n}\n\n/** Factory registry — pass-creation indexed by category name. */\nconst PASS_FACTORIES: Record<AuditCategory, PassFactory> = {\n schema: makeSchemaPass,\n \"deprecated-load\": makeDeprecatedLoadPass,\n \"close-candidate\": makeCloseCandidatePass,\n \"restart-candidate\": makeRestartCandidatePass,\n \"reaction-health\": makeReactionHealthPass,\n \"snapshot-drift\": makeSnapshotDriftPass,\n \"routing-health\": makeRoutingHealthPass,\n \"correlation-gaps\": makeCorrelationGapsPass,\n \"clock-anomalies\": makeClockAnomaliesPass,\n};\n","/**\n * @module build-classify\n * @category Internal\n *\n * Build-time classification of the registry + state map. The Act constructor\n * needs four pre-computed inputs to wire its runtime subsystems:\n *\n * - `staticTargets` — known-up-front reaction targets (statics get\n * subscribed once at init; dynamics scan per event)\n * - `hasDynamicResolvers` — short-circuit flag for `correlate()`\n * - `reactiveEvents` — event names with at least one reaction (drives\n * the drain skip-flag in `do()` and `reset()`)\n * - `eventToState` — event-name → owning state, for `close({restart})`\n * seed loading in multi-state apps\n *\n * Pure function — single pass over events + states, fully testable without\n * instantiating Act.\n *\n * @internal\n */\n\nimport type {\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport type { StaticTarget } from \"./correlate-cycle.js\";\n\n/**\n * Classification result. Returned by {@link classifyRegistry}; consumed\n * piecewise by Act's constructor.\n *\n * @internal\n */\n/**\n * Sentinel for \"any reaction on this event has a dynamic resolver, so\n * the lane is opaque until correlate runs the function — arm every\n * controller.\" A Symbol rather than a string literal so it can't\n * collide with a user-declared lane named `\"all\"`.\n *\n * @internal\n */\nexport const ALL_LANES: unique symbol = Symbol(\"act-1103/all-lanes\");\n\n/**\n * Per-event lane fan-in (ACT-1103). For events whose every reaction\n * has a static resolver, the value is the union of those reactions'\n * declared lanes — `do()` arms only those controllers on commit. For\n * events with at least one dynamic resolver, the value is\n * {@link ALL_LANES}; `do()` falls back to arming every controller.\n *\n * @internal\n */\nexport type EventLaneSet = ReadonlySet<string> | typeof ALL_LANES;\n\nexport type Classification = {\n readonly staticTargets: StaticTarget[];\n readonly hasDynamicResolvers: boolean;\n readonly reactiveEvents: ReadonlySet<string>;\n readonly eventToState: ReadonlyMap<string, State<any, any, any>>;\n readonly eventToLanes: ReadonlyMap<string, EventLaneSet>;\n};\n\n/**\n * Walk the registry once to collect static reaction targets, the dynamic-\n * resolvers flag, the set of reactive event names, and the event-to-state\n * map. Static targets are deduplicated by (target, source) — two reactions\n * routing to the same projection produce one subscription.\n *\n * @internal\n */\nexport function classifyRegistry<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(\n registry: Registry<TSchemaReg, TEvents, TActions>,\n states: ReadonlyMap<string, State<Schema, any, any>>\n): Classification {\n const statics = new Map<string, StaticTarget>();\n const reactiveEvents = new Set<string>();\n const eventToLanes = new Map<string, EventLaneSet>();\n let hasDynamicResolvers = false;\n\n for (const [name, register] of Object.entries(registry.events)) {\n if (register.reactions.size > 0) reactiveEvents.add(name);\n for (const reaction of register.reactions.values()) {\n if (typeof reaction.resolver === \"function\") {\n hasDynamicResolvers = true;\n // Dynamic resolver — lane is opaque until runtime. Mark the\n // event as wildcard so `do()` falls back to arming every\n // controller for any commit of it.\n eventToLanes.set(name, ALL_LANES);\n } else {\n const { target, source, priority = 0, lane } = reaction.resolver;\n const lane_name = lane ?? \"default\";\n const existing_lanes = eventToLanes.get(name);\n if (existing_lanes !== ALL_LANES) {\n const set =\n (existing_lanes as Set<string> | undefined) ?? new Set<string>();\n set.add(lane_name);\n eventToLanes.set(name, set);\n }\n const key = `${target}|${source ?? \"\"}`;\n const existing = statics.get(key);\n if (!existing) {\n statics.set(key, { stream: target, source, priority, lane });\n } else {\n // ACT-1103: lanes don't merge — disagreement is a config error.\n if ((existing.lane ?? undefined) !== (lane ?? undefined))\n throw new Error(\n `Stream \"${target}\" has conflicting lane assignments ` +\n `(\"${existing.lane ?? \"default\"}\" vs \"${lane ?? \"default\"}\")`\n );\n if (priority > (existing.priority as number)) {\n // Multiple reactions with the same (target, source) — keep\n // the max priority so the highest-priority registrant sets\n // the scheduling lane (mirrors subscribe-side semantics).\n // `existing.priority` is always defined here since we always\n // set it when inserting, but the StaticTarget type marks it\n // optional for backwards compat with external consumers.\n statics.set(key, { ...existing, priority });\n }\n }\n }\n }\n }\n\n // Event-name → owning state. Duplicate event names are rejected at\n // registration time (merge.ts), so each entry is unambiguous.\n const eventToState = new Map<string, State<any, any, any>>();\n for (const merged of states.values()) {\n for (const eventName of Object.keys(merged.events)) {\n eventToState.set(eventName, merged);\n }\n }\n\n return {\n staticTargets: [...statics.values()],\n hasDynamicResolvers,\n reactiveEvents,\n eventToState,\n eventToLanes,\n };\n}\n","/**\n * @module close-cycle\n * @category Internal\n *\n * Pure orchestration of the close-the-books flow: scan stream heads,\n * partition by reaction safety, guard with tombstones, optionally seed\n * restart state, run user archive callbacks, atomically truncate, and\n * update the cache.\n *\n * The Act orchestrator owns lifecycle (correlate gate, emit(\"closed\")) and\n * the registry-derived inputs (reactive-event count, event→state map). All\n * sequential phase work between those state touches lives here.\n *\n * @internal\n */\n\nimport { cache, SNAP_EVENT, store, TOMBSTONE_EVENT } from \"../ports.js\";\nimport type {\n CloseResult,\n CloseTarget,\n Logger,\n Schema,\n State,\n} from \"../types/index.js\";\nimport type { EsOps } from \"./event-sourcing.js\";\n\n/**\n * Dependencies the close cycle needs from the Act orchestrator. Decoupled\n * from `Act` itself so the cycle can be exercised from tests in isolation.\n *\n * @internal\n */\nexport type CloseCycleDeps = {\n readonly reactiveEventsSize: number;\n readonly eventToState: ReadonlyMap<string, State<any, any, any>>;\n readonly load: EsOps[\"load\"];\n readonly tombstone: EsOps[\"tombstone\"];\n readonly logger: Logger;\n /**\n * Correlation id for the close transaction. Caller (`Act.close`)\n * computes this via the configured {@link Correlator}, so close\n * commits share the user's chosen id scheme instead of stamping a\n * UUID.\n */\n readonly correlation: string;\n};\n\n/**\n * Per-stream scan result: latest non-tombstone domain event metadata.\n * `lastEventName` is always defined — the scan filters tombstones in the\n * callback and queries without `with_snaps`, so any event reaching the\n * callback is a domain event whose name we capture alongside id/version.\n */\ntype StreamHead = {\n readonly maxId: number;\n readonly version: number;\n readonly lastEventName: string;\n};\n\n/**\n * Run the full close cycle for the given targets. Caller owns the\n * lifecycle event emission.\n *\n * @internal\n */\nexport async function runCloseCycle(\n targets: CloseTarget[],\n deps: CloseCycleDeps\n): Promise<CloseResult> {\n // Caller (Act.close) filters empty targets; runCloseCycle assumes at\n // least one target.\n const targetMap = new Map(targets.map((t) => [t.stream, t]));\n const streams = [...targetMap.keys()];\n const skipped: string[] = [];\n\n // 1. Scan: find the latest non-tombstone event per stream\n const streamInfo = await scanStreamHeads(streams);\n\n // 2. Partition: skip streams with pending reactions in flight\n const safe = await partitionBySafety(\n streamInfo,\n deps.reactiveEventsSize,\n skipped\n );\n if (!safe.length) return { truncated: new Map(), skipped };\n\n // 3. Guard: commit a tombstone with expectedVersion per safe stream.\n // Correlation comes from the orchestrator's configured correlator so\n // close commits share the app's id scheme — see ACT-404.\n const { guarded, guardEvents } = await guardWithTombstones(\n safe,\n streamInfo,\n deps.correlation,\n deps.tombstone,\n skipped\n );\n if (!guarded.length) return { truncated: new Map(), skipped };\n\n // 4. Seed: load final state for restart targets through the owning state\n const seedStates = await loadRestartSeeds(\n guarded,\n targetMap,\n streamInfo,\n deps.eventToState,\n deps.load,\n deps.logger\n );\n\n // 5. Archive: user-provided per-stream callback while guarded\n await runArchiveCallbacks(guarded, targetMap);\n\n // 6. Truncate + seed: atomic per-store transaction\n const truncated = await truncateAndWarmCache(\n guarded,\n seedStates,\n guardEvents,\n deps.correlation\n );\n\n return { truncated, skipped };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 1 — scan stream heads\n// ---------------------------------------------------------------------------\n\nasync function scanStreamHeads(\n streams: string[]\n): Promise<Map<string, StreamHead>> {\n // One round trip: query_stats returns the latest non-snap event per\n // stream (heads-only cheap path, indexed). Streams whose latest non-snap\n // event is a tombstone are filtered out in the loop — we don't want to\n // re-tombstone an already-closed stream. Streams with no events (or\n // only snap/tombstone events filtered out) are absent from the result\n // map entirely.\n const stats = await store().query_stats(streams, {\n exclude: [SNAP_EVENT],\n });\n const out = new Map<string, StreamHead>();\n for (const [stream, { head }] of stats) {\n if (head.name === TOMBSTONE_EVENT) continue;\n out.set(stream, {\n maxId: head.id,\n version: head.version,\n lastEventName: head.name as string,\n });\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2 — partition by safety\n// ---------------------------------------------------------------------------\n\nasync function partitionBySafety(\n streamInfo: Map<string, StreamHead>,\n reactiveEventsSize: number,\n skipped: string[]\n): Promise<string[]> {\n if (reactiveEventsSize === 0) return [...streamInfo.keys()];\n\n // Read-only probe: query_streams returns subscription positions without\n // leasing or mutating retry state.\n const pendingSet = new Set<string>();\n await store().query_streams((position) => {\n const sourceRe = position.source ? RegExp(position.source) : undefined;\n for (const [stream, info] of streamInfo) {\n if ((!sourceRe || sourceRe.test(stream)) && position.at < info.maxId) {\n pendingSet.add(stream);\n }\n }\n });\n\n const safe: string[] = [];\n for (const [stream] of streamInfo) {\n if (pendingSet.has(stream)) skipped.push(stream);\n else safe.push(stream);\n }\n return safe;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 3 — guard with tombstones\n// ---------------------------------------------------------------------------\n\nasync function guardWithTombstones(\n safe: string[],\n streamInfo: Map<string, StreamHead>,\n correlation: string,\n tombstone: EsOps[\"tombstone\"],\n skipped: string[]\n): Promise<{\n guarded: string[];\n guardEvents: Map<string, { id: number; stream: string }>;\n}> {\n const guarded: string[] = [];\n const guardEvents = new Map<string, { id: number; stream: string }>();\n await Promise.all(\n safe.map(async (stream) => {\n const info = streamInfo.get(stream)!;\n const committed = await tombstone(stream, info.version, correlation);\n if (committed) {\n guarded.push(stream);\n guardEvents.set(stream, { id: committed.id, stream });\n } else {\n // ConcurrencyError → another writer beat the guard\n skipped.push(stream);\n }\n })\n );\n return { guarded, guardEvents };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 4 — load restart seeds\n// ---------------------------------------------------------------------------\n\nasync function loadRestartSeeds(\n guarded: string[],\n targetMap: Map<string, CloseTarget>,\n streamInfo: Map<string, StreamHead>,\n eventToState: ReadonlyMap<string, State<any, any, any>>,\n load: EsOps[\"load\"],\n logger: Logger\n): Promise<Map<string, Schema>> {\n const seedStates = new Map<string, Schema>();\n await Promise.all(\n guarded\n .filter((s) => targetMap.get(s)?.restart)\n .map(async (stream) => {\n // streamInfo entry is guaranteed (guarded ⊆ streamInfo.keys()).\n const lastEventName = streamInfo.get(stream)!.lastEventName;\n const ownerState = eventToState.get(lastEventName);\n if (!ownerState) {\n // No registered state owns the stream's events (deleted state,\n // schema versioning gone wrong, etc.). Tombstone instead of\n // seeding a corrupted snapshot.\n logger.error(\n `Cannot seed restart for \"${stream}\": no registered state owns event \"${lastEventName}\". Stream will be tombstoned instead.`\n );\n return;\n }\n const snap = await load(ownerState, stream);\n seedStates.set(stream, snap.state as Schema);\n })\n );\n return seedStates;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 5 — archive callbacks\n// ---------------------------------------------------------------------------\n\nasync function runArchiveCallbacks(\n guarded: string[],\n targetMap: Map<string, CloseTarget>\n): Promise<void> {\n // Sequential — user callbacks may share resources (S3 client, etc.) and\n // a failure should propagate to the caller without leaving partial state.\n for (const stream of guarded) {\n const archiveFn = targetMap.get(stream)?.archive;\n if (archiveFn) await archiveFn();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Phase 6 — atomic truncate + cache warm\n// ---------------------------------------------------------------------------\n\nasync function truncateAndWarmCache(\n guarded: string[],\n seedStates: Map<string, Schema>,\n guardEvents: Map<string, { id: number; stream: string }>,\n correlation: string\n): Promise<CloseResult[\"truncated\"]> {\n const truncTargets = guarded.map((stream) => {\n const snapshot = seedStates.get(stream);\n const guard = guardEvents.get(stream)!;\n return {\n stream,\n snapshot,\n meta: {\n correlation,\n causation: {\n event: { id: guard.id, name: TOMBSTONE_EVENT, stream: guard.stream },\n },\n },\n };\n });\n const truncated = await store().truncate(truncTargets);\n\n // Cache invalidate / warm — use real event IDs from committed events\n await Promise.all(\n guarded.map(async (stream) => {\n const entry = truncated.get(stream);\n const state = seedStates.get(stream);\n if (state && entry) {\n await cache().set(stream, {\n state,\n version: entry.committed.version,\n event_id: entry.committed.id,\n patches: 0,\n snaps: 1,\n });\n } else {\n await cache().invalidate(stream);\n }\n })\n );\n\n return truncated;\n}\n","/**\n * @module correlate-cycle\n * @category Internal\n *\n * Correlation — the discovery half of the correlate→drain pair. Owns the\n * lazy init (subscribe static targets, read cold-start watermark), the\n * dynamic-resolver scan that registers new streams as events arrive, and\n * the periodic timer that drives background discovery.\n *\n * The Act orchestrator passes registry + classification (which static\n * targets to subscribe, whether any dynamic resolvers exist) at build\n * time; everything past that lives here.\n *\n * @internal\n */\n\nimport { log, store } from \"../ports.js\";\nimport type {\n Query,\n ReactionPayload,\n Registry,\n SchemaRegister,\n Schemas,\n} from \"../types/index.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport { LruSet } from \"./lru-map.js\";\n\n/**\n * Static resolver target collected at build time. Subscribed once during\n * init; never re-evaluated.\n *\n * @property priority - Scheduling priority for the resolved target stream.\n * Combined with peers via `max()` at build time when multiple reactions\n * target the same stream — see `build-classify.ts`.\n *\n * @internal\n */\nexport type StaticTarget = {\n readonly stream: string;\n readonly source?: string;\n readonly priority?: number;\n readonly lane?: string;\n};\n\n/**\n * Drives correlation for one Act instance. Owns the checkpoint, the\n * subscribed-streams LRU, and the periodic timer.\n *\n * @internal\n */\nexport class CorrelateCycle<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n> {\n private _checkpoint = -1;\n private _initialized = false;\n private _timer: ReturnType<typeof setInterval> | undefined = undefined;\n private readonly _subscribed: LruSet<string>;\n\n constructor(\n private readonly registry: Registry<TSchemaReg, TEvents, TActions>,\n private readonly staticTargets: ReadonlyArray<StaticTarget>,\n private readonly hasDynamicResolvers: boolean,\n private readonly cd: DrainOps<TEvents>,\n maxSubscribedStreams: number,\n private readonly onInit?: () => void\n ) {\n this._subscribed = new LruSet(maxSubscribedStreams);\n }\n\n /** Last correlated event id. */\n get checkpoint(): number {\n return this._checkpoint;\n }\n\n /**\n * Initialize correlation state on first call.\n * - Reads max(at) from store as cold-start checkpoint\n * - Subscribes static resolver targets (idempotent upsert)\n * - Populates the subscribed-streams LRU\n * - Fires `onInit` once (Act uses this to flag a cold-start drain)\n */\n async init(): Promise<void> {\n if (this._initialized) return;\n this._initialized = true;\n\n const { watermark } = await store().subscribe([...this.staticTargets]);\n this._checkpoint = watermark;\n this.onInit?.();\n for (const { stream } of this.staticTargets) {\n this._subscribed.add(stream);\n }\n }\n\n /**\n * Discover dynamic-resolver targets in the events past the checkpoint\n * and register any new streams via `cd.subscribe`. Static targets are\n * subscribed at init time, so this only walks dynamic resolvers.\n */\n async correlate(\n query: Query = { after: -1, limit: 10 }\n ): Promise<{ subscribed: number; last_id: number }> {\n await this.init();\n\n // No dynamic resolvers — nothing to discover\n if (!this.hasDynamicResolvers)\n return { subscribed: 0, last_id: this._checkpoint };\n\n // Use checkpoint as floor, allow explicit query.after to override upward\n const after = Math.max(this._checkpoint, query.after || -1);\n const correlated = new Map<\n string,\n {\n source?: string;\n priority: number;\n lane?: string;\n payloads: ReactionPayload<TEvents>[];\n }\n >();\n let last_id = after;\n await store().query<TEvents>(\n (event) => {\n last_id = event.id;\n const register = this.registry.events[event.name];\n // skip events with no registered reactions\n if (register) {\n for (const reaction of register.reactions.values()) {\n // only evaluate dynamic resolvers — statics are subscribed at init\n if (typeof reaction.resolver !== \"function\") continue;\n const resolved = reaction.resolver(event);\n if (resolved && !this._subscribed.has(resolved.target)) {\n const incomingPriority = resolved.priority ?? 0;\n const entry = correlated.get(resolved.target) || {\n source: resolved.source,\n priority: incomingPriority,\n lane: resolved.lane,\n payloads: [],\n };\n // Multiple reactions targeting the same stream within a\n // single correlate scan — keep the max priority so the\n // highest-priority reaction sets the lane (matches the\n // subscribe-side `max()` invariant).\n if (incomingPriority > entry.priority)\n entry.priority = incomingPriority;\n entry.payloads.push({\n ...reaction,\n source: resolved.source,\n event,\n });\n correlated.set(resolved.target, entry);\n }\n }\n }\n },\n { ...query, after }\n );\n\n if (correlated.size) {\n const streams = [...correlated.entries()].map(\n ([stream, { source, priority, lane }]) => ({\n stream,\n source,\n priority,\n lane,\n })\n );\n const { subscribed } = await this.cd.subscribe(streams);\n // Advance checkpoint only after subscribe succeeds\n this._checkpoint = last_id;\n if (subscribed) {\n // Track newly subscribed dynamic targets\n for (const { stream } of streams) {\n this._subscribed.add(stream);\n }\n }\n return { subscribed, last_id };\n }\n // No streams to subscribe — safe to advance\n this._checkpoint = last_id;\n return { subscribed: 0, last_id };\n }\n\n /**\n * Start a periodic correlation worker. Returns false if one is already\n * running. Errors from `correlate()` are routed through `log()` so they\n * land in the configured logger (the timer keeps running on failure).\n */\n startPolling(\n query: Query = {},\n frequency = 10_000,\n callback?: (subscribed: number) => void\n ): boolean {\n if (this._timer) return false;\n\n const limit = query.limit || 100;\n this._timer = setInterval(\n () =>\n this.correlate({ ...query, after: this._checkpoint, limit })\n .then((result) => {\n if (callback && result.subscribed) callback(result.subscribed);\n })\n .catch((err) => log().error(err)),\n frequency\n );\n return true;\n }\n\n /** Stop the periodic correlation worker. Idempotent. */\n stopPolling(): void {\n if (this._timer) {\n clearInterval(this._timer);\n this._timer = undefined;\n }\n }\n}\n","/**\n * @module correlator\n * @category Internal\n *\n * Correlation-id generator and the default implementation (ACT-404).\n *\n * The default produces a readable, time-monotonic-within-window, lowercase\n * id like `coun-incr-lwxk9p3a` — short enough to scan in logs, structured\n * enough to identify the originating state/action, and well-distributed\n * enough that competing-consumer workers don't collide.\n *\n * Apps override via {@link ActOptions.correlator} to plug in any scheme\n * (tenant-prefixed, trace-id-propagated, DB-sequence-backed, etc.).\n *\n * @internal\n */\n\nimport { randomInt } from \"node:crypto\";\nimport type { Actor, Correlator } from \"../types/index.js\";\n\nconst BASE = 36;\nconst SEG_WIDTH = 4;\nconst SEG_SPACE = BASE ** SEG_WIDTH;\n\nfunction seg(n: number): string {\n return n.toString(BASE).padStart(SEG_WIDTH, \"0\");\n}\n\n/**\n * Default {@link Correlator}. Produces ids of the form\n * `{state[:4]}-{action[:4]}-{4 ms}{4 random}` — 18 characters, lowercase\n * base36.\n *\n * - Prefix carries human-meaningful context (state + action) so operators\n * can identify a workflow at a glance in logs and query results.\n * - The 4-character `Date.now() % 36^4` segment wraps every ~28 minutes,\n * long enough that adjacent inserts in a typical workflow share B-tree\n * pages — index locality, not global sortability, is the goal.\n * - The 4-character random tail gives 1.68M values per ms; collision risk\n * across K=100 concurrent workers is roughly K² / 3.4M per ms.\n *\n * Names shorter than 4 chars are used as-is (no padding) so a state named\n * `Tx` produces `tx-...` rather than `tx00-...`.\n */\nexport const defaultCorrelator: Correlator = ({ state, action }) => {\n const s = state.slice(0, SEG_WIDTH).toLowerCase();\n const a = action.slice(0, SEG_WIDTH).toLowerCase();\n const ts = seg(Date.now() % SEG_SPACE);\n const rnd = seg(randomInt(SEG_SPACE));\n return `${s}-${a}-${ts}${rnd}`;\n};\n\n/**\n * Resolves the correlation id for the close-the-books transaction.\n * Close runs outside any user action, so we synthesize a context with\n * sentinel state/action names — visible in the id when overrides aren't\n * configured.\n *\n * @internal\n */\nexport function closeCorrelation(correlator: Correlator, actor: Actor): string {\n return correlator({\n state: \"$close\",\n action: \"close\",\n stream: \"$close\",\n actor,\n });\n}\n","/**\n * @module drain-cycle\n * @category Internal\n *\n * Two layers of the drain pipeline:\n *\n * - {@link runDrainCycle} — pure function for one round-trip of\n * claim → fetch → group → dispatch → ack/block. No orchestrator state.\n * Reusable for property tests and standalone benchmarks.\n *\n * - {@link DrainController} — stateful driver that owns the armed flag,\n * the concurrency lock, and the adaptive lag/lead ratio. Wraps\n * `runDrainCycle` with the lifecycle decisions Act used to make inline.\n *\n * @internal\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type {\n BatchHandler,\n BlockedLease,\n Drain,\n DrainOptions,\n Fetch,\n Lease,\n Logger,\n ReactionPayload,\n Registry,\n SchemaRegister,\n Schemas,\n} from \"../types/index.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport { computeLagLeadRatio } from \"./drain-ratio.js\";\nimport { traceCycle } from \"./tracing.js\";\n\n/**\n * Outcome of processing a single leased stream — produced by Act's `handle`\n * / `handleBatch` dispatchers, consumed by `runDrainCycle` to drive ack/block.\n *\n * @internal\n */\nexport type HandleResult = Readonly<{\n lease: Lease;\n handled: number;\n /**\n * Event id at which the ack would land — the last *successful* event\n * id, or `lease.at` when the batch had no work (empty payloads). Named\n * `acked_at` to pair symmetrically with {@link failed_at} and to keep\n * it visually distinct from `Lease.at` (the pre-cycle watermark — same\n * field name across types but a different semantic).\n */\n acked_at: number;\n error?: string;\n block?: boolean;\n /**\n * Wall-clock timestamp (ms since epoch) at which the next attempt on\n * this stream may run. Populated by `_finalize` only on retry paths\n * where the reaction defined `options.backoff`. Undefined means \"no\n * backoff configured\" — drain re-attempts as soon as the lease expires.\n */\n nextAttemptAt?: number;\n /**\n * Event id that threw, when a handler error occurred. Distinct from\n * {@link acked_at}: `failed_at = acked_at + 1` in dense streams, but\n * adapters with sparse ids give the trace the exact position. Always\n * set on the per-event error path; absent in batch mode (where no\n * single event id can be attributed to the failure).\n */\n failed_at?: number;\n}>;\n\n/**\n * Per-event reaction dispatcher signature (matches `Act.handle`).\n * @internal\n */\nexport type Handle<TEvents extends Schemas> = (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[]\n) => Promise<HandleResult>;\n\n/**\n * Bulk reaction dispatcher signature (matches `Act.handleBatch`).\n * @internal\n */\nexport type HandleBatch<TEvents extends Schemas> = (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[],\n batchHandler: BatchHandler<TEvents>\n) => Promise<HandleResult>;\n\n/**\n * One drain cycle's results. Returned by {@link runDrainCycle}; consumed by\n * `Act.drain()` to update lifecycle state, the lag/lead ratio, and emit the\n * `acked` / `blocked` lifecycle events.\n *\n * @internal\n */\nexport type DrainCycle<TEvents extends Schemas> = {\n readonly leased: Lease[];\n readonly fetched: Fetch<TEvents>;\n readonly handled: HandleResult[];\n readonly acked: Lease[];\n readonly blocked: BlockedLease[];\n};\n\n/**\n * Run one drain cycle: claim streams, fetch their events, dispatch\n * matching reactions, ack the successes, block the retries-exhausted.\n *\n * Returns `undefined` when nothing was claimed — caller can short-circuit\n * the rest of the drain pass.\n *\n * **Deferred streams.** When `isDeferred(stream)` returns `true`, the\n * cycle skips dispatch for that lease — no handle, no ack, no block. The\n * lease holds for `leaseMillis` via the existing claim mechanism, which\n * blocks competing workers from re-attempting during the backoff window\n * and serves as the per-worker pacing timer. Subsequent claims after\n * `leased_until` expires will re-acquire the lease and re-skip until the\n * controller clears the entry.\n *\n * @internal\n */\nexport async function runDrainCycle<\n TEvents extends Schemas,\n TActions extends Schemas,\n TSchemaReg extends SchemaRegister<TActions>,\n>(\n ops: DrainOps<TEvents>,\n registry: Registry<TSchemaReg, TEvents, TActions>,\n batchHandlers: Map<string, BatchHandler<TEvents>>,\n handle: Handle<TEvents>,\n handleBatch: HandleBatch<TEvents>,\n lagging: number,\n leading: number,\n eventLimit: number,\n leaseMillis: number,\n isDeferred?: (stream: string) => boolean,\n lane?: string\n): Promise<DrainCycle<TEvents> | undefined> {\n // Atomically discover and lease streams (competing consumer pattern)\n const leased = await ops.claim(\n lagging,\n leading,\n randomUUID(),\n leaseMillis,\n lane\n );\n if (!leased.length) return undefined;\n\n // Partition out streams whose handler is in a backoff window. We hold\n // their leases (no ack/block) so competing workers can't re-attempt\n // during the configured delay.\n const active = isDeferred\n ? leased.filter((l) => !isDeferred(l.stream))\n : leased;\n if (!active.length) {\n return {\n leased,\n fetched: [],\n handled: [],\n acked: [],\n blocked: [],\n };\n }\n\n // Fetch events for each active leased stream\n const fetched = await ops.fetch(active, eventLimit);\n\n // Build a single index keyed by stream — collapses two passes\n // (payloadsMap build + per-lease fetched.find) into one Map lookup.\n type FetchEntry = (typeof fetched)[number];\n const fetchMap = new Map<\n string,\n { fetch: FetchEntry; payloads: ReactionPayload<TEvents>[] }\n >();\n\n // compute fetch window max event id\n const fetch_window_at = fetched.reduce(\n (max, { at, events }) => Math.max(max, events.at(-1)?.id || at),\n 0\n );\n\n for (const f of fetched) {\n const { stream, events } = f;\n const payloads = events.flatMap((event) => {\n const register = registry.events[event.name];\n if (!register) return [];\n return [...register.reactions.values()]\n .filter((reaction) => {\n const resolved =\n typeof reaction.resolver === \"function\"\n ? reaction.resolver(event)\n : reaction.resolver;\n return resolved && resolved.target === stream;\n })\n .map((reaction) => ({ ...reaction, event }));\n });\n fetchMap.set(stream, { fetch: f, payloads });\n }\n\n const handled = await Promise.all(\n active.map((lease) => {\n // fetch() returns one entry per leased stream — fetchMap.get is\n // always defined here (asserted with `!`).\n const entry = fetchMap.get(lease.stream)!;\n // fast-forward watermark using fetched events or window max\n const at = entry.fetch.events.at(-1)?.id || fetch_window_at;\n const { payloads } = entry;\n const batchHandler = batchHandlers.get(lease.stream);\n if (batchHandler && payloads.length > 0) {\n return handleBatch({ ...lease, at }, payloads, batchHandler);\n }\n return handle({ ...lease, at }, payloads);\n })\n );\n\n // Ack any result that made progress — full success (no error), empty\n // payloads (no work to do, watermark fast-forwards), and partial\n // success (some events processed before the failure). The `error`\n // string is no longer the \"skip ack\" signal; `handled > 0 || !error`\n // is. Partial-success-then-block now lands in both `acked` and\n // `blocked` arrays for the same stream — by design.\n const acked = await ops.ack(\n handled\n .filter((h) => h.handled > 0 || !h.error)\n .map((h) => ({ ...h.lease, at: h.acked_at }))\n );\n\n const blocked = await ops.block(\n handled\n .filter(({ block }) => block)\n .map(({ lease, error }) => ({ ...lease, error: error! }))\n );\n\n return { leased, fetched, handled, acked, blocked };\n}\n\n/**\n * Empty drain result returned when the controller short-circuits (not\n * armed, locked out by a concurrent caller, claim returned nothing,\n * cycle threw).\n *\n * @internal\n */\nconst EMPTY_DRAIN: Drain<Schemas> = {\n fetched: [],\n leased: [],\n acked: [],\n blocked: [],\n};\n\n/**\n * Dependencies the {@link DrainController} needs from the orchestrator.\n * The lifecycle event sinks (`onAcked` / `onBlocked`) are callbacks so\n * this module doesn't reach back into Act's emitter.\n *\n * @internal\n */\nexport type DrainControllerDeps<\n TEvents extends Schemas,\n TActions extends Schemas,\n TSchemaReg extends SchemaRegister<TActions>,\n> = {\n readonly logger: Logger;\n readonly ops: DrainOps<TEvents>;\n readonly registry: Registry<TSchemaReg, TEvents, TActions>;\n readonly batchHandlers: Map<string, BatchHandler<TEvents>>;\n readonly handle: Handle<TEvents>;\n readonly handleBatch: HandleBatch<TEvents>;\n readonly onAcked: (acked: Lease[]) => void;\n readonly onBlocked: (blocked: BlockedLease[]) => void;\n /** Lane this controller drains. Undefined = spans all lanes (legacy single-controller). */\n readonly lane?: string;\n /** Per-lane defaults applied when caller doesn't override via DrainOptions. */\n readonly defaults?: {\n readonly streamLimit?: number;\n readonly eventLimit?: number;\n readonly leaseMillis?: number;\n };\n};\n\n/**\n * Stateful driver around {@link runDrainCycle}. Owns:\n *\n * - `_armed` — has any commit / reset / cold-start signaled work to do?\n * - `_locked` — concurrent-call guard (overlapping `drain()` calls return\n * an empty result instead of running twice)\n * - `_ratio` — adaptive lag-to-lead frontier split, updated per cycle\n *\n * The orchestrator owns commits, lifecycle emission, and `arm()` triggers\n * — the controller owns everything between those edges.\n *\n * @internal\n */\nexport class DrainController<\n TEvents extends Schemas,\n TActions extends Schemas,\n TSchemaReg extends SchemaRegister<TActions>,\n> {\n private _armed = false;\n private _locked = false;\n private _ratio = 0.5;\n /**\n * Per-stream backoff: `stream → nextAttemptAt` (ms since epoch). Set by\n * `_finalize` via `HandleResult.nextAttemptAt`; cleared on successful\n * ack or terminal block. Lives in process memory — per-worker pacing\n * by design (see {@link BackoffOptions} for the multi-worker trade-off).\n */\n private _backoff = new Map<string, number>();\n /** Timer re-arming drain at the earliest pending `nextAttemptAt`. */\n private _backoffTimer: ReturnType<typeof setTimeout> | undefined;\n /** Worker timer (ACT-1103). Set when `start()` is active, undefined otherwise. */\n private _worker: ReturnType<typeof setTimeout> | undefined;\n private _stopped = false;\n\n constructor(\n private readonly deps: DrainControllerDeps<TEvents, TActions, TSchemaReg>\n ) {}\n\n /**\n * Signal that a commit (or reset / cold-start) may have produced work.\n * Subsequent `drain()` calls will run the pipeline; once the pipeline\n * settles to no-progress, the controller disarms itself.\n */\n arm(): void {\n this._armed = true;\n }\n\n /** Read-only flag — true while a commit / reset is unprocessed. */\n get armed(): boolean {\n return this._armed;\n }\n\n /** Returns true when `stream` is currently within a backoff window. */\n private isDeferred = (stream: string): boolean => {\n const next = this._backoff.get(stream);\n return next !== undefined && next > Date.now();\n };\n\n /**\n * Schedule the next drain re-arm at the earliest pending backoff\n * expiry. Called only when the backoff map is non-empty (caller guard).\n * Idempotent — collapses many simultaneously deferred streams into a\n * single timer.\n */\n private scheduleBackoffWake(): void {\n if (this._backoffTimer) clearTimeout(this._backoffTimer);\n let earliest = Number.POSITIVE_INFINITY;\n for (const t of this._backoff.values()) if (t < earliest) earliest = t;\n const delay = Math.max(0, earliest - Date.now());\n this._backoffTimer = setTimeout(() => {\n this._backoffTimer = undefined;\n // Garbage-collect expired entries so the next cycle sees ready\n // streams as active. Drain will be re-triggered by whoever owns the\n // settle loop (or by the next commit). Re-arm here so a debounced\n // settle picks it up.\n const now = Date.now();\n for (const [stream, at] of this._backoff) {\n if (at <= now) this._backoff.delete(stream);\n }\n this._armed = true;\n }, delay);\n // Don't keep the event loop alive solely for backoff timers — letting\n // a process exit during retry pacing is the right default. Safe to call\n // unconditionally: Node's `setTimeout` always returns a Timeout with\n // `unref()`.\n this._backoffTimer.unref();\n }\n\n /** Lane this controller drains (undefined = legacy single-lane span). */\n get lane(): string | undefined {\n return this.deps.lane;\n }\n\n /**\n * Start a per-lane worker that drains at the lane's `cycleMs`\n * cadence (ACT-1103). When armed, the worker calls `drain()` on every\n * tick and re-schedules; when not armed, it still re-schedules at\n * `cycleMs` so a future `arm()` is picked up on the next tick.\n *\n * The setTimeout chain uses `unref()` so it doesn't keep the process\n * alive on its own.\n */\n start(cycleMs: number): void {\n if (this._worker || this._stopped) return;\n // `drain()` swallows its own errors and returns EMPTY_DRAIN, so the\n // tick is exception-free by contract. The post-drain `_stopped`\n // check prevents re-scheduling after `stop()` was called mid-tick;\n // an already-queued timer that fires before `clearTimeout()` lands\n // will run at most one extra drain (drain is idempotent against\n // a non-armed controller and self-disarms when settled).\n const tick = async () => {\n if (this._armed) await this.drain();\n if (this._stopped) return;\n this._worker = setTimeout(tick, cycleMs);\n this._worker.unref();\n };\n this._worker = setTimeout(tick, cycleMs);\n this._worker.unref();\n }\n\n /** Stop the per-lane worker. Idempotent. */\n stop(): void {\n this._stopped = true;\n if (this._worker) {\n clearTimeout(this._worker);\n this._worker = undefined;\n }\n }\n\n /** Run one drain pass. Short-circuits when not armed or already running. */\n async drain(options: DrainOptions = {}): Promise<Drain<TEvents>> {\n if (!this._armed) return EMPTY_DRAIN as Drain<TEvents>;\n if (this._locked) return EMPTY_DRAIN as Drain<TEvents>;\n\n const d = this.deps.defaults ?? {};\n // Per-lane config wins over caller options (ACT-1103). The whole\n // point of `withLane({leaseMillis: 30_000})` is to give the slow\n // lane its own budget — a caller-level drain({leaseMillis}) would\n // erase it. Caller options apply only when the lane didn't pin a\n // value.\n const streamLimit = d.streamLimit ?? options.streamLimit ?? 10;\n const eventLimit = d.eventLimit ?? options.eventLimit ?? 10;\n const leaseMillis = d.leaseMillis ?? options.leaseMillis ?? 10_000;\n\n try {\n this._locked = true;\n const lagging = Math.ceil(streamLimit * this._ratio);\n const leading = streamLimit - lagging;\n\n const cycle = await runDrainCycle(\n this.deps.ops,\n this.deps.registry,\n this.deps.batchHandlers,\n this.deps.handle,\n this.deps.handleBatch,\n lagging,\n leading,\n eventLimit,\n leaseMillis,\n this._backoff.size > 0 ? this.isDeferred : undefined,\n this.deps.lane\n );\n\n if (!cycle) {\n // claim() returned no leases — fully caught up\n this._armed = false;\n return EMPTY_DRAIN as Drain<TEvents>;\n }\n\n const { leased, fetched, handled, acked, blocked } = cycle;\n\n // Cycle-level trace (ACT-1103) — one log line per drain pass:\n // claim + fetch + outcomes folded together so the operator sees\n // a single atomic narrative for each cycle. No-op when the\n // logger isn't at trace level.\n traceCycle(this.deps.logger, leased, fetched, handled, acked, blocked);\n\n // Adapt next cycle's frontier split to where the pressure is.\n this._ratio = computeLagLeadRatio(handled, lagging, leading);\n\n // Refresh per-stream backoff state from this cycle's outcomes.\n // Successful acks and terminal blocks both clear the window;\n // retry-not-block results carry a `nextAttemptAt` set by `_finalize`.\n for (const lease of acked) this._backoff.delete(lease.stream);\n for (const lease of blocked) this._backoff.delete(lease.stream);\n for (const h of handled) {\n if (h.nextAttemptAt !== undefined && !h.block) {\n this._backoff.set(h.lease.stream, h.nextAttemptAt);\n }\n }\n if (this._backoff.size > 0) this.scheduleBackoffWake();\n\n if (acked.length) this.deps.onAcked(acked);\n if (blocked.length) this.deps.onBlocked(blocked);\n\n // Disarm only when fully caught up. Errors keep the flag set so\n // retries flow through the next drain.\n const hasErrors = handled.some(({ error }) => error);\n if (!acked.length && !blocked.length && !hasErrors) this._armed = false;\n\n return { fetched, leased, acked, blocked };\n } catch (error) {\n this.deps.logger.error(error);\n return EMPTY_DRAIN as Drain<TEvents>;\n } finally {\n this._locked = false;\n }\n }\n}\n","/**\n * @module drain-ratio\n * @category Internal\n *\n * Adaptive lag-to-lead ratio for the dual-frontier drain strategy.\n *\n * The orchestrator splits its per-cycle stream budget between two frontiers:\n *\n * - **lagging** — newly subscribed or behind streams catching up.\n * - **leading** — actively-processing streams at the head of the log.\n *\n * After each cycle, this helper looks at how many events were actually\n * handled in each frontier and shifts the next cycle's split toward\n * whichever frontier had the higher per-stream throughput. The result is\n * clamped to `[0.2, 0.8]` so neither frontier can be starved.\n *\n * @internal\n */\n\nimport type { HandleResult } from \"./drain-cycle.js\";\n\n/** Floor / ceiling for the lag-to-lead ratio so neither frontier starves. */\nconst RATIO_MIN = 0.2;\nconst RATIO_MAX = 0.8;\n/** Default ratio when no events were handled in either frontier. */\nconst RATIO_DEFAULT = 0.5;\n\n/**\n * Compute the next lag-to-lead ratio from the cycle's handled events and\n * the frontier sizes used to claim them. Returns `RATIO_DEFAULT` when no\n * progress was made (nothing to base a decision on).\n */\nexport function computeLagLeadRatio(\n handled: ReadonlyArray<HandleResult>,\n lagging: number,\n leading: number\n): number {\n let lagging_handled = 0;\n let leading_handled = 0;\n for (const { lease, handled: count } of handled) {\n if (lease.lagging) lagging_handled += count;\n else leading_handled += count;\n }\n const lagging_avg = lagging > 0 ? lagging_handled / lagging : 0;\n const leading_avg = leading > 0 ? leading_handled / leading : 0;\n const total = lagging_avg + leading_avg;\n if (total === 0) return RATIO_DEFAULT;\n return Math.max(RATIO_MIN, Math.min(RATIO_MAX, lagging_avg / total));\n}\n","/**\n * @module drain\n * @category Internal\n *\n * Pipeline operations consumed by the drain/correlate loop. Each op is a\n * single async step the orchestrator invokes per drain cycle:\n *\n * - `claim` — atomically discover and lock streams for processing\n * - `fetch` — read events for each leased stream\n * - `ack` — release leases for successfully handled streams\n * - `block` — flag leases that exceeded the retry budget\n * - `subscribe` — register newly correlated streams with the store\n *\n * This module exposes only the bare implementations as plain async functions,\n * mirroring the shape of {@link \"event-sourcing\"}. Trace decoration is\n * layered on top in {@link \"tracing\"} and selected by the orchestrator at\n * construction time. No tracing imports here.\n *\n * @internal\n */\n\nimport { store } from \"../ports.js\";\nimport type {\n BlockedLease,\n Committed,\n Fetch,\n Lease,\n Schemas,\n} from \"../types/index.js\";\n\n/** @internal */\nexport interface DrainOps<TEvents extends Schemas> {\n claim: typeof claim;\n fetch: typeof fetch<TEvents>;\n ack: typeof ack;\n block: typeof block;\n subscribe: typeof subscribe;\n}\n\nexport const claim = (\n lagging: number,\n leading: number,\n by: string,\n millis: number,\n lane?: string\n): Promise<Lease[]> => store().claim(lagging, leading, by, millis, lane);\n\nexport async function fetch<TEvents extends Schemas>(\n leased: Lease[],\n eventLimit: number\n): Promise<Fetch<TEvents>> {\n return Promise.all(\n leased.map(async ({ stream, source, at, lagging }) => {\n const events: Committed<TEvents, keyof TEvents>[] = [];\n await store().query<TEvents>((e) => events.push(e), {\n stream: source,\n after: at,\n limit: eventLimit,\n });\n return { stream, source, at, lagging, events } as const;\n })\n );\n}\n\nexport const ack = (leases: Lease[]): Promise<Lease[]> => store().ack(leases);\n\nexport const block = (leases: BlockedLease[]): Promise<BlockedLease[]> =>\n store().block(leases);\n\nexport const subscribe = (\n streams: Array<{\n stream: string;\n source?: string;\n priority?: number;\n lane?: string;\n }>\n): Promise<{ subscribed: number; watermark: number }> =>\n store().subscribe(streams);\n","/**\n * @module event-sourcing\n * @category Internal\n *\n * Pure event-sourcing primitives: `snap` persists state checkpoints, `load`\n * reconstructs state by replaying events through reducers, and `action`\n * validates an action, runs invariants, emits events, and commits them\n * atomically. `tombstone` commits the close-the-books guard with optimistic\n * concurrency.\n *\n * These are the bare implementations — observability is layered on top in\n * {@link \"tracing\"} and wired by the orchestrator at construction time.\n * No tracing imports here, no module-level mutable state.\n *\n * @internal\n */\n\nimport { patch } from \"@rotorsoft/act-patch\";\nimport { cache, log, SNAP_EVENT, store, TOMBSTONE_EVENT } from \"../ports.js\";\nimport {\n ConcurrencyError,\n InvariantError,\n StreamClosedError,\n} from \"../types/errors.js\";\nimport type {\n AsOf,\n Committed,\n Correlator,\n Emitted,\n EventMeta,\n EventSource,\n ScanOptions,\n ScanResult,\n Schema,\n Schemas,\n Snapshot,\n State,\n Target,\n} from \"../types/index.js\";\nimport { validate } from \"../utils.js\";\nimport { defaultCorrelator } from \"./correlator.js\";\n\n/**\n * Default per-batch row count for the {@link scan} pagination loop\n * (ACT-1133). Callers override via {@link ScanOptions.batch_size}.\n *\n * @internal\n */\nconst DEFAULT_BATCH = 500;\n\n/**\n * Internal action signature seen by the orchestrator — the {@link Correlator}\n * is bound at `buildEs` time, so callers don't pass it through.\n *\n * @internal\n */\nexport type BoundAction = <\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n>(\n me: State<TState, TEvents, TActions>,\n action: TKey,\n target: Target,\n payload: Readonly<TActions[TKey]>,\n reactingTo?: Committed<Schemas, keyof Schemas>,\n skipValidation?: boolean\n) => Promise<Snapshot<TState, TEvents>[]>;\n\n/** @internal */\nexport interface EsOps {\n snap: typeof snap;\n load: typeof load;\n action: BoundAction;\n tombstone: typeof tombstone;\n}\n\n/**\n * Event sourcing utilities for snapshotting, loading, and committing actions/events.\n * Used internally by Act and state machines.\n */\n\n/**\n * Saves a snapshot of the state to the store.\n *\n * Snapshots are used to optimize state reconstruction for aggregates with long event streams.\n *\n * @template TState The type of state\n * @template TEvents The type of events\n * @param snapshot The snapshot to save\n * @returns Promise that resolves when the snapshot is saved\n *\n * @example\n * await snap(snapshot);\n */\nexport async function snap<TState extends Schema, TEvents extends Schemas>(\n snapshot: Snapshot<TState, TEvents>\n): Promise<void> {\n try {\n const { id, stream, name, meta, version } = snapshot.event!;\n await store().commit(\n stream,\n [{ name: SNAP_EVENT, data: snapshot.state }],\n {\n correlation: meta.correlation,\n causation: { event: { id, name: name as string, stream } },\n },\n version // IMPORTANT! - state events are committed right after the snapshot event\n );\n } catch (error) {\n log().error(error);\n }\n}\n\n/**\n * Commits a tombstone event with optimistic concurrency, returning the\n * committed record on success or `undefined` if the stream moved past\n * `expectedVersion` (concurrent write detected). Other store errors\n * propagate.\n *\n * Used by `close()` to guard a stream while archive/truncate runs:\n * subsequent `action()` calls see the tombstone at head and reject with\n * {@link StreamClosedError} until the close completes.\n *\n * @internal\n */\nexport async function tombstone(\n stream: string,\n expectedVersion: number,\n correlation: string\n): Promise<Committed<Schemas, keyof Schemas> | undefined> {\n try {\n const [committed] = await store().commit(\n stream,\n [{ name: TOMBSTONE_EVENT, data: {} }],\n { correlation, causation: {} },\n expectedVersion\n );\n return committed;\n } catch (error) {\n if (error instanceof ConcurrencyError) return undefined;\n throw error;\n }\n}\n\n/**\n * Per-event blocker check. Categories:\n *\n * - **Negative `version`** — versions are unsigned in the framework\n * contract.\n * - **Malformed `created`** — `event.created` must be a valid Date\n * instance. Restore sources stream parsed events; the orchestrator\n * trusts the caller's iterator did the parsing.\n *\n * Cross-event invariants (duplicate ids, per-stream version gaps) are\n * not the validator's job — DB `UNIQUE(stream, version)` catches\n * duplicates at commit time, and gap detection is a caller-specific\n * policy (partial backups intentionally have gaps).\n *\n * Extension point: per-event Zod schema validation against the active\n * registry will land here — the source-side check is the right layer\n * for it (catches malformed payloads before the sink transaction\n * opens), and adding it keeps the per-event blocker contract in one\n * place.\n *\n * @internal\n */\nfunction is_valid(event: Committed<Schemas, keyof Schemas>): boolean {\n if (event.version < 0) return false;\n if (!(event.created instanceof Date) || Number.isNaN(event.created.getTime()))\n return false;\n return true;\n}\n\n/**\n * Scan a restore source event by event. Owns pagination, validation,\n * the `drop_snapshots` filter, the `on_progress` callback, and the\n * causation remap; adapters supply only the per-event insert\n * `callback` via the driver pattern (see {@link Store.restore}).\n *\n * Walks the source in chunks of {@link BATCH} via the existing\n * `EventSource.query` interface — `limit: BATCH` and `after: <last\n * id seen>` per batch (ACT-1133). Stores that respect `limit`\n * (`PostgresStore`) return at most `BATCH` rows per call; sources\n * that ignore the filter (`CsvFile`) stream everything in one call\n * and the loop exits after the first batch when `got > BATCH`. The\n * source's own per-event `await Promise.resolve(callback(event))`\n * provides backpressure — no separate mailbox needed.\n *\n * Throws on the first invalid event (negative version, malformed\n * `created`) with the running index in the message.\n *\n * Returns the partial {@link ScanResult} (without `duration_ms`)\n * — {@link Act.restore} wraps the call with its own timing so the\n * duration covers transaction setup and commit, not just iteration.\n *\n * @internal\n */\nexport async function scan(\n source: EventSource,\n opts: ScanOptions = {},\n callback?: (event: Committed<Schemas, keyof Schemas>) => Promise<number>\n): Promise<Omit<ScanResult, \"duration_ms\">> {\n const { drop_snapshots = false, on_progress } = opts;\n const limit = opts.batch_size ?? DEFAULT_BATCH;\n const id_map = new Map<number, number>();\n let kept = 0;\n let dropped_snaps = 0;\n let processed = 0;\n let at: number | undefined;\n\n // Probe the source for the highest id once up front. On indexed\n // stores (PostgresStore, SqliteStore) `{ backward: true, limit: 1 }`\n // is an index-only seek — O(1) on the (id) index. Sources that\n // ignore the filter (CsvFile) stream every event from this one\n // call; we detect that via the returned count and leave max_id\n // undefined rather than reporting an unreliable value.\n let max_id: number | undefined;\n const probed = await source.query<Schemas>(\n (e) => {\n max_id = e.id;\n },\n { backward: true, limit: 1 }\n );\n if (probed !== 1) max_id = undefined;\n\n while (true) {\n let got = 0;\n let id: number | undefined;\n\n await source.query<Schemas>(\n async (event) => {\n got++;\n id = event.id;\n processed++;\n if (!is_valid(event))\n throw new Error(`Invalid event at index ${processed}`);\n if (on_progress) on_progress({ processed, id: event.id, max_id });\n if (drop_snapshots && event.name === SNAP_EVENT) {\n dropped_snaps++;\n return;\n }\n if (!callback) {\n kept++;\n return;\n }\n // Causation remap — rewrite `meta.causation.event.id` to the\n // new id space if the source pointed at an earlier event's\n // old id.\n let remapped = event;\n const caused_by = event.meta.causation.event?.id;\n if (caused_by !== undefined) {\n const new_caused_by = id_map.get(caused_by);\n if (new_caused_by !== undefined && new_caused_by !== caused_by) {\n remapped = {\n ...event,\n meta: {\n ...event.meta,\n causation: {\n ...event.meta.causation,\n event: { ...event.meta.causation.event!, id: new_caused_by },\n },\n },\n };\n }\n }\n const new_id = await callback(remapped);\n id_map.set(event.id, new_id);\n kept++;\n },\n { after: at, limit }\n );\n\n // Termination:\n // - got < batch: source honored limit but ran out (also covers\n // got === 0 — past-the-end on a paginating source).\n // - got > batch: source ignored the filter (CsvFile-style). It\n // streamed everything in one call; nothing left to ask for.\n // Otherwise (got === batch): more events may exist; bump and continue.\n if (got !== limit) break;\n at = id;\n }\n\n return {\n kept,\n dropped: {\n closed_streams: 0,\n snapshots: dropped_snaps,\n empty_streams: 0,\n },\n };\n}\n\n/**\n * Loads a snapshot of the state from the store by replaying events and applying patches.\n *\n * First checks the cache for a checkpoint, then queries the store for events\n * committed after the cached position. On cache miss, replays from the store\n * (using snapshots if available to avoid full replay).\n *\n * @template TState The type of state\n * @template TEvents The type of events\n * @template TActions The type of actions\n * @param me The state machine definition\n * @param stream The stream (instance) to load\n * @param callback (Optional) Callback to receive the loaded snapshot as it is built\n * @returns The snapshot of the loaded state\n *\n * @example\n * const snapshot = await load(Counter, \"counter1\");\n */\nexport async function load<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(\n me: State<TState, TEvents, TActions>,\n stream: string,\n callback?: (snapshot: Snapshot<TState, TEvents>) => void,\n asOf?: AsOf\n): Promise<Snapshot<TState, TEvents>> {\n const timeTravel = !!asOf && Object.values(asOf).some((v) => v !== undefined);\n const cached = timeTravel ? undefined : await cache().get<TState>(stream);\n const cache_hit = !!cached;\n let state = cached?.state ?? (me.init ? me.init() : ({} as TState));\n let patches = cached?.patches ?? 0;\n let snaps = cached?.snaps ?? 0;\n // version always reflects stream head: starts from the cached version\n // (or -1 for a fresh stream / cache miss), advances per event seen.\n let version = cached?.version ?? -1;\n // replayed counts events processed by THIS load only (snap or patch);\n // distinct from `patches` (the snap-distance accumulator carried over\n // from the cache).\n let replayed = 0;\n let event: Committed<TEvents, string> | undefined;\n\n await store().query(\n (e) => {\n event = e as Committed<TEvents, string>;\n version = e.version;\n if (e.name === SNAP_EVENT) {\n state = e.data as TState;\n snaps++;\n patches = 0;\n replayed++;\n } else if (me.patch[e.name]) {\n state = patch(state, me.patch[e.name](event, state));\n patches++;\n replayed++;\n } else if (e.name !== TOMBSTONE_EVENT) {\n // Unknown event — not in this state's reducer map. Causes:\n // deleted/renamed event in a versioned schema, load() called with\n // the wrong state, or stream contamination. Skipping silently\n // would corrupt replay; warn so the operator can investigate.\n log().warn(\n `Skipping unknown event \"${String(e.name)}\" on stream \"${stream}\" (id=${e.id}) — no reducer in state \"${me.name}\"`\n );\n }\n callback?.({\n event,\n state,\n version,\n patches,\n snaps,\n cache_hit,\n replayed,\n });\n },\n {\n stream,\n stream_exact: true,\n ...(cached ? { after: cached.event_id } : { with_snaps: true, ...asOf }),\n }\n );\n\n // Populate the cache when this load actually processed events. Without\n // this, read-heavy paths (UI loops calling load() many times between\n // commits) miss the cache forever — only action() would ever warm it.\n // No race-protection re-check needed: the cache is a state checkpoint\n // at (version, event_id), and any subsequent load queries past\n // event_id, picks up missed events, and replays — so an \"older\" cache\n // write from a concurrent slower load is self-correcting on next access.\n // Time-travel loads bypass cache entirely and skip this too.\n if (replayed > 0 && !timeTravel && event) {\n await cache().set(stream, {\n state,\n version,\n event_id: event.id,\n patches,\n snaps,\n });\n }\n\n return { event, state, version, patches, snaps, cache_hit, replayed };\n}\n\n/**\n * Executes an action and emits an event to be committed by the store.\n *\n * This function validates the action, applies business invariants, emits events, and commits them to the event store.\n *\n * @template TState The type of state\n * @template TEvents The type of events\n * @template TActions The type of actionSchemas\n * @template TKey The type of action to execute\n * @param me The state machine definition\n * @param action The action to execute\n * @param target The target (stream, actor, etc.)\n * @param payload The payload of the action\n * @param reactingTo (Optional) The event that the action is reacting to\n * @param skipValidation (Optional) Whether to skip validation (not recommended)\n * @returns The snapshot of the committed event\n *\n * @example\n * const snapshot = await action(Counter, \"increment\", { stream: \"counter1\", actor }, { by: 1 });\n */\nexport async function action<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n>(\n me: State<TState, TEvents, TActions>,\n action: TKey,\n target: Target,\n payload: Readonly<TActions[TKey]>,\n reactingTo?: Committed<Schemas, keyof Schemas>,\n skipValidation = false,\n correlator: Correlator = defaultCorrelator\n): Promise<Snapshot<TState, TEvents>[]> {\n const { stream, expectedVersion, actor } = target;\n if (!stream) throw new Error(\"Missing target stream\");\n\n const validated = skipValidation\n ? payload\n : validate(action as string, payload, me.actions[action]);\n\n const snapshot = await load(me, stream);\n if (snapshot.event?.name === TOMBSTONE_EVENT)\n throw new StreamClosedError(stream);\n const expected = expectedVersion ?? snapshot.event?.version;\n\n if (me.given) {\n const invariants = me.given[action] || [];\n invariants.forEach(({ valid, description }) => {\n if (!valid(snapshot.state, actor))\n throw new InvariantError(\n action,\n validated,\n target,\n snapshot,\n description\n );\n });\n }\n\n const result = me.on[action](validated, snapshot, target);\n if (!result) return [snapshot];\n\n // An empty array means no events were emitted\n if (Array.isArray(result) && result.length === 0) {\n return [snapshot];\n }\n\n const tuples = Array.isArray(result[0])\n ? (result as Emitted<TEvents>[]) // array of tuples\n : ([result] as Emitted<TEvents>[]); // single tuple\n\n // ACT-403: warn once per process per event name when a dynamic\n // `.emit((a) => [\"X\", ...])` produces a deprecated event. Static\n // `.emit(\"X\")` is already caught at build time by act-builder; this\n // is the runtime safety net for the dynamic form, which the static\n // checker can't inspect. The `_warned` set lives on the state so\n // multiple Act instances over the same merged state share idempotency.\n const deprecated = (me as { _deprecated?: Set<string> })._deprecated;\n if (deprecated && deprecated.size > 0) {\n const me_ = me as { _warned?: Set<string> };\n const warned = me_._warned ?? (me_._warned = new Set<string>());\n for (const [name] of tuples) {\n const evt = name as string;\n if (deprecated.has(evt) && !warned.has(evt)) {\n warned.add(evt);\n log().warn(\n `Action \"${String(action)}\" emitted deprecated event \"${evt}\". ` +\n `A newer version exists in the registry — update the action's ` +\n `.emit() to target the current version. (warned once per process)`\n );\n }\n }\n }\n\n const emitted = tuples.map(([name, data]) => ({\n name,\n data: skipValidation\n ? data\n : validate(name as string, data, me.events[name]),\n }));\n\n const meta: EventMeta = {\n correlation:\n reactingTo?.meta.correlation ||\n correlator({\n action: action as string,\n state: me.name,\n stream,\n actor: target.actor,\n }),\n causation: {\n action: {\n name: action as string,\n ...target,\n // payload intentionally omitted: it can be large or contain PII,\n // and callers correlate via the correlation id when they need it.\n },\n event: reactingTo\n ? {\n id: reactingTo.id,\n name: reactingTo.name,\n stream: reactingTo.stream,\n }\n : undefined,\n },\n };\n\n let committed: Committed<TEvents, keyof TEvents>[];\n try {\n committed = await store().commit(\n stream,\n emitted,\n meta,\n // Reactions skip optimistic concurrency: they always append against the\n // current head. Stream leasing already serializes concurrent reactions,\n // and forcing version checks here would turn ordinary catch-up into\n // spurious retries.\n reactingTo ? undefined : expected\n );\n } catch (error) {\n // Invalidate cache on concurrency errors — cached state is stale\n if (error instanceof ConcurrencyError) {\n await cache().invalidate(stream);\n }\n throw error;\n }\n\n let { state, patches } = snapshot;\n const snapshots = committed.map((event) => {\n const p = me.patch[event.name](event, state);\n state = patch(state, p);\n patches++;\n // cache_hit / replayed propagate from the initial load — these\n // post-commit snapshots all derive from the same loaded state.\n // version advances per committed event (each is a new stream head).\n return {\n event,\n state,\n version: event.version,\n patches,\n snaps: snapshot.snaps,\n patch: p,\n cache_hit: snapshot.cache_hit,\n replayed: snapshot.replayed,\n };\n });\n\n // fire and forget snaps\n const last = snapshots.at(-1)!;\n const snapped = me.snap?.(last);\n\n // Update cache with post-commit state (reset patches if snapped).\n // Fire-and-forget — log but don't fail the action on cache write errors\n // (e.g., transient network failures in a custom Cache adapter).\n cache()\n .set<TState>(stream, {\n state: last.state,\n version: last.event.version,\n event_id: last.event.id,\n patches: snapped ? 0 : last.patches,\n snaps: snapped ? last.snaps + 1 : last.snaps,\n })\n .catch((err) => log().error(err));\n\n // Persist snap to store for cold-start durability. Fire-and-forget:\n // snap() has its own try/catch that logs failures, so the rejection\n // can never escape — `void` is just to silence the floating-promise\n // lint (action() doesn't await store durability for the snapshot).\n if (snapped) void snap(last);\n\n return snapshots;\n}\n","/**\n * @module tracing\n * @category Internal\n *\n * Centralized observability for the framework's internal pipelines.\n *\n * Trace decorators wrap a bare implementation with `logger.trace(...)` calls\n * at well-defined moments — entry points for {@link \"event-sourcing\"} (`load`,\n * `snap`, `action`) and exit points for the {@link \"drain\"} pipeline (`claim`,\n * `fetch`, `ack`, `block`, `subscribe`). `action` carries both an entry log\n * and a post-commit log to preserve the diagnostic value of the historical\n * mid-function trace points.\n *\n * Output styles:\n * - **Pretty mode** (`config().env !== \"production\"`) — event-sourcing logs\n * show only the colored target body (color carries the operation/phase),\n * drain logs keep a colored caption.\n * - **Plain mode** (production / log aggregators) — every log gets a textual\n * prefix; event-sourcing uses `caption: body`, drain uses `caption body`.\n *\n * The two factories — {@link buildEs} and {@link buildDrain} — let the\n * orchestrator choose bare or traced variants once at `.build()` time based\n * on the configured log level. Outside this module, no other source file\n * imports tracing primitives.\n *\n * @internal\n */\n\nimport { config } from \"../config.js\";\nimport type { AsOf, Correlator, Logger, Schemas } from \"../types/index.js\";\nimport { defaultCorrelator } from \"./correlator.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport * as drain from \"./drain.js\";\nimport type { EsOps } from \"./event-sourcing.js\";\nimport * as es from \"./event-sourcing.js\";\n\ntype AsyncFn = (...args: any[]) => Promise<any>;\n\nconst PRETTY = config().env !== \"production\";\n\n// 256-color codes for distinctive, theme-friendly hues\nconst C_BLUE = \"\\x1b[38;5;39m\"; // vivid sky blue (action)\nconst C_ORANGE = \"\\x1b[38;5;208m\"; // true orange (committed)\nconst C_GREEN = \"\\x1b[38;5;42m\"; // emerald (load)\nconst C_MAGENTA = \"\\x1b[38;5;165m\"; // bright magenta (snap)\nconst C_DRAIN = \"\\x1b[38;5;244m\"; // muted gray for all drain ops\n// load-trace cache marker shades — distinguishable from C_GREEN body color\nconst C_HIT = \"\\x1b[38;5;82m\"; // lime — fast path, blends visually\nconst C_MISS = \"\\x1b[38;5;220m\"; // amber — non-trivial work happened\nconst C_RESET = \"\\x1b[0m\";\n\n/**\n * Format an event-sourcing trace line. Pretty mode renders just the colored\n * body (the color is the cue for which op/phase fired); plain mode prepends\n * `caption: ` so log aggregators stay readable without ANSI.\n */\nconst es_caption = (caption: string, color: string, body: string): string =>\n PRETTY ? `${color}${body}${C_RESET}` : `${caption}: ${body}`;\n\n/**\n * Format a drain-pipeline caption. Drain logs keep a `>>` marker for easy\n * spotting in mixed log streams, plus a `caption` (past tense — every drain\n * trace fires on exit). All drain ops share one color (gray) so the pipeline\n * reads as a single channel; the caption disambiguates the phase. Lane\n * (ACT-1103) is appended in lilac, unwrapped, when set and non-default,\n * so the operator's eye lands on the lane name without parsing per-stream\n * detail. Per-stream `@at/retry` and fetched event lists are muted via\n * {@link dim} so the stream name itself reads loudest.\n */\nconst C_LANE = \"\\x1b[38;5;183m\"; // lilac — distinct from gray drain + drain ops\nconst C_DIM = \"\\x1b[38;5;240m\"; // dim gray — dimmer than C_DRAIN\nconst C_ERR = \"\\x1b[38;5;196m\"; // bright red — block marker\nconst C_STREAM = \"\\x1b[38;5;226m\"; // bright yellow — target stream names in drain/correlate traces\n\n/** Wrap with the muted color when pretty mode is on. Plain in production. */\nconst dim = (text: string): string =>\n PRETTY ? `${C_DIM}${text}${C_RESET}` : text;\n\n/** Wrap with a foreground color when pretty mode is on; bare in production. */\nconst hue = (color: string, text: string): string =>\n PRETTY ? `${color}${text}${C_RESET}` : text;\n\nconst drain_caption = (caption: string, lane?: string): string => {\n const showLane = lane && lane !== \"default\";\n if (PRETTY) {\n const tag = `${C_DRAIN}>> ${caption}${C_RESET}`;\n return showLane ? `${tag} ${C_LANE}${lane}${C_RESET}` : tag;\n }\n return showLane ? `>> ${caption} ${lane}` : `>> ${caption}`;\n};\n\n/**\n * Format the cache hit/miss marker for the load trace. In pretty mode the\n * word is colored (lime for hit, amber for miss) and the surrounding\n * `C_GREEN` body color is restored after — embedded ANSI inside `es_caption`'s\n * outer wrap. Plain mode returns the bare word.\n */\nconst cache_marker = (hit: boolean): string => {\n const word = hit ? \"hit\" : \"miss\";\n if (!PRETTY) return word;\n return `${hit ? C_HIT : C_MISS}${word}${C_RESET}${C_GREEN}`;\n};\n\n/**\n * Format the load stats (`v=N replayed=N snaps=N patches=N`) for the load\n * trace. Muted gray in pretty mode so the cache marker reads as the most\n * important cue; plain mode returns the bare text.\n *\n * - `v` — stream head version (the version of the last event applied)\n * - `replayed` — events processed by THIS load past the cache point\n * - `snaps` — cumulative snapshots taken on this stream\n * - `patches` — events since the last snap (snap-policy accumulator)\n */\nconst stats_marker = (\n version: number,\n replayed: number,\n snaps: number,\n patches: number\n): string => {\n const text = `v=${version} replayed=${replayed} snaps=${snaps} patches=${patches}`;\n if (!PRETTY) return text;\n return `${C_DRAIN}${text}${C_RESET}${C_GREEN}`;\n};\n\n/**\n * Format the as-of marker for time-travel loads. Surfaces the active filter\n * fields (before id, created_before/after timestamps, limit) so an operator\n * can tell at a glance which slice was loaded. Empty `asOf` returns \"\" —\n * non-time-travel loads skip the marker entirely.\n */\nconst as_of_marker = (asOf: AsOf | undefined): string => {\n if (!asOf) return \"\";\n const parts: string[] = [];\n if (asOf.before !== undefined) parts.push(`before=${asOf.before}`);\n if (asOf.created_before !== undefined)\n parts.push(`created_before=${asOf.created_before.toISOString()}`);\n if (asOf.created_after !== undefined)\n parts.push(`created_after=${asOf.created_after.toISOString()}`);\n if (asOf.limit !== undefined) parts.push(`limit=${asOf.limit}`);\n return parts.length ? ` (as-of ${parts.join(\" \")})` : \" (as-of)\";\n};\n\n/**\n * Wraps an async function with optional `exit` and `entry` callbacks. Each\n * callback fires at the corresponding phase; both receive the call args, and\n * `exit` additionally receives the resolved result. Used to layer\n * `logger.trace` calls onto bare ops without changing their signatures.\n *\n * @internal\n */\nconst traced = <F extends AsyncFn>(\n inner: F,\n exit?: (result: Awaited<ReturnType<F>>, ...args: Parameters<F>) => void,\n entry?: (...args: Parameters<F>) => void\n): F =>\n (async (...args: Parameters<F>) => {\n entry?.(...args);\n const result = (await inner(...args)) as Awaited<ReturnType<F>>;\n exit?.(result, ...args);\n return result;\n }) as F;\n\n/**\n * Selects bare or traced event-sourcing handlers. Called once by the\n * orchestrator constructor.\n *\n * @internal\n */\nexport function buildEs(\n logger: Logger,\n correlator: Correlator = defaultCorrelator\n): EsOps {\n // `es.action` takes `correlator` as its last positional arg; the\n // orchestrator never wants to plumb it through every call site, so we\n // bind it once here and present an `EsOps.action` with the original\n // 6-arg signature.\n const boundAction: EsOps[\"action\"] = (\n me,\n actionName,\n target,\n payload,\n reactingTo,\n skipValidation = false\n ) =>\n es.action(\n me,\n actionName,\n target,\n payload,\n reactingTo,\n skipValidation,\n correlator\n );\n if (logger.level !== \"trace\") {\n return {\n snap: es.snap,\n load: es.load,\n action: boundAction,\n tombstone: es.tombstone,\n };\n }\n return {\n snap: traced(es.snap, undefined, (snapshot) => {\n logger.trace(\n es_caption(\n \"snap\",\n C_MAGENTA,\n `${snapshot.event!.stream}@${snapshot.event!.version}`\n )\n );\n }),\n load: traced(es.load, (result, _me, stream, _cb, asOf) => {\n const stats = stats_marker(\n result.version,\n result.replayed,\n result.snaps,\n result.patches\n );\n logger.trace(\n es_caption(\n \"load\",\n C_GREEN,\n `${stream}${as_of_marker(asOf)} ${cache_marker(result.cache_hit)} ${stats}`\n )\n );\n }),\n action: traced(\n boundAction,\n (snapshots, _me, _action, target) => {\n const committed = snapshots.filter((s) => s.event);\n if (committed.length) {\n logger.trace(\n committed.map((s) => s.event!.data),\n es_caption(\n \"committed\",\n C_ORANGE,\n `${target.stream}.${committed.map((s) => s.event!.name).join(\", \")}`\n )\n );\n }\n },\n (_me, action, target, payload) => {\n logger.trace(\n payload as object,\n es_caption(\"action\", C_BLUE, `${target.stream}.${action}`)\n );\n }\n ),\n tombstone: traced(es.tombstone, (committed, stream) => {\n if (committed)\n logger.trace(\n es_caption(\"tombstoned\", C_ORANGE, `${stream}@${committed.version}`)\n );\n }),\n };\n}\n\n/**\n * Selects bare or traced drain-pipeline ops. Called once by the orchestrator\n * constructor.\n *\n * @internal\n */\nexport function buildDrain<TEvents extends Schemas>(\n logger: Logger\n): DrainOps<TEvents> {\n // Cycle-level tracing happens in `DrainController.drain()` via\n // {@link traceCycle} — claim/fetch/ack/block all flow into one log\n // line per cycle to give the operator a single atomic narrative.\n // `subscribe` stays decorated because it's driven from correlate-\n // cycle (not from runDrainCycle) and doesn't fit the cycle shape.\n return {\n claim: drain.claim,\n fetch: drain.fetch,\n ack: drain.ack,\n block: drain.block,\n subscribe:\n logger.level !== \"trace\"\n ? drain.subscribe\n : traced(drain.subscribe, (result, streams) => {\n if (!result.subscribed) return;\n // Caption mirrors `drained`: lane in the caption when the\n // whole batch shares a single non-default lane. Mixed-lane\n // batches (rare — different correlated targets resolving\n // to different lanes in one scan) fall back to per-stream\n // `[lane]` tags, default-lane streams stay bare either way.\n const lanes = new Set(streams.map((s) => s.lane ?? \"default\"));\n const uniformLane = lanes.size === 1 ? streams[0]?.lane : undefined;\n const data = streams\n .map(({ stream, lane }) =>\n uniformLane || !lane || lane === \"default\"\n ? hue(C_STREAM, stream)\n : `${hue(C_STREAM, stream)}${dim(`[${lane}]`)}`\n )\n .join(\" \");\n logger.trace(`${drain_caption(\"correlated\", uniformLane)} ${data}`);\n }),\n };\n}\n\n/**\n * Emit one cycle-level drain trace summarizing what happened in a\n * single `runDrainCycle` pass. Per-stream rendering shape — outcome +\n * post-state anchored on the right:\n *\n * stream<-source [events] ✓ @<acked-at> — full success\n * stream<-source [events] ✗ @<failed-at>/<retry> (error) — total failure → blocked\n * stream<-source [events] ⚠ @<failed-at>/<retry> (error) — total failure → retrying\n * stream<-source [events] ✓ @<acked-at> ✗ @<failed-at>/<retry> (error) — partial then blocked\n * stream<-source [events] ✓ @<acked-at> ⚠ @<failed-at>/<retry> (error) — partial then retrying\n * stream<-source ⊘ @<at>/<retry> — deferred (backoff)\n *\n * Partial-success-then-failure is the dual-outcome case: events\n * 1..K succeeded (watermark advanced to K), event K+1 threw. The\n * trace renders both the lime `✓ @K` and the red/amber `✗`/`⚠ @K+1`\n * on the same line so an operator sees \"we made progress *and* then\n * something broke\" at a glance.\n *\n * Lane prefixes the caption in lilac when non-default. The outcome\n * marker and its adjacent post-state share the marker's color so the\n * eye reads \"outcome + where it landed\" as one unit. Per-stream\n * `[events]` and `(error)` stay dim — secondary context.\n *\n * @internal\n */\nexport function traceCycle<TEvents extends Schemas>(\n logger: Logger,\n leased: ReadonlyArray<{\n readonly stream: string;\n readonly at: number;\n readonly retry: number;\n readonly lane?: string;\n }>,\n fetched: ReadonlyArray<{\n readonly stream: string;\n readonly source?: string;\n readonly events: ReadonlyArray<{\n readonly id: number;\n readonly name: keyof TEvents;\n }>;\n }>,\n handled: ReadonlyArray<{\n readonly lease: { readonly stream: string };\n readonly error?: string;\n readonly block?: boolean;\n readonly failed_at?: number;\n }>,\n acked: ReadonlyArray<{ readonly stream: string; readonly at: number }>,\n blocked: ReadonlyArray<{ readonly stream: string; readonly error: string }>\n): void {\n if (logger.level !== \"trace\" || !leased.length) return;\n const lane = leased[0]?.lane;\n const fetchByStream = new Map(fetched.map((f) => [f.stream, f]));\n const ackedByStream = new Map(acked.map((a) => [a.stream, a.at]));\n const blockedByStream = new Map(blocked.map((b) => [b.stream, b.error]));\n // Handled-with-error stays a single index now: `block` discriminates\n // the marker (✗ vs ⚠); the failure exists independently of whether\n // ack happened.\n const failedByStream = new Map(\n handled.filter((h) => h.error).map((h) => [h.lease.stream, h] as const)\n );\n const detail = leased\n .map(({ stream, at, retry }) => {\n const f = fetchByStream.get(stream);\n // Target stream in yellow so the operator's eye lands on \"which\n // stream did this happen on?\" first; source (the events' origin)\n // stays dim — secondary info.\n const key = f?.source\n ? `${hue(C_STREAM, stream)}${dim(`<-${f.source}`)}`\n : hue(C_STREAM, stream);\n const events =\n f && f.events.length\n ? ` ${dim(\n `[${f.events.map(({ id, name }) => `#${id} ${String(name)}`).join(\", \")}]`\n )}`\n : \"\";\n // Build ack + fail segments independently — both can fire for\n // the same stream in the partial-success-then-failure case.\n const ackedAt = ackedByStream.get(stream);\n const ackPart =\n ackedAt !== undefined\n ? hue(C_HIT, `✓ @${ackedAt}`) // ✓ + new at in lime\n : \"\";\n const failure = failedByStream.get(stream);\n let failPart = \"\";\n if (failure) {\n // Failed event id when known (per-event path), else falls back\n // to lease.at — the post-fetch watermark — for batch-mode\n // total failures where no single event is \"the one.\"\n const failedAt = failure.failed_at ?? at;\n const blockedError = blockedByStream.get(stream);\n if (blockedError !== undefined) {\n failPart = `${hue(C_ERR, `✗ @${failedAt}/${retry}`)} ${dim(`(${blockedError})`)}`;\n } else {\n failPart = `${hue(C_MISS, `⚠ @${failedAt}/${retry}`)} ${dim(`(${failure.error})`)}`;\n }\n }\n let tail: string;\n if (ackPart && failPart) tail = ` ${ackPart} ${failPart}`;\n else if (ackPart) tail = ` ${ackPart}`;\n else if (failPart) tail = ` ${failPart}`;\n else tail = ` ${dim(`⊘ @${at}/${retry}`)}`; // nothing happened\n return `${key}${events}${tail}`;\n })\n .join(\", \");\n logger.trace(`${drain_caption(\"drained\", lane)} ${detail}`);\n}\n","/**\n * @module merge\n * @category Internal\n *\n * Shared utilities for merging partial states and projections across builders.\n * Lives in `internal/` because the symbols are consumed by the builder layer\n * (`act-builder`, `slice-builder`, `projection-builder`) but aren't part of\n * the public package surface.\n *\n * @internal\n */\nimport { ZodObject, type ZodType } from \"zod\";\nimport type { Projection } from \"../builders/projection-builder.js\";\nimport type { Schema, State } from \"../types/index.js\";\n\n/**\n * Unwraps wrapper types (ZodOptional, ZodNullable, ZodDefault, ZodReadonly)\n * to find the base type name, e.g. `z.string().optional()` -> `\"ZodString\"`.\n */\nfunction baseTypeName(zodType: ZodType): string {\n let t: any = zodType;\n while (typeof t.unwrap === \"function\") {\n t = t.unwrap();\n }\n return t.constructor.name;\n}\n\n/**\n * Merges two Zod schemas. If both are ZodObject instances, checks for\n * overlapping shape keys with incompatible base types (throws descriptive\n * error), then merges via `.extend()`. Falls back to keeping existing\n * schema if either is not a ZodObject.\n */\nfunction mergeSchemas(\n existing: ZodType,\n incoming: ZodType,\n stateName: string\n): ZodType {\n if (existing instanceof ZodObject && incoming instanceof ZodObject) {\n const existingShape = existing.shape as Record<string, ZodType>;\n const incomingShape = incoming.shape as Record<string, ZodType>;\n for (const key of Object.keys(incomingShape)) {\n if (key in existingShape) {\n const existingBase = baseTypeName(existingShape[key]);\n const incomingBase = baseTypeName(incomingShape[key]);\n if (existingBase !== incomingBase) {\n throw new Error(\n `Schema conflict in \"${stateName}\": key \"${key}\" has type \"${existingBase}\" but incoming partial declares \"${incomingBase}\"`\n );\n }\n }\n }\n return existing.extend(incomingShape);\n }\n return existing;\n}\n\n/**\n * Merges two init functions by spreading both results together.\n * Each partial only provides its own defaults.\n */\nfunction mergeInits<TState extends Schema>(\n existing: () => Readonly<TState>,\n incoming: () => Readonly<TState>\n): () => Readonly<TState> {\n return () => ({ ...existing(), ...incoming() });\n}\n\n/**\n * Registers a state into a states map and action/event registries,\n * merging with existing same-name states (partial state support).\n */\nexport function registerState(\n state: State<any, any, any>,\n states: Map<string, State<any, any, any>>,\n actions: Record<string, any>,\n events: Record<string, any>\n): void {\n const existing = states.get(state.name);\n if (existing) {\n mergeIntoExisting(state, existing, states, actions, events);\n } else {\n registerNewState(state, states, actions, events);\n }\n}\n\n/**\n * Registers a state for the first time. All action/event names must be unique\n * across the registry; collisions throw.\n */\nfunction registerNewState(\n state: State<any, any, any>,\n states: Map<string, State<any, any, any>>,\n actions: Record<string, any>,\n events: Record<string, any>\n): void {\n states.set(state.name, state);\n for (const name of Object.keys(state.actions)) {\n if (actions[name]) throw new Error(`Duplicate action \"${name}\"`);\n actions[name] = state;\n }\n for (const name of Object.keys(state.events)) {\n if (events[name]) throw new Error(`Duplicate event \"${name}\"`);\n events[name] = { schema: state.events[name], reactions: new Map() };\n }\n}\n\n/**\n * Merges an incoming partial state into an existing same-name state and\n * updates the action/event registries. Splits into four phases:\n * 1. validate no cross-state action/event collisions\n * 2. merge per-event patches (one custom patch per event)\n * 3. build the merged state and replace it in the states map\n * 4. update action→state pointers and register new events\n */\nfunction mergeIntoExisting(\n state: State<any, any, any>,\n existing: State<any, any, any>,\n states: Map<string, State<any, any, any>>,\n actions: Record<string, any>,\n events: Record<string, any>\n): void {\n // 1. Validate no cross-state collisions for actions/events\n for (const name of Object.keys(state.actions)) {\n // Same schema reference means the same partial re-registered via another slice\n if (existing.actions[name] === state.actions[name]) continue;\n if (actions[name]) throw new Error(`Duplicate action \"${name}\"`);\n }\n for (const name of Object.keys(state.events)) {\n // Same schema reference means the same partial re-registered via another slice\n if (existing.events[name] === state.events[name]) continue;\n // Same event name registered in a same-name state partial with a\n // different Zod schema reference — silent contract drift that the\n // type system can't catch (structurally compatible shapes flow\n // through TS even when refinements/enums/literals disagree).\n // Reference identity is the rule: cross-slice event schemas must\n // come from a single shared instance.\n if (existing.events[name]) {\n throw new Error(\n `Event \"${name}\" in state \"${state.name}\" is declared with different Zod schemas across slices. ` +\n `Cross-slice event schemas must reference the same instance — ` +\n `extract a shared schema (e.g. \\`export const ${name} = z.object({ ... })\\` in a shared module) ` +\n `and import it in every slice that declares it.`\n );\n }\n if (events[name]) throw new Error(`Duplicate event \"${name}\"`);\n }\n\n // 2. Merge patches with custom-vs-passthrough resolution\n const mergedPatch = mergePatches(existing.patch, state.patch, state.name);\n\n // 3. Build merged state\n const merged = {\n ...existing,\n state: mergeSchemas(existing.state, state.state, state.name),\n init: mergeInits(existing.init, state.init),\n events: { ...existing.events, ...state.events },\n actions: { ...existing.actions, ...state.actions },\n patch: mergedPatch,\n on: { ...existing.on, ...state.on },\n given: { ...existing.given, ...state.given },\n snap:\n state.snap && existing.snap && state.snap !== existing.snap\n ? (() => {\n throw new Error(\n `Duplicate snap strategy for state \"${state.name}\"`\n );\n })()\n : state.snap || existing.snap,\n };\n states.set(state.name, merged);\n\n // 4. Update action→state pointers; register events not yet seen\n for (const name of Object.keys(merged.actions)) {\n actions[name] = merged;\n }\n for (const name of Object.keys(state.events)) {\n if (events[name]) continue; // already registered, preserve reactions\n events[name] = { schema: state.events[name], reactions: new Map() };\n }\n}\n\n/**\n * Merges two patch maps. Only one custom (non-passthrough) patch per event is\n * allowed; passthroughs always yield to custom reducers, and re-registering\n * the same custom patch (same reference, e.g. across slices) is a no-op.\n */\nfunction mergePatches(\n existing: Record<string, any>,\n incoming: Record<string, any>,\n stateName: string\n): Record<string, any> {\n const merged = { ...existing };\n for (const name of Object.keys(incoming)) {\n const existingP = existing[name];\n const incomingP = incoming[name];\n if (!existingP) {\n merged[name] = incomingP;\n continue;\n }\n const existingIsDefault = existingP._passthrough;\n const incomingIsDefault = incomingP._passthrough;\n if (!existingIsDefault && !incomingIsDefault && existingP !== incomingP) {\n throw new Error(\n `Duplicate custom patch for event \"${name}\" in state \"${stateName}\"`\n );\n }\n // Keep whichever is custom; if both passthrough or existing custom, keep existing\n if (existingIsDefault && !incomingIsDefault) {\n merged[name] = incomingP;\n }\n }\n return merged;\n}\n\n/**\n * Merges reactions from one event register into another. The target is\n * assumed to already contain entries for every event name in the source\n * (e.g., act-builder's `.withSlice()` registers the slice's states first,\n * which seeds the target events). Reaction names collide by `set()`\n * semantics — last write wins.\n */\nexport function mergeEventRegister(\n target: Record<string, { reactions: Map<string, unknown> }>,\n source: Record<string, { reactions: Map<string, unknown> }>\n): void {\n for (const [eventName, sourceReg] of Object.entries(source)) {\n const targetReg = target[eventName];\n if (!targetReg) continue;\n for (const [name, reaction] of sourceReg.reactions) {\n targetReg.reactions.set(name, reaction);\n }\n }\n}\n\n/**\n * Merges a projection's event schemas and reactions into an event registry,\n * deduplicating reaction names by appending \"_p\" on collision.\n */\nexport function mergeProjection(\n proj: Projection<any>,\n events: Record<string, any>\n): void {\n for (const eventName of Object.keys(proj.events)) {\n const projRegister = proj.events[eventName];\n const existing = events[eventName];\n if (!existing) {\n events[eventName] = {\n schema: projRegister.schema,\n reactions: new Map(projRegister.reactions),\n };\n } else {\n for (const [name, reaction] of projRegister.reactions) {\n let key = name;\n while (existing.reactions.has(key)) key = `${key}_p`;\n existing.reactions.set(key, reaction);\n }\n }\n }\n}\n\n// Resolves the event stream as source and target (default)\nexport const _this_ = ({ stream }: { stream: string }) => ({\n source: stream,\n target: stream,\n});\n","/**\n * @module backoff\n * @category Internal\n *\n * Per-reaction retry backoff delay computation. Pure function — keeps\n * `DrainController` and `reactions._finalize` testable in isolation.\n *\n * @internal\n */\n\nimport type { BackoffOptions } from \"../types/reaction.js\";\n\n/**\n * Compute the wall-clock delay (in ms) to wait before the next attempt on\n * a stream whose handler just failed.\n *\n * @param retry - The lease's `retry` counter at finalize time. `0` is the\n * first attempt that failed; `1` is after one retry; etc.\n * @param opts - Per-reaction backoff config. Returns `0` when undefined.\n * @returns Non-negative integer milliseconds. Always `0` when `opts` is\n * undefined or `baseMs <= 0`.\n */\nexport function computeBackoffDelay(\n retry: number,\n opts: BackoffOptions | undefined\n): number {\n if (!opts || opts.baseMs <= 0) return 0;\n const r = Math.max(0, retry);\n let delay: number;\n switch (opts.strategy) {\n case \"fixed\":\n delay = opts.baseMs;\n break;\n case \"linear\":\n delay = opts.baseMs * (r + 1);\n break;\n case \"exponential\":\n delay = opts.baseMs * 2 ** r;\n if (opts.maxMs !== undefined) delay = Math.min(delay, opts.maxMs);\n break;\n }\n if (opts.jitter) delay = delay * (0.5 + Math.random());\n return Math.max(0, Math.floor(delay));\n}\n","/**\n * @module reactions\n * @category Internal\n *\n * Reaction dispatch — what runs inside the drain pipeline once `runDrainCycle`\n * has fetched events for a leased stream. Two shapes:\n *\n * - per-event `handle`: walks payloads sequentially, builds a scoped `IAct`\n * that auto-injects `reactingTo` so handlers don't have to thread it\n * through manually\n * - bulk `handleBatch`: hands every event for a static-target projection to\n * a single batch callback, enabling one-transaction replays\n *\n * Both share `_finalize`, which collapses the retry-vs-block decision and\n * the \"report error only when nothing was handled\" rule.\n *\n * @internal\n */\n\nimport {\n type Actor,\n type BatchHandler,\n type Committed,\n type IAct,\n type Lease,\n type Logger,\n NonRetryableError,\n type ReactionOptions,\n type ReactionPayload,\n type Schemas,\n type Target,\n} from \"../types/index.js\";\nimport { computeBackoffDelay } from \"./backoff.js\";\nimport type { Handle, HandleBatch, HandleResult } from \"./drain-cycle.js\";\n\n/**\n * Dependencies a reaction handler needs from the orchestrator: the logger\n * for retry/error breadcrumbs, plus the bound `IAct` methods that the scoped\n * proxy hands to user reaction code.\n *\n * @internal\n */\nexport type ReactionDeps<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n> = {\n readonly logger: Logger;\n readonly boundDo: IAct<TEvents, TActions, TActor>[\"do\"];\n readonly boundLoad: IAct<TEvents, TActions, TActor>[\"load\"];\n readonly boundQuery: IAct<TEvents, TActions, TActor>[\"query\"];\n readonly boundQueryArray: IAct<TEvents, TActions, TActor>[\"query_array\"];\n};\n\n/**\n * Shared finalization: log the error and decide retry vs. block. The\n * error string is *always* surfaced on the failure path — drain-cycle\n * uses `handled > 0` (not `error` presence) to decide whether to ack\n * the partial progress, so the message can travel for trace + blocked\n * record without affecting the ack/skip choice.\n */\nfunction finalize(\n lease: Lease,\n handled: number,\n at: number,\n error: Error | undefined,\n options: ReactionOptions,\n logger: Logger,\n failed_at?: number\n): HandleResult {\n if (!error) return { lease, handled, acked_at: at };\n logger.error(error);\n // A `NonRetryableError` from the handler short-circuits the retry\n // budget — block on first attempt when the operator has opted in via\n // `blockOnError`. When `blockOnError` is false, the operator has\n // explicitly chosen \"retry forever,\" so we don't override that.\n const nonRetryable = error instanceof NonRetryableError;\n const block =\n options.blockOnError && (nonRetryable || lease.retry >= options.maxRetries);\n if (block)\n logger.error(\n nonRetryable\n ? `Blocking ${lease.stream} on non-retryable error.`\n : `Blocking ${lease.stream} after ${lease.retry} retries.`\n );\n // Backoff applies only on retry paths — successful handles and terminal\n // blocks never defer. `lease.retry` here is the just-failed attempt's\n // counter, so the delay paces the *next* attempt.\n const nextAttemptAt =\n !block && options.backoff\n ? Date.now() + computeBackoffDelay(lease.retry, options.backoff)\n : undefined;\n return {\n lease,\n handled,\n acked_at: at,\n error: error.message,\n block,\n nextAttemptAt,\n failed_at,\n };\n}\n\n/**\n * Builds the per-event reaction dispatcher passed to `runDrainCycle`.\n *\n * The scoped `IAct` proxy auto-injects the triggering event as `reactingTo`\n * when handlers call `do()` without it (#587), keeping the correlation\n * chain by default. The non-do methods are reused across all dispatches —\n * only `do` rebinds per payload because it captures the triggering event.\n *\n * @internal\n */\nexport function buildHandle<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n>(deps: ReactionDeps<TEvents, TActions, TActor>): Handle<TEvents> {\n const { logger, boundDo, boundLoad, boundQuery, boundQueryArray } = deps;\n return async (lease, payloads) => {\n if (payloads.length === 0) return { lease, handled: 0, acked_at: lease.at };\n\n const stream = lease.stream;\n let at = payloads.at(0)!.event.id;\n let handled = 0;\n\n if (lease.retry > 0)\n logger.warn(`Retrying ${stream}@${at} (${lease.retry}).`);\n\n const scopedApp: IAct<TEvents, TActions, TActor> = {\n do: boundDo,\n load: boundLoad,\n query: boundQuery,\n query_array: boundQueryArray,\n };\n\n for (const payload of payloads) {\n const { event, handler } = payload;\n scopedApp.do = <TKey extends keyof TActions & string>(\n action: TKey,\n target: Target<TActor>,\n actionPayload: Readonly<TActions[TKey]>,\n reactingTo?: Committed<Schemas, string>,\n skipValidation?: boolean\n ) =>\n boundDo(\n action,\n target,\n actionPayload,\n (reactingTo ?? event) as Committed<TEvents, string & keyof TEvents>,\n skipValidation\n );\n try {\n await handler(event, stream, scopedApp);\n at = event.id;\n handled++;\n } catch (error) {\n return finalize(\n lease,\n handled,\n at,\n error as Error,\n payload.options,\n logger,\n event.id\n );\n }\n }\n return finalize(lease, handled, at, undefined, payloads[0].options, logger);\n };\n}\n\n/**\n * Builds the bulk reaction dispatcher passed to `runDrainCycle`. All events\n * for a static-target projection are handed to a single callback so the\n * projection can do one transaction per drain (catch-up replays especially).\n *\n * @internal\n */\nexport function buildHandleBatch<TEvents extends Schemas>(\n logger: Logger\n): HandleBatch<TEvents> {\n return async (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[],\n batchHandler: BatchHandler<TEvents>\n ) => {\n const stream = lease.stream;\n const events = payloads.map((p) => p.event);\n const options = payloads[0].options;\n\n if (lease.retry > 0)\n logger.warn(`Retrying batch ${stream}@${events[0].id} (${lease.retry}).`);\n\n try {\n await batchHandler(events, stream);\n return finalize(\n lease,\n events.length,\n events.at(-1)!.id,\n undefined,\n options,\n logger\n );\n } catch (error) {\n return finalize(lease, 0, lease.at, error as Error, options, logger);\n }\n };\n}\n","/**\n * @module settle\n * @category Internal\n *\n * Debounced correlate→drain loop. Sits one level above both correlation\n * and drain: schedule() coalesces rapid callers into a single cycle, then\n * runs correlate+drain in a loop until a pass produces no progress.\n *\n * Owns the debounce timer and the reentrancy flag. Everything else is\n * supplied via the `SettleDeps` callbacks so this module stays free of\n * orchestrator state.\n *\n * @internal\n */\n\nimport type {\n Drain,\n DrainOptions,\n Logger,\n Query,\n Schemas,\n SettleOptions,\n} from \"../types/index.js\";\n\n/**\n * Callbacks the settle loop needs from the orchestrator. Modeled as an\n * input bag so this file doesn't import `Act` (avoids a cycle) and stays\n * independently testable.\n *\n * @internal\n */\nexport type SettleDeps<TEvents extends Schemas> = {\n readonly logger: Logger;\n readonly init: () => Promise<void>;\n readonly checkpoint: () => number;\n readonly correlate: (\n query: Query\n ) => Promise<{ subscribed: number; last_id: number }>;\n readonly drain: (options: DrainOptions) => Promise<Drain<TEvents>>;\n readonly onSettled: (drain: Drain<TEvents>) => void;\n};\n\n/**\n * Drives the debounced correlate→drain catch-up cycle. One instance per\n * Act orchestrator.\n *\n * @internal\n */\nexport class SettleLoop<TEvents extends Schemas> {\n private _timer: ReturnType<typeof setTimeout> | undefined = undefined;\n private _running = false;\n\n constructor(\n private readonly deps: SettleDeps<TEvents>,\n /** Debounce window applied when the caller doesn't override via `SettleOptions.debounceMs`. */\n private readonly defaultDebounceMs: number\n ) {}\n\n /**\n * Schedule a settle pass. Multiple calls inside the debounce window\n * coalesce into one cycle. The cycle runs correlate→drain in a loop\n * until no progress is made (no new subscriptions, no acks, no blocks)\n * or `maxPasses` is reached, then emits the `\"settled\"` lifecycle event\n * via {@link SettleDeps.onSettled}.\n */\n schedule(options: SettleOptions = {}): void {\n const {\n debounceMs = this.defaultDebounceMs,\n correlate: correlateQuery = { after: -1, limit: 100 },\n maxPasses = Infinity,\n ...drainOptions\n } = options;\n\n if (this._timer) clearTimeout(this._timer);\n this._timer = setTimeout(() => {\n this._timer = undefined;\n if (this._running) return;\n this._running = true;\n\n (async () => {\n await this.deps.init();\n let lastDrain: Drain<TEvents> | undefined;\n // Loop correlate→drain until a pass produces no work — this fully\n // catches up paginated streams (e.g. after `reset()` on a long\n // projection) without forcing callers to roll their own loop.\n // `maxPasses` caps runtime in pathological cases.\n for (let i = 0; i < maxPasses; i++) {\n const { subscribed } = await this.deps.correlate({\n ...correlateQuery,\n after: this.deps.checkpoint(),\n });\n lastDrain = await this.deps.drain(drainOptions);\n const made_progress =\n subscribed > 0 ||\n lastDrain.acked.length > 0 ||\n lastDrain.blocked.length > 0;\n if (!made_progress) break;\n }\n if (lastDrain) this.deps.onSettled(lastDrain);\n })()\n .catch((err) => this.deps.logger.error(err))\n .finally(() => {\n this._running = false;\n });\n }, debounceMs);\n }\n\n /** Cancel any pending or active settle cycle. Idempotent. */\n stop(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n","/**\n * @module act-builder\n * @category Builders\n *\n * Fluent builder for composing event-sourced applications.\n */\nimport { Act, type ActOptions } from \"../act.js\";\nimport {\n _this_,\n currentVersionOf,\n deprecatedEventNames,\n mergeEventRegister,\n mergeProjection,\n registerState,\n} from \"../internal/index.js\";\nimport { DEFAULT_LANE, log } from \"../ports.js\";\nimport type {\n Actor,\n BatchHandler,\n Committed,\n EventRegister,\n IAct,\n LaneConfig,\n Reaction,\n ReactionOptions,\n ReactionResolver,\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n Snapshot,\n State,\n} from \"../types/index.js\";\nimport type { Projection } from \"./projection-builder.js\";\nimport type { Slice } from \"./slice-builder.js\";\n\n/**\n * Registers a projection's batch handler against its target stream, throwing\n * if a different handler is already registered for the same target. Two\n * projections silently overwriting each other's batch handlers used to be a\n * latent footgun.\n */\nfunction registerBatchHandler(\n proj: Projection<any>,\n batchHandlers: Map<string, BatchHandler<any>>\n): void {\n if (!proj.batchHandler || !proj.target) return;\n const existing = batchHandlers.get(proj.target);\n if (existing && existing !== proj.batchHandler) {\n throw new Error(`Duplicate batch handler for target \"${proj.target}\"`);\n }\n batchHandlers.set(proj.target, proj.batchHandler);\n}\n\n/**\n * Runtime backstop for slice-declared lane references — rejects\n * static `.to({lane})` entries that aren't in the declared set.\n * Inline reactions are caught at compile time; this only fires for\n * slices built against older type definitions.\n */\nfunction validateLaneReferences(\n registry: Registry<any, any, any>,\n lanes: ReadonlyArray<LaneConfig>\n): void {\n const declared = new Set<string>([DEFAULT_LANE, ...lanes.map((l) => l.name)]);\n for (const [eventName, def] of Object.entries(registry.events)) {\n const entry = def as { reactions: Map<string, Reaction<any, any>> };\n for (const [handlerName, reaction] of entry.reactions) {\n const resolver = reaction.resolver;\n if (typeof resolver === \"function\") continue;\n const lane = (resolver as { lane?: string }).lane;\n if (lane && !declared.has(lane)) {\n throw new Error(\n `Reaction \"${handlerName}\" on \"${eventName}\" targets undeclared lane \"${lane}\". ` +\n `Declared lanes: ${[...declared].map((l) => `\"${l}\"`).join(\", \")}. ` +\n `Add \\`.withLane({ name: \"${lane}\", ... })\\` to act() or correct the .to() declaration.`\n );\n }\n }\n }\n}\n\n/**\n * Fluent builder interface for composing event-sourced applications.\n *\n * Provides a chainable API for:\n * - Registering states via `.withState()`\n * - Registering slices via `.withSlice()`\n * - Registering projections via `.withProjection()`\n * - Locking a custom actor type via `.withActor<TActor>()`\n * - Declaring drain lanes via `.withLane({name, ...})` (ACT-1103)\n * - Defining event reactions via `.on()` → `.do()` → `.to()`\n * - Building the orchestrator via `.build()`\n *\n * @template TSchemaReg - Schema register for states (maps action names to state schemas)\n * @template TEvents - Event schemas (maps event names to event data schemas)\n * @template TActions - Action schemas (maps action names to action payload schemas)\n * @template TStateMap - Map of state names to state schemas\n * @template TActor - Actor type extending base Actor\n * @template TLanes - Union of declared lane names (ACT-1103). Narrowed by\n * `.withLane({name})` calls so `.to({lane})` and `ActOptions.onlyLanes`\n * reject typos at compile time. Starts at `\"default\"`.\n *\n * @see {@link act} for usage examples\n * @see {@link Act} for the built orchestrator API\n */\nexport type ActBuilder<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n TLanes extends string = typeof DEFAULT_LANE,\n> = {\n /**\n * Registers a state definition with the builder.\n *\n * State names, action names, and event names must be unique across the\n * application (partial states with the same name are merged automatically).\n *\n * @throws {Error} If duplicate action or event names are detected\n */\n withState: <\n TNewState extends Schema,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n TNewName extends string = string,\n >(\n state: State<TNewState, TNewEvents, TNewActions, TNewName>\n ) => ActBuilder<\n TSchemaReg & { [K in keyof TNewActions]: TNewState },\n TEvents & TNewEvents,\n TActions & TNewActions,\n TStateMap & { [K in TNewName]: TNewState },\n TActor,\n TLanes\n >;\n /**\n * Registers a slice with the builder.\n *\n * Merges all the slice's states and reactions into the application.\n * State names, action names, and event names must be unique across the\n * application (partial states with the same name are merged automatically).\n *\n * @throws {Error} If duplicate action or event names are detected\n */\n withSlice: <\n TNewSchemaReg extends SchemaRegister<TNewActions>,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n TNewMap extends Record<string, Schema>,\n TNewLanes extends string,\n >(\n slice: Slice<\n TNewSchemaReg,\n TNewEvents,\n TNewActions,\n TNewMap,\n Actor,\n TNewLanes\n >\n ) => ActBuilder<\n TSchemaReg & TNewSchemaReg,\n TEvents & TNewEvents,\n TActions & TNewActions,\n TStateMap & TNewMap,\n TActor,\n TLanes | TNewLanes\n >;\n /**\n * Registers a standalone projection with the builder.\n *\n * The projection's events must be a subset of events already registered\n * via `.withState()` or `.withSlice()`.\n */\n withProjection: <TNewEvents extends Schemas>(\n projection: [Exclude<keyof TNewEvents, keyof TEvents>] extends [never]\n ? Projection<TNewEvents>\n : never\n ) => ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\n /**\n * Locks a custom actor type for this application.\n *\n * This is a pure type-level method — it returns the same builder at\n * runtime but narrows the `TActor` generic so that `app.do()` and\n * reaction dispatchers require the richer actor shape.\n *\n * @template TNewActor - Custom actor type extending base Actor\n * @returns The same builder with `TActor` locked to `TNewActor`\n *\n * @example\n * ```typescript\n * type MyActor = { id: string; name: string; role: string; tenantId: string };\n *\n * const app = act()\n * .withActor<MyActor>()\n * .withState(Counter)\n * .build();\n *\n * // Now app.do() requires MyActor in the target\n * await app.do(\"increment\", {\n * stream: \"counter-1\",\n * actor: { id: \"1\", name: \"Alice\", role: \"admin\", tenantId: \"t1\" }\n * }, { by: 5 });\n * ```\n */\n withActor: <TNewActor extends Actor>() => ActBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TNewActor,\n TLanes\n >;\n /**\n * Declares a drain lane (ACT-1103). Lane name narrows `TLanes` so\n * `.to({lane})` and `ActOptions.onlyLanes` type-check against it.\n *\n * @example\n * ```typescript\n * const app = act()\n * .withState(Counter)\n * .withLane({ name: \"slow\", leaseMillis: 60_000, streamLimit: 5 })\n * .on(\"OrderConfirmed\")\n * .do(deliverWebhook)\n * .to({ target: \"webhooks-out\", lane: \"slow\" })\n * .build();\n * ```\n */\n withLane: <const TConfig extends LaneConfig>(\n config: TConfig\n ) => ActBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes | TConfig[\"name\"]\n >;\n /**\n * Begins defining a reaction to a specific event.\n *\n * Reactions are event handlers that respond to state changes. They can trigger\n * additional actions, update external systems, or perform side effects. Reactions\n * are processed asynchronously during drain cycles.\n *\n * @template TKey - Event name (must be a registered event)\n * @param event - The event name to react to\n * @returns An object with `.do()` method to define the reaction handler\n */\n on: <TKey extends keyof TEvents>(\n event: TKey\n ) => {\n do: (\n handler: (\n event: Committed<TEvents, TKey>,\n stream: string,\n app: IAct<TEvents, TActions, TActor>\n ) => Promise<Snapshot<Schema, TEvents> | void>,\n options?: Partial<ReactionOptions>\n ) => ActBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes\n > & {\n to: (\n resolver: ReactionResolver<TEvents, TKey, TLanes> | string\n ) => ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\n };\n };\n /**\n * Builds and returns the Act orchestrator instance.\n *\n * @param options - Optional runtime overrides (see {@link ActOptions}).\n * `options.onlyLanes` is narrowed to the declared `TLanes` union, so\n * `onlyLanes: [\"typo\"]` is a compile error when the lane wasn't\n * declared via `.withLane(...)`.\n * @returns The Act orchestrator instance\n *\n * @see {@link Act} for available orchestrator methods\n */\n build: (\n options?: ActOptions<TLanes>\n ) => Act<TSchemaReg, TEvents, TActions, TStateMap, TActor>;\n /**\n * The registered event schemas and their reaction maps.\n */\n readonly events: EventRegister<TEvents>;\n};\n\n/* eslint-disable @typescript-eslint/no-empty-object-type -- {} used as generic defaults */\n\n/**\n * Creates a new Act orchestrator builder for composing event-sourced applications.\n *\n * @example Basic application with single state\n * ```typescript\n * const app = act()\n * .withState(Counter)\n * .build();\n * ```\n *\n * @example Application with custom actor type\n * ```typescript\n * type MyActor = { id: string; name: string; role: string };\n *\n * const app = act()\n * .withActor<MyActor>()\n * .withState(Counter)\n * .build();\n * ```\n *\n * @example Application with slices (vertical slice architecture)\n * ```typescript\n * const CounterSlice = slice()\n * .withState(Counter)\n * .on(\"Incremented\")\n * .do(async (event) => { console.log(\"incremented!\"); })\n * .to(\"counter-target\")\n * .build();\n *\n * const app = act()\n * .withSlice(CounterSlice)\n * .build();\n * ```\n *\n *\n * @see {@link ActBuilder} for available builder methods\n * @see {@link Act} for orchestrator API methods\n * @see {@link state} for defining states\n * @see {@link slice} for defining slices\n */\nexport function act<\n // @ts-expect-error empty schema\n TSchemaReg extends SchemaRegister<TActions> = {},\n TEvents extends Schemas = {},\n TActions extends Schemas = {},\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n>(): ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor> {\n // Mutable runtime state — one set of references shared across the entire\n // fluent chain. Each `with*` / `on` call mutates these and returns the\n // same builder cast to the widened generic; type fanout is preserved\n // through the public type signatures, runtime allocation is not.\n const states = new Map<string, State<any, any, any>>();\n const registry: Registry<TSchemaReg, TEvents, TActions> = {\n actions: {} as Registry<TSchemaReg, TEvents, TActions>[\"actions\"],\n events: {} as Registry<TSchemaReg, TEvents, TActions>[\"events\"],\n };\n const pendingProjections: Projection<any>[] = [];\n const batchHandlers = new Map<string, BatchHandler<any>>();\n const lanes: LaneConfig[] = [];\n\n // Set on the first `.build()` call. Lets the same builder produce\n // many Acts (multi-tenant / A-B testing patterns) without re-merging\n // projections or re-logging the deprecation advisory.\n let _built = false;\n\n // ACT-403: auto-deprecation enforcement. Groups each state's events\n // by base name + `_v<digits>`; the highest version is current, all\n // lower ones are deprecated. Stashes the deprecation set on the\n // state so `event-sourcing.ts` can warn at runtime for dynamic\n // emits. Scans static `.emit(\"X\")` markers across every state and\n // throws if any target a deprecated event — the only legitimate use\n // of a deprecated event is on the reduce path. Finally, surfaces a\n // one-line startup advisory so operators can see \"your app has\n // legacy events kept for the read path, here's where they live.\"\n const finalizeDeprecations = () => {\n const deprecationSummary: Array<{\n stateName: string;\n deprecated: string;\n current: string;\n }> = [];\n for (const state of states.values()) {\n const eventNames = Object.keys(state.events);\n const deprecated = deprecatedEventNames(eventNames);\n if (deprecated.size === 0) continue;\n (state as { _deprecated?: Set<string> })._deprecated = deprecated;\n for (const name of deprecated) {\n // `currentVersionOf` is guaranteed non-undefined here — `name`\n // is in `deprecated`, which by construction means a higher-\n // versioned sibling exists in the same group.\n const current = currentVersionOf(name, eventNames) as string;\n deprecationSummary.push({\n stateName: state.name,\n deprecated: name,\n current,\n });\n }\n for (const [actionName, handler] of Object.entries(state.on)) {\n const staticTarget = (handler as { _staticEmit?: string } | undefined)\n ?._staticEmit;\n if (staticTarget && deprecated.has(staticTarget)) {\n const current = currentVersionOf(staticTarget, eventNames);\n throw new Error(\n `Action \"${actionName}\" in state \"${state.name}\" emits deprecated event \"${staticTarget}\". ` +\n `A newer version exists: \"${current}\". Update the .emit() call ` +\n `to target the current version. The reducer (.patch) for ` +\n `\"${staticTarget}\" stays as-is — historical events still need it.`\n );\n }\n }\n }\n if (deprecationSummary.length > 0) {\n const list = deprecationSummary\n .map(\n (d) =>\n `\"${d.deprecated}\" (current: \"${d.current}\", state: \"${d.stateName}\")`\n )\n .join(\", \");\n log().info(\n `Act registered ${deprecationSummary.length} deprecated event(s): ${list}. ` +\n `These are legacy versions kept for the read path. Consider truncating ` +\n `closed streams via app.close() when feasible to reduce historical event load. ` +\n `See docs/docs/architecture/event-schema-evolution.md.`\n );\n }\n };\n\n // The `as` chain on `self` is the type fanout: each fluent method\n // mutates state and returns `self` cast to its post-call generic\n // signature. Internal-only — public types stay narrow.\n const builder: ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor> =\n {\n withState: (state) => {\n registerState(state, states, registry.actions, registry.events);\n return builder as never;\n },\n withSlice: (input) => {\n for (const s of input.states.values()) {\n registerState(s, states, registry.actions, registry.events);\n }\n mergeEventRegister(registry.events, input.events);\n pendingProjections.push(...input.projections);\n for (const sliceLane of input.lanes) {\n const existing = lanes.find((l) => l.name === sliceLane.name);\n if (!existing) {\n lanes.push(sliceLane);\n continue;\n }\n if (\n existing.leaseMillis !== sliceLane.leaseMillis ||\n existing.streamLimit !== sliceLane.streamLimit ||\n existing.cycleMs !== sliceLane.cycleMs\n ) {\n throw new Error(\n `Lane \"${sliceLane.name}\" was already declared with a different config`\n );\n }\n }\n return builder as never;\n },\n withProjection: (proj) => {\n mergeProjection(proj as Projection<any>, registry.events);\n registerBatchHandler(proj as Projection<any>, batchHandlers);\n return builder;\n },\n withActor: <TNewActor extends Actor>() =>\n builder as unknown as ActBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TNewActor\n >,\n withLane: (config) => {\n if (config.name === DEFAULT_LANE)\n throw new Error(`Lane \"${DEFAULT_LANE}\" is reserved`);\n if (lanes.some((l) => l.name === config.name))\n throw new Error(`Lane \"${config.name}\" was already declared`);\n lanes.push(config);\n return builder as never;\n },\n on: <TKey extends keyof TEvents>(event: TKey) => ({\n do: (\n handler: (\n event: Committed<TEvents, TKey>,\n stream: string,\n app: IAct<TEvents, TActions, TActor>\n ) => Promise<Snapshot<Schema, TEvents> | void>,\n options?: Partial<ReactionOptions>\n ) => {\n const reaction: Reaction<TEvents, TKey, TActions, TActor> = {\n handler: handler,\n resolver: _this_,\n options: {\n blockOnError: options?.blockOnError ?? true,\n maxRetries: options?.maxRetries ?? 3,\n backoff: options?.backoff,\n },\n };\n if (!handler.name)\n throw new Error(\n `Reaction handler for \"${String(event)}\" must be a named function`\n );\n // Register once with the default _this_ resolver. If `.to()` is\n // chained next, it patches the same reaction's resolver in place\n // — no second Map.set() round-trip.\n registry.events[event].reactions.set(handler.name, reaction);\n return Object.assign(builder, {\n to(resolver: ReactionResolver<TEvents, TKey> | string) {\n reaction.resolver =\n typeof resolver === \"string\" ? { target: resolver } : resolver;\n return builder;\n },\n });\n },\n }),\n build: (options?: ActOptions) => {\n // One-time finalize: merge pending projections and run the\n // deprecation scan + advisory log exactly once. Calling\n // `.build({scoped: ...})` repeatedly (e.g., per tenant) is\n // supported — see extension-points.md § Scoped ports. Without\n // this guard, `mergeProjection` would re-add reactions to the\n // shared registry on every call (accumulating `_p`/`_p_p`\n // dedupe suffixes), and the deprecation advisory would log on\n // every tenant.\n if (!_built) {\n for (const proj of pendingProjections) {\n mergeProjection(proj, registry.events as Record<string, any>);\n registerBatchHandler(proj, batchHandlers);\n }\n finalizeDeprecations();\n validateLaneReferences(registry, lanes);\n _built = true;\n }\n\n return new Act<TSchemaReg, TEvents, TActions, TStateMap, TActor>(\n registry,\n states,\n batchHandlers,\n options,\n lanes\n );\n },\n events: registry.events,\n };\n return builder;\n}\n","/**\n * @module projection-builder\n * @category Builders\n *\n * Fluent builder for composing projection handlers — read-model updaters\n * that react to events and update external state (databases, caches, etc.).\n *\n * Projections differ from slices: they don't contain states, don't dispatch\n * actions, and are pure side-effect handlers routed to a named stream.\n */\nimport type { ZodType } from \"zod\";\nimport { _this_ } from \"../internal/index.js\";\nimport type {\n BatchHandler,\n Committed,\n EventRegister,\n Reaction,\n ReactionResolver,\n Schema,\n Schemas,\n} from \"../types/index.js\";\n\n/**\n * A self-contained projection grouping read-model update handlers.\n * Projections are composed into an Act orchestrator via `act().withProjection(projection)`.\n *\n * @template TEvents - Event schemas handled by this projection\n */\nexport type Projection<TEvents extends Schemas> = {\n readonly _tag: \"Projection\";\n readonly events: EventRegister<TEvents>;\n readonly target?: string;\n readonly batchHandler?: BatchHandler<TEvents>;\n};\n\n/** Helper: a single-key record mapping an event name to its Zod schema. */\ntype EventEntry<TKey extends string = string, TData extends Schema = Schema> = {\n [P in TKey]: ZodType<TData>;\n};\n\n/** Infer the handler-result type after registering one event. */\ntype DoResult<\n TEvents extends Schemas,\n TKey extends string,\n TData extends Schema,\n TTarget extends string | undefined = undefined,\n> = ProjectionBuilder<TEvents & { [P in TKey]: TData }, TTarget> & {\n to: (\n resolver: ReactionResolver<TEvents & { [P in TKey]: TData }, TKey> | string\n ) => ProjectionBuilder<TEvents & { [P in TKey]: TData }, TTarget>;\n};\n\n/**\n * Fluent builder interface for composing projections.\n *\n * When a static target is provided via `projection(\"target\")`, the builder\n * exposes a `.batch()` method for registering a batch handler that processes\n * all events in a single call.\n *\n * @template TEvents - Event schemas\n * @template TTarget - Static target string or undefined\n */\nexport type ProjectionBuilder<\n TEvents extends Schemas,\n TTarget extends string | undefined = undefined,\n> = {\n /**\n * Begins defining a projection handler for a specific event.\n *\n * Pass a `{ EventName: schema }` record — use shorthand `{ EventName }`\n * when the variable name matches the event name. The key becomes the\n * event name, the value the Zod schema.\n */\n on: <TKey extends string, TData extends Schema>(\n entry: EventEntry<TKey, TData>\n ) => {\n do: (\n handler: (\n event: Committed<TEvents & { [P in TKey]: TData }, TKey>,\n stream: string\n ) => Promise<void>\n ) => DoResult<TEvents, TKey, TData, TTarget>;\n };\n /**\n * Builds and returns the Projection data structure.\n */\n build: () => Projection<TEvents>;\n /**\n * The registered event schemas and their reaction maps.\n */\n readonly events: EventRegister<TEvents>;\n} & (TTarget extends string\n ? {\n /**\n * Registers a batch handler that processes all events in a single call.\n *\n * Only available on projections with a static target (`projection(\"target\")`).\n * The handler receives a discriminated union of all declared events,\n * enabling bulk DB operations in a single transaction.\n *\n * When defined, the batch handler is always called — even for a single event.\n * Individual `.do()` handlers serve as fallback for projections without `.batch()`.\n */\n batch: (handler: BatchHandler<TEvents>) => {\n build: () => Projection<TEvents>;\n };\n }\n : // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n {});\n\n/* eslint-disable @typescript-eslint/no-empty-object-type -- {} used as generic defaults */\n\n/**\n * Creates a new projection builder for composing read-model update handlers.\n *\n * Projections enable separation of read-model concerns from command handling.\n * Each `.on({ Event }).do(handler)` call registers a handler that updates\n * a projection (database table, cache, etc.) in response to events.\n *\n * Pass a target stream name to `projection(\"target\")` so every handler\n * inherits that resolver automatically. Omit it and use per-handler\n * `.to()` when handlers route to different streams.\n *\n * @param target - Optional default target stream for all handlers\n *\n * @example Default target (all handlers routed to \"tickets\")\n * ```typescript\n * const TicketProjection = projection(\"tickets\")\n * .on({ TicketOpened })\n * .do(async ({ stream, data }) => {\n * await db.insert(tickets).values({ id: stream, ...data });\n * })\n * .on({ TicketClosed })\n * .do(async ({ stream, data }) => {\n * await db.update(tickets).set(data).where(eq(tickets.id, stream));\n * })\n * .build();\n * ```\n *\n * @example Per-handler routing\n * ```typescript\n * const MultiProjection = projection()\n * .on({ OrderPlaced })\n * .do(async (event) => { ... })\n * .to(\"orders\")\n * .on({ PaymentReceived })\n * .do(async (event) => { ... })\n * .to(\"payments\")\n * .build();\n * ```\n *\n * @see {@link ProjectionBuilder} for builder methods\n * @see {@link Projection} for the output type\n */\n/**\n * @internal Build the core builder object (shared between overloads). One\n * mutable `events` register threaded through every fluent call; .on()\n * mutates and returns the same builder cast to its widened generic.\n */\nfunction _projection<\n TEvents extends Schemas,\n TTarget extends string | undefined,\n>(target: TTarget): ProjectionBuilder<TEvents, TTarget> {\n const events = {} as EventRegister<TEvents>;\n const defaultResolver: { target: string } | undefined =\n typeof target === \"string\" ? { target } : undefined;\n\n // Mutable runtime bag — typed loosely; the public projection() return\n // type narrows back to the user-facing `ProjectionBuilder<TEvents, TTarget>`.\n\n const base: any = {\n on: <TKey extends string, TData extends Schema>(\n entry: EventEntry<TKey, TData>\n ) => {\n const keys = Object.keys(entry);\n if (keys.length !== 1) throw new Error(\".on() requires exactly one key\");\n const event = keys[0] as TKey;\n const schema = entry[event];\n\n // Register the event schema if not already present\n if (!(event in events)) {\n (events as Record<string, unknown>)[event] = {\n schema,\n reactions: new Map(),\n };\n }\n\n return {\n do: (\n handler: (\n event: Committed<TEvents & { [P in TKey]: TData }, TKey>,\n stream: string\n ) => Promise<void>\n ) => {\n const reaction: Reaction<TEvents & { [P in TKey]: TData }, TKey> = {\n handler: handler,\n resolver: defaultResolver ?? _this_,\n options: {\n blockOnError: true,\n maxRetries: 3,\n },\n };\n const register = (events as Record<string, any>)[event];\n if (!handler.name)\n throw new Error(\n `Projection handler for \"${event}\" must be a named function`\n );\n register.reactions.set(handler.name, reaction);\n\n // Same builder, widened generic — no recursive call.\n const widened = base as unknown as ProjectionBuilder<\n TEvents & { [P in TKey]: TData },\n TTarget\n >;\n return Object.assign(widened, {\n to(\n resolver:\n | ReactionResolver<TEvents & { [P in TKey]: TData }, TKey>\n | string\n ) {\n // Patch the same reaction in place — no second Map.set().\n reaction.resolver =\n typeof resolver === \"string\" ? { target: resolver } : resolver;\n return widened;\n },\n });\n },\n };\n },\n build: () => ({\n _tag: \"Projection\" as const,\n events,\n ...(target !== undefined && { target }),\n }),\n events,\n };\n\n // Add .batch() only for static-target projections\n if (typeof target === \"string\") {\n return Object.assign(base, {\n batch: (handler: BatchHandler<TEvents>) => ({\n build: () => ({\n _tag: \"Projection\" as const,\n events,\n target,\n batchHandler: handler,\n }),\n }),\n }) as ProjectionBuilder<TEvents, TTarget>;\n }\n\n return base as ProjectionBuilder<TEvents, TTarget>;\n}\n\n/**\n * Creates a new projection builder with a static target stream.\n *\n * All handlers inherit the target resolver automatically. Enables `.batch()`\n * for bulk event processing in a single transaction.\n *\n * @param target - Static target stream for all handlers\n */\nexport function projection<TEvents extends Schemas = {}>(\n target: string\n): ProjectionBuilder<TEvents, string>;\n/**\n * Creates a new projection builder without a default target.\n *\n * Use per-handler `.to()` to route events to different streams.\n */\nexport function projection<TEvents extends Schemas = {}>(\n target?: undefined\n): ProjectionBuilder<TEvents, undefined>;\nexport function projection<TEvents extends Schemas = {}>(\n target?: string\n): ProjectionBuilder<TEvents, string | undefined> {\n return _projection<TEvents, string | undefined>(target);\n}\n","/**\n * @module slice-builder\n * @category Builders\n *\n * Fluent builder for composing partial states with scoped reactions into\n * self-contained functional slices (vertical slice architecture).\n */\nimport { _this_, registerState } from \"../internal/index.js\";\nimport { DEFAULT_LANE } from \"../ports.js\";\nimport type {\n Actor,\n Committed,\n EventRegister,\n IAct,\n LaneConfig,\n Reaction,\n ReactionOptions,\n ReactionResolver,\n Schema,\n SchemaRegister,\n Schemas,\n Snapshot,\n State,\n} from \"../types/index.js\";\nimport type { Projection } from \"./projection-builder.js\";\n\n/**\n * A self-contained functional slice grouping partial states with their\n * scoped reactions. Slices are composed into an Act orchestrator via\n * `act().withSlice(slice)`.\n *\n * @template TSchemaReg - Schema register for states\n * @template TEvents - Event schemas from this slice's states\n * @template TActions - Action schemas from this slice's states\n * @template TStateMap - Map of state names to state schemas\n * @template TActor - Actor type extending base Actor\n */\nexport type Slice<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n TLanes extends string = typeof DEFAULT_LANE,\n> = {\n readonly _tag: \"Slice\";\n readonly states: Map<string, State<any, any, any>>;\n readonly events: EventRegister<TEvents>;\n readonly projections: ReadonlyArray<Projection<any>>;\n /**\n * Drain lanes declared on this slice via `.withLane(...)` (ACT-1103).\n * `act().withSlice(slice)` merges these into the Act's lane set so\n * `.to({lane})` is statically checked at the slice's call site against\n * the lanes the slice itself declared.\n */\n readonly lanes: ReadonlyArray<LaneConfig>;\n /** @internal phantom field for type-level state schema tracking */\n readonly _S?: TSchemaReg;\n /** @internal phantom field for type-level state name tracking */\n readonly _M?: TStateMap;\n /** @internal phantom field for type-level actor tracking */\n readonly _TActor?: TActor;\n /** @internal phantom field for type-level lane union tracking */\n readonly _TLanes?: TLanes;\n};\n\n/**\n * Fluent builder interface for composing functional slices.\n *\n * Provides a chainable API for registering states and projections,\n * and defining reactions scoped to the slice's own events.\n *\n * @template TSchemaReg - Schema register for states\n * @template TEvents - Event schemas\n * @template TActions - Action schemas\n * @template TStateMap - Map of state names to state schemas\n * @template TActor - Actor type extending base Actor\n */\nexport type SliceBuilder<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n TLanes extends string = typeof DEFAULT_LANE,\n> = {\n /**\n * Registers a state definition with the slice.\n *\n * Include every state whose actions your reaction handlers need to\n * dispatch. Duplicate registrations (same state in multiple slices)\n * are handled automatically at composition time.\n */\n withState: <\n TNewState extends Schema,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n TNewName extends string = string,\n >(\n state: State<TNewState, TNewEvents, TNewActions, TNewName>\n ) => SliceBuilder<\n TSchemaReg & { [K in keyof TNewActions]: TNewState },\n TEvents & TNewEvents,\n TActions & TNewActions,\n TStateMap & { [K in TNewName]: TNewState },\n TActor,\n TLanes\n >;\n /**\n * Embeds a built Projection within this slice. The projection's events\n * must be a subset of events from states already registered via\n * `.withState()`. Projection handlers preserve their `(event, stream)`\n * signature and do not receive the app interface.\n */\n withProjection: <TNewEvents extends Schemas>(\n projection: [Exclude<keyof TNewEvents, keyof TEvents>] extends [never]\n ? Projection<TNewEvents>\n : never\n ) => SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\n /**\n * Declares a drain lane on this slice (ACT-1103). Merged into the\n * parent Act's lane set by `act().withSlice(slice)`.\n */\n withLane: <const TConfig extends LaneConfig>(\n config: TConfig\n ) => SliceBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes | TConfig[\"name\"]\n >;\n /**\n * Begins defining a reaction scoped to this slice's events.\n */\n on: <TKey extends keyof TEvents>(\n event: TKey\n ) => {\n do: (\n handler: (\n event: Committed<TEvents, TKey>,\n stream: string,\n app: IAct<TEvents, TActions, TActor>\n ) => Promise<Snapshot<Schema, TEvents> | void>,\n options?: Partial<ReactionOptions>\n ) => SliceBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes\n > & {\n to: (\n resolver: ReactionResolver<TEvents, TKey, TLanes> | string\n ) => SliceBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor,\n TLanes\n >;\n };\n };\n /**\n * Builds and returns the Slice data structure.\n */\n build: () => Slice<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\n /**\n * The registered event schemas and their reaction maps.\n */\n readonly events: EventRegister<TEvents>;\n};\n\n/* eslint-disable @typescript-eslint/no-empty-object-type -- {} used as generic defaults */\n\n/**\n * Creates a new slice builder for composing partial states with scoped reactions.\n *\n * Slices enable vertical slice architecture by grouping related states and\n * reactions into self-contained feature modules. Reactions defined in a slice\n * are type-scoped to events from that slice's states only.\n *\n * @example Single-state slice with typed dispatch\n * ```typescript\n * const CounterSlice = slice()\n * .withState(Counter)\n * .on(\"Incremented\")\n * .do(async (event, _stream, app) => {\n * await app.do(\"reset\", target, {});\n * })\n * .to(\"counter-target\")\n * .build();\n * ```\n *\n * @example Cross-state dispatch (include both states)\n * ```typescript\n * const CreationSlice = slice()\n * .withState(TicketCreation)\n * .withState(TicketOperations) // handler can dispatch AssignTicket\n * .on(\"TicketOpened\").do(async (event, _stream, app) => {\n * await app.do(\"AssignTicket\", target, payload, event);\n * })\n * .build();\n * ```\n *\n * @see {@link SliceBuilder} for builder methods\n * @see {@link Slice} for the output type\n */\nexport function slice<\n // @ts-expect-error empty schema\n TSchemaReg extends SchemaRegister<TActions> = {},\n TEvents extends Schemas = {},\n TActions extends Schemas = {},\n TStateMap extends Record<string, Schema> = {},\n TActor extends Actor = Actor,\n>(): SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor> {\n // One mutable state shared across the entire fluent chain. Each\n // `withState` / `withProjection` / `on` call mutates these and returns\n // the same builder cast to the widened generic; type fanout is preserved\n // through the public type signatures, runtime allocation is not.\n const states = new Map<string, State<any, any, any>>();\n const actions: Record<string, any> = {};\n const events = {} as EventRegister<TEvents>;\n const projections: Projection<any>[] = [];\n const lanes: LaneConfig[] = [];\n\n const builder: SliceBuilder<\n TSchemaReg,\n TEvents,\n TActions,\n TStateMap,\n TActor\n > = {\n withState: (state) => {\n registerState(state, states, actions, events as Record<string, unknown>);\n return builder as never;\n },\n withProjection: (proj) => {\n projections.push(proj as Projection<any>);\n return builder;\n },\n withLane: (config) => {\n if (config.name === DEFAULT_LANE)\n throw new Error(`Lane \"${DEFAULT_LANE}\" is reserved`);\n if (lanes.some((l) => l.name === config.name))\n throw new Error(`Lane \"${config.name}\" was already declared`);\n lanes.push(config);\n return builder as never;\n },\n on: <TKey extends keyof TEvents>(event: TKey) => ({\n do: (\n handler: (\n event: Committed<TEvents, TKey>,\n stream: string,\n app: IAct<TEvents, TActions, TActor>\n ) => Promise<Snapshot<Schema, TEvents> | void>,\n options?: Partial<ReactionOptions>\n ) => {\n const reaction: Reaction<TEvents, TKey, TActions, TActor> = {\n handler: handler,\n resolver: _this_,\n options: {\n blockOnError: options?.blockOnError ?? true,\n maxRetries: options?.maxRetries ?? 3,\n backoff: options?.backoff,\n },\n };\n if (!handler.name)\n throw new Error(\n `Reaction handler for \"${String(event)}\" must be a named function`\n );\n // Register once with the default _this_ resolver. If `.to()` is\n // chained next, it patches the same reaction's resolver in place\n // — no second Map.set() round-trip.\n events[event].reactions.set(handler.name, reaction);\n return Object.assign(builder, {\n to(resolver: ReactionResolver<TEvents, TKey> | string) {\n reaction.resolver =\n typeof resolver === \"string\" ? { target: resolver } : resolver;\n return builder;\n },\n });\n },\n }),\n build: () => ({\n _tag: \"Slice\" as const,\n states,\n events,\n projections,\n lanes,\n }),\n events,\n };\n return builder;\n}\n","/**\n * @module state-builder\n * @category Builders\n *\n * Fluent interface for defining a strongly-typed state machine using Zod schemas.\n */\nimport type { ZodType } from \"zod\";\nimport type {\n ActionHandler,\n GivenHandlers,\n Invariant,\n PassthroughPatchHandler,\n PatchHandlers,\n Schema,\n Schemas,\n Snapshot,\n State,\n ZodTypes,\n} from \"../types/index.js\";\n\n/**\n * Builder interface for defining a state with event sourcing.\n *\n * Provides a fluent API to configure the initial state, event types,\n * and event handlers (reducers) before moving to action configuration.\n *\n * @template TState - State schema type\n * @template TName - State name literal type\n *\n * @see {@link state} for usage examples\n * @see {@link ActionBuilder} for action configuration\n */\nexport type StateBuilder<\n TState extends Schema,\n TName extends string = string,\n> = {\n /**\n * Defines the initial state for new state instances.\n *\n * The init function is called when a new stream is created (first event).\n * It can accept initial data or return a default state.\n *\n * @param init - Function returning the initial state\n * @returns A builder with `.emits()` to declare event types\n *\n * @example\n * ```typescript\n * .init(() => ({ count: 0, created: new Date() }))\n * ```\n *\n * @example With initial data\n * ```typescript\n * .init((data) => ({ ...data, createdAt: new Date() }))\n * ```\n */\n init: (init: () => Readonly<TState>) => {\n /**\n * Declares the event types that this state can emit.\n *\n * Events represent facts that have happened - they should be named in past tense.\n * Each event is defined with a Zod schema for type safety and runtime validation.\n *\n * @template TEvents - Event schemas type\n * @param events - Object mapping event names to Zod schemas\n * @returns An ActionBuilder (with optional `.patch()` to override specific reducers)\n *\n * @example\n * ```typescript\n * .emits({\n * Incremented: z.object({ amount: z.number() }),\n * Decremented: z.object({ amount: z.number() }),\n * Reset: z.object({})\n * })\n * ```\n */\n emits: <TEvents extends Schemas>(\n events: ZodTypes<TEvents>\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- {} avoids string index signature that Record<string, never> would add, keeping keyof A precise\n ) => ActionBuilder<TState, TEvents, {}, TName> & {\n /**\n * Overrides specific event reducers. Events without a custom patch\n * default to passthrough: `({ data }) => data` (event data merges\n * into state).\n *\n * @param patch - Partial map of event names to patch handler functions\n * @returns An ActionBuilder for defining actions\n *\n * @example Only override the events that need custom logic\n * ```typescript\n * .emits({ TicketOpened, TicketClosed, TicketResolved })\n * .patch({\n * TicketOpened: ({ data }) => {\n * const { message, messageId, userId, ...other } = data;\n * return { ...other, userId, messages: { [messageId]: { ... } } };\n * },\n * })\n * // TicketClosed and TicketResolved use passthrough\n * ```\n */\n patch: (\n patch: Partial<PatchHandlers<TState, TEvents>>\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- {} avoids string index signature that Record<string, never> would add, keeping keyof A precise\n ) => ActionBuilder<TState, TEvents, {}, TName>;\n };\n };\n};\n\n/** Helper: a single-key record mapping a state name to its Zod schema. */\ntype StateEntry<\n TKey extends string = string,\n TState extends Schema = Schema,\n> = {\n [P in TKey]: ZodType<TState>;\n};\n\n/** Helper: a single-key record mapping an action name to its Zod schema. */\ntype ActionEntry<\n TKey extends string = string,\n TNewActions extends Schema = Schema,\n> = {\n [P in TKey]: ZodType<TNewActions>;\n};\n\n/**\n * Builder interface for defining actions (commands) on a state.\n *\n * Actions represent user/system intents to modify state. Each action is validated\n * against a schema, can have business rule invariants, and must emit one or more events.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TName - State name literal type\n *\n * @see {@link state} for complete usage examples\n */\nexport type ActionBuilder<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TName extends string = string,\n> = {\n /**\n * Defines an action (command) that can be executed on this state.\n *\n * Actions represent intents to change state - they should be named in imperative form\n * (e.g., \"CreateUser\", \"IncrementCounter\", \"PlaceOrder\"). Actions are validated against\n * their schema and must emit at least one event.\n *\n * Pass a `{ ActionName: schema }` record — use shorthand `{ ActionName }`\n * when the variable name matches the action name. The key becomes the\n * action name, the value the Zod schema.\n *\n * @template TKey - Action name (string literal type)\n * @template TNewActions - Action payload schema type\n * @param entry - Single-key record `{ ActionName: schema }`\n * @returns An object with `.given()` and `.emit()` for further configuration\n *\n * @example Simple action without invariants\n * ```typescript\n * .on({ increment: z.object({ by: z.number() }) })\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * ```\n *\n * @example Action with business rules\n * ```typescript\n * .on({ withdraw: z.object({ amount: z.number() }) })\n * .given([\n * (_, snap) => snap.state.balance >= 0 || \"Account closed\",\n * (_, snap, action) => snap.state.balance >= action.amount || \"Insufficient funds\"\n * ])\n * .emit((action) => [\"Withdrawn\", { amount: action.amount }])\n * ```\n *\n * @example Action with shorthand (variable name matches action name)\n * ```typescript\n * const OpenTicket = z.object({ title: z.string() });\n * .on({ OpenTicket })\n * .emit((action) => [\"TicketOpened\", { title: action.title }])\n * ```\n */\n on: <TKey extends string, TNewActions extends Schema>(\n entry: ActionEntry<TKey, TNewActions>\n ) => {\n /**\n * Adds business rule invariants that must hold before the action can execute.\n *\n * Invariants are checked after loading the current state but before emitting events.\n * Each invariant should return `true` or an error message string. All invariants\n * must pass for the action to succeed.\n *\n * @param rules - Array of invariant functions\n * @returns An object with `.emit()` to finalize the action\n *\n * @example\n * ```typescript\n * .given([\n * (_, snap) => snap.state.status === \"active\" || \"Must be active\",\n * (target, snap) => snap.state.ownerId === target.actor.id || \"Not authorized\"\n * ])\n * ```\n */\n given: (rules: Invariant<TState>[]) => {\n /**\n * Defines the action handler that emits events.\n *\n * The handler receives the action payload and current state snapshot,\n * and must return one or more events to emit. Events are applied to state\n * via the patch handlers defined earlier.\n *\n * Pass a string event name for passthrough: the action payload becomes\n * the event data directly.\n *\n * @param handler - Function that returns events to emit, or event name string for passthrough\n * @returns The ActionBuilder for chaining more actions\n *\n * @example Custom handler\n * ```typescript\n * .emit((action, snapshot) => {\n * const newBalance = snapshot.state.balance + action.amount;\n * return [\"Deposited\", { amount: action.amount, newBalance }];\n * })\n * ```\n *\n * @example Passthrough (action payload = event data)\n * ```typescript\n * .emit(\"TicketAssigned\")\n * ```\n */\n emit: {\n /** Custom handler — receives `(action, snapshot)` and returns one\n * or more `[EventName, data]` tuples (or `undefined`). */\n (\n handler: ActionHandler<\n TState,\n TEvents,\n { [P in TKey]: TNewActions },\n TKey\n >\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName\n >;\n /** Passthrough — the action payload becomes the event data\n * directly. Must reference an event declared in `.emits()`. */\n (\n eventName: keyof TEvents & string\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName\n >;\n };\n };\n /**\n * Defines the action handler that emits events. Same two overloads as\n * the post-`.given()` form above:\n *\n * - **Function** — receives `(action, snapshot)` and returns one or\n * more `[EventName, data]` tuples (or `undefined`).\n * - **String** — passthrough: the action payload becomes the event\n * data directly. Must reference an event declared in `.emits()`.\n *\n * The two overloads are kept separate (rather than merged into a\n * `handler | string` union) so that TS contextual typing of the\n * function alternative isn't degraded by considering the string\n * branch — under the union form `TState` could collapse to its\n * `Schema` constraint inside the callback.\n *\n * @example Passthrough (action payload = event data)\n * ```typescript\n * .emit(\"Incremented\")\n * ```\n *\n * @example Single event\n * ```typescript\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * ```\n *\n * @example Multiple events\n * ```typescript\n * .emit((action) => [\n * [\"Incremented\", { amount: action.by }],\n * [\"LogUpdated\", { message: `Incremented by ${action.by}` }]\n * ])\n * ```\n */\n emit: {\n (\n handler: ActionHandler<\n TState,\n TEvents,\n { [P in TKey]: TNewActions },\n TKey\n >\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName\n >;\n (\n eventName: keyof TEvents & string\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName\n >;\n };\n };\n /**\n * Defines a snapshotting strategy to optimize state reconstruction.\n *\n * Snapshots store the current state at a point in time, allowing faster state loading\n * by avoiding replaying all events from the beginning. The snap function is called\n * after each event is applied and should return `true` when a snapshot should be taken.\n *\n * @param snap - Predicate function that returns true when a snapshot should be taken\n * @returns The ActionBuilder for chaining\n *\n * @example Snapshot every 10 events\n * ```typescript\n * .snap((snapshot) => snapshot.patches >= 10)\n * ```\n *\n * @example Snapshot based on state size\n * ```typescript\n * .snap((snapshot) => {\n * const estimatedSize = JSON.stringify(snapshot.state).length;\n * return estimatedSize > 10000 || snapshot.patches >= 50;\n * })\n * ```\n *\n * @example Time-based snapshotting\n * ```typescript\n * .snap((snapshot) => {\n * const hoursSinceLastSnapshot = snapshot.patches * 0.1; // Estimate\n * return hoursSinceLastSnapshot >= 24;\n * })\n * ```\n */\n snap: (\n snap: (snapshot: Snapshot<TState, TEvents>) => boolean\n ) => ActionBuilder<TState, TEvents, TActions, TName>;\n /**\n * Finalizes and builds the state definition.\n *\n * Call this method after defining all actions, invariants, and patches to create\n * the complete State object that can be registered with Act.\n *\n * @returns The complete strongly-typed State definition\n *\n * @example\n * ```typescript\n * const Counter = state({ Counter: schema })\n * .init(() => ({ count: 0 }))\n * .emits({ Incremented: z.object({ amount: z.number() }) })\n * .patch({ Incremented: ({ data }, state) => ({ count: state.count + data.amount }) })\n * .on({ increment: z.object({ by: z.number() }) })\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * .build(); // Returns State<TState, TEvents, TActions, TName>\n * ```\n */\n build: () => State<TState, TEvents, TActions, TName>;\n};\n\n/**\n * Creates a new state definition with event sourcing capabilities.\n *\n * States are the core building blocks of Act. Each state represents a consistency\n * boundary (aggregate) that processes actions, emits events, and maintains its own\n * state through event patches (reducers). States use event sourcing to maintain a\n * complete audit trail and enable time-travel capabilities.\n *\n * The state builder provides a fluent API for defining:\n * 1. Initial state via `.init()`\n * 2. Event types via `.emits()` — all events default to passthrough (`({ data }) => data`)\n * 3. Custom event reducers via `.patch()` (optional — only for events that need custom logic)\n * 4. Actions (commands) via `.on()` → `.emit()` — pass an event name string for passthrough\n * 5. Business rules (invariants) via `.given()`\n * 6. Snapshotting strategy via `.snap()`\n *\n * @template TState - Zod schema type defining the shape of the state\n * @param entry - Single-key record mapping state name to Zod schema (e.g., `{ Counter: z.object({ count: z.number() }) }`)\n * @returns A StateBuilder instance for fluent API configuration\n *\n * @example Basic counter state (with custom patch)\n * ```typescript\n * import { state } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const Counter = state({ Counter: z.object({ count: z.number() }) })\n * .init(() => ({ count: 0 }))\n * .emits({\n * Incremented: z.object({ amount: z.number() })\n * })\n * .patch({ // optional — only for events needing custom reducers\n * Incremented: ({ data }, state) => ({ count: state.count + data.amount })\n * })\n * .on({ increment: z.object({ by: z.number() }) })\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * .build();\n * ```\n *\n * @example Passthrough state (no custom patch or emit needed)\n * ```typescript\n * const DigitBoard = state({ DigitBoard: z.object({ digit: z.string() }) })\n * .init(() => ({ digit: \"\" }))\n * .emits({ DigitCounted: z.object({ digit: z.string() }) })\n * // no .patch() — passthrough is the default (event data merges into state)\n * .on({ CountDigit: z.object({ digit: z.string() }) })\n * .emit(\"DigitCounted\") // string passthrough — action payload becomes event data\n * .build();\n * ```\n *\n * @example State with multiple events and invariants\n * ```typescript\n * const BankAccount = state({ BankAccount: z.object({\n * balance: z.number(),\n * currency: z.string(),\n * status: z.enum([\"open\", \"closed\"])\n * }) })\n * .init(() => ({ balance: 0, currency: \"USD\", status: \"open\" }))\n * .emits({\n * Deposited: z.object({ amount: z.number() }),\n * Withdrawn: z.object({ amount: z.number() }),\n * Closed: z.object({})\n * })\n * .patch({ // only override events needing custom logic\n * Deposited: ({ data }, state) => ({ balance: state.balance + data.amount }),\n * Withdrawn: ({ data }, state) => ({ balance: state.balance - data.amount }),\n * Closed: () => ({ status: \"closed\", balance: 0 })\n * })\n * .on({ deposit: z.object({ amount: z.number() }) })\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Account must be open\"\n * ])\n * .emit(\"Deposited\") // passthrough — action payload { amount } becomes event data\n * .on({ withdraw: z.object({ amount: z.number() }) })\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Account must be open\",\n * (_, snap, action) =>\n * snap.state.balance >= action.amount || \"Insufficient funds\"\n * ])\n * .emit(\"Withdrawn\")\n * .on({ close: z.object({}) })\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Already closed\",\n * (_, snap) => snap.state.balance === 0 || \"Balance must be zero\"\n * ])\n * .emit(\"Closed\")\n * .build();\n * ```\n *\n * @example State with snapshotting\n * ```typescript\n * const User = state({ User: z.object({\n * name: z.string(),\n * email: z.string(),\n * loginCount: z.number()\n * }) })\n * .init((data) => ({ ...data, loginCount: 0 }))\n * .emits({\n * UserCreated: z.object({ name: z.string(), email: z.string() }),\n * UserLoggedIn: z.object({})\n * })\n * .patch({ // only override events needing custom logic\n * UserLoggedIn: (_, state) => ({ loginCount: state.loginCount + 1 })\n * })\n * // UserCreated uses passthrough — event data merges into state\n * .on({ createUser: z.object({ name: z.string(), email: z.string() }) })\n * .emit(\"UserCreated\") // passthrough\n * .on({ login: z.object({}) })\n * .emit(\"UserLoggedIn\")\n * .snap((snap) => snap.patches >= 10) // Snapshot every 10 events\n * .build();\n * ```\n *\n * @see {@link StateBuilder} for available builder methods\n * @see {@link ActionBuilder} for action configuration methods\n * @see {@link https://rotorsoft.github.io/act-root/docs/intro | Getting Started Guide}\n * @see {@link https://rotorsoft.github.io/act-root/docs/examples/calculator | Calculator Example}\n */\nexport function state<TName extends string, TState extends Schema>(\n entry: StateEntry<TName, TState>\n): StateBuilder<TState, TName> {\n const keys = Object.keys(entry);\n if (keys.length !== 1) throw new Error(\"state() requires exactly one key\");\n const name = keys[0] as TName;\n const stateSchema = (entry as Record<string, ZodType<TState>>)[name];\n return {\n init(init) {\n return {\n emits<TEvents extends Schema>(events: ZodTypes<TEvents>) {\n // Default passthrough patches: event data merges into state\n const defaultPatch = Object.fromEntries(\n Object.keys(events).map((k) => {\n const fn = Object.assign(({ data }: { data: any }) => data, {\n _passthrough: true as const,\n }) satisfies PassthroughPatchHandler;\n return [k, fn];\n })\n ) as unknown as PatchHandlers<TState, TEvents>;\n\n // Build one mutable state object the action_builder threads\n // through every fluent call. patch() (if invoked) just mutates\n // the patch map in place — no re-builder wasted.\n const internal: State<TState, TEvents, Schemas, TName> = {\n events,\n actions: {},\n state: stateSchema,\n name,\n init,\n patch: defaultPatch,\n on: {},\n };\n\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- {} avoids string index signature\n const builder = action_builder<TState, TEvents, {}, TName>(internal);\n\n return Object.assign(builder, {\n patch(customPatch: Partial<PatchHandlers<TState, TEvents>>) {\n Object.assign(internal.patch, customPatch);\n return builder;\n },\n });\n },\n };\n },\n };\n}\n\n/**\n * Internal action-builder. The runtime object is a single mutable bag —\n * each fluent call (`on`, `snap`) mutates it and returns the same builder\n * cast to the widened generic type. Type-level fanout is preserved; the\n * O(N) `{...state}` spreads per call are not.\n *\n * Generics are erased to `Schemas` at runtime — the cast on return narrows\n * back to the call-site's widened types.\n */\nfunction action_builder<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TName extends string = string,\n>(\n state: State<TState, TEvents, TActions, TName>\n): ActionBuilder<TState, TEvents, TActions, TName> {\n // The mutable bag — typed loosely since callers narrow on return.\n const internal = state as unknown as State<TState, TEvents, Schemas, TName>;\n\n const builder: ActionBuilder<TState, TEvents, TActions, TName> = {\n on<TKey extends string, TNewActions extends Schema>(\n entry: ActionEntry<TKey, TNewActions>\n ) {\n const keys = Object.keys(entry);\n if (keys.length !== 1) throw new Error(\".on() requires exactly one key\");\n const action = keys[0] as TKey;\n const schema = entry[action];\n\n if (action in internal.actions)\n throw new Error(`Duplicate action \"${action}\"`);\n\n type MergedActions = TActions & { [P in TKey]: TNewActions };\n (internal.actions as Record<string, ZodType<Schema>>)[action] = schema;\n\n function given(rules: Invariant<TState>[]) {\n internal.given ??= {} as GivenHandlers<TState, Schemas>;\n (internal.given as Record<string, Invariant<TState>[]>)[action] = rules;\n return { emit };\n }\n\n function emit(\n handler:\n | ActionHandler<TState, TEvents, MergedActions, TKey>\n | (keyof TEvents & string)\n ) {\n if (typeof handler === \"string\") {\n const eventName = handler;\n // Tag the synthetic function with the static event name so\n // the act-builder can detect emissions of deprecated events\n // at build time (ACT-403). Dynamic forms — where the\n // returned event name is computed inside the user's\n // function — can't be inspected statically; they're caught\n // by the runtime warning in event-sourcing.ts.\n const emitFn = Object.assign((payload: any) => [eventName, payload], {\n _staticEmit: eventName,\n });\n (internal.on as Record<string, unknown>)[action] = emitFn;\n } else {\n (internal.on as Record<string, unknown>)[action] = handler;\n }\n return builder as unknown as ActionBuilder<\n TState,\n TEvents,\n MergedActions,\n TName\n >;\n }\n\n return { given, emit };\n },\n\n snap(snap: (snapshot: Snapshot<TState, TEvents>) => boolean) {\n internal.snap = snap;\n return builder;\n },\n\n build(): State<TState, TEvents, TActions, TName> {\n return internal as unknown as State<TState, TEvents, TActions, TName>;\n },\n };\n return builder;\n}\n","/**\n * @module csv\n *\n * `CsvFile` — a single class implementing both {@link EventSource}\n * and {@link EventSink} so a CSV file on disk can be either side of\n * a transfer pipeline (ACT-1128 / #788).\n *\n * - As a source: streams one row at a time off a line interface;\n * the awaited per-event callback gives 1-event-in-flight\n * backpressure on reads.\n * - As a sink: serialized `WriteStream.write` await per row,\n * propagating I/O errors through the chunk callback.\n *\n * `commit` / `claim` / `subscribe` and the rest of `Store` are NOT\n * implemented — `CsvFile` is a transfer-only primitive, not a\n * store you'd run an Act app against.\n */\n\nimport { createReadStream, createWriteStream, type WriteStream } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport type {\n Committed,\n EventSink,\n EventSource,\n Query,\n Schemas,\n} from \"./types/action.js\";\n\n/**\n * Construct a {@link CsvFile} from either a filesystem path (for\n * reading and/or writing through the OS) or an in-memory blob (a\n * pre-loaded CSV string, used by the inspector when a CSV arrives\n * over the wire via tRPC).\n *\n * Both modes share the same on-disk format, so the same blob shape\n * can be round-tripped through the transfer pipeline.\n */\nexport type CsvFileOptions = { path: string } | { blob: string };\n\n/**\n * Same column order as the inspector's backup endpoint, kept here\n * so `CsvFile` is round-trip-compatible with existing backups.\n */\nconst CSV_COLUMNS = [\n \"id\",\n \"name\",\n \"data\",\n \"stream\",\n \"version\",\n \"created\",\n \"meta\",\n] as const;\n\nexport class CsvFile implements EventSource, EventSink {\n private readonly path: string | null;\n private readonly blob: string | null;\n\n constructor(options: CsvFileOptions) {\n if (\"path\" in options) {\n this.path = options.path;\n this.blob = null;\n } else {\n this.path = null;\n this.blob = options.blob;\n }\n }\n\n async query<E extends Schemas>(\n callback: (event: Committed<E, keyof E>) => void,\n _filter?: Query\n ): Promise<number> {\n const lines =\n this.blob !== null ? linesFromBlob(this.blob) : linesFromFile(this.path!);\n let count = 0;\n let header: readonly string[] | null = null;\n for await (const line of lines) {\n if (!line.trim()) continue;\n const fields = parseCsvLine(line);\n if (!header) {\n header = fields;\n const expected = CSV_COLUMNS.join(\",\");\n if (header.join(\",\") !== expected)\n throw new Error(`Invalid CSV header. Expected: ${expected}`);\n continue;\n }\n if (fields.length !== CSV_COLUMNS.length)\n throw new Error(\n `Row ${count + 1}: expected ${CSV_COLUMNS.length} fields, got ${fields.length}`\n );\n const event: Committed<E, keyof E> = {\n id: Number.parseInt(fields[0]!, 10),\n name: fields[1]! as keyof E,\n data: JSON.parse(fields[2]!),\n stream: fields[3]!,\n version: Number.parseInt(fields[4]!, 10),\n created: new Date(fields[5]!),\n meta: JSON.parse(fields[6]!),\n };\n await Promise.resolve(callback(event));\n count++;\n }\n if (header === null)\n throw new Error(\"CSV must have a header and at least one row\");\n return count;\n }\n\n async restore(\n driver: (\n callback: (event: Committed<Schemas, keyof Schemas>) => Promise<number>\n ) => Promise<void>\n ): Promise<void> {\n if (this.path === null)\n throw new Error(\n \"CsvFile in blob mode is read-only — provide `path` to write\"\n );\n const writer = createWriteStream(this.path, {\n flags: \"w\",\n encoding: \"utf8\",\n });\n let nextId = 1;\n try {\n await writeLine(writer, CSV_COLUMNS.join(\",\"));\n await driver(async (event) => {\n const id = nextId++;\n const row = [\n String(id),\n csvEscape(event.name as string),\n csvEscape(JSON.stringify(event.data)),\n csvEscape(event.stream),\n String(event.version),\n event.created.toISOString(),\n csvEscape(JSON.stringify(event.meta)),\n ].join(\",\");\n await writeLine(writer, row);\n return id;\n });\n } finally {\n await new Promise<void>((resolve) => writer.end(resolve));\n }\n }\n\n async dispose(): Promise<void> {\n // No-op: `restore` always closes its writer in a `finally`, and\n // blob mode never opens one. The Disposable contract is here to\n // make `CsvFile` interchangeable with `Store` in transfer\n // pipelines, not because the file handle outlives the call.\n }\n}\n\nasync function* linesFromFile(path: string): AsyncIterable<string> {\n const stream = createReadStream(path, { encoding: \"utf8\" });\n const rl = createInterface({\n input: stream,\n crlfDelay: Number.POSITIVE_INFINITY,\n });\n try {\n for await (const line of rl) yield line;\n } finally {\n rl.close();\n stream.close();\n }\n}\n\nasync function* linesFromBlob(blob: string): AsyncIterable<string> {\n let start = 0;\n while (start < blob.length) {\n const nl = blob.indexOf(\"\\n\", start);\n const end = nl === -1 ? blob.length : nl;\n yield blob.slice(start, end);\n start = nl === -1 ? blob.length : nl + 1;\n await Promise.resolve();\n }\n}\n\nfunction parseCsvLine(line: string): string[] {\n const fields: string[] = [];\n let i = 0;\n while (i < line.length) {\n if (line[i] === '\"') {\n let value = \"\";\n i++;\n while (i < line.length) {\n if (line[i] === '\"' && line[i + 1] === '\"') {\n value += '\"';\n i += 2;\n } else if (line[i] === '\"') {\n i++;\n break;\n } else {\n value += line[i++];\n }\n }\n fields.push(value);\n if (line[i] === \",\") i++;\n } else {\n const next = line.indexOf(\",\", i);\n if (next === -1) {\n fields.push(line.slice(i));\n i = line.length;\n } else {\n fields.push(line.slice(i, next));\n i = next + 1;\n }\n }\n }\n return fields;\n}\n\nfunction csvEscape(value: string): string {\n if (/[\",\\n\\r]/.test(value)) return `\"${value.replace(/\"/g, '\"\"')}\"`;\n return value;\n}\n\nfunction writeLine(writer: WriteStream, line: string): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n writer.write(`${line}\\n`, (err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n}\n"],"mappings":"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","names":["state","deps","tombstone","load","snap","state","state","action","state","action","action","block","state","block","action","action","state","config","state","config","state","action","snap"]}
|