@rotorsoft/act 1.32.26 → 1.32.28

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.
Files changed (57) hide show
  1. package/README.md +2 -3
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/@types/act.d.ts +7 -152
  4. package/dist/@types/act.d.ts.map +1 -1
  5. package/dist/@types/adapters/in-memory-store.d.ts +0 -21
  6. package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
  7. package/dist/@types/builders/act-builder.d.ts +0 -25
  8. package/dist/@types/builders/act-builder.d.ts.map +1 -1
  9. package/dist/@types/builders/build-classify.d.ts +4 -4
  10. package/dist/@types/builders/build-classify.d.ts.map +1 -1
  11. package/dist/@types/builders/projection-builder.d.ts.map +1 -1
  12. package/dist/@types/builders/reaction-builder.d.ts +3 -3
  13. package/dist/@types/builders/reaction-builder.d.ts.map +1 -1
  14. package/dist/@types/builders/slice-builder.d.ts +1 -12
  15. package/dist/@types/builders/slice-builder.d.ts.map +1 -1
  16. package/dist/@types/builders/state-builder.d.ts +0 -189
  17. package/dist/@types/builders/state-builder.d.ts.map +1 -1
  18. package/dist/@types/config.d.ts +0 -27
  19. package/dist/@types/config.d.ts.map +1 -1
  20. package/dist/@types/internal/circuit-breaker.d.ts +2 -0
  21. package/dist/@types/internal/circuit-breaker.d.ts.map +1 -1
  22. package/dist/@types/internal/close-cycle.d.ts +2 -1
  23. package/dist/@types/internal/close-cycle.d.ts.map +1 -1
  24. package/dist/@types/internal/drain-cycle.d.ts +13 -4
  25. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  26. package/dist/@types/internal/index.d.ts +1 -1
  27. package/dist/@types/internal/index.d.ts.map +1 -1
  28. package/dist/@types/internal/settle.d.ts +2 -1
  29. package/dist/@types/internal/settle.d.ts.map +1 -1
  30. package/dist/@types/ports.d.ts +0 -7
  31. package/dist/@types/ports.d.ts.map +1 -1
  32. package/dist/@types/test/sandbox.d.ts +0 -14
  33. package/dist/@types/test/sandbox.d.ts.map +1 -1
  34. package/dist/@types/types/action.d.ts +0 -27
  35. package/dist/@types/types/action.d.ts.map +1 -1
  36. package/dist/@types/types/errors.d.ts +1 -92
  37. package/dist/@types/types/errors.d.ts.map +1 -1
  38. package/dist/@types/types/ports.d.ts +0 -70
  39. package/dist/@types/types/ports.d.ts.map +1 -1
  40. package/dist/@types/types/reaction.d.ts +1 -34
  41. package/dist/@types/types/reaction.d.ts.map +1 -1
  42. package/dist/{chunk-QXW3JV2H.js → chunk-5FXT63KF.js} +2 -2
  43. package/dist/chunk-5FXT63KF.js.map +1 -0
  44. package/dist/{chunk-XSG2NW4J.js → chunk-F7K7SIG6.js} +1 -1
  45. package/dist/chunk-F7K7SIG6.js.map +1 -0
  46. package/dist/index.cjs +83 -215
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.js +85 -217
  49. package/dist/index.js.map +1 -1
  50. package/dist/test/index.cjs.map +1 -1
  51. package/dist/test/index.js +2 -2
  52. package/dist/test/index.js.map +1 -1
  53. package/dist/types/index.cjs.map +1 -1
  54. package/dist/types/index.js +1 -1
  55. package/package.json +1 -4
  56. package/dist/chunk-QXW3JV2H.js.map +0 -1
  57. package/dist/chunk-XSG2NW4J.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/adapters/console-logger.ts","../src/internal/lru-map.ts","../src/adapters/in-memory-cache.ts","../src/types/errors.ts","../src/utils.ts","../src/config.ts","../src/types/schemas.ts","../src/internal/sensitive.ts","../src/types/index.ts","../src/adapters/in-memory-store.ts","../src/disposers.ts","../src/scoped.ts","../src/ports.ts","../src/signals.ts","../src/act.ts","../src/builders/build-classify.ts","../src/internal/event-versions.ts","../src/internal/walk-streams.ts","../src/internal/audit.ts","../src/internal/autoclose-policy.ts","../src/internal/autoclose-window.ts","../src/internal/close-signal.ts","../src/internal/config.ts","../src/internal/defer-signal.ts","../src/internal/autoclose-reaction.ts","../src/internal/backoff.ts","../src/internal/circuit-breaker.ts","../src/internal/close-cycle.ts","../src/internal/correlate-cycle.ts","../src/internal/report-once.ts","../src/internal/correlator.ts","../src/internal/date-reviver.ts","../src/internal/defer-config.ts","../src/internal/drain-cycle.ts","../src/internal/defer-timer.ts","../src/internal/drain-ratio.ts","../src/internal/drain.ts","../src/internal/event-sourcing.ts","../src/internal/tracing.ts","../src/internal/projection-fold.ts","../src/internal/settle.ts","../src/builders/reaction-builder.ts","../src/builders/merge.ts","../src/builders/builder-utils.ts","../src/builders/event-builder.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 \"./signals.js\";\n\n/**\n * @packageDocumentation\n * @module act\n * Main entry point for the Act framework. Re-exports all core APIs.\n */\nexport * from \"./act.js\";\nexport * from \"./adapters/index.js\";\nexport * from \"./builders/index.js\";\nexport * from \"./config.js\";\nexport * from \"./csv.js\";\n// The imperative defer escape hatch: a reaction throws this with a\n// `DeferWhen` (see ./types/action.ts) to hold itself until the resolved\n// due-time. The declarative `.defer(when)` builder step is the common path.\nexport { DeferSignal } from \"./internal/index.js\";\nexport * from \"./ports.js\";\nexport * from \"./types/index.js\";\nexport * from \"./utils.js\";\n","/**\n * @module adapters/console-logger\n *\n * High-performance console logger inspired by pino's design:\n * - Numeric level comparison for O(1) gating\n * - stdout.write() in production for raw JSON lines (no console overhead)\n * - Colorized single-line output in development\n * - No-op method replacement when level is above threshold\n * - Child logger support with merged bindings\n */\nimport type { Logger } from \"../types/index.js\";\n\nconst LEVEL_VALUES: Record<string, number> = {\n fatal: 60,\n error: 50,\n warn: 40,\n info: 30,\n debug: 20,\n trace: 10,\n};\n\nconst LEVEL_COLORS: Record<string, string> = {\n fatal: \"\\x1b[41m\\x1b[37m\", // white on red bg\n error: \"\\x1b[31m\", // red\n warn: \"\\x1b[33m\", // yellow\n info: \"\\x1b[32m\", // green\n debug: \"\\x1b[36m\", // cyan\n trace: \"\\x1b[90m\", // gray\n};\n\nconst RESET = \"\\x1b[0m\";\n\nconst noop = () => {};\n\n/**\n * Default console logger for the Act framework.\n *\n * Production mode emits newline-delimited JSON (compatible with GCP, AWS\n * CloudWatch, Datadog, and other structured log ingestion systems).\n *\n * Development mode emits colorized, human-readable output.\n */\nexport class ConsoleLogger implements Logger {\n level: string;\n private readonly _pretty: boolean;\n\n readonly fatal: Logger[\"fatal\"];\n readonly error: Logger[\"error\"];\n readonly warn: Logger[\"warn\"];\n readonly info: Logger[\"info\"];\n readonly debug: Logger[\"debug\"];\n readonly trace: Logger[\"trace\"];\n\n constructor(\n options: {\n level?: string;\n pretty?: boolean;\n bindings?: Record<string, unknown>;\n } = {}\n ) {\n const {\n level = \"info\",\n pretty = process.env.NODE_ENV !== \"production\",\n bindings,\n } = options;\n this._pretty = pretty;\n this.level = level;\n\n const threshold = LEVEL_VALUES[level] ?? 30;\n const write = pretty\n ? this._pretty_write.bind(this, bindings)\n : this._json_write.bind(this, bindings);\n\n // Assign methods — noop when level is gated (like pino's level-based replacement)\n this.fatal = write.bind(this, \"fatal\", 60); // fatal is always enabled\n this.error = threshold <= 50 ? write.bind(this, \"error\", 50) : noop;\n this.warn = threshold <= 40 ? write.bind(this, \"warn\", 40) : noop;\n this.info = threshold <= 30 ? write.bind(this, \"info\", 30) : noop;\n this.debug = threshold <= 20 ? write.bind(this, \"debug\", 20) : noop;\n this.trace = threshold <= 10 ? write.bind(this, \"trace\", 10) : noop;\n }\n\n /** No-op — `console.log` has no resources to release. */\n async dispose(): Promise<void> {}\n\n /** @inheritDoc */\n child(bindings: Record<string, unknown>): Logger {\n return new ConsoleLogger({\n level: this.level,\n pretty: this._pretty,\n bindings,\n });\n }\n\n private _json_write(\n bindings: Record<string, unknown> | undefined,\n level: string,\n _num: number,\n obj_or_msg: unknown,\n msg?: string\n ): void {\n let obj: Record<string, unknown>;\n let message: string | undefined;\n\n if (typeof obj_or_msg === \"string\") {\n message = obj_or_msg;\n obj = {};\n } else if (obj_or_msg instanceof Error) {\n // Error instances spread to `{}` — capture the salient fields\n // explicitly so structured log aggregators see them.\n message = msg ?? obj_or_msg.message;\n obj = {\n error: { message: obj_or_msg.message, name: obj_or_msg.name },\n stack: obj_or_msg.stack,\n };\n } else if (obj_or_msg !== null && typeof obj_or_msg === \"object\") {\n message = msg;\n obj = { ...(obj_or_msg as Record<string, unknown>) };\n } else {\n message = msg;\n obj = { value: obj_or_msg };\n }\n\n const entry = Object.assign({ level, time: Date.now() }, bindings, obj);\n if (message) entry.msg = message;\n\n let line: string;\n try {\n line = JSON.stringify(entry);\n } catch {\n // Cyclic or unserializable payload — emit a minimal line rather\n // than crash the log call site.\n line = JSON.stringify({\n level,\n time: entry.time,\n msg: message ?? \"[unserializable]\",\n unserializable: true,\n });\n }\n process.stdout.write(line + \"\\n\");\n }\n\n private _pretty_write(\n bindings: Record<string, unknown> | undefined,\n level: string,\n _num: number,\n obj_or_msg: unknown,\n msg?: string\n ): void {\n const color = LEVEL_COLORS[level];\n const tag = `${color}${level.toUpperCase().padEnd(5)}${RESET}`;\n const ts = new Date().toISOString().slice(11, 23); // HH:mm:ss.SSS\n\n let message: string;\n let data: string | undefined;\n\n if (typeof obj_or_msg === \"string\") {\n message = obj_or_msg;\n } else if (obj_or_msg instanceof Error) {\n // Error instances don't serialize their `message`/`stack` via\n // JSON.stringify — `JSON.stringify(err) === \"{}\"`. Render the\n // message inline and the stack as the data payload so operators\n // see something useful instead of an empty object.\n message = msg ?? obj_or_msg.message;\n data = obj_or_msg.stack;\n } else {\n message = msg ?? \"\";\n if (obj_or_msg !== undefined && obj_or_msg !== null) {\n try {\n data = JSON.stringify(obj_or_msg);\n } catch {\n data = \"[unserializable]\";\n }\n }\n }\n\n const bind_str =\n bindings && Object.keys(bindings).length\n ? ` ${JSON.stringify(bindings)}`\n : \"\";\n\n const parts = [ts, tag, message, data, bind_str].filter(Boolean);\n process.stdout.write(parts.join(\" \") + \"\\n\");\n }\n}\n","/**\n * @module lru-map\n * @category Internal\n *\n * Tiny bounded LRU map / set built on insertion-ordered `Map`. Used to cap\n * memory in long-running orchestrators that mint large numbers of keys —\n * notably:\n *\n * - {@link InMemoryCache}: stream → state checkpoint\n * - `Act._subscribed_streams`: stream → presence (LruSet)\n *\n * Apps with millions of dynamic streams (one target per aggregate) can't\n * afford an unbounded `Set<string>` — eviction is required.\n *\n * @internal\n */\n\n/**\n * Bounded LRU map. `get()` promotes; `has()` does not. `set()` always\n * promotes and evicts the oldest entry when at capacity.\n *\n * @internal\n */\nexport class LruMap<K, V> {\n private readonly _entries = new Map<K, V>();\n private readonly _max_size: number;\n\n constructor(maxSize: number) {\n this._max_size = maxSize;\n }\n\n get(key: K): V | undefined {\n const v = this._entries.get(key);\n if (v === undefined) return undefined;\n // promote: delete + re-insert moves to most-recent position\n this._entries.delete(key);\n this._entries.set(key, v);\n return v;\n }\n\n has(key: K): boolean {\n return this._entries.has(key);\n }\n\n set(key: K, value: V): void {\n this._entries.delete(key);\n if (this._entries.size >= this._max_size) {\n // size >= maxSize ≥ 1 → at least one entry exists → next().value\n // is the oldest key (asserted with `!`).\n const oldest = this._entries.keys().next().value!;\n this._entries.delete(oldest);\n }\n this._entries.set(key, value);\n }\n\n delete(key: K): boolean {\n return this._entries.delete(key);\n }\n\n clear(): void {\n this._entries.clear();\n }\n\n get size(): number {\n return this._entries.size;\n }\n}\n\n/**\n * Bounded LRU set built on top of {@link LruMap}. `has()` does not promote;\n * `add()` does (re-inserting if already present, evicting the oldest at\n * capacity).\n *\n * @internal\n */\nexport class LruSet<T> {\n private readonly _map: LruMap<T, true>;\n\n constructor(maxSize: number) {\n this._map = new LruMap(maxSize);\n }\n\n has(value: T): boolean {\n return this._map.has(value);\n }\n\n add(value: T): void {\n this._map.set(value, true);\n }\n\n delete(value: T): boolean {\n return this._map.delete(value);\n }\n\n clear(): void {\n this._map.clear();\n }\n\n get size(): number {\n return this._map.size;\n }\n}\n","import { LruMap } from \"../internal/lru-map.js\";\nimport type { Cache, CacheEntry, Schema } from \"../types/index.js\";\n\n/**\n * In-memory LRU cache for stream snapshots.\n *\n * Backed by an internal `LruMap` for O(1) get/set with LRU eviction.\n * Configurable `maxSize` bounds memory usage.\n *\n * @example\n * ```typescript\n * import { cache } from \"@rotorsoft/act\";\n * import { InMemoryCache } from \"@rotorsoft/act\";\n *\n * cache(new InMemoryCache({ maxSize: 500 }));\n * ```\n */\n/* eslint-disable @typescript-eslint/require-await -- async interface for Redis-compatibility */\nexport class InMemoryCache implements Cache {\n // CacheEntry<any> lets `get<TState>` and `set<TState>` flow without casts:\n // any is bidirectionally compatible with the per-call TState binding, while\n // the public Cache interface still presents a typed surface to callers.\n private readonly _entries: LruMap<string, CacheEntry<any>>;\n\n constructor(options?: { maxSize?: number }) {\n this._entries = new LruMap(options?.maxSize ?? 1000);\n }\n\n /** @inheritDoc */\n async get<TState extends Schema>(\n stream: string\n ): Promise<CacheEntry<TState> | undefined> {\n return this._entries.get(stream);\n }\n\n /** @inheritDoc */\n async set<TState extends Schema>(\n stream: string,\n entry: CacheEntry<TState>\n ): Promise<void> {\n this._entries.set(stream, entry);\n }\n\n /** @inheritDoc */\n async invalidate(stream: string): Promise<void> {\n this._entries.delete(stream);\n }\n\n /** @inheritDoc */\n async clear(): Promise<void> {\n this._entries.clear();\n }\n\n /** @inheritDoc */\n async dispose(): Promise<void> {\n this._entries.clear();\n }\n\n /** Current number of entries held by the LRU. */\n get size(): number {\n return this._entries.size;\n }\n}\n","import type {\n Actor,\n Message,\n Schema,\n Schemas,\n Snapshot,\n Target,\n} from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n StreamClosedError: \"ERR_STREAM_CLOSED\",\n NonRetryableError: \"ERR_NON_RETRYABLE\",\n StoreError: \"ERR_STORE\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @example Logging validation details\n * ```typescript\n * try {\n * await app.do(\"updateProfile\", target, payload);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * error.details.errors.forEach((err) => {\n * console.error(`Field ${err.path.join(\".\")}: ${err.message}`);\n * });\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string;\n /** The invalid payload that failed validation */\n public readonly payload: any;\n /** Zod validation error details */\n public readonly details: any;\n\n constructor(target: string, payload: any, details: any) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n this.target = target;\n this.payload = payload;\n this.details = details;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TKey - Action name\n * @template TActor - Actor type extending base Actor\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"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(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @example User-friendly error messages\n * ```typescript\n * try {\n * await app.do(\"closeTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * // Present friendly message to user\n * if (error.description === \"Ticket must be open\") {\n * return { error: \"This ticket is already closed\" };\n * } else if (error.description === \"Not authorized\") {\n * return { error: \"You don't have permission to close this ticket\" };\n * }\n * }\n * }\n * ```\n *\n * @example Logging with context\n * ```typescript\n * try {\n * await app.do(\"transfer\", target, { to: \"account2\", amount: 500 });\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * logger.error({\n * action: error.action,\n * stream: error.target.stream,\n * actor: error.target.actor,\n * reason: error.description,\n * balance: error.snapshot.state.balance,\n * attempted: error.payload.amount\n * }, \"Invariant violation\");\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n TActor extends Actor = Actor,\n> extends Error {\n /** The action that was attempted */\n readonly action: TKey;\n /** The action payload that was provided */\n readonly payload: Readonly<TActions[TKey]>;\n /** The target stream and actor context */\n readonly target: Target<TActor>;\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<TState, TEvents>;\n /** Human-readable description of why the invariant failed */\n readonly description: string;\n\n constructor(\n action: TKey,\n payload: Readonly<TActions[TKey]>,\n target: Target<TActor>,\n snapshot: Snapshot<TState, TEvents>,\n description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n this.action = action;\n this.payload = payload;\n this.target = target;\n this.snapshot = snapshot;\n this.description = description;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @example Logging concurrency conflicts\n * ```typescript\n * try {\n * await app.do(\"updateInventory\", target, payload);\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * logger.warn({\n * stream: error.stream,\n * expectedVersion: error.expectedVersion,\n * actualVersion: error.lastVersion,\n * events: error.events.map(e => e.name)\n * }, \"Concurrent modification detected\");\n * }\n * }\n * ```\n *\n * @example User feedback for conflicts\n * ```typescript\n * try {\n * await app.do(\"editDocument\", target, { content: newContent });\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * return {\n * error: \"This document was modified by another user. Please refresh and try again.\",\n * code: \"CONCURRENT_MODIFICATION\"\n * };\n * }\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\nexport class ConcurrencyError extends Error {\n /** The stream that had the concurrent modification */\n public readonly stream: string;\n /** The actual current version in the store */\n public readonly lastVersion: number;\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[];\n /** The version number that was expected */\n public readonly expectedVersion: number;\n\n constructor(\n stream: string,\n lastVersion: number,\n events: Message<Schemas, keyof Schemas>[],\n expectedVersion: number\n ) {\n // Message lists stream + event names only. Payloads remain accessible\n // via `error.events` for callers who need them — keeping them out of\n // the message avoids MB-scale strings on contended writes and keeps\n // potentially-sensitive data out of log streams.\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n this.stream = stream;\n this.lastVersion = lastVersion;\n this.events = events;\n this.expectedVersion = expectedVersion;\n }\n}\n\n/**\n * Thrown when attempting to write to a stream that has been closed\n * with a tombstone event.\n *\n * A tombstoned stream is permanently closed — no further actions can\n * be executed against it. The only way to reopen a tombstoned stream\n * is through `Act.close()` with a `restart` callback.\n *\n * @example\n * ```typescript\n * import { StreamClosedError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"updateTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof StreamClosedError) {\n * console.error(`Stream ${error.stream} is closed`);\n * }\n * }\n * ```\n *\n * @see {@link Act.close} for closing streams\n */\nexport class StreamClosedError extends Error {\n /** The stream that is closed */\n public readonly stream: string;\n\n constructor(stream: string) {\n super(`Stream \"${stream}\" is closed (tombstoned)`);\n this.name = Errors.StreamClosedError;\n this.stream = stream;\n }\n}\n\n/**\n * Thrown by a {@link Store} adapter when an infrastructure operation fails\n * for a reason that is *not* a domain condition — a dropped connection, a\n * transaction rollback, a query timeout. It is the typed boundary between\n * \"the store is unavailable/degraded\" and the domain errors above\n * ({@link ConcurrencyError}, {@link StreamClosedError}), which describe\n * legitimate outcomes the caller should branch on.\n *\n * Adapters wrap their driver errors in `StoreError` (preserving the\n * original via `cause`) so the orchestrator can distinguish a degraded\n * backend from \"no work\" and react accordingly — see the drain circuit\n * breaker, which trips on repeated `StoreError`s and surfaces an\n * `error` lifecycle event instead of silently spinning on a down\n * database.\n *\n * @example\n * ```typescript\n * app.on(\"error\", ({ error, circuit }) => {\n * if (error instanceof StoreError)\n * alert(`store ${error.operation} failing; circuit=${circuit}`);\n * });\n * ```\n */\nexport class StoreError extends Error {\n /** The store operation that failed (e.g. `\"claim\"`, `\"ack\"`, `\"commit\"`). */\n public readonly operation: string;\n\n constructor(operation: string, options?: { cause?: unknown }) {\n super(`Store operation \"${operation}\" failed`, options);\n this.name = Errors.StoreError;\n this.operation = operation;\n }\n}\n\n/**\n * Thrown by a reaction handler to signal that the failure is permanent\n * and the drain pipeline should block the stream immediately, without\n * consuming the rest of the `maxRetries` budget.\n *\n * The drain finalizer detects `instanceof NonRetryableError` and forces\n * `block = options.blockOnError` regardless of `lease.retry`. When\n * `blockOnError` is `false`, behavior is unchanged (drain keeps retrying\n * forever) — the class never overrides the operator's explicit \"never\n * block\" choice.\n *\n * Use this for failures the handler *knows* won't get better on retry:\n * a 4xx from a webhook, a `ZodError` on malformed input, a \"user\n * deleted\" 404 from a downstream API. Use regular `Error` (or a\n * subclass) for transient failures so the existing retry-with-backoff\n * loop applies.\n *\n * @example Wrapping a permanent downstream error\n * ```typescript\n * import { NonRetryableError } from \"@rotorsoft/act\";\n *\n * .on(\"OrderConfirmed\")\n * .do(async (event) => {\n * const res = await fetch(url, ...);\n * if (res.status >= 400 && res.status < 500) {\n * throw new NonRetryableError(\n * `webhook ${url} responded ${res.status}`,\n * { cause: await res.text() }\n * );\n * }\n * if (!res.ok) throw new Error(`webhook ${url} responded ${res.status}`);\n * })\n * ```\n *\n * @example Marking validation failures as non-retryable\n * ```typescript\n * .on(\"PaymentReceived\")\n * .do(async (event) => {\n * const parsed = Schema.safeParse(event.data);\n * if (!parsed.success) {\n * throw new NonRetryableError(\"payment payload failed validation\", {\n * cause: parsed.error,\n * });\n * }\n * // ... handle parsed payload\n * })\n * ```\n */\nexport class NonRetryableError extends Error {\n /** The original failure, if any. Mirrors the standard `Error.cause` shape. */\n public override readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = Errors.NonRetryableError;\n this.cause = options?.cause;\n }\n}\n","import { prettifyError, ZodError, type ZodType } from \"zod\";\nimport { config } from \"./config.js\";\nimport { ValidationError } from \"./types/index.js\";\n\n/**\n * @module utils\n * @category Utilities\n *\n * Small utilities used across the framework:\n * - {@link validate} — parse a payload against a Zod schema, throwing\n * {@link ValidationError} on failure.\n * - {@link extend} — validate a source object and merge into defaults.\n * - {@link sleep} — async delay (default duration from `config().sleepMs`).\n */\n\n/**\n * Parse `payload` against `schema`, returning the validated value or throwing\n * a {@link ValidationError} with prettified Zod details. When `schema` is\n * omitted, returns `payload` unchanged. The framework calls this for every\n * `app.do()` action, every emitted event, and every state init.\n *\n * @example\n * ```typescript\n * const UserSchema = z.object({ email: z.string().email() });\n * const user = validate(\"User\", { email: \"alice@example.com\" }, UserSchema);\n * ```\n *\n * @see {@link ValidationError}\n */\nexport const validate = <S>(\n target: string,\n payload: Readonly<S>,\n schema?: ZodType<S>\n): Readonly<S> => {\n try {\n return schema ? schema.parse(payload) : payload;\n } catch (error) {\n if (error instanceof ZodError) {\n throw new ValidationError(target, payload, prettifyError(error));\n }\n throw new ValidationError(target, payload, error);\n }\n};\n\n/**\n * Validate `source` against `schema` and return a new object that merges\n * `source` over the optional `target` defaults. Used by {@link config} for\n * env-var-overrides-defaults patterns; safe to call elsewhere — it never\n * mutates `target`.\n *\n * @example\n * ```typescript\n * const schema = z.object({ host: z.string(), port: z.number() });\n * const cfg = extend({ port: 8080 }, schema, { host: \"localhost\", port: 80 });\n * // → { host: \"localhost\", port: 8080 }\n * ```\n *\n * @throws {@link ValidationError} if `source` fails the schema.\n */\nexport const extend = <\n S extends Record<string, unknown>,\n T extends Record<string, unknown>,\n>(\n source: Readonly<S>,\n schema: ZodType<S>,\n target?: Readonly<T>\n): Readonly<S & T> => {\n const value = validate(\"config\", source, schema);\n return { ...target, ...value } as Readonly<S & T>;\n};\n\n/**\n * Pause for `ms` milliseconds (or `config().sleepMs` when omitted — `100ms`\n * in dev, `0ms` in tests). Used by adapters to simulate async I/O.\n *\n * @example\n * ```typescript\n * await sleep(); // default delay from config\n * await sleep(500); // explicit 500ms\n * ```\n */\nexport async function sleep(ms?: number) {\n return new Promise((resolve) => setTimeout(resolve, ms ?? config().sleepMs));\n}\n\n/**\n * Regex metacharacters that, when present in a reaction `source`, make it a\n * pattern rather than a literal stream name. A source containing none of\n * these is a bare stream name — the common case — and every claim/fetch\n * site matches it by string equality on the store's stream index. A source\n * containing any of them is compiled as a RegExp and matched against\n * candidate streams with the caller's own anchoring (e.g. `^(A|B)$`).\n */\nconst SOURCE_METACHARACTERS = /[\\^$.*+?()[\\]{}|\\\\]/;\n\n/**\n * True when `source` is a **literal** stream name — it carries no regex\n * metacharacter, so every adapter treats it as an exact match. This is the\n * fast, index-friendly path and covers every autoclose/dynamic-resolver\n * source (bare stream names). A `false` return means the source is a\n * **pattern** (contains `^ $ . * + ? ( ) [ ] { } | \\`) and must be compiled\n * as a RegExp before matching — the shape the calculator's static\n * `source: \"^(A|B)$\"` reaction relies on.\n *\n * The single source of truth for literal-vs-pattern classification across\n * correlate (which decides what a source marks), the drain fetch path, and\n * the SQLite adapter (which rejects a non-portable pattern), so all three\n * agree on which sources take the exact path.\n *\n * @example\n * ```typescript\n * is_literal_source(\"Board\"); // → true (exact lookup)\n * is_literal_source(\"^(A|B)$\"); // → false (compile as RegExp)\n * ```\n */\nexport function is_literal_source(source: string): boolean {\n return !SOURCE_METACHARACTERS.test(source);\n}\n\n/**\n * Matches an ISO-8601 timestamp, the shape `JSON.stringify` produces for a\n * `Date`.\n *\n * @internal\n */\nconst ISO_8601 =\n /^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(\\.\\d+)?(Z|[+-][0-2][0-9]:[0-5][0-9])?$/;\n\n/**\n * Revive ISO-8601-shaped strings into `Date`s during `JSON.parse`.\n *\n * **The framework no longer uses this.** Dates are resolved from the declared\n * `z.date()` paths at build time and converted on read, so a field declared\n * `z.string()` keeps its string even when the value looks like a timestamp\n *. Adapters\n * return what they stored; typing is the orchestrator's job.\n *\n * Kept exported for host applications that parse Act JSON themselves and want\n * the old shape-based behaviour. New code should let the schema decide.\n *\n */\nexport const dateReviver = (_key: string, value: unknown): unknown =>\n typeof value === \"string\" && ISO_8601.test(value) ? new Date(value) : value;\n","/**\n * @packageDocumentation\n * Configuration utilities for Act Framework environment, logging, and package metadata.\n *\n * Provides type-safe configuration loading and validation using Zod schemas.\n *\n * @module config\n */\nimport * as fs from \"node:fs\";\nimport { z } from \"zod\";\nimport { log } from \"./ports.js\";\nimport {\n type Environment,\n Environments,\n type LogLevel,\n LogLevels,\n} from \"./types/index.js\";\nimport { extend } from \"./utils.js\";\n\n/**\n * Zod schema for validating package.json metadata.\n * @internal\n */\nexport const PackageSchema = z.object({\n name: z.string().min(1),\n version: z.string().min(1),\n description: z.string().min(1).optional(),\n author: z\n .object({ name: z.string().min(1), email: z.string().optional() })\n .optional()\n .or(z.string().min(1))\n .optional(),\n license: z.string().min(1).optional(),\n dependencies: z.record(z.string(), z.string()).optional(),\n});\n\n/**\n * Type representing the validated package.json metadata.\n *\n * @internal\n */\nexport type Package = z.infer<typeof PackageSchema>;\n\n/**\n * Fallback package metadata when `package.json` can't be read at module\n * load — happens when the framework is consumed from a CWD that doesn't\n * have one (bundled CLIs, Lambda layers, embedded scripts) or when the\n * file exists but is malformed.\n *\n * The values are deliberately synthetic so callers spot them immediately:\n * `config().name === \"act-fallback\"` is a runtime signal that the framework\n * couldn't load the host project's package.json.\n *\n * @internal\n */\nconst FALLBACK_PACKAGE: Package = {\n name: \"act-fallback\",\n version: \"0.0.0-fallback\",\n description: \"Synthetic fallback — package.json could not be loaded\",\n};\n\n/**\n * Loads and parses the local package.json file as a Package object. On\n * any read or parse failure, falls back to {@link FALLBACK_PACKAGE} and\n * stashes the error so {@link config} can surface it on first access —\n * we can't call `log()` here because the logger port memoizes on first\n * call and locking it at module load defeats user injection.\n *\n * @internal\n */\nconst get_package = (): Package => {\n try {\n const raw = fs.readFileSync(\"package.json\");\n return JSON.parse(raw.toString()) as Package;\n } catch (err) {\n pkg_load_error = err;\n return FALLBACK_PACKAGE;\n }\n};\n\n/** Stashed read/parse error from {@link get_package}, surfaced by config(). */\nlet pkg_load_error: unknown;\n\n/**\n * Zod schema for the full Act Framework configuration object.\n * Includes package metadata, environment, logging, and timing options.\n * @internal\n */\nconst BaseSchema = PackageSchema.extend({\n env: z.enum(Environments),\n logLevel: z.enum(LogLevels),\n logSingleLine: z.boolean(),\n sleepMs: z.number().int().min(0).max(5000),\n});\n\n/**\n * Type representing the validated Act Framework configuration object.\n */\nexport type Config = z.infer<typeof BaseSchema>;\n\nconst { NODE_ENV, LOG_LEVEL, LOG_SINGLE_LINE, SLEEP_MS } = process.env;\n\nconst env = (NODE_ENV || \"development\") as Environment;\nconst logLevel = (LOG_LEVEL ||\n (NODE_ENV === \"test\"\n ? \"fatal\"\n : NODE_ENV === \"production\"\n ? \"info\"\n : \"trace\")) as LogLevel;\nconst logSingleLine = (LOG_SINGLE_LINE || \"true\") === \"true\";\nconst sleepMs = parseInt(NODE_ENV === \"test\" ? \"0\" : (SLEEP_MS ?? \"100\"), 10);\n\nconst pkg = get_package();\n\n// Lazily validated on first call. Cannot run extend() at module load\n// because of a utils.ts <-> config.ts cycle (utils imports config for\n// sleep()'s default). Inputs are frozen after import, so the cached\n// result is stable for the life of the process.\nlet _validated: Config | undefined;\n\n/**\n * Gets the current Act Framework configuration.\n *\n * Configuration is loaded from package.json and environment variables, providing\n * type-safe access to application metadata and runtime settings.\n *\n * **Environment Variables:**\n * - `NODE_ENV`: \"development\" | \"test\" | \"staging\" | \"production\" (default: \"development\")\n * - `LOG_LEVEL`: \"fatal\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"trace\"\n * - `LOG_SINGLE_LINE`: \"true\" | \"false\" (default: \"true\")\n * - `SLEEP_MS`: Milliseconds for sleep utility (default: 100, 0 for tests)\n *\n * **Defaults by environment:**\n * - test: logLevel=\"error\", sleepMs=0\n * - production: logLevel=\"info\"\n * - development: logLevel=\"trace\"\n *\n * @returns The validated configuration object\n *\n * @example Basic usage\n * ```typescript\n * import { config } from \"@rotorsoft/act\";\n *\n * const cfg = config();\n * console.log(`App: ${cfg.name} v${cfg.version}`);\n * console.log(`Environment: ${cfg.env}`);\n * console.log(`Log level: ${cfg.logLevel}`);\n * ```\n *\n * @example Environment-specific behavior\n * ```typescript\n * import { config } from \"@rotorsoft/act\";\n *\n * const cfg = config();\n *\n * if (cfg.env === \"production\") {\n * // Use PostgreSQL in production\n * store(new PostgresStore(prodConfig));\n * } else {\n * // Use in-memory store for dev/test\n * store(new InMemoryStore());\n * }\n * ```\n *\n * @example Adjusting log levels\n * ```typescript\n * // Set via environment variable:\n * // LOG_LEVEL=debug npm start\n *\n * // Or check in code:\n * const cfg = config();\n * if (cfg.logLevel === \"trace\") {\n * logger.trace(\"Detailed debugging enabled\");\n * }\n * ```\n *\n * @see {@link Config} for configuration type\n */\nexport const config = (): Config => {\n if (!_validated) {\n _validated = extend(\n { ...pkg, env, logLevel, logSingleLine, sleepMs },\n BaseSchema\n );\n if (pkg_load_error) {\n // Surface the fallback once, after _validated is set so the\n // recursive log() → config() call short-circuits. log() resolves\n // through the port singleton — respects user injection and level.\n const msg =\n pkg_load_error instanceof Error\n ? pkg_load_error.message\n : typeof pkg_load_error === \"string\"\n ? pkg_load_error\n : \"unknown error\";\n log().warn(\n `[act] Could not read package.json (${msg}); using synthetic ` +\n `name=\"${FALLBACK_PACKAGE.name}\" version=\"${FALLBACK_PACKAGE.version}\".`\n );\n pkg_load_error = undefined;\n }\n }\n return _validated;\n};\n","import { type ZodObject, type ZodRawShape, z } from \"zod\";\n// Deep-path import (vs `../internal/index.js`) is deliberate — `_registry` is\n// a side-effect-free leaf, and going through the internal barrel would pull\n// tracing.ts → config.ts in at type-schema load time and crash on TDZ when a\n// test imports a public schema before config is initialized.\nimport { _mark_sensitive, _registry } from \"../internal/sensitive.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Sensitive-data foundation re-exports.\n *\n * - `REDACTED` / `SHREDDED` — sentinels placed in `event.data[field]`\n * when the caller isn't authorized to see a sensitive field\n * (`.discloses(predicate)` returned `false` or none was declared —\n * recoverable) or the underlying PII was wiped (`Store.forget_pii` —\n * irrecoverable).\n * top-level field names marked via {@link sensitive}. A pure,\n * read-only helper that inspects the out-of-band sensitive registry (a\n * process-global `WeakMap`) `sensitive()` populates, otherwise\n * unreachable from outside the package. Surfaced for adapters and\n * tooling that must reflect input sensitivity on their own wire\n * surface — e.g. the `@rotorsoft/act-http/openapi` emitter marks these\n * fields `writeOnly` + `format: password` so generated clients and\n * Swagger UI don't echo PII freely. Returns `[]` for non-object\n * schemas or objects with no sensitive fields; top-level shape only.\n */\nexport { pii_fields, REDACTED, SHREDDED } from \"../internal/sensitive.js\";\n\n/**\n * Mark a Zod schema as sensitive. Returns the same schema instance — the\n * marker is registered out-of-band so the static type is preserved and the\n * call site reads as a pure annotation.\n *\n * Idempotent: re-wrapping an already-sensitive schema is a no-op.\n *\n * The marker is what the orchestrator inspects to split event payloads into\n * `data` + `pii` on commit, gate reads via `.discloses`, and strip handler\n * payloads. Part of the sensitive-data foundation.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { state, sensitive } from \"@rotorsoft/act\";\n *\n * const UserRegistered = z.object({\n * email: sensitive(z.string()),\n * name: sensitive(z.string()),\n * plan: z.enum([\"free\", \"pro\"]), // not sensitive — stays in events.data\n * });\n * ```\n *\n * @param schema - The Zod schema to mark sensitive.\n * @returns The same schema instance, unmodified at the type level.\n */\nexport function sensitive<T extends z.ZodType>(schema: T): T {\n _registry.add(schema, { sensitive: true });\n // Also stamp the def, so the marker survives the clone Zod produces for\n // any refinement chained AFTER this call — `sensitive(z.string()).min(1)`\n // used to lose it silently and write plaintext into `events.data`.\n _mark_sensitive(schema);\n return schema;\n}\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n with_pii: z.boolean().optional(),\n stream_exact: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @module sensitive\n * @category Internal\n *\n * Internal mechanics for the sensitive-data foundation.\n * The public surface (`sensitive(zodType)`) lives at `libs/act/src/sensitive.ts`\n * and re-exports `REDACTED` / `SHREDDED` from here; this module holds the\n * registry plus the helpers the orchestrator calls during commit, load, and\n * handler dispatch.\n *\n * - `_registry` — process-global `z.registry<{ sensitive: true }>()`. Public\n * `sensitive()` adds to it; the helpers in this module read it.\n * - `pii_fields(schema)` — walk a Zod schema's top-level shape, return the\n * keys marked via `sensitive(...)`.\n * - `pii_gate(event, fields, predicate, actor)` — produce the external\n * view: plaintext when authorized, `[REDACTED]` when not, `[SHREDDED]`\n * when the underlying pii column is null.\n * - `pii_strip(event, fields)` — remove sensitive keys entirely\n * before invoking projection / reaction handlers.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { Actor, Committed, Schemas } from \"../types/index.js\";\n\n/**\n * Sentinel placed in `event.data[field]` when the caller isn't authorized to\n * see the sensitive field — either `.discloses(predicate)` returned `false`,\n * or no predicate was declared (framework default-deny). Recoverable: a\n * properly-authorized read returns the plaintext.\n *\n * Re-exported from `libs/act/src/sensitive.ts` as part of the public surface.\n */\nexport const REDACTED = \"[REDACTED]\" as const;\n\n/**\n * Sentinel placed in `event.data[field]` when the underlying PII payload has\n * been wiped via `Store.forget_pii(stream)` — the row's pii column is `NULL`\n * and the original plaintext is gone forever. Irrecoverable.\n *\n * Re-exported from `libs/act/src/sensitive.ts` as part of the public surface.\n */\nexport const SHREDDED = \"[SHREDDED]\" as const;\n\n/**\n * Process-global registry holding every Zod schema marked sensitive. Backed\n * by a `WeakMap`, so wrapper-created instances (`.optional()`, `.nullable()`,\n * `.default()`) that chain off a marked schema produce *new* schema instances\n * the registry doesn't track; the field walker handles those via unwrap.\n *\n * Exported so the public `sensitive(zodType)` wrapper can call `_registry.add`.\n * Underscore prefix marks \"framework-private, don't touch from user code.\"\n *\n * @internal\n */\nexport const _registry = z.registry<{ sensitive: true }>();\n\n/**\n * Marker key stamped onto a schema's own `def`. Zod clones a schema on every\n * refinement (`.min()`, `.email()`, `.trim()`, `.describe()`, `.refine()`,\n * `.transform()`, …) via `{...def}`, which copies own symbol keys — so a\n * marker on the def survives the whole chain, while the `_registry` WeakMap\n * (keyed on the *instance*) does not.\n *\n * The registry is still populated and still consulted: it covers schemas\n * marked before this key existed, and it is the mechanism the public\n * `sensitive()` doc-comment describes.\n *\n * @internal\n */\nconst _SENSITIVE = Symbol.for(\"act.sensitive\");\n\n/**\n * Stamp the def-level marker. Called by the public `sensitive()` alongside\n * `_registry.add`.\n *\n * @internal\n */\nexport function _mark_sensitive(schema: z.ZodType): void {\n const def = (\n schema as unknown as {\n _zod?: { def?: Record<PropertyKey, unknown> };\n }\n )._zod?.def;\n if (def) def[_SENSITIVE] = true;\n}\n\n/**\n * True when the given schema was marked via `sensitive(...)`.\n *\n * Walks through Zod wrapper layers (`.optional()`, `.nullable()`,\n * `.default()`, `.readonly()`) by following `_def.innerType` until it reaches\n * a non-wrapper schema, then checks the registry. Wrappers create new schema\n * instances; the marker lives on the *inner* schema the user wrapped, so we\n * test that one.\n *\n * @internal\n */\nfunction is_pii(schema: z.ZodType): boolean {\n let cur: z.ZodType = schema;\n while (true) {\n if (_registry.has(cur)) return true;\n // Def-level marker: survives the clone a refinement produces, which the\n // instance-keyed registry above cannot.\n const def = (\n cur as unknown as {\n _zod?: { def?: Record<PropertyKey, unknown> };\n }\n )._zod?.def;\n if (def?.[_SENSITIVE] === true) return true;\n const inner = (cur as { _def?: { innerType?: z.ZodType } })._def?.innerType;\n if (!inner || inner === cur) return false;\n cur = inner;\n }\n}\n\n/**\n * Derive an event's sensitive fields, as the declared schema of each.\n *\n * Walks the top-level shape of a `z.object({...})` and keeps the keys whose\n * schema (after unwrapping optional/nullable/default wrappers) was marked via\n * `sensitive(...)`. Returns an empty object for non-object schemas or events\n * with no sensitive fields — the common-case zero-cost path.\n *\n * Only the top-level shape is walked. Sensitive fields nested inside a\n * `z.object` declared inside the event payload would require recursive\n * descent; that's deferred until a real callsite needs it.\n *\n * A union event has no top-level shape, so the options are walked and merged:\n * a key sensitive in any variant must be split, because the stored payload\n * could be that variant.\n * The first variant to declare a key wins, which only matters to a caller that\n * wants the schema rather than the name.\n *\n * Returning the schemas rather than just the names is what lets a caller do\n * something per field — the event builder asks each one whether it holds a\n * date, so the `pii` sidecar's dates can be revived like any other.\n *\n * @internal\n */\nexport function pii_schemas(schema: z.ZodType): Record<string, z.ZodType> {\n const shape = (schema as { shape?: Record<string, z.ZodType> }).shape;\n if (shape && typeof shape === \"object\") {\n const fields: Record<string, z.ZodType> = {};\n for (const key of Object.keys(shape))\n if (is_pii(shape[key])) fields[key] = shape[key];\n return fields;\n }\n const options = (schema as { options?: unknown }).options;\n if (Array.isArray(options)) {\n const fields: Record<string, z.ZodType> = {};\n for (const option of options)\n for (const [key, field] of Object.entries(\n pii_schemas(option as z.ZodType)\n ))\n fields[key] ??= field;\n return fields;\n }\n return {};\n}\n\n/**\n * The names of an event's sensitive fields — {@link pii_schemas} keyed.\n *\n * @internal — consumed by the registry's `sensitive_fields(event_name)` lookup,\n * and public through `types/schemas.ts`, where act-http's OpenAPI emitter uses\n * it to mark request-body properties `writeOnly`.\n */\nexport function pii_fields(schema: z.ZodType): readonly string[] {\n return Object.keys(pii_schemas(schema));\n}\n\n/**\n * Split an emitted event's `data` into `data` (non-sensitive) + `pii`\n * (sensitive) using the field list precomputed at build time. Used by the\n * State's `_pii_split` decorator just before `Store.commit`.\n *\n * Single forward pass over `Object.keys(validated)` — same shape as the\n * spread-and-delete-free implementation in slice 3, just hoisted out of the\n * orchestrator hot path so it's only invoked when the State actually has a\n * sensitive event.\n *\n * @internal\n */\nexport function pii_split<TName, TData extends Record<string, unknown>>(\n emitted: { name: TName; data: TData },\n fields: readonly string[]\n): { name: TName; data: TData; pii: Record<string, unknown> } {\n const data = { ...emitted.data };\n const pii: Record<string, unknown> = {};\n for (const f of fields) {\n if (f in data) {\n pii[f] = data[f];\n delete data[f];\n }\n }\n return { name: emitted.name, data, pii };\n}\n\n/**\n * Build the **external view** of a committed event — the form returned by\n * `load()`, `query()`, `query_array()`, and the snapshot in `do()`'s reply.\n *\n * Only ever reached for events that declare sensitive fields — the sole caller\n * is {@link make_gate}, which the builder invokes exclusively for sensitive\n * events; non-sensitive events short-circuit to {@link IDENTITY_GATE} before\n * they get here. `fields` is therefore guaranteed non-empty (same contract as\n * {@link pii_strip}).\n *\n * - Event whose `pii` payload is null/undefined → substitute {@link SHREDDED}\n * for each declared field. Irrecoverable, so no predicate check.\n * - Event with a `pii` payload, predicate returns `true` → merge `pii` into\n * `data` (plaintext).\n * - Event with a `pii` payload, predicate returns `false` OR no predicate\n * declared (framework default-deny) → substitute {@link REDACTED} for each\n * declared field.\n *\n * @internal\n */\nfunction pii_gate<TEvents extends Schemas, TKey extends keyof TEvents>(\n event: Committed<TEvents, TKey>,\n fields: readonly string[],\n predicate: ((event: any, actor: Actor) => boolean) | null,\n actor: Actor | undefined\n): Committed<TEvents, TKey> {\n const data = event.data as Record<string, unknown>;\n // The external view NEVER carries the isolated `pii` sidecar — dropping it\n // is the whole point of the gate. Keeping it (an earlier `...event` spread)\n // leaked plaintext PII on every gated read surface (`load`, `query`,\n // `query_array`) even while `data` was correctly redacted. Strip it\n // once here; the plaintext lives in `data` only on the authorized path.\n const { pii, ...rest } = event as Committed<TEvents, TKey> & {\n pii?: Record<string, unknown> | null;\n };\n if (pii == null) {\n const shredded: Record<string, unknown> = { ...data };\n for (const f of fields) shredded[f] = SHREDDED;\n return { ...rest, data: shredded as Committed<TEvents, TKey>[\"data\"] };\n }\n // Plaintext path requires both an actor AND a predicate that allows. Missing\n // either → default-deny → REDACTED.\n const allowed = !!actor && !!predicate && predicate(event, actor);\n if (allowed) {\n return {\n ...rest,\n data: { ...data, ...pii } as Committed<TEvents, TKey>[\"data\"],\n };\n }\n const redacted: Record<string, unknown> = { ...data };\n for (const f of fields) redacted[f] = REDACTED;\n return { ...rest, data: redacted as Committed<TEvents, TKey>[\"data\"] };\n}\n\n/**\n * A prebuilt per-event read gate: given a committed event and the reading\n * actor, return the caller-visible form. This is the single gating primitive\n * the builder prebuilds for **every** read surface — both the actor-less\n * `query` / `query_array` (which pass no actor → default-deny) and the\n * actor-aware `load` / `do`-return view (which pass the reader). Non-sensitive\n * events use the shared {@link IDENTITY_GATE}; sensitive events use a redactor\n * built by {@link make_gate} that closes over the field list and the state's\n * disclosure predicate, so the read path never recomputes the sensitive-field\n * lookup nor allocates per event.\n *\n * The `actor` is optional so the actor-less surfaces can call `gate(event)`.\n *\n * @internal\n */\nexport type EventGate = <TEvents extends Schemas, TKey extends keyof TEvents>(\n event: Committed<TEvents, TKey>,\n actor?: Actor\n) => Committed<TEvents, TKey>;\n\n/**\n * Shared zero-cost gate for every event with no `sensitive(...)` fields — a\n * single frozen reference the builder hands back for non-sensitive events, so\n * the common path is one `Map` miss and an identity call, no allocation. This\n * is the \"by default, return the event\" half of the prebuilt per-event gate.\n *\n * @internal\n */\nexport const IDENTITY_GATE: EventGate = (event) => event;\n\n/**\n * Prebuild a read gate for a sensitive event, capturing its field list and the\n * disclosure predicate once at build time. The returned closure defers to\n * {@link pii_gate} with the reading actor supplied per call:\n *\n * - `predicate = null` (the actor-less `query` surfaces, or a state that never\n * declared `.discloses`) → default-deny: declared fields come back\n * {@link REDACTED} (or {@link SHREDDED} once the pii column is forgotten).\n * - `predicate` set + an authorized actor → plaintext merged into `data`.\n *\n * Either way the isolated `pii` sidecar is dropped. The builder stores one gate\n * per sensitive event (per state for the load path; predicate-less for the\n * query path); non-sensitive events fall back to {@link IDENTITY_GATE}.\n *\n * @internal\n */\nexport function make_gate(\n fields: readonly string[],\n predicate: ((event: any, actor: Actor) => boolean) | null\n): EventGate {\n return (event, actor) => pii_gate(event, fields, predicate, actor);\n}\n\n/**\n * Build the **handler view** — sensitive keys removed entirely from `data`\n * and the `pii` field dropped from the event. Used before invoking projection\n * handlers and reaction handlers, which never see PII by framework rule.\n *\n * Different from {@link pii_gate} (which substitutes {@link REDACTED} or\n * {@link SHREDDED}) — projection tables and reaction sinks shouldn't even\n * structurally observe the keys, so a handler that mistakenly writes\n * `event.data.email` into a column would get `undefined`, not a sentinel\n * string that looks like real data. The strictness is deliberate.\n *\n * Reactions that genuinely need PII (e.g. a welcome-email reaction reading\n * `email`) opt back in by explicitly calling `app.load(stream, { actor:\n * system_actor })` inside the handler — pulling PII through the gate at the\n * call site makes the security-relevant path visible in code review.\n *\n * @internal\n */\nexport function pii_strip<\n TEvents extends Schemas,\n TKey extends keyof TEvents & string,\n>(\n event: Committed<TEvents, TKey>,\n fields: readonly string[]\n): Committed<TEvents, TKey> {\n // Contract: `fields` is non-empty. `build_handle` / `build_handle_batch`\n // filter on `fields.length > 0` before invocation.\n const data = event.data as Record<string, unknown>;\n const stripped: Record<string, unknown> = {};\n for (const k of Object.keys(data)) {\n if (!fields.includes(k)) stripped[k] = data[k];\n }\n const { pii: _drop_pii, ...rest } = event as Committed<TEvents, TKey> & {\n pii?: unknown;\n };\n return {\n ...rest,\n data: stripped as Committed<TEvents, TKey>[\"data\"],\n } as Committed<TEvents, TKey>;\n}\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport type * from \"./audit.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n","/**\n * @packageDocumentation\n * @module act/adapters\n * In-memory event store adapter for development and tests.\n *\n * @category Adapters\n */\n\nimport { DEFAULT_LANE, SNAP_EVENT, TOMBSTONE_EVENT } from \"../ports.js\";\nimport { ConcurrencyError } from \"../types/errors.js\";\nimport type {\n BlockedLease,\n Committed,\n EventMeta,\n Lease,\n Message,\n Query,\n QueryStatsOptions,\n QueryStreams,\n QueryStreamsResult,\n Schema,\n Schemas,\n Store,\n StreamFilter,\n StreamPosition,\n StreamStats,\n SubscribeInput,\n} from \"../types/index.js\";\nimport { sleep } from \"../utils.js\";\n\n/** One subscription row: watermark, lease, retry and schedule. */\nclass InMemoryStream {\n readonly stream: string;\n readonly source: string | undefined;\n private _at = -1;\n private _retry = -1;\n private _blocked = false;\n private _error = \"\";\n private _leased_by: string | undefined = undefined;\n private _leased_until: Date | undefined = undefined;\n private _priority = 0;\n private _lane: string = DEFAULT_LANE;\n // While in the future, the stream is held out of `claim`.\n private _deferred_at: number | undefined = undefined;\n // Work mark; `undefined` = never correlated, so `claim` skips it.\n private _correlated_at: number | undefined = undefined;\n\n constructor(\n stream: string,\n source: string | undefined,\n priority = 0,\n lane: string = DEFAULT_LANE\n ) {\n this.stream = stream;\n this.source = source;\n this._priority = priority;\n this._lane = lane;\n }\n\n get priority() {\n return this._priority;\n }\n\n get lane() {\n return this._lane;\n }\n\n /** Replaced on every subscribe, so the current config wins on restart. */\n set lane(value: string) {\n this._lane = value;\n }\n\n bump_priority(priority: number) {\n if (priority > this._priority) this._priority = priority;\n }\n\n get correlated_at() {\n return this._correlated_at;\n }\n\n /** A mark never regresses, including at zero and negatives. */\n mark(correlated_at: number) {\n if (\n this._correlated_at === undefined ||\n correlated_at > this._correlated_at\n )\n this._correlated_at = correlated_at;\n }\n\n /** Operator override; ignores the subscribe-time `max()`. */\n set_priority(priority: number) {\n this._priority = priority;\n }\n\n get is_available() {\n return (\n !this._blocked &&\n (!this._leased_until || this._leased_until <= new Date()) &&\n (!this._deferred_at || this._deferred_at <= Date.now())\n );\n }\n\n defer(deferred_at: number) {\n this._deferred_at = deferred_at;\n // A defer is not a failure, so the redelivery is a fresh attempt.\n this._retry = -1;\n }\n\n get at() {\n return this._at;\n }\n\n get retry() {\n return this._retry;\n }\n\n get blocked() {\n return this._blocked;\n }\n\n get error() {\n return this._error;\n }\n\n get leased_by() {\n return this._leased_by;\n }\n\n get leased_until() {\n return this._leased_until;\n }\n\n get deferred_at() {\n return this._deferred_at;\n }\n\n lease(lease: Lease, millis: number): Lease {\n // The holder is recorded even at zero `millis`: `ack` is gated on it,\n // so a lease with no holder would drop every ack.\n this._leased_by = lease.by;\n this._leased_until = new Date(Date.now() + millis);\n this._retry = this._retry + 1;\n return {\n stream: this.stream,\n source: this.source,\n at: lease.at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n lane: this._lane,\n };\n }\n\n /** Ack, or with `due`, also persist the schedule. See {@link Store.ack}. */\n ack(lease: Lease) {\n if (this._leased_by === lease.by) {\n this._leased_by = undefined;\n this._leased_until = undefined;\n if (lease.due !== undefined) {\n // Advance past the handled prefix and schedule the re-visit with the\n // caller's retry (-1 for a defer, the climbing count for a backoff).\n this._at = lease.at;\n this._retry = lease.retry;\n this._deferred_at = lease.due;\n return undefined;\n }\n this._retry = -1;\n this._at = lease.at;\n this._deferred_at = undefined;\n return {\n stream: this.stream,\n source: this.source,\n at: this._at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n lane: this._lane,\n };\n }\n }\n\n block(lease: Lease, error: string) {\n // Re-blocking is a no-op, like the SQL `AND blocked = false` guard.\n if (this._leased_by === lease.by && !this._blocked) {\n this._blocked = true;\n this._error = error;\n this._deferred_at = undefined;\n return {\n stream: this.stream,\n source: this.source,\n at: this._at,\n by: this._leased_by,\n retry: this._retry,\n error: this._error,\n lagging: lease.lagging,\n lane: this._lane,\n };\n }\n }\n\n /** Retry resets to -1 (released); the next claim makes it 0. */\n reset() {\n this._at = -1;\n this._retry = -1;\n this._blocked = false;\n this._error = \"\";\n this._leased_by = undefined;\n this._leased_until = undefined;\n this._deferred_at = undefined;\n }\n\n /** True only when the stream was blocked. */\n unblock(): boolean {\n if (!this._blocked) return false;\n this._blocked = false;\n this._retry = -1;\n this._error = \"\";\n this._leased_by = undefined;\n this._leased_until = undefined;\n this._deferred_at = undefined;\n return true;\n }\n}\n\n/**\n * In-memory event store: the default when no other store is injected.\n * For development, tests and examples; all data is lost when the process\n * exits. Use {@link PostgresStore} in production.\n *\n * `Store.notify` is not implemented: a single process has no remote writer\n * to hear from, and local commits already arm the drain.\n *\n * @example Using in tests\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n *\n * describe(\"Counter\", () => {\n * beforeEach(async () => {\n * // Reset store between tests\n * await store().seed();\n * });\n *\n * it(\"increments\", async () => {\n * await app.do(\"increment\", target, { by: 5 });\n * const snapshot = await app.load(Counter, \"counter-1\");\n * expect(snapshot.state.count).toBe(5);\n * });\n * });\n * ```\n *\n * @example Explicit instantiation\n * ```typescript\n * import { InMemoryStore } from \"@rotorsoft/act\";\n *\n * const testStore = new InMemoryStore();\n * await testStore.seed();\n *\n * // Use for specific test scenarios\n * await testStore.commit(\"test-stream\", events, meta);\n * ```\n *\n * @example Querying events\n * ```typescript\n * const events: any[] = [];\n * await store().query(\n * (event) => events.push(event),\n * { stream: \"test-stream\" }\n * );\n * console.log(`Found ${events.length} events`);\n * ```\n *\n * @see {@link Store} for the interface definition\n * @see {@link PostgresStore} for production use\n * @see {@link store} for injecting stores\n *\n * @category Adapters\n */\nexport class InMemoryStore implements Store {\n private _events: Committed<Schemas, keyof Schemas>[] = [];\n // Never reused. Deletions punch holes, so ids are not array indexes.\n private _next_id = 0;\n private _streams: Map<string, InMemoryStream> = new Map();\n /** Correlate checkpoint: how far the log has been READ. */\n private _correlated_at = -1;\n /** Per-correlator checkpoint and lease; keyless callers use `_correlated_at`. */\n private _correlators = new Map<\n string,\n { at: number; by: string; until: number }\n >();\n private _stream_versions: Map<string, number> = new Map();\n // stream → (event_id → cloned pii). Two levels so `forget_pii` drops one\n // inner Map. Absence means no PII.\n private _pii: Map<string, Map<number, Record<string, unknown>>> = new Map();\n\n private _reset_indexes() {\n this._events.length = 0;\n this._next_id = 0;\n this._correlated_at = -1;\n this._stream_versions.clear();\n this._pii.clear();\n }\n\n // Stores a cloned copy, so caller-side mutation can't reach it.\n private _put_pii(stream: string, id: number, pii: Record<string, unknown>) {\n let per_stream = this._pii.get(stream);\n if (!per_stream) {\n per_stream = new Map();\n this._pii.set(stream, per_stream);\n }\n per_stream.set(id, structuredClone(pii));\n }\n\n // First index whose id is greater than `after` (ids are sorted, not dense).\n private _first_index_after(after: number): number {\n let lo = 0;\n let hi = this._events.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (this._events[mid].id > after) hi = mid;\n else lo = mid + 1;\n }\n return lo;\n }\n\n // Allocation-free for events without PII, the common case.\n private _with_pii<E extends Schemas>(\n e: Committed<E, keyof E>,\n wanted = true\n ): Committed<E, keyof E> {\n if (!wanted) return e;\n const pii = this._pii.get(e.stream)?.get(e.id);\n return pii ? ({ ...e, pii } as Committed<E, keyof E>) : e;\n }\n\n async dispose() {\n await sleep();\n this._reset_indexes();\n }\n\n async seed() {\n await sleep();\n }\n\n async drop() {\n await sleep();\n this._reset_indexes();\n this._streams = new Map();\n }\n\n private in_query<E extends Schemas>(\n query: Query,\n e: Committed<E, keyof E>\n ): boolean {\n if (query.stream && !this._stream_matches(query.stream, query, e.stream))\n return false;\n if (query.names && !query.names.includes(e.name as string)) return false;\n if (query.correlation && e.meta?.correlation !== query.correlation)\n return false;\n if (e.name === SNAP_EVENT && !query.with_snaps) return false;\n // `created` is not monotonic with `id` (restore keeps it), so time\n // bounds filter; they never end the scan.\n if (query.created_after && e.created <= query.created_after) return false;\n if (query.created_before && e.created >= query.created_before) return false;\n return true;\n }\n\n private _stream_matches(pattern: string, query: Query, stream: string) {\n return query.stream_exact\n ? stream === pattern\n : RegExp(pattern).test(stream);\n }\n\n /** Index of the stream's latest snapshot, or -1; an explicit `after` wins. */\n private _snap_floor(query: Query | undefined): number {\n if (\n !query?.with_snaps ||\n !query.stream_exact ||\n query.stream === undefined ||\n query.after !== undefined\n )\n return -1;\n for (let j = this._events.length - 1; j >= 0; j--) {\n const e = this._events[j];\n if (e.stream === query.stream && e.name === SNAP_EVENT) return j;\n }\n return -1;\n }\n\n async query<E extends Schemas>(\n callback: (event: Committed<E, keyof E>) => void,\n query?: Query\n ) {\n await sleep();\n // The id bounds (`after`, `before`, the snapshot floor) are one index\n // window over the id-ordered log; every other filter is per event.\n const floor = this._snap_floor(query);\n const lo = floor >= 0 ? floor : this._first_index_after(query?.after ?? -1);\n const hi =\n query?.before !== undefined\n ? this._first_index_after(query.before - 1)\n : this._events.length;\n const with_pii = query?.with_pii !== false;\n let count = 0;\n for (let k = 0; k < hi - lo; k++) {\n const e = this._events[query?.backward ? hi - 1 - k : lo + k];\n if (query && !this.in_query(query, e)) continue;\n await Promise.resolve(\n callback(this._with_pii(e as Committed<E, keyof E>, with_pii))\n );\n count++;\n if (query?.limit && count >= query.limit) break;\n }\n return count;\n }\n\n async commit<E extends Schemas>(\n stream: string,\n msgs: Message<E, keyof E>[],\n meta: EventMeta,\n expectedVersion?: number\n ) {\n await sleep();\n const current_version = this._stream_versions.get(stream) ?? -1;\n if (\n typeof expectedVersion === \"number\" &&\n current_version !== expectedVersion\n ) {\n throw new ConcurrencyError(\n stream,\n current_version,\n msgs as Message<Schemas, keyof Schemas>[],\n expectedVersion\n );\n }\n\n let version = current_version + 1;\n const committed = msgs.map(({ name, data, pii }) => {\n const c: Committed<E, keyof E> = {\n id: this._next_id++,\n stream,\n version,\n created: new Date(),\n name,\n data,\n meta,\n };\n // Stored pii-less, so `forget_pii` never touches the event row.\n this._events.push(c as Committed<Schemas, keyof Schemas>);\n if (pii != null) this._put_pii(stream, c.id, pii);\n version++;\n return this._with_pii(c);\n });\n this._stream_versions.set(stream, version - 1);\n return committed;\n }\n\n async claim(\n lagging: number,\n leading: number,\n by: string,\n millis: number,\n lane?: string\n ) {\n await sleep();\n // Eligibility is `at < correlated_at` on the row alone; the event log\n // is never read. An unmarked row is not claimable.\n const has_work = (s: InMemoryStream): boolean =>\n s.correlated_at !== undefined && s.at < s.correlated_at;\n const available = [...this._streams.values()].filter(\n (s) =>\n s.is_available && has_work(s) && (lane === undefined || s.lane === lane)\n );\n // Lagging: priority DESC, then watermark ASC, like the PG SQL. The\n // `fair` slots ignore priority so sustained high-priority load can't\n // starve a default-priority stream.\n const fair = lagging >= 2 ? Math.max(1, Math.floor(lagging / 4)) : 0;\n const by_priority = [...available].sort(\n (a, b) => b.priority - a.priority || a.at - b.at\n );\n const priority_slice = by_priority.slice(0, lagging - fair);\n const picked = new Set(priority_slice.map((s) => s.stream));\n const fair_slice = [...available]\n .sort((a, b) => a.at - b.at)\n .filter((s) => !picked.has(s.stream))\n .slice(0, fair);\n const lag = [...priority_slice, ...fair_slice].map((s) => ({\n stream: s.stream,\n source: s.source,\n at: s.at,\n lagging: true,\n }));\n const lead = available\n .sort((a, b) => b.at - a.at)\n .slice(0, leading)\n .map((s) => ({\n stream: s.stream,\n source: s.source,\n at: s.at,\n lagging: false,\n }));\n const seen = new Set<string>();\n const combined = [...lag, ...lead].filter((p) => {\n if (seen.has(p.stream)) return false;\n seen.add(p.stream);\n return true;\n });\n return combined\n .map((p) =>\n this._streams.get(p.stream)?.lease({ ...p, by, retry: 0 }, millis)\n )\n .filter((l) => !!l);\n }\n\n async subscribe(\n streams: SubscribeInput[],\n correlated_at?: number,\n correlator?: { key: string; by: string; millis: number }\n ) {\n await sleep();\n\n // The checkpoint is monotonic. With a correlator, position and lease\n // are per key.\n let correlating: boolean | undefined;\n let keyed_at: number | undefined;\n if (correlator) {\n const now = Date.now();\n const held = this._correlators.get(correlator.key);\n // A key with no row yet inherits the shared position, so a new\n // correlator does not re-read history.\n const at = Math.max(held?.at ?? this._correlated_at, correlated_at ?? -1);\n keyed_at = at;\n if (!held || held.until < now || held.by === correlator.by) {\n correlating = true;\n this._correlators.set(correlator.key, {\n at,\n by: correlator.by,\n // Release outright, or a successor in the same ms is still refused.\n until: correlator.millis > 0 ? now + correlator.millis : 0,\n });\n } else {\n // Refused, but the position still advances: this caller may already\n // have scanned and marked.\n correlating = false;\n held.at = at;\n }\n // How far any correlator has read.\n if (correlated_at !== undefined && correlated_at > this._correlated_at)\n this._correlated_at = correlated_at;\n } else if (\n correlated_at !== undefined &&\n correlated_at > this._correlated_at\n )\n this._correlated_at = correlated_at;\n\n let subscribed = 0;\n for (const {\n stream,\n source,\n priority = 0,\n lane = DEFAULT_LANE,\n correlated_at,\n } of streams) {\n const existing = this._streams.get(stream);\n if (existing) {\n // The lane rides the priority max (compared before the bump), so a\n // lower-priority resolution can't re-lane the stream.\n if (priority >= existing.priority) existing.lane = lane;\n existing.bump_priority(priority);\n if (correlated_at !== undefined) existing.mark(correlated_at);\n } else {\n const created = new InMemoryStream(stream, source, priority, lane);\n if (correlated_at !== undefined) created.mark(correlated_at);\n this._streams.set(stream, created);\n subscribed++;\n }\n }\n let watermark = -1;\n for (const s of this._streams.values()) {\n if (s.at > watermark) watermark = s.at;\n }\n return {\n subscribed,\n watermark,\n correlated_at: keyed_at ?? this._correlated_at,\n ...(correlating === undefined ? {} : { correlating }),\n };\n }\n\n async ack(leases: Lease[]) {\n await sleep();\n // One synchronous pass: the in-memory form of the single transaction.\n return leases\n .map((l) => this._streams.get(l.stream)?.ack(l))\n .filter((l) => !!l);\n }\n\n async block(leases: BlockedLease[]) {\n await sleep();\n return leases\n .map((l) => this._streams.get(l.stream)?.block(l, l.error))\n .filter((l) => !!l);\n }\n\n async defer(input: string[] | StreamFilter, deferred_at: number) {\n await sleep();\n const selected = this._select(input);\n for (const s of selected) s.defer(deferred_at);\n return selected.length;\n }\n\n /** De-duplicated like the SQL `stream = ANY(...)`; unknown names skipped. */\n private _select(input: string[] | StreamFilter): InMemoryStream[] {\n if (Array.isArray(input))\n return [...new Set(input)]\n .map((name) => this._streams.get(name))\n .filter((s) => s !== undefined);\n return [...this._streams.values()].filter(this._filter_predicate(input));\n }\n\n private _filter_predicate(\n filter: StreamFilter\n ): (s: InMemoryStream) => boolean {\n const stream_re =\n filter.stream !== undefined && !filter.stream_exact\n ? new RegExp(filter.stream)\n : undefined;\n const source_re =\n filter.source !== undefined && !filter.source_exact\n ? new RegExp(filter.source)\n : undefined;\n return (s) => {\n if (filter.stream !== undefined) {\n if (\n filter.stream_exact\n ? s.stream !== filter.stream\n : !stream_re!.test(s.stream)\n )\n return false;\n }\n if (filter.source !== undefined) {\n if (s.source === undefined) return false;\n if (\n filter.source_exact\n ? s.source !== filter.source\n : !source_re!.test(s.source)\n )\n return false;\n }\n if (filter.blocked !== undefined && s.blocked !== filter.blocked)\n return false;\n if (filter.lane !== undefined && s.lane !== filter.lane) return false;\n return true;\n };\n }\n\n async reset(input: string[] | StreamFilter) {\n await sleep();\n const selected = this._select(input);\n for (const s of selected) s.reset();\n return selected.length;\n }\n\n async forget_pii(stream: string): Promise<number> {\n await sleep();\n const count = this._pii.get(stream)?.size ?? 0;\n this._pii.delete(stream);\n return count;\n }\n\n async unblock(input: string[] | StreamFilter) {\n await sleep();\n const selected = this._select(\n Array.isArray(input) ? input : { ...input, blocked: true }\n );\n return selected.filter((s) => s.unblock()).length;\n }\n\n async prioritize(filter: StreamFilter, priority: number) {\n await sleep();\n const changed = this._select(filter).filter((s) => s.priority !== priority);\n for (const s of changed) s.set_priority(priority);\n return changed.length;\n }\n\n async query_streams(\n callback: (position: StreamPosition) => void,\n query?: QueryStreams\n ): Promise<QueryStreamsResult> {\n await sleep();\n const limit = query?.limit ?? 100;\n const after = query?.after;\n const source_matches = query?.source_matches;\n const matches = this._filter_predicate(query ?? {});\n // Reverse-match: the stored `source` pattern must match a requested name.\n const reverse_cache = new Map<string, RegExp>();\n const reverse_match = (source: string): boolean => {\n let re = reverse_cache.get(source);\n if (!re) {\n re = new RegExp(source);\n reverse_cache.set(source, re);\n }\n return source_matches!.some((name) => re!.test(name));\n };\n\n // The default sort is code-unit order, which agrees with the `<=`\n // cursor and the SQL binary collation; `localeCompare` would not.\n const sorted = [...this._streams.keys()]\n .sort()\n .map((stream) => this._streams.get(stream) as InMemoryStream);\n\n let count = 0;\n for (const s of sorted) {\n if (after !== undefined && s.stream <= after) continue;\n if (!matches(s)) continue;\n if (source_matches !== undefined) {\n // No source consumes every stream, so it matches any name.\n if (s.source && !reverse_match(s.source)) continue;\n }\n // Before emitting, so `limit: 0` returns none.\n if (count >= limit) break;\n callback({\n stream: s.stream,\n source: s.source,\n at: s.at,\n retry: s.retry,\n blocked: s.blocked,\n error: s.error,\n priority: s.priority,\n leased_by: s.leased_by,\n leased_until: s.leased_until,\n lane: s.lane,\n deferred_at: s.deferred_at,\n correlated_at: s.correlated_at,\n });\n count++;\n }\n return { maxEventId: this._events.at(-1)?.id ?? -1, count };\n }\n\n async query_stats<E extends Schemas>(\n input: string[] | Pick<StreamFilter, \"stream\" | \"stream_exact\">,\n options?: QueryStatsOptions<E>\n ): Promise<Map<string, StreamStats<E>>> {\n await sleep();\n const exclude = new Set<string>(options?.exclude ?? []);\n const want_tail = options?.tail ?? false;\n const want_count = options?.count ?? false;\n const want_names = options?.names ?? false;\n const before = options?.before;\n const after = options?.after;\n const limit = options?.limit;\n\n const array_targets = Array.isArray(input) ? new Set(input) : null;\n const filter = Array.isArray(input) ? null : input;\n const stream_re =\n filter?.stream !== undefined && !filter.stream_exact\n ? new RegExp(filter.stream)\n : undefined;\n\n const scope_cache = new Map<string, boolean>();\n const in_scope = (stream: string): boolean => {\n const cached = scope_cache.get(stream);\n if (cached !== undefined) return cached;\n let ok = true;\n if (array_targets) {\n ok = array_targets.has(stream);\n } else if (filter?.stream !== undefined) {\n ok = filter.stream_exact\n ? stream === filter.stream\n : // stream_re set when stream is regex\n stream_re!.test(stream);\n }\n scope_cache.set(stream, ok);\n return ok;\n };\n\n type Acc = {\n head: Committed<Schemas, keyof Schemas>;\n tail?: Committed<Schemas, keyof Schemas>;\n count: number;\n names?: Record<string, number>;\n };\n const acc = new Map<string, Acc>();\n for (const e of this._events) {\n if (before !== undefined && e.id >= before) continue;\n if (!in_scope(e.stream)) continue;\n if (exclude.has(e.name as string)) continue;\n let a = acc.get(e.stream);\n if (!a) {\n a = { head: e, count: 0 };\n if (want_tail) a.tail = e;\n if (want_names) a.names = {};\n acc.set(e.stream, a);\n }\n a.head = e;\n a.count++;\n if (want_names) {\n const n = String(e.name);\n a.names![n] = (a.names![n] ?? 0) + 1;\n }\n }\n\n // Code-unit order, to agree with the `<=` cursor (see query_streams).\n const ordered = [...acc.keys()].sort();\n const out = new Map<string, StreamStats<E>>();\n for (const stream of ordered) {\n if (limit !== undefined && out.size >= limit) break;\n if (after !== undefined && stream <= after) continue;\n const a = acc.get(stream)!;\n const stats: {\n head: Committed<Schemas, keyof Schemas>;\n tail?: Committed<Schemas, keyof Schemas>;\n count?: number;\n names?: Record<string, number>;\n } = { head: a.head };\n if (want_tail) stats.tail = a.tail;\n if (want_count) stats.count = a.count;\n if (want_names) stats.names = a.names;\n out.set(stream, stats as StreamStats<E>);\n }\n return out;\n }\n\n async truncate(\n targets: Array<{\n stream: string;\n snapshot?: Schema;\n meta?: EventMeta;\n before?: Date;\n max_id?: number;\n }>\n ) {\n await sleep();\n const result = new Map<\n string,\n {\n deleted: number;\n committed: Committed<Schemas, keyof Schemas>;\n before?: Date;\n }\n >();\n\n const windowed = targets.filter((t) => t.before !== undefined);\n if (windowed.length) {\n const drop = new Set<number>();\n for (const { stream, before, max_id } of windowed) {\n let boundary: Committed<Schemas, keyof Schemas> | undefined;\n for (const e of this._events) {\n if (\n e.stream === stream &&\n e.name === SNAP_EVENT &&\n e.created < before! &&\n (max_id === undefined || e.id <= max_id) &&\n (!boundary || e.id > boundary.id)\n )\n boundary = e;\n }\n if (!boundary) continue; // no qualifying snapshot → no-op\n let deleted = 0;\n for (const e of this._events) {\n if (e.stream === stream && e.id < boundary.id) {\n drop.add(e.id);\n this._pii.get(stream)?.delete(e.id);\n deleted++;\n }\n }\n result.set(stream, { deleted, committed: boundary, before });\n }\n if (drop.size) this._events = this._events.filter((e) => !drop.has(e.id));\n }\n\n const full = targets.filter((t) => t.before === undefined);\n // Per target, like the SQL adapters, so a stream listed twice gets one seed.\n for (const { stream, snapshot, meta } of full) {\n let deleted = 0;\n this._events = this._events.filter((e) => {\n if (e.stream !== stream) return true;\n deleted++;\n return false;\n });\n // Subscriptions untouched; `seed()` reaps inert ones.\n this._stream_versions.delete(stream);\n this._pii.delete(stream);\n const event: Committed<Schemas, keyof Schemas> = {\n id: this._next_id++,\n stream,\n version: 0,\n created: new Date(),\n name: snapshot !== undefined ? SNAP_EVENT : TOMBSTONE_EVENT,\n data: snapshot ?? {},\n meta: meta ?? { correlation: \"\", causation: {} },\n };\n this._events.push(event);\n this._stream_versions.set(stream, 0);\n result.set(stream, { deleted, committed: event });\n }\n return result;\n }\n\n /** A throw inside the driver restores the captured state. Ids restart at 0. */\n async restore(\n driver: (\n callback: (event: Committed<Schemas, keyof Schemas>) => Promise<number>\n ) => Promise<void>\n ): Promise<void> {\n await sleep();\n const prev_events = this._events;\n const prev_next_id = this._next_id;\n const prev_streams = this._streams;\n const prev_stream_versions = this._stream_versions;\n const prev_pii = this._pii;\n const prev_correlated_at = this._correlated_at;\n const prev_correlators = new Map(\n [...this._correlators].map(([k, v]) => [k, { ...v }])\n );\n // Renumbered from 0, so checkpoints restart too; leases are kept.\n this._correlated_at = -1;\n for (const c of this._correlators.values()) c.at = -1;\n this._events = [];\n this._next_id = 0;\n this._streams = new Map();\n this._stream_versions = new Map();\n this._pii = new Map();\n try {\n await driver(async (event) => {\n const id = this._next_id++;\n // Split `pii` out like `commit`, so `forget_pii` erases restored PII.\n const { pii, ...rest } = event;\n const committed: Committed<Schemas, keyof Schemas> = { ...rest, id };\n this._events.push(committed);\n if (pii != null) this._put_pii(event.stream, id, pii);\n // Last event per stream wins.\n this._stream_versions.set(event.stream, event.version);\n return id;\n });\n } catch (err) {\n this._events = prev_events;\n this._next_id = prev_next_id;\n this._streams = prev_streams;\n this._stream_versions = prev_stream_versions;\n this._pii = prev_pii;\n this._correlated_at = prev_correlated_at;\n this._correlators = prev_correlators;\n throw err;\n }\n }\n}\n","import type { Disposer } from \"./types/index.js\";\n\n/**\n * The shape {@link register_weak_disposer} needs from a `WeakRef`. Declared\n * structurally so tests can hand in a stub that reports its target as\n * collected — real garbage collection is not schedulable, and a guarantee\n * about releasing memory deserves a deterministic test.\n */\nexport type RefLike<T extends object> = { deref: () => T | undefined };\n\n/**\n * A registered cleanup function, optionally tied to the lifetime of the\n * object it cleans up. `ref` present means \"run this only while its target\n * is still reachable\" — the entry holds no strong reference to that target,\n * so registering never keeps it alive. The target is handed back to `run`,\n * so a weak disposer never has to re-check what the registry just proved.\n */\ntype Entry = {\n readonly run: (target: never) => Promise<void>;\n readonly ref?: RefLike<object>;\n};\n\n/** Registered cleanup functions, executed in reverse order during shutdown. */\nconst entries: Entry[] = [];\n\n/**\n * Drop entries whose target has been collected.\n *\n * Called on every registration so the registry stays proportional to the\n * live objects rather than to every object ever built. That matters for apps\n * that mint short-lived Acts — one per tenant, per request, per test — where\n * the registry would otherwise grow without bound for the process lifetime.\n */\nconst prune = (): void => {\n for (let i = entries.length - 1; i >= 0; i--) {\n const { ref } = entries[i];\n if (ref && !ref.deref()) entries.splice(i, 1);\n }\n};\n\n/** Register a cleanup function that runs unconditionally at teardown. */\nexport const register_disposer = (run: Disposer): void => {\n prune();\n entries.push({ run });\n};\n\n/**\n * Register a cleanup function bound to `ref`'s target, held weakly.\n *\n * The registry never retains the target, so an object that becomes\n * unreachable is collectable whether or not it was cleaned up first, and its\n * entry is skipped at teardown — there is nothing left to clean up.\n */\nexport const register_weak_disposer = <T extends object>(\n ref: RefLike<T>,\n run: (target: T) => Promise<void>\n): void => {\n prune();\n entries.push({\n run: run as (target: never) => Promise<void>,\n ref: ref as RefLike<object>,\n });\n};\n\n/**\n * Run every live disposer in reverse registration order, sequentially, so a\n * disposer can rely on later-registered ones having already finished.\n *\n * Registrations are left in place, so a second teardown call re-runs them,\n * exactly as before this registry learned about weak entries.\n */\nexport const run_disposers = async (): Promise<void> => {\n for (const { run, ref } of [...entries].reverse()) {\n if (!ref) {\n await (run as Disposer)();\n continue;\n }\n const target = ref.deref();\n if (target) await (run as (t: object) => Promise<void>)(target);\n }\n};\n","/**\n * @module scoped\n * @category Internal\n *\n * Ambient execution context — every `AsyncLocalStorage` the framework owns\n * lives here, and so does every operation on one. No other module calls\n * `.run()` or `.getStore()`; they ask for a runner or a reader instead, so\n * this file is the single place to look at the abstraction.\n *\n * Two contexts:\n *\n * - **ports** — the active Act's store/cache bag, so `store()` / `cache()`\n * resolve per-Act rather than per-process. Installed by the\n * orchestrator via {@link make_run_scoped}, read by the port singletons\n * via {@link current_ports}.\n * - **reaction** — the event a handler is processing, so a dispatch made\n * anywhere inside that handler can thread `reactingTo` whichever `IAct`\n * reference made the call. Installed via {@link run_reacting},\n * read at the orchestrator boundary via {@link current_reacting}.\n *\n * Keeping the mechanics here keeps ambient state out of `internal/`, whose\n * modules are stateless implementations that receive what they need.\n *\n * @internal\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type {\n Actor,\n Cache,\n Committed,\n IAct,\n Schemas,\n Store,\n} from \"./types/index.js\";\n\n/** Per-Act ports bag. Both required together — a shared cache across stores would collide on stream keys. */\nexport type Scoped = {\n readonly store: Store;\n readonly cache: Cache;\n};\n\n/**\n * What an Act actually installs in its frame: the ports a caller passed,\n * plus per-Act settings that runtime code has to read from the *running*\n * Act rather than from whatever closure it was built in.\n *\n * `autoclose_window` is here because the autoclose reactions are\n * synthesized once into the shared registry and handed by reference to\n * every Act built from that builder, so a window captured at synthesis is\n * the first tenant's window for everyone. The frame is per-Act, so\n * reading it here is what makes the setting per-Act too.\n *\n * Wider than {@link Scoped} on purpose: `Scoped` types what a caller\n * *passes* through `ActOptions.scoped` and is public; this is what the\n * orchestrator *installs* and is not.\n *\n * @internal\n */\nexport type ActFrame = Scoped & {\n readonly autoclose_window?: {\n readonly start: number;\n readonly end: number;\n readonly timeZone: string;\n };\n};\n\n/**\n * AsyncLocalStorage carrying the active Act's ports.\n *\n * Exported for in-repo tooling that measures the context itself (the\n * scope-overhead bench). NOT public: `ports.ts` no longer re-exports it and\n * `index.ts` reaches this module only for the `Scoped` type, so it is not\n * importable from the package. Everything else uses the helpers below.\n */\nexport const scoped = new AsyncLocalStorage<ActFrame>();\n\n/**\n * The reaction currently running, as a box the handler can empty.\n *\n * A frame captured by work the handler started and did not await outlives the\n * handler and can never be unbound. The *frame* is unreclaimable, but the\n * *box inside it* is not: clearing `event` as the handler settles turns every\n * later read through that frame into \"no reaction\", without anyone having to\n * ask a second question.\n *\n * Not reachable from `index.ts`.\n */\ntype Reacting = { event: Committed<Schemas, string> | undefined };\n\nconst reacting = new AsyncLocalStorage<Reacting>();\n\n/**\n * Builds the runner an Act uses to enter its own port scope.\n *\n * Every Act gets a frame, including one built without `ActOptions.scoped` —\n * that one carries the singleton adapters (see `default_scope` in `ports.ts`).\n * Entering unconditionally is what makes an Act's ports its own: a runner that\n * collapsed to `fn()` for a singleton Act did not leave whatever frame it was\n * called from, so dispatching into a shared Act from inside a tenant's handler\n * resolved `store()` to that tenant and wrote the shared Act's events into the\n * tenant's log.\n *\n * @internal\n */\nexport function make_run_scoped(\n bag: ActFrame\n): <T>(fn: () => Promise<T>) => Promise<T> {\n return (fn) => scoped.run(bag, fn);\n}\n\n/**\n * The running Act's off-hours autoclose window, or `undefined` when it\n * declared none (or when read outside any Act).\n *\n * Read at resolution time rather than captured at synthesis: the autoclose\n * reactions belong to the shared registry, and only the frame knows which\n * Act is running them.\n *\n * @internal\n */\nexport function current_autoclose_window(): ActFrame[\"autoclose_window\"] {\n return scoped.getStore()?.autoclose_window;\n}\n\n/**\n * The active Act's ports, or `undefined` outside any Act.\n *\n * Every Act runs in a frame, so this is `undefined` only for a call made\n * outside one — `store()` and `cache()` fall back to the singleton adapters\n * there, which is what a bare `store()` in application setup expects.\n *\n * @internal\n */\nexport function current_ports(): Scoped | undefined {\n return scoped.getStore();\n}\n\n/**\n * Runs `fn` with `event` installed as the triggering-event context.\n *\n * Entered per payload rather than per lease: the context has to unwind with\n * the handler so it never reaches the drain cycle, and work a handler started\n * without awaiting has to resume into its own event's frame.\n *\n * @internal\n */\nfunction run_reacting<T>(\n event: Committed<Schemas, string>,\n fn: () => Promise<T>\n): Promise<T> {\n const box: Reacting = { event };\n return reacting.run(box, async () => {\n try {\n return await fn();\n } finally {\n // Anything still running keeps this frame; from here it reads empty.\n box.event = undefined;\n }\n });\n}\n\n/**\n * The event being reacted to, or `undefined` outside a running handler —\n * including inside work that outlived one.\n *\n * @internal\n */\nexport function current_reacting(): Committed<Schemas, string> | undefined {\n return reacting.getStore()?.event;\n}\n\n/**\n * Everything a reaction handler runs inside: the `IAct` facade it is handed\n * as its third argument, and the triggering-event context that every dispatch\n * made within it resolves — including one through a captured `app`.\n *\n * Built here rather than in the dispatcher so the dispatcher never has to\n * know how either half works; it receives this whole and calls it.\n *\n * @internal\n */\nexport type ReactionScope<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n> = {\n readonly app: IAct<TEvents, TActions, TActor>;\n readonly run: <T>(\n event: Committed<Schemas, string>,\n fn: () => Promise<T>\n ) => Promise<T>;\n};\n\n/**\n * Assembles the reaction scope from the orchestrator's bound `IAct` methods.\n *\n * @internal\n */\nexport function make_reaction_scope<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n>(\n app: IAct<TEvents, TActions, TActor>\n): ReactionScope<TEvents, TActions, TActor> {\n return { app, run: run_reacting };\n}\n","import { ConsoleLogger } from \"./adapters/console-logger.js\";\nimport { InMemoryCache } from \"./adapters/in-memory-cache.js\";\nimport { InMemoryStore } from \"./adapters/in-memory-store.js\";\nimport { config } from \"./config.js\";\nimport { register_disposer, run_disposers } from \"./disposers.js\";\nimport { current_ports, type Scoped } from \"./scoped.js\";\nimport type {\n Cache,\n Disposable,\n Disposer,\n Logger,\n Store,\n} from \"./types/index.js\";\n\n// `Scoped` is the type of the public `ActOptions.scoped` bag, so it stays\n// exported. The AsyncLocalStorage carrying it does not: it is a mechanism,\n// it was only ever reachable because `index.ts` star-exports this module,\n// and its own doc-comment already declared it internal.\nexport type { Scoped } from \"./scoped.js\";\n\n/**\n * Port/adapter infrastructure for the Act framework.\n *\n * All infrastructure concerns (logging, storage, caching) are managed as\n * singleton adapters injected via port functions. Each port follows the same\n * pattern: first call wins with a sensible default, optional adapter injection.\n *\n * - `log()` — structured logging (default: ConsoleLogger)\n * - `store()` — event persistence (default: InMemoryStore)\n * - `cache()` — state checkpoints (default: InMemoryCache)\n * - `dispose()` — register cleanup functions for graceful shutdown\n *\n * @module ports\n */\n\n/**\n * List of exit codes for process termination. Consumed by signal handlers\n * and {@link disposeAndExit}; not part of the user-facing surface.\n *\n * @internal\n */\nexport const ExitCodes = [\"ERROR\", \"EXIT\"] as const;\n\n/**\n * Type for allowed exit codes.\n *\n * - `\"ERROR\"` — abnormal termination (uncaught exception, unhandled rejection)\n * - `\"EXIT\"` — clean shutdown (SIGINT, SIGTERM, or manual trigger)\n *\n * @internal\n */\nexport type ExitCode = (typeof ExitCodes)[number];\n\n// ---------------------------------------------------------------------------\n// Port factory\n// ---------------------------------------------------------------------------\n\n/**\n * Factory function that creates or returns the injected adapter.\n * @internal\n */\ntype Injector<Port extends Disposable> = (adapter?: Port) => Port;\n\n/** Singleton adapter registry, keyed by injector function name. */\nconst adapters = new Map<string, Disposable>();\n\n/**\n * Creates a singleton port with optional adapter injection.\n *\n * The first call initializes the adapter (using the provided adapter or the\n * injector's default). Subsequent calls return the cached singleton. Adapters\n * are disposed in reverse registration order during {@link disposeAndExit}.\n *\n * @param injector - Named function that creates the default adapter\n * @returns Port function: call with no args to get the singleton, or pass an\n * adapter on the first call to override the default\n *\n * @example\n * ```typescript\n * const store = port(function store(adapter?: Store) {\n * return adapter || new InMemoryStore();\n * });\n * const s = store(); // InMemoryStore\n * ```\n */\nexport function port<Port extends Disposable>(injector: Injector<Port>) {\n return (adapter?: Port): Port => {\n if (!adapters.has(injector.name)) {\n const injected = injector(adapter);\n adapters.set(injector.name, injected);\n // log() is now in adapters (or this IS the log port we just registered),\n // so the recursive call resolves immediately. Routing through the logger\n // means level gating (e.g. silenced in tests at fatal) takes effect.\n log().info(`[act] + ${injector.name}:${injected.constructor.name}`);\n }\n return adapters.get(injector.name) as Port;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Ports: log, store, cache\n// ---------------------------------------------------------------------------\n\n/**\n * Gets or injects the singleton logger.\n *\n * By default, Act uses a built-in {@link ConsoleLogger} that emits JSON lines\n * in production (compatible with GCP, AWS CloudWatch, Datadog) and colorized\n * output in development — zero external dependencies.\n *\n * For pino, inject a `PinoLogger` from `@rotorsoft/act-pino` before building\n * your application.\n *\n * @param adapter - Optional logger implementation to inject\n * @returns The singleton logger instance\n *\n * @example Default console logger\n * ```typescript\n * import { log } from \"@rotorsoft/act\";\n * const logger = log();\n * logger.info(\"Application started\");\n * ```\n *\n * @example Injecting pino\n * ```typescript\n * import { log } from \"@rotorsoft/act\";\n * import { PinoLogger } from \"@rotorsoft/act-pino\";\n * log(new PinoLogger({ level: \"debug\", pretty: true }));\n * ```\n *\n * @see {@link Logger} for the interface contract\n * @see {@link ConsoleLogger} for the default implementation\n */\nexport const log = port(function log(adapter?: Logger) {\n const cfg = config();\n return (\n adapter ||\n new ConsoleLogger({\n level: cfg.logLevel,\n pretty: cfg.env !== \"production\",\n })\n );\n});\n\n/**\n * Gets or injects the singleton event store.\n *\n * By default, Act uses an {@link InMemoryStore} suitable for development and\n * testing. For production, inject a persistent store like `PostgresStore` from\n * `@rotorsoft/act-pg` before building your application.\n *\n * **Important:** Store injection must happen before creating any Act instances.\n * Once set, the store cannot be changed without restarting the application.\n *\n * @param adapter - Optional store implementation to inject\n * @returns The singleton store instance\n *\n * @example Default in-memory store\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n * const s = store();\n * ```\n *\n * @example Injecting PostgreSQL\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n * import { PostgresStore } from \"@rotorsoft/act-pg\";\n *\n * store(new PostgresStore({\n * host: \"localhost\",\n * port: 5432,\n * database: \"myapp\",\n * user: \"postgres\",\n * password: \"secret\",\n * }));\n * ```\n *\n * @see {@link Store} for the interface contract\n * @see {@link InMemoryStore} for the default implementation\n */\n// ALS check lives outside `port()` — its cache fires only once, so the\n// per-call branch on a scoped Act has to be in the public wrapper.\nconst _store = port(function store(adapter?: Store): Store {\n return adapter ?? new InMemoryStore();\n});\n\nexport const store = ((adapter?: Store): Store => {\n return current_ports()?.store ?? _store(adapter);\n}) as (adapter?: Store) => Store;\n\n/**\n * Gets or injects the singleton cache.\n *\n * By default, Act uses an {@link InMemoryCache} (LRU, maxSize 1000). For\n * distributed deployments, inject a Redis-backed cache before building your\n * application.\n *\n * @param adapter - Optional cache implementation to inject\n * @returns The singleton cache instance\n *\n * @see {@link Cache} for the interface contract\n * @see {@link InMemoryCache} for the default implementation\n */\nconst _cache = port(function cache(adapter?: Cache) {\n return adapter ?? new InMemoryCache();\n});\n\nexport const cache = ((adapter?: Cache): Cache => {\n return current_ports()?.cache ?? _cache(adapter);\n}) as (adapter?: Cache) => Cache;\n\n/**\n * The ports bag an Act without `ActOptions.scoped` runs in: the singleton\n * adapters, read through the same frame a scoped Act uses.\n *\n * Every Act entering a frame is what keeps its ports its own. Without one, a\n * shared Act called from inside a tenant's handler inherited that tenant's\n * frame and committed to the tenant's store.\n *\n * The properties are getters on purpose. The adapters are resolved lazily and\n * injected after `act().build()` in the normal case — `store(new PgStore())`\n * in application setup, or a test's `beforeEach` — so capturing them when the\n * bag is made would pin whatever existed at build time. They read the raw\n * resolvers rather than the public `store()`/`cache()`, which consult the\n * frame this bag *is* and would recurse.\n *\n * @internal\n */\nexport const default_scope = (): Scoped => DEFAULT_SCOPE;\n\nconst DEFAULT_SCOPE: Scoped = {\n get store() {\n return _store();\n },\n get cache() {\n return _cache();\n },\n};\n\n// ---------------------------------------------------------------------------\n// Disposal\n// ---------------------------------------------------------------------------\n\n/**\n * Registered cleanup functions live in `disposers.ts`, which holds\n * lifetime-bound entries weakly so registering never pins its target for the\n * process lifetime. The public surface here is unchanged.\n */\n\n/**\n * Disposes all registered adapters and disposers, then exits the process.\n *\n * Execution order:\n * 1. Custom disposers (registered via {@link dispose}) — in reverse order\n * 2. Port adapters (log, store, cache) — in reverse registration order\n * 3. Adapter registry is cleared\n * 4. Process exits (skipped in test environment)\n *\n * In production, `\"ERROR\"` exits are silently ignored to avoid crashing on\n * transient failures (e.g. an uncaught promise in a non-critical path).\n *\n * @param code - Exit code: `\"EXIT\"` for clean shutdown (exit 0),\n * `\"ERROR\"` for abnormal termination (exit 1)\n */\nexport async function disposeAndExit(code: ExitCode = \"EXIT\"): Promise<void> {\n if (code === \"ERROR\" && config().env === \"production\") {\n // Surface the swallow so incident triage can see it. Without this\n // log the framework looks unresponsive after an uncaught exception\n // in prod — exactly when operators most need a breadcrumb.\n log().warn(\n \"disposeAndExit('ERROR') ignored in production — process kept alive\"\n );\n return;\n }\n\n // Run sequentially in reverse registration order so a disposer can rely on\n // later-registered disposers (and adapters on later-registered adapters)\n // having already finished — Promise.all would race them.\n await run_disposers();\n for (const adapter of [...adapters.values()].reverse()) {\n await adapter.dispose();\n log().info(`[act] - ${adapter.constructor.name}`);\n }\n adapters.clear();\n config().env !== \"test\" && process.exit(code === \"ERROR\" ? 1 : 0);\n}\n\n/**\n * Registers a cleanup function for graceful shutdown.\n *\n * Disposers are called automatically on SIGINT, SIGTERM, uncaught exceptions,\n * and unhandled rejections. They execute in reverse registration order before\n * port adapters are disposed.\n *\n * @param disposer - Async function to call during cleanup. Omit to get a\n * reference to {@link disposeAndExit} without registering.\n * @returns Function to manually trigger disposal and exit\n *\n * @example\n * ```typescript\n * import { dispose } from \"@rotorsoft/act\";\n *\n * const db = connectDatabase();\n * dispose(async () => await db.close());\n *\n * // In tests\n * afterAll(async () => await dispose()());\n * ```\n *\n * @see {@link disposeAndExit} for the full shutdown sequence\n */\nexport function dispose(\n disposer?: Disposer\n): (code?: ExitCode) => Promise<void> {\n disposer && register_disposer(disposer);\n return disposeAndExit;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * Event name used internally for snapshot events in the event store.\n * Snapshot events store a full state checkpoint, enabling efficient cold-start\n * recovery without replaying the entire event stream.\n */\nexport const SNAP_EVENT = \"__snapshot__\";\n\n/**\n * Event name used internally for tombstone events in the event store.\n * A tombstone marks a stream as permanently closed — no further writes\n * are permitted until the stream is explicitly restarted via `close()`.\n *\n * @see {@link Act.close} for the close-the-books API\n */\nexport const TOMBSTONE_EVENT = \"__tombstone__\";\n\n/**\n * Name of the implicit lane every reaction lands in unless its `.to({lane})`\n * declaration says otherwise. Acts that don't call\n * `.withLane(...)` see only this lane, and behavior is identical to\n * pre-1103 single-controller drain.\n *\n * Persisted on `streams.lane` and threaded as the strict-typed default in\n * builder generics — `lane?: TLanes` always includes `\"default\"`.\n */\nexport const DEFAULT_LANE = \"default\";\n","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 classify_registry,\n type EventLaneSet,\n} from \"./builders/build-classify.js\";\nimport {\n build_handle,\n build_handle_batch,\n} from \"./builders/reaction-builder.js\";\nimport { register_weak_disposer } from \"./disposers.js\";\nimport {\n type AuditDeps,\n audit,\n bare_patch,\n build_drain,\n build_es,\n CircuitBreaker,\n type CircuitBreakerOptions,\n type CircuitState,\n CloseLock,\n CorrelateCycle,\n catch_up_correlation,\n close_correlation,\n DEFAULT_LEASE_MILLIS,\n DEFAULT_MAX_SUBSCRIBED_STREAMS,\n DEFAULT_SETTLE_DEBOUNCE_MS,\n DrainController,\n type DrainOps,\n default_correlator,\n type EsOps,\n FOLD_RESET,\n type Handle,\n type HandleBatch,\n MAX_SHUTDOWN_GRACE_MS,\n type PatchFn,\n type ResettableBatchHandler,\n resolveAutocloseConfig,\n resolveCircuitBreakerConfig,\n resolveDrainConfig,\n resolveSettleConfig,\n resolveShutdownConfig,\n run_close_cycle,\n SettleLoop,\n scan,\n walk_streams,\n} from \"./internal/index.js\";\nimport {\n current_reacting,\n make_reaction_scope,\n make_run_scoped,\n} from \"./scoped.js\";\n\n// Public re-exports: these appear in ActOptions / ActLifecycleEvents above.\nexport type { CircuitBreakerOptions, CircuitState } from \"./internal/index.js\";\n\nimport { cache, default_scope, log, type Scoped, store } from \"./ports.js\";\nimport { StoreError } from \"./types/errors.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 DoOptions,\n Drain,\n DrainOptions,\n EventSink,\n EventSource,\n IAct,\n LaneConfig,\n Lease,\n LoadTarget,\n Logger,\n Query,\n Registry,\n ScanOptions,\n ScanResult,\n Schema,\n SchemaRegister,\n Schemas,\n SettleOptions,\n ShutdownOptions,\n Snapshot,\n State,\n Store,\n StoreNotification,\n StreamFilter,\n StreamPosition,\n Target,\n} from \"./types/index.js\";\n\n// Re-export the autoclose config surface so operators can\n// `import { DEFAULT_AUTOCLOSE_CYCLE_MINUTES, resolveAutocloseConfig }\n// from \"@rotorsoft/act\"`. The implementation lives in\n// `internal/config.ts` (the single home for builder-facing config bags)\n// to keep this orchestrator file focused on the `Act` class.\nexport {\n type AutocloseConfig,\n type AutoclosePolicy,\n DEFAULT_AUTOCLOSE_CYCLE_MINUTES,\n DEFAULT_CLOSE_BATCH_SIZE,\n DEFAULT_CLOSE_YIELD_MS,\n DEFAULT_MAX_SUBSCRIBED_STREAMS,\n DEFAULT_SETTLE_DEBOUNCE_MS,\n resolveAutocloseConfig,\n} from \"./internal/index.js\";\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 *\n * The first parameter is kept (unused) for arity compatibility: `committed`\n * carries snapshots of whichever state each action targeted, so its honest\n * element type is `Snapshot<Schema, TEvents>` — the register map itself was\n * never the shape of any snapshot's state.\n */\nexport type ActLifecycleEvents<\n _TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n> = {\n committed: Snapshot<Schema, 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 * A stream's sensitive-data payload was wiped via {@link Act.forget}.\n * Fires exactly once per successful `forget(stream)` call — idempotent\n * second calls (no PII left on the stream) return `eventCount: 0` and\n * do NOT re-emit. Apps that never call `forget()` never see this event.\n *\n * Listeners use it for the compliance side of GDPR / CCPA: audit log,\n * downstream cache busts, projection-side wipes that the framework\n * doesn't reach (e.g., search indexes, ETL caches). The framework's own\n * cache is invalidated by `forget()` itself before the event fires.\n */\n forgotten: { stream: string; at: Date; eventCount: number };\n /**\n * A store operation failed during the drain loop. Fires on\n * every failed drain cycle — typically a {@link StoreError} from a\n * degraded backend — carrying the orchestrator circuit breaker's state\n * after the failure (`open` means the drain loop has backed off and will\n * retry after the cooldown). Listen to alert on a degraded store; the\n * framework logs the same error regardless. Emitted only when a listener\n * is registered (Node's `EventEmitter` throws on an unhandled `\"error\"`).\n */\n error: { error: unknown; circuit: CircuitState };\n};\n\n/**\n * Options for {@link Act} construction (passed via {@link ActBuilder.build}).\n *\n * @property maxSubscribedStreams - Cap for the LRU tracking what each\n * dynamically resolved reaction target was last subscribed at. Statically\n * declared targets are held outside it and never evicted, so their lane\n * and priority stay owned by the build-time subscribe.\n * 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. 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. When\n * omitted, Act uses {@link default_correlator}, 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. */\n readonly onlyLanes?: ReadonlyArray<TLanes>;\n /**\n * Subscribe to {@link Store.notify} on this instance. Defaults\n * to `true`. Set `false` on instances that only commit and never\n * react — the subscriber-connection budget is the practical scaling\n * ceiling for the notify/listen pattern, and writer-only fleets\n * spend it for nothing when they subscribe to a channel they never\n * read. Commits still emit notifications (that's part of the\n * store's commit protocol); only the subscriber side is gated.\n */\n readonly listen?: boolean;\n /**\n * Run the local reaction pipeline on this instance. Defaults\n * to `true`. Set `false` on writer-only or sidecar instances: drain\n * controllers' auto-cycle workers don't start, `correlate()` /\n * `drain()` / `settle()` become no-ops, and the notify handler\n * skips its drain-wakeup arm (but still emits the `notified`\n * lifecycle event so observability sidecars work).\n */\n readonly drain?: boolean;\n /**\n * Orchestrator circuit breaker for the drain loop. After\n * `failureThreshold` consecutive store failures the breaker opens and\n * the drain loop skips `claim()` for `cooldownMs` instead of hammering a\n * down backend, then allows a half-open trial. Out-of-range values throw\n * a `ZodError` at `act().build()`. Defaults: threshold 5, cooldown 30s.\n */\n readonly circuitBreaker?: CircuitBreakerOptions;\n /**\n * @deprecated Accepted, validated, and ignored. It paced the off-hours\n * re-check of the old autoclose sweep; the synthesized autoclose reaction now derives its re-check\n * directly from `autocloseWindow` — a tick landing outside the window\n * parks until the exact instant the window opens, so there is no\n * polling cadence to configure (and nothing minute-denominated on the\n * close surface). Still validated as an integer `[1, 1440]` so typos\n * keep failing loudly at `act().build()`. Will be removed in the next\n * major.\n */\n readonly autocloseCycleMinutes?: number;\n /**\n * @deprecated Unused since the autoclose sweep was replaced by a\n * synthesized per-aggregate reaction — nothing pages the store in\n * batches anymore, so nothing reads this. Accepted and validated\n * (`[1, 1024]`) for compatibility; will be removed in the next major.\n */\n readonly closeBatchSize?: number;\n /**\n * @deprecated Unused: the sweep that yielded between\n * successive `Store.truncate` calls no longer exists; closes are\n * staged per stream by the autoclose reaction. Accepted and validated\n * (`[0, 1000]`) for compatibility; will be removed in the next major.\n */\n readonly closeYieldMs?: number;\n /**\n * @deprecated Unused: the sweep-side predicate try/catch\n * this flag steered no longer exists; a throwing policy predicate now\n * follows the reaction retry path (`blockOnError: false`, three\n * retries). Accepted for compatibility; will be removed in the next\n * major.\n */\n readonly closeOnError?: boolean;\n /**\n * Optional off-hours window restricting when autoclose evaluates. A\n * synthesized autoclose reaction that triggers outside the window\n * defers to the next instant the window opens — derived from the\n * window itself, no polling cadence. Hours are `[0, 23]` integers in\n * `timeZone` (IANA, default `\"UTC\"`, DST-correct); `start > end` is\n * an overnight window (e.g. `{ start: 22, end: 6 }`). Omit to\n * evaluate regardless of clock time.\n */\n readonly autocloseWindow?: {\n readonly start: number;\n readonly end: number;\n readonly timeZone?: string;\n };\n /**\n * Validate folded state against its declared Zod schema after every\n * reduction. Off by default.\n *\n * When `true`, each time an event is folded into state — on the\n * command path (`do`), on `load`/replay, and inside projection-fold\n * projections — the merged full state is parsed against the owning\n * state's `state({ Name: schema })` schema. A reducer that produces\n * schema-violating state (the calculator divide-by-zero NaN\n * class) throws a {@link ValidationError} at the triggering event,\n * whose `target` names the state and the event (`<state>.<event>#<id>`)\n * — instead of the bad value propagating and surfacing hops later as a\n * confusing downstream error.\n *\n * This is a **debugging / CI aid, not a production guard**. Turn it on\n * in development and CI to catch total-reducer bugs at the source; the\n * framework already validates action inputs and emitted events, so the\n * reduced state is the one shape it otherwise trusts. The per-event\n * patch step is selected **once at `build()`** (the same way the\n * orchestrator picks bare vs trace-decorated store ops from the log\n * level): when `false` (the default) the fold loop is byte-identical to\n * a bare reduction — the validating patch step is never selected, so\n * there is no per-event cost, not even a branch.\n */\n readonly validateFoldedState?: boolean;\n};\n\n/** Reject `onlyLanes` entries that reference undeclared lanes. */\nfunction validate_only_lanes(\n options: ActOptions,\n lanes: ReadonlyArray<LaneConfig>\n): void {\n if (!options.onlyLanes || options.onlyLanes.length === 0) return;\n const declared = new Set<string>([\"default\", ...lanes.map((l) => l.name)]);\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\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 = act().withState(Counter).build();\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 */\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, TSchemaReg>\n{\n private _emitter = new EventEmitter();\n private readonly _breaker: CircuitBreaker;\n private readonly _listen: boolean;\n private readonly _drain: boolean;\n private readonly _reactive_events: ReadonlySet<string>;\n private readonly _drain_controllers: Map<\n string,\n DrainController<TEvents, TActions, TSchemaReg>\n >;\n private readonly _correlate: CorrelateCycle<TSchemaReg, TEvents, TActions>;\n private readonly _settle: SettleLoop<TEvents>;\n private _poll: ReturnType<typeof setInterval> | undefined;\n /** The deprecated `start_correlations` callback, while the poll runs. */\n private _on_discovered: ((subscribed: number) => void) | undefined;\n /**\n * Wired at construction against the store current then, so a store\n * injected after `build()` is never notified.\n */\n private readonly _notify_disposer: Promise<\n (() => void | Promise<void>) | undefined\n >;\n /** Public registry — kept as-is per the no-prefix-on-public convention. */\n public readonly registry: Registry<\n TSchemaReg,\n TEvents,\n TActions,\n keyof TStateMap & string\n >;\n private readonly _states: Map<string, State<any, any, any>>;\n /**\n * Emit a lifecycle event. The payload type is inferred from the event name\n * via {@link ActLifecycleEvents}.\n *\n * Each listener is contained on its own: a throwing listener is logged,\n * the remaining listeners still run, and the caller (`do()`, `forget()`,\n * `close()`, the drain) never sees the throw, since its durable work has\n * already landed.\n *\n * Uses `rawListeners` so `once` wrappers still de-register themselves, and\n * returns \"had listeners\" to preserve the `EventEmitter.emit` contract.\n */\n emit<E extends keyof ActLifecycleEvents<TSchemaReg, TEvents, TActions>>(\n event: E,\n args: ActLifecycleEvents<TSchemaReg, TEvents, TActions>[E]\n ): boolean {\n const listeners = this._emitter.rawListeners(event as string);\n for (const listener of listeners) {\n try {\n listener(args);\n } catch (error) {\n this._logger.error(error, `${String(event)} listener threw`);\n }\n }\n return listeners.length > 0;\n }\n\n /**\n * The one place a store failure is logged and emitted (the breaker's\n * `on_error`). The emit is guarded: an unhandled `\"error\"` emission\n * would crash the process.\n */\n private _emit_error(error: unknown, circuit: CircuitState): void {\n this._logger.error(error);\n if (this._emitter.listenerCount(\"error\") > 0)\n this.emit(\"error\", { error, circuit });\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 private readonly _batch_handlers: Map<string, BatchHandler<TEvents>>;\n private readonly _es: EsOps;\n private readonly _cd: DrainOps<TEvents>;\n /** Unambiguous: merge rejects an event name declared by two states. */\n private readonly _event_to_state: ReadonlyMap<string, State<any, any, any>>;\n /** Lanes to arm per event; `\"all\"` when a dynamic resolver hides the lane. */\n private readonly _event_to_lanes: ReadonlyMap<string, EventLaneSet>;\n private readonly _audit_deps: AuditDeps;\n private readonly _logger: Logger = log();\n /** This Act's ports: its own bag, or the singleton adapters. */\n private readonly _ports: Scoped;\n /** Runs a body so internal `store()`/`cache()` calls resolve to `_ports`. */\n private readonly _scoped: <T>(fn: () => Promise<T>) => Promise<T>;\n\n private readonly _correlator: Correlator;\n // Bound once, reused by every reaction payload.\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 private readonly _bound_forget = this.forget.bind(this);\n private readonly _handle: Handle<TEvents>;\n private readonly _handle_batch: HandleBatch<TEvents>;\n private readonly _lanes: ReadonlyArray<LaneConfig>;\n\n private readonly _close_lock = new CloseLock();\n /** Every lane a controller can exist for: `\"default\"` plus each declared one. */\n private readonly _declared_lanes: ReadonlyArray<string>;\n\n /** Drain lanes declared via `.withLane(...)`. Implicit default not included. */\n get lanes(): ReadonlyArray<LaneConfig> {\n return this._lanes;\n }\n\n /** Use the {@link act} builder rather than constructing directly. */\n constructor(\n registry: Registry<TSchemaReg, TEvents, TActions, keyof TStateMap & string>,\n states: Map<string, State<any, any, any>> = new Map(),\n batch_handlers: Map<string, BatchHandler<any>> = new Map(),\n options: ActOptions = {},\n lanes: ReadonlyArray<LaneConfig> = [],\n patch_fn: PatchFn = bare_patch\n ) {\n this.registry = registry;\n this._states = states;\n this._batch_handlers = batch_handlers;\n this._lanes = lanes;\n this._declared_lanes = [\"default\", ...lanes.map((l) => l.name)];\n validate_only_lanes(options, lanes);\n // Every Act runs in its own ports frame (the singletons when unscoped),\n // so a shared Act never inherits its caller's frame.\n this._ports = options.scoped ?? default_scope();\n const ports = this._ports;\n this._scoped = make_run_scoped({\n // Getters, not a spread: the singletons resolve lazily, so a later\n // `store(...)` / `cache(...)` still takes effect.\n get store() {\n return ports.store;\n },\n get cache() {\n return ports.cache;\n },\n // Parsed per build, so a bad window throws on every build.\n autoclose_window: resolveAutocloseConfig(options).autocloseWindow,\n });\n this._correlator = options.correlator ?? default_correlator;\n this._es = build_es(this._logger, this._correlator, patch_fn);\n this._cd = build_drain<TEvents>(this._logger);\n // PII stripping is wrapped around handlers at build time, so the\n // dispatcher is PII-unaware.\n this._handle = build_handle<TEvents, TActions, TActor>({\n logger: this._logger,\n reaction_scope: make_reaction_scope({\n do: this._bound_do,\n load: this._bound_load,\n query: this._bound_query,\n query_array: this._bound_query_array,\n forget: this._bound_forget,\n }),\n });\n this._handle_batch = build_handle_batch<TEvents>(this._logger);\n\n const classification = classify_registry(this.registry, this._states);\n this._reactive_events = classification.reactive_events;\n this._event_to_state = classification.event_to_state;\n this._event_to_lanes = classification.event_to_lanes;\n this._listen = options.listen !== false;\n this._drain = options.drain !== false;\n\n // Order matters: controllers read the breaker, the audit bag reads the\n // controller set, settle reads the correlate cycle.\n this._breaker = this._build_breaker(options);\n this._drain_controllers = this._build_drain_controllers(options, lanes);\n this._advise_orphaned_lanes(options);\n this._audit_deps = this._build_audit_deps();\n this._correlate = this._build_correlate(options, classification);\n this._settle = this._build_settle(options);\n\n // Wire cross-process notify against the store current at construction.\n this._notify_disposer = this._wire_notify(this._ports.store);\n\n // Registered weakly, so `dispose()()` reaches a live Act while an\n // unreachable one (per tenant, per test) can still be collected.\n register_weak_disposer(new WeakRef(this), (self) => self.shutdown());\n }\n\n /** Shared by drain, settle and autoclose; bad knobs throw at build. */\n private _build_breaker(options: ActOptions): CircuitBreaker {\n return new CircuitBreaker(\n resolveCircuitBreakerConfig(options.circuitBreaker),\n {\n on_error: (error, circuit) => this._emit_error(error, circuit),\n // When the cooldown elapses, settle once: its scan or claim is the\n // half-open probe that closes or re-opens the breaker.\n on_retry: () => {\n this.settle({ debounceMs: 0 });\n },\n }\n );\n }\n\n /** Apps that declare no lanes pass no lane filter to `claim`. */\n private _build_drain_controllers(\n options: ActOptions,\n lanes: ReadonlyArray<LaneConfig>\n ): Map<string, DrainController<TEvents, TActions, TSchemaReg>> {\n const all_lanes = this._declared_lanes;\n const only_set =\n options.onlyLanes && options.onlyLanes.length > 0\n ? new Set<string>(options.onlyLanes as readonly string[])\n : undefined;\n const active_lanes = only_set\n ? all_lanes.filter((n) => only_set.has(n))\n : all_lanes;\n // Decided by the declared lanes, not the active ones: a worker narrowed\n // to \"default\" must still filter, or it would claim every lane.\n const single_default_lane = lanes.length === 0;\n const controllers = new Map<\n string,\n DrainController<TEvents, TActions, TSchemaReg>\n >();\n for (const name of active_lanes) {\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 batch_handlers: this._batch_handlers,\n handle: this._handle,\n handle_batch: this._handle_batch,\n on_acked: (acked) => this.emit(\"acked\", acked),\n on_blocked: (blocked) => this.emit(\"blocked\", blocked),\n // Reaction-requested close: the same machinery as `app.close`.\n // A store failure reaches the breaker; anything else (the archive\n // callback is app code) is logged here, never counted.\n on_close: async (targets) => {\n try {\n await this._run_close(targets);\n } catch (error) {\n if (error instanceof StoreError) throw error;\n this._logger.error(\n error,\n `Reaction-requested close of ${targets.map((t) => `\"${t.stream}\"`).join(\", \")} failed and was not retried; close it with app.close(...) once the cause is fixed.`\n );\n }\n },\n breaker: this._breaker,\n run_scoped: this._scoped,\n lane: single_default_lane ? undefined : name,\n defaults: cfg && {\n streamLimit: cfg.streamLimit,\n leaseMillis: cfg.leaseMillis,\n },\n });\n // A lane with `cycleMs` drives itself on that timer (not on\n // writer-only instances).\n if (cfg?.cycleMs !== undefined && options.drain !== false)\n controller.start(cfg.cycleMs);\n controllers.set(name, controller);\n }\n return controllers;\n }\n\n /** One process can't see the cluster, so it reports its own lane gaps. */\n private _advise_orphaned_lanes(options: ActOptions): void {\n if (!options.onlyLanes || options.onlyLanes.length === 0) return;\n const active = new Set(this._drain_controllers.keys());\n const orphaned = this._declared_lanes.filter((name) => !active.has(name));\n if (orphaned.length === 0) return;\n const list = orphaned.map((name) => `\"${name}\"`).join(\", \");\n this._logger.info(\n `Act declared ${orphaned.length} orphaned lane(s) on this instance: ${list}. ` +\n `onlyLanes excludes them, so no DrainController claims their streams here — ` +\n `their reactions accumulate un-drained unless a peer worker deploys with these ` +\n `lanes in its onlyLanes. Ensure the cluster invariant holds: the union of every ` +\n `worker's onlyLanes must cover every declared lane. ` +\n `See docs/docs/guides/production-checklist.md § Sizing lanes.`\n );\n }\n\n /** Audit deps, built after the controllers so the lane set is final. */\n private _build_audit_deps(): AuditDeps {\n return {\n store,\n event_to_state: this._event_to_state,\n // Declared lanes, not this process's controllers: a lane another\n // worker drains is not `unknown-lane`.\n declared_lanes: new Set(this._declared_lanes),\n routed_events: new Set(this._event_to_lanes.keys()),\n };\n }\n\n private _build_correlate(\n options: ActOptions,\n classification: ReturnType<\n typeof classify_registry<TSchemaReg, TEvents, TActions>\n >\n ): CorrelateCycle<TSchemaReg, TEvents, TActions> {\n return new CorrelateCycle({\n registry: this.registry,\n static_targets: classification.static_targets,\n cd: this._cd,\n max_subscribed_streams:\n options.maxSubscribedStreams ?? DEFAULT_MAX_SUBSCRIBED_STREAMS,\n // Declared lanes (not active ones): a lane another process claims is\n // still a valid destination.\n declared_lanes: new Set(this._declared_lanes),\n // Built after the controllers, so their keys are the active lanes.\n shard:\n this._drain_controllers.size < this._declared_lanes.length\n ? [...this._drain_controllers.keys()]\n : undefined,\n on_init: () => {\n if (this._drain && this._reactive_events.size > 0) this._arm_all();\n },\n on_init_async: this._drain\n ? () => this._seed_persisted_defers()\n : undefined,\n });\n }\n\n /** Cold start: an idle deferred stream still fires on time after a restart. */\n private async _seed_persisted_defers(): Promise<void> {\n const now = Date.now();\n await walk_streams(store(), (pos) => {\n // A past-due schedule is already claimable.\n if (pos.deferred_at === undefined || pos.deferred_at <= now) return;\n const controller = this._drain_controllers.get(pos.lane ?? \"default\");\n controller?.seed_defer(pos.stream, pos.deferred_at);\n });\n }\n\n private _build_settle(options: ActOptions): SettleLoop<TEvents> {\n return new SettleLoop<TEvents>(\n {\n init: () => this._scoped(() => this._correlate.init()),\n checkpoint: () => this._correlate.checkpoint,\n correlate: (q) => this._correlate_scanned(q, true),\n drain: (o) => this.drain(o),\n on_settled: (drain) => this.emit(\"settled\", drain),\n breaker: this._breaker,\n },\n options.settleDebounceMs ?? DEFAULT_SETTLE_DEBOUNCE_MS\n );\n }\n\n private _shutdown_promise: Promise<void> | undefined;\n\n /**\n * Per-instance teardown: stop scheduling new work, give drain cycles\n * already in flight a bounded chance to finish, then remove lifecycle\n * listeners and tear down the cross-process notify subscription.\n *\n * Scheduling stops first, then in-flight cycles get up to `graceMs` to\n * reach their `ack` (an abandoned handler holds its lease until it\n * expires). Listeners come off after the wait, so they still see work that\n * finished during it. The budget is a ceiling, not a delay; when it runs\n * out, teardown proceeds anyway.\n *\n * Idempotent — repeated calls return the same promise, and the first\n * call's `graceMs` is the one that applies. Registered automatically with\n * the global `dispose()` registry at construction, so process-wide\n * `dispose()()` covers it; test helpers (or operators that mint\n * short-lived Acts) call it explicitly for prompt cleanup.\n *\n * @param options - See {@link ShutdownOptions}. Defaults the grace budget\n * to the largest lane `leaseMillis` (capped at 30s).\n */\n shutdown(options?: ShutdownOptions): Promise<void> {\n if (!this._shutdown_promise) {\n resolveShutdownConfig(options);\n this._shutdown_promise = (async () => {\n this.stop_correlations();\n // Unsubscribe from notify before stopping settle, or a late\n // notification would schedule a cycle nothing cancels. Never rejects.\n const disposer = await this._notify_disposer;\n if (disposer) await disposer();\n this._settle.stop();\n this._breaker.stop();\n for (const c of this._drain_controllers.values()) c.stop();\n await this._await_inflight(options?.graceMs);\n // Hand the correlation lease back last, after the wait (a settle\n // cycle still running would re-take it), and await it so a\n // successor isn't refused.\n await this._scoped(() => this._correlate.release_correlation());\n this._emitter.removeAllListeners();\n })();\n }\n return this._shutdown_promise;\n }\n\n /**\n * The largest `leaseMillis` among lanes with a cycle in flight (the\n * default for none or 0, and for a running settle), capped.\n */\n private _derive_grace_ms(\n running: { readonly lease_millis: number | undefined }[],\n settling: boolean\n ): number {\n // A lane with no lease waits the drain's default lease: as long as its\n // handlers were already allowed to hold a stream.\n let max = settling ? DEFAULT_LEASE_MILLIS : 0;\n for (const c of running)\n max = Math.max(max, c.lease_millis || DEFAULT_LEASE_MILLIS);\n return Math.min(max, MAX_SHUTDOWN_GRACE_MS);\n }\n\n private async _await_inflight(grace_ms?: number): Promise<void> {\n const running = [...this._drain_controllers.values()].filter(\n (c) => c.inflight !== undefined\n );\n // A settle cycle already running keeps going after `stop()`, so wait\n // for it too.\n const settling = this._settle.inflight;\n if (running.length === 0 && !settling) return;\n const grace = grace_ms ?? this._derive_grace_ms(running, !!settling);\n if (grace <= 0) return;\n const inflight = running.map((c) => c.inflight);\n if (settling) inflight.push(settling);\n let timer!: ReturnType<typeof setTimeout>;\n const budget = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, grace);\n timer.unref();\n });\n try {\n await Promise.race([Promise.all(inflight), budget]);\n } finally {\n // Don't leave the budget timer pending when the cycles won the race.\n clearTimeout(timer);\n }\n }\n\n /** Failures are logged, never thrown: `notify` is a hint. */\n private async _wire_notify(\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 // Only the subscriber side is gated; commits still notify.\n if (!this._listen) return undefined;\n try {\n return await s.notify((notification) => {\n // Errors are logged and swallowed so the store's listener survives.\n try {\n this.emit(\"notified\", notification);\n // Arm only the lanes whose reactions match the notified events.\n // A sidecar (`drain: false`) still gets the `notified` event.\n if (this._drain) {\n const armed = this._arm_for_event_names(\n notification.events.map((e) => e.name)\n );\n if (armed) this._settle.schedule({ debounceMs: 0 });\n }\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 options - Per-call dispatch options ({@link DoOptions}) —\n * `reactingTo` to thread correlation, `correlator` to override the\n * framework or orchestrator-level correlator for this call only.\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, { reactingTo: 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 options?: DoOptions<TEvents>\n ) {\n // Resolve the ambient reaction context here so `internal/` never reads\n // ambient state. An explicit `reactingTo` wins.\n const reacting_to = options?.reactingTo ?? current_reacting();\n const do_options =\n reacting_to === options?.reactingTo\n ? options\n : { ...options, reactingTo: reacting_to };\n return this._scoped(async () => {\n const snapshots = await this._es.action(\n this.registry.actions[action],\n action,\n target,\n payload,\n do_options\n );\n // Arm only the lanes whose reactions match the committed events.\n if (this._reactive_events.size > 0)\n // `action()` snapshots always carry their event.\n this._arm_for_event_names(\n snapshots.map((s) => (s.event as { name: string }).name)\n );\n this.emit(\"committed\", snapshots);\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 // Anonymous load (bare stream) — sensitive fields come back as REDACTED.\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 // Auth-aware load — runs `.discloses(predicate)` against the supplied actor.\n async load<\n TNewState extends Schema,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n >(\n state: State<TNewState, TNewEvents, TNewActions>,\n target: LoadTarget<TActor>,\n callback?: (snapshot: Snapshot<TNewState, TNewEvents>) => void\n ): Promise<Snapshot<TNewState, TNewEvents>>;\n async load<TKey extends keyof TStateMap & string>(\n name: TKey,\n target: LoadTarget<TActor>,\n callback?: (snapshot: Snapshot<TStateMap[TKey], TEvents>) => void\n ): Promise<Snapshot<TStateMap[TKey], TEvents>>;\n async load<TNewState extends Schema>(\n stateOrName: State<TNewState, any, any> | string,\n streamOrTarget: string | LoadTarget<TActor>,\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 // Normalize the two surfaces: bare-stream (default-deny — actor\n // undefined → REDACTED on the discloses check) vs LoadTarget\n // (auth-aware — actor flows into `.discloses(predicate)`).\n const target: LoadTarget<Actor> =\n typeof streamOrTarget === \"string\"\n ? {\n stream: streamOrTarget,\n actor: undefined as unknown as Actor,\n asOf,\n }\n : streamOrTarget;\n return await this._es.load(merged, target, callback);\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 const gated = this.registry.query_gate(e.name as string)(e);\n if (!first) first = gated;\n last = gated;\n callback?.(gated);\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) => {\n events.push(this.registry.query_gate(e.name as string)(e));\n }, query);\n return events;\n });\n }\n\n /**\n * Wipe the sensitive-data payload for every event on the stream — see\n * {@link IAct.forget}.\n *\n * Throws on adapters without `Store.forget_pii`, invalidates the cache\n * entry for the stream, emits the `forgotten` lifecycle event with the\n * row count. Idempotent: a second call returns `{eventCount: 0}` and\n * does NOT re-emit.\n *\n * @param stream - Target stream.\n * @returns `{eventCount}` — number of events whose PII column was wiped.\n */\n async forget(stream: string): Promise<{ eventCount: number }> {\n return this._scoped(async () => {\n const s = store();\n if (!s.forget_pii) {\n throw new Error(\n `Store does not implement forget_pii — adapter cannot comply with sensitive-data erasure. ` +\n `Use an adapter that declares pii_isolation: true (e.g. @rotorsoft/act on the in-memory store).`\n );\n }\n const eventCount = await s.forget_pii(stream);\n await cache().invalidate(stream);\n if (eventCount > 0) {\n this.emit(\"forgotten\", { stream, at: new Date(), eventCount });\n }\n return { eventCount };\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()`. It is not only how dynamic targets\n * are discovered: a stream is claimable while `at < correlated_at`, and\n * `correlate` is the only component that raises that mark, so a\n * commit no correlate has seen is not drainable, static targets included. For a\n * higher-level API that handles debouncing, correlation, and signaling\n * 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 // Validate the runtime knobs before anything runs (a bad leaseMillis /\n // streamLimit / eventLimit throws ZodError here, not on the first cycle).\n resolveDrainConfig(options);\n // Writer-only instances run no reactions.\n if (!this._drain)\n return { fetched: [], leased: [], acked: [], blocked: [] };\n return this._scoped(() => this._drain_all(options));\n }\n\n private _arm_all(): void {\n // A commit may also give the next correlate scan something to find.\n this._correlate.arm();\n for (const c of this._drain_controllers.values()) c.arm();\n }\n\n /** Arms only the lanes these events react on; true when any was armed. */\n private _arm_for_event_names(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._arm_all();\n return true;\n }\n for (const lane of set) to_arm.add(lane);\n }\n if (to_arm.size === 0) return false;\n this._correlate.arm();\n for (const lane of to_arm) this._drain_controllers.get(lane)?.arm();\n return true;\n }\n\n /** In parallel, so a slow lane never holds up a fast one. */\n private async _drain_all(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 // Actor-less like `query`/`query_array`, so default-deny.\n // Handlers are unaffected — they read through their own strip.\n fetched.push(\n ...r.fetched.map((f) => ({\n ...f,\n events: f.events.map((e) =>\n this.registry.query_gate(e.name as string)(e)\n ),\n }))\n );\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 const { subscribed, last_id } = await this._correlate_scanned(query);\n return { subscribed, last_id };\n }\n\n /** `correlate` plus `scanned`, which settle needs for the breaker. */\n private async _correlate_scanned(\n query: Query,\n /** Honour the correlation lease — settle and the poller only. */\n lease = false\n ): Promise<{ subscribed: number; last_id: number; scanned: boolean }> {\n // Writer-only instances don't correlate.\n if (!this._drain) return { subscribed: 0, last_id: -1, scanned: false };\n return this._scoped(async () => {\n const { subscribed, last_id, marked, scanned } =\n await this._correlate.correlate(query, lease);\n // Also re-arms correlate, so a backlog scan keeps going.\n if ((subscribed > 0 || marked > 0) && this._reactive_events.size > 0)\n this._arm_all();\n if (subscribed > 0) this._on_discovered?.(subscribed);\n return { subscribed, last_id, scanned };\n });\n }\n\n /**\n * Starts a background poll that settles on a timer: each tick looks for\n * new events, subscribes the streams their reactions target, and drains\n * them.\n *\n * Use it when this process can miss commits — another process writes to a\n * store without `notify`, or a notification is lost. It is the safety net\n * under `notify`: a missed wakeup costs at most one `frequency` of latency.\n *\n * Only one poll runs per Act instance. On a writer-only instance\n * (`drain: false`) each tick is a no-op, like `settle()`.\n *\n * @param query - Only `limit` is used: the most events each correlate pass\n * reads (default 100). The scan always starts at the correlation\n * checkpoint, so `after` is ignored.\n * @param frequency - Milliseconds between ticks (default: 10000)\n * @param callback - Called with the number of newly subscribed streams\n * after each correlate pass that found some.\n * @deprecated Listen to the `\"settled\"` lifecycle event instead.\n * @returns `true` if the poll started, `false` if one is already running\n *\n * @example\n * ```typescript\n * app.start_correlations({ limit: 100 }, 5000);\n * // later\n * app.stop_correlations();\n * ```\n *\n * @see {@link settle} for what each tick runs\n * @see {@link stop_correlations} to stop the poll\n */\n start_correlations(\n query: Query = {},\n frequency = 10_000,\n callback?: (subscribed: number) => void\n ): boolean {\n if (this._poll) return false;\n this._on_discovered = callback;\n const correlate = { limit: query.limit || 100 };\n this._poll = setInterval(() => {\n // No local signal says there is work, so look anyway.\n this._correlate.arm();\n this.settle({ debounceMs: 0, correlate });\n }, frequency);\n return true;\n }\n\n /**\n * Stops the poll started by {@link start_correlations}. Idempotent, and\n * called by `shutdown()`.\n *\n * @see {@link start_correlations}\n */\n stop_correlations() {\n if (this._poll) {\n clearInterval(this._poll);\n this._poll = undefined;\n }\n this._on_discovered = undefined;\n // Hand the correlation lease back, best-effort and not awaited (this\n // method is synchronous; the lease would expire anyway).\n void this._scoped(() => this._correlate.release_correlation());\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 input - Reaction target streams (e.g., projection names) to reset, or a {@link StreamFilter} for bulk operations\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 // Drop every fold cache before the replay, or a warm cache would\n // re-flush stale rows. Cleared for all targets: resolving `input`\n // costs a query, and an extra clear costs one head load per stream.\n for (const handler of this._batch_handlers.values())\n (handler as ResettableBatchHandler<TEvents>)[FOLD_RESET]?.();\n if (count > 0 && this._reactive_events.size > 0) this._arm_all();\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 input - Stream names to unblock, or a {@link StreamFilter} for bulk recovery\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._arm_all();\n return count;\n });\n }\n\n /**\n * Atomically wipe the store and rebuild it from an event source. The\n * framework owns iteration, validation, `drop_snapshots` filtering,\n * `on_progress`, and the per-call `old → new` causation remap; the\n * adapter's {@link Store.restore} driver supplies the transaction\n * 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 - Any {@link EventSource}: a `CsvFile` backup or\n * another store. Read in batches rather than buffered, so\n * multi-million-event backups don't OOM. Each event's original `id`\n * is used as a causation lookup key but never written through —\n * 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 * @param sink - Where the events land. Defaults to this Act's store.\n * @returns {@link ScanResult} with `kept`, `duration_ms`, and\n * `dropped` per-category counters.\n *\n * @example Restore a CSV backup into the connected store\n * ```typescript\n * const result = await app.restore(new CsvFile({ path: \"./backup.csv\" }));\n * console.log(`Restored ${result.kept} events in ${result.duration_ms}ms`);\n * await cache().clear(); // operator's responsibility\n * ```\n *\n * @example Copy one store into another\n * ```typescript\n * await app.restore(pg, {}, sqlite);\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: count what a restore would land, touching no sink.\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 this Act's store.\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 migrated = 0;\n let dropped = { closed_streams: 0, snapshots: 0 };\n await target.restore(async (callback) => {\n const partial = await scan(source, opts, callback);\n kept = partial.kept;\n migrated = partial.migrated;\n dropped = partial.dropped;\n });\n // Restoring into this app's own store replaced its log (new ids, no\n // subscription rows): restart correlation from cold and arm the drain.\n if (!sink) {\n this._correlate.restart();\n this._arm_all();\n }\n return { kept, migrated, 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.\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 async *audit(\n categories?: AuditCategory[],\n options?: AuditOptions\n ): AsyncIterable<AuditFinding> {\n // Step the generator inside `_scoped`: its body runs lazily in the\n // consumer's frame, which would otherwise resolve the wrong store.\n const it = audit(this._audit_deps, categories, options)[\n Symbol.asyncIterator\n ]();\n while (true) {\n const { value, done } = await this._scoped(() => it.next());\n if (done) break;\n yield value;\n }\n }\n\n /**\n * Bulk-update scheduling priority for streams matching `filter`.\n *\n * Operator-grade override of the `claim()` lagging-frontier\n * ordering. 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 /** Shared by `close()` and reaction-requested closes. */\n private async _run_close(targets: CloseTarget[]): Promise<CloseResult> {\n const close_actor = { id: \"$close\", name: \"close\" };\n const result = await run_close_cycle(targets, {\n reactive_events_size: this._reactive_events.size,\n catch_up_correlation: (until) =>\n catch_up_correlation(\n this._correlate,\n (limit) => this.correlate({ limit }),\n until\n ),\n event_to_state: this._event_to_state,\n load: this._es.load,\n tombstone: this._es.tombstone,\n logger: this._logger,\n correlation: close_correlation(this._correlator, close_actor),\n with_stream_lock: (stream, work) => this._close_lock.run(stream, work),\n forget_subscribed: (streams) =>\n this._correlate.forget_subscribed(streams),\n });\n this.emit(\"closed\", result);\n return result;\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 * Targets carrying `before` take the **windowed** branch instead —\n * close the books on a rolling window: probe the min consumer\n * watermark (so the boundary never rises past a lagging reaction),\n * run the archive callback against the cutoff, then prune the prefix\n * below the closest safe `__snapshot__`. No tombstone guard (the\n * pre-cutoff prefix is immutable), no seed, cache untouched — the\n * stream stays live and keeps accepting actions. Requires the state\n * to snapshot via `.snap(...)`; no qualifying snapshot ⇒ the stream\n * lands in `skipped` (retry after the next snapshot). Windowed\n * entries in the result echo `before` and carry the surviving\n * boundary snapshot as `committed`.\n *\n * @param targets - Per-stream close options (stream, restart?, archive?, before?)\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 * @example Windowed close — keep the last 180 days of real events\n * ```typescript\n * const cutoff = new Date();\n * cutoff.setDate(cutoff.getDate() - 180);\n * await app.close([\n * {\n * stream: \"ledger-acme\",\n * before: cutoff,\n * archive: async () => { await archiveToS3(\"ledger-acme\", cutoff); },\n * },\n * ]);\n * ```\n */\n async close(targets: CloseTarget[]): Promise<CloseResult> {\n if (!targets.length) return { truncated: new Map(), skipped: [] };\n\n return this._scoped(() => this._run_close(targets));\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 // Validate the runtime knobs before anything runs (a bad debounceMs /\n // leaseMillis / maxPasses throws ZodError here, not on the first pass).\n resolveSettleConfig(options);\n // Writer-only instances skip settle.\n if (!this._drain) return;\n this._settle.schedule(options);\n }\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 * - `static_targets` — known-up-front reaction targets, subscribed once\n * at init (correlate marks them from then on)\n * - `reactive_events` — event names with at least one reaction (drives\n * the drain skip-flag in `do()` and `reset()`)\n * - `event_to_state` — 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 { StaticTarget } from \"../internal/index.js\";\nimport type {\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\n\n/**\n * Classification result. Returned by {@link classify_registry}; 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. 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 static_targets: StaticTarget[];\n readonly reactive_events: ReadonlySet<string>;\n readonly event_to_state: ReadonlyMap<string, State<any, any, any>>;\n readonly event_to_lanes: ReadonlyMap<string, EventLaneSet>;\n};\n\n/**\n * Walk the registry once to collect static reaction targets, the set of\n * reactive event names, the per-event lane fan-in, 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 classify_registry<\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 // Per-target lane, checked across EVERY reaction to a target regardless of\n // source. A stream drains on exactly one lane, and `subscribe`\n // keys lane per-target, so lane must agree target-wide — the\n // `(target, source)` scoping of `statics` is too narrow to catch a\n // same-target/different-source lane disagreement.\n const target_lanes = new Map<string, string>();\n const reactive_events = new Set<string>();\n const event_to_lanes = new Map<string, EventLaneSet>();\n\n for (const [name, register] of Object.entries(registry.events)) {\n if (register.reactions.size > 0) reactive_events.add(name);\n for (const reaction of register.reactions.values()) {\n if (typeof reaction.resolver === \"function\") {\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 event_to_lanes.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 = event_to_lanes.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 event_to_lanes.set(name, set);\n }\n // Lanes don't merge — any two reactions to the\n // same target must declare the same lane, regardless of source.\n // First reaction to a target records its lane; every later one must\n // match or it's a config error caught at build time. Both sides\n // compare the NORMALIZED name, so an omitted lane and an\n // explicit \"default\" — the same lane — agree.\n const recorded_lane = target_lanes.get(target);\n if (recorded_lane === undefined) {\n target_lanes.set(target, lane_name);\n } else if (recorded_lane !== lane_name) {\n throw new Error(\n `Stream \"${target}\" has conflicting lane assignments ` +\n `(\"${recorded_lane}\" vs \"${lane_name}\")`\n );\n }\n // Keyed by target alone, because a subscription row IS keyed by\n // stream: every adapter sets `source` once at creation and ignores\n // it thereafter, so a second entry for one target could only ever\n // contribute its priority — and a batch carrying two would leave\n // the merge to the adapter, which a single batched SQL statement\n // cannot do. One entry per stream, max priority, so the\n // highest-priority registrant sets the scheduling priority.\n const existing = statics.get(target);\n if (!existing) {\n statics.set(target, { stream: target, source, priority, lane });\n } else if (priority > (existing.priority as number)) {\n // `existing.priority` is always defined here since we always set\n // it when inserting, but the StaticTarget type marks it optional\n // for external consumers.\n statics.set(target, { ...existing, priority });\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 event_to_state = new Map<string, State<any, any, any>>();\n for (const merged of states.values()) {\n for (const event_name of Object.keys(merged.events)) {\n event_to_state.set(event_name, merged);\n }\n }\n\n return {\n static_targets: [...statics.values()],\n reactive_events,\n event_to_state,\n event_to_lanes,\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.\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 deprecated_event_names(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 // Two names mapping to the same numeric version (e.g. a leading-zero\n // `Foo_v02` alongside `Foo_v2`) can't both be a distinct version — one\n // is a typo. Left unguarded, the sort below would flag whichever lands\n // second, so declaration order would decide which one is \"current\",\n // and the real current event could be marked deprecated (a static\n // `.emit(...)` on it would then throw at build). Reject the collision\n // with a clear, order-independent error instead.\n const by_version = new Map<number, string>();\n for (const { version, name } of list) {\n const clash = by_version.get(version);\n if (clash)\n throw new Error(\n `duplicate event version: ${clash} and ${name} both map to version ${version} — ` +\n \"leading zeros in a `_v<n>` suffix are not allowed; use a single canonical spelling\"\n );\n by_version.set(version, name);\n }\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 current_version_of(\n deprecated_name: string,\n all_names: Iterable<string>\n): string | undefined {\n const target = parse(deprecated_name);\n let highest: Versioned | undefined;\n for (const name of all_names) {\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","import type { QueryStreams, Store, StreamPosition } from \"../types/index.js\";\n\n/** Streams read per page when walking the whole table. */\nconst DEFAULT_STREAM_PAGE = 500;\n\n/**\n * Walks EVERY stream matching `query`, paging with the keyset cursor.\n *\n * `Store.query_streams` defaults to `limit: 100`, so a caller that wants\n * the whole table must page — passing no query silently truncates at the\n * first page, which is a false all-clear for anything that reports on\n * what it found.\n *\n * The cursor is the last stream name the callback saw; results are\n * ordered by stream name, so a short page means the walk is done.\n *\n * @param store - Store to walk.\n * @param callback - Invoked once per matching position, in name order.\n * @param query - Optional filter. A caller-supplied `limit` sets the page\n * size (the walk still visits every match); `after` seeds the cursor.\n * @returns The total number of positions emitted.\n *\n * @internal\n */\nexport async function walk_streams(\n store: Store,\n callback: (position: StreamPosition) => void,\n query?: Omit<QueryStreams, \"after\" | \"limit\"> & {\n after?: string;\n limit?: number;\n }\n): Promise<number> {\n const page_size = query?.limit ?? DEFAULT_STREAM_PAGE;\n let after = query?.after;\n let total = 0;\n for (;;) {\n let last: string | undefined;\n const { count } = await store.query_streams(\n (position) => {\n last = position.stream;\n callback(position);\n },\n { ...query, after, limit: page_size }\n );\n total += count;\n if (count < page_size) return total;\n after = last;\n }\n}\n","/**\n * Operator-driven store audit. Each category is an {@link AuditPass}; the\n * dispatcher runs each needed scan once and broadcasts rows to every pass,\n * so an audit costs at most three scans. Reads only {@link AuditDeps} and\n * the public `Store`, never orchestration internals.\n */\n\nimport { SNAP_EVENT } from \"../ports.js\";\nimport type {\n AuditCategory,\n AuditFinding,\n AuditOptions,\n Committed,\n Query,\n Schemas,\n State,\n Store,\n StreamPosition,\n StreamStats,\n} from \"../types/index.js\";\nimport {\n current_version_of,\n deprecated_event_names,\n} from \"./event-versions.js\";\nimport { pii_fields } from \"./sensitive.js\";\nimport { walk_streams } from \"./walk-streams.js\";\n\n/** The orchestrator state the audit reads, built once at `build()`. */\nexport type AuditDeps = {\n readonly store: () => Store;\n /** event-name → state that registers it (for schema validation). */\n readonly event_to_state: ReadonlyMap<string, State<any, any, any>>;\n /** Declared drain lanes (for routing-health unknown-lane). */\n readonly declared_lanes: ReadonlySet<string>;\n /** Event names with at least one reaction (routing-health `unrouted`). */\n readonly routed_events: ReadonlySet<string>;\n};\n\n/** Defaults for {@link AuditOptions.thresholds}. */\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 \"unreadable-events\",\n] as const satisfies readonly AuditCategory[];\n\n/**\n * One audit category. Which `on_*` callbacks it has decides which shared\n * scans run; `finalize` does targeted follow-up reads; `drain` returns\n * the findings.\n */\ntype AuditPass = {\n category: AuditCategory;\n on_event?: (e: Committed<Schemas, string>) => void;\n on_unreadable?: (row: UnreadableRow) => void;\n on_stream?: (p: StreamPosition) => void;\n on_stat?: (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/** Scans finish before the first yield; bound the work with `options.query`. */\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 // Declaration order, not the caller's.\n const ordered_categories = ALL_CATEGORIES.filter((c) => requested.has(c));\n const passes: AuditPass[] = ordered_categories.map((c) =>\n PASS_FACTORIES[c](deps, options)\n );\n\n const need_stats = passes.some((p) => p.on_stat !== undefined);\n const need_streams = passes.some((p) => p.on_stream !== undefined);\n const need_events = passes.some(\n (p) => p.on_event !== undefined || p.on_unreadable !== undefined\n );\n\n if (need_stats) {\n // Exclude `__snapshot__` so head and count are domain figures; keep\n // `__tombstone__`, which is how a closed stream is recognized.\n const stats = await deps\n .store()\n .query_stats<Schemas>(\n {},\n { count: true, names: true, exclude: [SNAP_EVENT] }\n );\n for (const [stream, s] of stats) {\n for (const p of passes) p.on_stat?.(stream, s);\n }\n }\n\n if (need_streams) {\n // Paged: `query_streams` defaults to 100 rows.\n await walk_streams(deps.store(), (pos) => {\n for (const p of passes) p.on_stream?.(pos);\n });\n }\n\n if (need_events) {\n await scan_events_resiliently(\n deps,\n options.query,\n (event) => {\n for (const p of passes) p.on_event?.(event);\n },\n (row) => {\n for (const p of passes) p.on_unreadable?.(row);\n }\n );\n }\n\n // Serial to avoid pool contention.\n for (const p of passes) await p.finalize?.(deps);\n\n for (const p of passes) {\n for (const f of p.drain()) yield f;\n }\n}\n\n/**\n * A row the store couldn't hand back, located by re-reading it without its\n * payload (`with_pii: false`), which can't fail.\n */\ntype UnreadableRow = {\n stream: string;\n event_id: number;\n error: unknown;\n};\n\n/**\n * Run the event scan so one unreadable row doesn't end it: locate the row\n * it stopped at, report it, and resume past it with the remaining `limit`.\n * Backward scans can't resume, so they rethrow.\n */\nasync function scan_events_resiliently(\n deps: AuditDeps,\n query: Query | undefined,\n on_event: (e: Committed<Schemas, string>) => void,\n on_unreadable: (row: UnreadableRow) => void\n): Promise<void> {\n let cursor = query?.after;\n let remaining = query?.limit;\n for (;;) {\n let seen = 0;\n try {\n await deps.store().query<Schemas>(\n (event) => {\n seen++;\n cursor = event.id;\n on_event(event);\n },\n {\n ...query,\n after: cursor,\n ...(remaining !== undefined && { limit: remaining }),\n }\n );\n return;\n } catch (error) {\n if (query?.backward) throw error;\n let row: UnreadableRow | undefined;\n await deps.store().query<Schemas>(\n (e) => {\n row = { stream: e.stream, event_id: e.id, error };\n },\n { ...query, after: cursor, limit: 1, with_pii: false }\n );\n // Not one unreadable row (a dropped connection, a timeout): rethrow.\n if (!row) throw error;\n on_unreadable(row);\n // The tripping row is never delivered, so `seen` is at most\n // `remaining - 1` and the resumed budget stays at 1 or more.\n if (remaining !== undefined) remaining -= seen;\n cursor = row.event_id;\n }\n }\n}\n\n// =================== Pass factories ===================\n\nconst make_schema_pass: PassFactory = (deps) => {\n const findings: AuditFinding[] = [];\n return {\n category: \"schema\",\n on_event(event) {\n const name = String(event.name);\n const state = deps.event_to_state.get(name);\n if (!state) {\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 // `sensitive()` keys live in the pii sidecar, so omit them from the parse.\n const sensitive = pii_fields(schema);\n let parse_schema = schema;\n if (sensitive.length > 0) {\n const omitter = (\n schema as unknown as {\n omit?: (mask: Record<string, true>) => typeof schema;\n }\n ).omit;\n if (typeof omitter !== \"function\") {\n // A non-object schema with pii can't be masked; any parse is a false positive.\n return;\n }\n parse_schema = omitter.call(\n schema,\n Object.fromEntries(sensitive.map((f) => [f, true as const]))\n );\n }\n const parsed = parse_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/** Deprecated event name → its current sibling, within one state only. */\nconst classify_deprecated_by_state = (\n deps: AuditDeps\n): ReadonlyMap<string, string> => {\n const names_by_state = new Map<State<any, any, any>, Set<string>>();\n for (const [name, state] of deps.event_to_state) {\n let set = names_by_state.get(state);\n if (!set) {\n set = new Set();\n names_by_state.set(state, set);\n }\n set.add(name);\n }\n const deprecated_to_current = new Map<string, string>();\n for (const names of names_by_state.values()) {\n for (const name of deprecated_event_names(names)) {\n deprecated_to_current.set(name, current_version_of(name, names)!);\n }\n }\n return deprecated_to_current;\n};\n\nconst make_deprecated_load_pass: PassFactory = (deps, options) => {\n const share_min =\n options.thresholds?.deprecated_min ?? DEFAULTS.deprecated_min;\n const totals = new Map<string, number>();\n const per_stream = new Map<string, Map<string, number>>();\n return {\n category: \"deprecated-load\",\n on_stat(stream, { names }) {\n for (const [name, count] of Object.entries(names!)) {\n totals.set(name, (totals.get(name) ?? 0) + count!);\n let m = per_stream.get(name);\n if (!m) {\n m = new Map();\n per_stream.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 const deprecated = classify_deprecated_by_state(deps);\n const sorted = [...deprecated.keys()]\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 const current_version = deprecated.get(name)!;\n const top_streams = [...per_stream.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,\n total: count,\n top_streams,\n });\n }\n return findings;\n },\n };\n};\n\nconst make_close_candidate_pass: 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 on_stat(stream, { head }) {\n const head_name = String(head.name);\n if (head_name.startsWith(\"__\")) return; // already-closed or mid-truncate\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: restart_is_supported(deps, head_name),\n });\n },\n drain: () => findings,\n };\n};\n\nconst make_restart_candidate_pass: PassFactory = (deps, options) => {\n const threshold = options.thresholds?.restart_min ?? DEFAULTS.restart_min;\n // Snapshot counts are resolved in finalize: the shared stat scan excludes\n // `__snapshot__`, and only a handful of candidates need them.\n const candidates: Array<{ stream: string; count: number }> = [];\n const findings: AuditFinding[] = [];\n return {\n category: \"restart-candidate\",\n on_stat(stream, { head, count }) {\n if (count! < threshold) return;\n const head_name = String(head.name);\n if (head_name.startsWith(\"__\")) return;\n if (!restart_is_supported(deps, head_name)) return;\n candidates.push({ stream, count: count! });\n },\n async finalize(deps) {\n for (const { stream, count } of candidates) {\n let snaps = 0;\n await deps.store().query(\n () => {\n snaps++;\n },\n {\n stream,\n stream_exact: true,\n names: [SNAP_EVENT],\n with_snaps: true,\n }\n );\n findings.push({\n category: \"restart-candidate\",\n stream,\n count,\n snaps,\n });\n }\n },\n drain: () => findings,\n };\n};\n\nconst make_reaction_health_pass: 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 on_stream(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\nconst make_snapshot_drift_pass: PassFactory = (deps, options) => {\n const drift_min = options.thresholds?.drift_min ?? DEFAULTS.drift_min;\n const candidates: Array<{\n stream: string;\n total: number;\n }> = [];\n const findings: AuditFinding[] = [];\n return {\n category: \"snapshot-drift\",\n on_stat(stream, { head, count }) {\n // Also rejects framework markers, which no user state declares.\n if (!restart_is_supported(deps, String(head.name))) return;\n if (count! < drift_min) return; // upper-bound short-circuit\n candidates.push({\n stream,\n total: count!,\n });\n },\n async finalize(deps) {\n for (const { stream, total } of candidates) {\n let events_since_snap = total;\n let snap_at: number | undefined;\n // The shared stat scan excludes `__snapshot__`, so look it up here.\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 if (collected.length > 0) {\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\nconst make_routing_health_pass: PassFactory = (deps) => {\n const findings: AuditFinding[] = [];\n const seen_event_names = new Set<string>();\n return {\n category: \"routing-health\",\n on_stream(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 on_stat(_stream, { names }) {\n for (const name of Object.keys(names!)) {\n seen_event_names.add(name);\n }\n },\n finalize() {\n for (const name of seen_event_names) {\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\nconst make_correlation_gaps_pass: PassFactory = () => {\n const seen_ids = new Set<number>();\n const checks: Array<{ stream: string; id: number; parent_id: number }> = [];\n return {\n category: \"correlation-gaps\",\n on_event(e) {\n seen_ids.add(e.id);\n const causation = (e.meta as Record<string, unknown> | undefined)\n ?.causation as { event?: { id?: number } } | undefined;\n const parent_id = causation?.event?.id;\n if (parent_id !== undefined) {\n checks.push({ stream: e.stream, id: e.id, parent_id });\n }\n },\n drain() {\n const findings: AuditFinding[] = [];\n for (const { stream, id, parent_id } of checks) {\n if (!seen_ids.has(parent_id)) {\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\nconst make_clock_anomalies_pass: PassFactory = () => {\n const findings: AuditFinding[] = [];\n const last_per_stream = new Map<string, number>();\n return {\n category: \"clock-anomalies\",\n on_event(e) {\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 = last_per_stream.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 last_per_stream.set(e.stream, created);\n },\n drain: () => findings,\n };\n};\n\nfunction restart_is_supported(\n deps: AuditDeps,\n head_event_name: string\n): boolean {\n const state = deps.event_to_state.get(head_event_name);\n return state?.snap !== undefined;\n}\n\n/** Fed by the dispatcher with rows the event scan tripped on; never reaches `on_event`. */\nfunction make_unreadable_events_pass(): AuditPass {\n const findings: AuditFinding[] = [];\n return {\n category: \"unreadable-events\",\n on_unreadable({ stream, event_id, error }) {\n findings.push({\n category: \"unreadable-events\",\n stream,\n event_id,\n reason: \"pii_decrypt_failed\",\n error,\n });\n },\n drain: () => findings,\n };\n}\n\nconst PASS_FACTORIES: Record<AuditCategory, PassFactory> = {\n schema: make_schema_pass,\n \"deprecated-load\": make_deprecated_load_pass,\n \"close-candidate\": make_close_candidate_pass,\n \"restart-candidate\": make_restart_candidate_pass,\n \"reaction-health\": make_reaction_health_pass,\n \"snapshot-drift\": make_snapshot_drift_pass,\n \"routing-health\": make_routing_health_pass,\n \"correlation-gaps\": make_correlation_gaps_pass,\n \"clock-anomalies\": make_clock_anomalies_pass,\n \"unreadable-events\": make_unreadable_events_pass,\n};\n","/**\n * @module autoclose-policy\n * @category Internal\n *\n * Declarative close-policy options consumed by `.autocloses({...})`\n * Three optional fields cover the three\n * operational pressure points every real close policy traces back to:\n *\n * - `after` — time / compliance (\"autocloses **after** N days\")\n * - `is` — domain lifecycle (\"autocloses ... **is** Resolved\")\n * - `reaches` — resource (\"autocloses ... **reaches** 10k events\")\n *\n * Top-level fields combine with **AND** semantics. This captures the\n * common cooldown-after-terminal pattern that runs through almost\n * every business app — *\"close 90 days after `Resolved`\"*, *\"close 14\n * days after `Delivered`\"*, *\"close 30 days after a GDPR deletion\n * request\"*. All conditions must hold for the cycle to truncate.\n *\n * A separate `or: {...}` block opens an alternative path: when\n * present, the policy fires if **either** the top-level AND group\n * matches **or** any field inside `or` matches. Use it for safety\n * nets — *\"close (Resolved AND aged 90 days) OR if event count\n * reaches 10k\"*. The two-axis split mirrors the two ways close\n * policies appear in practice: primary close logic (AND-shaped) and\n * defensive backstops (OR-shaped).\n *\n * The state builder's `.autocloses(...)` overload distinguishes\n * function (predicate) from object (policy) and routes the latter\n * through {@link compile_autoclose_policy}, which validates via\n * {@link AutoclosePolicySchema} and returns the compiled predicate.\n * Operators with custom needs (per-stream metadata, multi-branch\n * AND/OR like \"(`Resolved` + 90d) OR (`Cancelled` + 30d)\") keep the\n * function form; the declarative form covers the 90% case.\n *\n * Validation runs at the builder call (`act().build()` time), so\n * misconfiguration — empty bag, sub-1 `reaches`, sub-minute `after`,\n * empty `is`, empty `or`, nested `or` inside `or`, unknown keys —\n * throws at build, not on the first cycle tick.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { AutoclosePredicate, Schemas } from \"../types/action.js\";\n\n/**\n * One day in epoch milliseconds. The close surface is day-denominated\n * throughout — policies declare `{ days }`, the State carries\n * `autoclose_*_days`, and the reaction thinks in day offsets. This\n * constant (with {@link days_after} / {@link days_before_now}) is the\n * single place the closing process touches epoch arithmetic, because\n * `Date` itself has no other currency.\n */\nconst DAY_MS = 86_400_000;\n\n/**\n * Lower bound on a resolved `after` window: one minute, expressed in\n * days. Sub-minute cooldowns are almost always misconfiguration.\n * Rejecting at build keeps the failure mode noisy.\n */\nconst MIN_AFTER_DAYS = 1 / 1440;\n\n/**\n * Lower bound on a resolved `keep` window: one full day. The close\n * cycle is low-cadence, non-priority housekeeping — a rolling window\n * shorter than a day signals misconfiguration. Real retention\n * contracts (180 days, 7 years) are days and up.\n */\nconst MIN_KEEP_DAYS = 1;\n\n/** The `Date` that lies `days` after `date`. @internal */\nexport function days_after(date: Date, days: number): Date {\n return new Date(date.getTime() + days * DAY_MS);\n}\n\n/** The `Date` that lies `days` in the past. @internal */\nexport function days_before_now(days: number): Date {\n return new Date(Date.now() - days * DAY_MS);\n}\n\n/**\n * Day-denominated window shared by `after` (terminate cooldown) and\n * `keep` (rolling retention). Fractional days accepted; windows below\n * the field's floor reject at build.\n *\n * @internal\n */\nconst window_schema = (\n field: \"after\" | \"keep\",\n min_days: number,\n floor: string\n) =>\n z\n .object({\n days: z\n .number({ message: `autocloses: ${field}.days must be a number` })\n .positive(`autocloses: ${field}.days must be > 0`),\n })\n .refine((o) => o.days >= min_days, {\n message: `autocloses: ${field} resolves to < ${floor}, which is too short to be a meaningful retention window`,\n });\n\nconst AfterSchema = window_schema(\"after\", MIN_AFTER_DAYS, \"one minute\");\n\nconst KeepSchema = window_schema(\"keep\", MIN_KEEP_DAYS, \"one day\");\n\nconst IsSchema = z.union([\n z.string().min(1, \"autocloses: is must be a non-empty event name\"),\n z\n .array(\n z.string().min(1, \"autocloses: is entries must be non-empty event names\")\n )\n .min(1, \"autocloses: is must include at least one event name\")\n .readonly(),\n]);\n\nconst ReachesSchema = z\n .number({ message: \"autocloses: reaches must be a number\" })\n .int(\"autocloses: reaches must be an integer\")\n .min(1, \"autocloses: reaches must be >= 1\");\n\n/**\n * Schema for the `or: {...}` block — the OR-shaped alternative path.\n * Same field set as the top-level policy minus `or` itself (so nested\n * `or` inside `or` rejects via `.strict()` instead of recursing). At\n * least one field required; empty `{}` is a misconfiguration.\n *\n * @internal\n */\nconst OrBlockSchema = z\n .object({\n after: AfterSchema.optional(),\n is: IsSchema.optional(),\n reaches: ReachesSchema.optional(),\n })\n .strict()\n .refine(\n (o) =>\n o.after !== undefined || o.is !== undefined || o.reaches !== undefined,\n {\n message:\n \"autocloses: `or` block must include at least one of after / is / reaches\",\n }\n );\n\n/**\n * Zod schema for the declarative {@link AutoclosePolicy} bag.\n * Internal `const` per the config-validation-schema standard (CLAUDE.md\n * \"Config-validation schemas\") — the public surface is the inferred\n * {@link AutoclosePolicy} type and the `.autocloses({...})` overload,\n * never this schema. `.strict()` rejects unknown keys so typos surface\n * at build instead of being silently ignored.\n *\n * @internal\n */\nconst AutoclosePolicySchema = z\n .object({\n after: AfterSchema.optional(),\n is: IsSchema.optional(),\n reaches: ReachesSchema.optional(),\n or: OrBlockSchema.optional(),\n keep: KeepSchema.optional(),\n })\n .strict()\n .refine(\n (o) =>\n o.after !== undefined ||\n o.is !== undefined ||\n o.reaches !== undefined ||\n o.or !== undefined ||\n o.keep !== undefined,\n {\n message:\n \"autocloses: at least one of after / is / reaches / or / keep must be specified — empty `{}` is a misconfiguration\",\n }\n );\n\n/**\n * Declarative close-policy options consumed by `.autocloses({...})`.\n * Top-level fields are AND-combined; the optional `or` block opens an\n * alternative OR-path. Omitted fields contribute nothing — they do\n * not mean \"match everything.\"\n *\n * @property after - Close when `head.created` is at least the resolved\n * window in the past. Days are the close surface's only unit;\n * fractional `days` cover sub-day cooldowns (`{ days: 1/24 }` is one\n * hour) without introducing another denomination.\n * @property is - Close when `head.name` matches. String for the\n * single-terminal-event case (the most common); `readonly string[]`\n * for multi-terminal states (`Order: Shipped | Delivered |\n * Cancelled`).\n * @property reaches - Close when the stream's event count is `>= N`\n * (inclusive — fires the moment the threshold is reached).\n * @property or - Alternative OR-path. When present, the policy fires\n * if EITHER the top-level AND group matches OR any field inside\n * `or` matches. Used for safety-net backstops layered onto a\n * primary cooldown policy (e.g. *\"(Resolved AND 90 days) OR reaches\n * 10k\"*). Nested `or` inside `or` rejects at build time.\n * @property keep - Rolling-window retention, **independent** of\n * the terminate fields: while the stream stays open, prune events\n * older than `now − keep` behind the closest safe snapshot via a\n * windowed close. Does not participate in the AND group or the `or`\n * block — a policy may terminate, prune, or both. Requires\n * `.snap(...)` earlier in the builder chain (type-gated) and a\n * window of at least one day — the close cycle is low-cadence\n * housekeeping, never sub-day realtime.\n */\nexport type AutoclosePolicy = z.infer<typeof AutoclosePolicySchema>;\n\n/** Compile a single `after` field into its predicate slice. @internal */\nfunction compile_after(\n after: NonNullable<AutoclosePolicy[\"after\"]>\n): AutoclosePredicate<Schemas> {\n return (_stream, head) => days_after(head.created, after.days) <= new Date();\n}\n\n/** Compile a single `is` field into its predicate slice. @internal */\nfunction compile_is(\n is: NonNullable<AutoclosePolicy[\"is\"]>\n): AutoclosePredicate<Schemas> {\n const set = new Set(typeof is === \"string\" ? [is] : is);\n return (_stream, head) => set.has(head.name as string);\n}\n\n/** Compile a single `reaches` field into its predicate slice. @internal */\nfunction compile_reaches(\n reaches: NonNullable<AutoclosePolicy[\"reaches\"]>\n): AutoclosePredicate<Schemas> {\n return (_stream, _head, count) => count >= reaches;\n}\n\n/**\n * Compile a declarative {@link AutoclosePolicy} into an\n * {@link AutoclosePredicate}. The state-builder's\n * `.autocloses({...})` overload calls this; tests can also build a\n * state and read `state.autoclose` to grab the compiled predicate.\n *\n * Returned predicate fires when either:\n *\n * 1. **All** top-level non-`or` fields match (AND), or\n * 2. **Any** field inside the `or` block matches.\n *\n * Top-level with zero non-`or` fields never satisfies path (1) — the\n * `every` check on an empty list is short-circuited to `false` so the\n * policy doesn't truncate the entire universe on an `or`-only\n * declaration. (Validation rejects all-empty bags up front; this guard\n * is the in-cycle equivalent for the synthesized empty AND-group.)\n *\n * Assignable to any `AutoclosePredicate<TEvents>` slot via\n * function-parameter contravariance — the returned predicate inspects\n * `head.name` as a plain string, so narrower event unions stay\n * assignable.\n *\n * Throws `ZodError` at call time when the options are invalid (empty\n * bag, non-positive `reaches`, sub-minute `after`, empty `is`, empty\n * `or`, nested `or`, unknown keys).\n *\n * @internal\n */\n/**\n * The smallest `after` window (in days) anywhere in a policy — across\n * the top-level `after` and the `or.after` block — or `undefined` when\n * the policy has no time component.\n *\n * The synthesized autoclose reaction uses this to decide how to\n * wait: a policy with an `after` defers its re-check to `head.created`\n * plus this many days (the earliest its time gate could open); a policy\n * without one (`is` / `reaches` only) has no time gate, so the reaction\n * just waits for the next event to re-trigger rather than parking on a\n * due-time. Conservative — the min across branches never defers past\n * the soonest a branch could fire.\n *\n * @internal\n */\nexport function policy_min_after_days(\n options: AutoclosePolicy\n): number | undefined {\n const parsed = AutoclosePolicySchema.parse(options);\n const windows: number[] = [];\n if (parsed.after) windows.push(parsed.after.days);\n if (parsed.or?.after) windows.push(parsed.or.after.days);\n return windows.length ? Math.min(...windows) : undefined;\n}\n\n/**\n * The rolling-window width (in days) of a policy's `keep` field, or\n * `undefined` when the policy declares no rolling window. The\n * synthesized autoclose reaction prunes the prefix older than the\n * window (via a windowed close) and derives its prune due-time as\n * `tail.created` plus this many days — the earliest the oldest\n * surviving domain event can age out of the window.\n *\n * @internal\n */\nexport function policy_keep_days(options: AutoclosePolicy): number | undefined {\n const parsed = AutoclosePolicySchema.parse(options);\n return parsed.keep?.days;\n}\n\nexport function compile_autoclose_policy(\n options: AutoclosePolicy\n): AutoclosePredicate<Schemas> {\n const parsed = AutoclosePolicySchema.parse(options);\n\n // Top-level AND group — only the non-`or` fields.\n const and_preds: AutoclosePredicate<Schemas>[] = [];\n if (parsed.after) and_preds.push(compile_after(parsed.after));\n if (parsed.is) and_preds.push(compile_is(parsed.is));\n if (parsed.reaches) and_preds.push(compile_reaches(parsed.reaches));\n\n // OR-block — at least one of its fields must match.\n const or_preds: AutoclosePredicate<Schemas>[] = [];\n if (parsed.or) {\n if (parsed.or.after) or_preds.push(compile_after(parsed.or.after));\n if (parsed.or.is) or_preds.push(compile_is(parsed.or.is));\n if (parsed.or.reaches) or_preds.push(compile_reaches(parsed.or.reaches));\n }\n\n return (stream, head, count) => {\n // AND path: every top-level field matches AND the group is non-empty\n // (an `or`-only declaration leaves `and_preds` empty — that\n // shouldn't auto-fire).\n if (\n and_preds.length > 0 &&\n and_preds.every((p) => p(stream, head, count))\n ) {\n return true;\n }\n // OR path: any `or`-block field matches.\n if (or_preds.some((p) => p(stream, head, count))) {\n return true;\n }\n return false;\n };\n}\n","/**\n * @module autoclose-window\n * @category Internal\n *\n * Off-hours window math for autoclose — hour-in-zone, DST-gap handling, and\n * \"next time the window opens\". The autoclose **config** (defaults, schema,\n * resolver) lives in `./config.js`, the single home for builder-facing config\n * bags; this module is the runtime window logic those knobs drive.\n *\n * @internal\n */\n\nimport type { AutocloseConfig } from \"./config.js\";\n\n/**\n * The current hour `[0, 23]` in the given IANA time zone, DST-correct\n * via `Intl`. Split out so the window check can be unit-tested without\n * spinning a controller.\n *\n * @internal\n */\nexport function hour_in_zone(now: Date, timeZone: string): number {\n const parts = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour: \"2-digit\",\n hourCycle: \"h23\",\n }).formatToParts(now);\n return Number(parts.find((p) => p.type === \"hour\")?.value);\n}\n\n/**\n * True when a plain `[start, end)` hour comparison places `hour` inside\n * the window. Half-open on hour boundaries and wrapping past midnight\n * when `start > end`.\n *\n * @internal\n */\nfunction hour_in_range(hour: number, start: number, end: number): boolean {\n return start < end\n ? hour >= start && hour < end\n : hour >= start || hour < end;\n}\n\n/**\n * True when `now` is the instant a DST spring-forward gap skipped over\n * the window's `start` hour. On such a day the local `start` hour never\n * occurs — the clock jumps from `start - 1` straight past `start` — so a\n * plain hour comparison would report the window closed all day. The gap\n * surfaces as a one-hour boundary where the local hour jumps from below\n * `start` to above it; that boundary instant is the window's replacement\n * opening. Detected by comparing the hour at `now` with the hour one\n * hour earlier: a jump of more than one hour that steps over `start`.\n *\n * @internal\n */\nfunction is_dst_gap_open(now: Date, timeZone: string, start: number): boolean {\n const hour = hour_in_zone(now, timeZone);\n if (hour <= start) return false;\n const prev = hour_in_zone(new Date(now.getTime() - 3_600_000), timeZone);\n // A normal step advances one local hour; a spring-forward gap advances\n // two, skipping exactly one local hour. This instant is the gap opening\n // only when the skipped hour is the window's `start`: the previous hour\n // sits just below `start` and this hour just above it.\n return prev === start - 1 && hour === start + 1;\n}\n\n/**\n * Whether `now` falls inside the configured off-hours window. The\n * window is half-open on hour boundaries — `[start, end)` — and wraps\n * past midnight when `start > end`. With no window configured every\n * tick runs, so callers treat `undefined` as \"always in window.\"\n *\n * On a DST spring-forward day whose `start` hour is skipped, the window\n * would otherwise be closed for the whole day (the `start` hour never\n * occurs). The gap's replacement instant is admitted so autoclose still\n * runs — see {@link is_dst_gap_open}.\n *\n * @internal\n */\nexport function in_autoclose_window(\n window: AutocloseConfig[\"autocloseWindow\"],\n now: Date\n): boolean {\n if (!window) return true;\n const hour = hour_in_zone(now, window.timeZone);\n return (\n hour_in_range(hour, window.start, window.end) ||\n is_dst_gap_open(now, window.timeZone, window.start)\n );\n}\n\n/**\n * The next instant the off-hours window opens at or after `now`. The\n * synthesized autoclose reaction defers to this when a tick lands\n * outside the window — parking until the window actually opens instead\n * of blind-polling on a configured cadence (the old behavior,\n * where a poll interval longer than the window could oscillate around\n * it and miss it repeatedly).\n *\n * Walks forward hour by hour and asks `Intl` for the local hour at each\n * step, so DST transitions resolve exactly the way the runtime's zone\n * database says they do — a 23- or 25-hour day never desynchronizes the\n * walk. The window validates as non-empty at build, and every zone hits\n * each `[0, 23]` hour label within any 48-hour span, so the walk always\n * terminates; the bound is a defensive backstop, with \"one day out\" as\n * the fallback no real zone can reach.\n *\n * Minute/second offsets within the opening hour are preserved from\n * `now` shifted by whole hours — the contract is hour-granular, matching\n * the window's own `[start, end)` hour semantics.\n *\n * On a DST spring-forward day whose `start` hour is skipped, the `start`\n * hour never occurs, so the minute-preserving walk would never match and\n * the window would defer ~24 h. The walk also checks each hour-aligned\n * boundary for the gap opening (see {@link is_dst_gap_open}) and returns\n * that boundary instant — deferring ~1 h to the replacement instant\n * rather than a full day. The boundary is returned as-is (no minute\n * offset): the gap opening is a single transition instant, not a range.\n *\n * @internal\n */\nexport function next_window_open(\n window: NonNullable<AutocloseConfig[\"autocloseWindow\"]>,\n now: Date\n): Date {\n const start_ms = now.getTime();\n for (let h = 0; h <= 48; h++) {\n const candidate = new Date(start_ms + h * 3_600_000);\n if (hour_in_zone(candidate, window.timeZone) === window.start)\n return candidate;\n // The `start` hour may be unreachable on a spring-forward day; catch\n // the gap boundary at the top of this candidate's hour. The boundary is\n // UTC-hour aligned, so in a fractional-offset zone the first one can sit\n // behind `now` — a past due is never excluded by claim, so skip it.\n const boundary = new Date(\n candidate.getTime() - (candidate.getTime() % 3_600_000)\n );\n if (\n boundary.getTime() >= start_ms &&\n is_dst_gap_open(boundary, window.timeZone, window.start)\n )\n return boundary;\n }\n return new Date(start_ms + 86_400_000);\n}\n","/**\n * @module close-signal\n * @category Internal\n *\n * The control-flow signal a reaction handler throws to *close* a stream.\n * Like {@link \"defer-signal\".DeferSignal} it rides the dispatcher's\n * `try/catch`, but where a defer holds the stream for later, a close asks the\n * orchestrator to retire it: `build_handle` turns the signal into a\n * `HandleResult.close` (a {@link CloseTarget}), `run_drain_cycle` acks the\n * triggering event and collects the target, and the `DrainController` hands it\n * to the orchestrator's `on_close` callback, which runs the same\n * `run_close_cycle` machinery as `app.close`.\n *\n * Internal: the compiled autoclose reaction throws it. Closing stays an\n * orchestrator capability — reactions only *signal* the intent, so the public\n * reaction-scoped `IAct` gains no `close`.\n *\n * The autoclose reaction runs on a **synthetic stream** (`source` = the\n * aggregate, `target` = a per-aggregate `__autoclose__` key) so it never\n * shares a watermark with the aggregate's own reactions. That makes the close\n * *target* distinct from the reaction's lease stream, so the signal carries the\n * stream to close explicitly (`stream`); when omitted (a user reaction closing\n * its own stream) it defaults to the lease stream.\n *\n * @internal\n */\nexport class CloseSignal extends Error {\n /**\n * Stream to close. Omitted → the reaction's own lease stream (a self-close).\n * The synthesized autoclose reaction sets it to the aggregate stream, since\n * its lease runs on a synthetic `__autoclose__` target.\n */\n readonly stream?: string;\n /** Optional archive callback to run while the stream is guarded. */\n readonly archive?: () => Promise<void>;\n /**\n * Watermark to ack the requesting reaction to before the close runs. The\n * close-cycle safety guard skips a stream whose subscriptions (matched by\n * source) lag the head; the autoclose reaction's `source` is the aggregate,\n * so it must advance its own watermark to the live head id it evaluated\n * against — otherwise it blocks its own close. Defaults to the triggering\n * event id when omitted.\n */\n readonly at?: number;\n /**\n * Windowed close: prune events older than this cutoff behind\n * the closest safe snapshot instead of retiring the stream. Thrown by\n * the autoclose reaction of a `.autocloses({ keep })` state; flows\n * into {@link CloseTarget.before}. Omitted → a full close.\n */\n readonly before?: Date;\n\n constructor(opts?: {\n stream?: string;\n archive?: () => Promise<void>;\n at?: number;\n before?: Date;\n }) {\n super(\"reaction requested close\");\n this.name = \"CloseSignal\";\n this.stream = opts?.stream;\n this.archive = opts?.archive;\n this.at = opts?.at;\n this.before = opts?.before;\n }\n}\n","/**\n * @module internal/config\n * @category Internal\n *\n * **The single home for every builder-facing config bag in act-core.** Any\n * options object an operator hands to `act().build()`, a builder method\n * (`.on(...)`, `.do(...)`, `.withLane(...)`), or a runtime cycle\n * (`drain(...)` / `settle(...)`) is validated here with Zod — never with a\n * hand-written `if (x < min) throw` ladder — so misconfiguration surfaces as\n * a `ZodError` at the entry point, not as `NaN` arithmetic on the first cycle\n * tick.\n *\n * Layout: one section per bag, each with its `DEFAULT_*` constants, an\n * internal `<Type>OptionsSchema`, an inferred `<Type>Config`, and a\n * `resolve<Type>Config(options): <Type>Config`. The schema is never\n * re-exported — the public surface is the inferred type + resolver.\n *\n * Index of bags owned here:\n * - **Backoff** — retry pacing (`BackoffOptions`), nested in reaction/action.\n * - **Reaction** — `.do(handler, options)` (`blockOnError` / `maxRetries` / `backoff`).\n * - **Action** — `.on(entry, options)` (`maxRetries` / `backoff`).\n * - **Lane** — `.withLane({...})` (`leaseMillis` / `streamLimit` / `cycleMs`).\n * - **Drain / Settle** — `drain(...)` / `settle(...)` runtime knobs.\n * - **Autoclose** — the `.autocloses` / `ActOptions` autoclose knobs (+ window).\n * - **CircuitBreaker** — the store-op breaker on `ActOptions`.\n * - **Fold** — `projection(...).of(...)` batch-fold knobs.\n *\n * Sibling env/package config (`config()`, `NODE_ENV`, log level) lives in the\n * public `../config.ts` — a different concern (process environment, not\n * builder input). The `@rotorsoft/act-http` transport bags (`SseOptions`,\n * `OpenAPIOptions`) live in that package; core cannot own another package's\n * surface.\n *\n * Validation philosophy: reject only what is genuinely broken — `NaN`,\n * `±Infinity` (Zod 4's `z.number()` rejects both by default), and negatives\n * where nonsensical. A value that works today is never newly rejected. The\n * real strictness lands on `maxRetries` and `backoff`, the knobs whose bad\n * values silently corrupt the poison-quarantine and retry-loop-exit gates.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { ActOptions } from \"../act.js\";\nimport type {\n ActionOptions,\n BackoffOptions,\n DrainOptions,\n FoldOptions,\n LaneConfig,\n ReactionOptions,\n SettleOptions,\n ShutdownOptions,\n} from \"../types/index.js\";\n\n// ---------------------------------------------------------------------------\n// Backoff — retry pacing. Nested inside the reaction/action bags below; also\n// resolvable on its own (`resolveBackoffConfig`) for direct callers.\n// ---------------------------------------------------------------------------\n\n/**\n * Rejects an off-union `strategy`, a non-finite/negative `baseMs`, or a\n * non-finite/non-positive `maxMs`. Zod 4's `z.number()` rejects\n * `NaN`/`±Infinity` by default, so `.min(0)` / `.gt(0)` also close the\n * non-finite gap. No `maxMs >= baseMs` constraint — a sub-`baseMs` cap on\n * `exponential` is documented behavior, not an error.\n * @internal\n */\nconst BackoffOptionsSchema = z.object({\n strategy: z.enum([\"fixed\", \"linear\", \"exponential\"]),\n baseMs: z.number().min(0),\n maxMs: z.number().gt(0).optional(),\n jitter: z.boolean().optional(),\n});\n\n/**\n * Retry pacing for a reaction that declares no backoff, and for projections\n * and failed fetches, which have no options. Ten seconds, like the default\n * lease; the lease itself only keeps two workers off one stream.\n */\nexport const DEFAULT_BACKOFF: BackoffOptions = {\n strategy: \"fixed\",\n baseMs: 10_000,\n};\n\n/** Validate a backoff bag, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveBackoffConfig(\n options: BackoffOptions | undefined\n): BackoffOptions | undefined {\n return options === undefined\n ? undefined\n : BackoffOptionsSchema.parse(options);\n}\n\n// ---------------------------------------------------------------------------\n// Reaction — `.do(handler, options)`. `maxRetries` gates the poison-quarantine\n// decision (`retry >= maxRetries`), so a `NaN` here silently disables\n// `blockOnError` (a poison message retries forever). Validate the whole bag.\n// ---------------------------------------------------------------------------\n\n/** Retries a reaction gets before it blocks, unless `.do()` says otherwise. */\nexport const DEFAULT_MAX_RETRIES = 3;\n/** Whether a reaction blocks its stream once retries run out. */\nexport const DEFAULT_BLOCK_ON_ERROR = true;\n\nconst ReactionOptionsSchema = z.object({\n blockOnError: z.boolean(),\n maxRetries: z.number().int().min(0),\n backoff: BackoffOptionsSchema.optional(),\n});\n\n/** Resolved reaction options. */\nexport type ReactionConfig = z.infer<typeof ReactionOptionsSchema>;\n\n/** Validate a fully-defaulted reaction options bag. Throws `ZodError`. */\nexport function resolveReactionConfig(\n options: ReactionOptions\n): ReactionConfig {\n return ReactionOptionsSchema.parse(options);\n}\n\n// ---------------------------------------------------------------------------\n// Action — `.on(entry, options)`. `maxRetries` gates the command retry loop's\n// exit (`attempt >= maxRetries`), so a `NaN` here can spin the loop forever on\n// a contended stream. All fields optional (the argument itself is optional).\n// ---------------------------------------------------------------------------\n\nconst ActionOptionsSchema = z.object({\n maxRetries: z.number().int().min(0).optional(),\n backoff: BackoffOptionsSchema.optional(),\n});\n\n/** Resolved action options. */\nexport type ActionConfig = z.infer<typeof ActionOptionsSchema>;\n\n/** Validate an action options bag. Throws `ZodError`. */\nexport function resolveActionConfig(options: ActionOptions): ActionConfig {\n return ActionOptionsSchema.parse(options);\n}\n\n// ---------------------------------------------------------------------------\n// Lane — `.withLane({...})`. Per-lane overrides of the drain budget. Time\n// knobs (`leaseMillis` / `cycleMs`) accept any non-negative ms; `streamLimit`\n// is an integer count. Reject NaN/Infinity/negative; allow 0 (as today).\n// ---------------------------------------------------------------------------\n\nconst LaneConfigSchema = z.object({\n name: z.string().min(1),\n leaseMillis: z.number().min(0).optional(),\n streamLimit: z.number().int().min(0).optional(),\n cycleMs: z.number().min(0).optional(),\n});\n\n/** Validate a lane config. Throws `ZodError`. Returns the input shape. */\nexport function resolveLaneConfig<TName extends string>(\n options: LaneConfig<TName>\n): LaneConfig<TName> {\n LaneConfigSchema.parse(options);\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Drain / Settle — runtime knobs for `drain(...)` / `settle(...)`. Parsed once\n// per call (cheap). Reject NaN/Infinity/negative; allow 0. `correlate` is a\n// pass-through query filter (validated by the store), so it is not reshaped.\n// ---------------------------------------------------------------------------\n\n/** Streams a drain claims per cycle. */\nexport const DEFAULT_STREAM_LIMIT = 10;\n/** Events a drain reads per stream per cycle. */\nexport const DEFAULT_EVENT_LIMIT = 10;\n/** How long a drain holds a stream's lease (ms). */\nexport const DEFAULT_LEASE_MILLIS = 10_000;\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.\n */\nexport const DEFAULT_SETTLE_DEBOUNCE_MS = 10;\n/**\n * Default LRU cap for the subscribed-streams cache. Apps that mint many\n * dynamic targets (one per aggregate) should override it with\n * `ActOptions.maxSubscribedStreams`.\n */\nexport const DEFAULT_MAX_SUBSCRIBED_STREAMS = 1000;\n\nconst DrainOptionsSchema = z.object({\n streamLimit: z.number().int().min(0).optional(),\n eventLimit: z.number().int().min(0).optional(),\n leaseMillis: z.number().min(0).optional(),\n});\n\n/** Validate drain options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveDrainConfig(\n options: DrainOptions | undefined\n): DrainOptions | undefined {\n if (options === undefined) return undefined;\n DrainOptionsSchema.parse(options);\n return options;\n}\n\nconst SettleOptionsSchema = DrainOptionsSchema.extend({\n debounceMs: z.number().min(0).optional(),\n // `maxPasses` defaults to Infinity (no cap) when omitted; a present value is\n // a non-negative integer — `0` is legal and means \"run no passes\".\n //\n // `Infinity` is accepted explicitly. It is the documented default\n // (`Act.settle`'s doc-comment and `SettleOptions.maxPasses` both name it),\n // and `settle.ts` destructures `maxPasses = Infinity`, so the one value the\n // docs advertise was the one value `z.number().int()` refused — Zod 4\n // rejects `±Infinity`, and an integer check cannot pass it either. Wrapper\n // code normalizing an optional cap (`maxPasses: opts.maxPasses ?? Infinity`)\n // is the natural way to hit it. Accepting it also honors this module's own\n // rule that a value which works today is never newly rejected.\n maxPasses: z\n .union([z.number().int().min(0), z.literal(Number.POSITIVE_INFINITY)])\n .optional(),\n}).loose();\n\n/** Validate settle options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveSettleConfig(\n options: SettleOptions | undefined\n): SettleOptions | undefined {\n if (options === undefined) return undefined;\n SettleOptionsSchema.parse(options);\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Shutdown — the grace budget `shutdown(...)` gives in-flight drain cycles.\n// ---------------------------------------------------------------------------\n\n/**\n * Ceiling on the derived shutdown grace budget. Without a cap, a lane\n * configured with a long lease (minutes, for a genuinely slow integration)\n * would let one parked handler hold a rolling deploy open for that whole\n * lease. 30s is the longest `leaseMillis` the production checklist\n * recommends, so it is the point past which \"graceful\" stops being the\n * operator's intent.\n */\nexport const MAX_SHUTDOWN_GRACE_MS = 30_000;\n\nconst ShutdownOptionsSchema = z\n .object({\n // `0` is legal and is exactly today's behavior: stop scheduling and\n // return without waiting.\n graceMs: z.number().min(0).optional(),\n })\n .loose();\n\n/** Validate shutdown options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveShutdownConfig(\n options: ShutdownOptions | undefined\n): ShutdownOptions | undefined {\n if (options === undefined) return undefined;\n ShutdownOptionsSchema.parse(options);\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Act — the top-level `act().build(options)` scalar knobs. The nested bags\n// (`autocloseWindow`, `circuitBreaker`) are resolved by their own resolvers\n// below; the `scoped`/`correlator` fields are objects/functions passed\n// through untouched (`.loose()`), so only the scalar knobs are checked here.\n// ---------------------------------------------------------------------------\n\nconst ActOptionsSchema = z\n .object({\n maxSubscribedStreams: z.number().int().min(1).optional(),\n settleDebounceMs: z.number().int().min(0).optional(),\n })\n .loose();\n\n/** Validate the scalar `ActOptions` knobs at build. Throws `ZodError`. */\nexport function resolveActConfig(\n options: ActOptions | undefined\n): ActOptions | undefined {\n if (options === undefined) return undefined;\n ActOptionsSchema.parse(options);\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Autoclose — the autoclose knobs on `ActOptions` (+ the off-hours window).\n// The window *logic* (DST, hour math) stays in `autoclose-window.ts`; only\n// the schema, defaults, and resolver live here.\n// ---------------------------------------------------------------------------\n\n/**\n * @deprecated The cadence knob is derived from `autocloseWindow` now;\n * nothing consumes it. Kept for compat; removed in the next major.\n */\nexport const DEFAULT_AUTOCLOSE_CYCLE_MINUTES = 720;\n/** @deprecated Unused since the autoclose sweep was removed. */\nexport const DEFAULT_CLOSE_BATCH_SIZE = 64;\n/** @deprecated Unused since the autoclose sweep was removed. */\nexport const DEFAULT_CLOSE_YIELD_MS = 0;\n/** Default IANA zone for `autocloseWindow` when the operator omits one. */\nconst DEFAULT_AUTOCLOSE_WINDOW_TZ = \"UTC\";\n\n/** True when `tz` is a zone the runtime's `Intl` accepts. @internal */\nfunction is_valid_time_zone(tz: string): boolean {\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: tz });\n return true;\n } catch {\n return false;\n }\n}\n\nconst AutocloseWindowSchema = z\n .object({\n start: z\n .number()\n .int()\n .min(0)\n .max(23, { message: \"autocloseWindow.start must be an hour in [0, 23]\" }),\n end: z\n .number()\n .int()\n .min(0)\n .max(23, { message: \"autocloseWindow.end must be an hour in [0, 23]\" }),\n timeZone: z\n .string()\n .refine(is_valid_time_zone, {\n message: \"autocloseWindow.timeZone must be a valid IANA time zone\",\n })\n .default(DEFAULT_AUTOCLOSE_WINDOW_TZ),\n })\n .refine((w) => w.start !== w.end, {\n message:\n \"autocloseWindow.start and end must differ — an empty window disables autoclose\",\n });\n\nconst AutocloseOptionsSchema = z.object({\n autocloseCycleMinutes: z\n .number()\n .int()\n .min(1)\n .max(1440)\n .default(DEFAULT_AUTOCLOSE_CYCLE_MINUTES),\n closeBatchSize: z\n .number()\n .int()\n .min(1)\n .max(1024)\n .default(DEFAULT_CLOSE_BATCH_SIZE),\n closeYieldMs: z.number().min(0).max(1000).default(DEFAULT_CLOSE_YIELD_MS),\n closeOnError: z.boolean().default(false),\n autocloseWindow: AutocloseWindowSchema.optional(),\n});\n\n/** Resolved autoclose configuration after validation + default expansion. */\nexport type AutocloseConfig = z.infer<typeof AutocloseOptionsSchema>;\n\n/** Validate + default the autoclose knobs on `ActOptions`. Throws `ZodError`. */\nexport function resolveAutocloseConfig(\n options: ActOptions | undefined\n): AutocloseConfig {\n return AutocloseOptionsSchema.parse({\n autocloseCycleMinutes: options?.autocloseCycleMinutes,\n closeBatchSize: options?.closeBatchSize,\n closeYieldMs: options?.closeYieldMs,\n closeOnError: options?.closeOnError,\n autocloseWindow: options?.autocloseWindow,\n });\n}\n\n// ---------------------------------------------------------------------------\n// CircuitBreaker — the store-op breaker on `ActOptions`. The `CircuitBreaker`\n// state machine stays in `circuit-breaker.ts` and imports the resolved type.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_CIRCUIT_FAILURE_THRESHOLD = 5;\nconst DEFAULT_CIRCUIT_COOLDOWN_MS = 30_000;\n\nconst CircuitBreakerOptionsSchema = z.object({\n failureThreshold: z\n .number()\n .int()\n .min(1)\n .default(DEFAULT_CIRCUIT_FAILURE_THRESHOLD),\n cooldownMs: z\n .number()\n .int()\n .min(100)\n .max(3_600_000)\n .default(DEFAULT_CIRCUIT_COOLDOWN_MS),\n});\n\n/** Public, all-optional circuit-breaker options bag for `act().build()`. */\nexport type CircuitBreakerOptions = z.input<typeof CircuitBreakerOptionsSchema>;\n\n/** Resolved circuit-breaker configuration. */\nexport type CircuitBreakerConfig = z.infer<typeof CircuitBreakerOptionsSchema>;\n\n/** Parse + apply defaults. Throws `ZodError` on out-of-range values. */\nexport const resolveCircuitBreakerConfig = (\n options?: CircuitBreakerOptions\n): CircuitBreakerConfig => CircuitBreakerOptionsSchema.parse(options ?? {});\n\n// ---------------------------------------------------------------------------\n// Fold — `projection(name).of(state)` batch-fold knobs.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_FOLD_FLUSH_EVERY = 1_000;\nconst DEFAULT_MAX_CACHED_STATES = 10_000;\n\nconst FoldOptionsSchema = z.object({\n flushEvery: z.number().int().min(1).default(DEFAULT_FOLD_FLUSH_EVERY),\n maxCachedStates: z.number().int().min(1).default(DEFAULT_MAX_CACHED_STATES),\n});\n\n/** Resolved fold configuration. */\nexport type FoldConfig = z.infer<typeof FoldOptionsSchema>;\n\n/** Validate + default the fold knobs. Throws `ZodError`. */\nexport function resolveFoldConfig(options: FoldOptions): FoldConfig {\n return FoldOptionsSchema.parse(options);\n}\n","/**\n * @module defer-signal\n * @category Internal\n *\n * The control-flow signal a reaction handler throws to *defer* itself.\n * Unlike an error, a defer is not a failure: the dispatcher\n * ({@link \"reaction-builder\".build_handle}) catches it and produces a\n * `HandleResult.defer` — the triggering events stay pending (watermark not\n * advanced), `retry` is not bumped, and the drain re-visits the stream at the\n * resolved due-time.\n *\n * `DeferSignal` is the **imperative escape hatch** and is re-exported from the\n * package root, so reaction code can throw it directly when a static\n * `.defer(when)` step isn't expressive enough (a deadline computed from loaded\n * state, say). It carries the *unresolved* {@link DeferWhen}; the dispatcher\n * resolves it against the triggering event it is already dispatching (via\n * `resolve_defer_at`), which is what anchors `{ after }` and the `at` function\n * form to that event and keeps the due-time derivable. Fully dynamic times go\n * through `{ at: someDate }`.\n *\n * Modeled as an `Error` subclass — like `NonRetryableError` — so it rides the\n * existing `try/catch` in the handler loop instead of needing a separate\n * return channel through every dispatcher signature. The compiled autoclose\n * reaction throws the same signal.\n */\nimport type { DeferWhen } from \"../types/index.js\";\n\nexport class DeferSignal extends Error {\n /**\n * The unresolved schedule. The dispatcher turns this into an absolute\n * due-time by resolving it against the triggering event.\n */\n readonly when: DeferWhen;\n\n constructor(when: DeferWhen) {\n super(\"reaction deferred\");\n this.name = \"DeferSignal\";\n this.when = when;\n }\n}\n","/**\n * @module autoclose-reaction\n * @category Internal\n *\n * Synthesis of the online close-the-books reaction. `.autocloses(policy)`\n * is not a sweep: it is a reaction on every event the declaring state owns\n * that evaluates the policy against the LIVE head (so a reopened stream\n * re-evaluates correctly), defers to the cooldown's earliest opening\n * (`head.created + the policy's min after`), and closes via `CloseSignal`\n * once the policy holds.\n *\n * Runs at build time — after the registry is fully merged and before the\n * orchestrator classifies it — so the synthesized dynamic resolver is\n * discovered by `classify_registry` and its target stream subscribed. The\n * registry is complete once the builder finishes; the orchestrator never\n * mutates it.\n *\n * @internal\n */\n\nimport { SNAP_EVENT, store, TOMBSTONE_EVENT } from \"../ports.js\";\nimport type {\n Reaction,\n Registry,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport { days_after, days_before_now } from \"./autoclose-policy.js\";\nimport { in_autoclose_window, next_window_open } from \"./autoclose-window.js\";\nimport { CloseSignal } from \"./close-signal.js\";\nimport { type AutocloseConfig, DEFAULT_MAX_RETRIES } from \"./config.js\";\nimport { DeferSignal } from \"./defer-signal.js\";\n\n/**\n * Prefix for the synthetic per-aggregate stream the autoclose reaction\n * runs on. `target = \\`${AUTOCLOSE_TARGET_PREFIX}${aggregate}\\``, `source =\n * aggregate` — a watermark distinct from the aggregate's own reactions, so\n * an autoclose defer never short-circuits them. Internal; not a public\n * surface.\n */\nconst AUTOCLOSE_TARGET_PREFIX = \"__autoclose__:\";\n\n/**\n * Inject one synthesized autoclose reaction per `.autocloses(...)` state\n * into the registry's event registers. The handler resolves ports at call\n * time (`store()`), so the reaction is orchestrator-agnostic; the resolved\n * The reactions are synthesized once into the shared registry, so nothing\n * per-Act is captured here — the off-hours window is read from the running\n * Act at resolution time via the injected `read_window`.\n *\n * @internal\n */\nexport function synthesize_autoclose_reactions<\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<any, any, any>>,\n /**\n * Reads the *running* Act's off-hours window. Injected rather than\n * imported: these reactions are synthesized once into the shared\n * registry and run by every Act built from that builder, so the window\n * has to be resolved per call, and `internal/` never reaches for\n * ambient state itself.\n */\n read_window: () => AutocloseConfig[\"autocloseWindow\"]\n): void {\n for (const st of states.values()) {\n const predicate = st.autoclose;\n if (!predicate) continue;\n const after_days = st.autoclose_after_days;\n const keep_days = st.autoclose_keep_days;\n const archiver = st.archive;\n const reaction: Reaction<TEvents> = {\n // Run on a SYNTHETIC stream — `source` is the aggregate, `target` is a\n // per-aggregate `__autoclose__` key — so the autoclose reaction never\n // shares a watermark with the aggregate's own reactions. A shared\n // watermark would let autoclose's defer short-circuit the aggregate's\n // other reactions (the \"a defer affects all reactions on a stream\"\n // hazard). The close still targets the aggregate (`source`).\n resolver: (e) => ({\n target: `${AUTOCLOSE_TARGET_PREFIX}${e.stream}`,\n source: e.stream,\n }),\n // Never block on autoclose: a transient query/store error should retry,\n // not quarantine the synthetic stream.\n options: { blockOnError: false, maxRetries: DEFAULT_MAX_RETRIES },\n handler: async (event) => {\n const aggregate = event.stream;\n // Off-hours gating: outside the window, park until the window\n // opens. Derived from the window itself — no polling cadence.\n //\n // Read from the running Act's frame, not from a closure. These\n // reactions are synthesized once into the shared registry and\n // handed by reference to every Act built from the same builder, so\n // a captured window would be the first-built Act's for all of them\n // — and the documented multi-tenant shape is one builder built per\n // tenant.\n const window = read_window();\n if (!in_autoclose_window(window, new Date()))\n throw new DeferSignal({ at: next_window_open(window!, new Date()) });\n // Every policy keys on the *domain* head/count, so snapshots are\n // excluded unconditionally — matching `scan_stream_heads` in\n // close-cycle.ts. `snap()` commits a `__snapshot__` at a higher id\n // right after the triggering domain event, so a terminal commit that\n // crosses a `.snap()` boundary would otherwise make the snapshot the\n // head: `is` never matches (`head.name === \"__snapshot__\"`) and never\n // recovers, `after` measures the cooldown from the snapshot's\n // timestamp, and `reaches:N` counts snapshot events toward N. Only\n // rolling-window (`keep`) policies additionally fetch the tail: the\n // prune decision keys on the oldest *domain* event — after a prune the\n // oldest surviving event is the boundary snapshot, whose age says\n // nothing about whether another prune would be productive.\n const stats = await store().query_stats([aggregate], {\n count: true,\n tail: keep_days !== undefined ? true : undefined,\n exclude: [TOMBSTONE_EVENT, SNAP_EVENT],\n });\n const entry = stats.get(aggregate);\n // No live (non-tombstone) head → already closed, nothing to do.\n if (!entry) return;\n const head = entry.head;\n // `count` is always present — query_stats is called with\n // `count: true` above, so the option contract guarantees it.\n if (predicate(aggregate, head, entry.count!))\n throw new CloseSignal({\n stream: aggregate,\n archive: archiver ? () => archiver(aggregate, head) : undefined,\n // Ack this reaction's own watermark to the live head so the\n // close-cycle guard (which matches subscriptions by source =\n // aggregate) sees it caught up instead of blocking its own close.\n at: head.id,\n });\n // Rolling window: when the oldest domain event has aged out of the\n // window, stage a windowed close — prune the prefix older than the\n // cutoff behind the closest safe snapshot. `tail` is present\n // whenever the stats entry is (same non-excluded event set).\n if (keep_days !== undefined) {\n const cutoff = days_before_now(keep_days);\n if (entry.tail!.created < cutoff)\n throw new CloseSignal({\n stream: aggregate,\n before: cutoff,\n archive: archiver\n ? () => archiver(aggregate, head, cutoff)\n : undefined,\n at: head.id,\n });\n }\n // Not eligible yet: park on the earliest derivable due-time — the\n // day the terminate cooldown opens and/or the day the oldest\n // domain event ages out of the rolling window. Neither → wait for\n // the next event to re-trigger (e.g. a `reaches` threshold).\n const dues: Date[] = [];\n if (after_days !== undefined)\n dues.push(days_after(head.created, after_days));\n if (keep_days !== undefined)\n dues.push(days_after(entry.tail!.created, keep_days));\n // Only defer to a FUTURE due-time. A due already in the past (the\n // stream idled longer than the cooldown while the AND-combined\n // predicate stayed unmet) can never be excluded by `claim`, which\n // skips only future `deferred_at` — so a past defer would be\n // re-claimed every cycle (perpetual query_stats burn). When\n // nothing is future, fall through and return: advance the watermark\n // and wait for the next event to re-trigger.\n const future = dues\n .map((d) => d.getTime())\n .filter((t) => t > Date.now());\n if (future.length)\n throw new DeferSignal({ at: new Date(Math.min(...future)) });\n },\n };\n const key = `__autoclose_${st.name}`;\n for (const event_name of Object.keys(st.events)) {\n registry.events[event_name as keyof TEvents]?.reactions.set(\n key,\n reaction as Reaction<TEvents, keyof TEvents>\n );\n }\n }\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/action.js\";\n\n// The `BackoffOptions` config schema + resolver live in `./config.ts` (the\n// single home for every builder-facing config bag). This module keeps only\n// the runtime delay math, which stays hot-path and dependency-free.\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 compute_backoff_delay(\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 default: {\n // Unreachable once options pass `resolveBackoffConfig` at their\n // declaration site. Defensive so the pure function is total and can\n // never emit `NaN` from an unvalidated strategy — throw instead.\n const _never: never = opts.strategy;\n throw new Error(`unknown backoff strategy: ${String(_never)}`);\n }\n }\n if (opts.jitter) delay = delay * (0.5 + Math.random());\n return Math.max(0, Math.floor(delay));\n}\n","/**\n * @module internal/circuit-breaker\n *\n * Orchestrator-level circuit breaker for store operations. The drain loop\n * polls `claim()` continuously; when the backing store goes down every poll\n * throws a {@link StoreError}, and without a breaker the orchestrator would\n * spin at the cycle cadence hammering a dead database and flooding the logs.\n *\n * The breaker collapses that into three states:\n *\n * - **closed** — normal operation; failures are counted.\n * - **open** — `failureThreshold` consecutive failures tripped it; attempts\n * are skipped for `cooldownMs` so the store gets room to recover.\n * - **half-open** — the cooldown elapsed; a single trial attempt is allowed.\n * Success closes the breaker; failure re-opens it and restarts the clock.\n *\n * Time is passed in (`now`) rather than read from the clock so the state\n * machine is deterministic under test.\n */\n\nimport type { CircuitBreakerConfig } from \"./config.js\";\n\n/** Circuit breaker state. */\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\n// The circuit-breaker config schema, defaults, and resolver live in\n// `./config.js` (the single home for builder-facing config bags). This\n// module keeps only the state machine that consumes the resolved config.\n\n/**\n * Side-effect hooks the orchestrator wires into the breaker so consumers\n * (drain / settle / autoclose) don't each thread their own callbacks.\n */\nexport type CircuitBreakerHooks = {\n /** Invoked on every {@link CircuitBreaker.failed} with the error and state. */\n readonly on_error?: (error: unknown, circuit: CircuitState) => void;\n /**\n * Invoked once, `cooldownMs` after the breaker opens (and again on each\n * re-open). The orchestrator wires it to re-attempt a drain — so recovery\n * is automatic even on the default lane, which has no periodic poller.\n */\n readonly on_retry?: () => void;\n};\n\nexport class CircuitBreaker {\n private _failures = 0;\n private _opened_at: number | undefined;\n private _wake: ReturnType<typeof setTimeout> | undefined;\n private readonly _threshold: number;\n private readonly _cooldown_ms: number;\n private readonly _hooks: CircuitBreakerHooks;\n\n constructor(config: CircuitBreakerConfig, hooks: CircuitBreakerHooks = {}) {\n this._threshold = config.failureThreshold;\n this._cooldown_ms = config.cooldownMs;\n this._hooks = hooks;\n }\n\n /**\n * True when the store has failed at least once since the last pass that\n * went all the way through. The breaker can still read \"closed\" here: it\n * only opens after several failures in a row, so this catches the first\n * one, which `state()` cannot.\n */\n get failing(): boolean {\n return this._failures > 0;\n }\n\n /** Current state given the wall-clock `now`. */\n state(now: number): CircuitState {\n if (this._opened_at === undefined) return \"closed\";\n return now - this._opened_at >= this._cooldown_ms ? \"half-open\" : \"open\";\n }\n\n /** A store op passed — reset to closed and cancel any pending retry. */\n passed(): void {\n this._failures = 0;\n this._opened_at = undefined;\n this._clear_wake();\n }\n\n /**\n * A store op failed. Opens the breaker when the consecutive-failure\n * threshold is reached, or immediately re-opens (restarting the cooldown)\n * if a half-open trial just failed. Returns the resulting state.\n *\n * Callers gate on the state directly — `state(now) === \"open\"` means skip.\n * On opening, schedules the `on_retry` wake so recovery is automatic;\n * always surfaces the failure via `on_error`.\n */\n failed(now: number, error?: unknown): CircuitState {\n const circuit = this._advance(now);\n if (circuit === \"open\") this._schedule_wake();\n this._hooks.on_error?.(error, circuit);\n return circuit;\n }\n\n /** Cancel the pending retry timer. Idempotent; call on shutdown. */\n stop(): void {\n this._clear_wake();\n }\n\n /**\n * Schedule the `on_retry` wake `cooldownMs` out so the breaker re-trials\n * the store on its own. No-op when no `on_retry` hook is wired (e.g. unit\n * tests of the pure state machine). The timer is `unref`'d so it never\n * keeps the process alive.\n */\n private _schedule_wake(): void {\n if (!this._hooks.on_retry) return;\n this._clear_wake();\n this._wake = setTimeout(() => {\n this._wake = undefined;\n this._hooks.on_retry?.();\n }, this._cooldown_ms);\n this._wake.unref();\n }\n\n private _clear_wake(): void {\n if (this._wake) {\n clearTimeout(this._wake);\n this._wake = undefined;\n }\n }\n\n /** Pure state transition for a failure — no side effects. */\n private _advance(now: number): CircuitState {\n // Already tripped: this can only be reached from a half-open trial\n // (open skips attempts), so the trial failed — re-open and restart.\n if (this._opened_at !== undefined) {\n this._opened_at = now;\n return \"open\";\n }\n this._failures += 1;\n if (this._failures >= this._threshold) {\n this._opened_at = now;\n return \"open\";\n }\n return \"closed\";\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 * Also home to the pieces a closer needs around the cycle: the per-stream\n * {@link CloseLock} and the bounded {@link catch_up_correlation}. The Act\n * orchestrator only wires its ports in and emits `\"closed\"`.\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\";\nimport { walk_streams } from \"./walk-streams.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 reactive_events_size: number;\n readonly event_to_state: 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 * Page size for the safety probe's `query_streams` pagination.\n * Defaults to {@link SAFETY_PROBE_PAGE_SIZE}; production callers omit\n * it, tests set a small value to exercise the multi-page path.\n */\n readonly probe_page_size?: number;\n /**\n * Advance correlation to at least `until` (an event id) and return how\n * far it actually got.\n *\n * The safety probe can only judge events correlate has resolved (an\n * uncorrelated event has raised no mark and may not even have created its\n * subscription yet). An autoclose fires from its own, often uncorrelated,\n * trigger, so the cycle correlates the tail first; anything still above\n * the cursor is held back as pending.\n */\n readonly catch_up_correlation: (until: number) => Promise<number>;\n /**\n * Per-stream critical section, so two closers of one stream (a manual\n * close has no drain lease to exclude an autoclose) never archive the same\n * prefix, and a second full closer never mistakes the first one's\n * tombstone for an interrupted close. Identity when run in isolation.\n */\n readonly with_stream_lock?: <T>(\n stream: string,\n work: () => Promise<T>\n ) => Promise<T>;\n /**\n * Drop retired streams from correlate's in-process \"already subscribed\"\n * set, so a later scan re-issues `subscribe()` for them. An operator may\n * reclaim a retired subscription row while this process runs; forgetting\n * keeps the in-process view from outliving it, which would otherwise stop\n * delivery to a target named after the stream. Skipped in isolation.\n */\n readonly forget_subscribed?: (streams: string[]) => void;\n};\n\n/**\n * Scan window and pass cap for {@link catch_up_correlation}. Bounded, so a\n * close behind a large backlog skips the stream (the documented retryable\n * outcome) rather than scanning the whole log inside an operator call.\n *\n * @internal\n */\nconst CLOSE_CATCH_UP_LIMIT = 1000;\nconst CLOSE_CATCH_UP_PASSES = 20;\n\n/**\n * Advance correlation until the read cursor reaches `until`, and report\n * where it landed. The safety probe cannot judge a subscription's pending\n * work over events correlate has not resolved yet.\n *\n * Stops as soon as a pass makes no progress (the log has no more to give),\n * and after {@link CLOSE_CATCH_UP_PASSES} windows.\n *\n * @internal\n */\nexport async function catch_up_correlation(\n cursor: { readonly checkpoint: number; arm(): void },\n correlate: (limit: number) => Promise<unknown>,\n until: number\n): Promise<number> {\n for (\n let pass = 0;\n pass < CLOSE_CATCH_UP_PASSES && cursor.checkpoint < until;\n pass++\n ) {\n const before = cursor.checkpoint;\n // Force the scan: the armed flag can't say whether a tail exists.\n cursor.arm();\n await correlate(CLOSE_CATCH_UP_LIMIT);\n if (cursor.checkpoint <= before) break;\n }\n return cursor.checkpoint;\n}\n\n/**\n * Per-stream serialization for close critical sections: two closers of the\n * same stream never prune or archive concurrently, while different streams\n * proceed in parallel. One instance per Act.\n *\n * @internal\n */\nexport class CloseLock {\n private readonly _tails = new Map<string, Promise<unknown>>();\n\n /** Run `work` after every earlier close of `stream` has settled. */\n run<T>(stream: string, work: () => Promise<T>): Promise<T> {\n const prev = this._tails.get(stream) ?? Promise.resolve();\n // Chain after the previous holder however it settled, so a failed close\n // can't wedge the lock.\n const next = prev.then(work, work);\n this._tails.set(stream, next);\n // Drop the tail once settled, unless a later waiter replaced it.\n const cleanup = () => {\n if (this._tails.get(stream) === next) this._tails.delete(stream);\n };\n next.then(cleanup, cleanup);\n return next;\n }\n}\n\n/**\n * Page size for the safety probe's keyset pagination over the\n * subscriptions table. Above `query_streams`'s default `limit` of 100\n * to keep the round-trip count low while bounding per-page work.\n *\n * @internal\n */\nconst SAFETY_PROBE_PAGE_SIZE = 1000;\n\n/**\n * Per-stream scan result: latest non-tombstone domain event metadata.\n * `last_event_name` 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 max_id: number;\n readonly version: number;\n readonly last_event_name: string;\n /**\n * Set when the stream already carries a tombstone but still holds domain\n * events — a close that wrote its guard and was then interrupted before\n * truncating (a throwing archive callback, or a `truncate` that failed).\n * Carries the existing guard's event id so the retry resumes at Phase 4\n * instead of re-tombstoning (which would fail the version guard) or being\n * dropped from the scan entirely.\n */\n readonly resumed_guard?: { readonly id: number };\n};\n\n/**\n * Run the full close cycle for the given targets. Caller owns the\n * lifecycle event emission.\n *\n * Targets carrying a `before` cutoff take the **windowed** branch — a\n * pure prefix delete behind an existing snapshot (see\n * {@link run_windowed_closes}); the rest run the guarded\n * tombstone/restart pipeline below.\n *\n * @internal\n */\nexport async function run_close_cycle(\n targets: CloseTarget[],\n deps: CloseCycleDeps\n): Promise<CloseResult> {\n // Caller (Act.close) filters empty targets; run_close_cycle assumes at\n // least one target.\n const target_map = new Map(targets.map((t) => [t.stream, t]));\n for (const t of target_map.values()) {\n if (t.before !== undefined && t.restart)\n throw new Error(\n `close: \\`before\\` and \\`restart\\` are mutually exclusive (stream \"${t.stream}\") — a windowed close keeps the stream live behind a real snapshot; restart reseeds it`\n );\n }\n const windowed = [...target_map.values()].filter(\n (t) => t.before !== undefined\n );\n const full = [...target_map.values()].filter((t) => t.before === undefined);\n const skipped: string[] = [];\n const windowed_result = windowed.length\n ? await run_windowed_closes(windowed, deps, skipped)\n : new Map();\n if (!full.length) return { truncated: windowed_result, skipped };\n const truncated = await with_stream_locks(\n full.map((t) => t.stream),\n deps,\n () => run_full_closes(full, target_map, deps, skipped)\n );\n // A tombstone seed retired the stream; a snapshot seed restarted it.\n const retired = [...truncated.entries()]\n .filter(([, r]) => r.committed.name === TOMBSTONE_EVENT)\n .map(([stream]) => stream);\n if (retired.length) deps.forget_subscribed?.(retired);\n for (const [stream, entry] of windowed_result) truncated.set(stream, entry);\n return { truncated, skipped };\n}\n\n/**\n * Run `work` holding the per-stream close lock of every stream in\n * `streams`. Locks are taken in sorted order, so two closers whose batches\n * share streams in a different order cannot each hold one and wait on the\n * other.\n */\nfunction with_stream_locks<T>(\n streams: string[],\n deps: CloseCycleDeps,\n work: () => Promise<T>\n): Promise<T> {\n const with_lock = deps.with_stream_lock ?? ((_stream, w) => w());\n return [...streams]\n .sort()\n .reduceRight<() => Promise<T>>(\n (inner, stream) => () => with_lock(stream, inner),\n work\n )();\n}\n\n/**\n * The guarded tombstone/restart pipeline (Phases 1-6), run while holding\n * every target stream's close lock.\n */\nasync function run_full_closes(\n full: CloseTarget[],\n target_map: Map<string, CloseTarget>,\n deps: CloseCycleDeps,\n skipped: string[]\n): Promise<CloseResult[\"truncated\"]> {\n const none: CloseResult[\"truncated\"] = new Map();\n const streams = full.map((t) => t.stream);\n\n // 1. Scan: find the latest non-tombstone event per stream\n const stream_info = await scan_stream_heads(streams);\n\n // 1b. A restart target whose state has sensitive fields can't be seeded\n // (an actorless load would redact them; a privileged one would put\n // plaintext where `forget` can't reach), so it is skipped, untouched,\n // before anything is written.\n for (const target of full) {\n if (!target.restart) continue;\n const info = stream_info.get(target.stream);\n if (!info) continue;\n const owner = deps.event_to_state.get(info.last_event_name);\n if (owner?.pii_aware) {\n deps.logger.error(\n `Refusing to close \"${target.stream}\" with restart: state \"${owner.name}\" carries sensitive fields, so a restart seed would persist redacted values while deleting the originals. Close it without restart to retire the stream, or leave it open.`\n );\n skipped.push(target.stream);\n stream_info.delete(target.stream);\n }\n }\n\n // 2. Partition: skip streams with pending reactions in flight\n const safe = await partition_by_safety(\n stream_info,\n deps.reactive_events_size,\n skipped,\n deps.probe_page_size ?? SAFETY_PROBE_PAGE_SIZE,\n deps.catch_up_correlation\n );\n if (!safe.length) return none;\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.\n const { guarded, guard_events } = await guard_with_tombstones(\n safe,\n stream_info,\n deps.correlation,\n deps.tombstone,\n skipped\n );\n if (!guarded.length) return none;\n\n // 4. Seed: load final state for restart targets through the owning state\n const seed_states = await load_restart_seeds(\n guarded,\n target_map,\n stream_info,\n deps.event_to_state,\n deps.load,\n deps.logger\n );\n\n // 5. Archive: user-provided per-stream callback while guarded\n await run_archive_callbacks(guarded, target_map);\n\n // 5b. Re-check: truncate only streams whose head is still this close's\n // guard. The lock above serializes closers in this process; a closer in\n // another process can still resume our guard, finish first, and reseed\n // the stream, after which a commit can land on it. Truncating then would\n // delete that accepted commit.\n const still_guarded = await heads_still_guarded(\n guarded,\n guard_events,\n skipped\n );\n if (!still_guarded.length) return none;\n\n // 6. Truncate + seed: atomic per-store transaction\n return truncate_and_warm_cache(\n still_guarded,\n seed_states,\n guard_events,\n deps.correlation\n );\n}\n\n// ---------------------------------------------------------------------------\n// Windowed branch — prune the prefix behind an existing snapshot\n// ---------------------------------------------------------------------------\n\n/**\n * Run the windowed closes: probe the min consumer watermark per stream\n * (the `max_id` cap that keeps the boundary at/below what the laggiest\n * consumer has read), run archive callbacks against the cutoff, then\n * hand the boundary targets to {@link Store.truncate}.\n *\n * No tombstone guard and no cache touch — the cutoff is always in the\n * past, so a concurrently-written snapshot (`created = now`) can never\n * become the boundary: once the cutoff is fixed the boundary snapshot is\n * fixed, and the prefix below it is immutable. Concurrent appends land\n * at the head, above the boundary. Current state is unchanged, so the\n * cache stays warm. Streams the store skips (no qualifying snapshot)\n * are reported in `skipped`.\n *\n * @internal\n */\nasync function run_windowed_closes(\n windowed: CloseTarget[],\n deps: CloseCycleDeps,\n skipped: string[]\n): Promise<CloseResult[\"truncated\"]> {\n // 1. Safety probe: how far may each stream be pruned (skipped when the\n // app has no reactions). A consumer with pending work caps at its\n // watermark; a caught-up one caps at the correlate checkpoint, since a\n // reaction to only some event types sits below the head with nothing\n // pending. Catching up first makes that cap as high as it can be.\n const checkpoint =\n deps.reactive_events_size > 0\n ? await deps.catch_up_correlation(Number.MAX_SAFE_INTEGER)\n : -1;\n const min_at =\n deps.reactive_events_size > 0\n ? await probe_min_watermarks(\n windowed.map((t) => t.stream),\n deps.probe_page_size ?? SAFETY_PROBE_PAGE_SIZE,\n checkpoint\n )\n : new Map<string, number>();\n\n // 2 + 3. Per stream, under its lock: archive only when the prune would\n // delete a prefix, then truncate. The lock plus that check make the\n // archive fire at most once per pruned range.\n const with_lock = deps.with_stream_lock ?? ((_stream, work) => work());\n const truncated: CloseResult[\"truncated\"] = new Map();\n for (const t of windowed) {\n const entry = await with_lock(t.stream, async () => {\n const max_id = min_at.get(t.stream);\n // Boundary probe: will a windowed truncate prune anything? The\n // store deletes events with `id < boundary.id`, where `boundary`\n // is the latest `__snapshot__` with `created < before` (and, when\n // capped, `id <= max_id`). No such prefix ⇒ archive is skipped and\n // the stream is reported skipped, exactly as a no-op truncate would.\n if (!(await windowed_prune_pending(t.stream, t.before!, max_id)))\n return undefined;\n // Archive: user callback against the cutoff, run while the prefix\n // is still present. Sequential/fail-fast: a throw propagates to the\n // caller and leaves the stream un-truncated (no data loss).\n if (t.archive) await t.archive();\n // Boundary truncate: atomic per-store transaction; no seed.\n const result = await store().truncate([\n { stream: t.stream, before: t.before!, max_id },\n ]);\n return result.get(t.stream);\n });\n if (entry) truncated.set(t.stream, entry);\n else skipped.push(t.stream);\n }\n return truncated;\n}\n\n/**\n * Read-only probe: would a windowed truncate of `stream` at `before`\n * (optionally capped at `max_id`) delete a prefix? Mirrors the store's\n * boundary rule — the latest `__snapshot__` with `created < before` and,\n * when capped, `id <= max_id` — then reports whether any event sorts\n * strictly below that boundary. False when no snapshot qualifies (a\n * no-op truncate) or when the boundary is already the earliest event\n * (the prefix was pruned by a prior closer). This is the guard that\n * makes the windowed archive fire at most once per pruned range.\n *\n * @internal\n */\nasync function windowed_prune_pending(\n stream: string,\n before: Date,\n max_id: number | undefined\n): Promise<boolean> {\n let boundary_id: number | undefined;\n let min_id: number | undefined;\n await store().query(\n (event) => {\n if (min_id === undefined || event.id < min_id) min_id = event.id;\n if (\n event.name === SNAP_EVENT &&\n event.created < before &&\n (max_id === undefined || event.id <= max_id) &&\n (boundary_id === undefined || event.id > boundary_id)\n )\n boundary_id = event.id;\n },\n { stream, stream_exact: true, with_snaps: true, after: -1 }\n );\n // No qualifying snapshot → nothing to prune behind. Otherwise a prune\n // is pending only when some event sorts below the boundary.\n return boundary_id !== undefined && min_id! < boundary_id;\n}\n\n/**\n * Min subscription watermark per target stream — the read-only probe\n * backing the windowed close's `max_id` cap. Pagination and source\n * matching mirror {@link partition_by_safety}; instead of flagging\n * pending streams it folds `min(at)` per stream. Streams with no\n * matching subscriptions are absent (no cap).\n *\n * @internal\n */\nasync function probe_min_watermarks(\n streams: string[],\n page_size: number,\n checkpoint: number\n): Promise<Map<string, number>> {\n const min_at = new Map<string, number>();\n const matches = source_matcher();\n await walk_streams(\n store(),\n (position) => {\n // Pending work caps at the watermark; caught up caps at the\n // checkpoint; an unmarked row keeps the conservative watermark.\n const pending =\n position.correlated_at === undefined ||\n position.at < position.correlated_at;\n const cap = pending ? position.at : Math.max(position.at, checkpoint);\n for (const stream of streams) {\n if (matches(position.source, stream)) {\n const prev = min_at.get(stream);\n if (prev === undefined || cap < prev) min_at.set(stream, cap);\n }\n }\n },\n { limit: page_size, source_matches: streams }\n );\n return min_at;\n}\n\n/**\n * Does a subscription with this `source` consume from `stream`? No source\n * consumes every stream; a literal source matches itself as a regex.\n * Compiled patterns are cached per matcher.\n */\nfunction source_matcher(): (\n source: string | undefined,\n stream: string\n) => boolean {\n const compiled = new Map<string, RegExp>();\n return (source, stream) => {\n if (!source) return true;\n let re = compiled.get(source);\n if (!re) {\n re = new RegExp(source);\n compiled.set(source, re);\n }\n return re.test(stream);\n };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 1 — scan stream heads\n// ---------------------------------------------------------------------------\n\nasync function scan_stream_heads(\n streams: string[]\n): Promise<Map<string, StreamHead>> {\n // query_stats returns the latest non-snap event per stream (heads-only\n // cheap path, indexed). Streams whose latest non-snap event is a tombstone\n // are filtered out in the loop — we don't want to re-tombstone an\n // already-closed stream. Streams with no events (or only snap/tombstone\n // events filtered out) are absent from the result map entirely.\n const stats = await store().query_stats(streams, {\n exclude: [SNAP_EVENT],\n });\n // Domain head, markers excluded. A stream absent here has no domain\n // events left, so a previous close ran to completion and there is\n // nothing to do. A stream present here whose `stats` head is a tombstone\n // was guarded and then interrupted — it must be resumed, not skipped.\n // `last_event_name` also has to come from this pass: the\n // restart-seed owner lookup needs the domain event, not the marker.\n const domain_heads = await store().query_stats(streams, {\n exclude: [SNAP_EVENT, TOMBSTONE_EVENT],\n });\n // The tombstone must expect the stream's real head version, which a\n // trailing `__snapshot__` raises by one. Everything else uses the domain\n // head, so the true head gets its own heads-only read.\n const true_heads = await store().query_stats(streams, {});\n const out = new Map<string, StreamHead>();\n for (const [stream, { head }] of domain_heads) {\n const marker_head = stats.get(stream)?.head;\n const interrupted = marker_head?.name === TOMBSTONE_EVENT;\n out.set(stream, {\n max_id: head.id,\n version: true_heads.get(stream)!.head.version,\n last_event_name: head.name as string,\n ...(interrupted ? { resumed_guard: { id: marker_head.id } } : {}),\n });\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2 — partition by safety\n// ---------------------------------------------------------------------------\n\nasync function partition_by_safety(\n stream_info: Map<string, StreamHead>,\n reactive_events_size: number,\n skipped: string[],\n page_size: number,\n catch_up_correlation: (until: number) => Promise<number>\n): Promise<string[]> {\n if (reactive_events_size === 0) return [...stream_info.keys()];\n\n // Correlate the tail first (see `catch_up_correlation`); anything still\n // above the cursor afterwards is held back.\n let needed = -1;\n for (const info of stream_info.values())\n needed = Math.max(needed, info.max_id);\n const checkpoint = await catch_up_correlation(needed);\n const uncorrelated = new Set<string>();\n for (const [stream, info] of stream_info) {\n if (checkpoint < info.max_id) uncorrelated.add(stream);\n }\n\n // Over-matching a source only widens the pending set, the safe direction.\n const pending_set = new Set<string>();\n const matches = source_matcher();\n\n // `source_matches` narrows the probe server-side to subscriptions that\n // could consume from a stream we're closing — a best-effort hint, so\n // the per-position source/target re-check below still runs and keeps\n // the result correct even when a store returns a superset.\n const targets = [...stream_info.keys()];\n\n // Every page, so a lagging reaction past the first one still counts.\n await walk_streams(\n store(),\n (position) => {\n // Pending means what `claim` means: a mark above the watermark. An\n // unmarked row has nothing to wait for; the catch-up above has landed\n // every mark that was owed.\n const has_work =\n position.correlated_at !== undefined &&\n position.at < position.correlated_at;\n if (!has_work) return;\n for (const [stream, info] of stream_info) {\n if (matches(position.source, stream) && position.at < info.max_id)\n pending_set.add(stream);\n }\n },\n { limit: page_size, source_matches: targets }\n );\n\n const safe: string[] = [];\n for (const [stream] of stream_info) {\n if (pending_set.has(stream) || uncorrelated.has(stream))\n 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 guard_with_tombstones(\n safe: string[],\n stream_info: Map<string, StreamHead>,\n correlation: string,\n tombstone: EsOps[\"tombstone\"],\n skipped: string[]\n): Promise<{\n guarded: string[];\n guard_events: Map<string, { id: number; stream: string }>;\n}> {\n const guarded: string[] = [];\n const guard_events = new Map<string, { id: number; stream: string }>();\n await Promise.all(\n safe.map(async (stream) => {\n const info = stream_info.get(stream)!;\n if (info.resumed_guard) {\n // Guard already written by the interrupted run — reuse it rather\n // than re-tombstoning (the version guard would reject it anyway).\n guarded.push(stream);\n guard_events.set(stream, { id: info.resumed_guard.id, stream });\n return;\n }\n const committed = await tombstone(stream, info.version, correlation);\n if (committed) {\n guarded.push(stream);\n guard_events.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, guard_events };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 4 — load restart seeds\n// ---------------------------------------------------------------------------\n\nasync function load_restart_seeds(\n guarded: string[],\n target_map: Map<string, CloseTarget>,\n stream_info: Map<string, StreamHead>,\n event_to_state: ReadonlyMap<string, State<any, any, any>>,\n load: EsOps[\"load\"],\n logger: Logger\n): Promise<Map<string, Schema>> {\n const seed_states = new Map<string, Schema>();\n await Promise.all(\n guarded\n .filter((s) => target_map.get(s)?.restart)\n .map(async (stream) => {\n // stream_info entry is guaranteed (guarded ⊆ stream_info.keys()).\n const last_event_name = stream_info.get(stream)!.last_event_name;\n const owner_state = event_to_state.get(last_event_name);\n if (!owner_state) {\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 \"${last_event_name}\". Stream will be tombstoned instead.`\n );\n return;\n }\n const snap = await load(owner_state, { stream });\n seed_states.set(stream, snap.state as Schema);\n })\n );\n return seed_states;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 5 — archive callbacks\n// ---------------------------------------------------------------------------\n\nasync function run_archive_callbacks(\n guarded: string[],\n target_map: 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 archive_fn = target_map.get(stream)?.archive;\n if (archive_fn) await archive_fn();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Phase 5b — confirm the guard is still the head\n// ---------------------------------------------------------------------------\n\nasync function heads_still_guarded(\n guarded: string[],\n guard_events: Map<string, { id: number; stream: string }>,\n skipped: string[]\n): Promise<string[]> {\n // True heads, markers included: the guard is a tombstone, and a reseed\n // by another closer is a snapshot.\n const heads = await store().query_stats(guarded, {});\n return guarded.filter((stream) => {\n if (heads.get(stream)?.head.id === guard_events.get(stream)!.id)\n return true;\n skipped.push(stream);\n return false;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Phase 6 — atomic truncate + cache warm\n// ---------------------------------------------------------------------------\n\nasync function truncate_and_warm_cache(\n guarded: string[],\n seed_states: Map<string, Schema>,\n guard_events: Map<string, { id: number; stream: string }>,\n correlation: string\n): Promise<CloseResult[\"truncated\"]> {\n const trunc_targets = guarded.map((stream) => {\n const snapshot = seed_states.get(stream);\n const guard = guard_events.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(trunc_targets);\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 = seed_states.get(stream);\n if (state && entry) {\n await cache().set(stream, {\n 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 * Correlation, the discovery half of correlate→drain: resolves each event to\n * its target streams and raises each target's work mark (`correlated_at`),\n * which is what `claim` reads. See docs/architecture/correlation-and-drain.\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { DEFAULT_LANE, log, store } from \"../ports.js\";\nimport type {\n EventRegister,\n Query,\n Registry,\n Resolved,\n SchemaRegister,\n Schemas,\n StreamPosition,\n SubscribeInput,\n} from \"../types/index.js\";\nimport { is_literal_source } from \"../utils.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport { LruMap } from \"./lru-map.js\";\nimport { report_once } from \"./report-once.js\";\n\n/**\n * First-boot scan starts this far below the watermark, so an event committed\n * but not correlated before a crash is found again. Re-scanning is harmless:\n * `subscribe` is an idempotent upsert and a mark never regresses.\n */\nconst COLD_START_BACK_SCAN = 10_000;\n\n/**\n * Too short and a slow scan outruns its lease (duplicate work, still safe);\n * too long and a crashed holder stalls discovery.\n */\nconst CORRELATION_LEASE_MS = 5_000;\n\n/**\n * The correlation lease key: a hash of every reacted-to event name with its\n * handler names, so only interchangeable workers share a lease. See\n * docs/architecture/correlation-and-drain § The correlation lease.\n */\nconst registry_key = <TEvents extends Schemas>(\n events: EventRegister<TEvents>\n): string => {\n const shape = Object.keys(events)\n .filter((name) => events[name].reactions.size > 0)\n .sort()\n .map((name) => [name, [...events[name].reactions.keys()].sort()]);\n return createHash(\"sha256\")\n .update(JSON.stringify(shape))\n .digest(\"hex\")\n .slice(0, 32);\n};\n\n/** Bound on compiled pattern sources; guards a resolver that mints one per event. */\nconst PATTERN_CACHE_SIZE = 32;\n\n/** Static resolver target collected at build time and subscribed at init. */\nexport type StaticTarget = {\n readonly stream: string;\n readonly source?: string;\n readonly priority?: number;\n readonly lane?: string;\n};\n\n/**\n * What a target's subscription row holds. A resolution sends its own\n * priority/lane only when it beats `floor` (`+Infinity` for static targets);\n * otherwise it re-sends these values with the mark. The store owns the lane;\n * this only caches it, so a missing record is re-read from the row.\n */\ntype Subscription = {\n readonly floor: number;\n readonly priority: number;\n readonly lane: string | undefined;\n};\n\n/** One target accumulated during a scan; `correlated_at` is its work mark. */\ntype Correlated = {\n source: string | undefined;\n priority: number;\n lane: string | undefined;\n /** True when priority/lane came from a resolution that beat the floor. */\n upgraded: boolean;\n /** True when the target had no record, so its row must be read. */\n missed: boolean;\n /** The reaction whose resolution set priority/lane. */\n handler: string;\n correlated_at: number | undefined;\n};\n\n/** Constructor dependencies for {@link CorrelateCycle}. */\nexport type CorrelateCycleDeps<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n> = {\n registry: Registry<TSchemaReg, TEvents, TActions>;\n static_targets: ReadonlyArray<StaticTarget>;\n cd: DrainOps<TEvents>;\n max_subscribed_streams: number;\n /** Every lane a controller exists for; others are rerouted to default. */\n declared_lanes: ReadonlySet<string>;\n /** Set when `onlyLanes` leaves a lane out; each shard gets its own lease. */\n shard?: ReadonlyArray<string>;\n on_init?: () => void;\n on_init_async?: () => Promise<void>;\n};\n\n/**\n * A dynamic resolution named an undeclared lane. Rerouted to `\"default\"`\n * rather than skipped, so the work still runs. Reported once per reaction\n * and lane, since a resolver mints one target per aggregate.\n */\nfunction report_undeclared_lane(\n seen: Set<string>,\n handler: string,\n target: string,\n lane: string,\n declared: ReadonlySet<string>\n): void {\n report_once(\n seen,\n `lane|${handler}|${lane}`,\n `Reaction \"${handler}\" resolved onto undeclared lane \"${lane}\" — for example target \"${target}\". ` +\n `Declared lanes: ${[...declared].map((l) => `\"${l}\"`).join(\", \")}. ` +\n 'No controller claims it, so the stream would never drain — running it on \"default\" instead. ' +\n \"The equivalent static `.to({ lane })` is rejected at build; a dynamic resolver's lane is only knowable here.\"\n );\n}\n\n/**\n * Two resolutions disagreed on one target's lane. Reported, not corrected:\n * re-laning a live stream would move it out from under a lease holder.\n * Keyed by orientation, since \"first discovered\" can land either way.\n */\nfunction report_lane_conflict(\n seen: Set<string>,\n handler: string,\n target: string,\n kept: string,\n dropped: string\n): void {\n report_once(\n seen,\n `conflict|${handler}|${kept}|${dropped}`,\n `Reaction \"${handler}\" resolved lane \"${dropped}\" for a stream already on \"${kept}\" — for example \"${target}\". ` +\n `These are conflicting lane assignments from two dynamic resolutions at equal priority. ` +\n `Keeping \"${kept}\", the lane it was first discovered on — re-laning a live stream would move it out from under a worker holding its lease. ` +\n `The reaction resolving \"${dropped}\" runs inside the \"${kept}\" lane's budget, and a process restricted to \"${dropped}\" via onlyLanes never runs it. ` +\n \"The equivalent static declaration is rejected at build; align the resolvers, or split the target.\"\n );\n}\n\n/** Drives correlation for one Act: the checkpoint, the lease, the subscription records. */\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 /** Lease holder id; per instance, so a restart never inherits a stale claim. */\n private readonly _by = randomUUID();\n private readonly _key: string;\n /** Local expiry of the held lease (0 = none); stale only costs a duplicate scan. */\n private _lease_until = 0;\n /** Raised by a commit or notification, lowered by a short page. Starts armed. */\n private _armed = true;\n private _init_promise: Promise<void> | undefined;\n // Bounded by `maxSubscribedStreams`; static records live apart so eviction\n // never drops their +Infinity floor.\n private readonly _dynamic_subscriptions: LruMap<string, Subscription>;\n private readonly _static_subscriptions = new Map<string, Subscription>();\n private readonly _patterns = new LruMap<string, RegExp>(PATTERN_CACHE_SIZE);\n private readonly _registry: Registry<TSchemaReg, TEvents, TActions>;\n private readonly _static_targets: ReadonlyArray<StaticTarget>;\n private readonly _cd: DrainOps<TEvents>;\n private readonly _on_init: (() => void) | undefined;\n /** Runs once after `on_init`; re-seeds defer timers across a restart. */\n private readonly _on_init_async: (() => Promise<void>) | undefined;\n private readonly _declared_lanes: ReadonlySet<string>;\n /** Report-once keys; per instance because `internal/` holds no module state. */\n private readonly _reported = new Set<string>();\n\n constructor({\n registry,\n static_targets,\n cd,\n max_subscribed_streams,\n declared_lanes,\n shard,\n on_init,\n on_init_async,\n }: CorrelateCycleDeps<TSchemaReg, TEvents, TActions>) {\n this._key = shard\n ? `${registry_key(registry.events)}:${[...shard].sort().join(\",\")}`\n : registry_key(registry.events);\n this._dynamic_subscriptions = new LruMap(max_subscribed_streams);\n this._registry = registry;\n this._declared_lanes = declared_lanes;\n this._static_targets = static_targets;\n this._cd = cd;\n this._on_init = on_init;\n this._on_init_async = on_init_async;\n }\n\n get checkpoint(): number {\n return this._checkpoint;\n }\n\n /** A commit (local or remote) may have produced uncorrelated events. */\n arm(): void {\n this._armed = true;\n }\n\n async init(): Promise<void> {\n if (this._initialized) return;\n // Single-flight, but a failure clears the promise so the next call retries.\n if (!this._init_promise) {\n this._init_promise = this._run_init().catch((error) => {\n this._init_promise = undefined;\n throw error;\n });\n }\n await this._init_promise;\n this._initialized = true;\n }\n\n private async _run_init(): Promise<void> {\n const { watermark, correlated_at } = await this._cd.subscribe([\n ...this._static_targets,\n ]);\n this._checkpoint =\n correlated_at >= 0\n ? correlated_at\n : Math.max(-1, watermark - COLD_START_BACK_SCAN);\n this._on_init?.();\n for (const { stream, priority = 0, lane } of this._static_targets) {\n this._static_subscriptions.set(stream, {\n floor: Number.POSITIVE_INFINITY,\n priority,\n lane,\n });\n }\n // After the static subscribe, so the streams walk sees them.\n await this._on_init_async?.();\n }\n\n /** After `restore` replaced the log: forget everything and cold-start again. */\n restart(): void {\n this._initialized = false;\n this._init_promise = undefined;\n this._checkpoint = -1;\n this._dynamic_subscriptions.clear();\n this._static_subscriptions.clear();\n this._armed = true;\n }\n\n /** Forget dynamic targets whose rows a full close deleted, so they re-subscribe. */\n forget_subscribed(streams: Iterable<string>): void {\n for (const stream of streams) this._dynamic_subscriptions.delete(stream);\n }\n\n /** Would the target's own `fetch` (filtered by `source`) return this event? */\n private _in_fetch_window(\n source: string | undefined,\n stream: string\n ): boolean {\n if (source === undefined || source === stream) return true;\n if (is_literal_source(source)) return false;\n let pattern = this._patterns.get(source);\n if (!pattern) {\n pattern = new RegExp(source);\n this._patterns.set(source, pattern);\n }\n return pattern.test(stream);\n }\n\n /** Scan past the checkpoint, subscribe new targets and raise their work marks. */\n async correlate(\n query: Query = { after: -1, limit: 10 },\n /**\n * Honour the correlation lease. Only the settle loop and poller do; an\n * explicit `app.correlate()` scans now, since `close` loops on it.\n */\n lease = false\n ): Promise<{\n subscribed: number;\n last_id: number;\n marked: number;\n scanned: boolean;\n }> {\n await this.init();\n\n // A remote writer without notify leaves this disarmed; the poller re-arms.\n if (!this._armed)\n return {\n subscribed: 0,\n last_id: this._checkpoint,\n marked: 0,\n scanned: false,\n };\n\n // The lease rides `subscribe` with no streams (\"may I scan?\"). Its shared\n // checkpoint is ignored: adopting it would skip events this worker never\n // read. Renew at the halfway mark.\n const now = Date.now();\n if (lease && now >= this._lease_until - CORRELATION_LEASE_MS / 2) {\n const { correlating } = await this._cd.subscribe([], undefined, {\n key: this._key,\n by: this._by,\n millis: CORRELATION_LEASE_MS,\n });\n this._lease_until = correlating ? now + CORRELATION_LEASE_MS : 0;\n // `undefined` = store without leasing. Refused: stay armed, look again.\n if (correlating === false)\n return {\n subscribed: 0,\n last_id: this._checkpoint,\n marked: 0,\n scanned: false,\n };\n }\n\n const after = Math.max(this._checkpoint, query.after || -1);\n const correlated = new Map<string, Correlated>();\n let last_id = after;\n // A resolver threw: the scan stops before that event, so the next one\n // retries it and nothing past it is lost.\n let stopped = false;\n const found = await store().query<TEvents>(\n (event) => {\n if (stopped) return;\n const register = this._registry.events[event.name];\n if (register) {\n for (const reaction of register.reactions.values()) {\n let resolved: Resolved | undefined;\n try {\n resolved =\n typeof reaction.resolver === \"function\"\n ? reaction.resolver(event)\n : reaction.resolver;\n } catch (error) {\n stopped = true;\n report_once(\n this._reported,\n `resolver|${reaction.handler.name}|${event.id}`,\n `Resolver of reaction \"${reaction.handler.name}\" threw on ${String(event.name)} #${event.id} (stream \"${event.stream}\"): ${String(error)}. ` +\n \"Correlation stops before this event until the resolver stops throwing; work already found keeps draining.\"\n );\n return;\n }\n if (!resolved) continue;\n let lane = resolved.lane;\n if (lane !== undefined && !this._declared_lanes.has(lane)) {\n report_undeclared_lane(\n this._reported,\n reaction.handler.name,\n resolved.target,\n lane,\n this._declared_lanes\n );\n lane = undefined;\n }\n const recorded =\n this._static_subscriptions.get(resolved.target) ??\n this._dynamic_subscriptions.get(resolved.target);\n const priority = resolved.priority ?? 0;\n const upgraded = !recorded || priority > recorded.floor;\n const carried = upgraded\n ? { priority, lane }\n : { priority: recorded.priority, lane: recorded.lane };\n const entry = correlated.get(resolved.target) || {\n source: resolved.source,\n priority: carried.priority,\n lane: carried.lane,\n upgraded,\n missed: !recorded,\n handler: reaction.handler.name,\n correlated_at: undefined,\n };\n // Compare against what the target already carries, from this\n // scan or a past one.\n const seen_in_scan = correlated.has(resolved.target);\n const held_lane =\n (seen_in_scan ? entry.lane : recorded?.lane) ?? DEFAULT_LANE;\n const held_priority = seen_in_scan\n ? entry.priority\n : recorded?.priority;\n const resolved_lane = lane ?? DEFAULT_LANE;\n if (held_priority === priority && held_lane !== resolved_lane)\n report_lane_conflict(\n this._reported,\n reaction.handler.name,\n resolved.target,\n held_lane,\n resolved_lane\n );\n // Within one scan the highest priority sets the lane.\n if (carried.priority > entry.priority) {\n entry.priority = carried.priority;\n entry.lane = carried.lane;\n entry.upgraded = upgraded;\n entry.handler = reaction.handler.name;\n }\n if (this._in_fetch_window(resolved.source, event.stream))\n entry.correlated_at = event.id;\n correlated.set(resolved.target, entry);\n }\n }\n last_id = event.id;\n },\n // Resolvers see `pii: null`: correlate runs actor-less, and one\n // undecryptable row would otherwise stop every stream's reactions.\n { ...query, after, with_pii: false }\n );\n\n if (this._declared_lanes.size > 1) await this._recall(correlated);\n\n // Only targets with a mark to raise or priority/lane to register.\n const streams: SubscribeInput[] = [];\n for (const [stream, entry] of correlated) {\n if (entry.upgraded || entry.correlated_at !== undefined)\n streams.push({\n stream,\n source: entry.source,\n priority: entry.priority,\n lane: entry.lane,\n correlated_at: entry.correlated_at,\n });\n }\n\n if (streams.length) {\n // Leasing renews for free on the same call.\n const renewed_at = Date.now();\n const { subscribed, correlating } = await this._cd.subscribe(\n streams,\n last_id,\n lease\n ? { key: this._key, by: this._by, millis: CORRELATION_LEASE_MS }\n : undefined\n );\n if (lease && correlating !== false)\n this._lease_until = renewed_at + CORRELATION_LEASE_MS;\n // The orchestrator arms on re-marks too, not just new subscriptions.\n const marked = streams.filter(\n (entry) => entry.correlated_at !== undefined\n ).length;\n this._checkpoint = last_id;\n // Only dynamic targets can be upgraded (statics sit at +Infinity).\n for (const { stream, priority, lane } of streams) {\n if (correlated.get(stream)?.upgraded)\n this._dynamic_subscriptions.set(stream, {\n floor: priority as number,\n priority: priority as number,\n lane,\n });\n }\n return { subscribed, last_id, marked, scanned: true };\n }\n // Only a short page proves the log is exhausted; resolving nothing does not.\n this._checkpoint = last_id;\n this._armed = stopped || found === query.limit;\n return { subscribed: 0, last_id, marked: 0, scanned: true };\n }\n\n /**\n * Read the row of each target this scan had no record of (new or evicted),\n * so a resolution that doesn't beat its priority keeps the row's lane.\n * Only called with more than one lane declared.\n */\n private async _recall(correlated: Map<string, Correlated>): Promise<void> {\n const missed = [...correlated].filter(([, entry]) => entry.missed);\n await Promise.all(\n missed.map(async ([stream, entry]) => {\n let row: StreamPosition | undefined;\n await store().query_streams(\n (position) => {\n row = position;\n },\n { stream, stream_exact: true, limit: 1 }\n );\n if (!row) return;\n this._dynamic_subscriptions.set(stream, {\n floor: row.priority,\n priority: row.priority,\n lane: row.lane,\n });\n if (entry.priority > row.priority) return;\n const held_lane = row.lane ?? DEFAULT_LANE;\n const resolved_lane = entry.lane ?? DEFAULT_LANE;\n if (entry.priority === row.priority && held_lane !== resolved_lane)\n report_lane_conflict(\n this._reported,\n entry.handler,\n stream,\n held_lane,\n resolved_lane\n );\n entry.priority = row.priority;\n entry.lane = row.lane;\n entry.upgraded = false;\n })\n );\n }\n\n /** Release the lease early by re-acquiring it for zero ms. Best-effort. */\n async release_correlation(): Promise<void> {\n try {\n this._lease_until = 0;\n await this._cd.subscribe([], undefined, {\n key: this._key,\n by: this._by,\n millis: 0,\n });\n } catch (error) {\n log().warn(\n `Could not hand back the correlation lease during shutdown; it expires on its own within ${CORRELATION_LEASE_MS}ms and correlation resumes normally after that. ` +\n \"On a single-writer store this usually means another connection holds the database. \" +\n `Cause: ${String(error)}`\n );\n }\n }\n}\n","/**\n * @module report-once\n * @category Internal\n *\n * One-shot reporting for a misdeclaration that a build-time guard could not\n * catch.\n *\n * The guards in `build_events` and `build-classify` can only inspect a static\n * `.to({...})` — a `.to(fn)` target, lane and priority are a function until an\n * event arrives. The pipelines that resolve them (correlate for lane and\n * target, drain for the payload) are therefore where the same rules have to be\n * applied, and where the operator has to be told.\n *\n * Reporting there has one hazard the build-time guards don't: a resolver fires\n * for *every* matching event, so a naive log turns one bad declaration into a\n * line per event on a busy stream. Reporting once per offending declaration is\n * what makes the message readable.\n *\n * Which makes the key the whole design. It may only be built from things the\n * *declaration* names — handler names, event names, lane names, a statically\n * declared target — and never from a value a resolver computed at runtime.\n * A resolved target is the trap: the documented per-aggregate shape is\n * `.to(e => ({target: e.stream}))`, so a target-keyed report dedups nothing\n * across aggregates and one typo scales into one line per aggregate — the\n * unbounded volume this module exists to prevent. Runtime values\n * still belong in the *message*, as the concrete example that turns \"a\n * reaction misdeclared its lane\" into something an operator can go look at.\n *\n * Never throws. A throw inside correlate pins the checkpoint for the whole app;\n * inside drain it reaches the circuit breaker as a store failure and\n * stalls every stream.\n *\n * @internal\n */\n\nimport { log } from \"../ports.js\";\n\n/**\n * Report `message` the first time `key` is seen, and never again.\n *\n * `seen` belongs to the calling pipeline and is passed in, so a resolver\n * firing for every matching event still reports once without this module\n * remembering anything between calls — `internal/` holds no module state.\n *\n * @param seen - The caller's set of already-reported keys. Mutated.\n * @param key - Identifies the offending declaration, not the occurrence —\n * declared identifiers only, never a runtime-resolved target.\n * @param message - Wrapped in an `Error` so the logger renders a stack.\n *\n * @internal\n */\nexport function report_once(\n seen: Set<string>,\n key: string,\n message: string\n): void {\n if (seen.has(key)) return;\n seen.add(key);\n log().error(new Error(message));\n}\n","/**\n * @module correlator\n * @category Internal\n *\n * Correlation-id generator and the default implementation.\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 default_correlator: 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 close_correlation(\n correlator: Correlator,\n actor: Actor\n): string {\n return correlator({\n state: \"$close\",\n action: \"close\",\n stream: \"$close\",\n actor,\n });\n}\n","/**\n * @module date-reviver\n * @category Internal\n *\n * Turning stored text back into `Date`s, driven by the declared schema.\n *\n * JSON has no date type, so a `Date` is stored as its ISO form and something\n * has to revive it on the way out. Which fields those are is a property of the\n * Zod schema, so working it out is a Zod concern rather than an event one —\n * this module knows nothing about events, states or PII. It takes a declared\n * schema and returns the schema that revives its dates, or `undefined` when\n * there are none to revive.\n *\n * Sits beside the other schema utilities rather than inside the event builder,\n * which composes it: `event_tags` asks for one reviver for an event's `data`\n * and another for the sensitive fields held in its `pii` sidecar. One function\n * is the whole interface — how a Zod schema is taken apart stays in here.\n *\n * The shape-based {@link dateReviver} in `utils.ts` is the predecessor this\n * replaced — it revived anything ISO-8601-looking, including fields declared\n * `z.string()`.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\n\n/** Zod exposes its shape under `_zod.def` in v4 and `def` in older builds. */\nconst def_of = (schema: unknown): Record<string, unknown> | undefined =>\n (schema as { _zod?: { def?: Record<string, unknown> } })._zod?.def ??\n (schema as { def?: Record<string, unknown> }).def;\n\n/**\n * Rebuild one union variant so it still recognises its own payloads.\n *\n * Same date coercion as everywhere else, but the variant keeps its other\n * fields — this is the one place the date paths alone are not enough. A\n * variant can only reject a sibling's payload if enough of its shape is left\n * to check, and which fields do that is not knowable: a literal discriminator\n * usually does it, but a union can just as well be told apart by the *type* of\n * an ordinary field. Narrowing to the dates, or relaxing the rest, makes the\n * first variant match everything, so the one that declared the date is never\n * tried and a sibling's payload is read under the wrong rules.\n *\n * Every key is optional, so the variant still matches when a `sensitive(...)`\n * field sits in the `pii` sidecar or when a stored payload predates a field\n * the declaration has since gained.\n *\n * Reports whether this variant declared a date, so a union with none anywhere\n * builds nothing at all.\n */\nfunction variant_schema(schema: unknown): {\n schema: z.ZodType;\n dated: boolean;\n} {\n const shape = def_of(schema)?.shape as Record<string, z.ZodType> | undefined;\n if (!shape) {\n const dates = date_reviver_schema(schema);\n return { schema: dates ?? (schema as z.ZodType), dated: !!dates };\n }\n const next: Record<string, z.ZodType> = {};\n let dated = false;\n for (const [key, field] of Object.entries(shape)) {\n const dates = date_reviver_schema(field);\n if (dates) dated = true;\n next[key] = (dates ?? field).optional();\n }\n return { schema: z.looseObject(next), dated };\n}\n\n/**\n * Build the schema that revives an event's dates, or `undefined` when it\n * declares none.\n *\n * JSON has no date type, so a stored `Date` comes back as text and something\n * has to turn it back. That is this function's only job, and the schema it\n * returns says only where the dates are: every other field is left out and\n * rides through the loose object untouched. The payload was validated when it\n * was committed, so re-checking it on the way out would be work already done.\n *\n * Naming only the dates is also what makes a read tolerant, without needing a\n * rule per exception. A `sensitive(...)` field lives in the `pii` sidecar\n * rather than in `data`; an event written against an older declaration\n * predates whatever was added since; a field dropped from the declaration is\n * still in the store. None of those are dates, so none of them are described\n * here, and a payload carrying any of them still reads. The dates themselves\n * are optional for the same reason — absent is not wrong.\n *\n * Zod does the walking, so nesting, arrays, records, unions and the wrappers\n * are handled by the engine rather than by a traversal of our own that would\n * drift as Zod grows constructs. A construct this doesn't recognise\n * contributes no date, which is the documented fallthrough.\n */\nexport function date_reviver_schema(schema: unknown): z.ZodType | undefined {\n const def = def_of(schema);\n if (!def) return undefined;\n const inner = () => date_reviver_schema(def.innerType);\n switch (def.type) {\n case \"date\":\n return z.coerce.date();\n case \"object\": {\n const shape = def.shape as Record<string, z.ZodType> | undefined;\n if (!shape) return undefined;\n const dated: Record<string, z.ZodType> = {};\n for (const [key, field] of Object.entries(shape)) {\n const dates = date_reviver_schema(field);\n if (dates) dated[key] = dates.optional();\n }\n return Object.keys(dated).length ? z.looseObject(dated) : undefined;\n }\n case \"array\": {\n const element = date_reviver_schema(def.element);\n return element && z.array(element);\n }\n case \"tuple\": {\n const items = (def.items as unknown[]).map((i) => date_reviver_schema(i));\n return items.some(Boolean)\n ? z.tuple(items.map((i) => i ?? z.unknown()) as never)\n : undefined;\n }\n case \"record\": {\n const value = date_reviver_schema(def.valueType);\n return value && z.record(z.string(), value);\n }\n case \"union\": {\n // A union is the one place the date paths are not enough. Zod picks a\n // variant by trying each until one matches, so an option reduced to its\n // dates matches almost anything and the first one wins — the variant\n // that actually declared the date never gets tried, and a sibling's\n // payload gets the wrong variant's rules. Every option therefore keeps\n // its fields; see {@link variant_schema}.\n const variants = (def.options as unknown[]).map(variant_schema);\n return variants.some((v) => v.dated)\n ? z.union(variants.map((v) => v.schema) as never)\n : undefined;\n }\n case \"nullable\":\n // Keep the null: coercing it would hand back the epoch.\n return inner()?.nullable();\n case \"optional\":\n case \"nonoptional\":\n case \"readonly\":\n case \"default\":\n case \"prefault\":\n case \"catch\":\n return inner();\n default:\n return undefined;\n }\n}\n","/**\n * @module defer-config\n * @category Internal\n *\n * The `when` options for the public `defer` surface. A\n * reaction defers itself to a future time either declaratively (the\n * `.defer(when)` builder step) or imperatively (`throw new DeferSignal(when)`\n * inside a handler); both resolve `when` through here.\n *\n * The load-bearing rule is **derivability**. A deferred stream's due-time must\n * be recomputable by whichever worker re-claims it after the wait, so `when`\n * never resolves against `Date.now()`. `after` is measured from the triggering\n * event's `created` timestamp, and `at` is either a fixed `Date` or a pure\n * function of the event. Either way, re-delivering the same event yields the\n * same due-time, which is what makes a defer correct across restarts and\n * competing workers.\n *\n * Validation follows the config-schema standard (CLAUDE.md): an internal\n * `*OptionsSchema` const, a public inferred type, and a resolver. Slice 2\n * ships `after` / `at`; recurrence (`every`) extends this in Slice 3.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { Committed, DeferWhen, Schemas } from \"../types/index.js\";\nimport { DeferSignal } from \"./defer-signal.js\";\n\n/**\n * A relative span, measured from the triggering event's `created` time. At\n * least one field is required; fields are additive (`{ hours: 1, minutes: 30 }`\n * is 90 minutes).\n */\nconst DeferDurationSchema = z\n .object({\n days: z.number().positive().optional(),\n hours: z.number().positive().optional(),\n minutes: z.number().positive().optional(),\n })\n .strict()\n .refine((d) => d.days != null || d.hours != null || d.minutes != null, {\n message: \"defer: a duration needs at least one of days, hours, or minutes\",\n });\n\n/**\n * Zod schema for the `defer(when)` options bag. Exactly one of `after` / `at`;\n * `at` is an absolute `Date`. Internal per the config standard; the public\n * surface is {@link DeferWhen} and {@link resolve_defer_at}.\n *\n * @internal\n */\nconst DeferWhenSchema = z\n .object({\n after: DeferDurationSchema.optional(),\n at: z.date().optional(),\n })\n .strict()\n .refine((w) => (w.after === undefined) !== (w.at === undefined), {\n message: \"defer: specify exactly one of `after` or `at`\",\n });\n\n/** Sum a duration bag to milliseconds. @internal */\nfunction duration_ms(d: {\n days?: number;\n hours?: number;\n minutes?: number;\n}): number {\n return (\n (d.days ?? 0) * 86_400_000 +\n (d.hours ?? 0) * 3_600_000 +\n (d.minutes ?? 0) * 60_000\n );\n}\n\n/**\n * Resolve `when` to an absolute due-time (ms since epoch) for a given\n * triggering event. Validates via {@link DeferWhenSchema} (throws `ZodError`\n * on a bad shape), then derives the time: `after` from `event.created`, `at`\n * from its absolute `Date`. Never reads `Date.now()`, so the result is stable\n * across re-delivery.\n *\n * @internal\n */\nexport function resolve_defer_at<E extends Schemas>(\n when: DeferWhen,\n event: Committed<E, keyof E>\n): number {\n const parsed = DeferWhenSchema.parse(when);\n if (parsed.after) return event.created.getTime() + duration_ms(parsed.after);\n return parsed.at!.getTime();\n}\n\n/**\n * The schedule handed to the declarative `.defer` builder step: either a\n * literal {@link DeferWhen} (fixed cooldown/deadline) or a function of the\n * triggering event (read the payload to choose the schedule).\n *\n * @internal\n */\nexport type DeferSchedule<TEvent> = DeferWhen | ((event: TEvent) => DeferWhen);\n\n/**\n * Validate a literal `when` at build time (fail fast, per the config-schema\n * standard) — throws `ZodError` on a bad shape (both/neither of `after`/`at`,\n * an empty or non-positive duration). The function form of a `.defer` schedule\n * can only be checked when it runs, so builders pass just the literal here.\n *\n * @internal\n */\nexport function assert_defer_when(when: DeferWhen): void {\n DeferWhenSchema.parse(when);\n}\n\n/**\n * Wrap a reaction handler so it holds until its schedule is due, then runs.\n * On each delivery it resolves the schedule against the triggering event; if\n * the due-time hasn't arrived it throws {@link DeferSignal} (the drain holds\n * the stream, no watermark advance, no retry bump), otherwise it runs the\n * real handler. The wrapper keeps the original handler's `name` so reaction\n * registration and de-dup are unaffected, and preserves the handler's exact\n * type so the builder step is transparent.\n *\n * @internal\n */\nexport function make_deferred<H extends (...args: any[]) => Promise<unknown>>(\n handler: H,\n schedule: DeferSchedule<Parameters<H>[0]>\n): H {\n const call = handler as (...args: unknown[]) => Promise<unknown>;\n const deferred = async (\n event: Parameters<H>[0],\n stream: string,\n app: unknown\n ) => {\n const when = typeof schedule === \"function\" ? schedule(event) : schedule;\n if (Date.now() < resolve_defer_at(when, event)) throw new DeferSignal(when);\n return call(event, stream, app);\n };\n Object.defineProperty(deferred, \"name\", { value: handler.name });\n return deferred as unknown as H;\n}\n","/**\n * The drain pipeline: {@link run_drain_cycle} is one stateless\n * claim → fetch → dispatch → ack/block round-trip; {@link DrainController}\n * owns the armed flag, the lock, the lag/lead ratio and the defer wake.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { log } from \"../ports.js\";\nimport type {\n BatchHandler,\n BlockedLease,\n CloseTarget,\n Drain,\n DrainOptions,\n Fetch,\n Lease,\n Logger,\n ReactionOptions,\n ReactionPayload,\n Registry,\n Resolved,\n SchemaRegister,\n Schemas,\n} from \"../types/index.js\";\nimport { compute_backoff_delay } from \"./backoff.js\";\nimport type { CircuitBreaker } from \"./circuit-breaker.js\";\nimport {\n DEFAULT_BACKOFF,\n DEFAULT_EVENT_LIMIT,\n DEFAULT_LEASE_MILLIS,\n DEFAULT_STREAM_LIMIT,\n} from \"./config.js\";\nimport { DeferTimer } from \"./defer-timer.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport { compute_lag_lead_ratio } from \"./drain-ratio.js\";\nimport { report_once } from \"./report-once.js\";\nimport { trace_cycle } from \"./tracing.js\";\n\n/** Outcome of handling one leased stream; drives its ack/block. */\nexport type HandleResult = Readonly<{\n lease: Lease;\n handled: number;\n /** Last successful event id, or `lease.at` when there was no work. */\n acked_at: number;\n error?: string;\n block?: boolean;\n /** Epoch ms of the next retry, from the backoff. Only set on a retry. */\n next_attempt_at?: number;\n /** Epoch ms to redeliver a deferred stream; no error, no retry bump. */\n defer?: number;\n /** From a `CloseSignal`; acked first so the close guard sees it caught up. */\n close?: CloseTarget;\n /** Event id that threw (sparse ids make it differ from `acked_at + 1`); never in batch mode. */\n failed_at?: number;\n}>;\n\n/** `Act.handle`. */\nexport type Handle<TEvents extends Schemas> = (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[]\n) => Promise<HandleResult>;\n\n/** `Act.handle_batch`. */\nexport type HandleBatch<TEvents extends Schemas> = (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[],\n batchHandler: BatchHandler<TEvents>\n) => Promise<HandleResult>;\n\ntype 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 readonly closeable: CloseTarget[];\n};\n\n/**\n * Blocks a stream whose retries were all spent losing the lease (no handler\n * error ever reached the block decision). Strictly `> maxRetries`: the final\n * attempt runs at `=== maxRetries`. Stands down while the store is failing,\n * since `claim` counts retries no handler earned.\n */\nfunction budget_exhausted<TEvents extends Schemas>(\n lease: Lease,\n options: ReactionPayload<TEvents>[\"options\"] | undefined,\n store_failing: boolean\n): HandleResult | undefined {\n if (\n store_failing ||\n !options?.blockOnError ||\n lease.retry <= options.maxRetries\n )\n return undefined;\n const error = `Blocking ${lease.stream} after ${lease.retry} claims with no acknowledged progress — the retry budget (${options.maxRetries}) was spent without the handler ever reporting an error. That means every attempt lost its lease before it could ack: move the reaction to a lane whose leaseMillis covers the handler, then unblock the stream.`;\n log().error(error);\n return { lease, handled: 0, acked_at: lease.at, error, block: true };\n}\n\n/**\n * A failed fetch has no payloads to say which reaction it was for, so take\n * the most conservative policy: block only if every reaction does, after\n * the largest budget.\n */\nfunction fetch_failure_policy<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(registry: Registry<TSchemaReg, TEvents, TActions>): ReactionOptions {\n let blockOnError = true;\n let maxRetries = 0;\n for (const register of Object.values(registry.events))\n for (const reaction of register.reactions.values()) {\n blockOnError &&= reaction.options.blockOnError;\n maxRetries = Math.max(maxRetries, reaction.options.maxRetries);\n }\n return { blockOnError, maxRetries };\n}\n\n/** A resolver's error message, and the options of the reaction it belongs to. */\ntype ResolverFailure = { error: string; options: ReactionOptions };\n\n/**\n * A resolver threw while matching a leased stream's events. Only that\n * stream fails: it retries on the reaction's backoff and blocks when the\n * reaction's budget is spent, like a failing handler.\n */\nfunction resolver_failed(\n lease: Lease,\n { error, options }: ResolverFailure\n): HandleResult {\n log().error(error);\n const block = options.blockOnError && lease.retry >= options.maxRetries;\n return {\n lease,\n handled: 0,\n acked_at: lease.at,\n error,\n ...(block\n ? { block: true }\n : {\n next_attempt_at:\n Date.now() +\n compute_backoff_delay(\n lease.retry,\n options.backoff ?? DEFAULT_BACKOFF\n ),\n }),\n };\n}\n\n/** Reported once per declaration; every key part is declared, so it stays bounded. */\nfunction warn_misrouted(\n seen: Set<string>,\n stream: string,\n handler: string,\n event: string\n): void {\n report_once(\n seen,\n `${stream}|${handler}|${event}`,\n `Reaction \"${handler}\" on \"${event}\" resolved to target \"${stream}\", which a projection already serves. ` +\n \"A target is served by one batch handler or one state projection, so this reaction can never run — and delivering to it would hand the projection an aggregate from another stream. \" +\n \"Skipping it. The equivalent static `.to({ target })` is rejected at build; a dynamic resolver's target is only knowable here.\"\n );\n}\n\ntype CycleInput = {\n readonly lagging: number;\n readonly leading: number;\n readonly eventLimit: number;\n readonly leaseMillis: number;\n readonly misrouted: Set<string>;\n readonly store_failing: boolean;\n};\n\n/** One drain cycle; `undefined` when nothing was claimed. */\nasync function run_drain_cycle<\n TEvents extends Schemas,\n TActions extends Schemas,\n TSchemaReg extends SchemaRegister<TActions>,\n>(\n deps: DrainControllerDeps<TEvents, TActions, TSchemaReg>,\n cycle: CycleInput\n): Promise<DrainCycle<TEvents> | undefined> {\n const { ops, registry, batch_handlers, handle, handle_batch, lane } = deps;\n const {\n lagging,\n leading,\n eventLimit,\n leaseMillis,\n misrouted,\n store_failing,\n } = cycle;\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 const fetched = await ops.fetch(leased, eventLimit);\n\n type FetchEntry = (typeof fetched)[number];\n const fetch_map = new Map<\n string,\n {\n fetch: FetchEntry;\n payloads: ReactionPayload<TEvents>[];\n failed?: ResolverFailure;\n }\n >();\n\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 let failed: ResolverFailure | undefined;\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 resolver = reaction.resolver;\n const dynamic = typeof resolver === \"function\";\n let resolved: Resolved | undefined;\n try {\n resolved = dynamic ? resolver(event) : resolver;\n } catch (error) {\n failed ??= {\n error: `Resolver of reaction \"${reaction.handler.name}\" threw on ${String(event.name)} #${event.id} (stream \"${event.stream}\"): ${String(error)}`,\n options: reaction.options,\n };\n return false;\n }\n if (!resolved || resolved.target !== stream) return false;\n // A dynamic resolution onto a projection's target: skip and report.\n // Not a throw, which would read as a store failure.\n if (!dynamic || !batch_handlers.has(stream)) return true;\n warn_misrouted(\n misrouted,\n stream,\n reaction.handler.name,\n String(event.name)\n );\n return false;\n })\n .map((reaction) => ({ ...reaction, event }));\n });\n fetch_map.set(stream, { fetch: f, payloads, failed });\n }\n\n const handled = await Promise.all(\n leased.map((lease) => {\n const entry = fetch_map.get(lease.stream)!;\n // Retried after the default backoff; blocks once the budget is spent,\n // unless the whole store is failing (the breaker's job).\n if (entry.fetch.error !== undefined) {\n const error = `Fetch failed for ${lease.stream}: ${entry.fetch.error}`;\n log().error(error);\n const policy = fetch_failure_policy(registry);\n const block =\n !store_failing &&\n policy.blockOnError &&\n lease.retry >= policy.maxRetries;\n const failed: HandleResult = {\n lease,\n handled: 0,\n acked_at: lease.at,\n error,\n ...(block\n ? { block: true }\n : {\n next_attempt_at:\n Date.now() +\n compute_backoff_delay(lease.retry, DEFAULT_BACKOFF),\n }),\n };\n return Promise.resolve(failed);\n }\n // A resolver threw: this stream fails like a handler would.\n if (entry.failed)\n return Promise.resolve(resolver_failed(lease, entry.failed));\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 exhausted = budget_exhausted(\n lease,\n payloads[0]?.options,\n store_failing\n );\n if (exhausted) return Promise.resolve(exhausted);\n const batchHandler = batch_handlers.get(lease.stream);\n if (batchHandler && payloads.length > 0) {\n return handle_batch({ ...lease, at }, payloads, batchHandler);\n }\n return handle({ ...lease, at }, payloads);\n })\n );\n\n // `block` before `ack`: block needs the lease, ack releases it. A\n // partial-progress block goes to both. Deferred and backing-off entries\n // carry `due`, so one `ack` also persists the schedule (defer: retry -1).\n const blocked = await ops.block(\n handled\n .filter(({ block }) => block)\n .map(({ lease, error }) => ({ ...lease, error: error! }))\n );\n\n // Before the `ack`, so an ack failure can't lose the terminal event.\n if (blocked.length) deps.on_blocked(blocked);\n\n const submitted = handled.flatMap((h, i) => {\n const advance = h.handled > 0 ? h.acked_at : leased[i].at;\n return h.defer !== undefined\n ? { ...h.lease, at: advance, due: h.defer, retry: -1 }\n : h.next_attempt_at !== undefined\n ? { ...h.lease, at: advance, due: h.next_attempt_at }\n : h.handled > 0 || !h.error\n ? { ...h.lease, at: h.acked_at }\n : [];\n });\n const acked = await ops.ack(submitted);\n\n // `ack` drops entries whose lease another worker took (deferred entries\n // are never returned).\n const expected = submitted.filter((l) => l.due === undefined).length;\n if (acked.length < expected)\n log().warn(\n `drain: ${expected - acked.length} of ${expected} acks were dropped — the lease was taken by another worker mid-handler. That work will be redelivered (at-least-once), but persistent drops mean leaseMillis is too short for this handler.`\n );\n\n const closeable = handled\n .filter((h) => h.close !== undefined)\n .map((h) => h.close!);\n\n return { leased, fetched, handled, acked, blocked, closeable };\n}\n\nconst EMPTY_DRAIN: Drain<Schemas> = {\n fetched: [],\n leased: [],\n acked: [],\n blocked: [],\n};\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 batch_handlers: Map<string, BatchHandler<TEvents>>;\n readonly handle: Handle<TEvents>;\n readonly handle_batch: HandleBatch<TEvents>;\n readonly on_acked: (acked: Lease[]) => void;\n readonly on_blocked: (blocked: BlockedLease[]) => void;\n /** Awaited, so a slow close doesn't overlap the next claim. */\n readonly on_close: (targets: CloseTarget[]) => Promise<void>;\n readonly breaker: CircuitBreaker;\n /** The worker ticks outside any caller frame, so its drain is re-scoped. */\n readonly run_scoped: <T>(fn: () => Promise<T>) => Promise<T>;\n /** Lane this controller drains. Undefined spans all lanes. */\n readonly lane?: string;\n /** The lane's own config; it wins over the caller's DrainOptions. */\n readonly defaults?: {\n readonly streamLimit?: number;\n readonly leaseMillis?: number;\n };\n};\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 * Local wake at the earliest parked (backoff or defer) visit; the schedule\n * itself is persisted. On an idle app nothing else would drain it. A due\n * entry stays until handled or until a later pass claims nothing.\n */\n private readonly _defer = new DeferTimer(() => {\n this._armed = true;\n void this._deps.run_scoped(() => this.drain());\n });\n private _worker: ReturnType<typeof setTimeout> | undefined;\n private readonly _misrouted = new Set<string>();\n private _stopped = false;\n /** Never rejects; graceful shutdown waits on it. */\n private _inflight: Promise<void> | undefined;\n private _inflight_done: (() => void) | undefined;\n\n private readonly _deps: DrainControllerDeps<TEvents, TActions, TSchemaReg>;\n\n constructor(deps: DrainControllerDeps<TEvents, TActions, TSchemaReg>) {\n this._deps = deps;\n }\n\n arm(): void {\n this._armed = true;\n }\n\n /** Cold start: re-seed a persisted `deferred_at` into the local wake. */\n seed_defer(stream: string, at: number): void {\n this._defer.set(stream, at);\n this._defer.schedule();\n }\n\n get armed(): boolean {\n return this._armed;\n }\n\n get inflight(): Promise<void> | undefined {\n return this._inflight;\n }\n\n /** This lane's configured lease, or `undefined`; the shutdown grace basis. */\n get lease_millis(): number | undefined {\n return this._deps.defaults?.leaseMillis;\n }\n\n get lane(): string | undefined {\n return this._deps.lane;\n }\n\n /** Drains every `cycleMs` while armed; the unref'd timer never holds the process. */\n start(cycleMs: number): void {\n if (this._worker || this._stopped) return;\n // `drain()` never throws.\n const run = this._deps.run_scoped;\n const tick = async () => {\n if (this._armed) await run(() => 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(): void {\n this._stopped = true;\n if (this._worker) {\n clearTimeout(this._worker);\n this._worker = undefined;\n }\n this._defer.stop();\n }\n\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 // A lane's own budget wins over caller options.\n const streamLimit =\n d.streamLimit ?? options.streamLimit ?? DEFAULT_STREAM_LIMIT;\n const eventLimit = options.eventLimit ?? DEFAULT_EVENT_LIMIT;\n const leaseMillis =\n d.leaseMillis ?? options.leaseMillis ?? DEFAULT_LEASE_MILLIS;\n\n // Circuit open: stay armed and leave the wake alone (re-aiming would fire\n // at once for anything due); the breaker's own wake re-aims it.\n if (this._deps.breaker.state(Date.now()) === \"open\")\n return EMPTY_DRAIN as Drain<TEvents>;\n\n try {\n this._locked = true;\n this._inflight = new Promise<void>((done) => {\n this._inflight_done = done;\n });\n const lagging = Math.ceil(streamLimit * this._ratio);\n const leading = streamLimit - lagging;\n\n const started = Date.now();\n const cycle = await run_drain_cycle(this._deps, {\n lagging,\n leading,\n eventLimit,\n leaseMillis,\n misrouted: this._misrouted,\n store_failing: this._deps.breaker.failing,\n });\n\n if (!cycle) {\n // Caught up: whatever was due when this pass started has no work.\n this._defer.prune(started);\n this._deps.breaker.passed();\n this._armed = false;\n return EMPTY_DRAIN as Drain<TEvents>;\n }\n\n const { leased, fetched, handled, acked, blocked, closeable } = cycle;\n\n trace_cycle(this._deps.logger, leased, fetched, handled, acked, blocked);\n\n this._ratio = compute_lag_lead_ratio(handled, lagging, leading);\n\n for (const lease of acked) this._defer.delete(lease.stream);\n for (const lease of blocked) this._defer.delete(lease.stream);\n for (const h of handled) {\n const next = h.defer ?? h.next_attempt_at;\n if (next !== undefined) this._defer.set(h.lease.stream, next);\n }\n\n // Listener throws are contained in `Act.emit`.\n if (acked.length) this._deps.on_acked(acked);\n // The orchestrator contains close failures; anything that still\n // throws here reaches the breaker.\n if (closeable.length) await this._deps.on_close(closeable);\n\n // After `on_close`, so a failed close never counts as a store success.\n this._deps.breaker.passed();\n\n // Errors keep the flag set so retries flow through the next drain.\n const has_errors = handled.some(({ error }) => error);\n if (!acked.length && !blocked.length && !has_errors) this._armed = false;\n\n return { fetched, leased, acked, blocked };\n } catch (error) {\n // A store op threw: stay armed, retry after the cooldown.\n this._deps.breaker.failed(Date.now(), error);\n return EMPTY_DRAIN as Drain<TEvents>;\n } finally {\n // Re-aim at the earliest stream still parked.\n if (!this._stopped) this._defer.schedule();\n this._locked = false;\n this._inflight = undefined;\n this._inflight_done?.();\n this._inflight_done = undefined;\n }\n }\n}\n","/**\n * @module defer-timer\n * @category Internal\n *\n * The shared \"next visit time\" primitive. A `DeferTimer` holds a\n * `stream → due-time` map and a single collapsed wake timer: it parks\n * streams that should be re-visited later and fires one `on_wake` callback\n * at the earliest pending due-time.\n *\n * The {@link \"drain-cycle\".DrainController} rides it for per-reaction\n * backoff (a retry's `next_attempt_at`) and for the `defer` outcome, which\n * holds a stream pending without advancing the watermark or bumping `retry`.\n * The wake runs a drain, and the drain re-schedules the timer when it ends.\n * An entry stays until its stream is acked or blocked, re-parked, or a\n * drain that started after it came due claims nothing ({@link prune}): a\n * wake that lands during another drain, or a pass that reaches only some of\n * the due streams, leaves the rest due, so the next re-schedule fires again\n * at once.\n *\n * Lives in process memory, per worker — the same per-worker pacing trade-off\n * documented for backoff. Durability comes from the data the due-time is\n * *derived* from (an un-advanced watermark, an event's `created` timestamp),\n * not from the map. A restart empties the map, so the cold-start rebuild is\n * explicit: `CorrelateCycle.init` seeds each still-future `deferred_at` back\n * onto the owning lane's timer via {@link \"drain-cycle\".DrainController.seed_defer},\n * so an idle deferred stream re-arms at its due-time with no\n * intervening commit.\n *\n * @internal\n */\n\n/**\n * A min-heap-free scheduler over a small `stream → due-time` map. The maps\n * are bounded by the worker's claim/stream limits, so a linear scan for the\n * earliest entry is cheaper than maintaining a heap.\n *\n * @internal\n */\n\n/**\n * Node's `setTimeout` delay is a 32-bit signed int (~24.8 days). A larger\n * delay overflows and fires immediately, so we cap at this and re-arm.\n *\n * @internal\n */\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nexport class DeferTimer {\n private readonly _due = new Map<string, number>();\n private _timer: ReturnType<typeof setTimeout> | undefined;\n private readonly _on_wake: () => void;\n\n /**\n * @param on_wake - invoked once each time the earliest due-time elapses.\n * The consumer re-schedules for whatever is still parked.\n */\n constructor(on_wake: () => void) {\n this._on_wake = on_wake;\n }\n\n /** Number of currently parked streams. */\n get size(): number {\n return this._due.size;\n }\n\n /**\n * Park `stream` for a re-visit at `at` (ms since epoch). A plain\n * overwrite: the caller computes the authoritative next-visit for the\n * stream (the drain's `handle` already reconciles a stream's reactions\n * into one result per cycle), so there is no stale value to merge against.\n */\n set(stream: string, at: number): void {\n this._due.set(stream, at);\n }\n\n /** Drop `stream` from the parked set (e.g. on a successful ack or block). */\n delete(stream: string): void {\n this._due.delete(stream);\n }\n\n /**\n * Drop every entry due at or before `before`. The drain calls it when a\n * pass that started at `before` claimed nothing: whatever was due by then\n * was handled elsewhere (another worker) or has no work left, so waking\n * for it again would spin.\n */\n prune(before: number): void {\n for (const [stream, at] of this._due)\n if (at <= before) this._due.delete(stream);\n }\n\n /**\n * (Re)schedule the wake timer at the earliest pending due-time. Idempotent\n * — collapses many parked streams into a single timer. A no-op clears any\n * pending timer when the map is empty.\n *\n * The timer is `unref()`-ed so pending re-visits never keep the process\n * alive on their own.\n */\n schedule(): void {\n if (this._timer) clearTimeout(this._timer);\n if (this._due.size === 0) {\n this._timer = undefined;\n return;\n }\n let earliest = Number.POSITIVE_INFINITY;\n for (const t of this._due.values()) if (t < earliest) earliest = t;\n // Clamp to setTimeout's 32-bit ceiling (~24.8 days). A longer due-time\n // (e.g. a 90-day autoclose cooldown) would otherwise overflow and Node\n // fires it immediately, busy-looping. Instead we wake at the ceiling: the\n // still-future entry stays, the consumer re-schedules for the remaining\n // span, and (for persisted defers) `claim` skips the stream until its\n // real due-time anyway.\n const delay = Math.min(\n Math.max(0, earliest - Date.now()),\n MAX_TIMER_DELAY_MS\n );\n this._timer = setTimeout(() => {\n this._timer = undefined;\n this._on_wake();\n }, delay);\n this._timer.unref();\n }\n\n /** Cancel any pending wake timer. Idempotent. Leaves the parked set intact. */\n stop(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\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 compute_lag_lead_ratio(\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 SubscribeInput,\n SubscribeResult,\n} from \"../types/index.js\";\nimport { is_literal_source } from \"../utils.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 // A literal `source` fetches with `stream_exact` so an exact name\n // like \"s1\" reads only \"s1\" — never a sibling prefix \"s12\". A\n // pattern source (e.g. `^(A|B)$`) stays a regex query, matching the\n // same streams correlate resolved it for.\n const stream_exact =\n source !== undefined && is_literal_source(source) ? true : undefined;\n try {\n await store().query<TEvents>((e) => events.push(e), {\n stream: source,\n stream_exact,\n after: at,\n limit: eventLimit,\n });\n } catch (error) {\n // Contain it per stream. These reads are already per-stream, but they\n // shared one `Promise.all`, so one stream's failure rejected the whole\n // cycle and every healthy stream leased beside it got nothing —\n // an unreadable `pii` payload on one aggregate stalled unrelated\n // reactions. The cycle turns this into a no-progress failure\n // for THIS stream only, which the retry budget then escalates.\n //\n // Unlike correlate, this read cannot simply decline the payload:\n // handlers receive it (through their own gate), so a fetch that\n // dropped it would hand them a silently incomplete event.\n return {\n stream,\n source,\n at,\n lagging,\n events: [],\n error: (error as Error)?.message ?? String(error),\n } as const;\n }\n return { stream, source, at, lagging, events } as const;\n })\n );\n}\n\n// Finalize: acks and defers in one atomic store call. Leases\n// carrying `due` are deferred, the rest acked — a failed finalize lands\n// nothing, and redelivery covers every outcome uniformly.\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: SubscribeInput[],\n correlated_at?: number,\n correlator?: { key: string; by: string; millis: number }\n): Promise<SubscribeResult> =>\n store().subscribe(streams, correlated_at, correlator);\n","/**\n * Event-sourcing primitives: `snap`, `load`, `action`, `tombstone`, `scan`.\n * Bare implementations; tracing wraps them in `tracing.ts`.\n */\n\nimport { type Patch, 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 CacheEntry,\n Committed,\n DoOptions,\n Emitted,\n EventMeta,\n EventSource,\n LoadTarget,\n ScanOptions,\n ScanResult,\n Schema,\n Schemas,\n Snapshot,\n State,\n Target,\n} from \"../types/index.js\";\nimport { sleep, validate } from \"../utils.js\";\nimport { compute_backoff_delay } from \"./backoff.js\";\nimport { default_correlator } from \"./correlator.js\";\n\n/**\n * The patch step: merges a reducer's partial into state. Chosen once at\n * construction (`build_es`), never per event. `me`/`event` only serve\n * {@link validating_patch}, to name the failing reduction.\n */\nexport type PatchFn = <\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(\n me: State<TState, TEvents, TActions>,\n state: TState,\n partial: Readonly<Patch<TState>>,\n event: Committed<TEvents, keyof TEvents>\n) => TState;\n\n/** The default patch step: a bare merge, so the hot path pays nothing. */\nexport const bare_patch: PatchFn = (_me, state, partial) =>\n patch(state, partial) as typeof state;\n\n/**\n * `validateFoldedState`: merge, then parse against the state schema, so a\n * bad reducer fails at its own event. A debugging aid, not a production guard.\n */\nexport const validating_patch: PatchFn = (me, state, partial, event) => {\n const next = patch(state, partial) as typeof state;\n return validate(\n `${me.name}.${String(event.name)}#${event.id}`,\n next,\n me.state\n );\n};\n\nconst DEFAULT_BATCH = 500;\n\n/** `action` with the correlator and patch step bound by `build_es`. */\ntype 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 options?: DoOptions<TEvents>\n) => Promise<Snapshot<TState, TEvents>[]>;\n\nexport interface EsOps {\n snap: typeof snap;\n load: typeof load;\n action: BoundAction;\n tombstone: typeof tombstone;\n}\n\n/** Writes a cache checkpoint. A failure only costs the next load a re-fold. */\nconst cache_put = <TState extends Schema>(\n stream: string,\n entry: CacheEntry<TState>\n): Promise<void> =>\n cache()\n .set(stream, entry)\n .catch((err) =>\n log().warn(\n err,\n \"cache set skipped; the next load re-folds from the store\"\n )\n );\n\n/** Drops a cache checkpoint. A failure leaves a stale one, which re-folds. */\nconst cache_drop = (stream: string): Promise<void> =>\n cache()\n .invalidate(stream)\n .catch((err) =>\n log().warn(\n err,\n \"cache invalidate skipped; a stale checkpoint re-folds from its event_id\"\n )\n );\n\n/** Commits a snapshot event. Never throws: a failed snapshot must not fail the action. */\nexport async function snap<TState extends Schema, TEvents extends Schemas>(\n snapshot: Snapshot<TState, TEvents>\n): Promise<Committed<TEvents, keyof TEvents> | undefined> {\n const { id, stream, name, meta, version } = snapshot.event!;\n try {\n const [committed] = 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 return committed as Committed<TEvents, keyof TEvents>;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n log().warn(\n `Snapshot write failed on stream \"${stream}\": ${reason} — cold starts will replay full history until snapshots succeed.`\n );\n }\n}\n\n/**\n * Commits the close guard at `expectedVersion`; `undefined` when the stream\n * moved. Actions then see the tombstone at head and throw {@link StreamClosedError}.\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 * Rejects a negative version or an invalid `created` Date. Duplicate ids and\n * version gaps are left to the sink (partial backups have gaps).\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 * Pages a restore source: validation, drop filters, migrations, progress and\n * causation remap. Adapters supply only the per-event insert `callback`\n * (see {@link Store.restore}). A source that ignores `limit` (`CsvFile`)\n * returns everything in one page.\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 {\n drop_snapshots = false,\n drop_closed_streams = false,\n on_progress,\n event_migrations,\n stream_rename,\n } = 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 dropped_closed = 0;\n let migrated_count = 0;\n let processed = 0;\n let at: number | undefined;\n\n // `drop_closed_streams`: one extra walk to collect tombstoned streams.\n const closed_streams = new Set<string>();\n if (drop_closed_streams) {\n await source.query<Schemas>(\n (e) => {\n if (e.name === TOMBSTONE_EVENT) closed_streams.add(e.stream);\n },\n { names: [TOMBSTONE_EVENT] }\n );\n }\n\n // Probe the highest id (an index seek on SQL stores). A source that\n // ignores the filter returns more than one row; leave max_id unknown.\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, with_snaps: true }\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 (\n closed_streams.has(event.stream) &&\n event.name !== TOMBSTONE_EVENT\n ) {\n // Keep the tombstone: it is what keeps the stream closed.\n dropped_closed++;\n return;\n }\n // Before the causation remap, so `id_map` stays keyed by source id.\n let migrated: typeof event = event;\n const migration = event_migrations?.[event.name as string];\n if (migration) {\n const old_data = migration.from_schema.parse(event.data);\n const new_data = migration.migrate(old_data);\n migration.to_schema.parse(new_data);\n migrated = {\n ...event,\n name: migration.to as typeof event.name,\n data: new_data as any,\n };\n migrated_count++;\n }\n if (stream_rename) {\n const renamed = stream_rename(migrated.stream);\n if (renamed !== migrated.stream)\n migrated = { ...migrated, stream: renamed };\n }\n if (!callback) {\n kept++;\n return;\n }\n let remapped = migrated;\n const caused_by = migrated.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 // Spread `migrated`, not `event`, or the migration is undone.\n remapped = {\n ...migrated,\n meta: {\n ...migrated.meta,\n causation: {\n ...migrated.meta.causation,\n event: {\n ...migrated.meta.causation.event!,\n id: new_caused_by,\n },\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, with_snaps: true }\n );\n\n // Stop on a short page, or on an oversized one (the source ignored the\n // limit and already returned everything).\n if (got !== limit) break;\n at = id;\n }\n\n return {\n kept,\n migrated: migrated_count,\n dropped: {\n closed_streams: dropped_closed,\n snapshots: dropped_snaps,\n },\n };\n}\n\n/**\n * Folds a stream into state, from the cached checkpoint or the latest\n * snapshot. `asOf` time-travels and bypasses the cache.\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 target: LoadTarget,\n callback?: (snapshot: Snapshot<TState, TEvents>) => void,\n patch_fn: PatchFn = bare_patch\n): Promise<Snapshot<TState, TEvents>> {\n const { stream, actor, asOf } = target;\n const time_travel =\n !!asOf && Object.values(asOf).some((v) => v !== undefined);\n const cached = time_travel ? 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 // Events this load processed; `patches` is the snap distance from the cache.\n let replayed = 0;\n let event: Committed<TEvents, keyof TEvents> | undefined;\n\n await store().query<TEvents>(\n (raw) => {\n event = me.view(raw, actor);\n if (event.name === SNAP_EVENT) {\n state = event.data as TState;\n snaps++;\n patches = 0;\n replayed++;\n } else if (me.patch[event.name]) {\n state = patch_fn(me, state, me.patch[event.name](event, state), event);\n patches++;\n replayed++;\n } else if (event.name !== TOMBSTONE_EVENT) {\n // A renamed event, the wrong state, or a contaminated stream.\n log().warn(\n `Skipping unknown event \"${String(event.name)}\" on stream \"${stream}\" (id=${event.id}) — no reducer in state \"${me.name}\"`\n );\n }\n callback?.({\n event,\n state,\n version: event.version,\n id: event.id,\n patches,\n snaps,\n cache_hit,\n replayed,\n });\n },\n {\n stream,\n stream_exact: true,\n // `with_snaps` on every non-time-travel load: cold, it resumes from the\n // latest snapshot; warm, it keeps a snapshot above a stale checkpoint,\n // so a windowed close's prune can't fold the tail onto stale state.\n ...(cached\n ? { after: cached.event_id, with_snaps: true }\n : { ...(time_travel ? {} : { with_snaps: true }), ...asOf }),\n }\n );\n\n // A stale write self-corrects: the next load replays past its `event_id`.\n // Not at a tombstone head, or `action()`'s closed check would pass vacuously.\n const head_is_tombstone = event?.name === TOMBSTONE_EVENT;\n if (\n replayed > 0 &&\n !time_travel &&\n event &&\n !me.pii_aware &&\n !head_is_tombstone\n ) {\n await cache_put(stream, {\n stream,\n state,\n version: event.version,\n event_id: event.id,\n patches,\n snaps,\n });\n }\n\n return {\n event,\n state,\n version: event?.version ?? cached?.version ?? -1,\n // Captured with `state`, so consumers never race a separate cache lookup.\n id: event?.id ?? cached?.event_id ?? -1,\n patches,\n snaps,\n cache_hit,\n replayed,\n };\n}\n\n/**\n * Validates, checks invariants, emits and commits. On {@link ConcurrencyError}\n * it re-runs from `load` within the action's `maxRetries`; any other error\n * rethrows. Reactions commit without the inferred version guard.\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 options?: DoOptions<TEvents>,\n patch_fn: PatchFn = bare_patch\n): Promise<Snapshot<TState, TEvents>[]> {\n const { stream, expectedVersion, actor } = target;\n if (!stream) throw new Error(\"Missing target stream\");\n // `Act.do` already filled in the ambient reaction context.\n const reactingTo = options?.reactingTo;\n const correlator = options?.correlator ?? default_correlator;\n\n const validated = validate(action as string, payload, me.actions[action]);\n\n const opts = me.options?.[action];\n const max_retries = opts?.maxRetries ?? 0;\n\n for (let attempt = 0; ; attempt++) {\n try {\n const snapshot = await load(\n me,\n { stream, actor: target.actor },\n undefined,\n patch_fn\n );\n if (snapshot.event?.name === TOMBSTONE_EVENT)\n throw new StreamClosedError(stream);\n // `version`, not `event`: on a warm hit `event` is undefined. A new\n // stream (-1) stays unguarded.\n const expected =\n expectedVersion ??\n (snapshot.version >= 0 ? snapshot.version : undefined);\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 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 const valid = tuples.map(([name, data]) => ({\n name,\n data: validate(name as string, data, me.events[name]),\n }));\n const emitted = valid.map((e) => me.message(e));\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\n },\n event: reactingTo\n ? {\n id: reactingTo.id,\n name: reactingTo.name as string,\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 the inferred version guard (leases already\n // serialize them); an explicit expectedVersion is still honored.\n reactingTo ? expectedVersion : expected\n );\n } catch (error) {\n // Fire-and-forget, so a cache failure can't replace the ConcurrencyError.\n if (error instanceof ConcurrencyError) void cache_drop(stream);\n throw error;\n }\n\n let { state, patches } = snapshot;\n const snapshots = committed.map((row, i) => {\n // The caller sent the plaintext, so no view/gate round-trip.\n const event = { ...row, data: valid[i].data };\n const p = me.patch[event.name](event, state);\n state = patch_fn(me, state, p, event);\n patches++;\n return {\n event,\n state,\n version: event.version,\n id: event.id,\n patches,\n snaps: snapshot.snaps,\n patch: p,\n cache_hit: snapshot.cache_hit,\n replayed: snapshot.replayed,\n };\n });\n\n const last = snapshots.at(-1)!;\n // A guardless (reaction) commit can land past events this fold never\n // saw; a gapped fold must not become a snapshot or a cache entry.\n const contiguous = committed[0].version === snapshot.version + 1;\n const snapped = contiguous && me.snap?.(last);\n\n // Awaited, so the cache holds the post-snap checkpoint for the next caller.\n const snap_event = snapped ? await snap(last) : undefined;\n\n // Sensitive states depend on the actor, so they aren't cached.\n if (!me.pii_aware) {\n if (contiguous)\n void cache_put<TState>(stream, {\n stream,\n state: last.state,\n version: snap_event?.version ?? last.event.version,\n event_id: snap_event?.id ?? last.event.id,\n patches: snap_event ? 0 : last.patches,\n snaps: snap_event ? last.snaps + 1 : last.snaps,\n });\n else void cache_drop(stream);\n }\n\n return snapshots;\n } catch (error) {\n if (!(error instanceof ConcurrencyError)) throw error;\n // A caller-pinned version would conflict again on every retry.\n if (expectedVersion !== undefined) throw error;\n if (attempt >= max_retries) throw error;\n if (opts?.backoff) {\n const delay_ms = compute_backoff_delay(attempt, opts.backoff);\n if (delay_ms > 0) await sleep(delay_ms);\n }\n }\n }\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 build_es} and {@link build_drain} — 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 { default_correlator } from \"./correlator.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport * as drain from \"./drain.js\";\nimport type { EsOps, PatchFn } 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 * 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 show_lane = lane && lane !== \"default\";\n if (PRETTY) {\n const tag = `${C_DRAIN}>> ${caption}${C_RESET}`;\n return show_lane ? `${tag} ${C_LANE}${lane}${C_RESET}` : tag;\n }\n return show_lane ? `>> ${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 build_es(\n logger: Logger,\n correlator: Correlator = default_correlator,\n patch_fn: PatchFn = es.bare_patch\n): EsOps {\n // Bake the orchestrator-level `correlator` into every `action()` call\n // so EsOps callers don't need to thread it. A per-call\n // `options.correlator` still wins — the orchestrator default fills in\n // only when the caller didn't supply one.\n //\n // The per-event patch step is selected ONCE by the builder\n // (`act-builder.ts`) — bare vs validating — and passed in here already\n // bound, so this factory stays agnostic to `validateFoldedState`. It\n // just bakes the given `patch_fn` into the load/action closures, so\n // the projection-fold engine and close-cycle callers inherit the same\n // choice without threading anything through their own signatures. The\n // default (`bare_patch`) keeps direct callers on the plain path.\n const bound_action: EsOps[\"action\"] = (\n me,\n action_name,\n target,\n payload,\n options\n ) =>\n es.action(\n me,\n action_name,\n target,\n payload,\n { correlator, ...options },\n patch_fn\n );\n const bound_load: EsOps[\"load\"] = (me, target, callback) =>\n es.load(me, target, callback, patch_fn);\n if (logger.level !== \"trace\") {\n return {\n snap: es.snap,\n load: bound_load,\n action: bound_action,\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(bound_load, (result, _me, target) => {\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 `${target.stream}${as_of_marker(target.asOf)} ${cache_marker(result.cache_hit)} ${stats}`\n )\n );\n }),\n action: traced(\n bound_action,\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 build_drain<TEvents extends Schemas>(\n logger: Logger\n): DrainOps<TEvents> {\n // Cycle-level tracing happens in `DrainController.drain()` via\n // {@link trace_cycle} — 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 run_drain_cycle) 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 uniform_lane =\n lanes.size === 1 ? streams[0]?.lane : undefined;\n const data = streams\n .map(({ stream, lane }) =>\n uniform_lane || !lane || lane === \"default\"\n ? hue(C_STREAM, stream)\n : `${hue(C_STREAM, stream)}${dim(`[${lane}]`)}`\n )\n .join(\" \");\n logger.trace(\n `${drain_caption(\"correlated\", uniform_lane)} ${data}`\n );\n }),\n };\n}\n\n/**\n * Emit one cycle-level drain trace summarizing what happened in a\n * single `run_drain_cycle` 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 trace_cycle<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 fetch_by_stream = new Map(fetched.map((f) => [f.stream, f]));\n const acked_by_stream = new Map(acked.map((a) => [a.stream, a.at]));\n const blocked_by_stream = 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 failed_by_stream = 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 = fetch_by_stream.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 = 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 acked_at = acked_by_stream.get(stream);\n const ack_part =\n acked_at !== undefined\n ? hue(C_HIT, `✓ @${acked_at}`) // ✓ + new at in lime\n : \"\";\n const failure = failed_by_stream.get(stream);\n let fail_part = \"\";\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 failed_at = failure.failed_at ?? at;\n const blocked_error = blocked_by_stream.get(stream);\n if (blocked_error !== undefined) {\n fail_part = `${hue(C_ERR, `✗ @${failed_at}/${retry}`)} ${dim(`(${blocked_error})`)}`;\n } else {\n fail_part = `${hue(C_MISS, `⚠ @${failed_at}/${retry}`)} ${dim(`(${failure.error})`)}`;\n }\n }\n let tail: string;\n if (ack_part && fail_part) tail = ` ${ack_part} ${fail_part}`;\n else if (ack_part) tail = ` ${ack_part}`;\n else if (fail_part) tail = ` ${fail_part}`;\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 projection-fold\n * @category Internal\n *\n * Fold engine behind `projection(name).of(state)` — maintains per-stream\n * folded states in a bounded in-memory cache and flushes one row per dirty\n * stream per round, so write amplification tracks the distinct-key count\n * instead of the event count.\n *\n * The flush payload deliberately has no type of its own: a state\n * projection flushes the cache layer outward — the rows ARE the\n * streams' {@link CacheEntry} values.\n *\n * Correctness discipline:\n * - The engine runs as the projection's batch handler, so the watermark\n * acks only after a fully-flushed batch — fold work is never\n * acknowledged before it is durable.\n * - On first sight of a stream the engine loads its head state through\n * the same `load()` the command path uses (cache, snapshots and all).\n * The loaded snapshot carries its own head position (`version` and the\n * global event `id`), captured atomically with `state`, so the engine\n * never pairs a stale state with a newer head id read separately from\n * the cache. Fetched events at or below the loaded id are\n * skipped, later ones fold through the state's own patch reducers.\n * - Eviction under `maxCachedStates` pressure flushes the evictee first\n * (flush-before-evict) — eviction never loses folded work.\n */\nimport type {\n BatchHandler,\n CacheEntry,\n Schema,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport type { FoldConfig } from \"./config.js\";\nimport { bare_patch, load, type PatchFn } from \"./event-sourcing.js\";\nimport { pii_strip } from \"./sensitive.js\";\n\n// The fold config schema, defaults, and resolver live in `./config.js` (the\n// single home for builder-facing config bags). This module keeps the fold\n// engine that consumes the resolved config.\n\n/**\n * A stream's in-flight fold: a mutable {@link CacheEntry} plus the\n * engine's `dirty` flag. Mutable because the hot loop updates one\n * object per stream rather than allocating per event; the required\n * frontier fields are what keep a warm-cache load from ever\n * re-applying history. Stripping `dirty` at the flush boundary yields\n * the entry — the flush payload IS the cache entry.\n */\ntype Fold<TState extends Schema> = {\n -readonly [K in keyof CacheEntry<TState>]: CacheEntry<TState>[K];\n} & { dirty: boolean };\n\n/**\n * Internal handle a fold handler exposes so the orchestrator can drop its\n * process-local state.\n *\n * A rebuild must not trust a per-Act cache: `reset` rewinds the watermark and\n * replays from the beginning, and every replayed event is at or below the\n * cached head, so the fold takes its already-folded branch and re-flushes\n * whatever it happens to hold. If that cache is stale, the rebuild writes the\n * staleness back out — the one outcome a rebuild exists to prevent. Dropping\n * the cache makes the next batch re-load head state from the store, which is\n * authoritative by definition.\n *\n * A symbol on the function keeps `BatchHandler` a plain function type; nothing\n * here is re-exported from `src/index.ts`.\n */\nexport const FOLD_RESET = Symbol(\"act.fold.reset\");\n\n/** A batch handler that owns a fold cache it can be told to drop. */\nexport type ResettableBatchHandler<TEvents extends Schemas> =\n BatchHandler<TEvents> & {\n readonly [FOLD_RESET]?: () => void;\n };\n\n/**\n * Build the batch handler that folds a state's events into per-stream rows.\n * The returned closure is long-lived (one per built projection): its cache\n * survives across drain cycles, so warm streams fold without I/O. It carries\n * a {@link FOLD_RESET} handle so a rebuild can drop that cache.\n */\nexport function make_fold_handler<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(\n me: State<TState, TEvents, TActions>,\n flush: (rows: ReadonlyArray<CacheEntry<TState>>) => Promise<void>,\n config: FoldConfig,\n patch_fn: PatchFn = bare_patch,\n sensitive_fields: (event_name: string) => readonly string[]\n): BatchHandler<TEvents> {\n // First-sight head loads must apply the SAME PII treatment as the warm\n // path (which folds `pii_strip`ped events handed in by the batch handler):\n // sensitive keys removed entirely, not gated to `[REDACTED]`. `load()`\n // folds over `me.view`, so compose the view with `pii_strip` for sensitive\n // events — otherwise an actorless head load would gate to `[REDACTED]` and\n // the projected row would differ from the warm path by cache warmth.\n // For a non-PII projection every lookup is empty, so `load_me === me`\n // behaviorally.\n const load_me: State<TState, TEvents, TActions> = {\n ...me,\n view: (raw, actor) => {\n const viewed = me.view(raw, actor);\n const fields = sensitive_fields(viewed.name as string);\n return fields.length\n ? (pii_strip(viewed as never, fields) as typeof viewed)\n : viewed;\n },\n };\n // Insertion-ordered Map as LRU: first key is the oldest. A promote is\n // delete + re-insert. Not the shared LruMap — eviction here must await\n // a flush, and a sync auto-evicting set() would drop folded work.\n const cache = new Map<string, Fold<TState>>();\n\n const row = ({ dirty: _, ...row }: Fold<TState>): CacheEntry<TState> => row;\n\n const flush_dirty = async () => {\n const rows: CacheEntry<TState>[] = [];\n const flushed: Fold<TState>[] = [];\n for (const f of cache.values())\n if (f.dirty) {\n rows.push(row(f));\n flushed.push(f);\n }\n if (rows.length === 0) return;\n await flush(rows);\n for (const f of flushed) f.dirty = false;\n };\n\n /**\n * Load a stream's head state and seat it in the cache.\n *\n * The loaded state and its head position (`version`, global `id`,\n * `patches`, `snaps`) are captured atomically inside `load()` — even on a\n * warm cache hit where `snapshot.event` is undefined. Reading the head id\n * back from the cache separately opened a TOCTOU window: a\n * concurrent `action()` committing between the two awaits pairs this\n * OLDER state with a NEWER event_id, and the frontier guard below then\n * permanently skips the intervening events. Dirty from the start: the row\n * must be written at least once.\n */\n const first_sight = async (stream: string): Promise<Fold<TState>> => {\n if (cache.size >= config.maxCachedStates) {\n // flush-before-evict: the oldest entry leaves only after its folded\n // work is durable.\n const oldest = cache.keys().next().value as string;\n const evictee = cache.get(oldest) as Fold<TState>;\n if (evictee.dirty) await flush([row(evictee)]);\n cache.delete(oldest);\n }\n const snapshot = await load(load_me, { stream }, undefined, patch_fn);\n const seated: Fold<TState> = {\n stream,\n state: snapshot.state,\n version: snapshot.version,\n event_id: snapshot.id,\n patches: snapshot.patches,\n snaps: snapshot.snaps,\n dirty: true,\n };\n cache.set(stream, seated);\n return seated;\n };\n\n const handler: ResettableBatchHandler<TEvents> = async (events) => {\n let folded_since_flush = 0;\n for (const event of events) {\n const stream = event.stream;\n let fold = cache.get(stream);\n if (fold) {\n // promote to most-recent\n cache.delete(stream);\n cache.set(stream, fold);\n } else {\n fold = await first_sight(stream);\n }\n // Fold forward only across a CONTIGUOUS version step. The\n // cache is per-Act but the subscription watermark is shared, so a\n // worker can be handed an event whose predecessors were drained by a\n // sibling worker — its cached state is then stale, and folding onto\n // it silently corrupts the row for good (the flushed row carries the\n // newest event_id, so the monotonic-upsert guard overwrites the\n // correct row with the wrong one). \"Newer than what I hold\" is not\n // the same question as \"next after what I hold\".\n //\n // A gap re-takes the first-sight path: drop the entry and load head\n // state, which is authoritative and absorbs both the missed window\n // and the version slot a `__snapshot__` consumes. The reloaded entry\n // sits at head, so this event then takes the already-folded branch.\n const contiguous = event.version === fold.version + 1;\n if (event.id > fold.event_id && !contiguous) {\n cache.delete(stream);\n fold = await first_sight(stream);\n }\n if (event.id > fold.event_id) {\n const reducer = me.patch[event.name as keyof TEvents];\n fold.state = patch_fn(\n me,\n fold.state,\n reducer(event as never, fold.state),\n event as never\n );\n fold.version = event.version;\n fold.event_id = event.id;\n fold.patches++;\n fold.dirty = true;\n } else {\n // Already folded (head load or redelivery) — mark dirty anyway\n // so replays repopulate the read table: this is what keeps a\n // rebuild at one upsert per stream instead of zero.\n fold.dirty = true;\n }\n if (++folded_since_flush >= config.flushEvery) {\n await flush_dirty();\n folded_since_flush = 0;\n }\n }\n // Flush before returning: the drain acks this batch's watermark only\n // after the handler resolves, so rows are durable before the ack.\n await flush_dirty();\n };\n\n // Dirty entries are dropped rather than flushed: a rebuild is about to\n // re-derive every row from the store, so a pending write of process-local\n // state has nothing to contribute and everything to get wrong.\n Object.defineProperty(handler, FOLD_RESET, { value: () => cache.clear() });\n return handler;\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 Query,\n Schemas,\n SettleOptions,\n} from \"../types/index.js\";\nimport type { CircuitBreaker } from \"./circuit-breaker.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 init: () => Promise<void>;\n readonly checkpoint: () => number;\n readonly correlate: (\n query: Query\n ) => Promise<{ subscribed: number; last_id: number; scanned?: boolean }>;\n readonly drain: (options: DrainOptions) => Promise<Drain<TEvents>>;\n readonly on_settled: (drain: Drain<TEvents>) => void;\n /**\n * Shared orchestrator circuit breaker. The settle loop's\n * `correlate` (subscribe + query) is a store consumer too: a successful\n * pass records `passed()`, a failed one `failed(now, err)` — feeding the\n * same breaker that paces the drain loop, which also surfaces the failure\n * to the `error` lifecycle event.\n */\n readonly breaker: CircuitBreaker;\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 * Resolves when the cycle in flight finishes, so shutdown can wait for\n * it (`stop()` cancels scheduling only). Never rejects.\n */\n private _inflight: Promise<void> | undefined;\n /**\n * A wake-up that fired while a cycle was running. The running cycle's\n * `finally` schedules one more pass with these options, so it isn't lost.\n */\n private _pending: SettleOptions | undefined = undefined;\n private readonly _deps: SettleDeps<TEvents>;\n /** Debounce window applied when the caller doesn't override via `SettleOptions.debounceMs`. */\n private readonly _default_debounce_ms: number;\n\n constructor(deps: SettleDeps<TEvents>, default_debounce_ms: number) {\n this._deps = deps;\n this._default_debounce_ms = default_debounce_ms;\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.on_settled}.\n */\n schedule(options: SettleOptions = {}): void {\n const {\n debounceMs = this._default_debounce_ms,\n correlate: correlate_query = { after: -1, limit: 100 },\n maxPasses = Infinity,\n ...drain_options\n } = options;\n\n if (this._timer) clearTimeout(this._timer);\n this._timer = setTimeout(() => {\n this._timer = undefined;\n // A cycle is already running. Record this wake-up as pending rather\n // than dropping it — the running cycle's `finally`\n // re-schedules it so armed controllers always get one more drain.\n if (this._running) {\n this._pending = options;\n return;\n }\n this._running = true;\n\n let settle_done!: () => void;\n this._inflight = new Promise<void>((done) => {\n settle_done = done;\n });\n\n (async () => {\n await this._deps.init();\n // Accumulated across every pass, so `settled` reports what the\n // SETTLE did rather than what its last pass did. The loop only\n // exits on a pass that made no progress, so emitting that pass\n // alone meant the payload was always empty — while the guide tells\n // operators to sum `drain.fetched` for throughput.\n let settled_drain: 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 after_before = this._deps.checkpoint();\n const { subscribed, last_id, scanned } = await this._deps.correlate({\n ...correlate_query,\n after: after_before,\n });\n // A scan that reached the store and came back is a real health\n // signal; a disarmed pass that returned without touching it is not.\n // Recording the latter would re-close an OPEN breaker mid-outage and\n // let the drain below hammer a store nobody has heard from — so the\n // question is asked per pass.\n if (scanned) this._deps.breaker.passed();\n const drain = await this._deps.drain(drain_options);\n settled_drain = settled_drain\n ? {\n fetched: [...settled_drain.fetched, ...drain.fetched],\n leased: [...settled_drain.leased, ...drain.leased],\n acked: [...settled_drain.acked, ...drain.acked],\n blocked: [...settled_drain.blocked, ...drain.blocked],\n }\n : drain;\n // Reading events counts as progress even when nothing reacted, so a\n // window of inert events can't stop the loop short. It still ends:\n // ids are finite.\n const made_progress =\n subscribed > 0 ||\n drain.acked.length > 0 ||\n drain.blocked.length > 0 ||\n last_id > after_before;\n if (!made_progress) break;\n }\n // `Act.emit` contains listener throws, so the store-failure catch\n // below never sees one.\n if (settled_drain) this._deps.on_settled(settled_drain);\n })()\n .catch((err) => {\n // correlate / init failed (a store op). Record on the shared\n // breaker, which logs it and surfaces the `error` event; the\n // drain loop reads the same breaker to pace itself.\n this._deps.breaker.failed(Date.now(), err);\n })\n .finally(() => {\n this._running = false;\n this._inflight = undefined;\n settle_done();\n // A wake-up arrived mid-cycle. Re-arm one more pass with its\n // options so the requested drain actually happens.\n const pending = this._pending;\n if (pending !== undefined) {\n this._pending = undefined;\n this.schedule(pending);\n }\n });\n }, debounceMs);\n }\n\n /**\n * The cycle currently in flight, or `undefined` when idle. A\n * graceful shutdown awaits this alongside the drain controllers so a\n * settle parked in `correlate` does not resume after teardown.\n */\n get inflight(): Promise<void> | undefined {\n return this._inflight;\n }\n\n /** Cancel any pending or active settle cycle. Idempotent. */\n stop(): void {\n // Drop a mid-cycle wake-up too — a stopped loop must not re-arm from\n // the running cycle's `finally`.\n this._pending = undefined;\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n","/**\n * @module reaction-builder\n * @category Internal\n *\n * Reaction dispatch — what runs inside the drain pipeline once `run_drain_cycle`\n * has fetched events for a leased stream. Two shapes:\n *\n * - per-event `handle`: walks payloads sequentially, running each handler\n * inside the reaction scope so `action()` threads `reactingTo`\n * - bulk `handle_batch`: 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 CloseSignal,\n compute_backoff_delay,\n DEFAULT_BACKOFF,\n DeferSignal,\n type Handle,\n type HandleBatch,\n type HandleResult,\n resolve_defer_at,\n} from \"../internal/index.js\";\n\nimport type { ReactionScope } from \"../scoped.js\";\nimport {\n type Actor,\n type BatchHandler,\n type Committed,\n type Lease,\n type Logger,\n NonRetryableError,\n type ReactionOptions,\n type ReactionPayload,\n type Schemas,\n} from \"../types/index.js\";\n\n/**\n * What the dispatcher needs from the orchestrator: a logger for retry and\n * error breadcrumbs, and the scope a handler runs inside.\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 /**\n * What a handler runs inside — its `IAct` facade and its triggering-event\n * context — assembled by the orchestrator. How either half works is not\n * this module's business; it receives the scope whole and calls it.\n */\n readonly reaction_scope: ReactionScope<TEvents, TActions, TActor>;\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 non_retryable = error instanceof NonRetryableError;\n const block =\n options.blockOnError &&\n (non_retryable || lease.retry >= options.maxRetries);\n if (block)\n logger.error(\n non_retryable\n ? `Blocking ${lease.stream} on non-retryable error.`\n : `Blocking ${lease.stream} after ${lease.retry} retries.`\n );\n // Every retry is paced by the reaction's backoff, or the default one;\n // terminal blocks never defer. `lease.retry` here is the just-failed\n // attempt's counter, so the delay paces the *next* attempt.\n const next_attempt_at = block\n ? undefined\n : Date.now() +\n compute_backoff_delay(lease.retry, options.backoff ?? DEFAULT_BACKOFF);\n return {\n lease,\n handled,\n acked_at: at,\n error: error.message,\n block,\n next_attempt_at,\n failed_at,\n };\n}\n\n/**\n * Builds the per-event reaction dispatcher passed to `run_drain_cycle`.\n *\n * The triggering event is installed as ambient context around each handler\n * call, so `action()` resolves it as `reactingTo`. Ambient\n * rather than bound to the `IAct` argument, so a handler that dispatches\n * through a captured `app` inherits the chain too.\n *\n * @internal\n */\nexport function build_handle<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n>(deps: ReactionDeps<TEvents, TActions, TActor>): Handle<TEvents> {\n const { logger, reaction_scope } = 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 // One event fans out to one payload per matching reaction, and the\n // watermark may only advance past an event once EVERY reaction on it\n // has handled it — acking mid-group would silently drop the remaining\n // reactions on redelivery. Track the last payload index per\n // event id (payloads arrive in event order) so `at` advances exactly\n // when a group completes; `handled` counts completed events, not\n // payloads, so a mid-group failure with no completed events is a\n // no-progress result (no ack, retry counter advances toward\n // `blockOnError` instead of resetting on every partial pass).\n const last_index_of = new Map<number, number>();\n for (let i = 0; i < payloads.length; i++)\n last_index_of.set(payloads[i].event.id, i);\n let at = lease.at;\n let handled = 0;\n\n if (lease.retry > 0)\n logger.warn(\n `Retrying ${stream}@${payloads.at(0)!.event.id} (${lease.retry}).`\n );\n\n for (let i = 0; i < payloads.length; i++) {\n const payload = payloads[i];\n const { event, handler } = payload;\n try {\n // Scoped per payload, not hoisted to the lease: the context has to\n // unwind with the handler so it never reaches the drain cycle, and\n // work a handler started without awaiting has to resume into its\n // own event's frame.\n await reaction_scope.run(event as Committed<Schemas, string>, () =>\n handler(event, stream, reaction_scope.app)\n );\n if (last_index_of.get(event.id) === i) {\n at = event.id;\n handled++;\n }\n } catch (error) {\n // A defer is not a failure: hold the triggering events pending\n // (exclude from ack via `defer`), don't bump `retry`, and re-visit\n // the stream at the carried due-time. `acked_at` is unused on\n // the defer path — drain never acks a deferred result.\n if (error instanceof DeferSignal)\n return {\n lease,\n handled,\n acked_at: at,\n defer: resolve_defer_at<TEvents>(error.when, event),\n };\n // A close request advances past the triggering event (so the\n // requesting reaction isn't counted as in-flight by the close-cycle\n // guard) and hands the target to the orchestrator's on_close.\n if (error instanceof CloseSignal)\n return {\n lease,\n handled: handled + 1,\n // Advance to the live head the handler evaluated against (when\n // provided) so the close-cycle guard sees this reaction caught up.\n acked_at: error.at ?? event.id,\n // Close the signalled stream (the autoclose reaction's aggregate,\n // which differs from its synthetic lease stream); a self-closing\n // user reaction omits it and closes its own lease stream. A\n // carried `before` makes it a windowed close (prune, not retire).\n close: {\n stream: error.stream ?? stream,\n archive: error.archive,\n before: error.before,\n },\n };\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 `run_drain_cycle`. 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 build_handle_batch<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 // One payload per (event, reaction) pair: an event with several\n // reactions on this target arrives several times in a row. The batch\n // handler gets each event once, in order — handing it the duplicates\n // made a non-idempotent batch count every event once per reaction.\n // The per-event path groups by id for the same reason.\n const events: Committed<TEvents, keyof TEvents & string>[] = [];\n const seen = new Set<number>();\n for (const p of payloads) {\n if (seen.has(p.event.id)) continue;\n seen.add(p.event.id);\n events.push(p.event as Committed<TEvents, keyof TEvents & string>);\n }\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 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 { Schema, State } from \"../types/index.js\";\nimport type { Projection } from \"./projection-builder.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 base_type_name(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()`. The same schema instance (one partial\n * re-registered through another slice) is kept as-is. Any other pair where\n * either side is not a ZodObject throws — there is no shape to extend, and\n * keeping one side would silently drop the other partial's fields.\n */\nfunction merge_schemas(\n existing: ZodType,\n incoming: ZodType,\n state_name: string\n): ZodType {\n if (existing === incoming) return existing;\n const existing_object = as_object(existing, \"existing\", state_name);\n const incoming_object = as_object(incoming, \"incoming\", state_name);\n const existing_shape = existing_object.shape as Record<string, ZodType>;\n const incoming_shape = incoming_object.shape as Record<string, ZodType>;\n for (const key of Object.keys(incoming_shape)) {\n if (key in existing_shape) {\n const existing_base = base_type_name(existing_shape[key]);\n const incoming_base = base_type_name(incoming_shape[key]);\n if (existing_base !== incoming_base) {\n throw new Error(\n `Schema conflict in \"${state_name}\": key \"${key}\" has type \"${existing_base}\" but incoming partial declares \"${incoming_base}\"`\n );\n }\n }\n }\n return existing_object.extend(incoming_shape);\n}\n\n/**\n * Narrows a partial's state schema to the ZodObject that merging needs, or\n * throws naming the state, which side failed, and what it is instead.\n */\nfunction as_object(\n schema: ZodType,\n side: \"existing\" | \"incoming\",\n state_name: string\n): ZodObject {\n if (schema instanceof ZodObject) return schema;\n throw new Error(\n `Cannot merge state schemas for \"${state_name}\": the ${side} partial's schema is a ${schema.constructor.name}, not a z.object. ` +\n `Partials of the same state are merged by extending their shapes, ` +\n `so declare every partial's state as a plain z.object({ ... }).`\n );\n}\n\n/**\n * Merges two init functions by spreading both results together.\n * Each partial only provides its own defaults.\n */\nfunction merge_inits<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 register_state(\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 merge_into_existing(state, existing, states, actions, events);\n } else {\n register_new_state(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 register_new_state(\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 * Picks the value of a field only one partial may declare. Mirrors the\n * `snap` rule: whichever partial declared it wins, and two different\n * declarations are a conflict rather than a silent first-wins.\n *\n * Without this, a spread of `existing` keeps the FIRST partial's value and\n * silently discards the incoming one, so a policy declared on a later slice\n * never runs.\n */\nfunction pick_declared<T>(\n existing: T | undefined,\n incoming: T | undefined,\n what: string,\n state_name: string\n): T | undefined {\n if (existing && incoming && existing !== incoming)\n throw new Error(`Duplicate ${what} for state \"${state_name}\"`);\n return incoming ?? existing;\n}\n\n/**\n * Resolves the `.autocloses(...)` triple. The predicate and its two day\n * fields are set together by the builder, so they move together — taking the\n * predicate from one partial and a day field from another would produce a\n * window the caller never declared.\n */\nfunction autoclose_of(\n existing: State<any, any, any>,\n state: State<any, any, any>\n): Pick<\n State<any, any, any>,\n \"autoclose\" | \"autoclose_after_days\" | \"autoclose_keep_days\"\n> {\n pick_declared(\n existing.autoclose,\n state.autoclose,\n \"autoclose policy\",\n state.name\n );\n const owner = state.autoclose ? state : existing;\n return {\n autoclose: owner.autoclose,\n autoclose_after_days: owner.autoclose_after_days,\n autoclose_keep_days: owner.autoclose_keep_days,\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 * (including the single-declaration policies, which a bare spread\n * would silently take from the first partial only)\n * 4. update action→state pointers and register new events\n */\nfunction merge_into_existing(\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 merged_patch = merge_patches(existing.patch, state.patch, state.name);\n\n // 3. Build merged state\n const merged = {\n ...existing,\n state: merge_schemas(existing.state, state.state, state.name),\n init: merge_inits(existing.init, state.init),\n events: { ...existing.events, ...state.events },\n actions: { ...existing.actions, ...state.actions },\n patch: merged_patch,\n on: { ...existing.on, ...state.on },\n given: { ...existing.given, ...state.given },\n snap: pick_declared(existing.snap, state.snap, \"snap strategy\", state.name),\n // Per-action retry policy is keyed by action name, so the two partials'\n // maps combine. Left `undefined` when neither declared one, so the\n // orchestrator's `me.options?.[action]` lookup is unchanged.\n options:\n existing.options || state.options\n ? { ...existing.options, ...state.options }\n : undefined,\n disclose: pick_declared(\n existing.disclose,\n state.disclose,\n \"disclosure predicate\",\n state.name\n ),\n archive: pick_declared(\n existing.archive,\n state.archive,\n \"archiver\",\n state.name\n ),\n // `.autocloses(...)` sets its two day fields alongside the predicate, so\n // the whole triple travels together from whichever partial declared it.\n ...autoclose_of(existing, state),\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 merge_patches(\n existing: Record<string, any>,\n incoming: Record<string, any>,\n state_name: string\n): Record<string, any> {\n const merged = { ...existing };\n for (const name of Object.keys(incoming)) {\n const existing_p = existing[name];\n const incoming_p = incoming[name];\n if (!existing_p) {\n merged[name] = incoming_p;\n continue;\n }\n const existing_is_default = existing_p._passthrough;\n const incoming_is_default = incoming_p._passthrough;\n if (\n !existing_is_default &&\n !incoming_is_default &&\n existing_p !== incoming_p\n ) {\n throw new Error(\n `Duplicate custom patch for event \"${name}\" in state \"${state_name}\"`\n );\n }\n // Keep whichever is custom; if both passthrough or existing custom, keep existing\n if (existing_is_default && !incoming_is_default) {\n merged[name] = incoming_p;\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). Reactions are keyed by `handler.name`;\n * two distinct handlers sharing a name on the same event throw rather than\n * silently overwriting. Re-merging the identical reaction object\n * is idempotent — mirrors {@link register_batch_handler}.\n */\nexport function merge_event_register(\n target: Record<string, { reactions: Map<string, unknown> }>,\n source: Record<string, { reactions: Map<string, unknown> }>\n): void {\n for (const [event_name, source_reg] of Object.entries(source)) {\n const target_reg = target[event_name];\n if (!target_reg) continue;\n for (const [name, reaction] of source_reg.reactions) {\n const existing = target_reg.reactions.get(name);\n if (existing !== undefined && existing !== reaction)\n throw new Error(\n `Duplicate reaction \"${name}\" for event \"${event_name}\". ` +\n `Reaction handlers are keyed by function name; rename one of them.`\n );\n target_reg.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 merge_projection(\n proj: Projection<any>,\n events: Record<string, any>\n): void {\n for (const event_name of Object.keys(proj.events)) {\n const proj_register = proj.events[event_name];\n const existing = events[event_name];\n if (!existing) {\n events[event_name] = {\n schema: proj_register.schema,\n reactions: new Map(proj_register.reactions),\n };\n } else {\n for (const [name, reaction] of proj_register.reactions) {\n // The `_p` rename resolves a NAME collision between two genuinely\n // different handlers. Registering the SAME reaction object again is\n // not a collision — it is the same projection reached along two\n // paths (exported from a module and embedded by two slices, or a\n // `.withProjection(p)` written twice) — and renaming it registered a\n // second copy under `name_p`, so the handler ran twice per event,\n // forever, frozen into the registry at build.\n //\n // Not the at-least-once redelivery contract: a structural duplicate,\n // deterministic on every event, with no signal anywhere. Both\n // siblings already guard on identity — `merge_event_register` throws\n // on a different handler under the same name, `register_batch_handler`\n // likewise — this one only lacked the check.\n if ([...existing.reactions.values()].includes(reaction)) continue;\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 builder-utils\n * @category Internal\n *\n * Shared builder machinery reused by both `act-builder.ts` and\n * `slice-builder.ts`. The two builders expose the same reaction-registration\n * and lane-declaration surface and differ only in the concrete builder type\n * they return (`ActBuilder` vs `SliceBuilder`) and the event register they\n * write into (`registry.events` vs the slice's `events`). This module owns the\n * one copy of that logic so the builders stay thin delegations.\n *\n * @internal\n */\n\nimport {\n assert_defer_when,\n DEFAULT_BLOCK_ON_ERROR,\n DEFAULT_MAX_RETRIES,\n type DeferSchedule,\n make_deferred,\n resolveReactionConfig,\n} from \"../internal/index.js\";\nimport { DEFAULT_LANE } from \"../ports.js\";\nimport type {\n Committed,\n EventRegister,\n LaneConfig,\n Reaction,\n ReactionHandler,\n ReactionOptions,\n ReactionResolver,\n Schemas,\n} from \"../types/index.js\";\nimport { _this_ } from \"./merge.js\";\n\n/**\n * Validate and register a drain lane: the `\"default\"` name is\n * reserved and each lane name must be unique. Mutates `lanes` in place; the\n * caller returns its own builder for chaining.\n *\n * @internal\n */\nexport function register_lane(config: LaneConfig, lanes: LaneConfig[]): void {\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}\n\n/**\n * Build the `.on(event)` step shared by both builders. Registers a reaction\n * (named-function + duplicate guards, fail-fast literal-schedule validation,\n * the default `_this_` resolver, and the `.defer` handler wrap) into\n * `events[event].reactions`, and hands back `builder` patched with `.to(...)`\n * for in-place resolver routing.\n *\n * The strict, builder-specific type is supplied by each builder's own `on`\n * signature ({@link ReactionOn}); the runtime here is builder-agnostic.\n *\n * @internal\n */\nexport function reaction_on<\n TEvents extends Schemas,\n TKey extends keyof TEvents,\n TBuilder,\n>(event: TKey, events: EventRegister<TEvents>, builder: TBuilder) {\n const register = (\n handler: ReactionHandler<TEvents, TKey>,\n options?: Partial<ReactionOptions>,\n schedule?: DeferSchedule<Committed<TEvents, TKey>>\n ) => {\n if (!handler.name)\n throw new Error(\n `Reaction handler for \"${String(event)}\" must be a named function`\n );\n if (events[event].reactions.has(handler.name))\n throw new Error(\n `Duplicate reaction \"${handler.name}\" for event \"${String(event)}\". ` +\n `Reaction handlers are keyed by function name; rename one of them.`\n );\n // Fail fast on a bad literal schedule; the function form is checked when it\n // runs (no event to resolve against at build time).\n if (schedule && typeof schedule !== \"function\") assert_defer_when(schedule);\n const reaction: Reaction<TEvents, TKey> = {\n handler: schedule ? make_deferred(handler, schedule) : handler,\n resolver: _this_,\n // Validate the whole bag at the declaration site so a bad\n // `maxRetries`/`backoff`/`blockOnError` throws ZodError at build,\n // not a NaN gate on the first retry.\n options: resolveReactionConfig({\n blockOnError: options?.blockOnError ?? DEFAULT_BLOCK_ON_ERROR,\n maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,\n backoff: options?.backoff,\n }),\n };\n // Register once with the default _this_ resolver. If `.to()` is chained\n // next, it patches the same reaction's resolver in place — no second\n // Map.set() round-trip.\n events[event].reactions.set(handler.name, reaction);\n return Object.assign(builder as object, {\n to(resolver: ReactionResolver<TEvents, TKey> | string) {\n reaction.resolver =\n typeof resolver === \"string\" ? { target: resolver } : resolver;\n return builder;\n },\n });\n };\n return {\n do: (\n handler: ReactionHandler<TEvents, TKey>,\n options?: Partial<ReactionOptions>\n ) => register(handler, options),\n defer: (schedule: DeferSchedule<Committed<TEvents, TKey>>) => ({\n do: (\n handler: ReactionHandler<TEvents, TKey>,\n options?: Partial<ReactionOptions>\n ) => register(handler, options, schedule),\n }),\n };\n}\n","/**\n * @module event-builder\n * @category Internal\n *\n * Everything `act().build()` derives from the registered events.\n *\n * This is the build-time half of the event lifecycle. `internal/sensitive.ts`\n * owns the other two halves — the `sensitive(...)` marker itself, and the\n * runtime transforms (`pii_gate`, `pii_strip`, `pii_split`) that a reader is\n * composed from. Nothing here runs per event at runtime; everything here runs\n * once, at build, and hands the orchestrator a prebuilt function.\n *\n * Three things are derived, all in ONE walk over the registered events:\n *\n * - **validation** — a reaction may not target a lane nobody declared, nor a\n * target a projection already serves. Both checks skip dynamic resolvers,\n * because a `.to(fn)` target is unknowable until an event arrives.\n * - **resolution** — each event's schema is read once into {@link EventTags}:\n * which fields are sensitive, and how to revive the dates in a stored\n * payload. Working out where the dates are is a Zod concern, so it lives in\n * `internal/date-reviver.ts`; this module composes what that returns.\n * - **composition** — the per-surface readers, each a single {@link EventGate}\n * that types the payload and applies disclosure in one call.\n *\n * Deliberately NOT here: deprecation. `Foo` is deprecated only because\n * `Foo_v2` exists beside it, so it is derived from event *names across a whole\n * state* rather than from one event's schema — and it governs *emitting* (a\n * static `.emit()` throws at build), not reading. Replay of a deprecated event\n * stays silent by design.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport { date_reviver_schema } from \"../internal/index.js\";\nimport {\n type EventGate,\n IDENTITY_GATE,\n make_gate,\n pii_schemas,\n pii_split,\n pii_strip,\n} from \"../internal/sensitive.js\";\nimport { DEFAULT_LANE, SNAP_EVENT } from \"../ports.js\";\nimport type { Actor, LaneConfig, Registry } from \"../types/index.js\";\n\n/** What one pass over an event's schema resolves. @internal */\nexport type EventTags = {\n /** Keys marked `sensitive(...)`, top level (and across union variants). */\n readonly sensitive: readonly string[];\n /**\n * Revives the dates in a stored `data` payload, or `undefined` when the\n * schema declares none.\n */\n readonly date_reviver: ((data: unknown) => unknown) | undefined;\n /**\n * Revives the dates in a stored `pii` sidecar, or `undefined` when no\n * sensitive field is a date.\n */\n readonly pii_date_reviver: ((pii: unknown) => unknown) | undefined;\n};\n\n/**\n * Resolve an event's schema in a single pass.\n *\n * Sensitive markers are read at the top level only — the documented carve-out\n * (`sensitive.ts`), since the write path splits whole top-level keys. A union\n * event has no top-level shape, so its variants are walked and unioned: a key\n * sensitive in any variant must be split, because the stored payload could be\n * that variant.\n *\n * @internal\n */\nexport function event_tags(schema: z.ZodType): EventTags {\n // Which fields are sensitive is `sensitive.ts`'s question and where the\n // dates are is `date-reviver.ts`'s; this composes the two answers. The\n // sidecar holds the split-out fields alone, so a date among them needs its\n // own reviver — without it a disclosed `sensitive(z.date())` arrives as text\n // beside a plain sibling that is a Date.\n const pii = pii_schemas(schema);\n const pii_dates: Record<string, z.ZodType> = {};\n for (const [key, field] of Object.entries(pii)) {\n const dates = date_reviver_schema(field);\n if (dates) pii_dates[key] = dates.optional();\n }\n\n const data_reviver_schema = date_reviver_schema(schema);\n // Reviving must never reject. A stored payload can disagree with the current\n // declaration in ways this schema deliberately does not describe, and handing\n // back what is stored beats refusing to read it.\n const revive = (schema: z.ZodType) => (data: unknown) => {\n const revived = schema.safeParse(data);\n return revived.success ? revived.data : data;\n };\n const dated_pii = Object.keys(pii_dates).length > 0;\n return {\n sensitive: Object.keys(pii),\n date_reviver: data_reviver_schema && revive(data_reviver_schema),\n pii_date_reviver: dated_pii ? revive(z.looseObject(pii_dates)) : undefined,\n };\n}\n\n/**\n * What the reader should do about sensitive fields.\n *\n * - `redact` — substitute `[REDACTED]` unless `disclose` authorizes the actor,\n * and drop the `pii` sidecar. The read surfaces (`query`, `query_array`,\n * `load`).\n * - `strip` — remove the keys entirely. Reaction and projection handlers,\n * which never see PII by framework rule, and shouldn't structurally observe\n * the keys either.\n *\n * @internal\n */\nexport type Disclosure = \"redact\" | \"strip\";\n\n/**\n * Compose one event's typing and disclosure into a single gate.\n *\n * Returns `undefined` when the event needs neither, so the caller can fall\n * back to the shared {@link IDENTITY_GATE} and the common path allocates\n * nothing.\n *\n * @internal\n */\nfunction make_event_reader(\n tags: EventTags,\n disclosure: Disclosure,\n predicate: ((event: never, actor: Actor) => boolean) | null = null\n): EventGate | undefined {\n const { sensitive, date_reviver, pii_date_reviver } = tags;\n if (!date_reviver && sensitive.length === 0) return undefined;\n\n const gate: EventGate =\n sensitive.length === 0\n ? IDENTITY_GATE\n : disclosure === \"strip\"\n ? (((event) => pii_strip(event as never, sensitive)) as EventGate)\n : make_gate(sensitive, predicate as never);\n\n if (!date_reviver) return gate;\n\n // The sidecar is only worth reviving for a reader that can be shown it.\n // A `strip` reader drops `pii` outright, and a redacting one discloses only\n // to an actor a predicate approves — so no actor and no predicate means the\n // values are on their way to REDACTED whatever they hold. The predicate\n // itself stays uncalled here: the gate owns that decision and calling it\n // twice would run a caller's code twice.\n const revive_pii =\n disclosure === \"redact\" && predicate ? pii_date_reviver : undefined;\n\n // Revive before disclosing: the gate copies, so reviving afterwards would\n // leave the consumer's value a string — and it substitutes REDACTED and\n // SHREDDED, which are not dates.\n return ((event, actor) => {\n const pii = (event as { pii?: unknown }).pii;\n return gate(\n {\n ...event,\n data: date_reviver(event.data),\n ...(revive_pii && actor && pii != null ? { pii: revive_pii(pii) } : {}),\n } as never,\n actor\n );\n }) as EventGate;\n}\n\n/**\n * Exactly what the registry serves, keyed by event name — no intermediates.\n *\n * The per-state `view` is installed directly on each state rather than\n * returned: it is event-derived wiring like the rest, and handing it back for\n * the caller to install would put the composition back where it came from.\n *\n * @internal\n */\nexport type BuiltEvents = {\n /** Backs `registry.sensitive_fields`. */\n readonly sensitive: Map<string, readonly string[]>;\n /** Backs `registry.query_gate` — the actor-less read surfaces. */\n readonly query_readers: Map<string, EventGate>;\n /** Readers for handlers — sensitive keys removed, payload typed. */\n readonly handler_readers: Map<string, EventGate>;\n};\n\n/** What validation needs to know about the projections already registered. */\nexport type TargetOwners = {\n readonly batch_handlers: ReadonlyMap<string, unknown>;\n readonly fold_targets: ReadonlySet<string>;\n /** A projection's own reactions legitimately target it — excluded by identity. */\n readonly projection_reactions: ReadonlySet<unknown>;\n};\n\ntype EventEntry = {\n schema: import(\"zod\").ZodType;\n reactions: Map<string, { handler: any; resolver: unknown }>;\n};\n\n/**\n * Validate every static reaction and wire every event, in a single walk.\n *\n * Ownership conflicts throw as they are found; lane violations are collected\n * and thrown afterwards. That ordering is deliberate — it preserves the\n * precedence the two separate passes had, where the ownership guard ran to\n * completion before lane references were checked, so a config violating both\n * reports the same error it always did.\n *\n * @internal\n */\nexport function build_events(\n registry: Registry<any, any, any>,\n states: ReadonlyMap<string, any>,\n lanes: ReadonlyArray<LaneConfig>,\n owners: TargetOwners\n): BuiltEvents {\n const declared = new Set<string>([DEFAULT_LANE, ...lanes.map((l) => l.name)]);\n const lane_errors: string[] = [];\n\n const tags = new Map<string, EventTags>();\n const sensitive = new Map<string, readonly string[]>();\n const query_readers = new Map<string, EventGate>();\n const handler_readers = new Map<string, EventGate>();\n\n for (const [event_name, def] of Object.entries(\n registry.events as Record<string, EventEntry>\n )) {\n for (const [handler_name, reaction] of def.reactions) {\n // A build-time guard can only see a static target: a `.to(fn)` target\n // is unknowable until an event arrives.\n if (typeof reaction.resolver === \"function\") continue;\n const resolver = reaction.resolver as { target: string; lane?: string };\n\n const claimed =\n owners.batch_handlers.has(resolver.target) ||\n owners.fold_targets.has(resolver.target);\n if (claimed && !owners.projection_reactions.has(reaction))\n throw new Error(\n `Reaction on target \"${resolver.target}\" conflicts with the projection that already serves it — a target is served by one batch handler or one state projection, and a reaction to it would never run`\n );\n\n if (resolver.lane && !declared.has(resolver.lane))\n lane_errors.push(\n `Reaction \"${handler_name}\" on \"${event_name}\" targets undeclared lane \"${resolver.lane}\". ` +\n `Declared lanes: ${[...declared].map((l) => `\"${l}\"`).join(\", \")}. ` +\n `Add \\`.withLane({ name: \"${resolver.lane}\", ... })\\` to act() or correct the .to() declaration.`\n );\n }\n\n // One resolution of the declared schema yields both facts a reader is\n // built from: which fields are sensitive, and how to type the payload.\n const event = event_tags(def.schema);\n tags.set(event_name, event);\n if (event.sensitive.length > 0) sensitive.set(event_name, event.sensitive);\n\n // An event needing neither typing nor redaction produces no reader and\n // falls back to the shared IDENTITY_GATE — zero per-event cost.\n const query_reader = make_event_reader(event, \"redact\", null);\n if (query_reader) query_readers.set(event_name, query_reader);\n\n // Handlers never see PII by framework rule, and shouldn't observe the\n // keys structurally either — so `strip`, not `redact`.\n const handler_reader = make_event_reader(event, \"strip\");\n if (handler_reader) {\n handler_readers.set(event_name, handler_reader);\n for (const [name, reaction] of def.reactions) {\n const inner = reaction.handler;\n const wrapped = (evt: any, stream: string, app: any) =>\n inner(handler_reader(evt), stream, app);\n // Preserve handler.name — build_handle asserts on named functions.\n Object.defineProperty(wrapped, \"name\", { value: inner.name });\n reaction.handler = wrapped;\n def.reactions.set(name, reaction as never);\n }\n }\n }\n\n if (lane_errors.length > 0) throw new Error(lane_errors[0]);\n\n // Per-state wiring, all of it derived from the same event resolution: the\n // read view, the write split, and the guard that refuses to combine the two\n // things that cannot coexist.\n for (const state of states.values()) {\n const state_fields = new Map<string, readonly string[]>();\n for (const event_name of Object.keys(state.events)) {\n const fields = sensitive.get(event_name);\n if (fields) state_fields.set(event_name, fields);\n }\n\n if (state_fields.size > 0) {\n // Snapshots write derived state into `__snapshot__.data`, which\n // `forget_pii` cannot reach. Reject the combination at build so the\n // misconfiguration surfaces in dev/CI, not as a silent leak past the\n // GDPR boundary months later.\n if (state.snap)\n throw new Error(\n `State \"${state.name}\" cannot snapshot — events {${[...state_fields.keys()].join(\", \")}} carry sensitive fields. ` +\n \"Snapshots write derived state into __snapshot__.data, which forget_pii cannot reach. \" +\n \"Remove .snap() or remove sensitive(...) markers.\"\n );\n state.pii_aware = true;\n // The write half: split declared fields into the `pii` sidecar on the\n // way to `Store.commit`.\n state.message = (validated: { name: string }) => {\n const fields = state_fields.get(validated.name);\n return fields ? pii_split(validated as never, fields) : validated;\n };\n }\n\n // The read half. A state's disclosure predicate is an input to the\n // reader, not a second gate layered over it. A `__snapshot__` carries\n // folded STATE rather than event data, so its typing comes from the state\n // schema — without that a restart from a snapshot loses every `z.date()`\n // the state holds.\n const readers = new Map<string, EventGate>();\n for (const event_name of Object.keys(state.events)) {\n const event = tags.get(event_name);\n const reader =\n event && make_event_reader(event, \"redact\", state.disclose ?? null);\n if (reader) readers.set(event_name, reader);\n }\n const snap = make_event_reader(event_tags(state.state), \"redact\", null);\n if (snap) readers.set(SNAP_EVENT, snap);\n if (readers.size === 0) continue;\n state.view = (event: { name: string }, actor: Actor) =>\n (readers.get(event.name) ?? IDENTITY_GATE)(event as never, actor);\n }\n\n return { sensitive, query_readers, handler_readers };\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 bare_patch,\n current_version_of,\n deprecated_event_names,\n type EventGate,\n FOLD_RESET,\n IDENTITY_GATE,\n make_fold_handler,\n type PatchFn,\n type ResettableBatchHandler,\n resolveActConfig,\n resolveLaneConfig,\n synthesize_autoclose_reactions,\n validating_patch,\n} from \"../internal/index.js\";\nimport { type DEFAULT_LANE, log } from \"../ports.js\";\nimport { current_autoclose_window } from \"../scoped.js\";\nimport type {\n Actor,\n BatchHandler,\n LaneConfig,\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport type { BuilderBase } from \"./builder-base.js\";\nimport { reaction_on, register_lane } from \"./builder-utils.js\";\nimport { build_events } from \"./event-builder.js\";\nimport {\n merge_event_register,\n merge_projection,\n register_state,\n} from \"./merge.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 already serves it. Folds (`.of(...)`) have no\n * batch handler; their side of the check is in `build()`.\n */\nfunction register_batch_handler(\n proj: Projection<any>,\n batch_handlers: Map<string, BatchHandler<any>>\n): void {\n if (!proj.batchHandler || !proj.target) return;\n const existing = batch_handlers.get(proj.target);\n if (existing && existing !== proj.batchHandler) {\n throw new Error(\n `Duplicate projection target \"${proj.target}\" — a target is served by one batch handler or one state projection, never both`\n );\n }\n batch_handlers.set(proj.target, proj.batchHandler);\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, ...})`\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. 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 interface 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> extends BuilderBase<\n ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>,\n TEvents,\n TActions,\n TActor,\n TLanes\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 * 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. 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 * 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\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 // Caches behind the registry's derived lookups, populated on the first\n // `.build()`. Each event schema is walked once.\n const _sf = new Map<string, readonly string[]>();\n // Prebuilt handler readers — sensitive keys removed, payload typed. Absent\n // when the event needs neither.\n const _hr = new Map<string, EventGate>();\n // Prebuilt default-deny read gates, one per sensitive event. Non-sensitive\n // events are absent → `query_gate` falls back to the shared IDENTITY_GATE.\n const _qg = new Map<string, EventGate>();\n const _dp = new Map<string, (event: any, actor: Actor) => boolean>();\n const _de = new Map<string, ReadonlySet<string>>();\n const _ac = new Map<\n string,\n (stream: string, head: any, count: number) => boolean\n >();\n const _aa = new Map<string, (stream: string, head: any) => Promise<void>>();\n const EMPTY_DEPRECATED: ReadonlySet<string> = new Set();\n const registry: Registry<TSchemaReg, TEvents, TActions> = {\n actions: {} as Registry<TSchemaReg, TEvents, TActions>[\"actions\"],\n events: {} as Registry<TSchemaReg, TEvents, TActions>[\"events\"],\n sensitive_fields: (event_name) => _sf.get(event_name) ?? [],\n query_gate: (event_name) => _qg.get(event_name) ?? IDENTITY_GATE,\n disclosure_predicate: (state_name) => _dp.get(state_name) ?? null,\n deprecated_events: (state_name) => _de.get(state_name) ?? EMPTY_DEPRECATED,\n autoclose_policy: (state_name) => _ac.get(state_name) ?? null,\n autoclose_archiver: (state_name) => _aa.get(state_name) ?? null,\n };\n const pending_projections: Projection<any>[] = [];\n /**\n * Reactions contributed by projections, recorded at registration. Only\n * these may target a projection's stream; anything else is a collision.\n */\n const projection_reactions = new Set<unknown>();\n const record_projection_reactions = (proj: Projection<any>) => {\n // Only a projection that SERVES its target (a batch handler or a fold)\n // owns it. A per-event projection naming the same target is just another\n // claimant: exempting it let it share a fold's or batch's target, where\n // its handler never ran and the fold wrote foreign rows.\n if (!proj.batchHandler && !proj.fold) return;\n for (const register of Object.values(\n proj.events as Record<string, { reactions: Map<string, unknown> }>\n ))\n for (const reaction of register.reactions.values())\n projection_reactions.add(reaction);\n };\n const fold_projections: Projection<any>[] = [];\n const batch_handlers = new Map<string, BatchHandler<any>>();\n const add_projection = (proj: Projection<any>) => {\n record_projection_reactions(proj);\n merge_projection(proj, registry.events as Record<string, any>);\n register_batch_handler(proj, batch_handlers);\n if (proj.fold) fold_projections.push(proj);\n };\n // Validated fold-projection ingredients, resolved once on the first\n // build. The HANDLERS themselves are built per `.build()` — see\n // `make_batch_handlers` — because a fold handler owns a mutable\n // per-stream cache that must never be shared across Acts.\n const fold_specs: {\n target: string;\n /** Identity of the registering projection, so a repeat registration of\n * the same object is recognized as one claim rather than two. */\n projection: Projection<any>;\n merged: any;\n flush: any;\n config: any;\n }[] = [];\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 /**\n * Wraps a batch handler so it receives events in handler form — payload\n * typed from the declared schema, sensitive keys removed — the same reader\n * `event-builder` gives per-event handlers. Resolved lazily at dispatch, by\n * when the events pass has populated it.\n */\n const read_wrap = (original: BatchHandler<any>): BatchHandler<any> => {\n const wrapped = async (events: readonly any[], stream: string) => {\n // The same prebuilt reader the per-event handlers get: typed payload,\n // sensitive keys removed. Absent → the event passes through untouched.\n const read = events.map((e) => _hr.get(e.name as string)?.(e) ?? e);\n return original(read as never, stream);\n };\n // Carry the fold's cache-reset handle through the wrapper. The\n // orchestrator only ever sees what this map holds, so a handle left on\n // the inner handler is a handle nobody can reach.\n const reset = (original as ResettableBatchHandler<any>)[FOLD_RESET];\n if (reset) Object.defineProperty(wrapped, FOLD_RESET, { value: reset });\n return wrapped;\n };\n\n /**\n * Per-Act batch-handler map. Stateless handlers are shared; fold\n * handlers own a per-stream cache, so each `.build()` gets fresh ones\n * (and its own `patch_fn`).\n */\n const make_batch_handlers = (patch_fn: PatchFn) => {\n const handlers = new Map(batch_handlers);\n for (const spec of fold_specs) {\n handlers.set(\n spec.target,\n read_wrap(\n make_fold_handler(\n spec.merged,\n spec.flush,\n spec.config,\n patch_fn,\n // Head loads strip sensitive keys like the warm path.\n registry.sensitive_fields\n )\n ) as never\n );\n }\n return handlers;\n };\n\n // Versioned events: per state, the highest `_v<n>` is current and lower\n // ones are deprecated (`registry.deprecated_events`). A static\n // `.emit(\"X\")` of a deprecated event throws; a one-line advisory lists\n // the legacy events kept for replay.\n const finalize_deprecations = () => {\n const deprecation_summary: Array<{\n state_name: string;\n deprecated: string;\n current: string;\n }> = [];\n for (const state of states.values()) {\n const event_names = Object.keys(state.events);\n const deprecated = deprecated_event_names(event_names);\n if (deprecated.size === 0) continue;\n _de.set(state.name, deprecated);\n for (const name of deprecated) {\n // `current_version_of` 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 = current_version_of(name, event_names) as string;\n deprecation_summary.push({\n state_name: state.name,\n deprecated: name,\n current,\n });\n }\n for (const [action_name, handler] of Object.entries(state.on)) {\n const static_target = (handler as { _static_emit?: string } | undefined)\n ?._static_emit;\n if (static_target && deprecated.has(static_target)) {\n const current = current_version_of(static_target, event_names);\n throw new Error(\n `Action \"${action_name}\" in state \"${state.name}\" emits deprecated event \"${static_target}\". ` +\n `A newer version exists: \"${current}\". Update the .emit() call ` +\n `to target the current version. The reducer (.patch) for ` +\n `\"${static_target}\" stays as-is — historical events still need it.`\n );\n }\n }\n }\n if (deprecation_summary.length > 0) {\n const list = deprecation_summary\n .map(\n (d) =>\n `\"${d.deprecated}\" (current: \"${d.current}\", state: \"${d.state_name}\")`\n )\n .join(\", \");\n log().info(\n `Act registered ${deprecation_summary.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 /**\n * Registration is closed once `build()` has classified the registry: every\n * mutating method throws a clear error after it. `build()` itself stays\n * callable repeatedly, since the multi-tenant pattern calls\n * `.build({scoped})` per tenant and registers nothing.\n */\n const closed = (method: string): never => {\n throw new Error(\n `act().${method}() was called after build(); the registry is already classified. Register everything before build() — build() itself may be called repeatedly (e.g. once per tenant with ActOptions.scoped).`\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 if (_built) closed(\"withState\");\n register_state(state, states, registry.actions, registry.events);\n return builder as never;\n },\n withSlice: (input) => {\n if (_built) closed(\"withSlice\");\n for (const s of input.states.values()) {\n register_state(s, states, registry.actions, registry.events);\n }\n merge_event_register(registry.events, input.events);\n pending_projections.push(...input.projections);\n for (const slice_lane of input.lanes) {\n const existing = lanes.find((l) => l.name === slice_lane.name);\n if (!existing) {\n lanes.push(slice_lane);\n continue;\n }\n if (\n existing.leaseMillis !== slice_lane.leaseMillis ||\n existing.streamLimit !== slice_lane.streamLimit ||\n existing.cycleMs !== slice_lane.cycleMs\n ) {\n throw new Error(\n `Lane \"${slice_lane.name}\" was already declared with a different config`\n );\n }\n }\n return builder as never;\n },\n withProjection: (proj) => {\n if (_built) closed(\"withProjection\");\n add_projection(proj as Projection<any>);\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 (_built) closed(\"withLane\");\n // Validate the lane bag at declaration (a bad leaseMillis/streamLimit\n // throws ZodError at build, not on the first cycle).\n register_lane(resolveLaneConfig(config), lanes);\n return builder as never;\n },\n on: <TKey extends keyof TEvents>(event: TKey) => {\n if (_built) closed(\"on\");\n return reaction_on(event, registry.events, builder) as never;\n },\n build: (options?: ActOptions) => {\n // Validate the top-level scalar knobs at build (the nested autoclose /\n // circuitBreaker bags are validated by their own resolvers). A bad\n // maxSubscribedStreams / settleDebounceMs throws ZodError here.\n resolveActConfig(options);\n // The one place the patch step is chosen; folds and `build_es` share\n // it.\n const patch_fn: PatchFn =\n options?.validateFoldedState === true ? validating_patch : bare_patch;\n // Finalize once: repeated builds (per tenant) share the registry.\n if (!_built) {\n for (const proj of pending_projections) add_projection(proj);\n // State projections fold the registry-merged FULL state — the\n // builder only recorded intent. Resolve here, where every\n // partial has merged, and refuse silently-partial folds: the\n // projection's register must cover the state's whole register.\n // The `patch_fn` selected once at the top of `build()` feeds the\n // fold handlers, matching the command/load paths.\n for (const proj of fold_projections) {\n const fold = proj.fold!;\n const merged = states.get(fold.name);\n if (!merged)\n throw new Error(\n `State projection \"${proj.target}\" folds \"${fold.name}\", which is not registered — add it via withState/withSlice before build()`\n );\n const missing = Object.keys(merged.events).filter(\n (event_name) => !(event_name in proj.events)\n );\n if (missing.length > 0)\n throw new Error(\n `State projection \"${proj.target}\" of \"${fold.name}\" is missing events ${missing.join(\", \")} — pass every partial of the state to .of()`\n );\n // A target is claimed once, by a batch handler or a fold; two\n // different projections on one target throw. The same projection\n // registered twice is fine.\n const claimed = fold_specs.find((s) => s.target === proj.target);\n if (claimed?.projection === proj) continue;\n if (batch_handlers.has(proj.target!) || claimed)\n throw new Error(\n `Duplicate projection target \"${proj.target}\" — a target is served by one batch handler or one state projection, never both`\n );\n // Record the validated ingredients only. The handler is\n // constructed per `.build()` (see `make_batch_handlers`) — it\n // owns a mutable per-stream fold cache, so one shared instance\n // would leak folded rows between Acts built from this builder.\n fold_specs.push({\n target: proj.target!,\n projection: proj,\n merged,\n flush: fold.flush,\n config: fold.config,\n });\n }\n // An ordinary reaction on a projection's target would never run and\n // would feed the fold another aggregate, so `build_events` rejects\n // it (the projection's own reactions are exempt).\n //\n // One walk over the registered events: validate every static\n // reaction, resolve each schema once, and compose the per-surface\n // readers from it. See `event-builder.ts`.\n const built = build_events(registry, states, lanes, {\n batch_handlers,\n fold_targets: new Set(fold_specs.map((f) => f.target)),\n projection_reactions,\n });\n for (const [name, fields] of built.sensitive) _sf.set(name, fields);\n for (const [name, gate] of built.query_readers) _qg.set(name, gate);\n for (const [name, gate] of built.handler_readers) _hr.set(name, gate);\n finalize_deprecations();\n\n for (const state of states.values()) {\n if (state.disclose) _dp.set(state.name, state.disclose);\n if (state.autoclose) _ac.set(state.name, state.autoclose);\n if (state.archive) _aa.set(state.name, state.archive);\n }\n for (const [target, original] of batch_handlers) {\n batch_handlers.set(target, read_wrap(original) as never);\n }\n // Synthesize the autoclose reactions last, once the registry is\n // fully merged — their dynamic resolvers must be present before\n // the orchestrator classifies the registry.\n //\n // Nothing per-Act is captured: repeat builds share these reactions,\n // and the off-hours window comes from the running Act's frame.\n synthesize_autoclose_reactions(\n registry,\n states,\n current_autoclose_window\n );\n // Freeze the registry shape; the `_built` latch on each method stops\n // later registration (freezing doesn't seal the reaction `Map`s).\n Object.freeze(registry.actions);\n Object.freeze(registry.events);\n Object.freeze(registry);\n _built = true;\n }\n\n return new Act<TSchemaReg, TEvents, TActions, TStateMap, TActor>(\n registry,\n states,\n make_batch_handlers(patch_fn),\n options,\n lanes,\n patch_fn\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 {\n DEFAULT_BLOCK_ON_ERROR,\n DEFAULT_MAX_RETRIES,\n type FoldConfig,\n resolveFoldConfig,\n} from \"../internal/index.js\";\nimport type {\n BatchHandler,\n CacheEntry,\n Committed,\n EventRegister,\n FoldOptions,\n Reaction,\n ReactionResolver,\n Schema,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport { _this_ } from \"./merge.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 * State-fold spec from `.of()`. The builder only records intent — the\n * orchestrator resolves the REGISTRY-MERGED full state at\n * `act().build()` and synthesizes the batch handler there, so the\n * fold always covers every reducer of the state, including partials\n * merged by slices the projection never saw.\n * @internal\n */\n readonly fold?: {\n readonly name: string;\n readonly flush: (rows: ReadonlyArray<CacheEntry<any>>) => Promise<void>;\n readonly config: FoldConfig;\n };\n};\n\n/**\n * The `.of()` continuation: state projections flush the cache layer\n * outward — the rows ARE the streams' {@link CacheEntry} values, one\n * per dirty stream per flush round. Must be an idempotent upsert keyed\n * on `stream` (guard with `event_id` for order safety when a rebuild\n * races a live worker).\n */\ntype FoldFlush<TState extends Schema, TE extends Schemas> = {\n flush: (\n handler: (rows: ReadonlyArray<CacheEntry<TState>>) => Promise<void>\n ) => {\n build: () => Projection<TE>;\n };\n};\n\n/**\n * `.of()` accepts the partials of ONE state (same name, enforced at the\n * type level via `TName`) purely for typing and event registration —\n * the fold itself always runs on the registry-merged full state,\n * resolved at `act().build()`. Passing every partial is required: the\n * orchestrator validates completeness at build and throws on missing\n * events.\n */\ntype OfSignatures = {\n <\n TS1 extends Schema,\n TE1 extends Schemas,\n TA1 extends Schemas,\n TN extends string,\n >(\n s1: State<TS1, TE1, TA1, TN>,\n options?: FoldOptions\n ): FoldFlush<TS1, TE1>;\n <\n TS1 extends Schema,\n TE1 extends Schemas,\n TA1 extends Schemas,\n TS2 extends Schema,\n TE2 extends Schemas,\n TA2 extends Schemas,\n TN extends string,\n >(\n s1: State<TS1, TE1, TA1, TN>,\n s2: State<TS2, TE2, TA2, TN>,\n options?: FoldOptions\n ): FoldFlush<TS1 & TS2, TE1 & TE2>;\n <\n TS1 extends Schema,\n TE1 extends Schemas,\n TA1 extends Schemas,\n TS2 extends Schema,\n TE2 extends Schemas,\n TA2 extends Schemas,\n TS3 extends Schema,\n TE3 extends Schemas,\n TA3 extends Schemas,\n TN extends string,\n >(\n s1: State<TS1, TE1, TA1, TN>,\n s2: State<TS2, TE2, TA2, TN>,\n s3: State<TS3, TE3, TA3, TN>,\n options?: FoldOptions\n ): FoldFlush<TS1 & TS2 & TS3, TE1 & TE2 & TE3>;\n <\n TS1 extends Schema,\n TE1 extends Schemas,\n TA1 extends Schemas,\n TS2 extends Schema,\n TE2 extends Schemas,\n TA2 extends Schemas,\n TS3 extends Schema,\n TE3 extends Schemas,\n TA3 extends Schemas,\n TS4 extends Schema,\n TE4 extends Schemas,\n TA4 extends Schemas,\n TN extends string,\n >(\n s1: State<TS1, TE1, TA1, TN>,\n s2: State<TS2, TE2, TA2, TN>,\n s3: State<TS3, TE3, TA3, TN>,\n s4: State<TS4, TE4, TA4, TN>,\n options?: FoldOptions\n ): FoldFlush<TS1 & TS2 & TS3 & TS4, TE1 & TE2 & TE3 & TE4>;\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, true> & {\n to: (\n resolver: ReactionResolver<TEvents & { [P in TKey]: TData }, TKey> | string\n ) => ProjectionBuilder<TEvents & { [P in TKey]: TData }, TTarget, true>;\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 THasHandlers extends boolean = false,\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 } & (THasHandlers extends false\n ? {\n /**\n * Declares a state projection: fold every event of the given\n * state through its own reducers and flush one row per stream —\n * the queryable list of the aggregates themselves.\n *\n * The state is the filter: the projection consumes exactly the\n * state's event register, so in a multi-state app only that\n * state's streams are folded — and every event of a folded\n * stream reaches the reducer. Write amplification tracks the\n * distinct stream count, not the event count; `app.reset`\n * rebuilds in O(streams) upserts.\n *\n * The fluent chain enforces the shape: `.of()` is only offered\n * before any `.on()` handler, and narrows to `.flush()` +\n * `.build()` — a projection either folds a state or declares\n * handlers, never both.\n */\n of: OfSignatures;\n }\n : // eslint-disable-next-line @typescript-eslint/no-empty-object-type\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 default_resolver: { 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,\n resolver: default_resolver ?? _this_,\n options: {\n blockOnError: DEFAULT_BLOCK_ON_ERROR,\n maxRetries: DEFAULT_MAX_RETRIES,\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 if (register.reactions.has(handler.name))\n throw new Error(\n `Duplicate projection handler \"${handler.name}\" for event \"${event}\". ` +\n `Projection handlers are keyed by function name; rename one of them.`\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() and .of() 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 of: (...args: unknown[]) => {\n if (Object.keys(events).length > 0)\n throw new Error(\n `Projection \"${target}\" mixes .of() with .on() handlers — a projection either folds a state or declares handlers, never both`\n );\n // Trailing options bag is the only non-State argument.\n const is_state = (a: unknown): a is State<Schema, Schemas, Schemas> =>\n !!a &&\n typeof (a as State<Schema, Schemas, Schemas>).init === \"function\";\n const partials = args.filter(is_state);\n const options = (args.find((a) => !is_state(a)) ?? {}) as FoldOptions;\n if (partials.length === 0)\n throw new Error(`Projection \"${target}\" .of() requires a state`);\n const name = partials[0].name;\n for (const partial of partials)\n if (partial.name !== name)\n throw new Error(\n `Projection \"${target}\" .of() partials must share one state name — got \"${name}\" and \"${partial.name}\"`\n );\n // Misconfiguration surfaces here, at startup — not on first drain.\n const config = resolveFoldConfig(options);\n // The partials' own schema instances register the events, so the\n // same-name declarations in slices pass the identity check in\n // merge_event_register. The named no-op reaction routes fetches\n // to this target; dispatch always goes through the batch handler\n // the orchestrator synthesizes from the registry-merged state.\n const fold_events = {} as EventRegister<Schemas>;\n for (const partial of partials)\n for (const [event_name, schema] of Object.entries(partial.events)) {\n if (event_name in fold_events) continue;\n const noop = {\n [`${target}_fold`]: async () => {},\n }[`${target}_fold`] as (\n event: Committed<Schemas, string>,\n stream: string\n ) => Promise<void>;\n (fold_events as Record<string, unknown>)[event_name] = {\n schema,\n reactions: new Map([\n [\n `${target}_fold`,\n {\n handler: noop,\n resolver: { target },\n options: {\n blockOnError: DEFAULT_BLOCK_ON_ERROR,\n maxRetries: DEFAULT_MAX_RETRIES,\n },\n },\n ],\n ]),\n };\n }\n return {\n flush: (\n handler: (rows: ReadonlyArray<CacheEntry<Schema>>) => Promise<void>\n ) => ({\n build: () => ({\n _tag: \"Projection\" as const,\n events: fold_events,\n target,\n fold: { name, flush: handler, config },\n }),\n }),\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 */\n\nimport { resolveLaneConfig } from \"../internal/index.js\";\nimport type { DEFAULT_LANE } from \"../ports.js\";\nimport type {\n Actor,\n EventRegister,\n LaneConfig,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport type { BuilderBase } from \"./builder-base.js\";\nimport { reaction_on, register_lane } from \"./builder-utils.js\";\nimport { register_state } from \"./merge.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(...)`.\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 interface 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> extends BuilderBase<\n SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>,\n TEvents,\n TActions,\n TActor,\n TLanes\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 * Declares a drain lane on this slice. 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 * Builds and returns the Slice data structure.\n */\n build: () => Slice<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\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, { reactingTo: 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 register_state(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 // Validate at declaration, exactly as the `act()` path does. Without\n // this the slice path accepted a bag the act() path rejects — and a\n // lane carrying a bad streamLimit/leaseMillis/cycleMs drains nothing\n // for the life of the process, silently: no error, no log, and nothing\n // in `blocked_streams()` to find it by.\n register_lane(resolveLaneConfig(config), lanes);\n return builder as never;\n },\n on: <TKey extends keyof TEvents>(event: TKey) =>\n reaction_on(event, events, builder) as never,\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 {\n type AutoclosePolicy,\n compile_autoclose_policy,\n policy_keep_days,\n policy_min_after_days,\n resolveActionConfig,\n} from \"../internal/index.js\";\nimport type {\n ActionHandler,\n ActionOptions,\n Actor,\n AutocloseArchiver,\n AutoclosePredicate,\n Committed,\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 * @template TSnap - `true` once `.snap(...)` has been called. Gates the\n * `.autocloses({ keep })` rolling-window option — a windowed close is\n * meaningless without snapshots, so `keep` only typechecks after\n * `.snap` in the chain.\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 TSnap extends boolean = false,\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 * Pass an optional second argument to declare a per-action retry\n * policy — the orchestrator retries this action on\n * {@link ConcurrencyError} up to `maxRetries` extra times, applying\n * `backoff` between attempts when set. Omit the argument to keep the\n * current single-attempt behavior (`ConcurrencyError` surfaces on\n * first conflict).\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 * @param options - Optional per-action retry policy\n * ({@link ActionOptions}).\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 Hot-stream action with retry + jittered exponential backoff\n * ```typescript\n * .on(\n * { transfer: z.object({ amount: z.number() }) },\n * {\n * maxRetries: 5,\n * backoff: { strategy: \"exponential\", baseMs: 10, maxMs: 200, jitter: true },\n * }\n * )\n * .emit((action) => [\"Transferred\", { amount: action.amount }])\n * ```\n *\n * @example Action with business rules\n * ```typescript\n * .on({ withdraw: z.object({ amount: z.number() }) })\n * .given([\n * { description: \"Account must be open\", valid: (state) => state.status === \"open\" },\n * { description: \"Funds must be available\", valid: (state) => state.balance > 0 }\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 options?: ActionOptions\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\n * events. Each invariant pairs a `description` with a `valid(state, actor?)`\n * predicate — when a predicate returns `false`, the action throws\n * `InvariantError` carrying the description. All invariants must pass for\n * the action to succeed.\n *\n * @param rules - Array of {@link Invariant} objects (`{ description, valid }`)\n * @returns An object with `.emit()` to finalize the action\n *\n * @example\n * ```typescript\n * .given([\n * { description: \"Must be active\", valid: (state) => state.status === \"active\" },\n * { description: \"Must be the owner\", valid: (state, actor) => state.ownerId === actor?.id }\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 TSnap\n >;\n /** Passthrough — the action payload becomes the event data\n * directly. Must reference an event declared in `.emits()`. */\n (\n event_name: keyof TEvents & string\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName,\n TSnap\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 TSnap\n >;\n (\n event_name: keyof TEvents & string\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName,\n TSnap\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, true>;\n /**\n * Declares the disclosure predicate for `sensitive(...)`-marked event\n * fields. Gates external reads: returning `true` allows the actor to see\n * plaintext on the event; returning `false` substitutes `\"[REDACTED]\"`.\n * When absent, the framework default-denies on every external read —\n * fail-safe.\n *\n * One predicate per state. A second `.discloses(...)` call replaces the\n * first (same shape as snapshots being state-level, not per-event).\n *\n * The predicate receives the full event including merged PII so it can\n * branch on the payload itself (e.g.\n * `event.data.ownerId === actor.id`). Reducers, projections, and\n * reactions are unaffected — they follow separate visibility rules.\n *\n * @param disclose - Predicate `(event, actor) => boolean`. `true` =\n * plaintext, `false` = `\"[REDACTED]\"` substitution.\n * @returns The ActionBuilder for chaining.\n *\n * @example Owner-or-admin disclosure\n * ```typescript\n * state({ User: userSchema })\n * .init(() => ({ ... }))\n * .emits({ UserRegistered: z.object({ email: sensitive(z.string()) }) })\n * .discloses((event, actor) =>\n * actor.id === event.stream || actor.roles?.includes(\"admin\"))\n * ```\n */\n discloses: (\n disclose: (\n event: Committed<TEvents, keyof TEvents & string>,\n actor: Actor\n ) => boolean\n ) => ActionBuilder<TState, TEvents, TActions, TName, TSnap>;\n /**\n * Declares the online close predicate for this state. The\n * orchestrator's autoclose cycle iterates the state's streams once\n * per tick and calls the predicate per candidate; truthy results are\n * scheduled for atomic truncate-and-seed via `Store.truncate` on the\n * next batch.\n *\n * One predicate per state. A second `.autocloses(...)` call replaces\n * the first (same shape as `.snap` / `.discloses` — state-level, not\n * per-event). Absent → the state opts out of online close entirely;\n * the cycle skips it and pays zero per-tick cost for it.\n *\n * Pass a declarative {@link AutoclosePolicy} object literal covering the\n * three operational pressure points (`after`, `is`, `reaches`). Top-level\n * fields combine with AND; an optional `or: {...}` block opens an\n * alternative OR path. Validated via Zod at build time; misconfiguration\n * throws before `act().build()` completes.\n *\n * Under the hood this compiles to a synthesized reaction that runs\n * on a per-aggregate synthetic stream: it defers to `head.created + the\n * policy's min after` while the cooldown holds and closes the stream once\n * the policy matches. There is no background sweep.\n *\n * **The function-predicate form was removed.** `.autocloses` no\n * longer accepts `(stream, head, count) => boolean`; an opaque predicate has\n * no derivable due-time or terminal event to react to. For conditions the\n * declarative form can't express, call `app.close(...)` from your own logic.\n *\n * @param policy The declarative {@link AutoclosePolicy} bag.\n * @returns The ActionBuilder for chaining.\n *\n * @example Declarative — cooldown after terminal (a Ticket closes\n * 90 days after resolution).\n * ```typescript\n * .autocloses({ is: \"TicketResolved\", after: { days: 90 } })\n * ```\n *\n * @example Declarative — multi-terminal (an Order closes on any of\n * three terminal events, no cooldown).\n * ```typescript\n * .autocloses({ is: [\"Shipped\", \"Delivered\", \"Cancelled\"] })\n * ```\n *\n * @example Declarative — time-only retention (a Session closes\n * after 24h regardless of head event).\n * ```typescript\n * .autocloses({ after: { days: 1 } })\n * ```\n *\n * @example Declarative — pure cardinality cap.\n * ```typescript\n * .autocloses({ reaches: 10_000 })\n * ```\n *\n * @example Declarative — primary cooldown + safety-net backstop.\n * ```typescript\n * .autocloses({\n * is: \"TicketResolved\", // primary trigger\n * after: { days: 90 }, // AND aged 90 days\n * or: { reaches: 10_000 }, // OR cardinality safety net\n * })\n * ```\n *\n * @example Declarative — pure OR (only backstops, no primary\n * cooldown).\n * ```typescript\n * .autocloses({ or: { is: \"TicketResolved\", reaches: 10_000 } })\n * ```\n *\n * @example Rolling window — keep the last 180 days of real events on a\n * live stream (requires `.snap(...)` earlier in the chain; `keep`\n * won't typecheck without it). Each eligible cycle prunes the prefix\n * below the closest safe snapshot older than `now − keep`.\n * ```typescript\n * .snap((s) => s.patches >= 100)\n * .autocloses({ keep: { days: 180 } })\n * ```\n *\n * @example Terminate AND prune — close 90 days after resolution,\n * meanwhile keep open streams pruned to a 180-day window.\n * ```typescript\n * .snap((s) => s.patches >= 100)\n * .autocloses({ is: \"TicketResolved\", after: { days: 90 }, keep: { days: 180 } })\n * ```\n */\n autocloses: (\n policy: [TSnap] extends [true]\n ? AutoclosePolicy\n : Omit<AutoclosePolicy, \"keep\"> & {\n /** Rolling-window retention requires `.snap(...)` earlier in\n * the builder chain — a windowed close prunes behind a real\n * snapshot, so a state that never snapshots has nothing to\n * prune behind. */\n keep?: never;\n }\n ) => ActionBuilder<TState, TEvents, TActions, TName, TSnap>;\n /**\n * Declares the archiver the online close cycle runs **before**\n * truncating a stream this state's `.autocloses(...)` predicate\n * accepted. Hosts use it to write events to durable storage (S3,\n * an analytics warehouse, cold tier) before the tombstone lands,\n * so the truncate doesn't lose history that the operator still\n * needs.\n *\n * Threads into `CloseTarget.archive` via the same plumbing\n * `app.close({ stream, archive })` already uses — the cycle holds\n * the stream's guard while the archiver runs, and a thrown\n * archiver leaves the stream guarded but un-truncated. No partial\n * truncate state, no data loss. It is not retried automatically;\n * `app.close([{ stream, archive }])` resumes the guarded stream.\n *\n * One archiver per state. A second `.archives(...)` call replaces\n * the first (same shape as `.snap` / `.discloses` /\n * `.autocloses`). Absent → the cycle truncates without an archive\n * step.\n *\n * @param archive `(stream, head) => Promise<void>`. Runs while\n * the stream is locked against new writes; the truncate runs\n * immediately after a successful resolve.\n * @returns The ActionBuilder for chaining.\n *\n * @example Archive to S3 before truncate.\n * ```typescript\n * state({ Ticket: ticketSchema })\n * .emits({ TicketOpened, TicketResolved })\n * // ...\n * .autocloses({ is: \"TicketResolved\" })\n * .archives(async (stream) => {\n * const events = await loadEvents(stream);\n * await s3.upload(`tickets/${stream}.jsonl`, events);\n * })\n * ```\n */\n archives: (\n archive: AutocloseArchiver<TEvents>\n ) => ActionBuilder<TState, TEvents, TActions, TName, TSnap>;\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 * { description: \"Account must be open\", valid: (state) => state.status === \"open\" }\n * ])\n * .emit(\"Deposited\") // passthrough — action payload { amount } becomes event data\n * .on({ withdraw: z.object({ amount: z.number() }) })\n * .given([\n * { description: \"Account must be open\", valid: (state) => state.status === \"open\" },\n * { description: \"Funds must be available\", valid: (state) => state.balance > 0 }\n * ])\n * .emit(\"Withdrawn\")\n * .on({ close: z.object({}) })\n * .given([\n * { description: \"Account must be open\", valid: (state) => state.status === \"open\" },\n * { description: \"Balance must be zero\", valid: (state) => state.balance === 0 }\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 state_schema = (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 default_patch = 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: state_schema,\n name,\n init,\n patch: default_patch,\n on: {},\n // Step delegates initialized as identity, `pii_aware` false.\n // `act().build()` flips both on states with `sensitive(...)`\n // events to bake in the gate / split and gate the cache write.\n pii_aware: false,\n view: (event) => event,\n message: (validated) => validated,\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 options?: ActionOptions\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 if (options) {\n // Validate the whole action bag at declaration so a bad\n // `maxRetries`/`backoff` throws ZodError at build, not a NaN gate.\n resolveActionConfig(options);\n internal.options ??= {};\n (internal.options as Record<string, ActionOptions>)[action] = options;\n }\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 event_name = 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. 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 emit_fn = Object.assign(\n (payload: any) => [event_name, payload],\n {\n _static_emit: event_name,\n }\n );\n (internal.on as Record<string, unknown>)[action] = emit_fn;\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 // Flip the type-level TSnap flag — same runtime object, the cast\n // unlocks `.autocloses({ keep })` for the rest of the chain.\n return builder as unknown as ActionBuilder<\n TState,\n TEvents,\n TActions,\n TName,\n true\n >;\n },\n\n discloses(\n disclose: (\n event: Committed<TEvents, keyof TEvents & string>,\n actor: Actor\n ) => boolean\n ) {\n // Replace on every call — matches snap's state-level semantics. Operators\n // who need per-event differences branch inside the predicate.\n internal.disclose = disclose;\n return builder;\n },\n\n autocloses(policy: AutoclosePolicy) {\n // Declarative policy only. The online path is a synthesized\n // reaction that defers to a derivable due-time and closes — an opaque\n // function predicate has no terminal event to react to nor a window to\n // derive, so it's no longer accepted online. Operators who need custom\n // logic call `app.close(...)` from their own reaction.\n if (typeof policy === \"function\") {\n throw new Error(\n \".autocloses(fn) is no longer supported — pass a declarative policy \" +\n \"({ after, is, reaches, or }) or call app.close(...) from your own \" +\n \"reaction for custom logic.\"\n );\n }\n if (policy === null || typeof policy !== \"object\") {\n throw new Error(\n \".autocloses(...) requires a policy object; got \" + typeof policy\n );\n }\n // The type gate (`TSnap`) already rejects `keep` before `.snap` at\n // compile time; this is the equivalent guard for untyped callers.\n if ((policy as AutoclosePolicy).keep && !internal.snap) {\n throw new Error(\n \".autocloses({ keep }) requires .snap(...) earlier in the chain — a rolling window prunes behind a real snapshot, so a state that never snapshots has nothing to prune behind.\"\n );\n }\n // Replace on every call — matches snap / discloses state-level\n // semantics. Compile to the predicate the reaction evaluates, and\n // cache the policy's min `after` window so the reaction knows whether\n // to park on a due-time or wait for the next event; `keep` resolves\n // to the rolling-window width the reaction prunes against.\n internal.autoclose = compile_autoclose_policy(\n policy\n ) as AutoclosePredicate<TEvents>;\n internal.autoclose_after_days = policy_min_after_days(policy);\n internal.autoclose_keep_days = policy_keep_days(policy);\n return builder;\n },\n\n archives(archive: AutocloseArchiver<TEvents>) {\n if (typeof archive !== \"function\") {\n throw new Error(\n \".archives(archive) requires a function; got \" + typeof archive\n );\n }\n internal.archive = archive;\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.\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 = parse_csv_line(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 // Revive dates like every Store adapter does — a Date in an event\n // payload must not depend on whether it came back through a store or\n // through a CSV restore. The `created` column below has\n // always been parsed explicitly; the JSON columns were missed.\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 next_id = 1;\n try {\n await write_line(writer, CSV_COLUMNS.join(\",\"));\n await driver(async (event) => {\n const id = next_id++;\n const row = [\n String(id),\n csv_escape(event.name as string),\n csv_escape(JSON.stringify(event.data)),\n csv_escape(event.stream),\n String(event.version),\n event.created.toISOString(),\n csv_escape(JSON.stringify(event.meta)),\n ].join(\",\");\n await write_line(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 parse_csv_line(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 csv_escape(value: string): string {\n if (/[\",\\n\\r]/.test(value)) return `\"${value.replace(/\"/g, '\"\"')}\"`;\n return value;\n}\n\nfunction write_line(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":["cache","store","action","import_zod","import_zod","import_zod","correlated_at","log","store","cache","store","state","sensitive","deps","import_zod","import_zod","store","config","store","catch_up_correlation","tombstone","load","snap","state","cache","store","import_node_crypto","state","action","import_zod","import_zod","import_node_crypto","store","state","cache","store","action","valid","action","block","config","cache","row","block","EventEmitter","store","action","cache","import_zod","state","config","import_zod","schema","sensitive","state","snap","state","config","config","noop","state","config","state","action","snap"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/adapters/console-logger.ts","../src/internal/lru-map.ts","../src/adapters/in-memory-cache.ts","../src/types/errors.ts","../src/utils.ts","../src/config.ts","../src/types/schemas.ts","../src/internal/sensitive.ts","../src/types/index.ts","../src/adapters/in-memory-store.ts","../src/disposers.ts","../src/scoped.ts","../src/ports.ts","../src/signals.ts","../src/act.ts","../src/builders/build-classify.ts","../src/internal/event-versions.ts","../src/internal/walk-streams.ts","../src/internal/audit.ts","../src/internal/autoclose-policy.ts","../src/internal/autoclose-window.ts","../src/internal/close-signal.ts","../src/internal/config.ts","../src/internal/defer-signal.ts","../src/internal/autoclose-reaction.ts","../src/internal/backoff.ts","../src/internal/circuit-breaker.ts","../src/internal/close-cycle.ts","../src/internal/correlate-cycle.ts","../src/internal/report-once.ts","../src/internal/correlator.ts","../src/internal/date-reviver.ts","../src/internal/defer-config.ts","../src/internal/drain-cycle.ts","../src/internal/defer-timer.ts","../src/internal/drain-ratio.ts","../src/internal/drain.ts","../src/internal/event-sourcing.ts","../src/internal/tracing.ts","../src/internal/projection-fold.ts","../src/internal/settle.ts","../src/builders/reaction-builder.ts","../src/builders/merge.ts","../src/builders/builder-utils.ts","../src/builders/event-builder.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 \"./signals.js\";\n\n/**\n * @packageDocumentation\n * @module act\n * Main entry point for the Act framework. Re-exports all core APIs.\n */\nexport * from \"./act.js\";\nexport * from \"./adapters/index.js\";\nexport * from \"./builders/index.js\";\nexport * from \"./config.js\";\nexport * from \"./csv.js\";\n// The imperative defer escape hatch: a reaction throws this with a\n// `DeferWhen` (see ./types/action.ts) to hold itself until the resolved\n// due-time. The declarative `.defer(when)` builder step is the common path.\nexport { DeferSignal } from \"./internal/index.js\";\nexport * from \"./ports.js\";\nexport * from \"./types/index.js\";\nexport * from \"./utils.js\";\n","/**\n * @module adapters/console-logger\n *\n * High-performance console logger inspired by pino's design:\n * - Numeric level comparison for O(1) gating\n * - stdout.write() in production for raw JSON lines (no console overhead)\n * - Colorized single-line output in development\n * - No-op method replacement when level is above threshold\n * - Child logger support with merged bindings\n */\nimport type { Logger } from \"../types/index.js\";\n\nconst LEVEL_VALUES: Record<string, number> = {\n fatal: 60,\n error: 50,\n warn: 40,\n info: 30,\n debug: 20,\n trace: 10,\n};\n\nconst LEVEL_COLORS: Record<string, string> = {\n fatal: \"\\x1b[41m\\x1b[37m\", // white on red bg\n error: \"\\x1b[31m\", // red\n warn: \"\\x1b[33m\", // yellow\n info: \"\\x1b[32m\", // green\n debug: \"\\x1b[36m\", // cyan\n trace: \"\\x1b[90m\", // gray\n};\n\nconst RESET = \"\\x1b[0m\";\n\nconst noop = () => {};\n\n/**\n * Default console logger for the Act framework.\n *\n * Production mode emits newline-delimited JSON (compatible with GCP, AWS\n * CloudWatch, Datadog, and other structured log ingestion systems).\n *\n * Development mode emits colorized, human-readable output.\n */\nexport class ConsoleLogger implements Logger {\n level: string;\n private readonly _pretty: boolean;\n\n readonly fatal: Logger[\"fatal\"];\n readonly error: Logger[\"error\"];\n readonly warn: Logger[\"warn\"];\n readonly info: Logger[\"info\"];\n readonly debug: Logger[\"debug\"];\n readonly trace: Logger[\"trace\"];\n\n constructor(\n options: {\n level?: string;\n pretty?: boolean;\n bindings?: Record<string, unknown>;\n } = {}\n ) {\n const {\n level = \"info\",\n pretty = process.env.NODE_ENV !== \"production\",\n bindings,\n } = options;\n this._pretty = pretty;\n this.level = level;\n\n const threshold = LEVEL_VALUES[level] ?? 30;\n const write = pretty\n ? this._pretty_write.bind(this, bindings)\n : this._json_write.bind(this, bindings);\n\n // Assign methods — noop when level is gated (like pino's level-based replacement)\n this.fatal = write.bind(this, \"fatal\", 60); // fatal is always enabled\n this.error = threshold <= 50 ? write.bind(this, \"error\", 50) : noop;\n this.warn = threshold <= 40 ? write.bind(this, \"warn\", 40) : noop;\n this.info = threshold <= 30 ? write.bind(this, \"info\", 30) : noop;\n this.debug = threshold <= 20 ? write.bind(this, \"debug\", 20) : noop;\n this.trace = threshold <= 10 ? write.bind(this, \"trace\", 10) : noop;\n }\n\n /** No-op — `console.log` has no resources to release. */\n async dispose(): Promise<void> {}\n\n /** @inheritDoc */\n child(bindings: Record<string, unknown>): Logger {\n return new ConsoleLogger({\n level: this.level,\n pretty: this._pretty,\n bindings,\n });\n }\n\n private _json_write(\n bindings: Record<string, unknown> | undefined,\n level: string,\n _num: number,\n obj_or_msg: unknown,\n msg?: string\n ): void {\n let obj: Record<string, unknown>;\n let message: string | undefined;\n\n if (typeof obj_or_msg === \"string\") {\n message = obj_or_msg;\n obj = {};\n } else if (obj_or_msg instanceof Error) {\n // Error instances spread to `{}` — capture the salient fields\n // explicitly so structured log aggregators see them.\n message = msg ?? obj_or_msg.message;\n obj = {\n error: { message: obj_or_msg.message, name: obj_or_msg.name },\n stack: obj_or_msg.stack,\n };\n } else if (obj_or_msg !== null && typeof obj_or_msg === \"object\") {\n message = msg;\n obj = { ...(obj_or_msg as Record<string, unknown>) };\n } else {\n message = msg;\n obj = { value: obj_or_msg };\n }\n\n const entry = Object.assign({ level, time: Date.now() }, bindings, obj);\n if (message) entry.msg = message;\n\n let line: string;\n try {\n line = JSON.stringify(entry);\n } catch {\n // Cyclic or unserializable payload — emit a minimal line rather\n // than crash the log call site.\n line = JSON.stringify({\n level,\n time: entry.time,\n msg: message ?? \"[unserializable]\",\n unserializable: true,\n });\n }\n process.stdout.write(line + \"\\n\");\n }\n\n private _pretty_write(\n bindings: Record<string, unknown> | undefined,\n level: string,\n _num: number,\n obj_or_msg: unknown,\n msg?: string\n ): void {\n const color = LEVEL_COLORS[level];\n const tag = `${color}${level.toUpperCase().padEnd(5)}${RESET}`;\n const ts = new Date().toISOString().slice(11, 23); // HH:mm:ss.SSS\n\n let message: string;\n let data: string | undefined;\n\n if (typeof obj_or_msg === \"string\") {\n message = obj_or_msg;\n } else if (obj_or_msg instanceof Error) {\n // Error instances don't serialize their `message`/`stack` via\n // JSON.stringify — `JSON.stringify(err) === \"{}\"`. Render the\n // message inline and the stack as the data payload so operators\n // see something useful instead of an empty object.\n message = msg ?? obj_or_msg.message;\n data = obj_or_msg.stack;\n } else {\n message = msg ?? \"\";\n if (obj_or_msg !== undefined && obj_or_msg !== null) {\n try {\n data = JSON.stringify(obj_or_msg);\n } catch {\n data = \"[unserializable]\";\n }\n }\n }\n\n const bind_str =\n bindings && Object.keys(bindings).length\n ? ` ${JSON.stringify(bindings)}`\n : \"\";\n\n const parts = [ts, tag, message, data, bind_str].filter(Boolean);\n process.stdout.write(parts.join(\" \") + \"\\n\");\n }\n}\n","/**\n * @module lru-map\n * @category Internal\n *\n * Tiny bounded LRU map / set built on insertion-ordered `Map`. Used to cap\n * memory in long-running orchestrators that mint large numbers of keys —\n * notably:\n *\n * - {@link InMemoryCache}: stream → state checkpoint\n * - `Act._subscribed_streams`: stream → presence (LruSet)\n *\n * Apps with millions of dynamic streams (one target per aggregate) can't\n * afford an unbounded `Set<string>` — eviction is required.\n *\n * @internal\n */\n\n/**\n * Bounded LRU map. `get()` promotes; `has()` does not. `set()` always\n * promotes and evicts the oldest entry when at capacity.\n *\n * @internal\n */\nexport class LruMap<K, V> {\n private readonly _entries = new Map<K, V>();\n private readonly _max_size: number;\n\n constructor(maxSize: number) {\n this._max_size = maxSize;\n }\n\n get(key: K): V | undefined {\n const v = this._entries.get(key);\n if (v === undefined) return undefined;\n // promote: delete + re-insert moves to most-recent position\n this._entries.delete(key);\n this._entries.set(key, v);\n return v;\n }\n\n has(key: K): boolean {\n return this._entries.has(key);\n }\n\n set(key: K, value: V): void {\n this._entries.delete(key);\n if (this._entries.size >= this._max_size) {\n // size >= maxSize ≥ 1 → at least one entry exists → next().value\n // is the oldest key (asserted with `!`).\n const oldest = this._entries.keys().next().value!;\n this._entries.delete(oldest);\n }\n this._entries.set(key, value);\n }\n\n delete(key: K): boolean {\n return this._entries.delete(key);\n }\n\n clear(): void {\n this._entries.clear();\n }\n\n get size(): number {\n return this._entries.size;\n }\n}\n\n/**\n * Bounded LRU set built on top of {@link LruMap}. `has()` does not promote;\n * `add()` does (re-inserting if already present, evicting the oldest at\n * capacity).\n *\n * @internal\n */\nexport class LruSet<T> {\n private readonly _map: LruMap<T, true>;\n\n constructor(maxSize: number) {\n this._map = new LruMap(maxSize);\n }\n\n has(value: T): boolean {\n return this._map.has(value);\n }\n\n add(value: T): void {\n this._map.set(value, true);\n }\n\n delete(value: T): boolean {\n return this._map.delete(value);\n }\n\n clear(): void {\n this._map.clear();\n }\n\n get size(): number {\n return this._map.size;\n }\n}\n","import { LruMap } from \"../internal/lru-map.js\";\nimport type { Cache, CacheEntry, Schema } from \"../types/index.js\";\n\n/**\n * In-memory LRU cache for stream snapshots.\n *\n * Backed by an internal `LruMap` for O(1) get/set with LRU eviction.\n * Configurable `maxSize` bounds memory usage.\n *\n * @example\n * ```typescript\n * import { cache } from \"@rotorsoft/act\";\n * import { InMemoryCache } from \"@rotorsoft/act\";\n *\n * cache(new InMemoryCache({ maxSize: 500 }));\n * ```\n */\n/* eslint-disable @typescript-eslint/require-await -- async interface for Redis-compatibility */\nexport class InMemoryCache implements Cache {\n // CacheEntry<any> lets `get<TState>` and `set<TState>` flow without casts:\n // any is bidirectionally compatible with the per-call TState binding, while\n // the public Cache interface still presents a typed surface to callers.\n private readonly _entries: LruMap<string, CacheEntry<any>>;\n\n constructor(options?: { maxSize?: number }) {\n this._entries = new LruMap(options?.maxSize ?? 1000);\n }\n\n /** @inheritDoc */\n async get<TState extends Schema>(\n stream: string\n ): Promise<CacheEntry<TState> | undefined> {\n return this._entries.get(stream);\n }\n\n /** @inheritDoc */\n async set<TState extends Schema>(\n stream: string,\n entry: CacheEntry<TState>\n ): Promise<void> {\n this._entries.set(stream, entry);\n }\n\n /** @inheritDoc */\n async invalidate(stream: string): Promise<void> {\n this._entries.delete(stream);\n }\n\n /** @inheritDoc */\n async clear(): Promise<void> {\n this._entries.clear();\n }\n\n /** @inheritDoc */\n async dispose(): Promise<void> {\n this._entries.clear();\n }\n\n /** Current number of entries held by the LRU. */\n get size(): number {\n return this._entries.size;\n }\n}\n","import type {\n Actor,\n Message,\n Schema,\n Schemas,\n Snapshot,\n Target,\n} from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n StreamClosedError: \"ERR_STREAM_CLOSED\",\n NonRetryableError: \"ERR_NON_RETRYABLE\",\n StoreError: \"ERR_STORE\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string;\n /** The invalid payload that failed validation */\n public readonly payload: any;\n /** Zod validation error details */\n public readonly details: any;\n\n constructor(target: string, payload: any, details: any) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n this.target = target;\n this.payload = payload;\n this.details = details;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TKey - Action name\n * @template TActor - Actor type extending base Actor\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"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(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n TActor extends Actor = Actor,\n> extends Error {\n /** The action that was attempted */\n readonly action: TKey;\n /** The action payload that was provided */\n readonly payload: Readonly<TActions[TKey]>;\n /** The target stream and actor context */\n readonly target: Target<TActor>;\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<TState, TEvents>;\n /** Human-readable description of why the invariant failed */\n readonly description: string;\n\n constructor(\n action: TKey,\n payload: Readonly<TActions[TKey]>,\n target: Target<TActor>,\n snapshot: Snapshot<TState, TEvents>,\n description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n this.action = action;\n this.payload = payload;\n this.target = target;\n this.snapshot = snapshot;\n this.description = description;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\nexport class ConcurrencyError extends Error {\n /** The stream that had the concurrent modification */\n public readonly stream: string;\n /** The actual current version in the store */\n public readonly lastVersion: number;\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[];\n /** The version number that was expected */\n public readonly expectedVersion: number;\n\n constructor(\n stream: string,\n lastVersion: number,\n events: Message<Schemas, keyof Schemas>[],\n expectedVersion: number\n ) {\n // Message lists stream + event names only. Payloads remain accessible\n // via `error.events` for callers who need them — keeping them out of\n // the message avoids MB-scale strings on contended writes and keeps\n // potentially-sensitive data out of log streams.\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n this.stream = stream;\n this.lastVersion = lastVersion;\n this.events = events;\n this.expectedVersion = expectedVersion;\n }\n}\n\n/**\n * Thrown when attempting to write to a stream that has been closed\n * with a tombstone event.\n *\n * A tombstoned stream is permanently closed — no further actions can\n * be executed against it. The only way to reopen a tombstoned stream\n * is through `Act.close()` with a `restart` callback.\n *\n * @example\n * ```typescript\n * import { StreamClosedError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"updateTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof StreamClosedError) {\n * console.error(`Stream ${error.stream} is closed`);\n * }\n * }\n * ```\n *\n * @see {@link Act.close} for closing streams\n */\nexport class StreamClosedError extends Error {\n /** The stream that is closed */\n public readonly stream: string;\n\n constructor(stream: string) {\n super(`Stream \"${stream}\" is closed (tombstoned)`);\n this.name = Errors.StreamClosedError;\n this.stream = stream;\n }\n}\n\n/**\n * Thrown by a {@link Store} adapter when an infrastructure operation fails\n * for a reason that is *not* a domain condition — a dropped connection, a\n * transaction rollback, a query timeout. It is the typed boundary between\n * \"the store is unavailable/degraded\" and the domain errors above\n * ({@link ConcurrencyError}, {@link StreamClosedError}), which describe\n * legitimate outcomes the caller should branch on.\n *\n * Adapters wrap their driver errors in `StoreError` (preserving the\n * original via `cause`) so the orchestrator can distinguish a degraded\n * backend from \"no work\" and react accordingly — see the drain circuit\n * breaker, which trips on repeated `StoreError`s and surfaces an\n * `error` lifecycle event instead of silently spinning on a down\n * database.\n *\n * @example\n * ```typescript\n * app.on(\"error\", ({ error, circuit }) => {\n * if (error instanceof StoreError)\n * alert(`store ${error.operation} failing; circuit=${circuit}`);\n * });\n * ```\n */\nexport class StoreError extends Error {\n /** The store operation that failed (e.g. `\"claim\"`, `\"ack\"`, `\"commit\"`). */\n public readonly operation: string;\n\n constructor(operation: string, options?: { cause?: unknown }) {\n super(`Store operation \"${operation}\" failed`, options);\n this.name = Errors.StoreError;\n this.operation = operation;\n }\n}\n\n/**\n * Thrown by a reaction handler to signal that the failure is permanent\n * and the drain pipeline should block the stream immediately, without\n * consuming the rest of the `maxRetries` budget.\n *\n * The drain finalizer detects `instanceof NonRetryableError` and forces\n * `block = options.blockOnError` regardless of `lease.retry`. When\n * `blockOnError` is `false`, behavior is unchanged (drain keeps retrying\n * forever) — the class never overrides the operator's explicit \"never\n * block\" choice.\n *\n * Use this for failures the handler *knows* won't get better on retry:\n * a 4xx from a webhook, a `ZodError` on malformed input, a \"user\n * deleted\" 404 from a downstream API. Use regular `Error` (or a\n * subclass) for transient failures so the existing retry-with-backoff\n * loop applies.\n *\n * @example Wrapping a permanent downstream error\n * ```typescript\n * import { NonRetryableError } from \"@rotorsoft/act\";\n *\n * .on(\"OrderConfirmed\")\n * .do(async function notifyPartner(event) {\n * const res = await fetch(url, ...);\n * if (res.status >= 400 && res.status < 500) {\n * throw new NonRetryableError(\n * `webhook ${url} responded ${res.status}`,\n * { cause: await res.text() }\n * );\n * }\n * if (!res.ok) throw new Error(`webhook ${url} responded ${res.status}`);\n * })\n * ```\n */\nexport class NonRetryableError extends Error {\n /** The original failure, if any. Mirrors the standard `Error.cause` shape. */\n public override readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = Errors.NonRetryableError;\n this.cause = options?.cause;\n }\n}\n","import { prettifyError, ZodError, type ZodType } from \"zod\";\nimport { config } from \"./config.js\";\nimport { ValidationError } from \"./types/index.js\";\n\n/**\n * @module utils\n * @category Utilities\n *\n * Small utilities used across the framework:\n * - {@link validate} — parse a payload against a Zod schema, throwing\n * {@link ValidationError} on failure.\n * - {@link extend} — validate a source object and merge into defaults.\n * - {@link sleep} — async delay (default duration from `config().sleepMs`).\n */\n\n/**\n * Parse `payload` against `schema`, returning the validated value or throwing\n * a {@link ValidationError} with prettified Zod details. When `schema` is\n * omitted, returns `payload` unchanged. The framework calls this for every\n * `app.do()` action, every emitted event, and every state init.\n *\n * @example\n * ```typescript\n * const UserSchema = z.object({ email: z.string().email() });\n * const user = validate(\"User\", { email: \"alice@example.com\" }, UserSchema);\n * ```\n *\n * @see {@link ValidationError}\n */\nexport const validate = <S>(\n target: string,\n payload: Readonly<S>,\n schema?: ZodType<S>\n): Readonly<S> => {\n try {\n return schema ? schema.parse(payload) : payload;\n } catch (error) {\n if (error instanceof ZodError) {\n throw new ValidationError(target, payload, prettifyError(error));\n }\n throw new ValidationError(target, payload, error);\n }\n};\n\n/**\n * Validate `source` against `schema` and return a new object that merges\n * `source` over the optional `target` defaults. Used by {@link config} for\n * env-var-overrides-defaults patterns; safe to call elsewhere — it never\n * mutates `target`.\n *\n * @example\n * ```typescript\n * const schema = z.object({ host: z.string(), port: z.number() });\n * const cfg = extend({ port: 8080 }, schema, { host: \"localhost\", port: 80 });\n * // → { host: \"localhost\", port: 8080 }\n * ```\n *\n * @throws {@link ValidationError} if `source` fails the schema.\n */\nexport const extend = <\n S extends Record<string, unknown>,\n T extends Record<string, unknown>,\n>(\n source: Readonly<S>,\n schema: ZodType<S>,\n target?: Readonly<T>\n): Readonly<S & T> => {\n const value = validate(\"config\", source, schema);\n return { ...target, ...value } as Readonly<S & T>;\n};\n\n/**\n * Pause for `ms` milliseconds (or `config().sleepMs` when omitted — `100ms`\n * in dev, `0ms` in tests). Used by adapters to simulate async I/O.\n *\n * @example\n * ```typescript\n * await sleep(); // default delay from config\n * await sleep(500); // explicit 500ms\n * ```\n */\nexport async function sleep(ms?: number) {\n return new Promise((resolve) => setTimeout(resolve, ms ?? config().sleepMs));\n}\n\n/**\n * Regex metacharacters that, when present in a reaction `source`, make it a\n * pattern rather than a literal stream name. A source containing none of\n * these is a bare stream name — the common case — and every claim/fetch\n * site matches it by string equality on the store's stream index. A source\n * containing any of them is compiled as a RegExp and matched against\n * candidate streams with the caller's own anchoring (e.g. `^(A|B)$`).\n */\nconst SOURCE_METACHARACTERS = /[\\^$.*+?()[\\]{}|\\\\]/;\n\n/**\n * True when `source` is a **literal** stream name — it carries no regex\n * metacharacter, so every adapter treats it as an exact match. This is the\n * fast, index-friendly path and covers every autoclose/dynamic-resolver\n * source (bare stream names). A `false` return means the source is a\n * **pattern** (contains `^ $ . * + ? ( ) [ ] { } | \\`) and must be compiled\n * as a RegExp before matching — the shape the calculator's static\n * `source: \"^(A|B)$\"` reaction relies on.\n *\n * The single source of truth for literal-vs-pattern classification across\n * correlate (which decides what a source marks), the drain fetch path, and\n * the SQLite adapter (which rejects a non-portable pattern), so all three\n * agree on which sources take the exact path.\n *\n * @example\n * ```typescript\n * is_literal_source(\"Board\"); // → true (exact lookup)\n * is_literal_source(\"^(A|B)$\"); // → false (compile as RegExp)\n * ```\n */\nexport function is_literal_source(source: string): boolean {\n return !SOURCE_METACHARACTERS.test(source);\n}\n\n/**\n * Matches an ISO-8601 timestamp, the shape `JSON.stringify` produces for a\n * `Date`.\n *\n * @internal\n */\nconst ISO_8601 =\n /^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(\\.\\d+)?(Z|[+-][0-2][0-9]:[0-5][0-9])?$/;\n\n/**\n * Revive ISO-8601-shaped strings into `Date`s during `JSON.parse`.\n *\n * **The framework no longer uses this.** Dates are resolved from the declared\n * `z.date()` paths at build time and converted on read, so a field declared\n * `z.string()` keeps its string even when the value looks like a timestamp\n *. Adapters\n * return what they stored; typing is the orchestrator's job.\n *\n * Kept exported for host applications that parse Act JSON themselves and want\n * the old shape-based behaviour. New code should let the schema decide.\n *\n */\nexport const dateReviver = (_key: string, value: unknown): unknown =>\n typeof value === \"string\" && ISO_8601.test(value) ? new Date(value) : value;\n","/**\n * @packageDocumentation\n * Configuration utilities for Act Framework environment, logging, and package metadata.\n *\n * Provides type-safe configuration loading and validation using Zod schemas.\n *\n * @module config\n */\nimport * as fs from \"node:fs\";\nimport { z } from \"zod\";\nimport { log } from \"./ports.js\";\nimport {\n type Environment,\n Environments,\n type LogLevel,\n LogLevels,\n} from \"./types/index.js\";\nimport { extend } from \"./utils.js\";\n\n/**\n * Zod schema for validating package.json metadata.\n * @internal\n */\nexport const PackageSchema = z.object({\n name: z.string().min(1),\n version: z.string().min(1),\n description: z.string().min(1).optional(),\n author: z\n .object({ name: z.string().min(1), email: z.string().optional() })\n .optional()\n .or(z.string().min(1))\n .optional(),\n license: z.string().min(1).optional(),\n dependencies: z.record(z.string(), z.string()).optional(),\n});\n\n/**\n * Type representing the validated package.json metadata.\n *\n * @internal\n */\nexport type Package = z.infer<typeof PackageSchema>;\n\n/**\n * Fallback package metadata when `package.json` can't be read at module\n * load — happens when the framework is consumed from a CWD that doesn't\n * have one (bundled CLIs, Lambda layers, embedded scripts) or when the\n * file exists but is malformed.\n *\n * The values are deliberately synthetic so callers spot them immediately:\n * `config().name === \"act-fallback\"` is a runtime signal that the framework\n * couldn't load the host project's package.json.\n *\n * @internal\n */\nconst FALLBACK_PACKAGE: Package = {\n name: \"act-fallback\",\n version: \"0.0.0-fallback\",\n description: \"Synthetic fallback — package.json could not be loaded\",\n};\n\n/**\n * Loads and parses the local package.json file as a Package object. On\n * any read or parse failure, falls back to {@link FALLBACK_PACKAGE} and\n * stashes the error so {@link config} can surface it on first access —\n * we can't call `log()` here because the logger port memoizes on first\n * call and locking it at module load defeats user injection.\n *\n * @internal\n */\nconst get_package = (): Package => {\n try {\n const raw = fs.readFileSync(\"package.json\");\n return JSON.parse(raw.toString()) as Package;\n } catch (err) {\n pkg_load_error = err;\n return FALLBACK_PACKAGE;\n }\n};\n\n/** Stashed read/parse error from {@link get_package}, surfaced by config(). */\nlet pkg_load_error: unknown;\n\n/**\n * Zod schema for the full Act Framework configuration object.\n * Includes package metadata, environment, logging, and timing options.\n * @internal\n */\nconst BaseSchema = PackageSchema.extend({\n env: z.enum(Environments),\n logLevel: z.enum(LogLevels),\n logSingleLine: z.boolean(),\n sleepMs: z.number().int().min(0).max(5000),\n});\n\n/**\n * Type representing the validated Act Framework configuration object.\n */\nexport type Config = z.infer<typeof BaseSchema>;\n\nconst { NODE_ENV, LOG_LEVEL, LOG_SINGLE_LINE, SLEEP_MS } = process.env;\n\nconst env = (NODE_ENV || \"development\") as Environment;\nconst logLevel = (LOG_LEVEL ||\n (NODE_ENV === \"test\"\n ? \"fatal\"\n : NODE_ENV === \"production\"\n ? \"info\"\n : \"trace\")) as LogLevel;\nconst logSingleLine = (LOG_SINGLE_LINE || \"true\") === \"true\";\nconst sleepMs = parseInt(NODE_ENV === \"test\" ? \"0\" : (SLEEP_MS ?? \"100\"), 10);\n\nconst pkg = get_package();\n\n// Lazily validated on first call. Cannot run extend() at module load\n// because of a utils.ts <-> config.ts cycle (utils imports config for\n// sleep()'s default). Inputs are frozen after import, so the cached\n// result is stable for the life of the process.\nlet _validated: Config | undefined;\n\n/**\n * Gets the current Act Framework configuration.\n *\n * Configuration is loaded from package.json and environment variables, providing\n * type-safe access to application metadata and runtime settings.\n *\n * **Environment Variables:**\n * - `NODE_ENV`: \"development\" | \"test\" | \"staging\" | \"production\" (default: \"development\")\n * - `LOG_LEVEL`: \"fatal\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"trace\"\n * - `LOG_SINGLE_LINE`: \"true\" | \"false\" (default: \"true\")\n * - `SLEEP_MS`: Milliseconds for sleep utility (default: 100, 0 for tests)\n *\n * **Defaults by environment:**\n * - test: logLevel=\"error\", sleepMs=0\n * - production: logLevel=\"info\"\n * - development: logLevel=\"trace\"\n *\n * @returns The validated configuration object\n *\n * @example Basic usage\n * ```typescript\n * import { config } from \"@rotorsoft/act\";\n *\n * const cfg = config();\n * console.log(`App: ${cfg.name} v${cfg.version}`);\n * console.log(`Environment: ${cfg.env}`);\n * console.log(`Log level: ${cfg.logLevel}`);\n * ```\n *\n * @see {@link Config} for configuration type\n */\nexport const config = (): Config => {\n if (!_validated) {\n _validated = extend(\n { ...pkg, env, logLevel, logSingleLine, sleepMs },\n BaseSchema\n );\n if (pkg_load_error) {\n // Surface the fallback once, after _validated is set so the\n // recursive log() → config() call short-circuits. log() resolves\n // through the port singleton — respects user injection and level.\n const msg =\n pkg_load_error instanceof Error\n ? pkg_load_error.message\n : typeof pkg_load_error === \"string\"\n ? pkg_load_error\n : \"unknown error\";\n log().warn(\n `[act] Could not read package.json (${msg}); using synthetic ` +\n `name=\"${FALLBACK_PACKAGE.name}\" version=\"${FALLBACK_PACKAGE.version}\".`\n );\n pkg_load_error = undefined;\n }\n }\n return _validated;\n};\n","import { type ZodObject, type ZodRawShape, z } from \"zod\";\n// Deep-path import (vs `../internal/index.js`) is deliberate — `_registry` is\n// a side-effect-free leaf, and going through the internal barrel would pull\n// tracing.ts → config.ts in at type-schema load time and crash on TDZ when a\n// test imports a public schema before config is initialized.\nimport { _mark_sensitive, _registry } from \"../internal/sensitive.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Sensitive-data foundation re-exports.\n *\n * - `REDACTED` / `SHREDDED` — sentinels placed in `event.data[field]`\n * when the caller isn't authorized to see a sensitive field\n * (`.discloses(predicate)` returned `false` or none was declared —\n * recoverable) or the underlying PII was wiped (`Store.forget_pii` —\n * irrecoverable).\n * top-level field names marked via {@link sensitive}. A pure,\n * read-only helper that inspects the out-of-band sensitive registry (a\n * process-global `WeakMap`) `sensitive()` populates, otherwise\n * unreachable from outside the package. Surfaced for adapters and\n * tooling that must reflect input sensitivity on their own wire\n * surface — e.g. the `@rotorsoft/act-http/openapi` emitter marks these\n * fields `writeOnly` + `format: password` so generated clients and\n * Swagger UI don't echo PII freely. Returns `[]` for non-object\n * schemas or objects with no sensitive fields; top-level shape only.\n */\nexport { pii_fields, REDACTED, SHREDDED } from \"../internal/sensitive.js\";\n\n/**\n * Mark a Zod schema as sensitive. Returns the same schema instance — the\n * marker is registered out-of-band so the static type is preserved and the\n * call site reads as a pure annotation.\n *\n * Idempotent: re-wrapping an already-sensitive schema is a no-op.\n *\n * The marker is what the orchestrator inspects to split event payloads into\n * `data` + `pii` on commit, gate reads via `.discloses`, and strip handler\n * payloads. Part of the sensitive-data foundation.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { state, sensitive } from \"@rotorsoft/act\";\n *\n * const UserRegistered = z.object({\n * email: sensitive(z.string()),\n * name: sensitive(z.string()),\n * plan: z.enum([\"free\", \"pro\"]), // not sensitive — stays in events.data\n * });\n * ```\n *\n * @param schema - The Zod schema to mark sensitive.\n * @returns The same schema instance, unmodified at the type level.\n */\nexport function sensitive<T extends z.ZodType>(schema: T): T {\n _registry.add(schema, { sensitive: true });\n // Also stamp the def, so the marker survives the clone Zod produces for\n // any refinement chained AFTER this call — `sensitive(z.string()).min(1)`\n // used to lose it silently and write plaintext into `events.data`.\n _mark_sensitive(schema);\n return schema;\n}\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n with_pii: z.boolean().optional(),\n stream_exact: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @module sensitive\n * @category Internal\n *\n * Internal mechanics for the sensitive-data foundation.\n * The public surface (`sensitive(zodType)`) lives at `libs/act/src/sensitive.ts`\n * and re-exports `REDACTED` / `SHREDDED` from here; this module holds the\n * registry plus the helpers the orchestrator calls during commit, load, and\n * handler dispatch.\n *\n * - `_registry` — process-global `z.registry<{ sensitive: true }>()`. Public\n * `sensitive()` adds to it; the helpers in this module read it.\n * - `pii_fields(schema)` — walk a Zod schema's top-level shape, return the\n * keys marked via `sensitive(...)`.\n * - `pii_gate(event, fields, predicate, actor)` — produce the external\n * view: plaintext when authorized, `[REDACTED]` when not, `[SHREDDED]`\n * when the underlying pii column is null.\n * - `pii_strip(event, fields)` — remove sensitive keys entirely\n * before invoking projection / reaction handlers.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { Actor, Committed, Schemas } from \"../types/index.js\";\n\n/**\n * Sentinel placed in `event.data[field]` when the caller isn't authorized to\n * see the sensitive field — either `.discloses(predicate)` returned `false`,\n * or no predicate was declared (framework default-deny). Recoverable: a\n * properly-authorized read returns the plaintext.\n *\n * Re-exported from `libs/act/src/sensitive.ts` as part of the public surface.\n */\nexport const REDACTED = \"[REDACTED]\" as const;\n\n/**\n * Sentinel placed in `event.data[field]` when the underlying PII payload has\n * been wiped via `Store.forget_pii(stream)` — the row's pii column is `NULL`\n * and the original plaintext is gone forever. Irrecoverable.\n *\n * Re-exported from `libs/act/src/sensitive.ts` as part of the public surface.\n */\nexport const SHREDDED = \"[SHREDDED]\" as const;\n\n/**\n * Process-global registry holding every Zod schema marked sensitive. Backed\n * by a `WeakMap`, so wrapper-created instances (`.optional()`, `.nullable()`,\n * `.default()`) that chain off a marked schema produce *new* schema instances\n * the registry doesn't track; the field walker handles those via unwrap.\n *\n * Exported so the public `sensitive(zodType)` wrapper can call `_registry.add`.\n * Underscore prefix marks \"framework-private, don't touch from user code.\"\n *\n * @internal\n */\nexport const _registry = z.registry<{ sensitive: true }>();\n\n/**\n * Marker key stamped onto a schema's own `def`. Zod clones a schema on every\n * refinement (`.min()`, `.email()`, `.trim()`, `.describe()`, `.refine()`,\n * `.transform()`, …) via `{...def}`, which copies own symbol keys — so a\n * marker on the def survives the whole chain, while the `_registry` WeakMap\n * (keyed on the *instance*) does not.\n *\n * The registry is still populated and still consulted: it covers schemas\n * marked before this key existed, and it is the mechanism the public\n * `sensitive()` doc-comment describes.\n *\n * @internal\n */\nconst _SENSITIVE = Symbol.for(\"act.sensitive\");\n\n/**\n * Stamp the def-level marker. Called by the public `sensitive()` alongside\n * `_registry.add`.\n *\n * @internal\n */\nexport function _mark_sensitive(schema: z.ZodType): void {\n const def = (\n schema as unknown as {\n _zod?: { def?: Record<PropertyKey, unknown> };\n }\n )._zod?.def;\n if (def) def[_SENSITIVE] = true;\n}\n\n/**\n * True when the given schema was marked via `sensitive(...)`.\n *\n * Walks through Zod wrapper layers (`.optional()`, `.nullable()`,\n * `.default()`, `.readonly()`) by following `_def.innerType` until it reaches\n * a non-wrapper schema, then checks the registry. Wrappers create new schema\n * instances; the marker lives on the *inner* schema the user wrapped, so we\n * test that one.\n *\n * @internal\n */\nfunction is_pii(schema: z.ZodType): boolean {\n let cur: z.ZodType = schema;\n while (true) {\n if (_registry.has(cur)) return true;\n // Def-level marker: survives the clone a refinement produces, which the\n // instance-keyed registry above cannot.\n const def = (\n cur as unknown as {\n _zod?: { def?: Record<PropertyKey, unknown> };\n }\n )._zod?.def;\n if (def?.[_SENSITIVE] === true) return true;\n const inner = (cur as { _def?: { innerType?: z.ZodType } })._def?.innerType;\n if (!inner || inner === cur) return false;\n cur = inner;\n }\n}\n\n/**\n * Derive an event's sensitive fields, as the declared schema of each.\n *\n * Walks the top-level shape of a `z.object({...})` and keeps the keys whose\n * schema (after unwrapping optional/nullable/default wrappers) was marked via\n * `sensitive(...)`. Returns an empty object for non-object schemas or events\n * with no sensitive fields — the common-case zero-cost path.\n *\n * Only the top-level shape is walked. Sensitive fields nested inside a\n * `z.object` declared inside the event payload would require recursive\n * descent; that's deferred until a real callsite needs it.\n *\n * A union event has no top-level shape, so the options are walked and merged:\n * a key sensitive in any variant must be split, because the stored payload\n * could be that variant.\n * The first variant to declare a key wins, which only matters to a caller that\n * wants the schema rather than the name.\n *\n * Returning the schemas rather than just the names is what lets a caller do\n * something per field — the event builder asks each one whether it holds a\n * date, so the `pii` sidecar's dates can be revived like any other.\n *\n * @internal\n */\nexport function pii_schemas(schema: z.ZodType): Record<string, z.ZodType> {\n const shape = (schema as { shape?: Record<string, z.ZodType> }).shape;\n if (shape && typeof shape === \"object\") {\n const fields: Record<string, z.ZodType> = {};\n for (const key of Object.keys(shape))\n if (is_pii(shape[key])) fields[key] = shape[key];\n return fields;\n }\n const options = (schema as { options?: unknown }).options;\n if (Array.isArray(options)) {\n const fields: Record<string, z.ZodType> = {};\n for (const option of options)\n for (const [key, field] of Object.entries(\n pii_schemas(option as z.ZodType)\n ))\n fields[key] ??= field;\n return fields;\n }\n return {};\n}\n\n/**\n * The names of an event's sensitive fields — {@link pii_schemas} keyed.\n *\n * @internal — consumed by the registry's `sensitive_fields(event_name)` lookup,\n * and public through `types/schemas.ts`, where act-http's OpenAPI emitter uses\n * it to mark request-body properties `writeOnly`.\n */\nexport function pii_fields(schema: z.ZodType): readonly string[] {\n return Object.keys(pii_schemas(schema));\n}\n\n/**\n * Split an emitted event's `data` into `data` (non-sensitive) + `pii`\n * (sensitive) using the field list precomputed at build time. Used by the\n * State's `_pii_split` decorator just before `Store.commit`.\n *\n * Single forward pass over `Object.keys(validated)` — same shape as the\n * spread-and-delete-free implementation in slice 3, just hoisted out of the\n * orchestrator hot path so it's only invoked when the State actually has a\n * sensitive event.\n *\n * @internal\n */\nexport function pii_split<TName, TData extends Record<string, unknown>>(\n emitted: { name: TName; data: TData },\n fields: readonly string[]\n): { name: TName; data: TData; pii: Record<string, unknown> } {\n const data = { ...emitted.data };\n const pii: Record<string, unknown> = {};\n for (const f of fields) {\n if (f in data) {\n pii[f] = data[f];\n delete data[f];\n }\n }\n return { name: emitted.name, data, pii };\n}\n\n/**\n * Build the **external view** of a committed event — the form returned by\n * `load()`, `query()`, `query_array()`, and the snapshot in `do()`'s reply.\n *\n * Only ever reached for events that declare sensitive fields — the sole caller\n * is {@link make_gate}, which the builder invokes exclusively for sensitive\n * events; non-sensitive events short-circuit to {@link IDENTITY_GATE} before\n * they get here. `fields` is therefore guaranteed non-empty (same contract as\n * {@link pii_strip}).\n *\n * - Event whose `pii` payload is null/undefined → substitute {@link SHREDDED}\n * for each declared field. Irrecoverable, so no predicate check.\n * - Event with a `pii` payload, predicate returns `true` → merge `pii` into\n * `data` (plaintext).\n * - Event with a `pii` payload, predicate returns `false` OR no predicate\n * declared (framework default-deny) → substitute {@link REDACTED} for each\n * declared field.\n *\n * @internal\n */\nfunction pii_gate<TEvents extends Schemas, TKey extends keyof TEvents>(\n event: Committed<TEvents, TKey>,\n fields: readonly string[],\n predicate: ((event: any, actor: Actor) => boolean) | null,\n actor: Actor | undefined\n): Committed<TEvents, TKey> {\n const data = event.data as Record<string, unknown>;\n // The external view NEVER carries the isolated `pii` sidecar — dropping it\n // is the whole point of the gate. Keeping it (an earlier `...event` spread)\n // leaked plaintext PII on every gated read surface (`load`, `query`,\n // `query_array`) even while `data` was correctly redacted. Strip it\n // once here; the plaintext lives in `data` only on the authorized path.\n const { pii, ...rest } = event as Committed<TEvents, TKey> & {\n pii?: Record<string, unknown> | null;\n };\n if (pii == null) {\n const shredded: Record<string, unknown> = { ...data };\n for (const f of fields) shredded[f] = SHREDDED;\n return { ...rest, data: shredded as Committed<TEvents, TKey>[\"data\"] };\n }\n // Plaintext path requires both an actor AND a predicate that allows. Missing\n // either → default-deny → REDACTED.\n const allowed = !!actor && !!predicate && predicate(event, actor);\n if (allowed) {\n return {\n ...rest,\n data: { ...data, ...pii } as Committed<TEvents, TKey>[\"data\"],\n };\n }\n const redacted: Record<string, unknown> = { ...data };\n for (const f of fields) redacted[f] = REDACTED;\n return { ...rest, data: redacted as Committed<TEvents, TKey>[\"data\"] };\n}\n\n/**\n * A prebuilt per-event read gate: given a committed event and the reading\n * actor, return the caller-visible form. This is the single gating primitive\n * the builder prebuilds for **every** read surface — both the actor-less\n * `query` / `query_array` (which pass no actor → default-deny) and the\n * actor-aware `load` / `do`-return view (which pass the reader). Non-sensitive\n * events use the shared {@link IDENTITY_GATE}; sensitive events use a redactor\n * built by {@link make_gate} that closes over the field list and the state's\n * disclosure predicate, so the read path never recomputes the sensitive-field\n * lookup nor allocates per event.\n *\n * The `actor` is optional so the actor-less surfaces can call `gate(event)`.\n *\n * @internal\n */\nexport type EventGate = <TEvents extends Schemas, TKey extends keyof TEvents>(\n event: Committed<TEvents, TKey>,\n actor?: Actor\n) => Committed<TEvents, TKey>;\n\n/**\n * Shared zero-cost gate for every event with no `sensitive(...)` fields — a\n * single frozen reference the builder hands back for non-sensitive events, so\n * the common path is one `Map` miss and an identity call, no allocation. This\n * is the \"by default, return the event\" half of the prebuilt per-event gate.\n *\n * @internal\n */\nexport const IDENTITY_GATE: EventGate = (event) => event;\n\n/**\n * Prebuild a read gate for a sensitive event, capturing its field list and the\n * disclosure predicate once at build time. The returned closure defers to\n * {@link pii_gate} with the reading actor supplied per call:\n *\n * - `predicate = null` (the actor-less `query` surfaces, or a state that never\n * declared `.discloses`) → default-deny: declared fields come back\n * {@link REDACTED} (or {@link SHREDDED} once the pii column is forgotten).\n * - `predicate` set + an authorized actor → plaintext merged into `data`.\n *\n * Either way the isolated `pii` sidecar is dropped. The builder stores one gate\n * per sensitive event (per state for the load path; predicate-less for the\n * query path); non-sensitive events fall back to {@link IDENTITY_GATE}.\n *\n * @internal\n */\nexport function make_gate(\n fields: readonly string[],\n predicate: ((event: any, actor: Actor) => boolean) | null\n): EventGate {\n return (event, actor) => pii_gate(event, fields, predicate, actor);\n}\n\n/**\n * Build the **handler view** — sensitive keys removed entirely from `data`\n * and the `pii` field dropped from the event. Used before invoking projection\n * handlers and reaction handlers, which never see PII by framework rule.\n *\n * Different from {@link pii_gate} (which substitutes {@link REDACTED} or\n * {@link SHREDDED}) — projection tables and reaction sinks shouldn't even\n * structurally observe the keys, so a handler that mistakenly writes\n * `event.data.email` into a column would get `undefined`, not a sentinel\n * string that looks like real data. The strictness is deliberate.\n *\n * Reactions that genuinely need PII (e.g. a welcome-email reaction reading\n * `email`) opt back in by explicitly calling `app.load(stream, { actor:\n * system_actor })` inside the handler — pulling PII through the gate at the\n * call site makes the security-relevant path visible in code review.\n *\n * @internal\n */\nexport function pii_strip<\n TEvents extends Schemas,\n TKey extends keyof TEvents & string,\n>(\n event: Committed<TEvents, TKey>,\n fields: readonly string[]\n): Committed<TEvents, TKey> {\n // Contract: `fields` is non-empty. `build_handle` / `build_handle_batch`\n // filter on `fields.length > 0` before invocation.\n const data = event.data as Record<string, unknown>;\n const stripped: Record<string, unknown> = {};\n for (const k of Object.keys(data)) {\n if (!fields.includes(k)) stripped[k] = data[k];\n }\n const { pii: _drop_pii, ...rest } = event as Committed<TEvents, TKey> & {\n pii?: unknown;\n };\n return {\n ...rest,\n data: stripped as Committed<TEvents, TKey>[\"data\"],\n } as Committed<TEvents, TKey>;\n}\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport type * from \"./audit.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n","/**\n * @packageDocumentation\n * @module act/adapters\n * In-memory event store adapter for development and tests.\n *\n * @category Adapters\n */\n\nimport { DEFAULT_LANE, SNAP_EVENT, TOMBSTONE_EVENT } from \"../ports.js\";\nimport { ConcurrencyError } from \"../types/errors.js\";\nimport type {\n BlockedLease,\n Committed,\n EventMeta,\n Lease,\n Message,\n Query,\n QueryStatsOptions,\n QueryStreams,\n QueryStreamsResult,\n Schema,\n Schemas,\n Store,\n StreamFilter,\n StreamPosition,\n StreamStats,\n SubscribeInput,\n} from \"../types/index.js\";\nimport { sleep } from \"../utils.js\";\n\n/** One subscription row: watermark, lease, retry and schedule. */\nclass InMemoryStream {\n readonly stream: string;\n readonly source: string | undefined;\n private _at = -1;\n private _retry = -1;\n private _blocked = false;\n private _error = \"\";\n private _leased_by: string | undefined = undefined;\n private _leased_until: Date | undefined = undefined;\n private _priority = 0;\n private _lane: string = DEFAULT_LANE;\n // While in the future, the stream is held out of `claim`.\n private _deferred_at: number | undefined = undefined;\n // Work mark; `undefined` = never correlated, so `claim` skips it.\n private _correlated_at: number | undefined = undefined;\n\n constructor(\n stream: string,\n source: string | undefined,\n priority = 0,\n lane: string = DEFAULT_LANE\n ) {\n this.stream = stream;\n this.source = source;\n this._priority = priority;\n this._lane = lane;\n }\n\n get priority() {\n return this._priority;\n }\n\n get lane() {\n return this._lane;\n }\n\n /** Replaced on every subscribe, so the current config wins on restart. */\n set lane(value: string) {\n this._lane = value;\n }\n\n bump_priority(priority: number) {\n if (priority > this._priority) this._priority = priority;\n }\n\n get correlated_at() {\n return this._correlated_at;\n }\n\n /** A mark never regresses, including at zero and negatives. */\n mark(correlated_at: number) {\n if (\n this._correlated_at === undefined ||\n correlated_at > this._correlated_at\n )\n this._correlated_at = correlated_at;\n }\n\n /** Operator override; ignores the subscribe-time `max()`. */\n set_priority(priority: number) {\n this._priority = priority;\n }\n\n get is_available() {\n return (\n !this._blocked &&\n (!this._leased_until || this._leased_until <= new Date()) &&\n (!this._deferred_at || this._deferred_at <= Date.now())\n );\n }\n\n defer(deferred_at: number) {\n this._deferred_at = deferred_at;\n // A defer is not a failure, so the redelivery is a fresh attempt.\n this._retry = -1;\n }\n\n get at() {\n return this._at;\n }\n\n get retry() {\n return this._retry;\n }\n\n get blocked() {\n return this._blocked;\n }\n\n get error() {\n return this._error;\n }\n\n get leased_by() {\n return this._leased_by;\n }\n\n get leased_until() {\n return this._leased_until;\n }\n\n get deferred_at() {\n return this._deferred_at;\n }\n\n lease(lease: Lease, millis: number): Lease {\n // The holder is recorded even at zero `millis`: `ack` is gated on it,\n // so a lease with no holder would drop every ack.\n this._leased_by = lease.by;\n this._leased_until = new Date(Date.now() + millis);\n this._retry = this._retry + 1;\n return {\n stream: this.stream,\n source: this.source,\n at: lease.at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n lane: this._lane,\n };\n }\n\n /** Ack, or with `due`, also persist the schedule. See {@link Store.ack}. */\n ack(lease: Lease) {\n if (this._leased_by === lease.by) {\n this._leased_by = undefined;\n this._leased_until = undefined;\n if (lease.due !== undefined) {\n // Advance past the handled prefix and schedule the re-visit with the\n // caller's retry (-1 for a defer, the climbing count for a backoff).\n this._at = lease.at;\n this._retry = lease.retry;\n this._deferred_at = lease.due;\n return undefined;\n }\n this._retry = -1;\n this._at = lease.at;\n this._deferred_at = undefined;\n return {\n stream: this.stream,\n source: this.source,\n at: this._at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n lane: this._lane,\n };\n }\n }\n\n block(lease: Lease, error: string) {\n // Re-blocking is a no-op, like the SQL `AND blocked = false` guard.\n if (this._leased_by === lease.by && !this._blocked) {\n this._blocked = true;\n this._error = error;\n this._deferred_at = undefined;\n return {\n stream: this.stream,\n source: this.source,\n at: this._at,\n by: this._leased_by,\n retry: this._retry,\n error: this._error,\n lagging: lease.lagging,\n lane: this._lane,\n };\n }\n }\n\n /** Retry resets to -1 (released); the next claim makes it 0. */\n reset() {\n this._at = -1;\n this._retry = -1;\n this._blocked = false;\n this._error = \"\";\n this._leased_by = undefined;\n this._leased_until = undefined;\n this._deferred_at = undefined;\n }\n\n /** True only when the stream was blocked. */\n unblock(): boolean {\n if (!this._blocked) return false;\n this._blocked = false;\n this._retry = -1;\n this._error = \"\";\n this._leased_by = undefined;\n this._leased_until = undefined;\n this._deferred_at = undefined;\n return true;\n }\n}\n\n/**\n * In-memory event store: the default when no other store is injected.\n * For development, tests and examples; all data is lost when the process\n * exits. Use {@link PostgresStore} in production.\n *\n * `Store.notify` is not implemented: a single process has no remote writer\n * to hear from, and local commits already arm the drain.\n *\n * @example Using in tests\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n *\n * describe(\"Counter\", () => {\n * beforeEach(async () => {\n * // Reset store between tests\n * await store().seed();\n * });\n *\n * it(\"increments\", async () => {\n * await app.do(\"increment\", target, { by: 5 });\n * const snapshot = await app.load(Counter, \"counter-1\");\n * expect(snapshot.state.count).toBe(5);\n * });\n * });\n * ```\n *\n * @see {@link Store} for the interface definition\n * @see {@link PostgresStore} for production use\n * @see {@link store} for injecting stores\n *\n * @category Adapters\n */\nexport class InMemoryStore implements Store {\n private _events: Committed<Schemas, keyof Schemas>[] = [];\n // Never reused. Deletions punch holes, so ids are not array indexes.\n private _next_id = 0;\n private _streams: Map<string, InMemoryStream> = new Map();\n /** Correlate checkpoint: how far the log has been READ. */\n private _correlated_at = -1;\n /** Per-correlator checkpoint and lease; keyless callers use `_correlated_at`. */\n private _correlators = new Map<\n string,\n { at: number; by: string; until: number }\n >();\n private _stream_versions: Map<string, number> = new Map();\n // stream → (event_id → cloned pii). Two levels so `forget_pii` drops one\n // inner Map. Absence means no PII.\n private _pii: Map<string, Map<number, Record<string, unknown>>> = new Map();\n\n private _reset_indexes() {\n this._events.length = 0;\n this._next_id = 0;\n this._correlated_at = -1;\n this._stream_versions.clear();\n this._pii.clear();\n }\n\n // Stores a cloned copy, so caller-side mutation can't reach it.\n private _put_pii(stream: string, id: number, pii: Record<string, unknown>) {\n let per_stream = this._pii.get(stream);\n if (!per_stream) {\n per_stream = new Map();\n this._pii.set(stream, per_stream);\n }\n per_stream.set(id, structuredClone(pii));\n }\n\n // First index whose id is greater than `after` (ids are sorted, not dense).\n private _first_index_after(after: number): number {\n let lo = 0;\n let hi = this._events.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (this._events[mid].id > after) hi = mid;\n else lo = mid + 1;\n }\n return lo;\n }\n\n // Allocation-free for events without PII, the common case.\n private _with_pii<E extends Schemas>(\n e: Committed<E, keyof E>,\n wanted = true\n ): Committed<E, keyof E> {\n if (!wanted) return e;\n const pii = this._pii.get(e.stream)?.get(e.id);\n return pii ? ({ ...e, pii } as Committed<E, keyof E>) : e;\n }\n\n async dispose() {\n await sleep();\n this._reset_indexes();\n }\n\n async seed() {\n await sleep();\n }\n\n async drop() {\n await sleep();\n this._reset_indexes();\n this._streams = new Map();\n }\n\n private in_query<E extends Schemas>(\n query: Query,\n e: Committed<E, keyof E>\n ): boolean {\n if (query.stream && !this._stream_matches(query.stream, query, e.stream))\n return false;\n if (query.names && !query.names.includes(e.name as string)) return false;\n if (query.correlation && e.meta?.correlation !== query.correlation)\n return false;\n if (e.name === SNAP_EVENT && !query.with_snaps) return false;\n // `created` is not monotonic with `id` (restore keeps it), so time\n // bounds filter; they never end the scan.\n if (query.created_after && e.created <= query.created_after) return false;\n if (query.created_before && e.created >= query.created_before) return false;\n return true;\n }\n\n private _stream_matches(pattern: string, query: Query, stream: string) {\n return query.stream_exact\n ? stream === pattern\n : RegExp(pattern).test(stream);\n }\n\n /** Index of the stream's latest snapshot, or -1; an explicit `after` wins. */\n private _snap_floor(query: Query | undefined): number {\n if (\n !query?.with_snaps ||\n !query.stream_exact ||\n query.stream === undefined ||\n query.after !== undefined\n )\n return -1;\n for (let j = this._events.length - 1; j >= 0; j--) {\n const e = this._events[j];\n if (e.stream === query.stream && e.name === SNAP_EVENT) return j;\n }\n return -1;\n }\n\n async query<E extends Schemas>(\n callback: (event: Committed<E, keyof E>) => void,\n query?: Query\n ) {\n await sleep();\n // The id bounds (`after`, `before`, the snapshot floor) are one index\n // window over the id-ordered log; every other filter is per event.\n const floor = this._snap_floor(query);\n const lo = floor >= 0 ? floor : this._first_index_after(query?.after ?? -1);\n const hi =\n query?.before !== undefined\n ? this._first_index_after(query.before - 1)\n : this._events.length;\n const with_pii = query?.with_pii !== false;\n let count = 0;\n for (let k = 0; k < hi - lo; k++) {\n const e = this._events[query?.backward ? hi - 1 - k : lo + k];\n if (query && !this.in_query(query, e)) continue;\n await Promise.resolve(\n callback(this._with_pii(e as Committed<E, keyof E>, with_pii))\n );\n count++;\n if (query?.limit && count >= query.limit) break;\n }\n return count;\n }\n\n async commit<E extends Schemas>(\n stream: string,\n msgs: Message<E, keyof E>[],\n meta: EventMeta,\n expectedVersion?: number\n ) {\n await sleep();\n const current_version = this._stream_versions.get(stream) ?? -1;\n if (\n typeof expectedVersion === \"number\" &&\n current_version !== expectedVersion\n ) {\n throw new ConcurrencyError(\n stream,\n current_version,\n msgs as Message<Schemas, keyof Schemas>[],\n expectedVersion\n );\n }\n\n let version = current_version + 1;\n const committed = msgs.map(({ name, data, pii }) => {\n const c: Committed<E, keyof E> = {\n id: this._next_id++,\n stream,\n version,\n created: new Date(),\n name,\n data,\n meta,\n };\n // Stored pii-less, so `forget_pii` never touches the event row.\n this._events.push(c as Committed<Schemas, keyof Schemas>);\n if (pii != null) this._put_pii(stream, c.id, pii);\n version++;\n return this._with_pii(c);\n });\n this._stream_versions.set(stream, version - 1);\n return committed;\n }\n\n async claim(\n lagging: number,\n leading: number,\n by: string,\n millis: number,\n lane?: string\n ) {\n await sleep();\n // Eligibility is `at < correlated_at` on the row alone; the event log\n // is never read. An unmarked row is not claimable.\n const has_work = (s: InMemoryStream): boolean =>\n s.correlated_at !== undefined && s.at < s.correlated_at;\n const available = [...this._streams.values()].filter(\n (s) =>\n s.is_available && has_work(s) && (lane === undefined || s.lane === lane)\n );\n // Lagging: priority DESC, then watermark ASC, like the PG SQL. The\n // `fair` slots ignore priority so sustained high-priority load can't\n // starve a default-priority stream.\n const fair = lagging >= 2 ? Math.max(1, Math.floor(lagging / 4)) : 0;\n const by_priority = [...available].sort(\n (a, b) => b.priority - a.priority || a.at - b.at\n );\n const priority_slice = by_priority.slice(0, lagging - fair);\n const picked = new Set(priority_slice.map((s) => s.stream));\n const fair_slice = [...available]\n .sort((a, b) => a.at - b.at)\n .filter((s) => !picked.has(s.stream))\n .slice(0, fair);\n const lag = [...priority_slice, ...fair_slice].map((s) => ({\n stream: s.stream,\n source: s.source,\n at: s.at,\n lagging: true,\n }));\n const lead = available\n .sort((a, b) => b.at - a.at)\n .slice(0, leading)\n .map((s) => ({\n stream: s.stream,\n source: s.source,\n at: s.at,\n lagging: false,\n }));\n const seen = new Set<string>();\n const combined = [...lag, ...lead].filter((p) => {\n if (seen.has(p.stream)) return false;\n seen.add(p.stream);\n return true;\n });\n return combined\n .map((p) =>\n this._streams.get(p.stream)?.lease({ ...p, by, retry: 0 }, millis)\n )\n .filter((l) => !!l);\n }\n\n async subscribe(\n streams: SubscribeInput[],\n correlated_at?: number,\n correlator?: { key: string; by: string; millis: number }\n ) {\n await sleep();\n\n // The checkpoint is monotonic. With a correlator, position and lease\n // are per key.\n let correlating: boolean | undefined;\n let keyed_at: number | undefined;\n if (correlator) {\n const now = Date.now();\n const held = this._correlators.get(correlator.key);\n // A key with no row yet inherits the shared position, so a new\n // correlator does not re-read history.\n const at = Math.max(held?.at ?? this._correlated_at, correlated_at ?? -1);\n keyed_at = at;\n if (!held || held.until < now || held.by === correlator.by) {\n correlating = true;\n this._correlators.set(correlator.key, {\n at,\n by: correlator.by,\n // Release outright, or a successor in the same ms is still refused.\n until: correlator.millis > 0 ? now + correlator.millis : 0,\n });\n } else {\n // Refused, but the position still advances: this caller may already\n // have scanned and marked.\n correlating = false;\n held.at = at;\n }\n // How far any correlator has read.\n if (correlated_at !== undefined && correlated_at > this._correlated_at)\n this._correlated_at = correlated_at;\n } else if (\n correlated_at !== undefined &&\n correlated_at > this._correlated_at\n )\n this._correlated_at = correlated_at;\n\n let subscribed = 0;\n for (const {\n stream,\n source,\n priority = 0,\n lane = DEFAULT_LANE,\n correlated_at,\n } of streams) {\n const existing = this._streams.get(stream);\n if (existing) {\n // The lane rides the priority max (compared before the bump), so a\n // lower-priority resolution can't re-lane the stream.\n if (priority >= existing.priority) existing.lane = lane;\n existing.bump_priority(priority);\n if (correlated_at !== undefined) existing.mark(correlated_at);\n } else {\n const created = new InMemoryStream(stream, source, priority, lane);\n if (correlated_at !== undefined) created.mark(correlated_at);\n this._streams.set(stream, created);\n subscribed++;\n }\n }\n let watermark = -1;\n for (const s of this._streams.values()) {\n if (s.at > watermark) watermark = s.at;\n }\n return {\n subscribed,\n watermark,\n correlated_at: keyed_at ?? this._correlated_at,\n ...(correlating === undefined ? {} : { correlating }),\n };\n }\n\n async ack(leases: Lease[]) {\n await sleep();\n // One synchronous pass: the in-memory form of the single transaction.\n return leases\n .map((l) => this._streams.get(l.stream)?.ack(l))\n .filter((l) => !!l);\n }\n\n async block(leases: BlockedLease[]) {\n await sleep();\n return leases\n .map((l) => this._streams.get(l.stream)?.block(l, l.error))\n .filter((l) => !!l);\n }\n\n async defer(input: string[] | StreamFilter, deferred_at: number) {\n await sleep();\n const selected = this._select(input);\n for (const s of selected) s.defer(deferred_at);\n return selected.length;\n }\n\n /** De-duplicated like the SQL `stream = ANY(...)`; unknown names skipped. */\n private _select(input: string[] | StreamFilter): InMemoryStream[] {\n if (Array.isArray(input))\n return [...new Set(input)]\n .map((name) => this._streams.get(name))\n .filter((s) => s !== undefined);\n return [...this._streams.values()].filter(this._filter_predicate(input));\n }\n\n private _filter_predicate(\n filter: StreamFilter\n ): (s: InMemoryStream) => boolean {\n const stream_re =\n filter.stream !== undefined && !filter.stream_exact\n ? new RegExp(filter.stream)\n : undefined;\n const source_re =\n filter.source !== undefined && !filter.source_exact\n ? new RegExp(filter.source)\n : undefined;\n return (s) => {\n if (filter.stream !== undefined) {\n if (\n filter.stream_exact\n ? s.stream !== filter.stream\n : !stream_re!.test(s.stream)\n )\n return false;\n }\n if (filter.source !== undefined) {\n if (s.source === undefined) return false;\n if (\n filter.source_exact\n ? s.source !== filter.source\n : !source_re!.test(s.source)\n )\n return false;\n }\n if (filter.blocked !== undefined && s.blocked !== filter.blocked)\n return false;\n if (filter.lane !== undefined && s.lane !== filter.lane) return false;\n return true;\n };\n }\n\n async reset(input: string[] | StreamFilter) {\n await sleep();\n const selected = this._select(input);\n for (const s of selected) s.reset();\n return selected.length;\n }\n\n async forget_pii(stream: string): Promise<number> {\n await sleep();\n const count = this._pii.get(stream)?.size ?? 0;\n this._pii.delete(stream);\n return count;\n }\n\n async unblock(input: string[] | StreamFilter) {\n await sleep();\n const selected = this._select(\n Array.isArray(input) ? input : { ...input, blocked: true }\n );\n return selected.filter((s) => s.unblock()).length;\n }\n\n async prioritize(filter: StreamFilter, priority: number) {\n await sleep();\n const changed = this._select(filter).filter((s) => s.priority !== priority);\n for (const s of changed) s.set_priority(priority);\n return changed.length;\n }\n\n async query_streams(\n callback: (position: StreamPosition) => void,\n query?: QueryStreams\n ): Promise<QueryStreamsResult> {\n await sleep();\n const limit = query?.limit ?? 100;\n const after = query?.after;\n const source_matches = query?.source_matches;\n const matches = this._filter_predicate(query ?? {});\n // Reverse-match: the stored `source` pattern must match a requested name.\n const reverse_cache = new Map<string, RegExp>();\n const reverse_match = (source: string): boolean => {\n let re = reverse_cache.get(source);\n if (!re) {\n re = new RegExp(source);\n reverse_cache.set(source, re);\n }\n return source_matches!.some((name) => re!.test(name));\n };\n\n // The default sort is code-unit order, which agrees with the `<=`\n // cursor and the SQL binary collation; `localeCompare` would not.\n const sorted = [...this._streams.keys()]\n .sort()\n .map((stream) => this._streams.get(stream) as InMemoryStream);\n\n let count = 0;\n for (const s of sorted) {\n if (after !== undefined && s.stream <= after) continue;\n if (!matches(s)) continue;\n if (source_matches !== undefined) {\n // No source consumes every stream, so it matches any name.\n if (s.source && !reverse_match(s.source)) continue;\n }\n // Before emitting, so `limit: 0` returns none.\n if (count >= limit) break;\n callback({\n stream: s.stream,\n source: s.source,\n at: s.at,\n retry: s.retry,\n blocked: s.blocked,\n error: s.error,\n priority: s.priority,\n leased_by: s.leased_by,\n leased_until: s.leased_until,\n lane: s.lane,\n deferred_at: s.deferred_at,\n correlated_at: s.correlated_at,\n });\n count++;\n }\n return { maxEventId: this._events.at(-1)?.id ?? -1, count };\n }\n\n async query_stats<E extends Schemas>(\n input: string[] | Pick<StreamFilter, \"stream\" | \"stream_exact\">,\n options?: QueryStatsOptions<E>\n ): Promise<Map<string, StreamStats<E>>> {\n await sleep();\n const exclude = new Set<string>(options?.exclude ?? []);\n const want_tail = options?.tail ?? false;\n const want_count = options?.count ?? false;\n const want_names = options?.names ?? false;\n const before = options?.before;\n const after = options?.after;\n const limit = options?.limit;\n\n const array_targets = Array.isArray(input) ? new Set(input) : null;\n const filter = Array.isArray(input) ? null : input;\n const stream_re =\n filter?.stream !== undefined && !filter.stream_exact\n ? new RegExp(filter.stream)\n : undefined;\n\n const scope_cache = new Map<string, boolean>();\n const in_scope = (stream: string): boolean => {\n const cached = scope_cache.get(stream);\n if (cached !== undefined) return cached;\n let ok = true;\n if (array_targets) {\n ok = array_targets.has(stream);\n } else if (filter?.stream !== undefined) {\n ok = filter.stream_exact\n ? stream === filter.stream\n : // stream_re set when stream is regex\n stream_re!.test(stream);\n }\n scope_cache.set(stream, ok);\n return ok;\n };\n\n type Acc = {\n head: Committed<Schemas, keyof Schemas>;\n tail?: Committed<Schemas, keyof Schemas>;\n count: number;\n names?: Record<string, number>;\n };\n const acc = new Map<string, Acc>();\n for (const e of this._events) {\n if (before !== undefined && e.id >= before) continue;\n if (!in_scope(e.stream)) continue;\n if (exclude.has(e.name as string)) continue;\n let a = acc.get(e.stream);\n if (!a) {\n a = { head: e, count: 0 };\n if (want_tail) a.tail = e;\n if (want_names) a.names = {};\n acc.set(e.stream, a);\n }\n a.head = e;\n a.count++;\n if (want_names) {\n const n = String(e.name);\n a.names![n] = (a.names![n] ?? 0) + 1;\n }\n }\n\n // Code-unit order, to agree with the `<=` cursor (see query_streams).\n const ordered = [...acc.keys()].sort();\n const out = new Map<string, StreamStats<E>>();\n for (const stream of ordered) {\n if (limit !== undefined && out.size >= limit) break;\n if (after !== undefined && stream <= after) continue;\n const a = acc.get(stream)!;\n const stats: {\n head: Committed<Schemas, keyof Schemas>;\n tail?: Committed<Schemas, keyof Schemas>;\n count?: number;\n names?: Record<string, number>;\n } = { head: a.head };\n if (want_tail) stats.tail = a.tail;\n if (want_count) stats.count = a.count;\n if (want_names) stats.names = a.names;\n out.set(stream, stats as StreamStats<E>);\n }\n return out;\n }\n\n async truncate(\n targets: Array<{\n stream: string;\n snapshot?: Schema;\n meta?: EventMeta;\n before?: Date;\n max_id?: number;\n }>\n ) {\n await sleep();\n const result = new Map<\n string,\n {\n deleted: number;\n committed: Committed<Schemas, keyof Schemas>;\n before?: Date;\n }\n >();\n\n const windowed = targets.filter((t) => t.before !== undefined);\n if (windowed.length) {\n const drop = new Set<number>();\n for (const { stream, before, max_id } of windowed) {\n let boundary: Committed<Schemas, keyof Schemas> | undefined;\n for (const e of this._events) {\n if (\n e.stream === stream &&\n e.name === SNAP_EVENT &&\n e.created < before! &&\n (max_id === undefined || e.id <= max_id) &&\n (!boundary || e.id > boundary.id)\n )\n boundary = e;\n }\n if (!boundary) continue; // no qualifying snapshot → no-op\n let deleted = 0;\n for (const e of this._events) {\n if (e.stream === stream && e.id < boundary.id) {\n drop.add(e.id);\n this._pii.get(stream)?.delete(e.id);\n deleted++;\n }\n }\n result.set(stream, { deleted, committed: boundary, before });\n }\n if (drop.size) this._events = this._events.filter((e) => !drop.has(e.id));\n }\n\n const full = targets.filter((t) => t.before === undefined);\n // Per target, like the SQL adapters, so a stream listed twice gets one seed.\n for (const { stream, snapshot, meta } of full) {\n let deleted = 0;\n this._events = this._events.filter((e) => {\n if (e.stream !== stream) return true;\n deleted++;\n return false;\n });\n // Subscriptions untouched; `seed()` reaps inert ones.\n this._stream_versions.delete(stream);\n this._pii.delete(stream);\n const event: Committed<Schemas, keyof Schemas> = {\n id: this._next_id++,\n stream,\n version: 0,\n created: new Date(),\n name: snapshot !== undefined ? SNAP_EVENT : TOMBSTONE_EVENT,\n data: snapshot ?? {},\n meta: meta ?? { correlation: \"\", causation: {} },\n };\n this._events.push(event);\n this._stream_versions.set(stream, 0);\n result.set(stream, { deleted, committed: event });\n }\n return result;\n }\n\n /** A throw inside the driver restores the captured state. Ids restart at 0. */\n async restore(\n driver: (\n callback: (event: Committed<Schemas, keyof Schemas>) => Promise<number>\n ) => Promise<void>\n ): Promise<void> {\n await sleep();\n const prev_events = this._events;\n const prev_next_id = this._next_id;\n const prev_streams = this._streams;\n const prev_stream_versions = this._stream_versions;\n const prev_pii = this._pii;\n const prev_correlated_at = this._correlated_at;\n const prev_correlators = new Map(\n [...this._correlators].map(([k, v]) => [k, { ...v }])\n );\n // Renumbered from 0, so checkpoints restart too; leases are kept.\n this._correlated_at = -1;\n for (const c of this._correlators.values()) c.at = -1;\n this._events = [];\n this._next_id = 0;\n this._streams = new Map();\n this._stream_versions = new Map();\n this._pii = new Map();\n try {\n await driver(async (event) => {\n const id = this._next_id++;\n // Split `pii` out like `commit`, so `forget_pii` erases restored PII.\n const { pii, ...rest } = event;\n const committed: Committed<Schemas, keyof Schemas> = { ...rest, id };\n this._events.push(committed);\n if (pii != null) this._put_pii(event.stream, id, pii);\n // Last event per stream wins.\n this._stream_versions.set(event.stream, event.version);\n return id;\n });\n } catch (err) {\n this._events = prev_events;\n this._next_id = prev_next_id;\n this._streams = prev_streams;\n this._stream_versions = prev_stream_versions;\n this._pii = prev_pii;\n this._correlated_at = prev_correlated_at;\n this._correlators = prev_correlators;\n throw err;\n }\n }\n}\n","import type { Disposer } from \"./types/index.js\";\n\n/**\n * The shape {@link register_weak_disposer} needs from a `WeakRef`. Declared\n * structurally so tests can hand in a stub that reports its target as\n * collected — real garbage collection is not schedulable, and a guarantee\n * about releasing memory deserves a deterministic test.\n */\nexport type RefLike<T extends object> = { deref: () => T | undefined };\n\n/**\n * A registered cleanup function, optionally tied to the lifetime of the\n * object it cleans up. `ref` present means \"run this only while its target\n * is still reachable\" — the entry holds no strong reference to that target,\n * so registering never keeps it alive. The target is handed back to `run`,\n * so a weak disposer never has to re-check what the registry just proved.\n */\ntype Entry = {\n readonly run: (target: never) => Promise<void>;\n readonly ref?: RefLike<object>;\n};\n\n/** Registered cleanup functions, executed in reverse order during shutdown. */\nconst entries: Entry[] = [];\n\n/**\n * Drop entries whose target has been collected.\n *\n * Called on every registration so the registry stays proportional to the\n * live objects rather than to every object ever built. That matters for apps\n * that mint short-lived Acts — one per tenant, per request, per test — where\n * the registry would otherwise grow without bound for the process lifetime.\n */\nconst prune = (): void => {\n for (let i = entries.length - 1; i >= 0; i--) {\n const { ref } = entries[i];\n if (ref && !ref.deref()) entries.splice(i, 1);\n }\n};\n\n/** Register a cleanup function that runs unconditionally at teardown. */\nexport const register_disposer = (run: Disposer): void => {\n prune();\n entries.push({ run });\n};\n\n/**\n * Register a cleanup function bound to `ref`'s target, held weakly.\n *\n * The registry never retains the target, so an object that becomes\n * unreachable is collectable whether or not it was cleaned up first, and its\n * entry is skipped at teardown — there is nothing left to clean up.\n */\nexport const register_weak_disposer = <T extends object>(\n ref: RefLike<T>,\n run: (target: T) => Promise<void>\n): void => {\n prune();\n entries.push({\n run: run as (target: never) => Promise<void>,\n ref: ref as RefLike<object>,\n });\n};\n\n/**\n * Run every live disposer in reverse registration order, sequentially, so a\n * disposer can rely on later-registered ones having already finished.\n *\n * Registrations are left in place, so a second teardown call re-runs them,\n * exactly as before this registry learned about weak entries.\n */\nexport const run_disposers = async (): Promise<void> => {\n for (const { run, ref } of [...entries].reverse()) {\n if (!ref) {\n await (run as Disposer)();\n continue;\n }\n const target = ref.deref();\n if (target) await (run as (t: object) => Promise<void>)(target);\n }\n};\n","/**\n * @module scoped\n * @category Internal\n *\n * Ambient execution context — every `AsyncLocalStorage` the framework owns\n * lives here, and so does every operation on one. No other module calls\n * `.run()` or `.getStore()`; they ask for a runner or a reader instead, so\n * this file is the single place to look at the abstraction.\n *\n * Two contexts:\n *\n * - **ports** — the active Act's store/cache bag, so `store()` / `cache()`\n * resolve per-Act rather than per-process. Installed by the\n * orchestrator via {@link make_run_scoped}, read by the port singletons\n * via {@link current_ports}.\n * - **reaction** — the event a handler is processing, so a dispatch made\n * anywhere inside that handler can thread `reactingTo` whichever `IAct`\n * reference made the call. Installed via {@link run_reacting},\n * read at the orchestrator boundary via {@link current_reacting}.\n *\n * Keeping the mechanics here keeps ambient state out of `internal/`, whose\n * modules are stateless implementations that receive what they need.\n *\n * @internal\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type {\n Actor,\n Cache,\n Committed,\n IAct,\n Schemas,\n Store,\n} from \"./types/index.js\";\n\n/** Per-Act ports bag. Both required together — a shared cache across stores would collide on stream keys. */\nexport type Scoped = {\n readonly store: Store;\n readonly cache: Cache;\n};\n\n/**\n * What an Act actually installs in its frame: the ports a caller passed,\n * plus per-Act settings that runtime code has to read from the *running*\n * Act rather than from whatever closure it was built in.\n *\n * `autoclose_window` is here because the autoclose reactions are\n * synthesized once into the shared registry and handed by reference to\n * every Act built from that builder, so a window captured at synthesis is\n * the first tenant's window for everyone. The frame is per-Act, so\n * reading it here is what makes the setting per-Act too.\n *\n * Wider than {@link Scoped} on purpose: `Scoped` types what a caller\n * *passes* through `ActOptions.scoped` and is public; this is what the\n * orchestrator *installs* and is not.\n *\n * @internal\n */\nexport type ActFrame = Scoped & {\n readonly autoclose_window?: {\n readonly start: number;\n readonly end: number;\n readonly timeZone: string;\n };\n};\n\n/**\n * AsyncLocalStorage carrying the active Act's ports.\n *\n * Exported for in-repo tooling that measures the context itself (the\n * scope-overhead bench). NOT public: `ports.ts` no longer re-exports it and\n * `index.ts` reaches this module only for the `Scoped` type, so it is not\n * importable from the package. Everything else uses the helpers below.\n */\nexport const scoped = new AsyncLocalStorage<ActFrame>();\n\n/**\n * The reaction currently running, as a box the handler can empty.\n *\n * A frame captured by work the handler started and did not await outlives the\n * handler and can never be unbound. The *frame* is unreclaimable, but the\n * *box inside it* is not: clearing `event` as the handler settles turns every\n * later read through that frame into \"no reaction\", without anyone having to\n * ask a second question.\n *\n * Not reachable from `index.ts`.\n */\ntype Reacting = { event: Committed<Schemas, string> | undefined };\n\nconst reacting = new AsyncLocalStorage<Reacting>();\n\n/**\n * Builds the runner an Act uses to enter its own port scope.\n *\n * Every Act gets a frame, including one built without `ActOptions.scoped` —\n * that one carries the singleton adapters (see `default_scope` in `ports.ts`).\n * Entering unconditionally is what makes an Act's ports its own: a runner that\n * collapsed to `fn()` for a singleton Act did not leave whatever frame it was\n * called from, so dispatching into a shared Act from inside a tenant's handler\n * resolved `store()` to that tenant and wrote the shared Act's events into the\n * tenant's log.\n *\n * @internal\n */\nexport function make_run_scoped(\n bag: ActFrame\n): <T>(fn: () => Promise<T>) => Promise<T> {\n return (fn) => scoped.run(bag, fn);\n}\n\n/**\n * The running Act's off-hours autoclose window, or `undefined` when it\n * declared none (or when read outside any Act).\n *\n * Read at resolution time rather than captured at synthesis: the autoclose\n * reactions belong to the shared registry, and only the frame knows which\n * Act is running them.\n *\n * @internal\n */\nexport function current_autoclose_window(): ActFrame[\"autoclose_window\"] {\n return scoped.getStore()?.autoclose_window;\n}\n\n/**\n * The active Act's ports, or `undefined` outside any Act.\n *\n * Every Act runs in a frame, so this is `undefined` only for a call made\n * outside one — `store()` and `cache()` fall back to the singleton adapters\n * there, which is what a bare `store()` in application setup expects.\n *\n * @internal\n */\nexport function current_ports(): Scoped | undefined {\n return scoped.getStore();\n}\n\n/**\n * Runs `fn` with `event` installed as the triggering-event context.\n *\n * Entered per payload rather than per lease: the context has to unwind with\n * the handler so it never reaches the drain cycle, and work a handler started\n * without awaiting has to resume into its own event's frame.\n *\n * @internal\n */\nfunction run_reacting<T>(\n event: Committed<Schemas, string>,\n fn: () => Promise<T>\n): Promise<T> {\n const box: Reacting = { event };\n return reacting.run(box, async () => {\n try {\n return await fn();\n } finally {\n // Anything still running keeps this frame; from here it reads empty.\n box.event = undefined;\n }\n });\n}\n\n/**\n * The event being reacted to, or `undefined` outside a running handler —\n * including inside work that outlived one.\n *\n * @internal\n */\nexport function current_reacting(): Committed<Schemas, string> | undefined {\n return reacting.getStore()?.event;\n}\n\n/**\n * Everything a reaction handler runs inside: the `IAct` facade it is handed\n * as its third argument, and the triggering-event context that every dispatch\n * made within it resolves — including one through a captured `app`.\n *\n * Built here rather than in the dispatcher so the dispatcher never has to\n * know how either half works; it receives this whole and calls it.\n *\n * @internal\n */\nexport type ReactionScope<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n> = {\n readonly app: IAct<TEvents, TActions, TActor>;\n readonly run: <T>(\n event: Committed<Schemas, string>,\n fn: () => Promise<T>\n ) => Promise<T>;\n};\n\n/**\n * Assembles the reaction scope from the orchestrator's bound `IAct` methods.\n *\n * @internal\n */\nexport function make_reaction_scope<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n>(\n app: IAct<TEvents, TActions, TActor>\n): ReactionScope<TEvents, TActions, TActor> {\n return { app, run: run_reacting };\n}\n","import { ConsoleLogger } from \"./adapters/console-logger.js\";\nimport { InMemoryCache } from \"./adapters/in-memory-cache.js\";\nimport { InMemoryStore } from \"./adapters/in-memory-store.js\";\nimport { config } from \"./config.js\";\nimport { register_disposer, run_disposers } from \"./disposers.js\";\nimport { current_ports, type Scoped } from \"./scoped.js\";\nimport type {\n Cache,\n Disposable,\n Disposer,\n Logger,\n Store,\n} from \"./types/index.js\";\n\n// `Scoped` is the type of the public `ActOptions.scoped` bag, so it stays\n// exported. The AsyncLocalStorage carrying it does not: it is a mechanism,\n// it was only ever reachable because `index.ts` star-exports this module,\n// and its own doc-comment already declared it internal.\nexport type { Scoped } from \"./scoped.js\";\n\n/**\n * Port/adapter infrastructure for the Act framework.\n *\n * All infrastructure concerns (logging, storage, caching) are managed as\n * singleton adapters injected via port functions. Each port follows the same\n * pattern: first call wins with a sensible default, optional adapter injection.\n *\n * - `log()` — structured logging (default: ConsoleLogger)\n * - `store()` — event persistence (default: InMemoryStore)\n * - `cache()` — state checkpoints (default: InMemoryCache)\n * - `dispose()` — register cleanup functions for graceful shutdown\n *\n * @module ports\n */\n\n/**\n * List of exit codes for process termination. Consumed by signal handlers\n * and {@link disposeAndExit}; not part of the user-facing surface.\n *\n * @internal\n */\nexport const ExitCodes = [\"ERROR\", \"EXIT\"] as const;\n\n/**\n * Type for allowed exit codes.\n *\n * - `\"ERROR\"` — abnormal termination (uncaught exception, unhandled rejection)\n * - `\"EXIT\"` — clean shutdown (SIGINT, SIGTERM, or manual trigger)\n *\n * @internal\n */\nexport type ExitCode = (typeof ExitCodes)[number];\n\n// ---------------------------------------------------------------------------\n// Port factory\n// ---------------------------------------------------------------------------\n\n/**\n * Factory function that creates or returns the injected adapter.\n * @internal\n */\ntype Injector<Port extends Disposable> = (adapter?: Port) => Port;\n\n/** Singleton adapter registry, keyed by injector function name. */\nconst adapters = new Map<string, Disposable>();\n\n/**\n * Creates a singleton port with optional adapter injection.\n *\n * The first call initializes the adapter (using the provided adapter or the\n * injector's default). Subsequent calls return the cached singleton. Adapters\n * are disposed in reverse registration order during {@link disposeAndExit}.\n *\n * @param injector - Named function that creates the default adapter\n * @returns Port function: call with no args to get the singleton, or pass an\n * adapter on the first call to override the default\n *\n * @example\n * ```typescript\n * const store = port(function store(adapter?: Store) {\n * return adapter || new InMemoryStore();\n * });\n * const s = store(); // InMemoryStore\n * ```\n */\nexport function port<Port extends Disposable>(injector: Injector<Port>) {\n return (adapter?: Port): Port => {\n if (!adapters.has(injector.name)) {\n const injected = injector(adapter);\n adapters.set(injector.name, injected);\n // log() is now in adapters (or this IS the log port we just registered),\n // so the recursive call resolves immediately. Routing through the logger\n // means level gating (e.g. silenced in tests at fatal) takes effect.\n log().info(`[act] + ${injector.name}:${injected.constructor.name}`);\n }\n return adapters.get(injector.name) as Port;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Ports: log, store, cache\n// ---------------------------------------------------------------------------\n\n/**\n * Gets or injects the singleton logger.\n *\n * By default, Act uses a built-in {@link ConsoleLogger} that emits JSON lines\n * in production (compatible with GCP, AWS CloudWatch, Datadog) and colorized\n * output in development — zero external dependencies.\n *\n * For pino, inject a `PinoLogger` from `@rotorsoft/act-pino` before building\n * your application.\n *\n * @param adapter - Optional logger implementation to inject\n * @returns The singleton logger instance\n *\n * @example Default console logger\n * ```typescript\n * import { log } from \"@rotorsoft/act\";\n * const logger = log();\n * logger.info(\"Application started\");\n * ```\n *\n * @see {@link Logger} for the interface contract\n * @see {@link ConsoleLogger} for the default implementation\n */\nexport const log = port(function log(adapter?: Logger) {\n const cfg = config();\n return (\n adapter ||\n new ConsoleLogger({\n level: cfg.logLevel,\n pretty: cfg.env !== \"production\",\n })\n );\n});\n\n/**\n * Gets or injects the singleton event store.\n *\n * By default, Act uses an {@link InMemoryStore} suitable for development and\n * testing. For production, inject a persistent store like `PostgresStore` from\n * `@rotorsoft/act-pg` before building your application.\n *\n * **Important:** Store injection must happen before creating any Act instances.\n * Once set, the store cannot be changed without restarting the application.\n *\n * @param adapter - Optional store implementation to inject\n * @returns The singleton store instance\n *\n * @example Default in-memory store\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n * const s = store();\n * ```\n *\n * @see {@link Store} for the interface contract\n * @see {@link InMemoryStore} for the default implementation\n */\n// ALS check lives outside `port()` — its cache fires only once, so the\n// per-call branch on a scoped Act has to be in the public wrapper.\nconst _store = port(function store(adapter?: Store): Store {\n return adapter ?? new InMemoryStore();\n});\n\nexport const store = ((adapter?: Store): Store => {\n return current_ports()?.store ?? _store(adapter);\n}) as (adapter?: Store) => Store;\n\n/**\n * Gets or injects the singleton cache.\n *\n * By default, Act uses an {@link InMemoryCache} (LRU, maxSize 1000). For\n * distributed deployments, inject a Redis-backed cache before building your\n * application.\n *\n * @param adapter - Optional cache implementation to inject\n * @returns The singleton cache instance\n *\n * @see {@link Cache} for the interface contract\n * @see {@link InMemoryCache} for the default implementation\n */\nconst _cache = port(function cache(adapter?: Cache) {\n return adapter ?? new InMemoryCache();\n});\n\nexport const cache = ((adapter?: Cache): Cache => {\n return current_ports()?.cache ?? _cache(adapter);\n}) as (adapter?: Cache) => Cache;\n\n/**\n * The ports bag an Act without `ActOptions.scoped` runs in: the singleton\n * adapters, read through the same frame a scoped Act uses.\n *\n * Every Act entering a frame is what keeps its ports its own. Without one, a\n * shared Act called from inside a tenant's handler inherited that tenant's\n * frame and committed to the tenant's store.\n *\n * The properties are getters on purpose. The adapters are resolved lazily and\n * injected after `act().build()` in the normal case — `store(new PgStore())`\n * in application setup, or a test's `beforeEach` — so capturing them when the\n * bag is made would pin whatever existed at build time. They read the raw\n * resolvers rather than the public `store()`/`cache()`, which consult the\n * frame this bag *is* and would recurse.\n *\n * @internal\n */\nexport const default_scope = (): Scoped => DEFAULT_SCOPE;\n\nconst DEFAULT_SCOPE: Scoped = {\n get store() {\n return _store();\n },\n get cache() {\n return _cache();\n },\n};\n\n// ---------------------------------------------------------------------------\n// Disposal\n// ---------------------------------------------------------------------------\n\n/**\n * Registered cleanup functions live in `disposers.ts`, which holds\n * lifetime-bound entries weakly so registering never pins its target for the\n * process lifetime. The public surface here is unchanged.\n */\n\n/**\n * Disposes all registered adapters and disposers, then exits the process.\n *\n * Execution order:\n * 1. Custom disposers (registered via {@link dispose}) — in reverse order\n * 2. Port adapters (log, store, cache) — in reverse registration order\n * 3. Adapter registry is cleared\n * 4. Process exits (skipped in test environment)\n *\n * In production, `\"ERROR\"` exits are silently ignored to avoid crashing on\n * transient failures (e.g. an uncaught promise in a non-critical path).\n *\n * @param code - Exit code: `\"EXIT\"` for clean shutdown (exit 0),\n * `\"ERROR\"` for abnormal termination (exit 1)\n */\nexport async function disposeAndExit(code: ExitCode = \"EXIT\"): Promise<void> {\n if (code === \"ERROR\" && config().env === \"production\") {\n // Surface the swallow so incident triage can see it. Without this\n // log the framework looks unresponsive after an uncaught exception\n // in prod — exactly when operators most need a breadcrumb.\n log().warn(\n \"disposeAndExit('ERROR') ignored in production — process kept alive\"\n );\n return;\n }\n\n // Run sequentially in reverse registration order so a disposer can rely on\n // later-registered disposers (and adapters on later-registered adapters)\n // having already finished — Promise.all would race them.\n await run_disposers();\n for (const adapter of [...adapters.values()].reverse()) {\n await adapter.dispose();\n log().info(`[act] - ${adapter.constructor.name}`);\n }\n adapters.clear();\n config().env !== \"test\" && process.exit(code === \"ERROR\" ? 1 : 0);\n}\n\n/**\n * Registers a cleanup function for graceful shutdown.\n *\n * Disposers are called automatically on SIGINT, SIGTERM, uncaught exceptions,\n * and unhandled rejections. They execute in reverse registration order before\n * port adapters are disposed.\n *\n * @param disposer - Async function to call during cleanup. Omit to get a\n * reference to {@link disposeAndExit} without registering.\n * @returns Function to manually trigger disposal and exit\n *\n * @example\n * ```typescript\n * import { dispose } from \"@rotorsoft/act\";\n *\n * const db = connectDatabase();\n * dispose(async () => await db.close());\n *\n * // In tests\n * afterAll(async () => await dispose()());\n * ```\n *\n * @see {@link disposeAndExit} for the full shutdown sequence\n */\nexport function dispose(\n disposer?: Disposer\n): (code?: ExitCode) => Promise<void> {\n disposer && register_disposer(disposer);\n return disposeAndExit;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * Event name used internally for snapshot events in the event store.\n * Snapshot events store a full state checkpoint, enabling efficient cold-start\n * recovery without replaying the entire event stream.\n */\nexport const SNAP_EVENT = \"__snapshot__\";\n\n/**\n * Event name used internally for tombstone events in the event store.\n * A tombstone marks a stream as permanently closed — no further writes\n * are permitted until the stream is explicitly restarted via `close()`.\n *\n * @see {@link Act.close} for the close-the-books API\n */\nexport const TOMBSTONE_EVENT = \"__tombstone__\";\n\n/**\n * Name of the implicit lane every reaction lands in unless its `.to({lane})`\n * declaration says otherwise. Acts that don't call\n * `.withLane(...)` see only this lane, and behavior is identical to\n * pre-1103 single-controller drain.\n *\n * Persisted on `streams.lane` and threaded as the strict-typed default in\n * builder generics — `lane?: TLanes` always includes `\"default\"`.\n */\nexport const DEFAULT_LANE = \"default\";\n","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 classify_registry,\n type EventLaneSet,\n} from \"./builders/build-classify.js\";\nimport {\n build_handle,\n build_handle_batch,\n} from \"./builders/reaction-builder.js\";\nimport { register_weak_disposer } from \"./disposers.js\";\nimport {\n type AuditDeps,\n audit,\n bare_patch,\n build_drain,\n build_es,\n CircuitBreaker,\n type CircuitBreakerOptions,\n type CircuitState,\n CloseLock,\n CorrelateCycle,\n catch_up_correlation,\n close_correlation,\n DEFAULT_LEASE_MILLIS,\n DEFAULT_MAX_SUBSCRIBED_STREAMS,\n DEFAULT_SETTLE_DEBOUNCE_MS,\n DrainController,\n type DrainOps,\n default_correlator,\n type EsOps,\n FOLD_RESET,\n type Handle,\n type HandleBatch,\n MAX_SHUTDOWN_GRACE_MS,\n type PatchFn,\n type ResettableBatchHandler,\n resolveAutocloseConfig,\n resolveCircuitBreakerConfig,\n resolveDrainConfig,\n resolveSettleConfig,\n resolveShutdownConfig,\n run_close_cycle,\n SettleLoop,\n scan,\n walk_streams,\n} from \"./internal/index.js\";\nimport {\n current_reacting,\n make_reaction_scope,\n make_run_scoped,\n} from \"./scoped.js\";\n\n// Public re-exports: these appear in ActOptions / ActLifecycleEvents above.\nexport type { CircuitBreakerOptions, CircuitState } from \"./internal/index.js\";\n\nimport { cache, default_scope, log, type Scoped, store } from \"./ports.js\";\nimport { StoreError } from \"./types/errors.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 DoOptions,\n Drain,\n DrainOptions,\n EventSink,\n EventSource,\n IAct,\n LaneConfig,\n Lease,\n LoadTarget,\n Logger,\n Query,\n Registry,\n ScanOptions,\n ScanResult,\n Schema,\n SchemaRegister,\n Schemas,\n SettleOptions,\n ShutdownOptions,\n Snapshot,\n State,\n Store,\n StoreNotification,\n StreamFilter,\n StreamPosition,\n Target,\n} from \"./types/index.js\";\n\n// Re-export the autoclose config surface so operators can\n// `import { DEFAULT_AUTOCLOSE_CYCLE_MINUTES, resolveAutocloseConfig }\n// from \"@rotorsoft/act\"`. The implementation lives in\n// `internal/config.ts` (the single home for builder-facing config bags)\n// to keep this orchestrator file focused on the `Act` class.\nexport {\n type AutocloseConfig,\n type AutoclosePolicy,\n DEFAULT_AUTOCLOSE_CYCLE_MINUTES,\n DEFAULT_CLOSE_BATCH_SIZE,\n DEFAULT_CLOSE_YIELD_MS,\n DEFAULT_MAX_SUBSCRIBED_STREAMS,\n DEFAULT_SETTLE_DEBOUNCE_MS,\n resolveAutocloseConfig,\n} from \"./internal/index.js\";\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 *\n * The first parameter is kept (unused) for arity compatibility: `committed`\n * carries snapshots of whichever state each action targeted, so its honest\n * element type is `Snapshot<Schema, TEvents>` — the register map itself was\n * never the shape of any snapshot's state.\n */\nexport type ActLifecycleEvents<\n _TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n> = {\n committed: Snapshot<Schema, 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 * A stream's sensitive-data payload was wiped via {@link Act.forget}.\n * Fires exactly once per successful `forget(stream)` call — idempotent\n * second calls (no PII left on the stream) return `eventCount: 0` and\n * do NOT re-emit. Apps that never call `forget()` never see this event.\n *\n * Listeners use it for the compliance side of GDPR / CCPA: audit log,\n * downstream cache busts, projection-side wipes that the framework\n * doesn't reach (e.g., search indexes, ETL caches). The framework's own\n * cache is invalidated by `forget()` itself before the event fires.\n */\n forgotten: { stream: string; at: Date; eventCount: number };\n /**\n * A store operation failed during the drain loop. Fires on\n * every failed drain cycle — typically a {@link StoreError} from a\n * degraded backend — carrying the orchestrator circuit breaker's state\n * after the failure (`open` means the drain loop has backed off and will\n * retry after the cooldown). Listen to alert on a degraded store; the\n * framework logs the same error regardless. Emitted only when a listener\n * is registered (Node's `EventEmitter` throws on an unhandled `\"error\"`).\n */\n error: { error: unknown; circuit: CircuitState };\n};\n\n/**\n * Options for {@link Act} construction (passed via {@link ActBuilder.build}).\n *\n * @property maxSubscribedStreams - Cap for the LRU tracking what each\n * dynamically resolved reaction target was last subscribed at. Statically\n * declared targets are held outside it and never evicted, so their lane\n * and priority stay owned by the build-time subscribe.\n * 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. 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. When\n * omitted, Act uses {@link default_correlator}, 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. */\n readonly onlyLanes?: ReadonlyArray<TLanes>;\n /**\n * Subscribe to {@link Store.notify} on this instance. Defaults\n * to `true`. Set `false` on instances that only commit and never\n * react — the subscriber-connection budget is the practical scaling\n * ceiling for the notify/listen pattern, and writer-only fleets\n * spend it for nothing when they subscribe to a channel they never\n * read. Commits still emit notifications (that's part of the\n * store's commit protocol); only the subscriber side is gated.\n */\n readonly listen?: boolean;\n /**\n * Run the local reaction pipeline on this instance. Defaults\n * to `true`. Set `false` on writer-only or sidecar instances: drain\n * controllers' auto-cycle workers don't start, `correlate()` /\n * `drain()` / `settle()` become no-ops, and the notify handler\n * skips its drain-wakeup arm (but still emits the `notified`\n * lifecycle event so observability sidecars work).\n */\n readonly drain?: boolean;\n /**\n * Orchestrator circuit breaker for the drain loop. After\n * `failureThreshold` consecutive store failures the breaker opens and\n * the drain loop skips `claim()` for `cooldownMs` instead of hammering a\n * down backend, then allows a half-open trial. Out-of-range values throw\n * a `ZodError` at `act().build()`. Defaults: threshold 5, cooldown 30s.\n */\n readonly circuitBreaker?: CircuitBreakerOptions;\n /**\n * @deprecated Accepted, validated, and ignored. It paced the off-hours\n * re-check of the old autoclose sweep; the synthesized autoclose reaction now derives its re-check\n * directly from `autocloseWindow` — a tick landing outside the window\n * parks until the exact instant the window opens, so there is no\n * polling cadence to configure (and nothing minute-denominated on the\n * close surface). Still validated as an integer `[1, 1440]` so typos\n * keep failing loudly at `act().build()`. Will be removed in the next\n * major.\n */\n readonly autocloseCycleMinutes?: number;\n /**\n * @deprecated Unused since the autoclose sweep was replaced by a\n * synthesized per-aggregate reaction — nothing pages the store in\n * batches anymore, so nothing reads this. Accepted and validated\n * (`[1, 1024]`) for compatibility; will be removed in the next major.\n */\n readonly closeBatchSize?: number;\n /**\n * @deprecated Unused: the sweep that yielded between\n * successive `Store.truncate` calls no longer exists; closes are\n * staged per stream by the autoclose reaction. Accepted and validated\n * (`[0, 1000]`) for compatibility; will be removed in the next major.\n */\n readonly closeYieldMs?: number;\n /**\n * @deprecated Unused: the sweep-side predicate try/catch\n * this flag steered no longer exists; a throwing policy predicate now\n * follows the reaction retry path (`blockOnError: false`, three\n * retries). Accepted for compatibility; will be removed in the next\n * major.\n */\n readonly closeOnError?: boolean;\n /**\n * Optional off-hours window restricting when autoclose evaluates. A\n * synthesized autoclose reaction that triggers outside the window\n * defers to the next instant the window opens — derived from the\n * window itself, no polling cadence. Hours are `[0, 23]` integers in\n * `timeZone` (IANA, default `\"UTC\"`, DST-correct); `start > end` is\n * an overnight window (e.g. `{ start: 22, end: 6 }`). Omit to\n * evaluate regardless of clock time.\n */\n readonly autocloseWindow?: {\n readonly start: number;\n readonly end: number;\n readonly timeZone?: string;\n };\n /**\n * Validate folded state against its declared Zod schema after every\n * reduction. Off by default.\n *\n * When `true`, each time an event is folded into state — on the\n * command path (`do`), on `load`/replay, and inside projection-fold\n * projections — the merged full state is parsed against the owning\n * state's `state({ Name: schema })` schema. A reducer that produces\n * schema-violating state (the calculator divide-by-zero NaN\n * class) throws a {@link ValidationError} at the triggering event,\n * whose `target` names the state and the event (`<state>.<event>#<id>`)\n * — instead of the bad value propagating and surfacing hops later as a\n * confusing downstream error.\n *\n * This is a **debugging / CI aid, not a production guard**. Turn it on\n * in development and CI to catch total-reducer bugs at the source; the\n * framework already validates action inputs and emitted events, so the\n * reduced state is the one shape it otherwise trusts. The per-event\n * patch step is selected **once at `build()`** (the same way the\n * orchestrator picks bare vs trace-decorated store ops from the log\n * level): when `false` (the default) the fold loop is byte-identical to\n * a bare reduction — the validating patch step is never selected, so\n * there is no per-event cost, not even a branch.\n */\n readonly validateFoldedState?: boolean;\n};\n\n/** Reject `onlyLanes` entries that reference undeclared lanes. */\nfunction validate_only_lanes(\n options: ActOptions,\n lanes: ReadonlyArray<LaneConfig>\n): void {\n if (!options.onlyLanes || options.onlyLanes.length === 0) return;\n const declared = new Set<string>([\"default\", ...lanes.map((l) => l.name)]);\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\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 = act().withState(Counter).build();\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 */\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, TSchemaReg>\n{\n private _emitter = new EventEmitter();\n private readonly _breaker: CircuitBreaker;\n private readonly _listen: boolean;\n private readonly _drain: boolean;\n /** Whether any event has a reaction; nothing arms without one. */\n private readonly _reactive: boolean;\n private readonly _drain_controllers: Map<\n string,\n DrainController<TEvents, TActions, TSchemaReg>\n >;\n private readonly _correlate: CorrelateCycle<TSchemaReg, TEvents, TActions>;\n private readonly _settle: SettleLoop<TEvents>;\n private _poll: ReturnType<typeof setInterval> | undefined;\n /** The deprecated `start_correlations` callback, while the poll runs. */\n private _on_discovered: ((subscribed: number) => void) | undefined;\n /**\n * Wired at construction against the store current then, so a store\n * injected after `build()` is never notified.\n */\n private readonly _notify_disposer: Promise<\n (() => void | Promise<void>) | undefined\n >;\n /** Public registry — kept as-is per the no-prefix-on-public convention. */\n public readonly registry: Registry<\n TSchemaReg,\n TEvents,\n TActions,\n keyof TStateMap & string\n >;\n private readonly _states: Map<string, State<any, any, any>>;\n /**\n * Emit a lifecycle event. The payload type is inferred from the event name\n * via {@link ActLifecycleEvents}.\n *\n * Each listener is contained on its own: a throwing listener is logged,\n * the remaining listeners still run, and the caller (`do()`, `forget()`,\n * `close()`, the drain) never sees the throw, since its durable work has\n * already landed.\n *\n * Uses `rawListeners` so `once` wrappers still de-register themselves, and\n * returns \"had listeners\" to preserve the `EventEmitter.emit` contract.\n */\n emit<E extends keyof ActLifecycleEvents<TSchemaReg, TEvents, TActions>>(\n event: E,\n args: ActLifecycleEvents<TSchemaReg, TEvents, TActions>[E]\n ): boolean {\n const listeners = this._emitter.rawListeners(event as string);\n for (const listener of listeners) {\n try {\n listener(args);\n } catch (error) {\n this._logger.error(error, `${String(event)} listener threw`);\n }\n }\n return listeners.length > 0;\n }\n\n /**\n * The one place a store failure is logged and emitted (the breaker's\n * `on_error`). The emit is guarded: an unhandled `\"error\"` emission\n * would crash the process.\n */\n private _emit_error(error: unknown, circuit: CircuitState): void {\n this._logger.error(error);\n if (this._emitter.listenerCount(\"error\") > 0)\n this.emit(\"error\", { error, circuit });\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 private readonly _batch_handlers: Map<string, BatchHandler<TEvents>>;\n private readonly _es: EsOps;\n private readonly _cd: DrainOps<TEvents>;\n /** Unambiguous: merge rejects an event name declared by two states. */\n private readonly _event_to_state: ReadonlyMap<string, State<any, any, any>>;\n /** Lanes to arm per event; `\"all\"` when a dynamic resolver hides the lane. */\n private readonly _event_to_lanes: ReadonlyMap<string, EventLaneSet>;\n private readonly _audit_deps: AuditDeps;\n private readonly _logger: Logger = log();\n /** This Act's ports: its own bag, or the singleton adapters. */\n private readonly _ports: Scoped;\n /** Runs a body so internal `store()`/`cache()` calls resolve to `_ports`. */\n private readonly _scoped: <T>(fn: () => Promise<T>) => Promise<T>;\n\n private readonly _correlator: Correlator;\n // Bound once, reused by every reaction payload.\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 private readonly _bound_forget = this.forget.bind(this);\n private readonly _handle: Handle<TEvents>;\n private readonly _handle_batch: HandleBatch<TEvents>;\n private readonly _lanes: ReadonlyArray<LaneConfig>;\n\n private readonly _close_lock = new CloseLock();\n /** Every lane a controller can exist for: `\"default\"` plus each declared one. */\n private readonly _declared_lanes: ReadonlyArray<string>;\n\n /** Drain lanes declared via `.withLane(...)`. Implicit default not included. */\n get lanes(): ReadonlyArray<LaneConfig> {\n return this._lanes;\n }\n\n /** Use the {@link act} builder rather than constructing directly. */\n constructor(\n registry: Registry<TSchemaReg, TEvents, TActions, keyof TStateMap & string>,\n states: Map<string, State<any, any, any>> = new Map(),\n batch_handlers: Map<string, BatchHandler<any>> = new Map(),\n options: ActOptions = {},\n lanes: ReadonlyArray<LaneConfig> = [],\n patch_fn: PatchFn = bare_patch\n ) {\n this.registry = registry;\n this._states = states;\n this._batch_handlers = batch_handlers;\n this._lanes = lanes;\n this._declared_lanes = [\"default\", ...lanes.map((l) => l.name)];\n validate_only_lanes(options, lanes);\n // Every Act runs in its own ports frame (the singletons when unscoped),\n // so a shared Act never inherits its caller's frame.\n this._ports = options.scoped ?? default_scope();\n const ports = this._ports;\n this._scoped = make_run_scoped({\n // Getters, not a spread: the singletons resolve lazily, so a later\n // `store(...)` / `cache(...)` still takes effect.\n get store() {\n return ports.store;\n },\n get cache() {\n return ports.cache;\n },\n // Parsed per build, so a bad window throws on every build.\n autoclose_window: resolveAutocloseConfig(options).autocloseWindow,\n });\n this._correlator = options.correlator ?? default_correlator;\n this._es = build_es(this._logger, this._correlator, patch_fn);\n this._cd = build_drain<TEvents>(this._logger);\n // PII stripping is wrapped around handlers at build time, so the\n // dispatcher is PII-unaware.\n this._handle = build_handle<TEvents, TActions, TActor>({\n logger: this._logger,\n reaction_scope: make_reaction_scope({\n do: this._bound_do,\n load: this._bound_load,\n query: this._bound_query,\n query_array: this._bound_query_array,\n forget: this._bound_forget,\n }),\n });\n this._handle_batch = build_handle_batch<TEvents>(this._logger);\n\n const classification = classify_registry(this.registry, this._states);\n this._reactive = classification.event_to_lanes.size > 0;\n this._event_to_state = classification.event_to_state;\n this._event_to_lanes = classification.event_to_lanes;\n this._listen = options.listen !== false;\n this._drain = options.drain !== false;\n\n // Order matters: controllers read the breaker, the audit bag reads the\n // controller set, settle reads the correlate cycle.\n this._breaker = this._build_breaker(options);\n this._drain_controllers = this._build_drain_controllers(options, lanes);\n this._advise_orphaned_lanes(options);\n this._audit_deps = this._build_audit_deps();\n this._correlate = this._build_correlate(options, classification);\n this._settle = this._build_settle(options);\n\n // Wire cross-process notify against the store current at construction.\n this._notify_disposer = this._wire_notify(this._ports.store);\n\n // Registered weakly, so `dispose()()` reaches a live Act while an\n // unreachable one (per tenant, per test) can still be collected.\n register_weak_disposer(new WeakRef(this), (self) => self.shutdown());\n }\n\n /** Shared by drain, settle and autoclose; bad knobs throw at build. */\n private _build_breaker(options: ActOptions): CircuitBreaker {\n return new CircuitBreaker(\n resolveCircuitBreakerConfig(options.circuitBreaker),\n {\n on_error: (error, circuit) => this._emit_error(error, circuit),\n // When the cooldown elapses, settle once: its scan or claim is the\n // half-open probe that closes or re-opens the breaker.\n on_retry: () => {\n this.settle({ debounceMs: 0 });\n },\n }\n );\n }\n\n /** Apps that declare no lanes pass no lane filter to `claim`. */\n private _build_drain_controllers(\n options: ActOptions,\n lanes: ReadonlyArray<LaneConfig>\n ): Map<string, DrainController<TEvents, TActions, TSchemaReg>> {\n const all_lanes = this._declared_lanes;\n const only_set =\n options.onlyLanes && options.onlyLanes.length > 0\n ? new Set<string>(options.onlyLanes as readonly string[])\n : undefined;\n const active_lanes = only_set\n ? all_lanes.filter((n) => only_set.has(n))\n : all_lanes;\n // Decided by the declared lanes, not the active ones: a worker narrowed\n // to \"default\" must still filter, or it would claim every lane.\n const single_default_lane = lanes.length === 0;\n const controllers = new Map<\n string,\n DrainController<TEvents, TActions, TSchemaReg>\n >();\n for (const name of active_lanes) {\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 batch_handlers: this._batch_handlers,\n handle: this._handle,\n handle_batch: this._handle_batch,\n on_acked: (acked) => this.emit(\"acked\", acked),\n on_blocked: (blocked) => this.emit(\"blocked\", blocked),\n // Reaction-requested close: the same machinery as `app.close`.\n // A store failure reaches the breaker; anything else (the archive\n // callback is app code) is logged here, never counted.\n on_close: async (targets) => {\n try {\n await this._run_close(targets);\n } catch (error) {\n if (error instanceof StoreError) throw error;\n this._logger.error(\n error,\n `Reaction-requested close of ${targets.map((t) => `\"${t.stream}\"`).join(\", \")} failed and was not retried; close it with app.close(...) once the cause is fixed.`\n );\n }\n },\n breaker: this._breaker,\n run_scoped: this._scoped,\n lane: single_default_lane ? undefined : name,\n defaults: cfg && {\n streamLimit: cfg.streamLimit,\n leaseMillis: cfg.leaseMillis,\n },\n });\n // A lane with `cycleMs` drives itself on that timer (not on\n // writer-only instances).\n if (cfg?.cycleMs !== undefined && options.drain !== false)\n controller.start(cfg.cycleMs);\n controllers.set(name, controller);\n }\n return controllers;\n }\n\n /** One process can't see the cluster, so it reports its own lane gaps. */\n private _advise_orphaned_lanes(options: ActOptions): void {\n if (!options.onlyLanes || options.onlyLanes.length === 0) return;\n const active = new Set(this._drain_controllers.keys());\n const orphaned = this._declared_lanes.filter((name) => !active.has(name));\n if (orphaned.length === 0) return;\n const list = orphaned.map((name) => `\"${name}\"`).join(\", \");\n this._logger.info(\n `Act declared ${orphaned.length} orphaned lane(s) on this instance: ${list}. ` +\n `onlyLanes excludes them, so no DrainController claims their streams here — ` +\n `their reactions accumulate un-drained unless a peer worker deploys with these ` +\n `lanes in its onlyLanes. Ensure the cluster invariant holds: the union of every ` +\n `worker's onlyLanes must cover every declared lane. ` +\n `See docs/docs/guides/production-checklist.md § Sizing lanes.`\n );\n }\n\n /** Audit deps, built after the controllers so the lane set is final. */\n private _build_audit_deps(): AuditDeps {\n return {\n store,\n event_to_state: this._event_to_state,\n // Declared lanes, not this process's controllers: a lane another\n // worker drains is not `unknown-lane`.\n declared_lanes: new Set(this._declared_lanes),\n routed_events: new Set(this._event_to_lanes.keys()),\n };\n }\n\n private _build_correlate(\n options: ActOptions,\n classification: ReturnType<\n typeof classify_registry<TSchemaReg, TEvents, TActions>\n >\n ): CorrelateCycle<TSchemaReg, TEvents, TActions> {\n return new CorrelateCycle({\n registry: this.registry,\n static_targets: classification.static_targets,\n cd: this._cd,\n max_subscribed_streams:\n options.maxSubscribedStreams ?? DEFAULT_MAX_SUBSCRIBED_STREAMS,\n // Declared lanes (not active ones): a lane another process claims is\n // still a valid destination.\n declared_lanes: new Set(this._declared_lanes),\n // Built after the controllers, so their keys are the active lanes.\n shard:\n this._drain_controllers.size < this._declared_lanes.length\n ? [...this._drain_controllers.keys()]\n : undefined,\n // Only reached on a draining app: writer-only ones never correlate.\n on_init: () => this._arm_all(),\n on_init_async: this._drain\n ? () => this._seed_persisted_defers()\n : undefined,\n });\n }\n\n /** Cold start: an idle deferred stream still fires on time after a restart. */\n private async _seed_persisted_defers(): Promise<void> {\n const now = Date.now();\n await walk_streams(store(), (pos) => {\n // A past-due schedule is already claimable.\n if (pos.deferred_at === undefined || pos.deferred_at <= now) return;\n const controller = this._drain_controllers.get(pos.lane ?? \"default\");\n controller?.seed_defer(pos.stream, pos.deferred_at);\n });\n }\n\n private _build_settle(options: ActOptions): SettleLoop<TEvents> {\n return new SettleLoop<TEvents>(\n {\n init: () => this._scoped(() => this._correlate.init()),\n checkpoint: () => this._correlate.checkpoint,\n correlate: (q) => this._correlate_scanned(q, true),\n drain: (o) => this.drain(o),\n on_settled: (drain) => this.emit(\"settled\", drain),\n breaker: this._breaker,\n },\n options.settleDebounceMs ?? DEFAULT_SETTLE_DEBOUNCE_MS\n );\n }\n\n private _shutdown_promise: Promise<void> | undefined;\n\n /**\n * Per-instance teardown: stop scheduling new work, give drain cycles\n * already in flight a bounded chance to finish, then remove lifecycle\n * listeners and tear down the cross-process notify subscription.\n *\n * Scheduling stops first, then in-flight cycles get up to `graceMs` to\n * reach their `ack` (an abandoned handler holds its lease until it\n * expires). Listeners come off after the wait, so they still see work that\n * finished during it. The budget is a ceiling, not a delay; when it runs\n * out, teardown proceeds anyway.\n *\n * Idempotent — repeated calls return the same promise, and the first\n * call's `graceMs` is the one that applies. Registered automatically with\n * the global `dispose()` registry at construction, so process-wide\n * `dispose()()` covers it; test helpers (or operators that mint\n * short-lived Acts) call it explicitly for prompt cleanup.\n *\n * @param options - See {@link ShutdownOptions}. Defaults the grace budget\n * to the largest lane `leaseMillis` (capped at 30s).\n */\n shutdown(options?: ShutdownOptions): Promise<void> {\n if (!this._shutdown_promise) {\n resolveShutdownConfig(options);\n this._shutdown_promise = (async () => {\n this.stop_correlations();\n // Unsubscribe from notify before stopping settle, or a late\n // notification would schedule a cycle nothing cancels. Never rejects.\n const disposer = await this._notify_disposer;\n if (disposer) await disposer();\n this._settle.stop();\n this._breaker.stop();\n for (const c of this._drain_controllers.values()) c.stop();\n await this._await_inflight(options?.graceMs);\n // Hand the correlation lease back last, after the wait (a settle\n // cycle still running would re-take it), and await it so a\n // successor isn't refused.\n await this._scoped(() => this._correlate.release_correlation());\n this._emitter.removeAllListeners();\n })();\n }\n return this._shutdown_promise;\n }\n\n /**\n * The largest `leaseMillis` among lanes with a cycle in flight (the\n * default for none or 0, and for a running settle), capped.\n */\n private _derive_grace_ms(\n running: { readonly lease_millis: number | undefined }[],\n settling: boolean\n ): number {\n // A lane with no lease waits the drain's default lease: as long as its\n // handlers were already allowed to hold a stream.\n let max = settling ? DEFAULT_LEASE_MILLIS : 0;\n for (const c of running)\n max = Math.max(max, c.lease_millis || DEFAULT_LEASE_MILLIS);\n return Math.min(max, MAX_SHUTDOWN_GRACE_MS);\n }\n\n private async _await_inflight(grace_ms?: number): Promise<void> {\n const running = [...this._drain_controllers.values()].filter(\n (c) => c.inflight !== undefined\n );\n // A settle cycle already running keeps going after `stop()`, so wait\n // for it too.\n const settling = this._settle.inflight;\n if (running.length === 0 && !settling) return;\n const grace = grace_ms ?? this._derive_grace_ms(running, !!settling);\n if (grace <= 0) return;\n const inflight = running.map((c) => c.inflight);\n if (settling) inflight.push(settling);\n let timer!: ReturnType<typeof setTimeout>;\n const budget = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, grace);\n timer.unref();\n });\n try {\n await Promise.race([Promise.all(inflight), budget]);\n } finally {\n // Don't leave the budget timer pending when the cycles won the race.\n clearTimeout(timer);\n }\n }\n\n /** Failures are logged, never thrown: `notify` is a hint. */\n private async _wire_notify(\n s: Store\n ): Promise<(() => void | Promise<void>) | undefined> {\n if (!this._reactive) return undefined;\n if (!s.notify) return undefined;\n // Only the subscriber side is gated; commits still notify.\n if (!this._listen) return undefined;\n try {\n return await s.notify((notification) => {\n // Errors are logged and swallowed so the store's listener survives.\n try {\n this.emit(\"notified\", notification);\n // Arm only the lanes whose reactions match the notified events.\n // A sidecar (`drain: false`) still gets the `notified` event.\n if (this._drain) {\n const armed = this._arm_for_event_names(\n notification.events.map((e) => e.name)\n );\n if (armed) this._settle.schedule({ debounceMs: 0 });\n }\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 options - Per-call dispatch options ({@link DoOptions}) —\n * `reactingTo` to thread correlation, `correlator` to override the\n * framework or orchestrator-level correlator for this call only.\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 * @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 options?: DoOptions<TEvents>\n ) {\n // Resolve the ambient reaction context here so `internal/` never reads\n // ambient state. An explicit `reactingTo` wins.\n const reacting_to = options?.reactingTo ?? current_reacting();\n const do_options =\n reacting_to === options?.reactingTo\n ? options\n : { ...options, reactingTo: reacting_to };\n return this._scoped(async () => {\n const snapshots = await this._es.action(\n this.registry.actions[action],\n action,\n target,\n payload,\n do_options\n );\n // Arm only the lanes whose reactions match the committed events\n // (`action()` snapshots always carry their event).\n this._arm_for_event_names(\n snapshots.map((s) => (s.event as { name: string }).name)\n );\n this.emit(\"committed\", snapshots);\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 * @see {@link Snapshot} for snapshot structure\n */\n // Anonymous load (bare stream) — sensitive fields come back as REDACTED.\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 // Auth-aware load — runs `.discloses(predicate)` against the supplied actor.\n async load<\n TNewState extends Schema,\n TNewEvents extends Schemas,\n TNewActions extends Schemas,\n >(\n state: State<TNewState, TNewEvents, TNewActions>,\n target: LoadTarget<TActor>,\n callback?: (snapshot: Snapshot<TNewState, TNewEvents>) => void\n ): Promise<Snapshot<TNewState, TNewEvents>>;\n async load<TKey extends keyof TStateMap & string>(\n name: TKey,\n target: LoadTarget<TActor>,\n callback?: (snapshot: Snapshot<TStateMap[TKey], TEvents>) => void\n ): Promise<Snapshot<TStateMap[TKey], TEvents>>;\n async load<TNewState extends Schema>(\n stateOrName: State<TNewState, any, any> | string,\n streamOrTarget: string | LoadTarget<TActor>,\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 // Normalize the two surfaces: bare-stream (default-deny — actor\n // undefined → REDACTED on the discloses check) vs LoadTarget\n // (auth-aware — actor flows into `.discloses(predicate)`).\n const target: LoadTarget<Actor> =\n typeof streamOrTarget === \"string\"\n ? {\n stream: streamOrTarget,\n actor: undefined as unknown as Actor,\n asOf,\n }\n : streamOrTarget;\n return await this._es.load(merged, target, callback);\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 * @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 const gated = this.registry.query_gate(e.name as string)(e);\n if (!first) first = gated;\n last = gated;\n callback?.(gated);\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 * @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) => {\n events.push(this.registry.query_gate(e.name as string)(e));\n }, query);\n return events;\n });\n }\n\n /**\n * Wipe the sensitive-data payload for every event on the stream — see\n * {@link IAct.forget}.\n *\n * Throws on adapters without `Store.forget_pii`, invalidates the cache\n * entry for the stream, emits the `forgotten` lifecycle event with the\n * row count. Idempotent: a second call returns `{eventCount: 0}` and\n * does NOT re-emit.\n *\n * @param stream - Target stream.\n * @returns `{eventCount}` — number of events whose PII column was wiped.\n */\n async forget(stream: string): Promise<{ eventCount: number }> {\n return this._scoped(async () => {\n const s = store();\n if (!s.forget_pii) {\n throw new Error(\n `Store does not implement forget_pii — adapter cannot comply with sensitive-data erasure. ` +\n `Use an adapter that declares pii_isolation: true (e.g. @rotorsoft/act on the in-memory store).`\n );\n }\n const eventCount = await s.forget_pii(stream);\n await cache().invalidate(stream);\n if (eventCount > 0) {\n this.emit(\"forgotten\", { stream, at: new Date(), eventCount });\n }\n return { eventCount };\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()`. It is not only how dynamic targets\n * are discovered: a stream is claimable while `at < correlated_at`, and\n * `correlate` is the only component that raises that mark, so a\n * commit no correlate has seen is not drainable, static targets included. For a\n * higher-level API that handles debouncing, correlation, and signaling\n * 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 * @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 // Validate the runtime knobs before anything runs (a bad leaseMillis /\n // streamLimit / eventLimit throws ZodError here, not on the first cycle).\n resolveDrainConfig(options);\n // Writer-only instances run no reactions.\n if (!this._drain)\n return { fetched: [], leased: [], acked: [], blocked: [] };\n return this._scoped(() => this._drain_all(options));\n }\n\n private _arm_all(): void {\n if (!this._reactive) return;\n // A commit may also give the next correlate scan something to find.\n this._correlate.arm();\n for (const c of this._drain_controllers.values()) c.arm();\n }\n\n /** Arms only the lanes these events react on; true when any was armed. */\n private _arm_for_event_names(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._arm_all();\n return true;\n }\n for (const lane of set) to_arm.add(lane);\n }\n if (to_arm.size === 0) return false;\n this._correlate.arm();\n for (const lane of to_arm) this._drain_controllers.get(lane)?.arm();\n return true;\n }\n\n /** In parallel, so a slow lane never holds up a fast one. */\n private async _drain_all(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 // Actor-less like `query`/`query_array`, so default-deny.\n // Handlers are unaffected — they read through their own strip.\n fetched.push(\n ...r.fetched.map((f) => ({\n ...f,\n events: f.events.map((e) =>\n this.registry.query_gate(e.name as string)(e)\n ),\n }))\n );\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 - Scan filter — see {@link Query} for fields (typically\n * `{ after: <event-id>, limit: <count> }`)\n * @returns The number of newly subscribed streams and the last scanned event id\n *\n * @example Manual correlation\n * ```typescript\n * // Scan for new streams\n * const { subscribed, last_id } = await app.correlate({ after: 0, limit: 100 });\n * console.log(`Subscribed ${subscribed} new streams`);\n *\n * // Save last_id for next scan\n * await saveCheckpoint(last_id);\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 const { subscribed, last_id } = await this._correlate_scanned(query);\n return { subscribed, last_id };\n }\n\n /** `correlate` plus `scanned`, which settle needs for the breaker. */\n private async _correlate_scanned(\n query: Query,\n /** Honour the correlation lease — settle and the poller only. */\n lease = false\n ): Promise<{ subscribed: number; last_id: number; scanned: boolean }> {\n // Writer-only instances don't correlate.\n if (!this._drain) return { subscribed: 0, last_id: -1, scanned: false };\n return this._scoped(async () => {\n const { subscribed, last_id, marked, scanned } =\n await this._correlate.correlate(query, lease);\n // Also re-arms correlate, so a backlog scan keeps going.\n if (subscribed > 0 || marked > 0) this._arm_all();\n if (subscribed > 0) this._on_discovered?.(subscribed);\n return { subscribed, last_id, scanned };\n });\n }\n\n /**\n * Starts a background poll that settles on a timer: each tick looks for\n * new events, subscribes the streams their reactions target, and drains\n * them.\n *\n * Use it when this process can miss commits — another process writes to a\n * store without `notify`, or a notification is lost. It is the safety net\n * under `notify`: a missed wakeup costs at most one `frequency` of latency.\n *\n * Only one poll runs per Act instance. On a writer-only instance\n * (`drain: false`) each tick is a no-op, like `settle()`.\n *\n * @param query - Only `limit` is used: the most events each correlate pass\n * reads (default 100). The scan always starts at the correlation\n * checkpoint, so `after` is ignored.\n * @param frequency - Milliseconds between ticks (default: 10000)\n * @param callback - Called with the number of newly subscribed streams\n * after each correlate pass that found some.\n * @deprecated Listen to the `\"settled\"` lifecycle event instead.\n * @returns `true` if the poll started, `false` if one is already running\n *\n * @example\n * ```typescript\n * app.start_correlations({ limit: 100 }, 5000);\n * // later\n * app.stop_correlations();\n * ```\n *\n * @see {@link settle} for what each tick runs\n * @see {@link stop_correlations} to stop the poll\n */\n start_correlations(\n query: Query = {},\n frequency = 10_000,\n callback?: (subscribed: number) => void\n ): boolean {\n if (this._poll) return false;\n this._on_discovered = callback;\n const correlate = { limit: query.limit || 100 };\n this._poll = setInterval(() => {\n // No local signal says there is work, so look anyway.\n this._correlate.arm();\n this.settle({ debounceMs: 0, correlate });\n }, frequency);\n return true;\n }\n\n /**\n * Stops the poll started by {@link start_correlations}. Idempotent, and\n * called by `shutdown()`.\n *\n * @see {@link start_correlations}\n */\n stop_correlations() {\n if (this._poll) {\n clearInterval(this._poll);\n this._poll = undefined;\n }\n this._on_discovered = undefined;\n // Hand the correlation lease back, best-effort and not awaited (this\n // method is synchronous; the lease would expire anyway).\n void this._scoped(() => this._correlate.release_correlation());\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 input - Reaction target streams (e.g., projection names) to reset, or a {@link StreamFilter} for bulk operations\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 * @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 // Drop every fold cache before the replay, or a warm cache would\n // re-flush stale rows. Cleared for all targets: resolving `input`\n // costs a query, and an extra clear costs one head load per stream.\n for (const handler of this._batch_handlers.values())\n (handler as ResettableBatchHandler<TEvents>)[FOLD_RESET]?.();\n if (count > 0) this._arm_all();\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 input - Stream names to unblock, or a {@link StreamFilter} for bulk recovery\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._arm_all();\n return count;\n });\n }\n\n /**\n * Atomically wipe the store and rebuild it from an event source. The\n * framework owns iteration, validation, `drop_snapshots` filtering,\n * `on_progress`, and the per-call `old → new` causation remap; the\n * adapter's {@link Store.restore} driver supplies the transaction\n * 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 - Any {@link EventSource}: a `CsvFile` backup or\n * another store. Read in batches rather than buffered, so\n * multi-million-event backups don't OOM. Each event's original `id`\n * is used as a causation lookup key but never written through —\n * 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 * @param sink - Where the events land. Defaults to this Act's store.\n * @returns {@link ScanResult} with `kept`, `duration_ms`, and\n * `dropped` per-category counters.\n *\n * @example Restore a CSV backup into the connected store\n * ```typescript\n * const result = await app.restore(new CsvFile({ path: \"./backup.csv\" }));\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: count what a restore would land, touching no sink.\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 this Act's store.\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 migrated = 0;\n let dropped = { closed_streams: 0, snapshots: 0 };\n await target.restore(async (callback) => {\n const partial = await scan(source, opts, callback);\n kept = partial.kept;\n migrated = partial.migrated;\n dropped = partial.dropped;\n });\n // Restoring into this app's own store replaced its log (new ids, no\n // subscription rows): restart correlation from cold and arm the drain.\n if (!sink) {\n this._correlate.restart();\n this._arm_all();\n }\n return { kept, migrated, 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.\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 async *audit(\n categories?: AuditCategory[],\n options?: AuditOptions\n ): AsyncIterable<AuditFinding> {\n // Step the generator inside `_scoped`: its body runs lazily in the\n // consumer's frame, which would otherwise resolve the wrong store.\n const it = audit(this._audit_deps, categories, options)[\n Symbol.asyncIterator\n ]();\n while (true) {\n const { value, done } = await this._scoped(() => it.next());\n if (done) break;\n yield value;\n }\n }\n\n /**\n * Bulk-update scheduling priority for streams matching `filter`.\n *\n * Operator-grade override of the `claim()` lagging-frontier\n * ordering. 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 * @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 /** Shared by `close()` and reaction-requested closes. */\n private async _run_close(targets: CloseTarget[]): Promise<CloseResult> {\n const close_actor = { id: \"$close\", name: \"close\" };\n const result = await run_close_cycle(targets, {\n reactive: this._reactive,\n catch_up_correlation: (until) =>\n catch_up_correlation(\n this._correlate,\n (limit) => this.correlate({ limit }),\n until\n ),\n event_to_state: this._event_to_state,\n load: this._es.load,\n tombstone: this._es.tombstone,\n logger: this._logger,\n correlation: close_correlation(this._correlator, close_actor),\n with_stream_lock: (stream, work) => this._close_lock.run(stream, work),\n forget_subscribed: (streams) =>\n this._correlate.forget_subscribed(streams),\n });\n this.emit(\"closed\", result);\n return result;\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 * Targets carrying `before` take the **windowed** branch instead —\n * close the books on a rolling window: probe the min consumer\n * watermark (so the boundary never rises past a lagging reaction),\n * run the archive callback against the cutoff, then prune the prefix\n * below the closest safe `__snapshot__`. No tombstone guard (the\n * pre-cutoff prefix is immutable), no seed, cache untouched — the\n * stream stays live and keeps accepting actions. Requires the state\n * to snapshot via `.snap(...)`; no qualifying snapshot ⇒ the stream\n * lands in `skipped` (retry after the next snapshot). Windowed\n * entries in the result echo `before` and carry the surviving\n * boundary snapshot as `committed`.\n *\n * @param targets - Per-stream close options (stream, restart?, archive?, before?)\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 async close(targets: CloseTarget[]): Promise<CloseResult> {\n if (!targets.length) return { truncated: new Map(), skipped: [] };\n\n return this._scoped(() => this._run_close(targets));\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 events read, no streams leased —\n * 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 // Validate the runtime knobs before anything runs (a bad debounceMs /\n // leaseMillis / maxPasses throws ZodError here, not on the first pass).\n resolveSettleConfig(options);\n // Writer-only instances skip settle.\n if (!this._drain) return;\n this._settle.schedule(options);\n }\n}\n","/**\n * @module build-classify\n * @category Internal\n *\n * Build-time classification of the registry + state map. The Act constructor\n * needs three pre-computed inputs to wire its runtime subsystems:\n *\n * - `static_targets` — known-up-front reaction targets, subscribed once\n * at init (correlate marks them from then on)\n * - `event_to_state` — event-name → owning state, for `close({restart})`\n * seed loading in multi-state apps\n * - `event_to_lanes` — event-name → the lanes its reactions run on, for\n * selective arming; its keys are exactly the events\n * that have a reaction\n *\n * Pure function — single pass over events + states, fully testable without\n * instantiating Act.\n *\n * @internal\n */\n\nimport type { StaticTarget } from \"../internal/index.js\";\nimport type {\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\n\n/**\n * Classification result. Returned by {@link classify_registry}; 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. 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 static_targets: StaticTarget[];\n readonly event_to_state: ReadonlyMap<string, State<any, any, any>>;\n readonly event_to_lanes: ReadonlyMap<string, EventLaneSet>;\n};\n\n/**\n * Walk the registry once to collect static reaction targets, the set of\n * reactive event names, the per-event lane fan-in, 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 classify_registry<\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 // Per-target lane, checked across EVERY reaction to a target regardless of\n // source. A stream drains on exactly one lane, and `subscribe`\n // keys lane per-target, so lane must agree target-wide — the\n // `(target, source)` scoping of `statics` is too narrow to catch a\n // same-target/different-source lane disagreement.\n const target_lanes = new Map<string, string>();\n const event_to_lanes = new Map<string, EventLaneSet>();\n\n for (const [name, register] of Object.entries(registry.events)) {\n for (const reaction of register.reactions.values()) {\n if (typeof reaction.resolver === \"function\") {\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 event_to_lanes.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 = event_to_lanes.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 event_to_lanes.set(name, set);\n }\n // Lanes don't merge — any two reactions to the\n // same target must declare the same lane, regardless of source.\n // First reaction to a target records its lane; every later one must\n // match or it's a config error caught at build time. Both sides\n // compare the NORMALIZED name, so an omitted lane and an\n // explicit \"default\" — the same lane — agree.\n const recorded_lane = target_lanes.get(target);\n if (recorded_lane === undefined) {\n target_lanes.set(target, lane_name);\n } else if (recorded_lane !== lane_name) {\n throw new Error(\n `Stream \"${target}\" has conflicting lane assignments ` +\n `(\"${recorded_lane}\" vs \"${lane_name}\")`\n );\n }\n // Keyed by target alone, because a subscription row IS keyed by\n // stream: every adapter sets `source` once at creation and ignores\n // it thereafter, so a second entry for one target could only ever\n // contribute its priority — and a batch carrying two would leave\n // the merge to the adapter, which a single batched SQL statement\n // cannot do. One entry per stream, max priority, so the\n // highest-priority registrant sets the scheduling priority.\n const existing = statics.get(target);\n if (!existing) {\n statics.set(target, { stream: target, source, priority, lane });\n } else if (priority > (existing.priority as number)) {\n // `existing.priority` is always defined here since we always set\n // it when inserting, but the StaticTarget type marks it optional\n // for external consumers.\n statics.set(target, { ...existing, priority });\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 event_to_state = new Map<string, State<any, any, any>>();\n for (const merged of states.values()) {\n for (const event_name of Object.keys(merged.events)) {\n event_to_state.set(event_name, merged);\n }\n }\n\n return {\n static_targets: [...statics.values()],\n event_to_state,\n event_to_lanes,\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.\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 deprecated_event_names(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 // Two names mapping to the same numeric version (e.g. a leading-zero\n // `Foo_v02` alongside `Foo_v2`) can't both be a distinct version — one\n // is a typo. Left unguarded, the sort below would flag whichever lands\n // second, so declaration order would decide which one is \"current\",\n // and the real current event could be marked deprecated (a static\n // `.emit(...)` on it would then throw at build). Reject the collision\n // with a clear, order-independent error instead.\n const by_version = new Map<number, string>();\n for (const { version, name } of list) {\n const clash = by_version.get(version);\n if (clash)\n throw new Error(\n `duplicate event version: ${clash} and ${name} both map to version ${version} — ` +\n \"leading zeros in a `_v<n>` suffix are not allowed; use a single canonical spelling\"\n );\n by_version.set(version, name);\n }\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 current_version_of(\n deprecated_name: string,\n all_names: Iterable<string>\n): string | undefined {\n const target = parse(deprecated_name);\n let highest: Versioned | undefined;\n for (const name of all_names) {\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","import type { QueryStreams, Store, StreamPosition } from \"../types/index.js\";\n\n/** Streams read per page when walking the whole table. */\nconst DEFAULT_STREAM_PAGE = 500;\n\n/**\n * Walks EVERY stream matching `query`, paging with the keyset cursor.\n *\n * `Store.query_streams` defaults to `limit: 100`, so a caller that wants\n * the whole table must page — passing no query silently truncates at the\n * first page, which is a false all-clear for anything that reports on\n * what it found.\n *\n * The cursor is the last stream name the callback saw; results are\n * ordered by stream name, so a short page means the walk is done.\n *\n * @param store - Store to walk.\n * @param callback - Invoked once per matching position, in name order.\n * @param query - Optional filter. A caller-supplied `limit` sets the page\n * size (the walk still visits every match); `after` seeds the cursor.\n * @returns The total number of positions emitted.\n *\n * @internal\n */\nexport async function walk_streams(\n store: Store,\n callback: (position: StreamPosition) => void,\n query?: Omit<QueryStreams, \"after\" | \"limit\"> & {\n after?: string;\n limit?: number;\n }\n): Promise<number> {\n const page_size = query?.limit ?? DEFAULT_STREAM_PAGE;\n let after = query?.after;\n let total = 0;\n for (;;) {\n let last: string | undefined;\n const { count } = await store.query_streams(\n (position) => {\n last = position.stream;\n callback(position);\n },\n { ...query, after, limit: page_size }\n );\n total += count;\n if (count < page_size) return total;\n after = last;\n }\n}\n","/**\n * Operator-driven store audit. Each category is an {@link AuditPass}; the\n * dispatcher runs each needed scan once and broadcasts rows to every pass,\n * so an audit costs at most three scans. Reads only {@link AuditDeps} and\n * the public `Store`, never orchestration internals.\n */\n\nimport { SNAP_EVENT } from \"../ports.js\";\nimport type {\n AuditCategory,\n AuditFinding,\n AuditOptions,\n Committed,\n Query,\n Schemas,\n State,\n Store,\n StreamPosition,\n StreamStats,\n} from \"../types/index.js\";\nimport {\n current_version_of,\n deprecated_event_names,\n} from \"./event-versions.js\";\nimport { pii_fields } from \"./sensitive.js\";\nimport { walk_streams } from \"./walk-streams.js\";\n\n/** The orchestrator state the audit reads, built once at `build()`. */\nexport type AuditDeps = {\n readonly store: () => Store;\n /** event-name → state that registers it (for schema validation). */\n readonly event_to_state: ReadonlyMap<string, State<any, any, any>>;\n /** Declared drain lanes (for routing-health unknown-lane). */\n readonly declared_lanes: ReadonlySet<string>;\n /** Event names with at least one reaction (routing-health `unrouted`). */\n readonly routed_events: ReadonlySet<string>;\n};\n\n/** Defaults for {@link AuditOptions.thresholds}. */\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 \"unreadable-events\",\n] as const satisfies readonly AuditCategory[];\n\n/**\n * One audit category. Which `on_*` callbacks it has decides which shared\n * scans run; `finalize` does targeted follow-up reads; `drain` returns\n * the findings.\n */\ntype AuditPass = {\n category: AuditCategory;\n on_event?: (e: Committed<Schemas, string>) => void;\n on_unreadable?: (row: UnreadableRow) => void;\n on_stream?: (p: StreamPosition) => void;\n on_stat?: (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/** Scans finish before the first yield; bound the work with `options.query`. */\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 // Declaration order, not the caller's.\n const ordered_categories = ALL_CATEGORIES.filter((c) => requested.has(c));\n const passes: AuditPass[] = ordered_categories.map((c) =>\n PASS_FACTORIES[c](deps, options)\n );\n\n const need_stats = passes.some((p) => p.on_stat !== undefined);\n const need_streams = passes.some((p) => p.on_stream !== undefined);\n const need_events = passes.some(\n (p) => p.on_event !== undefined || p.on_unreadable !== undefined\n );\n\n if (need_stats) {\n // Exclude `__snapshot__` so head and count are domain figures; keep\n // `__tombstone__`, which is how a closed stream is recognized.\n const stats = await deps\n .store()\n .query_stats<Schemas>(\n {},\n { count: true, names: true, exclude: [SNAP_EVENT] }\n );\n for (const [stream, s] of stats) {\n for (const p of passes) p.on_stat?.(stream, s);\n }\n }\n\n if (need_streams) {\n // Paged: `query_streams` defaults to 100 rows.\n await walk_streams(deps.store(), (pos) => {\n for (const p of passes) p.on_stream?.(pos);\n });\n }\n\n if (need_events) {\n await scan_events_resiliently(\n deps,\n options.query,\n (event) => {\n for (const p of passes) p.on_event?.(event);\n },\n (row) => {\n for (const p of passes) p.on_unreadable?.(row);\n }\n );\n }\n\n // Serial to avoid pool contention.\n for (const p of passes) await p.finalize?.(deps);\n\n for (const p of passes) {\n for (const f of p.drain()) yield f;\n }\n}\n\n/**\n * A row the store couldn't hand back, located by re-reading it without its\n * payload (`with_pii: false`), which can't fail.\n */\ntype UnreadableRow = {\n stream: string;\n event_id: number;\n error: unknown;\n};\n\n/**\n * Run the event scan so one unreadable row doesn't end it: locate the row\n * it stopped at, report it, and resume past it with the remaining `limit`.\n * Backward scans can't resume, so they rethrow.\n */\nasync function scan_events_resiliently(\n deps: AuditDeps,\n query: Query | undefined,\n on_event: (e: Committed<Schemas, string>) => void,\n on_unreadable: (row: UnreadableRow) => void\n): Promise<void> {\n let cursor = query?.after;\n let remaining = query?.limit;\n for (;;) {\n let seen = 0;\n try {\n await deps.store().query<Schemas>(\n (event) => {\n seen++;\n cursor = event.id;\n on_event(event);\n },\n {\n ...query,\n after: cursor,\n ...(remaining !== undefined && { limit: remaining }),\n }\n );\n return;\n } catch (error) {\n if (query?.backward) throw error;\n let row: UnreadableRow | undefined;\n await deps.store().query<Schemas>(\n (e) => {\n row = { stream: e.stream, event_id: e.id, error };\n },\n { ...query, after: cursor, limit: 1, with_pii: false }\n );\n // Not one unreadable row (a dropped connection, a timeout): rethrow.\n if (!row) throw error;\n on_unreadable(row);\n // The tripping row is never delivered, so `seen` is at most\n // `remaining - 1` and the resumed budget stays at 1 or more.\n if (remaining !== undefined) remaining -= seen;\n cursor = row.event_id;\n }\n }\n}\n\n// =================== Pass factories ===================\n\nconst make_schema_pass: PassFactory = (deps) => {\n const findings: AuditFinding[] = [];\n return {\n category: \"schema\",\n on_event(event) {\n const name = String(event.name);\n const state = deps.event_to_state.get(name);\n if (!state) {\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 // `sensitive()` keys live in the pii sidecar, so omit them from the parse.\n const sensitive = pii_fields(schema);\n let parse_schema = schema;\n if (sensitive.length > 0) {\n const omitter = (\n schema as unknown as {\n omit?: (mask: Record<string, true>) => typeof schema;\n }\n ).omit;\n if (typeof omitter !== \"function\") {\n // A non-object schema with pii can't be masked; any parse is a false positive.\n return;\n }\n parse_schema = omitter.call(\n schema,\n Object.fromEntries(sensitive.map((f) => [f, true as const]))\n );\n }\n const parsed = parse_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/** Deprecated event name → its current sibling, within one state only. */\nconst classify_deprecated_by_state = (\n deps: AuditDeps\n): ReadonlyMap<string, string> => {\n const names_by_state = new Map<State<any, any, any>, Set<string>>();\n for (const [name, state] of deps.event_to_state) {\n let set = names_by_state.get(state);\n if (!set) {\n set = new Set();\n names_by_state.set(state, set);\n }\n set.add(name);\n }\n const deprecated_to_current = new Map<string, string>();\n for (const names of names_by_state.values()) {\n for (const name of deprecated_event_names(names)) {\n deprecated_to_current.set(name, current_version_of(name, names)!);\n }\n }\n return deprecated_to_current;\n};\n\nconst make_deprecated_load_pass: PassFactory = (deps, options) => {\n const share_min =\n options.thresholds?.deprecated_min ?? DEFAULTS.deprecated_min;\n const totals = new Map<string, number>();\n const per_stream = new Map<string, Map<string, number>>();\n return {\n category: \"deprecated-load\",\n on_stat(stream, { names }) {\n for (const [name, count] of Object.entries(names!)) {\n totals.set(name, (totals.get(name) ?? 0) + count!);\n let m = per_stream.get(name);\n if (!m) {\n m = new Map();\n per_stream.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 const deprecated = classify_deprecated_by_state(deps);\n const sorted = [...deprecated.keys()]\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 const current_version = deprecated.get(name)!;\n const top_streams = [...per_stream.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,\n total: count,\n top_streams,\n });\n }\n return findings;\n },\n };\n};\n\nconst make_close_candidate_pass: 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 on_stat(stream, { head }) {\n const head_name = String(head.name);\n if (head_name.startsWith(\"__\")) return; // already-closed or mid-truncate\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: restart_is_supported(deps, head_name),\n });\n },\n drain: () => findings,\n };\n};\n\nconst make_restart_candidate_pass: PassFactory = (deps, options) => {\n const threshold = options.thresholds?.restart_min ?? DEFAULTS.restart_min;\n // Snapshot counts are resolved in finalize: the shared stat scan excludes\n // `__snapshot__`, and only a handful of candidates need them.\n const candidates: Array<{ stream: string; count: number }> = [];\n const findings: AuditFinding[] = [];\n return {\n category: \"restart-candidate\",\n on_stat(stream, { head, count }) {\n if (count! < threshold) return;\n const head_name = String(head.name);\n if (head_name.startsWith(\"__\")) return;\n if (!restart_is_supported(deps, head_name)) return;\n candidates.push({ stream, count: count! });\n },\n async finalize(deps) {\n for (const { stream, count } of candidates) {\n let snaps = 0;\n await deps.store().query(\n () => {\n snaps++;\n },\n {\n stream,\n stream_exact: true,\n names: [SNAP_EVENT],\n with_snaps: true,\n }\n );\n findings.push({\n category: \"restart-candidate\",\n stream,\n count,\n snaps,\n });\n }\n },\n drain: () => findings,\n };\n};\n\nconst make_reaction_health_pass: 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 on_stream(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\nconst make_snapshot_drift_pass: PassFactory = (deps, options) => {\n const drift_min = options.thresholds?.drift_min ?? DEFAULTS.drift_min;\n const candidates: Array<{\n stream: string;\n total: number;\n }> = [];\n const findings: AuditFinding[] = [];\n return {\n category: \"snapshot-drift\",\n on_stat(stream, { head, count }) {\n // Also rejects framework markers, which no user state declares.\n if (!restart_is_supported(deps, String(head.name))) return;\n if (count! < drift_min) return; // upper-bound short-circuit\n candidates.push({\n stream,\n total: count!,\n });\n },\n async finalize(deps) {\n for (const { stream, total } of candidates) {\n let events_since_snap = total;\n let snap_at: number | undefined;\n // The shared stat scan excludes `__snapshot__`, so look it up here.\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 if (collected.length > 0) {\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\nconst make_routing_health_pass: PassFactory = (deps) => {\n const findings: AuditFinding[] = [];\n const seen_event_names = new Set<string>();\n return {\n category: \"routing-health\",\n on_stream(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 on_stat(_stream, { names }) {\n for (const name of Object.keys(names!)) {\n seen_event_names.add(name);\n }\n },\n finalize() {\n for (const name of seen_event_names) {\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\nconst make_correlation_gaps_pass: PassFactory = () => {\n const seen_ids = new Set<number>();\n const checks: Array<{ stream: string; id: number; parent_id: number }> = [];\n return {\n category: \"correlation-gaps\",\n on_event(e) {\n seen_ids.add(e.id);\n const causation = (e.meta as Record<string, unknown> | undefined)\n ?.causation as { event?: { id?: number } } | undefined;\n const parent_id = causation?.event?.id;\n if (parent_id !== undefined) {\n checks.push({ stream: e.stream, id: e.id, parent_id });\n }\n },\n drain() {\n const findings: AuditFinding[] = [];\n for (const { stream, id, parent_id } of checks) {\n if (!seen_ids.has(parent_id)) {\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\nconst make_clock_anomalies_pass: PassFactory = () => {\n const findings: AuditFinding[] = [];\n const last_per_stream = new Map<string, number>();\n return {\n category: \"clock-anomalies\",\n on_event(e) {\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 = last_per_stream.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 last_per_stream.set(e.stream, created);\n },\n drain: () => findings,\n };\n};\n\nfunction restart_is_supported(\n deps: AuditDeps,\n head_event_name: string\n): boolean {\n const state = deps.event_to_state.get(head_event_name);\n return state?.snap !== undefined;\n}\n\n/** Fed by the dispatcher with rows the event scan tripped on; never reaches `on_event`. */\nfunction make_unreadable_events_pass(): AuditPass {\n const findings: AuditFinding[] = [];\n return {\n category: \"unreadable-events\",\n on_unreadable({ stream, event_id, error }) {\n findings.push({\n category: \"unreadable-events\",\n stream,\n event_id,\n reason: \"pii_decrypt_failed\",\n error,\n });\n },\n drain: () => findings,\n };\n}\n\nconst PASS_FACTORIES: Record<AuditCategory, PassFactory> = {\n schema: make_schema_pass,\n \"deprecated-load\": make_deprecated_load_pass,\n \"close-candidate\": make_close_candidate_pass,\n \"restart-candidate\": make_restart_candidate_pass,\n \"reaction-health\": make_reaction_health_pass,\n \"snapshot-drift\": make_snapshot_drift_pass,\n \"routing-health\": make_routing_health_pass,\n \"correlation-gaps\": make_correlation_gaps_pass,\n \"clock-anomalies\": make_clock_anomalies_pass,\n \"unreadable-events\": make_unreadable_events_pass,\n};\n","/**\n * @module autoclose-policy\n * @category Internal\n *\n * Declarative close-policy options consumed by `.autocloses({...})`\n * Three optional fields cover the three\n * operational pressure points every real close policy traces back to:\n *\n * - `after` — time / compliance (\"autocloses **after** N days\")\n * - `is` — domain lifecycle (\"autocloses ... **is** Resolved\")\n * - `reaches` — resource (\"autocloses ... **reaches** 10k events\")\n *\n * Top-level fields combine with **AND** semantics. This captures the\n * common cooldown-after-terminal pattern that runs through almost\n * every business app — *\"close 90 days after `Resolved`\"*, *\"close 14\n * days after `Delivered`\"*, *\"close 30 days after a GDPR deletion\n * request\"*. All conditions must hold for the cycle to truncate.\n *\n * A separate `or: {...}` block opens an alternative path: when\n * present, the policy fires if **either** the top-level AND group\n * matches **or** any field inside `or` matches. Use it for safety\n * nets — *\"close (Resolved AND aged 90 days) OR if event count\n * reaches 10k\"*. The two-axis split mirrors the two ways close\n * policies appear in practice: primary close logic (AND-shaped) and\n * defensive backstops (OR-shaped).\n *\n * The state builder's `.autocloses(...)` overload distinguishes\n * function (predicate) from object (policy) and routes the latter\n * through {@link compile_autoclose_policy}, which validates via\n * {@link AutoclosePolicySchema} and returns the compiled predicate.\n * Operators with custom needs (per-stream metadata, multi-branch\n * AND/OR like \"(`Resolved` + 90d) OR (`Cancelled` + 30d)\") keep the\n * function form; the declarative form covers the 90% case.\n *\n * Validation runs at the builder call (`act().build()` time), so\n * misconfiguration — empty bag, sub-1 `reaches`, sub-minute `after`,\n * empty `is`, empty `or`, nested `or` inside `or`, unknown keys —\n * throws at build, not on the first cycle tick.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { AutoclosePredicate, Schemas } from \"../types/action.js\";\n\n/**\n * One day in epoch milliseconds. The close surface is day-denominated\n * throughout — policies declare `{ days }`, the State carries\n * `autoclose_*_days`, and the reaction thinks in day offsets. This\n * constant (with {@link days_after} / {@link days_before_now}) is the\n * single place the closing process touches epoch arithmetic, because\n * `Date` itself has no other currency.\n */\nconst DAY_MS = 86_400_000;\n\n/**\n * Lower bound on a resolved `after` window: one minute, expressed in\n * days. Sub-minute cooldowns are almost always misconfiguration.\n * Rejecting at build keeps the failure mode noisy.\n */\nconst MIN_AFTER_DAYS = 1 / 1440;\n\n/**\n * Lower bound on a resolved `keep` window: one full day. The close\n * cycle is low-cadence, non-priority housekeeping — a rolling window\n * shorter than a day signals misconfiguration. Real retention\n * contracts (180 days, 7 years) are days and up.\n */\nconst MIN_KEEP_DAYS = 1;\n\n/** The `Date` that lies `days` after `date`. @internal */\nexport function days_after(date: Date, days: number): Date {\n return new Date(date.getTime() + days * DAY_MS);\n}\n\n/** The `Date` that lies `days` in the past. @internal */\nexport function days_before_now(days: number): Date {\n return new Date(Date.now() - days * DAY_MS);\n}\n\n/**\n * Day-denominated window shared by `after` (terminate cooldown) and\n * `keep` (rolling retention). Fractional days accepted; windows below\n * the field's floor reject at build.\n *\n * @internal\n */\nconst window_schema = (\n field: \"after\" | \"keep\",\n min_days: number,\n floor: string\n) =>\n z\n .object({\n days: z\n .number({ message: `autocloses: ${field}.days must be a number` })\n .positive(`autocloses: ${field}.days must be > 0`),\n })\n .refine((o) => o.days >= min_days, {\n message: `autocloses: ${field} resolves to < ${floor}, which is too short to be a meaningful retention window`,\n });\n\nconst AfterSchema = window_schema(\"after\", MIN_AFTER_DAYS, \"one minute\");\n\nconst KeepSchema = window_schema(\"keep\", MIN_KEEP_DAYS, \"one day\");\n\nconst IsSchema = z.union([\n z.string().min(1, \"autocloses: is must be a non-empty event name\"),\n z\n .array(\n z.string().min(1, \"autocloses: is entries must be non-empty event names\")\n )\n .min(1, \"autocloses: is must include at least one event name\")\n .readonly(),\n]);\n\nconst ReachesSchema = z\n .number({ message: \"autocloses: reaches must be a number\" })\n .int(\"autocloses: reaches must be an integer\")\n .min(1, \"autocloses: reaches must be >= 1\");\n\n/**\n * Schema for the `or: {...}` block — the OR-shaped alternative path.\n * Same field set as the top-level policy minus `or` itself (so nested\n * `or` inside `or` rejects via `.strict()` instead of recursing). At\n * least one field required; empty `{}` is a misconfiguration.\n *\n * @internal\n */\nconst OrBlockSchema = z\n .object({\n after: AfterSchema.optional(),\n is: IsSchema.optional(),\n reaches: ReachesSchema.optional(),\n })\n .strict()\n .refine(\n (o) =>\n o.after !== undefined || o.is !== undefined || o.reaches !== undefined,\n {\n message:\n \"autocloses: `or` block must include at least one of after / is / reaches\",\n }\n );\n\n/**\n * Zod schema for the declarative {@link AutoclosePolicy} bag.\n * Internal `const` per the config-validation-schema standard (CLAUDE.md\n * \"Config-validation schemas\") — the public surface is the inferred\n * {@link AutoclosePolicy} type and the `.autocloses({...})` overload,\n * never this schema. `.strict()` rejects unknown keys so typos surface\n * at build instead of being silently ignored.\n *\n * @internal\n */\nconst AutoclosePolicySchema = z\n .object({\n after: AfterSchema.optional(),\n is: IsSchema.optional(),\n reaches: ReachesSchema.optional(),\n or: OrBlockSchema.optional(),\n keep: KeepSchema.optional(),\n })\n .strict()\n .refine(\n (o) =>\n o.after !== undefined ||\n o.is !== undefined ||\n o.reaches !== undefined ||\n o.or !== undefined ||\n o.keep !== undefined,\n {\n message:\n \"autocloses: at least one of after / is / reaches / or / keep must be specified — empty `{}` is a misconfiguration\",\n }\n );\n\n/**\n * Declarative close-policy options consumed by `.autocloses({...})`.\n * Top-level fields are AND-combined; the optional `or` block opens an\n * alternative OR-path. Omitted fields contribute nothing — they do\n * not mean \"match everything.\"\n *\n * @property after - Close when `head.created` is at least the resolved\n * window in the past. Days are the close surface's only unit;\n * fractional `days` cover sub-day cooldowns (`{ days: 1/24 }` is one\n * hour) without introducing another denomination.\n * @property is - Close when `head.name` matches. String for the\n * single-terminal-event case (the most common); `readonly string[]`\n * for multi-terminal states (`Order: Shipped | Delivered |\n * Cancelled`).\n * @property reaches - Close when the stream's event count is `>= N`\n * (inclusive — fires the moment the threshold is reached).\n * @property or - Alternative OR-path. When present, the policy fires\n * if EITHER the top-level AND group matches OR any field inside\n * `or` matches. Used for safety-net backstops layered onto a\n * primary cooldown policy (e.g. *\"(Resolved AND 90 days) OR reaches\n * 10k\"*). Nested `or` inside `or` rejects at build time.\n * @property keep - Rolling-window retention, **independent** of\n * the terminate fields: while the stream stays open, prune events\n * older than `now − keep` behind the closest safe snapshot via a\n * windowed close. Does not participate in the AND group or the `or`\n * block — a policy may terminate, prune, or both. Requires\n * `.snap(...)` earlier in the builder chain (type-gated) and a\n * window of at least one day — the close cycle is low-cadence\n * housekeeping, never sub-day realtime.\n */\nexport type AutoclosePolicy = z.infer<typeof AutoclosePolicySchema>;\n\n/** Compile a single `after` field into its predicate slice. @internal */\nfunction compile_after(\n after: NonNullable<AutoclosePolicy[\"after\"]>\n): AutoclosePredicate<Schemas> {\n return (_stream, head) => days_after(head.created, after.days) <= new Date();\n}\n\n/** Compile a single `is` field into its predicate slice. @internal */\nfunction compile_is(\n is: NonNullable<AutoclosePolicy[\"is\"]>\n): AutoclosePredicate<Schemas> {\n const set = new Set(typeof is === \"string\" ? [is] : is);\n return (_stream, head) => set.has(head.name as string);\n}\n\n/** Compile a single `reaches` field into its predicate slice. @internal */\nfunction compile_reaches(\n reaches: NonNullable<AutoclosePolicy[\"reaches\"]>\n): AutoclosePredicate<Schemas> {\n return (_stream, _head, count) => count >= reaches;\n}\n\n/**\n * Compile a declarative {@link AutoclosePolicy} into an\n * {@link AutoclosePredicate}. The state-builder's\n * `.autocloses({...})` overload calls this; tests can also build a\n * state and read `state.autoclose` to grab the compiled predicate.\n *\n * Returned predicate fires when either:\n *\n * 1. **All** top-level non-`or` fields match (AND), or\n * 2. **Any** field inside the `or` block matches.\n *\n * Top-level with zero non-`or` fields never satisfies path (1) — the\n * `every` check on an empty list is short-circuited to `false` so the\n * policy doesn't truncate the entire universe on an `or`-only\n * declaration. (Validation rejects all-empty bags up front; this guard\n * is the in-cycle equivalent for the synthesized empty AND-group.)\n *\n * Assignable to any `AutoclosePredicate<TEvents>` slot via\n * function-parameter contravariance — the returned predicate inspects\n * `head.name` as a plain string, so narrower event unions stay\n * assignable.\n *\n * Throws `ZodError` at call time when the options are invalid (empty\n * bag, non-positive `reaches`, sub-minute `after`, empty `is`, empty\n * `or`, nested `or`, unknown keys).\n *\n * @internal\n */\n/**\n * The smallest `after` window (in days) anywhere in a policy — across\n * the top-level `after` and the `or.after` block — or `undefined` when\n * the policy has no time component.\n *\n * The synthesized autoclose reaction uses this to decide how to\n * wait: a policy with an `after` defers its re-check to `head.created`\n * plus this many days (the earliest its time gate could open); a policy\n * without one (`is` / `reaches` only) has no time gate, so the reaction\n * just waits for the next event to re-trigger rather than parking on a\n * due-time. Conservative — the min across branches never defers past\n * the soonest a branch could fire.\n *\n * @internal\n */\nexport function policy_min_after_days(\n options: AutoclosePolicy\n): number | undefined {\n const parsed = AutoclosePolicySchema.parse(options);\n const windows: number[] = [];\n if (parsed.after) windows.push(parsed.after.days);\n if (parsed.or?.after) windows.push(parsed.or.after.days);\n return windows.length ? Math.min(...windows) : undefined;\n}\n\n/**\n * The rolling-window width (in days) of a policy's `keep` field, or\n * `undefined` when the policy declares no rolling window. The\n * synthesized autoclose reaction prunes the prefix older than the\n * window (via a windowed close) and derives its prune due-time as\n * `tail.created` plus this many days — the earliest the oldest\n * surviving domain event can age out of the window.\n *\n * @internal\n */\nexport function policy_keep_days(options: AutoclosePolicy): number | undefined {\n const parsed = AutoclosePolicySchema.parse(options);\n return parsed.keep?.days;\n}\n\nexport function compile_autoclose_policy(\n options: AutoclosePolicy\n): AutoclosePredicate<Schemas> {\n const parsed = AutoclosePolicySchema.parse(options);\n\n // Top-level AND group — only the non-`or` fields.\n const and_preds: AutoclosePredicate<Schemas>[] = [];\n if (parsed.after) and_preds.push(compile_after(parsed.after));\n if (parsed.is) and_preds.push(compile_is(parsed.is));\n if (parsed.reaches) and_preds.push(compile_reaches(parsed.reaches));\n\n // OR-block — at least one of its fields must match.\n const or_preds: AutoclosePredicate<Schemas>[] = [];\n if (parsed.or) {\n if (parsed.or.after) or_preds.push(compile_after(parsed.or.after));\n if (parsed.or.is) or_preds.push(compile_is(parsed.or.is));\n if (parsed.or.reaches) or_preds.push(compile_reaches(parsed.or.reaches));\n }\n\n return (stream, head, count) => {\n // AND path: every top-level field matches AND the group is non-empty\n // (an `or`-only declaration leaves `and_preds` empty — that\n // shouldn't auto-fire).\n if (\n and_preds.length > 0 &&\n and_preds.every((p) => p(stream, head, count))\n ) {\n return true;\n }\n // OR path: any `or`-block field matches.\n if (or_preds.some((p) => p(stream, head, count))) {\n return true;\n }\n return false;\n };\n}\n","/**\n * @module autoclose-window\n * @category Internal\n *\n * Off-hours window math for autoclose — hour-in-zone, DST-gap handling, and\n * \"next time the window opens\". The autoclose **config** (defaults, schema,\n * resolver) lives in `./config.js`, the single home for builder-facing config\n * bags; this module is the runtime window logic those knobs drive.\n *\n * @internal\n */\n\nimport type { AutocloseConfig } from \"./config.js\";\n\n/**\n * The current hour `[0, 23]` in the given IANA time zone, DST-correct\n * via `Intl`. Split out so the window check can be unit-tested without\n * spinning a controller.\n *\n * @internal\n */\nexport function hour_in_zone(now: Date, timeZone: string): number {\n const parts = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour: \"2-digit\",\n hourCycle: \"h23\",\n }).formatToParts(now);\n return Number(parts.find((p) => p.type === \"hour\")?.value);\n}\n\n/**\n * True when a plain `[start, end)` hour comparison places `hour` inside\n * the window. Half-open on hour boundaries and wrapping past midnight\n * when `start > end`.\n *\n * @internal\n */\nfunction hour_in_range(hour: number, start: number, end: number): boolean {\n return start < end\n ? hour >= start && hour < end\n : hour >= start || hour < end;\n}\n\n/**\n * True when `now` is the instant a DST spring-forward gap skipped over\n * the window's `start` hour. On such a day the local `start` hour never\n * occurs — the clock jumps from `start - 1` straight past `start` — so a\n * plain hour comparison would report the window closed all day. The gap\n * surfaces as a one-hour boundary where the local hour jumps from below\n * `start` to above it; that boundary instant is the window's replacement\n * opening. Detected by comparing the hour at `now` with the hour one\n * hour earlier: a jump of more than one hour that steps over `start`.\n *\n * @internal\n */\nfunction is_dst_gap_open(now: Date, timeZone: string, start: number): boolean {\n const hour = hour_in_zone(now, timeZone);\n if (hour <= start) return false;\n const prev = hour_in_zone(new Date(now.getTime() - 3_600_000), timeZone);\n // A normal step advances one local hour; a spring-forward gap advances\n // two, skipping exactly one local hour. This instant is the gap opening\n // only when the skipped hour is the window's `start`: the previous hour\n // sits just below `start` and this hour just above it.\n return prev === start - 1 && hour === start + 1;\n}\n\n/**\n * Whether `now` falls inside the configured off-hours window. The\n * window is half-open on hour boundaries — `[start, end)` — and wraps\n * past midnight when `start > end`. With no window configured every\n * tick runs, so callers treat `undefined` as \"always in window.\"\n *\n * On a DST spring-forward day whose `start` hour is skipped, the window\n * would otherwise be closed for the whole day (the `start` hour never\n * occurs). The gap's replacement instant is admitted so autoclose still\n * runs — see {@link is_dst_gap_open}.\n *\n * @internal\n */\nexport function in_autoclose_window(\n window: AutocloseConfig[\"autocloseWindow\"],\n now: Date\n): boolean {\n if (!window) return true;\n const hour = hour_in_zone(now, window.timeZone);\n return (\n hour_in_range(hour, window.start, window.end) ||\n is_dst_gap_open(now, window.timeZone, window.start)\n );\n}\n\n/**\n * The next instant the off-hours window opens at or after `now`. The\n * synthesized autoclose reaction defers to this when a tick lands\n * outside the window — parking until the window actually opens instead\n * of blind-polling on a configured cadence (the old behavior,\n * where a poll interval longer than the window could oscillate around\n * it and miss it repeatedly).\n *\n * Walks forward hour by hour and asks `Intl` for the local hour at each\n * step, so DST transitions resolve exactly the way the runtime's zone\n * database says they do — a 23- or 25-hour day never desynchronizes the\n * walk. The window validates as non-empty at build, and every zone hits\n * each `[0, 23]` hour label within any 48-hour span, so the walk always\n * terminates; the bound is a defensive backstop, with \"one day out\" as\n * the fallback no real zone can reach.\n *\n * Minute/second offsets within the opening hour are preserved from\n * `now` shifted by whole hours — the contract is hour-granular, matching\n * the window's own `[start, end)` hour semantics.\n *\n * On a DST spring-forward day whose `start` hour is skipped, the `start`\n * hour never occurs, so the minute-preserving walk would never match and\n * the window would defer ~24 h. The walk also checks each hour-aligned\n * boundary for the gap opening (see {@link is_dst_gap_open}) and returns\n * that boundary instant — deferring ~1 h to the replacement instant\n * rather than a full day. The boundary is returned as-is (no minute\n * offset): the gap opening is a single transition instant, not a range.\n *\n * @internal\n */\nexport function next_window_open(\n window: NonNullable<AutocloseConfig[\"autocloseWindow\"]>,\n now: Date\n): Date {\n const start_ms = now.getTime();\n for (let h = 0; h <= 48; h++) {\n const candidate = new Date(start_ms + h * 3_600_000);\n if (hour_in_zone(candidate, window.timeZone) === window.start)\n return candidate;\n // The `start` hour may be unreachable on a spring-forward day; catch\n // the gap boundary at the top of this candidate's hour. The boundary is\n // UTC-hour aligned, so in a fractional-offset zone the first one can sit\n // behind `now` — a past due is never excluded by claim, so skip it.\n const boundary = new Date(\n candidate.getTime() - (candidate.getTime() % 3_600_000)\n );\n if (\n boundary.getTime() >= start_ms &&\n is_dst_gap_open(boundary, window.timeZone, window.start)\n )\n return boundary;\n }\n return new Date(start_ms + 86_400_000);\n}\n","/**\n * @module close-signal\n * @category Internal\n *\n * The control-flow signal a reaction handler throws to *close* a stream.\n * Like {@link \"defer-signal\".DeferSignal} it rides the dispatcher's\n * `try/catch`, but where a defer holds the stream for later, a close asks the\n * orchestrator to retire it: `build_handle` turns the signal into a\n * `HandleResult.close` (a {@link CloseTarget}), `run_drain_cycle` acks the\n * triggering event and collects the target, and the `DrainController` hands it\n * to the orchestrator's `on_close` callback, which runs the same\n * `run_close_cycle` machinery as `app.close`.\n *\n * Internal: the compiled autoclose reaction throws it. Closing stays an\n * orchestrator capability — reactions only *signal* the intent, so the public\n * reaction-scoped `IAct` gains no `close`.\n *\n * The autoclose reaction runs on a **synthetic stream** (`source` = the\n * aggregate, `target` = a per-aggregate `__autoclose__` key) so it never\n * shares a watermark with the aggregate's own reactions. That makes the close\n * *target* distinct from the reaction's lease stream, so the signal carries the\n * stream to close explicitly (`stream`); when omitted (a user reaction closing\n * its own stream) it defaults to the lease stream.\n *\n * @internal\n */\nexport class CloseSignal extends Error {\n /**\n * Stream to close. Omitted → the reaction's own lease stream (a self-close).\n * The synthesized autoclose reaction sets it to the aggregate stream, since\n * its lease runs on a synthetic `__autoclose__` target.\n */\n readonly stream?: string;\n /** Optional archive callback to run while the stream is guarded. */\n readonly archive?: () => Promise<void>;\n /**\n * Watermark to ack the requesting reaction to before the close runs. The\n * close-cycle safety guard skips a stream whose subscriptions (matched by\n * source) lag the head; the autoclose reaction's `source` is the aggregate,\n * so it must advance its own watermark to the live head id it evaluated\n * against — otherwise it blocks its own close. Defaults to the triggering\n * event id when omitted.\n */\n readonly at?: number;\n /**\n * Windowed close: prune events older than this cutoff behind\n * the closest safe snapshot instead of retiring the stream. Thrown by\n * the autoclose reaction of a `.autocloses({ keep })` state; flows\n * into {@link CloseTarget.before}. Omitted → a full close.\n */\n readonly before?: Date;\n\n constructor(opts?: {\n stream?: string;\n archive?: () => Promise<void>;\n at?: number;\n before?: Date;\n }) {\n super(\"reaction requested close\");\n this.name = \"CloseSignal\";\n this.stream = opts?.stream;\n this.archive = opts?.archive;\n this.at = opts?.at;\n this.before = opts?.before;\n }\n}\n","/**\n * @module internal/config\n * @category Internal\n *\n * **The single home for every builder-facing config bag in act-core.** Any\n * options object an operator hands to `act().build()`, a builder method\n * (`.on(...)`, `.do(...)`, `.withLane(...)`), or a runtime cycle\n * (`drain(...)` / `settle(...)`) is validated here with Zod — never with a\n * hand-written `if (x < min) throw` ladder — so misconfiguration surfaces as\n * a `ZodError` at the entry point, not as `NaN` arithmetic on the first cycle\n * tick.\n *\n * Layout: one section per bag, each with its `DEFAULT_*` constants, an\n * internal `<Type>OptionsSchema`, an inferred `<Type>Config`, and a\n * `resolve<Type>Config(options): <Type>Config`. The schema is never\n * re-exported — the public surface is the inferred type + resolver.\n *\n * Index of bags owned here:\n * - **Backoff** — retry pacing (`BackoffOptions`), nested in reaction/action.\n * - **Reaction** — `.do(handler, options)` (`blockOnError` / `maxRetries` / `backoff`).\n * - **Action** — `.on(entry, options)` (`maxRetries` / `backoff`).\n * - **Lane** — `.withLane({...})` (`leaseMillis` / `streamLimit` / `cycleMs`).\n * - **Drain / Settle** — `drain(...)` / `settle(...)` runtime knobs.\n * - **Autoclose** — the `.autocloses` / `ActOptions` autoclose knobs (+ window).\n * - **CircuitBreaker** — the store-op breaker on `ActOptions`.\n * - **Fold** — `projection(...).of(...)` batch-fold knobs.\n *\n * Sibling env/package config (`config()`, `NODE_ENV`, log level) lives in the\n * public `../config.ts` — a different concern (process environment, not\n * builder input). The `@rotorsoft/act-http` transport bags (`SseOptions`,\n * `OpenAPIOptions`) live in that package; core cannot own another package's\n * surface.\n *\n * Validation philosophy: reject only what is genuinely broken — `NaN`,\n * `±Infinity` (Zod 4's `z.number()` rejects both by default), and negatives\n * where nonsensical. A value that works today is never newly rejected. The\n * real strictness lands on `maxRetries` and `backoff`, the knobs whose bad\n * values silently corrupt the poison-quarantine and retry-loop-exit gates.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { ActOptions } from \"../act.js\";\nimport type {\n ActionOptions,\n BackoffOptions,\n DrainOptions,\n FoldOptions,\n LaneConfig,\n ReactionOptions,\n SettleOptions,\n ShutdownOptions,\n} from \"../types/index.js\";\n\n// ---------------------------------------------------------------------------\n// Backoff — retry pacing. Nested inside the reaction/action bags below; also\n// resolvable on its own (`resolveBackoffConfig`) for direct callers.\n// ---------------------------------------------------------------------------\n\n/**\n * Rejects an off-union `strategy`, a non-finite/negative `baseMs`, or a\n * non-finite/non-positive `maxMs`. Zod 4's `z.number()` rejects\n * `NaN`/`±Infinity` by default, so `.min(0)` / `.gt(0)` also close the\n * non-finite gap. No `maxMs >= baseMs` constraint — a sub-`baseMs` cap on\n * `exponential` is documented behavior, not an error.\n * @internal\n */\nconst BackoffOptionsSchema = z.object({\n strategy: z.enum([\"fixed\", \"linear\", \"exponential\"]),\n baseMs: z.number().min(0),\n maxMs: z.number().gt(0).optional(),\n jitter: z.boolean().optional(),\n});\n\n/**\n * Retry pacing for a reaction that declares no backoff, and for projections\n * and failed fetches, which have no options. Ten seconds, like the default\n * lease; the lease itself only keeps two workers off one stream.\n */\nexport const DEFAULT_BACKOFF: BackoffOptions = {\n strategy: \"fixed\",\n baseMs: 10_000,\n};\n\n/** Validate a backoff bag, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveBackoffConfig(\n options: BackoffOptions | undefined\n): BackoffOptions | undefined {\n return options === undefined\n ? undefined\n : BackoffOptionsSchema.parse(options);\n}\n\n// ---------------------------------------------------------------------------\n// Reaction — `.do(handler, options)`. `maxRetries` gates the poison-quarantine\n// decision (`retry >= maxRetries`), so a `NaN` here silently disables\n// `blockOnError` (a poison message retries forever). Validate the whole bag.\n// ---------------------------------------------------------------------------\n\n/** Retries a reaction gets before it blocks, unless `.do()` says otherwise. */\nexport const DEFAULT_MAX_RETRIES = 3;\n/** Whether a reaction blocks its stream once retries run out. */\nexport const DEFAULT_BLOCK_ON_ERROR = true;\n\nconst ReactionOptionsSchema = z.object({\n blockOnError: z.boolean(),\n maxRetries: z.number().int().min(0),\n backoff: BackoffOptionsSchema.optional(),\n});\n\n/** Resolved reaction options. */\nexport type ReactionConfig = z.infer<typeof ReactionOptionsSchema>;\n\n/** Validate a fully-defaulted reaction options bag. Throws `ZodError`. */\nexport function resolveReactionConfig(\n options: ReactionOptions\n): ReactionConfig {\n return ReactionOptionsSchema.parse(options);\n}\n\n// ---------------------------------------------------------------------------\n// Action — `.on(entry, options)`. `maxRetries` gates the command retry loop's\n// exit (`attempt >= maxRetries`), so a `NaN` here can spin the loop forever on\n// a contended stream. All fields optional (the argument itself is optional).\n// ---------------------------------------------------------------------------\n\nconst ActionOptionsSchema = z.object({\n maxRetries: z.number().int().min(0).optional(),\n backoff: BackoffOptionsSchema.optional(),\n});\n\n/** Resolved action options. */\nexport type ActionConfig = z.infer<typeof ActionOptionsSchema>;\n\n/** Validate an action options bag. Throws `ZodError`. */\nexport function resolveActionConfig(options: ActionOptions): ActionConfig {\n return ActionOptionsSchema.parse(options);\n}\n\n// ---------------------------------------------------------------------------\n// Lane — `.withLane({...})`. Per-lane overrides of the drain budget. Time\n// knobs (`leaseMillis` / `cycleMs`) accept any non-negative ms; `streamLimit`\n// is an integer count. Reject NaN/Infinity/negative; allow 0 (as today).\n// ---------------------------------------------------------------------------\n\nconst LaneConfigSchema = z.object({\n name: z.string().min(1),\n leaseMillis: z.number().min(0).optional(),\n streamLimit: z.number().int().min(0).optional(),\n cycleMs: z.number().min(0).optional(),\n});\n\n/** Validate a lane config. Throws `ZodError`. Returns the input shape. */\nexport function resolveLaneConfig<TName extends string>(\n options: LaneConfig<TName>\n): LaneConfig<TName> {\n LaneConfigSchema.parse(options);\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Drain / Settle — runtime knobs for `drain(...)` / `settle(...)`. Parsed once\n// per call (cheap). Reject NaN/Infinity/negative; allow 0. `correlate` is a\n// pass-through query filter (validated by the store), so it is not reshaped.\n// ---------------------------------------------------------------------------\n\n/** Streams a drain claims per cycle. */\nexport const DEFAULT_STREAM_LIMIT = 10;\n/** Events a drain reads per stream per cycle. */\nexport const DEFAULT_EVENT_LIMIT = 10;\n/** How long a drain holds a stream's lease (ms). */\nexport const DEFAULT_LEASE_MILLIS = 10_000;\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.\n */\nexport const DEFAULT_SETTLE_DEBOUNCE_MS = 10;\n/**\n * Default LRU cap for the subscribed-streams cache. Apps that mint many\n * dynamic targets (one per aggregate) should override it with\n * `ActOptions.maxSubscribedStreams`.\n */\nexport const DEFAULT_MAX_SUBSCRIBED_STREAMS = 1000;\n\nconst DrainOptionsSchema = z.object({\n streamLimit: z.number().int().min(0).optional(),\n eventLimit: z.number().int().min(0).optional(),\n leaseMillis: z.number().min(0).optional(),\n});\n\n/** Validate drain options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveDrainConfig(\n options: DrainOptions | undefined\n): DrainOptions | undefined {\n if (options === undefined) return undefined;\n DrainOptionsSchema.parse(options);\n return options;\n}\n\nconst SettleOptionsSchema = DrainOptionsSchema.extend({\n debounceMs: z.number().min(0).optional(),\n // `maxPasses` defaults to Infinity (no cap) when omitted; a present value is\n // a non-negative integer — `0` is legal and means \"run no passes\".\n //\n // `Infinity` is accepted explicitly. It is the documented default\n // (`Act.settle`'s doc-comment and `SettleOptions.maxPasses` both name it),\n // and `settle.ts` destructures `maxPasses = Infinity`, so the one value the\n // docs advertise was the one value `z.number().int()` refused — Zod 4\n // rejects `±Infinity`, and an integer check cannot pass it either. Wrapper\n // code normalizing an optional cap (`maxPasses: opts.maxPasses ?? Infinity`)\n // is the natural way to hit it. Accepting it also honors this module's own\n // rule that a value which works today is never newly rejected.\n maxPasses: z\n .union([z.number().int().min(0), z.literal(Number.POSITIVE_INFINITY)])\n .optional(),\n}).loose();\n\n/** Validate settle options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveSettleConfig(\n options: SettleOptions | undefined\n): SettleOptions | undefined {\n if (options === undefined) return undefined;\n SettleOptionsSchema.parse(options);\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Shutdown — the grace budget `shutdown(...)` gives in-flight drain cycles.\n// ---------------------------------------------------------------------------\n\n/**\n * Ceiling on the derived shutdown grace budget. Without a cap, a lane\n * configured with a long lease (minutes, for a genuinely slow integration)\n * would let one parked handler hold a rolling deploy open for that whole\n * lease. 30s is the longest `leaseMillis` the production checklist\n * recommends, so it is the point past which \"graceful\" stops being the\n * operator's intent.\n */\nexport const MAX_SHUTDOWN_GRACE_MS = 30_000;\n\nconst ShutdownOptionsSchema = z\n .object({\n // `0` is legal and is exactly today's behavior: stop scheduling and\n // return without waiting.\n graceMs: z.number().min(0).optional(),\n })\n .loose();\n\n/** Validate shutdown options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveShutdownConfig(\n options: ShutdownOptions | undefined\n): ShutdownOptions | undefined {\n if (options === undefined) return undefined;\n ShutdownOptionsSchema.parse(options);\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Act — the top-level `act().build(options)` scalar knobs. The nested bags\n// (`autocloseWindow`, `circuitBreaker`) are resolved by their own resolvers\n// below; the `scoped`/`correlator` fields are objects/functions passed\n// through untouched (`.loose()`), so only the scalar knobs are checked here.\n// ---------------------------------------------------------------------------\n\nconst ActOptionsSchema = z\n .object({\n maxSubscribedStreams: z.number().int().min(1).optional(),\n settleDebounceMs: z.number().int().min(0).optional(),\n })\n .loose();\n\n/** Validate the scalar `ActOptions` knobs at build. Throws `ZodError`. */\nexport function resolveActConfig(\n options: ActOptions | undefined\n): ActOptions | undefined {\n if (options === undefined) return undefined;\n ActOptionsSchema.parse(options);\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Autoclose — the autoclose knobs on `ActOptions` (+ the off-hours window).\n// The window *logic* (DST, hour math) stays in `autoclose-window.ts`; only\n// the schema, defaults, and resolver live here.\n// ---------------------------------------------------------------------------\n\n/**\n * @deprecated The cadence knob is derived from `autocloseWindow` now;\n * nothing consumes it. Kept for compat; removed in the next major.\n */\nexport const DEFAULT_AUTOCLOSE_CYCLE_MINUTES = 720;\n/** @deprecated Unused since the autoclose sweep was removed. */\nexport const DEFAULT_CLOSE_BATCH_SIZE = 64;\n/** @deprecated Unused since the autoclose sweep was removed. */\nexport const DEFAULT_CLOSE_YIELD_MS = 0;\n/** Default IANA zone for `autocloseWindow` when the operator omits one. */\nconst DEFAULT_AUTOCLOSE_WINDOW_TZ = \"UTC\";\n\n/** True when `tz` is a zone the runtime's `Intl` accepts. @internal */\nfunction is_valid_time_zone(tz: string): boolean {\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: tz });\n return true;\n } catch {\n return false;\n }\n}\n\nconst AutocloseWindowSchema = z\n .object({\n start: z\n .number()\n .int()\n .min(0)\n .max(23, { message: \"autocloseWindow.start must be an hour in [0, 23]\" }),\n end: z\n .number()\n .int()\n .min(0)\n .max(23, { message: \"autocloseWindow.end must be an hour in [0, 23]\" }),\n timeZone: z\n .string()\n .refine(is_valid_time_zone, {\n message: \"autocloseWindow.timeZone must be a valid IANA time zone\",\n })\n .default(DEFAULT_AUTOCLOSE_WINDOW_TZ),\n })\n .refine((w) => w.start !== w.end, {\n message:\n \"autocloseWindow.start and end must differ — an empty window disables autoclose\",\n });\n\nconst AutocloseOptionsSchema = z.object({\n autocloseCycleMinutes: z\n .number()\n .int()\n .min(1)\n .max(1440)\n .default(DEFAULT_AUTOCLOSE_CYCLE_MINUTES),\n closeBatchSize: z\n .number()\n .int()\n .min(1)\n .max(1024)\n .default(DEFAULT_CLOSE_BATCH_SIZE),\n closeYieldMs: z.number().min(0).max(1000).default(DEFAULT_CLOSE_YIELD_MS),\n closeOnError: z.boolean().default(false),\n autocloseWindow: AutocloseWindowSchema.optional(),\n});\n\n/** Resolved autoclose configuration after validation + default expansion. */\nexport type AutocloseConfig = z.infer<typeof AutocloseOptionsSchema>;\n\n/** Validate + default the autoclose knobs on `ActOptions`. Throws `ZodError`. */\nexport function resolveAutocloseConfig(\n options: ActOptions | undefined\n): AutocloseConfig {\n return AutocloseOptionsSchema.parse({\n autocloseCycleMinutes: options?.autocloseCycleMinutes,\n closeBatchSize: options?.closeBatchSize,\n closeYieldMs: options?.closeYieldMs,\n closeOnError: options?.closeOnError,\n autocloseWindow: options?.autocloseWindow,\n });\n}\n\n// ---------------------------------------------------------------------------\n// CircuitBreaker — the store-op breaker on `ActOptions`. The `CircuitBreaker`\n// state machine stays in `circuit-breaker.ts` and imports the resolved type.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_CIRCUIT_FAILURE_THRESHOLD = 5;\nconst DEFAULT_CIRCUIT_COOLDOWN_MS = 30_000;\n\nconst CircuitBreakerOptionsSchema = z.object({\n failureThreshold: z\n .number()\n .int()\n .min(1)\n .default(DEFAULT_CIRCUIT_FAILURE_THRESHOLD),\n cooldownMs: z\n .number()\n .int()\n .min(100)\n .max(3_600_000)\n .default(DEFAULT_CIRCUIT_COOLDOWN_MS),\n});\n\n/** Public, all-optional circuit-breaker options bag for `act().build()`. */\nexport type CircuitBreakerOptions = z.input<typeof CircuitBreakerOptionsSchema>;\n\n/** Resolved circuit-breaker configuration. */\nexport type CircuitBreakerConfig = z.infer<typeof CircuitBreakerOptionsSchema>;\n\n/** Parse + apply defaults. Throws `ZodError` on out-of-range values. */\nexport const resolveCircuitBreakerConfig = (\n options?: CircuitBreakerOptions\n): CircuitBreakerConfig => CircuitBreakerOptionsSchema.parse(options ?? {});\n\n// ---------------------------------------------------------------------------\n// Fold — `projection(name).of(state)` batch-fold knobs.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_FOLD_FLUSH_EVERY = 1_000;\nconst DEFAULT_MAX_CACHED_STATES = 10_000;\n\nconst FoldOptionsSchema = z.object({\n flushEvery: z.number().int().min(1).default(DEFAULT_FOLD_FLUSH_EVERY),\n maxCachedStates: z.number().int().min(1).default(DEFAULT_MAX_CACHED_STATES),\n});\n\n/** Resolved fold configuration. */\nexport type FoldConfig = z.infer<typeof FoldOptionsSchema>;\n\n/** Validate + default the fold knobs. Throws `ZodError`. */\nexport function resolveFoldConfig(options: FoldOptions): FoldConfig {\n return FoldOptionsSchema.parse(options);\n}\n","/**\n * @module defer-signal\n * @category Internal\n *\n * The control-flow signal a reaction handler throws to *defer* itself.\n * Unlike an error, a defer is not a failure: the dispatcher\n * ({@link \"reaction-builder\".build_handle}) catches it and produces a\n * `HandleResult.defer` — the triggering events stay pending (watermark not\n * advanced), `retry` is not bumped, and the drain re-visits the stream at the\n * resolved due-time.\n *\n * `DeferSignal` is the **imperative escape hatch** and is re-exported from the\n * package root, so reaction code can throw it directly when a static\n * `.defer(when)` step isn't expressive enough (a deadline computed from loaded\n * state, say). It carries the *unresolved* {@link DeferWhen}; the dispatcher\n * resolves it against the triggering event it is already dispatching (via\n * `resolve_defer_at`), which is what anchors `{ after }` and the `at` function\n * form to that event and keeps the due-time derivable. Fully dynamic times go\n * through `{ at: someDate }`.\n *\n * Modeled as an `Error` subclass — like `NonRetryableError` — so it rides the\n * existing `try/catch` in the handler loop instead of needing a separate\n * return channel through every dispatcher signature. The compiled autoclose\n * reaction throws the same signal.\n */\nimport type { DeferWhen } from \"../types/index.js\";\n\nexport class DeferSignal extends Error {\n /**\n * The unresolved schedule. The dispatcher turns this into an absolute\n * due-time by resolving it against the triggering event.\n */\n readonly when: DeferWhen;\n\n constructor(when: DeferWhen) {\n super(\"reaction deferred\");\n this.name = \"DeferSignal\";\n this.when = when;\n }\n}\n","/**\n * @module autoclose-reaction\n * @category Internal\n *\n * Synthesis of the online close-the-books reaction. `.autocloses(policy)`\n * is not a sweep: it is a reaction on every event the declaring state owns\n * that evaluates the policy against the LIVE head (so a reopened stream\n * re-evaluates correctly), defers to the cooldown's earliest opening\n * (`head.created + the policy's min after`), and closes via `CloseSignal`\n * once the policy holds.\n *\n * Runs at build time — after the registry is fully merged and before the\n * orchestrator classifies it — so the synthesized dynamic resolver is\n * discovered by `classify_registry` and its target stream subscribed. The\n * registry is complete once the builder finishes; the orchestrator never\n * mutates it.\n *\n * @internal\n */\n\nimport { SNAP_EVENT, store, TOMBSTONE_EVENT } from \"../ports.js\";\nimport type {\n Reaction,\n Registry,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport { days_after, days_before_now } from \"./autoclose-policy.js\";\nimport { in_autoclose_window, next_window_open } from \"./autoclose-window.js\";\nimport { CloseSignal } from \"./close-signal.js\";\nimport { type AutocloseConfig, DEFAULT_MAX_RETRIES } from \"./config.js\";\nimport { DeferSignal } from \"./defer-signal.js\";\n\n/**\n * Prefix for the synthetic per-aggregate stream the autoclose reaction\n * runs on. `target = \\`${AUTOCLOSE_TARGET_PREFIX}${aggregate}\\``, `source =\n * aggregate` — a watermark distinct from the aggregate's own reactions, so\n * an autoclose defer never short-circuits them. Internal; not a public\n * surface.\n */\nconst AUTOCLOSE_TARGET_PREFIX = \"__autoclose__:\";\n\n/**\n * Inject one synthesized autoclose reaction per `.autocloses(...)` state\n * into the registry's event registers. The handler resolves ports at call\n * time (`store()`), so the reaction is orchestrator-agnostic; the resolved\n * The reactions are synthesized once into the shared registry, so nothing\n * per-Act is captured here — the off-hours window is read from the running\n * Act at resolution time via the injected `read_window`.\n *\n * @internal\n */\nexport function synthesize_autoclose_reactions<\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<any, any, any>>,\n /**\n * Reads the *running* Act's off-hours window. Injected rather than\n * imported: these reactions are synthesized once into the shared\n * registry and run by every Act built from that builder, so the window\n * has to be resolved per call, and `internal/` never reaches for\n * ambient state itself.\n */\n read_window: () => AutocloseConfig[\"autocloseWindow\"]\n): void {\n for (const st of states.values()) {\n const predicate = st.autoclose;\n if (!predicate) continue;\n const after_days = st.autoclose_after_days;\n const keep_days = st.autoclose_keep_days;\n const archiver = st.archive;\n const reaction: Reaction<TEvents> = {\n // Run on a SYNTHETIC stream — `source` is the aggregate, `target` is a\n // per-aggregate `__autoclose__` key — so the autoclose reaction never\n // shares a watermark with the aggregate's own reactions. A shared\n // watermark would let autoclose's defer short-circuit the aggregate's\n // other reactions (the \"a defer affects all reactions on a stream\"\n // hazard). The close still targets the aggregate (`source`).\n resolver: (e) => ({\n target: `${AUTOCLOSE_TARGET_PREFIX}${e.stream}`,\n source: e.stream,\n }),\n // Never block on autoclose: a transient query/store error should retry,\n // not quarantine the synthetic stream.\n options: { blockOnError: false, maxRetries: DEFAULT_MAX_RETRIES },\n handler: async (event) => {\n const aggregate = event.stream;\n // Off-hours gating: outside the window, park until the window\n // opens. Derived from the window itself — no polling cadence.\n //\n // Read from the running Act's frame, not from a closure. These\n // reactions are synthesized once into the shared registry and\n // handed by reference to every Act built from the same builder, so\n // a captured window would be the first-built Act's for all of them\n // — and the documented multi-tenant shape is one builder built per\n // tenant.\n const window = read_window();\n if (!in_autoclose_window(window, new Date()))\n throw new DeferSignal({ at: next_window_open(window!, new Date()) });\n // Every policy keys on the *domain* head/count, so snapshots are\n // excluded unconditionally — matching `scan_stream_heads` in\n // close-cycle.ts. `snap()` commits a `__snapshot__` at a higher id\n // right after the triggering domain event, so a terminal commit that\n // crosses a `.snap()` boundary would otherwise make the snapshot the\n // head: `is` never matches (`head.name === \"__snapshot__\"`) and never\n // recovers, `after` measures the cooldown from the snapshot's\n // timestamp, and `reaches:N` counts snapshot events toward N. Only\n // rolling-window (`keep`) policies additionally fetch the tail: the\n // prune decision keys on the oldest *domain* event — after a prune the\n // oldest surviving event is the boundary snapshot, whose age says\n // nothing about whether another prune would be productive.\n const stats = await store().query_stats([aggregate], {\n count: true,\n tail: keep_days !== undefined ? true : undefined,\n exclude: [TOMBSTONE_EVENT, SNAP_EVENT],\n });\n const entry = stats.get(aggregate);\n // No live (non-tombstone) head → already closed, nothing to do.\n if (!entry) return;\n const head = entry.head;\n // `count` is always present — query_stats is called with\n // `count: true` above, so the option contract guarantees it.\n if (predicate(aggregate, head, entry.count!))\n throw new CloseSignal({\n stream: aggregate,\n archive: archiver ? () => archiver(aggregate, head) : undefined,\n // Ack this reaction's own watermark to the live head so the\n // close-cycle guard (which matches subscriptions by source =\n // aggregate) sees it caught up instead of blocking its own close.\n at: head.id,\n });\n // Rolling window: when the oldest domain event has aged out of the\n // window, stage a windowed close — prune the prefix older than the\n // cutoff behind the closest safe snapshot. `tail` is present\n // whenever the stats entry is (same non-excluded event set).\n if (keep_days !== undefined) {\n const cutoff = days_before_now(keep_days);\n if (entry.tail!.created < cutoff)\n throw new CloseSignal({\n stream: aggregate,\n before: cutoff,\n archive: archiver\n ? () => archiver(aggregate, head, cutoff)\n : undefined,\n at: head.id,\n });\n }\n // Not eligible yet: park on the earliest derivable due-time — the\n // day the terminate cooldown opens and/or the day the oldest\n // domain event ages out of the rolling window. Neither → wait for\n // the next event to re-trigger (e.g. a `reaches` threshold).\n const dues: Date[] = [];\n if (after_days !== undefined)\n dues.push(days_after(head.created, after_days));\n if (keep_days !== undefined)\n dues.push(days_after(entry.tail!.created, keep_days));\n // Only defer to a FUTURE due-time. A due already in the past (the\n // stream idled longer than the cooldown while the AND-combined\n // predicate stayed unmet) can never be excluded by `claim`, which\n // skips only future `deferred_at` — so a past defer would be\n // re-claimed every cycle (perpetual query_stats burn). When\n // nothing is future, fall through and return: advance the watermark\n // and wait for the next event to re-trigger.\n const future = dues\n .map((d) => d.getTime())\n .filter((t) => t > Date.now());\n if (future.length)\n throw new DeferSignal({ at: new Date(Math.min(...future)) });\n },\n };\n const key = `__autoclose_${st.name}`;\n for (const event_name of Object.keys(st.events)) {\n registry.events[event_name as keyof TEvents]?.reactions.set(\n key,\n reaction as Reaction<TEvents, keyof TEvents>\n );\n }\n }\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/action.js\";\n\n// The `BackoffOptions` config schema + resolver live in `./config.ts` (the\n// single home for every builder-facing config bag). This module keeps only\n// the runtime delay math, which stays hot-path and dependency-free.\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 compute_backoff_delay(\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 default: {\n // Unreachable once options pass `resolveBackoffConfig` at their\n // declaration site. Defensive so the pure function is total and can\n // never emit `NaN` from an unvalidated strategy — throw instead.\n const _never: never = opts.strategy;\n throw new Error(`unknown backoff strategy: ${String(_never)}`);\n }\n }\n if (opts.jitter) delay = delay * (0.5 + Math.random());\n return Math.max(0, Math.floor(delay));\n}\n","/**\n * @module internal/circuit-breaker\n *\n * Orchestrator-level circuit breaker for store operations. The drain loop\n * polls `claim()` continuously; when the backing store goes down every poll\n * throws a {@link StoreError}, and without a breaker the orchestrator would\n * spin at the cycle cadence hammering a dead database and flooding the logs.\n *\n * The breaker collapses that into three states:\n *\n * - **closed** — normal operation; failures are counted.\n * - **open** — `failureThreshold` consecutive failures tripped it; attempts\n * are skipped for `cooldownMs` so the store gets room to recover.\n * - **half-open** — the cooldown elapsed; a single trial attempt is allowed.\n * Success closes the breaker; failure re-opens it and restarts the clock.\n *\n * Time is passed in (`now`) rather than read from the clock so the state\n * machine is deterministic under test.\n */\n\nimport type { CircuitBreakerConfig } from \"./config.js\";\n\n/** Circuit breaker state. */\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\n// The circuit-breaker config schema, defaults, and resolver live in\n// `./config.js` (the single home for builder-facing config bags). This\n// module keeps only the state machine that consumes the resolved config.\n\n/**\n * Side-effect hooks the orchestrator wires into the breaker so consumers\n * (drain / settle / autoclose) don't each thread their own callbacks.\n */\nexport type CircuitBreakerHooks = {\n /** Invoked on every {@link CircuitBreaker.failed} with the error and state. */\n readonly on_error?: (error: unknown, circuit: CircuitState) => void;\n /**\n * Invoked once, `cooldownMs` after the breaker opens (and again on each\n * re-open). The orchestrator wires it to re-attempt a drain — so recovery\n * is automatic even on the default lane, which has no periodic poller.\n */\n readonly on_retry?: () => void;\n};\n\nexport class CircuitBreaker {\n private _failures = 0;\n private _opened_at: number | undefined;\n private _wake: ReturnType<typeof setTimeout> | undefined;\n private readonly _threshold: number;\n private readonly _cooldown_ms: number;\n private readonly _hooks: CircuitBreakerHooks;\n\n constructor(config: CircuitBreakerConfig, hooks: CircuitBreakerHooks = {}) {\n this._threshold = config.failureThreshold;\n this._cooldown_ms = config.cooldownMs;\n this._hooks = hooks;\n }\n\n /**\n * True when the store has failed at least once since the last pass that\n * went all the way through. The breaker can still read \"closed\" here: it\n * only opens after several failures in a row, so this catches the first\n * one, which `state()` cannot.\n */\n get failing(): boolean {\n return this._failures > 0;\n }\n\n /** How long the store is left alone after a failure before a retry. */\n get cooldown_ms(): number {\n return this._cooldown_ms;\n }\n\n /** Current state given the wall-clock `now`. */\n state(now: number): CircuitState {\n if (this._opened_at === undefined) return \"closed\";\n return now - this._opened_at >= this._cooldown_ms ? \"half-open\" : \"open\";\n }\n\n /** A store op passed — reset to closed and cancel any pending retry. */\n passed(): void {\n this._failures = 0;\n this._opened_at = undefined;\n this._clear_wake();\n }\n\n /**\n * A store op failed. Opens the breaker when the consecutive-failure\n * threshold is reached, or immediately re-opens (restarting the cooldown)\n * if a half-open trial just failed. Returns the resulting state.\n *\n * Callers gate on the state directly — `state(now) === \"open\"` means skip.\n * On opening, schedules the `on_retry` wake so recovery is automatic;\n * always surfaces the failure via `on_error`.\n */\n failed(now: number, error?: unknown): CircuitState {\n const circuit = this._advance(now);\n if (circuit === \"open\") this._schedule_wake();\n this._hooks.on_error?.(error, circuit);\n return circuit;\n }\n\n /** Cancel the pending retry timer. Idempotent; call on shutdown. */\n stop(): void {\n this._clear_wake();\n }\n\n /**\n * Schedule the `on_retry` wake `cooldownMs` out so the breaker re-trials\n * the store on its own. No-op when no `on_retry` hook is wired (e.g. unit\n * tests of the pure state machine). The timer is `unref`'d so it never\n * keeps the process alive.\n */\n private _schedule_wake(): void {\n if (!this._hooks.on_retry) return;\n this._clear_wake();\n this._wake = setTimeout(() => {\n this._wake = undefined;\n this._hooks.on_retry?.();\n }, this._cooldown_ms);\n this._wake.unref();\n }\n\n private _clear_wake(): void {\n if (this._wake) {\n clearTimeout(this._wake);\n this._wake = undefined;\n }\n }\n\n /** Pure state transition for a failure — no side effects. */\n private _advance(now: number): CircuitState {\n // Already tripped: this can only be reached from a half-open trial\n // (open skips attempts), so the trial failed — re-open and restart.\n if (this._opened_at !== undefined) {\n this._opened_at = now;\n return \"open\";\n }\n this._failures += 1;\n if (this._failures >= this._threshold) {\n this._opened_at = now;\n return \"open\";\n }\n return \"closed\";\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 * Also home to the pieces a closer needs around the cycle: the per-stream\n * {@link CloseLock} and the bounded {@link catch_up_correlation}. The Act\n * orchestrator only wires its ports in and emits `\"closed\"`.\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\";\nimport { walk_streams } from \"./walk-streams.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 /** Whether any event has a reaction; without one nothing can be pending. */\n readonly reactive: boolean;\n readonly event_to_state: 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 * Page size for the safety probe's `query_streams` pagination.\n * Defaults to {@link SAFETY_PROBE_PAGE_SIZE}; production callers omit\n * it, tests set a small value to exercise the multi-page path.\n */\n readonly probe_page_size?: number;\n /**\n * Advance correlation to at least `until` (an event id) and return how\n * far it actually got.\n *\n * The safety probe can only judge events correlate has resolved (an\n * uncorrelated event has raised no mark and may not even have created its\n * subscription yet). An autoclose fires from its own, often uncorrelated,\n * trigger, so the cycle correlates the tail first; anything still above\n * the cursor is held back as pending.\n */\n readonly catch_up_correlation: (until: number) => Promise<number>;\n /**\n * Per-stream critical section, so two closers of one stream (a manual\n * close has no drain lease to exclude an autoclose) never archive the same\n * prefix, and a second full closer never mistakes the first one's\n * tombstone for an interrupted close. Identity when run in isolation.\n */\n readonly with_stream_lock?: <T>(\n stream: string,\n work: () => Promise<T>\n ) => Promise<T>;\n /**\n * Drop retired streams from correlate's in-process \"already subscribed\"\n * set, so a later scan re-issues `subscribe()` for them. An operator may\n * reclaim a retired subscription row while this process runs; forgetting\n * keeps the in-process view from outliving it, which would otherwise stop\n * delivery to a target named after the stream. Skipped in isolation.\n */\n readonly forget_subscribed?: (streams: string[]) => void;\n};\n\n/**\n * Scan window and pass cap for {@link catch_up_correlation}. Bounded, so a\n * close behind a large backlog skips the stream (the documented retryable\n * outcome) rather than scanning the whole log inside an operator call.\n *\n * @internal\n */\nconst CLOSE_CATCH_UP_LIMIT = 1000;\nconst CLOSE_CATCH_UP_PASSES = 20;\n\n/**\n * Advance correlation until the read cursor reaches `until`, and report\n * where it landed. The safety probe cannot judge a subscription's pending\n * work over events correlate has not resolved yet.\n *\n * Stops as soon as a pass makes no progress (the log has no more to give),\n * and after {@link CLOSE_CATCH_UP_PASSES} windows.\n *\n * @internal\n */\nexport async function catch_up_correlation(\n cursor: { readonly checkpoint: number; arm(): void },\n correlate: (limit: number) => Promise<unknown>,\n until: number\n): Promise<number> {\n for (\n let pass = 0;\n pass < CLOSE_CATCH_UP_PASSES && cursor.checkpoint < until;\n pass++\n ) {\n const before = cursor.checkpoint;\n // Force the scan: the armed flag can't say whether a tail exists.\n cursor.arm();\n await correlate(CLOSE_CATCH_UP_LIMIT);\n if (cursor.checkpoint <= before) break;\n }\n return cursor.checkpoint;\n}\n\n/**\n * Per-stream serialization for close critical sections: two closers of the\n * same stream never prune or archive concurrently, while different streams\n * proceed in parallel. One instance per Act.\n *\n * @internal\n */\nexport class CloseLock {\n private readonly _tails = new Map<string, Promise<unknown>>();\n\n /** Run `work` after every earlier close of `stream` has settled. */\n run<T>(stream: string, work: () => Promise<T>): Promise<T> {\n const prev = this._tails.get(stream) ?? Promise.resolve();\n // Chain after the previous holder however it settled, so a failed close\n // can't wedge the lock.\n const next = prev.then(work, work);\n this._tails.set(stream, next);\n // Drop the tail once settled, unless a later waiter replaced it.\n const cleanup = () => {\n if (this._tails.get(stream) === next) this._tails.delete(stream);\n };\n next.then(cleanup, cleanup);\n return next;\n }\n}\n\n/**\n * Page size for the safety probe's keyset pagination over the\n * subscriptions table. Above `query_streams`'s default `limit` of 100\n * to keep the round-trip count low while bounding per-page work.\n *\n * @internal\n */\nconst SAFETY_PROBE_PAGE_SIZE = 1000;\n\n/**\n * Per-stream scan result: latest non-tombstone domain event metadata.\n * `last_event_name` 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 max_id: number;\n readonly version: number;\n readonly last_event_name: string;\n /**\n * Set when the stream already carries a tombstone but still holds domain\n * events — a close that wrote its guard and was then interrupted before\n * truncating (a throwing archive callback, or a `truncate` that failed).\n * Carries the existing guard's event id so the retry resumes at Phase 4\n * instead of re-tombstoning (which would fail the version guard) or being\n * dropped from the scan entirely.\n */\n readonly resumed_guard?: { readonly id: number };\n};\n\n/**\n * Run the full close cycle for the given targets. Caller owns the\n * lifecycle event emission.\n *\n * Targets carrying a `before` cutoff take the **windowed** branch — a\n * pure prefix delete behind an existing snapshot (see\n * {@link run_windowed_closes}); the rest run the guarded\n * tombstone/restart pipeline below.\n *\n * @internal\n */\nexport async function run_close_cycle(\n targets: CloseTarget[],\n deps: CloseCycleDeps\n): Promise<CloseResult> {\n // Caller (Act.close) filters empty targets; run_close_cycle assumes at\n // least one target.\n const target_map = new Map(targets.map((t) => [t.stream, t]));\n for (const t of target_map.values()) {\n if (t.before !== undefined && t.restart)\n throw new Error(\n `close: \\`before\\` and \\`restart\\` are mutually exclusive (stream \"${t.stream}\") — a windowed close keeps the stream live behind a real snapshot; restart reseeds it`\n );\n }\n const windowed = [...target_map.values()].filter(\n (t) => t.before !== undefined\n );\n const full = [...target_map.values()].filter((t) => t.before === undefined);\n const skipped: string[] = [];\n const windowed_result = windowed.length\n ? await run_windowed_closes(windowed, deps, skipped)\n : new Map();\n if (!full.length) return { truncated: windowed_result, skipped };\n const truncated = await with_stream_locks(\n full.map((t) => t.stream),\n deps,\n () => run_full_closes(full, target_map, deps, skipped)\n );\n // A tombstone seed retired the stream; a snapshot seed restarted it.\n const retired = [...truncated.entries()]\n .filter(([, r]) => r.committed.name === TOMBSTONE_EVENT)\n .map(([stream]) => stream);\n if (retired.length) deps.forget_subscribed?.(retired);\n for (const [stream, entry] of windowed_result) truncated.set(stream, entry);\n return { truncated, skipped };\n}\n\n/**\n * Run `work` holding the per-stream close lock of every stream in\n * `streams`. Locks are taken in sorted order, so two closers whose batches\n * share streams in a different order cannot each hold one and wait on the\n * other.\n */\nfunction with_stream_locks<T>(\n streams: string[],\n deps: CloseCycleDeps,\n work: () => Promise<T>\n): Promise<T> {\n const with_lock = deps.with_stream_lock ?? ((_stream, w) => w());\n return [...streams]\n .sort()\n .reduceRight<() => Promise<T>>(\n (inner, stream) => () => with_lock(stream, inner),\n work\n )();\n}\n\n/**\n * The guarded tombstone/restart pipeline (Phases 1-6), run while holding\n * every target stream's close lock.\n */\nasync function run_full_closes(\n full: CloseTarget[],\n target_map: Map<string, CloseTarget>,\n deps: CloseCycleDeps,\n skipped: string[]\n): Promise<CloseResult[\"truncated\"]> {\n const none: CloseResult[\"truncated\"] = new Map();\n const streams = full.map((t) => t.stream);\n\n // 1. Scan: find the latest non-tombstone event per stream\n const stream_info = await scan_stream_heads(streams);\n\n // 1b. A restart target whose state has sensitive fields can't be seeded\n // (an actorless load would redact them; a privileged one would put\n // plaintext where `forget` can't reach), so it is skipped, untouched,\n // before anything is written.\n for (const target of full) {\n if (!target.restart) continue;\n const info = stream_info.get(target.stream);\n if (!info) continue;\n const owner = deps.event_to_state.get(info.last_event_name);\n if (owner?.pii_aware) {\n deps.logger.error(\n `Refusing to close \"${target.stream}\" with restart: state \"${owner.name}\" carries sensitive fields, so a restart seed would persist redacted values while deleting the originals. Close it without restart to retire the stream, or leave it open.`\n );\n skipped.push(target.stream);\n stream_info.delete(target.stream);\n }\n }\n\n // 2. Partition: skip streams with pending reactions in flight\n const safe = await partition_by_safety(\n stream_info,\n deps.reactive,\n skipped,\n deps.probe_page_size ?? SAFETY_PROBE_PAGE_SIZE,\n deps.catch_up_correlation\n );\n if (!safe.length) return none;\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.\n const { guarded, guard_events } = await guard_with_tombstones(\n safe,\n stream_info,\n deps.correlation,\n deps.tombstone,\n skipped\n );\n if (!guarded.length) return none;\n\n // 4. Seed: load final state for restart targets through the owning state\n const seed_states = await load_restart_seeds(\n guarded,\n target_map,\n stream_info,\n deps.event_to_state,\n deps.load,\n deps.logger\n );\n\n // 5. Archive: user-provided per-stream callback while guarded\n await run_archive_callbacks(guarded, target_map);\n\n // 5b. Re-check: truncate only streams whose head is still this close's\n // guard. The lock above serializes closers in this process; a closer in\n // another process can still resume our guard, finish first, and reseed\n // the stream, after which a commit can land on it. Truncating then would\n // delete that accepted commit.\n const still_guarded = await heads_still_guarded(\n guarded,\n guard_events,\n skipped\n );\n if (!still_guarded.length) return none;\n\n // 6. Truncate + seed: atomic per-store transaction\n return truncate_and_warm_cache(\n still_guarded,\n seed_states,\n guard_events,\n deps.correlation\n );\n}\n\n// ---------------------------------------------------------------------------\n// Windowed branch — prune the prefix behind an existing snapshot\n// ---------------------------------------------------------------------------\n\n/**\n * Run the windowed closes: probe the min consumer watermark per stream\n * (the `max_id` cap that keeps the boundary at/below what the laggiest\n * consumer has read), run archive callbacks against the cutoff, then\n * hand the boundary targets to {@link Store.truncate}.\n *\n * No tombstone guard and no cache touch — the cutoff is always in the\n * past, so a concurrently-written snapshot (`created = now`) can never\n * become the boundary: once the cutoff is fixed the boundary snapshot is\n * fixed, and the prefix below it is immutable. Concurrent appends land\n * at the head, above the boundary. Current state is unchanged, so the\n * cache stays warm. Streams the store skips (no qualifying snapshot)\n * are reported in `skipped`.\n *\n * @internal\n */\nasync function run_windowed_closes(\n windowed: CloseTarget[],\n deps: CloseCycleDeps,\n skipped: string[]\n): Promise<CloseResult[\"truncated\"]> {\n // 1. Safety probe: how far may each stream be pruned (skipped when the\n // app has no reactions). A consumer with pending work caps at its\n // watermark; a caught-up one caps at the correlate checkpoint, since a\n // reaction to only some event types sits below the head with nothing\n // pending. Catching up first makes that cap as high as it can be.\n const checkpoint = deps.reactive\n ? await deps.catch_up_correlation(Number.MAX_SAFE_INTEGER)\n : -1;\n const min_at = deps.reactive\n ? await probe_min_watermarks(\n windowed.map((t) => t.stream),\n deps.probe_page_size ?? SAFETY_PROBE_PAGE_SIZE,\n checkpoint\n )\n : new Map<string, number>();\n\n // 2 + 3. Per stream, under its lock: archive only when the prune would\n // delete a prefix, then truncate. The lock plus that check make the\n // archive fire at most once per pruned range.\n const with_lock = deps.with_stream_lock ?? ((_stream, work) => work());\n const truncated: CloseResult[\"truncated\"] = new Map();\n for (const t of windowed) {\n const entry = await with_lock(t.stream, async () => {\n const max_id = min_at.get(t.stream);\n // Boundary probe: will a windowed truncate prune anything? The\n // store deletes events with `id < boundary.id`, where `boundary`\n // is the latest `__snapshot__` with `created < before` (and, when\n // capped, `id <= max_id`). No such prefix ⇒ archive is skipped and\n // the stream is reported skipped, exactly as a no-op truncate would.\n if (!(await windowed_prune_pending(t.stream, t.before!, max_id)))\n return undefined;\n // Archive: user callback against the cutoff, run while the prefix\n // is still present. Sequential/fail-fast: a throw propagates to the\n // caller and leaves the stream un-truncated (no data loss).\n if (t.archive) await t.archive();\n // Boundary truncate: atomic per-store transaction; no seed.\n const result = await store().truncate([\n { stream: t.stream, before: t.before!, max_id },\n ]);\n return result.get(t.stream);\n });\n if (entry) truncated.set(t.stream, entry);\n else skipped.push(t.stream);\n }\n return truncated;\n}\n\n/**\n * Read-only probe: would a windowed truncate of `stream` at `before`\n * (optionally capped at `max_id`) delete a prefix? Mirrors the store's\n * boundary rule — the latest `__snapshot__` with `created < before` and,\n * when capped, `id <= max_id` — then reports whether any event sorts\n * strictly below that boundary. False when no snapshot qualifies (a\n * no-op truncate) or when the boundary is already the earliest event\n * (the prefix was pruned by a prior closer). This is the guard that\n * makes the windowed archive fire at most once per pruned range.\n *\n * @internal\n */\nasync function windowed_prune_pending(\n stream: string,\n before: Date,\n max_id: number | undefined\n): Promise<boolean> {\n let boundary_id: number | undefined;\n let min_id: number | undefined;\n await store().query(\n (event) => {\n if (min_id === undefined || event.id < min_id) min_id = event.id;\n if (\n event.name === SNAP_EVENT &&\n event.created < before &&\n (max_id === undefined || event.id <= max_id) &&\n (boundary_id === undefined || event.id > boundary_id)\n )\n boundary_id = event.id;\n },\n { stream, stream_exact: true, with_snaps: true, after: -1 }\n );\n // No qualifying snapshot → nothing to prune behind. Otherwise a prune\n // is pending only when some event sorts below the boundary.\n return boundary_id !== undefined && min_id! < boundary_id;\n}\n\n/**\n * Min subscription watermark per target stream — the read-only probe\n * backing the windowed close's `max_id` cap. Pagination and source\n * matching mirror {@link partition_by_safety}; instead of flagging\n * pending streams it folds `min(at)` per stream. Streams with no\n * matching subscriptions are absent (no cap).\n *\n * @internal\n */\nasync function probe_min_watermarks(\n streams: string[],\n page_size: number,\n checkpoint: number\n): Promise<Map<string, number>> {\n const min_at = new Map<string, number>();\n const matches = source_matcher();\n await walk_streams(\n store(),\n (position) => {\n // Pending work caps at the watermark; caught up caps at the\n // checkpoint; an unmarked row keeps the conservative watermark.\n const pending =\n position.correlated_at === undefined ||\n position.at < position.correlated_at;\n const cap = pending ? position.at : Math.max(position.at, checkpoint);\n for (const stream of streams) {\n if (matches(position.source, stream)) {\n const prev = min_at.get(stream);\n if (prev === undefined || cap < prev) min_at.set(stream, cap);\n }\n }\n },\n { limit: page_size, source_matches: streams }\n );\n return min_at;\n}\n\n/**\n * Does a subscription with this `source` consume from `stream`? No source\n * consumes every stream; a literal source matches itself as a regex.\n * Compiled patterns are cached per matcher.\n */\nfunction source_matcher(): (\n source: string | undefined,\n stream: string\n) => boolean {\n const compiled = new Map<string, RegExp>();\n return (source, stream) => {\n if (!source) return true;\n let re = compiled.get(source);\n if (!re) {\n re = new RegExp(source);\n compiled.set(source, re);\n }\n return re.test(stream);\n };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 1 — scan stream heads\n// ---------------------------------------------------------------------------\n\nasync function scan_stream_heads(\n streams: string[]\n): Promise<Map<string, StreamHead>> {\n // query_stats returns the latest non-snap event per stream (heads-only\n // cheap path, indexed). Streams whose latest non-snap event is a tombstone\n // are filtered out in the loop — we don't want to re-tombstone an\n // already-closed stream. Streams with no events (or only snap/tombstone\n // events filtered out) are absent from the result map entirely.\n const stats = await store().query_stats(streams, {\n exclude: [SNAP_EVENT],\n });\n // Domain head, markers excluded. A stream absent here has no domain\n // events left, so a previous close ran to completion and there is\n // nothing to do. A stream present here whose `stats` head is a tombstone\n // was guarded and then interrupted — it must be resumed, not skipped.\n // `last_event_name` also has to come from this pass: the\n // restart-seed owner lookup needs the domain event, not the marker.\n const domain_heads = await store().query_stats(streams, {\n exclude: [SNAP_EVENT, TOMBSTONE_EVENT],\n });\n // The tombstone must expect the stream's real head version, which a\n // trailing `__snapshot__` raises by one. Everything else uses the domain\n // head, so the true head gets its own heads-only read.\n const true_heads = await store().query_stats(streams, {});\n const out = new Map<string, StreamHead>();\n for (const [stream, { head }] of domain_heads) {\n const marker_head = stats.get(stream)?.head;\n const interrupted = marker_head?.name === TOMBSTONE_EVENT;\n out.set(stream, {\n max_id: head.id,\n version: true_heads.get(stream)!.head.version,\n last_event_name: head.name as string,\n ...(interrupted ? { resumed_guard: { id: marker_head.id } } : {}),\n });\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2 — partition by safety\n// ---------------------------------------------------------------------------\n\nasync function partition_by_safety(\n stream_info: Map<string, StreamHead>,\n reactive: boolean,\n skipped: string[],\n page_size: number,\n catch_up_correlation: (until: number) => Promise<number>\n): Promise<string[]> {\n if (!reactive) return [...stream_info.keys()];\n\n // Correlate the tail first (see `catch_up_correlation`); anything still\n // above the cursor afterwards is held back.\n let needed = -1;\n for (const info of stream_info.values())\n needed = Math.max(needed, info.max_id);\n const checkpoint = await catch_up_correlation(needed);\n const uncorrelated = new Set<string>();\n for (const [stream, info] of stream_info) {\n if (checkpoint < info.max_id) uncorrelated.add(stream);\n }\n\n // Over-matching a source only widens the pending set, the safe direction.\n const pending_set = new Set<string>();\n const matches = source_matcher();\n\n // `source_matches` narrows the probe server-side to subscriptions that\n // could consume from a stream we're closing — a best-effort hint, so\n // the per-position source/target re-check below still runs and keeps\n // the result correct even when a store returns a superset.\n const targets = [...stream_info.keys()];\n\n // Every page, so a lagging reaction past the first one still counts.\n await walk_streams(\n store(),\n (position) => {\n // Pending means what `claim` means: a mark above the watermark. An\n // unmarked row has nothing to wait for; the catch-up above has landed\n // every mark that was owed.\n const has_work =\n position.correlated_at !== undefined &&\n position.at < position.correlated_at;\n if (!has_work) return;\n for (const [stream, info] of stream_info) {\n if (matches(position.source, stream) && position.at < info.max_id)\n pending_set.add(stream);\n }\n },\n { limit: page_size, source_matches: targets }\n );\n\n const safe: string[] = [];\n for (const [stream] of stream_info) {\n if (pending_set.has(stream) || uncorrelated.has(stream))\n 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 guard_with_tombstones(\n safe: string[],\n stream_info: Map<string, StreamHead>,\n correlation: string,\n tombstone: EsOps[\"tombstone\"],\n skipped: string[]\n): Promise<{\n guarded: string[];\n guard_events: Map<string, { id: number; stream: string }>;\n}> {\n const guarded: string[] = [];\n const guard_events = new Map<string, { id: number; stream: string }>();\n await Promise.all(\n safe.map(async (stream) => {\n const info = stream_info.get(stream)!;\n if (info.resumed_guard) {\n // Guard already written by the interrupted run — reuse it rather\n // than re-tombstoning (the version guard would reject it anyway).\n guarded.push(stream);\n guard_events.set(stream, { id: info.resumed_guard.id, stream });\n return;\n }\n const committed = await tombstone(stream, info.version, correlation);\n if (committed) {\n guarded.push(stream);\n guard_events.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, guard_events };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 4 — load restart seeds\n// ---------------------------------------------------------------------------\n\nasync function load_restart_seeds(\n guarded: string[],\n target_map: Map<string, CloseTarget>,\n stream_info: Map<string, StreamHead>,\n event_to_state: ReadonlyMap<string, State<any, any, any>>,\n load: EsOps[\"load\"],\n logger: Logger\n): Promise<Map<string, Schema>> {\n const seed_states = new Map<string, Schema>();\n await Promise.all(\n guarded\n .filter((s) => target_map.get(s)?.restart)\n .map(async (stream) => {\n // stream_info entry is guaranteed (guarded ⊆ stream_info.keys()).\n const last_event_name = stream_info.get(stream)!.last_event_name;\n const owner_state = event_to_state.get(last_event_name);\n if (!owner_state) {\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 \"${last_event_name}\". Stream will be tombstoned instead.`\n );\n return;\n }\n const snap = await load(owner_state, { stream });\n seed_states.set(stream, snap.state as Schema);\n })\n );\n return seed_states;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 5 — archive callbacks\n// ---------------------------------------------------------------------------\n\nasync function run_archive_callbacks(\n guarded: string[],\n target_map: 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 archive_fn = target_map.get(stream)?.archive;\n if (archive_fn) await archive_fn();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Phase 5b — confirm the guard is still the head\n// ---------------------------------------------------------------------------\n\nasync function heads_still_guarded(\n guarded: string[],\n guard_events: Map<string, { id: number; stream: string }>,\n skipped: string[]\n): Promise<string[]> {\n // True heads, markers included: the guard is a tombstone, and a reseed\n // by another closer is a snapshot.\n const heads = await store().query_stats(guarded, {});\n return guarded.filter((stream) => {\n if (heads.get(stream)?.head.id === guard_events.get(stream)!.id)\n return true;\n skipped.push(stream);\n return false;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Phase 6 — atomic truncate + cache warm\n// ---------------------------------------------------------------------------\n\nasync function truncate_and_warm_cache(\n guarded: string[],\n seed_states: Map<string, Schema>,\n guard_events: Map<string, { id: number; stream: string }>,\n correlation: string\n): Promise<CloseResult[\"truncated\"]> {\n const trunc_targets = guarded.map((stream) => {\n const snapshot = seed_states.get(stream);\n const guard = guard_events.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(trunc_targets);\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 = seed_states.get(stream);\n if (state && entry) {\n await cache().set(stream, {\n 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 * Correlation, the discovery half of correlate→drain: resolves each event to\n * its target streams and raises each target's work mark (`correlated_at`),\n * which is what `claim` reads. See docs/architecture/correlation-and-drain.\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { DEFAULT_LANE, log, store } from \"../ports.js\";\nimport type {\n EventRegister,\n Query,\n Registry,\n Resolved,\n SchemaRegister,\n Schemas,\n StreamPosition,\n SubscribeInput,\n} from \"../types/index.js\";\nimport { is_literal_source } from \"../utils.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport { LruMap } from \"./lru-map.js\";\nimport { report_once } from \"./report-once.js\";\n\n/**\n * First-boot scan starts this far below the watermark, so an event committed\n * but not correlated before a crash is found again. Re-scanning is harmless:\n * `subscribe` is an idempotent upsert and a mark never regresses.\n */\nconst COLD_START_BACK_SCAN = 10_000;\n\n/**\n * Too short and a slow scan outruns its lease (duplicate work, still safe);\n * too long and a crashed holder stalls discovery.\n */\nconst CORRELATION_LEASE_MS = 5_000;\n\n/**\n * The correlation lease key: a hash of every reacted-to event name with its\n * handler names, so only interchangeable workers share a lease. See\n * docs/architecture/correlation-and-drain § The correlation lease.\n */\nconst registry_key = <TEvents extends Schemas>(\n events: EventRegister<TEvents>\n): string => {\n const shape = Object.keys(events)\n .filter((name) => events[name].reactions.size > 0)\n .sort()\n .map((name) => [name, [...events[name].reactions.keys()].sort()]);\n return createHash(\"sha256\")\n .update(JSON.stringify(shape))\n .digest(\"hex\")\n .slice(0, 32);\n};\n\n/** Bound on compiled pattern sources; guards a resolver that mints one per event. */\nconst PATTERN_CACHE_SIZE = 32;\n\n/** Static resolver target collected at build time and subscribed at init. */\nexport type StaticTarget = {\n readonly stream: string;\n readonly source?: string;\n readonly priority?: number;\n readonly lane?: string;\n};\n\n/**\n * What a target's subscription row holds. A resolution sends its own\n * priority/lane only when it beats `floor` (`+Infinity` for static targets);\n * otherwise it re-sends these values with the mark. The store owns the lane;\n * this only caches it, so a missing record is re-read from the row.\n */\ntype Subscription = {\n readonly floor: number;\n readonly priority: number;\n readonly lane: string | undefined;\n};\n\n/** One target accumulated during a scan; `correlated_at` is its work mark. */\ntype Correlated = {\n source: string | undefined;\n priority: number;\n lane: string | undefined;\n /** True when priority/lane came from a resolution that beat the floor. */\n upgraded: boolean;\n /** True when the target had no record, so its row must be read. */\n missed: boolean;\n /** The reaction whose resolution set priority/lane. */\n handler: string;\n correlated_at: number | undefined;\n};\n\n/** Constructor dependencies for {@link CorrelateCycle}. */\nexport type CorrelateCycleDeps<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n> = {\n registry: Registry<TSchemaReg, TEvents, TActions>;\n static_targets: ReadonlyArray<StaticTarget>;\n cd: DrainOps<TEvents>;\n max_subscribed_streams: number;\n /** Every lane a controller exists for; others are rerouted to default. */\n declared_lanes: ReadonlySet<string>;\n /** Set when `onlyLanes` leaves a lane out; each shard gets its own lease. */\n shard?: ReadonlyArray<string>;\n on_init?: () => void;\n on_init_async?: () => Promise<void>;\n};\n\n/**\n * A dynamic resolution named an undeclared lane. Rerouted to `\"default\"`\n * rather than skipped, so the work still runs. Reported once per reaction\n * and lane, since a resolver mints one target per aggregate.\n */\nfunction report_undeclared_lane(\n seen: Set<string>,\n handler: string,\n target: string,\n lane: string,\n declared: ReadonlySet<string>\n): void {\n report_once(\n seen,\n `lane|${handler}|${lane}`,\n `Reaction \"${handler}\" resolved onto undeclared lane \"${lane}\" — for example target \"${target}\". ` +\n `Declared lanes: ${[...declared].map((l) => `\"${l}\"`).join(\", \")}. ` +\n 'No controller claims it, so the stream would never drain — running it on \"default\" instead. ' +\n \"The equivalent static `.to({ lane })` is rejected at build; a dynamic resolver's lane is only knowable here.\"\n );\n}\n\n/**\n * Two resolutions disagreed on one target's lane. Reported, not corrected:\n * re-laning a live stream would move it out from under a lease holder.\n * Keyed by orientation, since \"first discovered\" can land either way.\n */\nfunction report_lane_conflict(\n seen: Set<string>,\n handler: string,\n target: string,\n kept: string,\n dropped: string\n): void {\n report_once(\n seen,\n `conflict|${handler}|${kept}|${dropped}`,\n `Reaction \"${handler}\" resolved lane \"${dropped}\" for a stream already on \"${kept}\" — for example \"${target}\". ` +\n `These are conflicting lane assignments from two dynamic resolutions at equal priority. ` +\n `Keeping \"${kept}\", the lane it was first discovered on — re-laning a live stream would move it out from under a worker holding its lease. ` +\n `The reaction resolving \"${dropped}\" runs inside the \"${kept}\" lane's budget, and a process restricted to \"${dropped}\" via onlyLanes never runs it. ` +\n \"The equivalent static declaration is rejected at build; align the resolvers, or split the target.\"\n );\n}\n\n/** Drives correlation for one Act: the checkpoint, the lease, the subscription records. */\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 /** Lease holder id; per instance, so a restart never inherits a stale claim. */\n private readonly _by = randomUUID();\n private readonly _key: string;\n /** Local expiry of the held lease (0 = none); stale only costs a duplicate scan. */\n private _lease_until = 0;\n /** Raised by a commit or notification, lowered by a short page. Starts armed. */\n private _armed = true;\n private _init_promise: Promise<void> | undefined;\n // Bounded by `maxSubscribedStreams`; static records live apart so eviction\n // never drops their +Infinity floor.\n private readonly _dynamic_subscriptions: LruMap<string, Subscription>;\n private readonly _static_subscriptions = new Map<string, Subscription>();\n private readonly _patterns = new LruMap<string, RegExp>(PATTERN_CACHE_SIZE);\n private readonly _registry: Registry<TSchemaReg, TEvents, TActions>;\n private readonly _static_targets: ReadonlyArray<StaticTarget>;\n private readonly _cd: DrainOps<TEvents>;\n private readonly _on_init: (() => void) | undefined;\n /** Runs once after `on_init`; re-seeds defer timers across a restart. */\n private readonly _on_init_async: (() => Promise<void>) | undefined;\n private readonly _declared_lanes: ReadonlySet<string>;\n /** Report-once keys; per instance because `internal/` holds no module state. */\n private readonly _reported = new Set<string>();\n\n constructor({\n registry,\n static_targets,\n cd,\n max_subscribed_streams,\n declared_lanes,\n shard,\n on_init,\n on_init_async,\n }: CorrelateCycleDeps<TSchemaReg, TEvents, TActions>) {\n this._key = shard\n ? `${registry_key(registry.events)}:${[...shard].sort().join(\",\")}`\n : registry_key(registry.events);\n this._dynamic_subscriptions = new LruMap(max_subscribed_streams);\n this._registry = registry;\n this._declared_lanes = declared_lanes;\n this._static_targets = static_targets;\n this._cd = cd;\n this._on_init = on_init;\n this._on_init_async = on_init_async;\n }\n\n get checkpoint(): number {\n return this._checkpoint;\n }\n\n /** A commit (local or remote) may have produced uncorrelated events. */\n arm(): void {\n this._armed = true;\n }\n\n async init(): Promise<void> {\n if (this._initialized) return;\n // Single-flight, but a failure clears the promise so the next call retries.\n if (!this._init_promise) {\n this._init_promise = this._run_init().catch((error) => {\n this._init_promise = undefined;\n throw error;\n });\n }\n await this._init_promise;\n this._initialized = true;\n }\n\n private async _run_init(): Promise<void> {\n const { watermark, correlated_at } = await this._cd.subscribe([\n ...this._static_targets,\n ]);\n this._checkpoint =\n correlated_at >= 0\n ? correlated_at\n : Math.max(-1, watermark - COLD_START_BACK_SCAN);\n this._on_init?.();\n for (const { stream, priority = 0, lane } of this._static_targets) {\n this._static_subscriptions.set(stream, {\n floor: Number.POSITIVE_INFINITY,\n priority,\n lane,\n });\n }\n // After the static subscribe, so the streams walk sees them.\n await this._on_init_async?.();\n }\n\n /** After `restore` replaced the log: forget everything and cold-start again. */\n restart(): void {\n this._initialized = false;\n this._init_promise = undefined;\n this._checkpoint = -1;\n this._dynamic_subscriptions.clear();\n this._static_subscriptions.clear();\n this._armed = true;\n }\n\n /** Forget dynamic targets whose rows a full close deleted, so they re-subscribe. */\n forget_subscribed(streams: Iterable<string>): void {\n for (const stream of streams) this._dynamic_subscriptions.delete(stream);\n }\n\n /** Would the target's own `fetch` (filtered by `source`) return this event? */\n private _in_fetch_window(\n source: string | undefined,\n stream: string\n ): boolean {\n if (source === undefined || source === stream) return true;\n if (is_literal_source(source)) return false;\n let pattern = this._patterns.get(source);\n if (!pattern) {\n pattern = new RegExp(source);\n this._patterns.set(source, pattern);\n }\n return pattern.test(stream);\n }\n\n /** Scan past the checkpoint, subscribe new targets and raise their work marks. */\n async correlate(\n query: Query = { after: -1, limit: 10 },\n /**\n * Honour the correlation lease. Only the settle loop and poller do; an\n * explicit `app.correlate()` scans now, since `close` loops on it.\n */\n lease = false\n ): Promise<{\n subscribed: number;\n last_id: number;\n marked: number;\n scanned: boolean;\n }> {\n await this.init();\n\n // A remote writer without notify leaves this disarmed; the poller re-arms.\n if (!this._armed)\n return {\n subscribed: 0,\n last_id: this._checkpoint,\n marked: 0,\n scanned: false,\n };\n\n // The lease rides `subscribe` with no streams (\"may I scan?\"). Its shared\n // checkpoint is ignored: adopting it would skip events this worker never\n // read. Renew at the halfway mark.\n const now = Date.now();\n if (lease && now >= this._lease_until - CORRELATION_LEASE_MS / 2) {\n const { correlating } = await this._cd.subscribe([], undefined, {\n key: this._key,\n by: this._by,\n millis: CORRELATION_LEASE_MS,\n });\n this._lease_until = correlating ? now + CORRELATION_LEASE_MS : 0;\n // `undefined` = store without leasing. Refused: stay armed, look again.\n if (correlating === false)\n return {\n subscribed: 0,\n last_id: this._checkpoint,\n marked: 0,\n scanned: false,\n };\n }\n\n const after = Math.max(this._checkpoint, query.after || -1);\n const correlated = new Map<string, Correlated>();\n let last_id = after;\n // A resolver threw: the scan stops before that event, so the next one\n // retries it and nothing past it is lost.\n let stopped = false;\n const found = await store().query<TEvents>(\n (event) => {\n if (stopped) return;\n const register = this._registry.events[event.name];\n if (register) {\n for (const reaction of register.reactions.values()) {\n let resolved: Resolved | undefined;\n try {\n resolved =\n typeof reaction.resolver === \"function\"\n ? reaction.resolver(event)\n : reaction.resolver;\n } catch (error) {\n stopped = true;\n report_once(\n this._reported,\n `resolver|${reaction.handler.name}|${event.id}`,\n `Resolver of reaction \"${reaction.handler.name}\" threw on ${String(event.name)} #${event.id} (stream \"${event.stream}\"): ${String(error)}. ` +\n \"Correlation stops before this event until the resolver stops throwing; work already found keeps draining.\"\n );\n return;\n }\n if (!resolved) continue;\n let lane = resolved.lane;\n if (lane !== undefined && !this._declared_lanes.has(lane)) {\n report_undeclared_lane(\n this._reported,\n reaction.handler.name,\n resolved.target,\n lane,\n this._declared_lanes\n );\n lane = undefined;\n }\n const recorded =\n this._static_subscriptions.get(resolved.target) ??\n this._dynamic_subscriptions.get(resolved.target);\n const priority = resolved.priority ?? 0;\n const upgraded = !recorded || priority > recorded.floor;\n const carried = upgraded\n ? { priority, lane }\n : { priority: recorded.priority, lane: recorded.lane };\n const entry = correlated.get(resolved.target) || {\n source: resolved.source,\n priority: carried.priority,\n lane: carried.lane,\n upgraded,\n missed: !recorded,\n handler: reaction.handler.name,\n correlated_at: undefined,\n };\n // Compare against what the target already carries, from this\n // scan or a past one.\n const seen_in_scan = correlated.has(resolved.target);\n const held_lane =\n (seen_in_scan ? entry.lane : recorded?.lane) ?? DEFAULT_LANE;\n const held_priority = seen_in_scan\n ? entry.priority\n : recorded?.priority;\n const resolved_lane = lane ?? DEFAULT_LANE;\n if (held_priority === priority && held_lane !== resolved_lane)\n report_lane_conflict(\n this._reported,\n reaction.handler.name,\n resolved.target,\n held_lane,\n resolved_lane\n );\n // Within one scan the highest priority sets the lane.\n if (carried.priority > entry.priority) {\n entry.priority = carried.priority;\n entry.lane = carried.lane;\n entry.upgraded = upgraded;\n entry.handler = reaction.handler.name;\n }\n if (this._in_fetch_window(resolved.source, event.stream))\n entry.correlated_at = event.id;\n correlated.set(resolved.target, entry);\n }\n }\n last_id = event.id;\n },\n // Resolvers see `pii: null`: correlate runs actor-less, and one\n // undecryptable row would otherwise stop every stream's reactions.\n { ...query, after, with_pii: false }\n );\n\n if (this._declared_lanes.size > 1) await this._recall(correlated);\n\n // Only targets with a mark to raise or priority/lane to register.\n const streams: SubscribeInput[] = [];\n for (const [stream, entry] of correlated) {\n if (entry.upgraded || entry.correlated_at !== undefined)\n streams.push({\n stream,\n source: entry.source,\n priority: entry.priority,\n lane: entry.lane,\n correlated_at: entry.correlated_at,\n });\n }\n\n if (streams.length) {\n // Leasing renews for free on the same call.\n const renewed_at = Date.now();\n const { subscribed, correlating } = await this._cd.subscribe(\n streams,\n last_id,\n lease\n ? { key: this._key, by: this._by, millis: CORRELATION_LEASE_MS }\n : undefined\n );\n if (lease && correlating !== false)\n this._lease_until = renewed_at + CORRELATION_LEASE_MS;\n // The orchestrator arms on re-marks too, not just new subscriptions.\n const marked = streams.filter(\n (entry) => entry.correlated_at !== undefined\n ).length;\n this._checkpoint = last_id;\n // Only dynamic targets can be upgraded (statics sit at +Infinity).\n for (const { stream, priority, lane } of streams) {\n if (correlated.get(stream)?.upgraded)\n this._dynamic_subscriptions.set(stream, {\n floor: priority as number,\n priority: priority as number,\n lane,\n });\n }\n return { subscribed, last_id, marked, scanned: true };\n }\n // Only a short page proves the log is exhausted; resolving nothing does not.\n this._checkpoint = last_id;\n this._armed = stopped || found === query.limit;\n return { subscribed: 0, last_id, marked: 0, scanned: true };\n }\n\n /**\n * Read the row of each target this scan had no record of (new or evicted),\n * so a resolution that doesn't beat its priority keeps the row's lane.\n * Only called with more than one lane declared.\n */\n private async _recall(correlated: Map<string, Correlated>): Promise<void> {\n const missed = [...correlated].filter(([, entry]) => entry.missed);\n await Promise.all(\n missed.map(async ([stream, entry]) => {\n let row: StreamPosition | undefined;\n await store().query_streams(\n (position) => {\n row = position;\n },\n { stream, stream_exact: true, limit: 1 }\n );\n if (!row) return;\n this._dynamic_subscriptions.set(stream, {\n floor: row.priority,\n priority: row.priority,\n lane: row.lane,\n });\n if (entry.priority > row.priority) return;\n const held_lane = row.lane ?? DEFAULT_LANE;\n const resolved_lane = entry.lane ?? DEFAULT_LANE;\n if (entry.priority === row.priority && held_lane !== resolved_lane)\n report_lane_conflict(\n this._reported,\n entry.handler,\n stream,\n held_lane,\n resolved_lane\n );\n entry.priority = row.priority;\n entry.lane = row.lane;\n entry.upgraded = false;\n })\n );\n }\n\n /** Release the lease early by re-acquiring it for zero ms. Best-effort. */\n async release_correlation(): Promise<void> {\n try {\n this._lease_until = 0;\n await this._cd.subscribe([], undefined, {\n key: this._key,\n by: this._by,\n millis: 0,\n });\n } catch (error) {\n log().warn(\n `Could not hand back the correlation lease during shutdown; it expires on its own within ${CORRELATION_LEASE_MS}ms and correlation resumes normally after that. ` +\n \"On a single-writer store this usually means another connection holds the database. \" +\n `Cause: ${String(error)}`\n );\n }\n }\n}\n","/**\n * @module report-once\n * @category Internal\n *\n * One-shot reporting for a misdeclaration that a build-time guard could not\n * catch.\n *\n * The guards in `build_events` and `build-classify` can only inspect a static\n * `.to({...})` — a `.to(fn)` target, lane and priority are a function until an\n * event arrives. The pipelines that resolve them (correlate for lane and\n * target, drain for the payload) are therefore where the same rules have to be\n * applied, and where the operator has to be told.\n *\n * Reporting there has one hazard the build-time guards don't: a resolver fires\n * for *every* matching event, so a naive log turns one bad declaration into a\n * line per event on a busy stream. Reporting once per offending declaration is\n * what makes the message readable.\n *\n * Which makes the key the whole design. It may only be built from things the\n * *declaration* names — handler names, event names, lane names, a statically\n * declared target — and never from a value a resolver computed at runtime.\n * A resolved target is the trap: the documented per-aggregate shape is\n * `.to(e => ({target: e.stream}))`, so a target-keyed report dedups nothing\n * across aggregates and one typo scales into one line per aggregate — the\n * unbounded volume this module exists to prevent. Runtime values\n * still belong in the *message*, as the concrete example that turns \"a\n * reaction misdeclared its lane\" into something an operator can go look at.\n *\n * Never throws. A throw inside correlate pins the checkpoint for the whole app;\n * inside drain it reaches the circuit breaker as a store failure and\n * stalls every stream.\n *\n * @internal\n */\n\nimport { log } from \"../ports.js\";\n\n/**\n * Report `message` the first time `key` is seen, and never again.\n *\n * `seen` belongs to the calling pipeline and is passed in, so a resolver\n * firing for every matching event still reports once without this module\n * remembering anything between calls — `internal/` holds no module state.\n *\n * @param seen - The caller's set of already-reported keys. Mutated.\n * @param key - Identifies the offending declaration, not the occurrence —\n * declared identifiers only, never a runtime-resolved target.\n * @param message - Wrapped in an `Error` so the logger renders a stack.\n *\n * @internal\n */\nexport function report_once(\n seen: Set<string>,\n key: string,\n message: string\n): void {\n if (seen.has(key)) return;\n seen.add(key);\n log().error(new Error(message));\n}\n","/**\n * @module correlator\n * @category Internal\n *\n * Correlation-id generator and the default implementation.\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 default_correlator: 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 close_correlation(\n correlator: Correlator,\n actor: Actor\n): string {\n return correlator({\n state: \"$close\",\n action: \"close\",\n stream: \"$close\",\n actor,\n });\n}\n","/**\n * @module date-reviver\n * @category Internal\n *\n * Turning stored text back into `Date`s, driven by the declared schema.\n *\n * JSON has no date type, so a `Date` is stored as its ISO form and something\n * has to revive it on the way out. Which fields those are is a property of the\n * Zod schema, so working it out is a Zod concern rather than an event one —\n * this module knows nothing about events, states or PII. It takes a declared\n * schema and returns the schema that revives its dates, or `undefined` when\n * there are none to revive.\n *\n * Sits beside the other schema utilities rather than inside the event builder,\n * which composes it: `event_tags` asks for one reviver for an event's `data`\n * and another for the sensitive fields held in its `pii` sidecar. One function\n * is the whole interface — how a Zod schema is taken apart stays in here.\n *\n * The shape-based {@link dateReviver} in `utils.ts` is the predecessor this\n * replaced — it revived anything ISO-8601-looking, including fields declared\n * `z.string()`.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\n\n/** Zod exposes its shape under `_zod.def` in v4 and `def` in older builds. */\nconst def_of = (schema: unknown): Record<string, unknown> | undefined =>\n (schema as { _zod?: { def?: Record<string, unknown> } })._zod?.def ??\n (schema as { def?: Record<string, unknown> }).def;\n\n/**\n * Rebuild one union variant so it still recognises its own payloads.\n *\n * Same date coercion as everywhere else, but the variant keeps its other\n * fields — this is the one place the date paths alone are not enough. A\n * variant can only reject a sibling's payload if enough of its shape is left\n * to check, and which fields do that is not knowable: a literal discriminator\n * usually does it, but a union can just as well be told apart by the *type* of\n * an ordinary field. Narrowing to the dates, or relaxing the rest, makes the\n * first variant match everything, so the one that declared the date is never\n * tried and a sibling's payload is read under the wrong rules.\n *\n * Every key is optional, so the variant still matches when a `sensitive(...)`\n * field sits in the `pii` sidecar or when a stored payload predates a field\n * the declaration has since gained.\n *\n * Reports whether this variant declared a date, so a union with none anywhere\n * builds nothing at all.\n */\nfunction variant_schema(schema: unknown): {\n schema: z.ZodType;\n dated: boolean;\n} {\n const shape = def_of(schema)?.shape as Record<string, z.ZodType> | undefined;\n if (!shape) {\n const dates = date_reviver_schema(schema);\n return { schema: dates ?? (schema as z.ZodType), dated: !!dates };\n }\n const next: Record<string, z.ZodType> = {};\n let dated = false;\n for (const [key, field] of Object.entries(shape)) {\n const dates = date_reviver_schema(field);\n if (dates) dated = true;\n next[key] = (dates ?? field).optional();\n }\n return { schema: z.looseObject(next), dated };\n}\n\n/**\n * Build the schema that revives an event's dates, or `undefined` when it\n * declares none.\n *\n * JSON has no date type, so a stored `Date` comes back as text and something\n * has to turn it back. That is this function's only job, and the schema it\n * returns says only where the dates are: every other field is left out and\n * rides through the loose object untouched. The payload was validated when it\n * was committed, so re-checking it on the way out would be work already done.\n *\n * Naming only the dates is also what makes a read tolerant, without needing a\n * rule per exception. A `sensitive(...)` field lives in the `pii` sidecar\n * rather than in `data`; an event written against an older declaration\n * predates whatever was added since; a field dropped from the declaration is\n * still in the store. None of those are dates, so none of them are described\n * here, and a payload carrying any of them still reads. The dates themselves\n * are optional for the same reason — absent is not wrong.\n *\n * Zod does the walking, so nesting, arrays, records, unions and the wrappers\n * are handled by the engine rather than by a traversal of our own that would\n * drift as Zod grows constructs. A construct this doesn't recognise\n * contributes no date, which is the documented fallthrough.\n */\nexport function date_reviver_schema(schema: unknown): z.ZodType | undefined {\n const def = def_of(schema);\n if (!def) return undefined;\n const inner = () => date_reviver_schema(def.innerType);\n switch (def.type) {\n case \"date\":\n return z.coerce.date();\n case \"object\": {\n const shape = def.shape as Record<string, z.ZodType> | undefined;\n if (!shape) return undefined;\n const dated: Record<string, z.ZodType> = {};\n for (const [key, field] of Object.entries(shape)) {\n const dates = date_reviver_schema(field);\n if (dates) dated[key] = dates.optional();\n }\n return Object.keys(dated).length ? z.looseObject(dated) : undefined;\n }\n case \"array\": {\n const element = date_reviver_schema(def.element);\n return element && z.array(element);\n }\n case \"tuple\": {\n const items = (def.items as unknown[]).map((i) => date_reviver_schema(i));\n return items.some(Boolean)\n ? z.tuple(items.map((i) => i ?? z.unknown()) as never)\n : undefined;\n }\n case \"record\": {\n const value = date_reviver_schema(def.valueType);\n return value && z.record(z.string(), value);\n }\n case \"union\": {\n // A union is the one place the date paths are not enough. Zod picks a\n // variant by trying each until one matches, so an option reduced to its\n // dates matches almost anything and the first one wins — the variant\n // that actually declared the date never gets tried, and a sibling's\n // payload gets the wrong variant's rules. Every option therefore keeps\n // its fields; see {@link variant_schema}.\n const variants = (def.options as unknown[]).map(variant_schema);\n return variants.some((v) => v.dated)\n ? z.union(variants.map((v) => v.schema) as never)\n : undefined;\n }\n case \"nullable\":\n // Keep the null: coercing it would hand back the epoch.\n return inner()?.nullable();\n case \"optional\":\n case \"nonoptional\":\n case \"readonly\":\n case \"default\":\n case \"prefault\":\n case \"catch\":\n return inner();\n default:\n return undefined;\n }\n}\n","/**\n * @module defer-config\n * @category Internal\n *\n * The `when` options for the public `defer` surface. A\n * reaction defers itself to a future time either declaratively (the\n * `.defer(when)` builder step) or imperatively (`throw new DeferSignal(when)`\n * inside a handler); both resolve `when` through here.\n *\n * The load-bearing rule is **derivability**. A deferred stream's due-time must\n * be recomputable by whichever worker re-claims it after the wait, so `when`\n * never resolves against `Date.now()`. `after` is measured from the triggering\n * event's `created` timestamp, and `at` is either a fixed `Date` or a pure\n * function of the event. Either way, re-delivering the same event yields the\n * same due-time, which is what makes a defer correct across restarts and\n * competing workers.\n *\n * Validation follows the config-schema standard (CLAUDE.md): an internal\n * `*OptionsSchema` const, a public inferred type, and a resolver. Slice 2\n * ships `after` / `at`; recurrence (`every`) extends this in Slice 3.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { Committed, DeferWhen, Schemas } from \"../types/index.js\";\nimport { DeferSignal } from \"./defer-signal.js\";\n\n/**\n * A relative span, measured from the triggering event's `created` time. At\n * least one field is required; fields are additive (`{ hours: 1, minutes: 30 }`\n * is 90 minutes).\n */\nconst DeferDurationSchema = z\n .object({\n days: z.number().positive().optional(),\n hours: z.number().positive().optional(),\n minutes: z.number().positive().optional(),\n })\n .strict()\n .refine((d) => d.days != null || d.hours != null || d.minutes != null, {\n message: \"defer: a duration needs at least one of days, hours, or minutes\",\n });\n\n/**\n * Zod schema for the `defer(when)` options bag. Exactly one of `after` / `at`;\n * `at` is an absolute `Date`. Internal per the config standard; the public\n * surface is {@link DeferWhen} and {@link resolve_defer_at}.\n *\n * @internal\n */\nconst DeferWhenSchema = z\n .object({\n after: DeferDurationSchema.optional(),\n at: z.date().optional(),\n })\n .strict()\n .refine((w) => (w.after === undefined) !== (w.at === undefined), {\n message: \"defer: specify exactly one of `after` or `at`\",\n });\n\n/** Sum a duration bag to milliseconds. @internal */\nfunction duration_ms(d: {\n days?: number;\n hours?: number;\n minutes?: number;\n}): number {\n return (\n (d.days ?? 0) * 86_400_000 +\n (d.hours ?? 0) * 3_600_000 +\n (d.minutes ?? 0) * 60_000\n );\n}\n\n/**\n * Resolve `when` to an absolute due-time (ms since epoch) for a given\n * triggering event. Validates via {@link DeferWhenSchema} (throws `ZodError`\n * on a bad shape), then derives the time: `after` from `event.created`, `at`\n * from its absolute `Date`. Never reads `Date.now()`, so the result is stable\n * across re-delivery.\n *\n * @internal\n */\nexport function resolve_defer_at<E extends Schemas>(\n when: DeferWhen,\n event: Committed<E, keyof E>\n): number {\n const parsed = DeferWhenSchema.parse(when);\n if (parsed.after) return event.created.getTime() + duration_ms(parsed.after);\n return parsed.at!.getTime();\n}\n\n/**\n * The schedule handed to the declarative `.defer` builder step: either a\n * literal {@link DeferWhen} (fixed cooldown/deadline) or a function of the\n * triggering event (read the payload to choose the schedule).\n *\n * @internal\n */\nexport type DeferSchedule<TEvent> = DeferWhen | ((event: TEvent) => DeferWhen);\n\n/**\n * Validate a literal `when` at build time (fail fast, per the config-schema\n * standard) — throws `ZodError` on a bad shape (both/neither of `after`/`at`,\n * an empty or non-positive duration). The function form of a `.defer` schedule\n * can only be checked when it runs, so builders pass just the literal here.\n *\n * @internal\n */\nexport function assert_defer_when(when: DeferWhen): void {\n DeferWhenSchema.parse(when);\n}\n\n/**\n * Wrap a reaction handler so it holds until its schedule is due, then runs.\n * On each delivery it resolves the schedule against the triggering event; if\n * the due-time hasn't arrived it throws {@link DeferSignal} (the drain holds\n * the stream, no watermark advance, no retry bump), otherwise it runs the\n * real handler. The wrapper keeps the original handler's `name` so reaction\n * registration and de-dup are unaffected, and preserves the handler's exact\n * type so the builder step is transparent.\n *\n * @internal\n */\nexport function make_deferred<H extends (...args: any[]) => Promise<unknown>>(\n handler: H,\n schedule: DeferSchedule<Parameters<H>[0]>\n): H {\n const call = handler as (...args: unknown[]) => Promise<unknown>;\n const deferred = async (\n event: Parameters<H>[0],\n stream: string,\n app: unknown\n ) => {\n const when = typeof schedule === \"function\" ? schedule(event) : schedule;\n if (Date.now() < resolve_defer_at(when, event)) throw new DeferSignal(when);\n return call(event, stream, app);\n };\n Object.defineProperty(deferred, \"name\", { value: handler.name });\n return deferred as unknown as H;\n}\n","/**\n * The drain pipeline: {@link run_drain_cycle} is one stateless\n * claim → fetch → dispatch → ack/block round-trip; {@link DrainController}\n * owns the armed flag, the lock, the lag/lead ratio and the defer wake.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { log } from \"../ports.js\";\nimport { NonRetryableError } from \"../types/errors.js\";\nimport type {\n BatchHandler,\n BlockedLease,\n CloseTarget,\n Drain,\n DrainOptions,\n Fetch,\n Lease,\n Logger,\n ReactionOptions,\n ReactionPayload,\n Registry,\n Resolved,\n SchemaRegister,\n Schemas,\n} from \"../types/index.js\";\nimport { compute_backoff_delay } from \"./backoff.js\";\nimport type { CircuitBreaker } from \"./circuit-breaker.js\";\nimport {\n DEFAULT_BACKOFF,\n DEFAULT_EVENT_LIMIT,\n DEFAULT_LEASE_MILLIS,\n DEFAULT_STREAM_LIMIT,\n} from \"./config.js\";\nimport { DeferTimer } from \"./defer-timer.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport { compute_lag_lead_ratio } from \"./drain-ratio.js\";\nimport { report_once } from \"./report-once.js\";\nimport { trace_cycle } from \"./tracing.js\";\n\n/** Outcome of handling one leased stream; drives its ack/block. */\nexport type HandleResult = Readonly<{\n lease: Lease;\n handled: number;\n /** Last successful event id, or `lease.at` when there was no work. */\n acked_at: number;\n error?: string;\n block?: boolean;\n /** Epoch ms of the next retry, from the backoff. Only set on a retry. */\n next_attempt_at?: number;\n /** Epoch ms to redeliver a deferred stream; no error, no retry bump. */\n defer?: number;\n /** From a `CloseSignal`; acked first so the close guard sees it caught up. */\n close?: CloseTarget;\n /** Event id that threw (sparse ids make it differ from `acked_at + 1`); never in batch mode. */\n failed_at?: number;\n}>;\n\n/** `Act.handle`. */\nexport type Handle<TEvents extends Schemas> = (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[]\n) => Promise<HandleResult>;\n\n/** `Act.handle_batch`. */\nexport type HandleBatch<TEvents extends Schemas> = (\n lease: Lease,\n payloads: ReactionPayload<TEvents>[],\n batchHandler: BatchHandler<TEvents>\n) => Promise<HandleResult>;\n\ntype 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 readonly closeable: CloseTarget[];\n};\n\n/**\n * Blocks a stream whose retries were all spent losing the lease (no handler\n * error ever reached the block decision). Strictly `> maxRetries`: the final\n * attempt runs at `=== maxRetries`. Stands down while the store is failing,\n * since `claim` counts retries no handler earned.\n */\nfunction budget_exhausted<TEvents extends Schemas>(\n lease: Lease,\n options: ReactionPayload<TEvents>[\"options\"] | undefined,\n store_failing: boolean\n): HandleResult | undefined {\n if (\n store_failing ||\n !options?.blockOnError ||\n lease.retry <= options.maxRetries\n )\n return undefined;\n const error = `Blocking ${lease.stream} after ${lease.retry} claims with no acknowledged progress — the retry budget (${options.maxRetries}) was spent without the handler ever reporting an error. That means every attempt lost its lease before it could ack: move the reaction to a lane whose leaseMillis covers the handler, then unblock the stream.`;\n log().error(error);\n return { lease, handled: 0, acked_at: lease.at, error, block: true };\n}\n\n/**\n * A failed fetch has no payloads to say which reaction it was for, so take\n * the most conservative policy: block only if every reaction does, after\n * the largest budget.\n */\nfunction fetch_failure_policy<\n TSchemaReg extends SchemaRegister<TActions>,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(registry: Registry<TSchemaReg, TEvents, TActions>): ReactionOptions {\n let blockOnError = true;\n let maxRetries = 0;\n for (const register of Object.values(registry.events))\n for (const reaction of register.reactions.values()) {\n blockOnError &&= reaction.options.blockOnError;\n maxRetries = Math.max(maxRetries, reaction.options.maxRetries);\n }\n return { blockOnError, maxRetries };\n}\n\n/** A resolver's error, and the options of the reaction it belongs to. */\ntype ResolverFailure = { error: Error; options: ReactionOptions };\n\n/**\n * The one retry-or-block decision for a stream that failed: a handler,\n * a resolver, or the stream's own fetch. The error string always rides\n * the result; the drain decides whether to ack partial progress from\n * `handled > 0`, not from the error.\n */\nexport function 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 non_retryable = error instanceof NonRetryableError;\n const block =\n options.blockOnError &&\n (non_retryable || lease.retry >= options.maxRetries);\n if (block)\n logger.error(\n non_retryable\n ? `Blocking ${lease.stream} on non-retryable error.`\n : `Blocking ${lease.stream} after ${lease.retry} retries.`\n );\n // Every retry is paced by the reaction's backoff, or the default one;\n // terminal blocks never defer. `lease.retry` here is the just-failed\n // attempt's counter, so the delay paces the *next* attempt.\n const next_attempt_at = block\n ? undefined\n : Date.now() +\n compute_backoff_delay(lease.retry, options.backoff ?? DEFAULT_BACKOFF);\n return {\n lease,\n handled,\n acked_at: at,\n error: error.message,\n block,\n next_attempt_at,\n failed_at,\n };\n}\n\n/** Reported once per declaration; every key part is declared, so it stays bounded. */\nfunction warn_misrouted(\n seen: Set<string>,\n stream: string,\n handler: string,\n event: string\n): void {\n report_once(\n seen,\n `${stream}|${handler}|${event}`,\n `Reaction \"${handler}\" on \"${event}\" resolved to target \"${stream}\", which a projection already serves. ` +\n \"A target is served by one batch handler or one state projection, so this reaction can never run — and delivering to it would hand the projection an aggregate from another stream. \" +\n \"Skipping it. The equivalent static `.to({ target })` is rejected at build; a dynamic resolver's target is only knowable here.\"\n );\n}\n\ntype CycleInput = {\n readonly lagging: number;\n readonly leading: number;\n readonly eventLimit: number;\n readonly leaseMillis: number;\n readonly misrouted: Set<string>;\n readonly store_failing: boolean;\n};\n\n/** One drain cycle; `undefined` when nothing was claimed. */\nasync function run_drain_cycle<\n TEvents extends Schemas,\n TActions extends Schemas,\n TSchemaReg extends SchemaRegister<TActions>,\n>(\n deps: DrainControllerDeps<TEvents, TActions, TSchemaReg>,\n cycle: CycleInput\n): Promise<DrainCycle<TEvents> | undefined> {\n const { ops, registry, batch_handlers, handle, handle_batch, lane } = deps;\n const {\n lagging,\n leading,\n eventLimit,\n leaseMillis,\n misrouted,\n store_failing,\n } = cycle;\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 const fetched = await ops.fetch(leased, eventLimit);\n\n type FetchEntry = (typeof fetched)[number];\n const fetch_map = new Map<\n string,\n {\n fetch: FetchEntry;\n payloads: ReactionPayload<TEvents>[];\n failed?: ResolverFailure;\n }\n >();\n\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 let failed: ResolverFailure | undefined;\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 resolver = reaction.resolver;\n const dynamic = typeof resolver === \"function\";\n let resolved: Resolved | undefined;\n try {\n resolved = dynamic ? resolver(event) : resolver;\n } catch (error) {\n failed ??= {\n error: new Error(\n `Resolver of reaction \"${reaction.handler.name}\" threw on ${String(event.name)} #${event.id} (stream \"${event.stream}\"): ${String(error)}`\n ),\n options: reaction.options,\n };\n return false;\n }\n if (!resolved || resolved.target !== stream) return false;\n // A dynamic resolution onto a projection's target: skip and report.\n // Not a throw, which would read as a store failure.\n if (!dynamic || !batch_handlers.has(stream)) return true;\n warn_misrouted(\n misrouted,\n stream,\n reaction.handler.name,\n String(event.name)\n );\n return false;\n })\n .map((reaction) => ({ ...reaction, event }));\n });\n fetch_map.set(stream, { fetch: f, payloads, failed });\n }\n\n const handled = await Promise.all(\n leased.map((lease) => {\n const entry = fetch_map.get(lease.stream)!;\n // Retried after the default backoff; blocks once the budget is spent,\n // unless the whole store is failing (the breaker's job).\n if (entry.fetch.error !== undefined) {\n const policy = fetch_failure_policy(registry);\n return Promise.resolve(\n finalize(\n lease,\n 0,\n lease.at,\n new Error(`Fetch failed for ${lease.stream}: ${entry.fetch.error}`),\n store_failing ? { ...policy, blockOnError: false } : policy,\n deps.logger\n )\n );\n }\n // A resolver threw: this stream fails like a handler would.\n if (entry.failed)\n return Promise.resolve(\n finalize(\n lease,\n 0,\n lease.at,\n entry.failed.error,\n entry.failed.options,\n deps.logger\n )\n );\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 exhausted = budget_exhausted(\n lease,\n payloads[0]?.options,\n store_failing\n );\n if (exhausted) return Promise.resolve(exhausted);\n const batchHandler = batch_handlers.get(lease.stream);\n if (batchHandler && payloads.length > 0) {\n return handle_batch({ ...lease, at }, payloads, batchHandler);\n }\n return handle({ ...lease, at }, payloads);\n })\n );\n\n // `block` before `ack`: block needs the lease, ack releases it. A\n // partial-progress block goes to both. Deferred and backing-off entries\n // carry `due`, so one `ack` also persists the schedule (defer: retry -1).\n const blocked = await ops.block(\n handled\n .filter(({ block }) => block)\n .map(({ lease, error }) => ({ ...lease, error: error! }))\n );\n\n // Before the `ack`, so an ack failure can't lose the terminal event.\n if (blocked.length) deps.on_blocked(blocked);\n\n const submitted = handled.flatMap((h, i) => {\n const advance = h.handled > 0 ? h.acked_at : leased[i].at;\n return h.defer !== undefined\n ? { ...h.lease, at: advance, due: h.defer, retry: -1 }\n : h.next_attempt_at !== undefined\n ? { ...h.lease, at: advance, due: h.next_attempt_at }\n : h.handled > 0 || !h.error\n ? { ...h.lease, at: h.acked_at }\n : [];\n });\n const acked = await ops.ack(submitted);\n\n // `ack` drops entries whose lease another worker took (deferred entries\n // are never returned).\n const expected = submitted.filter((l) => l.due === undefined).length;\n if (acked.length < expected)\n log().warn(\n `drain: ${expected - acked.length} of ${expected} acks were dropped — the lease was taken by another worker mid-handler. That work will be redelivered (at-least-once), but persistent drops mean leaseMillis is too short for this handler.`\n );\n\n const closeable = handled\n .filter((h) => h.close !== undefined)\n .map((h) => h.close!);\n\n return { leased, fetched, handled, acked, blocked, closeable };\n}\n\nconst EMPTY_DRAIN: Drain<Schemas> = {\n fetched: [],\n leased: [],\n acked: [],\n blocked: [],\n};\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 batch_handlers: Map<string, BatchHandler<TEvents>>;\n readonly handle: Handle<TEvents>;\n readonly handle_batch: HandleBatch<TEvents>;\n readonly on_acked: (acked: Lease[]) => void;\n readonly on_blocked: (blocked: BlockedLease[]) => void;\n /** Awaited, so a slow close doesn't overlap the next claim. */\n readonly on_close: (targets: CloseTarget[]) => Promise<void>;\n readonly breaker: CircuitBreaker;\n /** The worker ticks outside any caller frame, so its drain is re-scoped. */\n readonly run_scoped: <T>(fn: () => Promise<T>) => Promise<T>;\n /** Lane this controller drains. Undefined spans all lanes. */\n readonly lane?: string;\n /** The lane's own config; it wins over the caller's DrainOptions. */\n readonly defaults?: {\n readonly streamLimit?: number;\n readonly leaseMillis?: number;\n };\n};\n\n/** Wake key for the controller's own retry; no stream is named \"\". */\nconst RETRY = \"\";\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 * Local wake at the earliest parked (backoff or defer) visit, or at the\n * lease expiry after a failed pass (the {@link RETRY} key); the schedule\n * itself is persisted. On an idle app nothing else would drain it. It\n * drains until a pass leases nothing, and an entry stays until handled or\n * until a later pass claims nothing.\n */\n private readonly _defer = new DeferTimer(() => {\n this._armed = true;\n void this._deps.run_scoped(async () => {\n while ((await this.drain()).leased.length > 0);\n });\n });\n private _worker: ReturnType<typeof setTimeout> | undefined;\n private readonly _misrouted = new Set<string>();\n private _stopped = false;\n /** Never rejects; graceful shutdown waits on it. */\n private _inflight: Promise<void> | undefined;\n private _inflight_done: (() => void) | undefined;\n\n private readonly _deps: DrainControllerDeps<TEvents, TActions, TSchemaReg>;\n\n constructor(deps: DrainControllerDeps<TEvents, TActions, TSchemaReg>) {\n this._deps = deps;\n }\n\n arm(): void {\n this._armed = true;\n }\n\n /** Cold start: re-seed a persisted `deferred_at` into the local wake. */\n seed_defer(stream: string, at: number): void {\n this._defer.set(stream, at);\n this._defer.schedule();\n }\n\n get armed(): boolean {\n return this._armed;\n }\n\n get inflight(): Promise<void> | undefined {\n return this._inflight;\n }\n\n /** This lane's configured lease, or `undefined`; the shutdown grace basis. */\n get lease_millis(): number | undefined {\n return this._deps.defaults?.leaseMillis;\n }\n\n get lane(): string | undefined {\n return this._deps.lane;\n }\n\n /** Drains every `cycleMs` while armed; the unref'd timer never holds the process. */\n start(cycleMs: number): void {\n if (this._worker || this._stopped) return;\n // `drain()` never throws.\n const run = this._deps.run_scoped;\n const tick = async () => {\n if (this._armed) await run(() => 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(): void {\n this._stopped = true;\n if (this._worker) {\n clearTimeout(this._worker);\n this._worker = undefined;\n }\n this._defer.stop();\n }\n\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 // A lane's own budget wins over caller options.\n const streamLimit =\n d.streamLimit ?? options.streamLimit ?? DEFAULT_STREAM_LIMIT;\n const eventLimit = options.eventLimit ?? DEFAULT_EVENT_LIMIT;\n const leaseMillis =\n d.leaseMillis ?? options.leaseMillis ?? DEFAULT_LEASE_MILLIS;\n\n // Circuit open: stay armed and leave the wake alone (re-aiming would fire\n // at once for anything due); the breaker's own wake re-aims it.\n if (this._deps.breaker.state(Date.now()) === \"open\")\n return EMPTY_DRAIN as Drain<TEvents>;\n\n try {\n this._locked = true;\n this._inflight = new Promise<void>((done) => {\n this._inflight_done = done;\n });\n const lagging = Math.ceil(streamLimit * this._ratio);\n const leading = streamLimit - lagging;\n\n const started = Date.now();\n const cycle = await run_drain_cycle(this._deps, {\n lagging,\n leading,\n eventLimit,\n leaseMillis,\n misrouted: this._misrouted,\n store_failing: this._deps.breaker.failing,\n });\n\n if (!cycle) {\n // Caught up: whatever was due when this pass started has no work.\n this._defer.prune(started);\n this._deps.breaker.passed();\n this._armed = false;\n return EMPTY_DRAIN as Drain<TEvents>;\n }\n\n const { leased, fetched, handled, acked, blocked, closeable } = cycle;\n\n trace_cycle(this._deps.logger, leased, fetched, handled, acked, blocked);\n\n this._ratio = compute_lag_lead_ratio(handled, lagging, leading);\n\n for (const lease of acked) this._defer.delete(lease.stream);\n for (const lease of blocked) this._defer.delete(lease.stream);\n for (const h of handled) {\n const next = h.defer ?? h.next_attempt_at;\n if (next !== undefined) this._defer.set(h.lease.stream, next);\n }\n\n // Listener throws are contained in `Act.emit`.\n if (acked.length) this._deps.on_acked(acked);\n // The orchestrator contains close failures; anything that still\n // throws here reaches the breaker.\n if (closeable.length) await this._deps.on_close(closeable);\n\n // After `on_close`, so a failed close never counts as a store success.\n this._deps.breaker.passed();\n\n return { fetched, leased, acked, blocked };\n } catch (error) {\n // A store op threw: stay armed and retry after the breaker's cooldown,\n // never before this pass's leases expire, so an idle app retries\n // without waiting for the breaker to open.\n this._defer.set(\n RETRY,\n Date.now() + Math.max(leaseMillis, this._deps.breaker.cooldown_ms)\n );\n this._deps.breaker.failed(Date.now(), error);\n return EMPTY_DRAIN as Drain<TEvents>;\n } finally {\n // Re-aim at the earliest stream still parked.\n if (!this._stopped) this._defer.schedule();\n this._locked = false;\n this._inflight = undefined;\n this._inflight_done?.();\n this._inflight_done = undefined;\n }\n }\n}\n","/**\n * @module defer-timer\n * @category Internal\n *\n * The shared \"next visit time\" primitive. A `DeferTimer` holds a\n * `stream → due-time` map and a single collapsed wake timer: it parks\n * streams that should be re-visited later and fires one `on_wake` callback\n * at the earliest pending due-time.\n *\n * The {@link \"drain-cycle\".DrainController} rides it for per-reaction\n * backoff (a retry's `next_attempt_at`) and for the `defer` outcome, which\n * holds a stream pending without advancing the watermark or bumping `retry`.\n * The wake runs a drain, and the drain re-schedules the timer when it ends.\n * An entry stays until its stream is acked or blocked, re-parked, or a\n * drain that started after it came due claims nothing ({@link prune}): a\n * wake that lands during another drain, or a pass that reaches only some of\n * the due streams, leaves the rest due, so the next re-schedule fires again\n * at once.\n *\n * Lives in process memory, per worker — the same per-worker pacing trade-off\n * documented for backoff. Durability comes from the data the due-time is\n * *derived* from (an un-advanced watermark, an event's `created` timestamp),\n * not from the map. A restart empties the map, so the cold-start rebuild is\n * explicit: `CorrelateCycle.init` seeds each still-future `deferred_at` back\n * onto the owning lane's timer via {@link \"drain-cycle\".DrainController.seed_defer},\n * so an idle deferred stream re-arms at its due-time with no\n * intervening commit.\n *\n * @internal\n */\n\n/**\n * A min-heap-free scheduler over a small `stream → due-time` map. The maps\n * are bounded by the worker's claim/stream limits, so a linear scan for the\n * earliest entry is cheaper than maintaining a heap.\n *\n * @internal\n */\n\n/**\n * Node's `setTimeout` delay is a 32-bit signed int (~24.8 days). A larger\n * delay overflows and fires immediately, so we cap at this and re-arm.\n *\n * @internal\n */\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nexport class DeferTimer {\n private readonly _due = new Map<string, number>();\n private _timer: ReturnType<typeof setTimeout> | undefined;\n private readonly _on_wake: () => void;\n\n /**\n * @param on_wake - invoked once each time the earliest due-time elapses.\n * The consumer re-schedules for whatever is still parked.\n */\n constructor(on_wake: () => void) {\n this._on_wake = on_wake;\n }\n\n /** Number of currently parked streams. */\n get size(): number {\n return this._due.size;\n }\n\n /**\n * Park `stream` for a re-visit at `at` (ms since epoch). A plain\n * overwrite: the caller computes the authoritative next-visit for the\n * stream (the drain's `handle` already reconciles a stream's reactions\n * into one result per cycle), so there is no stale value to merge against.\n */\n set(stream: string, at: number): void {\n this._due.set(stream, at);\n }\n\n /** Drop `stream` from the parked set (e.g. on a successful ack or block). */\n delete(stream: string): void {\n this._due.delete(stream);\n }\n\n /**\n * Drop every entry due at or before `before`. The drain calls it when a\n * pass that started at `before` claimed nothing: whatever was due by then\n * was handled elsewhere (another worker) or has no work left, so waking\n * for it again would spin.\n */\n prune(before: number): void {\n for (const [stream, at] of this._due)\n if (at <= before) this._due.delete(stream);\n }\n\n /**\n * (Re)schedule the wake timer at the earliest pending due-time. Idempotent\n * — collapses many parked streams into a single timer. A no-op clears any\n * pending timer when the map is empty.\n *\n * The timer is `unref()`-ed so pending re-visits never keep the process\n * alive on their own.\n */\n schedule(): void {\n if (this._timer) clearTimeout(this._timer);\n if (this._due.size === 0) {\n this._timer = undefined;\n return;\n }\n let earliest = Number.POSITIVE_INFINITY;\n for (const t of this._due.values()) if (t < earliest) earliest = t;\n // Clamp to setTimeout's 32-bit ceiling (~24.8 days). A longer due-time\n // (e.g. a 90-day autoclose cooldown) would otherwise overflow and Node\n // fires it immediately, busy-looping. Instead we wake at the ceiling: the\n // still-future entry stays, the consumer re-schedules for the remaining\n // span, and (for persisted defers) `claim` skips the stream until its\n // real due-time anyway.\n const delay = Math.min(\n Math.max(0, earliest - Date.now()),\n MAX_TIMER_DELAY_MS\n );\n this._timer = setTimeout(() => {\n this._timer = undefined;\n this._on_wake();\n }, delay);\n this._timer.unref();\n }\n\n /** Cancel any pending wake timer. Idempotent. Leaves the parked set intact. */\n stop(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\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 compute_lag_lead_ratio(\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 SubscribeInput,\n SubscribeResult,\n} from \"../types/index.js\";\nimport { is_literal_source } from \"../utils.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 // A literal `source` fetches with `stream_exact` so an exact name\n // like \"s1\" reads only \"s1\" — never a sibling prefix \"s12\". A\n // pattern source (e.g. `^(A|B)$`) stays a regex query, matching the\n // same streams correlate resolved it for.\n const stream_exact =\n source !== undefined && is_literal_source(source) ? true : undefined;\n try {\n await store().query<TEvents>((e) => events.push(e), {\n stream: source,\n stream_exact,\n after: at,\n limit: eventLimit,\n });\n } catch (error) {\n // Contain it per stream. These reads are already per-stream, but they\n // shared one `Promise.all`, so one stream's failure rejected the whole\n // cycle and every healthy stream leased beside it got nothing —\n // an unreadable `pii` payload on one aggregate stalled unrelated\n // reactions. The cycle turns this into a no-progress failure\n // for THIS stream only, which the retry budget then escalates.\n //\n // Unlike correlate, this read cannot simply decline the payload:\n // handlers receive it (through their own gate), so a fetch that\n // dropped it would hand them a silently incomplete event.\n return {\n stream,\n source,\n at,\n lagging,\n events: [],\n error: (error as Error)?.message ?? String(error),\n } as const;\n }\n return { stream, source, at, lagging, events } as const;\n })\n );\n}\n\n// Finalize: acks and defers in one atomic store call. Leases\n// carrying `due` are deferred, the rest acked — a failed finalize lands\n// nothing, and redelivery covers every outcome uniformly.\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: SubscribeInput[],\n correlated_at?: number,\n correlator?: { key: string; by: string; millis: number }\n): Promise<SubscribeResult> =>\n store().subscribe(streams, correlated_at, correlator);\n","/**\n * Event-sourcing primitives: `snap`, `load`, `action`, `tombstone`, `scan`.\n * Bare implementations; tracing wraps them in `tracing.ts`.\n */\n\nimport { type Patch, 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 CacheEntry,\n Committed,\n DoOptions,\n Emitted,\n EventMeta,\n EventSource,\n LoadTarget,\n ScanOptions,\n ScanResult,\n Schema,\n Schemas,\n Snapshot,\n State,\n Target,\n} from \"../types/index.js\";\nimport { sleep, validate } from \"../utils.js\";\nimport { compute_backoff_delay } from \"./backoff.js\";\nimport { default_correlator } from \"./correlator.js\";\n\n/**\n * The patch step: merges a reducer's partial into state. Chosen once at\n * construction (`build_es`), never per event. `me`/`event` only serve\n * {@link validating_patch}, to name the failing reduction.\n */\nexport type PatchFn = <\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(\n me: State<TState, TEvents, TActions>,\n state: TState,\n partial: Readonly<Patch<TState>>,\n event: Committed<TEvents, keyof TEvents>\n) => TState;\n\n/** The default patch step: a bare merge, so the hot path pays nothing. */\nexport const bare_patch: PatchFn = (_me, state, partial) =>\n patch(state, partial) as typeof state;\n\n/**\n * `validateFoldedState`: merge, then parse against the state schema, so a\n * bad reducer fails at its own event. A debugging aid, not a production guard.\n */\nexport const validating_patch: PatchFn = (me, state, partial, event) => {\n const next = patch(state, partial) as typeof state;\n return validate(\n `${me.name}.${String(event.name)}#${event.id}`,\n next,\n me.state\n );\n};\n\nconst DEFAULT_BATCH = 500;\n\n/** `action` with the correlator and patch step bound by `build_es`. */\ntype 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 options?: DoOptions<TEvents>\n) => Promise<Snapshot<TState, TEvents>[]>;\n\nexport interface EsOps {\n snap: typeof snap;\n load: typeof load;\n action: BoundAction;\n tombstone: typeof tombstone;\n}\n\n/** Writes a cache checkpoint. A failure only costs the next load a re-fold. */\nconst cache_put = <TState extends Schema>(\n stream: string,\n entry: CacheEntry<TState>\n): Promise<void> =>\n cache()\n .set(stream, entry)\n .catch((err) =>\n log().warn(\n err,\n \"cache set skipped; the next load re-folds from the store\"\n )\n );\n\n/** Drops a cache checkpoint. A failure leaves a stale one, which re-folds. */\nconst cache_drop = (stream: string): Promise<void> =>\n cache()\n .invalidate(stream)\n .catch((err) =>\n log().warn(\n err,\n \"cache invalidate skipped; a stale checkpoint re-folds from its event_id\"\n )\n );\n\n/** Commits a snapshot event. Never throws: a failed snapshot must not fail the action. */\nexport async function snap<TState extends Schema, TEvents extends Schemas>(\n snapshot: Snapshot<TState, TEvents>\n): Promise<Committed<TEvents, keyof TEvents> | undefined> {\n const { id, stream, name, meta, version } = snapshot.event!;\n try {\n const [committed] = 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 return committed as Committed<TEvents, keyof TEvents>;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n log().warn(\n `Snapshot write failed on stream \"${stream}\": ${reason} — cold starts will replay full history until snapshots succeed.`\n );\n }\n}\n\n/**\n * Commits the close guard at `expectedVersion`; `undefined` when the stream\n * moved. Actions then see the tombstone at head and throw {@link StreamClosedError}.\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 * Rejects a negative version or an invalid `created` Date. Duplicate ids and\n * version gaps are left to the sink (partial backups have gaps).\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 * Pages a restore source: validation, drop filters, migrations, progress and\n * causation remap. Adapters supply only the per-event insert `callback`\n * (see {@link Store.restore}). A source that ignores `limit` (`CsvFile`)\n * returns everything in one page.\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 {\n drop_snapshots = false,\n drop_closed_streams = false,\n on_progress,\n event_migrations,\n stream_rename,\n } = 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 dropped_closed = 0;\n let migrated_count = 0;\n let processed = 0;\n let at: number | undefined;\n\n // `drop_closed_streams`: one extra walk to collect tombstoned streams.\n const closed_streams = new Set<string>();\n if (drop_closed_streams) {\n await source.query<Schemas>(\n (e) => {\n if (e.name === TOMBSTONE_EVENT) closed_streams.add(e.stream);\n },\n { names: [TOMBSTONE_EVENT] }\n );\n }\n\n // Probe the highest id (an index seek on SQL stores). A source that\n // ignores the filter returns more than one row; leave max_id unknown.\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, with_snaps: true }\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 (\n closed_streams.has(event.stream) &&\n event.name !== TOMBSTONE_EVENT\n ) {\n // Keep the tombstone: it is what keeps the stream closed.\n dropped_closed++;\n return;\n }\n // Before the causation remap, so `id_map` stays keyed by source id.\n let migrated: typeof event = event;\n const migration = event_migrations?.[event.name as string];\n if (migration) {\n const old_data = migration.from_schema.parse(event.data);\n const new_data = migration.migrate(old_data);\n migration.to_schema.parse(new_data);\n migrated = {\n ...event,\n name: migration.to as typeof event.name,\n data: new_data as any,\n };\n migrated_count++;\n }\n if (stream_rename) {\n const renamed = stream_rename(migrated.stream);\n if (renamed !== migrated.stream)\n migrated = { ...migrated, stream: renamed };\n }\n if (!callback) {\n kept++;\n return;\n }\n let remapped = migrated;\n const caused_by = migrated.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 // Spread `migrated`, not `event`, or the migration is undone.\n remapped = {\n ...migrated,\n meta: {\n ...migrated.meta,\n causation: {\n ...migrated.meta.causation,\n event: {\n ...migrated.meta.causation.event!,\n id: new_caused_by,\n },\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, with_snaps: true }\n );\n\n // Stop on a short page, or on an oversized one (the source ignored the\n // limit and already returned everything).\n if (got !== limit) break;\n at = id;\n }\n\n return {\n kept,\n migrated: migrated_count,\n dropped: {\n closed_streams: dropped_closed,\n snapshots: dropped_snaps,\n },\n };\n}\n\n/**\n * Folds a stream into state, from the cached checkpoint or the latest\n * snapshot. `asOf` time-travels and bypasses the cache.\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 target: LoadTarget,\n callback?: (snapshot: Snapshot<TState, TEvents>) => void,\n patch_fn: PatchFn = bare_patch\n): Promise<Snapshot<TState, TEvents>> {\n const { stream, actor, asOf } = target;\n const time_travel =\n !!asOf && Object.values(asOf).some((v) => v !== undefined);\n const cached = time_travel ? 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 // Events this load processed; `patches` is the snap distance from the cache.\n let replayed = 0;\n let event: Committed<TEvents, keyof TEvents> | undefined;\n\n await store().query<TEvents>(\n (raw) => {\n event = me.view(raw, actor);\n if (event.name === SNAP_EVENT) {\n state = event.data as TState;\n snaps++;\n patches = 0;\n replayed++;\n } else if (me.patch[event.name]) {\n state = patch_fn(me, state, me.patch[event.name](event, state), event);\n patches++;\n replayed++;\n } else if (event.name !== TOMBSTONE_EVENT) {\n // A renamed event, the wrong state, or a contaminated stream.\n log().warn(\n `Skipping unknown event \"${String(event.name)}\" on stream \"${stream}\" (id=${event.id}) — no reducer in state \"${me.name}\"`\n );\n }\n callback?.({\n event,\n state,\n version: event.version,\n id: event.id,\n patches,\n snaps,\n cache_hit,\n replayed,\n });\n },\n {\n stream,\n stream_exact: true,\n // `with_snaps` on every non-time-travel load: cold, it resumes from the\n // latest snapshot; warm, it keeps a snapshot above a stale checkpoint,\n // so a windowed close's prune can't fold the tail onto stale state.\n ...(cached\n ? { after: cached.event_id, with_snaps: true }\n : { ...(time_travel ? {} : { with_snaps: true }), ...asOf }),\n }\n );\n\n // A stale write self-corrects: the next load replays past its `event_id`.\n // Not at a tombstone head, or `action()`'s closed check would pass vacuously.\n const head_is_tombstone = event?.name === TOMBSTONE_EVENT;\n if (\n replayed > 0 &&\n !time_travel &&\n event &&\n !me.pii_aware &&\n !head_is_tombstone\n ) {\n await cache_put(stream, {\n stream,\n state,\n version: event.version,\n event_id: event.id,\n patches,\n snaps,\n });\n }\n\n return {\n event,\n state,\n version: event?.version ?? cached?.version ?? -1,\n // Captured with `state`, so consumers never race a separate cache lookup.\n id: event?.id ?? cached?.event_id ?? -1,\n patches,\n snaps,\n cache_hit,\n replayed,\n };\n}\n\n/**\n * Validates, checks invariants, emits and commits. On {@link ConcurrencyError}\n * it re-runs from `load` within the action's `maxRetries`; any other error\n * rethrows. Reactions commit without the inferred version guard.\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 options?: DoOptions<TEvents>,\n patch_fn: PatchFn = bare_patch\n): Promise<Snapshot<TState, TEvents>[]> {\n const { stream, expectedVersion, actor } = target;\n if (!stream) throw new Error(\"Missing target stream\");\n // `Act.do` already filled in the ambient reaction context.\n const reactingTo = options?.reactingTo;\n const correlator = options?.correlator ?? default_correlator;\n\n const validated = validate(action as string, payload, me.actions[action]);\n\n const opts = me.options?.[action];\n const max_retries = opts?.maxRetries ?? 0;\n\n for (let attempt = 0; ; attempt++) {\n try {\n const snapshot = await load(\n me,\n { stream, actor: target.actor },\n undefined,\n patch_fn\n );\n if (snapshot.event?.name === TOMBSTONE_EVENT)\n throw new StreamClosedError(stream);\n // `version`, not `event`: on a warm hit `event` is undefined. A new\n // stream (-1) stays unguarded.\n const expected =\n expectedVersion ??\n (snapshot.version >= 0 ? snapshot.version : undefined);\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 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 const valid = tuples.map(([name, data]) => ({\n name,\n data: validate(name as string, data, me.events[name]),\n }));\n const emitted = valid.map((e) => me.message(e));\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\n },\n event: reactingTo\n ? {\n id: reactingTo.id,\n name: reactingTo.name as string,\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 the inferred version guard (leases already\n // serialize them); an explicit expectedVersion is still honored.\n reactingTo ? expectedVersion : expected\n );\n } catch (error) {\n // Fire-and-forget, so a cache failure can't replace the ConcurrencyError.\n if (error instanceof ConcurrencyError) void cache_drop(stream);\n throw error;\n }\n\n let { state, patches } = snapshot;\n const snapshots = committed.map((row, i) => {\n // The caller sent the plaintext, so no view/gate round-trip.\n const event = { ...row, data: valid[i].data };\n const p = me.patch[event.name](event, state);\n state = patch_fn(me, state, p, event);\n patches++;\n return {\n event,\n state,\n version: event.version,\n id: event.id,\n patches,\n snaps: snapshot.snaps,\n patch: p,\n cache_hit: snapshot.cache_hit,\n replayed: snapshot.replayed,\n };\n });\n\n const last = snapshots.at(-1)!;\n // A guardless (reaction) commit can land past events this fold never\n // saw; a gapped fold must not become a snapshot or a cache entry.\n const contiguous = committed[0].version === snapshot.version + 1;\n const snapped = contiguous && me.snap?.(last);\n\n // Awaited, so the cache holds the post-snap checkpoint for the next caller.\n const snap_event = snapped ? await snap(last) : undefined;\n\n // Sensitive states depend on the actor, so they aren't cached.\n if (!me.pii_aware) {\n if (contiguous)\n void cache_put<TState>(stream, {\n stream,\n state: last.state,\n version: snap_event?.version ?? last.event.version,\n event_id: snap_event?.id ?? last.event.id,\n patches: snap_event ? 0 : last.patches,\n snaps: snap_event ? last.snaps + 1 : last.snaps,\n });\n else void cache_drop(stream);\n }\n\n return snapshots;\n } catch (error) {\n if (!(error instanceof ConcurrencyError)) throw error;\n // A caller-pinned version would conflict again on every retry.\n if (expectedVersion !== undefined) throw error;\n if (attempt >= max_retries) throw error;\n if (opts?.backoff) {\n const delay_ms = compute_backoff_delay(attempt, opts.backoff);\n if (delay_ms > 0) await sleep(delay_ms);\n }\n }\n }\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 build_es} and {@link build_drain} — 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 { default_correlator } from \"./correlator.js\";\nimport type { DrainOps } from \"./drain.js\";\nimport * as drain from \"./drain.js\";\nimport type { EsOps, PatchFn } 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 * 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 show_lane = lane && lane !== \"default\";\n if (PRETTY) {\n const tag = `${C_DRAIN}>> ${caption}${C_RESET}`;\n return show_lane ? `${tag} ${C_LANE}${lane}${C_RESET}` : tag;\n }\n return show_lane ? `>> ${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 build_es(\n logger: Logger,\n correlator: Correlator = default_correlator,\n patch_fn: PatchFn = es.bare_patch\n): EsOps {\n // Bake the orchestrator-level `correlator` into every `action()` call\n // so EsOps callers don't need to thread it. A per-call\n // `options.correlator` still wins — the orchestrator default fills in\n // only when the caller didn't supply one.\n //\n // The per-event patch step is selected ONCE by the builder\n // (`act-builder.ts`) — bare vs validating — and passed in here already\n // bound, so this factory stays agnostic to `validateFoldedState`. It\n // just bakes the given `patch_fn` into the load/action closures, so\n // the projection-fold engine and close-cycle callers inherit the same\n // choice without threading anything through their own signatures. The\n // default (`bare_patch`) keeps direct callers on the plain path.\n const bound_action: EsOps[\"action\"] = (\n me,\n action_name,\n target,\n payload,\n options\n ) =>\n es.action(\n me,\n action_name,\n target,\n payload,\n { correlator, ...options },\n patch_fn\n );\n const bound_load: EsOps[\"load\"] = (me, target, callback) =>\n es.load(me, target, callback, patch_fn);\n if (logger.level !== \"trace\") {\n return {\n snap: es.snap,\n load: bound_load,\n action: bound_action,\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(bound_load, (result, _me, target) => {\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 `${target.stream}${as_of_marker(target.asOf)} ${cache_marker(result.cache_hit)} ${stats}`\n )\n );\n }),\n action: traced(\n bound_action,\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 build_drain<TEvents extends Schemas>(\n logger: Logger\n): DrainOps<TEvents> {\n // Cycle-level tracing happens in `DrainController.drain()` via\n // {@link trace_cycle} — 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 run_drain_cycle) 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 uniform_lane =\n lanes.size === 1 ? streams[0]?.lane : undefined;\n const data = streams\n .map(({ stream, lane }) =>\n uniform_lane || !lane || lane === \"default\"\n ? hue(C_STREAM, stream)\n : `${hue(C_STREAM, stream)}${dim(`[${lane}]`)}`\n )\n .join(\" \");\n logger.trace(\n `${drain_caption(\"correlated\", uniform_lane)} ${data}`\n );\n }),\n };\n}\n\n/**\n * Emit one cycle-level drain trace summarizing what happened in a\n * single `run_drain_cycle` 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 trace_cycle<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 fetch_by_stream = new Map(fetched.map((f) => [f.stream, f]));\n const acked_by_stream = new Map(acked.map((a) => [a.stream, a.at]));\n const blocked_by_stream = 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 failed_by_stream = 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 = fetch_by_stream.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 = 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 acked_at = acked_by_stream.get(stream);\n const ack_part =\n acked_at !== undefined\n ? hue(C_HIT, `✓ @${acked_at}`) // ✓ + new at in lime\n : \"\";\n const failure = failed_by_stream.get(stream);\n let fail_part = \"\";\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 failed_at = failure.failed_at ?? at;\n const blocked_error = blocked_by_stream.get(stream);\n if (blocked_error !== undefined) {\n fail_part = `${hue(C_ERR, `✗ @${failed_at}/${retry}`)} ${dim(`(${blocked_error})`)}`;\n } else {\n fail_part = `${hue(C_MISS, `⚠ @${failed_at}/${retry}`)} ${dim(`(${failure.error})`)}`;\n }\n }\n let tail: string;\n if (ack_part && fail_part) tail = ` ${ack_part} ${fail_part}`;\n else if (ack_part) tail = ` ${ack_part}`;\n else if (fail_part) tail = ` ${fail_part}`;\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 projection-fold\n * @category Internal\n *\n * Fold engine behind `projection(name).of(state)` — maintains per-stream\n * folded states in a bounded in-memory cache and flushes one row per dirty\n * stream per round, so write amplification tracks the distinct-key count\n * instead of the event count.\n *\n * The flush payload deliberately has no type of its own: a state\n * projection flushes the cache layer outward — the rows ARE the\n * streams' {@link CacheEntry} values.\n *\n * Correctness discipline:\n * - The engine runs as the projection's batch handler, so the watermark\n * acks only after a fully-flushed batch — fold work is never\n * acknowledged before it is durable.\n * - On first sight of a stream the engine loads its head state through\n * the same `load()` the command path uses (cache, snapshots and all).\n * The loaded snapshot carries its own head position (`version` and the\n * global event `id`), captured atomically with `state`, so the engine\n * never pairs a stale state with a newer head id read separately from\n * the cache. Fetched events at or below the loaded id are\n * skipped, later ones fold through the state's own patch reducers.\n * - Eviction under `maxCachedStates` pressure flushes the evictee first\n * (flush-before-evict) — eviction never loses folded work.\n */\nimport type {\n BatchHandler,\n CacheEntry,\n Schema,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport type { FoldConfig } from \"./config.js\";\nimport { bare_patch, load, type PatchFn } from \"./event-sourcing.js\";\nimport { pii_strip } from \"./sensitive.js\";\n\n// The fold config schema, defaults, and resolver live in `./config.js` (the\n// single home for builder-facing config bags). This module keeps the fold\n// engine that consumes the resolved config.\n\n/**\n * A stream's in-flight fold: a mutable {@link CacheEntry} plus the\n * engine's `dirty` flag. Mutable because the hot loop updates one\n * object per stream rather than allocating per event; the required\n * frontier fields are what keep a warm-cache load from ever\n * re-applying history. Stripping `dirty` at the flush boundary yields\n * the entry — the flush payload IS the cache entry.\n */\ntype Fold<TState extends Schema> = {\n -readonly [K in keyof CacheEntry<TState>]: CacheEntry<TState>[K];\n} & { dirty: boolean };\n\n/**\n * Internal handle a fold handler exposes so the orchestrator can drop its\n * process-local state.\n *\n * A rebuild must not trust a per-Act cache: `reset` rewinds the watermark and\n * replays from the beginning, and every replayed event is at or below the\n * cached head, so the fold takes its already-folded branch and re-flushes\n * whatever it happens to hold. If that cache is stale, the rebuild writes the\n * staleness back out — the one outcome a rebuild exists to prevent. Dropping\n * the cache makes the next batch re-load head state from the store, which is\n * authoritative by definition.\n *\n * A symbol on the function keeps `BatchHandler` a plain function type; nothing\n * here is re-exported from `src/index.ts`.\n */\nexport const FOLD_RESET = Symbol(\"act.fold.reset\");\n\n/** A batch handler that owns a fold cache it can be told to drop. */\nexport type ResettableBatchHandler<TEvents extends Schemas> =\n BatchHandler<TEvents> & {\n readonly [FOLD_RESET]?: () => void;\n };\n\n/**\n * Build the batch handler that folds a state's events into per-stream rows.\n * The returned closure is long-lived (one per built projection): its cache\n * survives across drain cycles, so warm streams fold without I/O. It carries\n * a {@link FOLD_RESET} handle so a rebuild can drop that cache.\n */\nexport function make_fold_handler<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n>(\n me: State<TState, TEvents, TActions>,\n flush: (rows: ReadonlyArray<CacheEntry<TState>>) => Promise<void>,\n config: FoldConfig,\n patch_fn: PatchFn = bare_patch,\n sensitive_fields: (event_name: string) => readonly string[]\n): BatchHandler<TEvents> {\n // First-sight head loads must apply the SAME PII treatment as the warm\n // path (which folds `pii_strip`ped events handed in by the batch handler):\n // sensitive keys removed entirely, not gated to `[REDACTED]`. `load()`\n // folds over `me.view`, so compose the view with `pii_strip` for sensitive\n // events — otherwise an actorless head load would gate to `[REDACTED]` and\n // the projected row would differ from the warm path by cache warmth.\n // For a non-PII projection every lookup is empty, so `load_me === me`\n // behaviorally.\n const load_me: State<TState, TEvents, TActions> = {\n ...me,\n view: (raw, actor) => {\n const viewed = me.view(raw, actor);\n const fields = sensitive_fields(viewed.name as string);\n return fields.length\n ? (pii_strip(viewed as never, fields) as typeof viewed)\n : viewed;\n },\n };\n // Insertion-ordered Map as LRU: first key is the oldest. A promote is\n // delete + re-insert. Not the shared LruMap — eviction here must await\n // a flush, and a sync auto-evicting set() would drop folded work.\n const cache = new Map<string, Fold<TState>>();\n\n const row = ({ dirty: _, ...row }: Fold<TState>): CacheEntry<TState> => row;\n\n const flush_dirty = async () => {\n const rows: CacheEntry<TState>[] = [];\n const flushed: Fold<TState>[] = [];\n for (const f of cache.values())\n if (f.dirty) {\n rows.push(row(f));\n flushed.push(f);\n }\n if (rows.length === 0) return;\n await flush(rows);\n for (const f of flushed) f.dirty = false;\n };\n\n /**\n * Load a stream's head state and seat it in the cache.\n *\n * The loaded state and its head position (`version`, global `id`,\n * `patches`, `snaps`) are captured atomically inside `load()` — even on a\n * warm cache hit where `snapshot.event` is undefined. Reading the head id\n * back from the cache separately opened a TOCTOU window: a\n * concurrent `action()` committing between the two awaits pairs this\n * OLDER state with a NEWER event_id, and the frontier guard below then\n * permanently skips the intervening events. Dirty from the start: the row\n * must be written at least once.\n */\n const first_sight = async (stream: string): Promise<Fold<TState>> => {\n if (cache.size >= config.maxCachedStates) {\n // flush-before-evict: the oldest entry leaves only after its folded\n // work is durable.\n const oldest = cache.keys().next().value as string;\n const evictee = cache.get(oldest) as Fold<TState>;\n if (evictee.dirty) await flush([row(evictee)]);\n cache.delete(oldest);\n }\n const snapshot = await load(load_me, { stream }, undefined, patch_fn);\n const seated: Fold<TState> = {\n stream,\n state: snapshot.state,\n version: snapshot.version,\n event_id: snapshot.id,\n patches: snapshot.patches,\n snaps: snapshot.snaps,\n dirty: true,\n };\n cache.set(stream, seated);\n return seated;\n };\n\n const handler: ResettableBatchHandler<TEvents> = async (events) => {\n let folded_since_flush = 0;\n for (const event of events) {\n const stream = event.stream;\n let fold = cache.get(stream);\n if (fold) {\n // promote to most-recent\n cache.delete(stream);\n cache.set(stream, fold);\n } else {\n fold = await first_sight(stream);\n }\n // Fold forward only across a CONTIGUOUS version step. The\n // cache is per-Act but the subscription watermark is shared, so a\n // worker can be handed an event whose predecessors were drained by a\n // sibling worker — its cached state is then stale, and folding onto\n // it silently corrupts the row for good (the flushed row carries the\n // newest event_id, so the monotonic-upsert guard overwrites the\n // correct row with the wrong one). \"Newer than what I hold\" is not\n // the same question as \"next after what I hold\".\n //\n // A gap re-takes the first-sight path: drop the entry and load head\n // state, which is authoritative and absorbs both the missed window\n // and the version slot a `__snapshot__` consumes. The reloaded entry\n // sits at head, so this event then takes the already-folded branch.\n const contiguous = event.version === fold.version + 1;\n if (event.id > fold.event_id && !contiguous) {\n cache.delete(stream);\n fold = await first_sight(stream);\n }\n if (event.id > fold.event_id) {\n const reducer = me.patch[event.name as keyof TEvents];\n fold.state = patch_fn(\n me,\n fold.state,\n reducer(event as never, fold.state),\n event as never\n );\n fold.version = event.version;\n fold.event_id = event.id;\n fold.patches++;\n fold.dirty = true;\n } else {\n // Already folded (head load or redelivery) — mark dirty anyway\n // so replays repopulate the read table: this is what keeps a\n // rebuild at one upsert per stream instead of zero.\n fold.dirty = true;\n }\n if (++folded_since_flush >= config.flushEvery) {\n await flush_dirty();\n folded_since_flush = 0;\n }\n }\n // Flush before returning: the drain acks this batch's watermark only\n // after the handler resolves, so rows are durable before the ack.\n await flush_dirty();\n };\n\n // Dirty entries are dropped rather than flushed: a rebuild is about to\n // re-derive every row from the store, so a pending write of process-local\n // state has nothing to contribute and everything to get wrong.\n Object.defineProperty(handler, FOLD_RESET, { value: () => cache.clear() });\n return handler;\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 Query,\n Schemas,\n SettleOptions,\n} from \"../types/index.js\";\nimport type { CircuitBreaker } from \"./circuit-breaker.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 init: () => Promise<void>;\n readonly checkpoint: () => number;\n readonly correlate: (\n query: Query\n ) => Promise<{ subscribed: number; last_id: number; scanned?: boolean }>;\n readonly drain: (options: DrainOptions) => Promise<Drain<TEvents>>;\n readonly on_settled: (drain: Drain<TEvents>) => void;\n /**\n * Shared orchestrator circuit breaker. The settle loop's\n * `correlate` (subscribe + query) is a store consumer too: a successful\n * pass records `passed()`, a failed one `failed(now, err)` — feeding the\n * same breaker that paces the drain loop, which also surfaces the failure\n * to the `error` lifecycle event.\n */\n readonly breaker: CircuitBreaker;\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 * Resolves when the cycle in flight finishes, so shutdown can wait for\n * it (`stop()` cancels scheduling only). Never rejects.\n */\n private _inflight: Promise<void> | undefined;\n /**\n * A wake-up that fired while a cycle was running. The running cycle's\n * `finally` schedules one more pass with these options, so it isn't lost.\n */\n private _pending: SettleOptions | undefined = undefined;\n private readonly _deps: SettleDeps<TEvents>;\n /** Debounce window applied when the caller doesn't override via `SettleOptions.debounceMs`. */\n private readonly _default_debounce_ms: number;\n\n constructor(deps: SettleDeps<TEvents>, default_debounce_ms: number) {\n this._deps = deps;\n this._default_debounce_ms = default_debounce_ms;\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 events read, no\n * streams leased)\n * or `maxPasses` is reached, then emits the `\"settled\"` lifecycle event\n * via {@link SettleDeps.on_settled}.\n */\n schedule(options: SettleOptions = {}): void {\n const {\n debounceMs = this._default_debounce_ms,\n correlate: correlate_query = { after: -1, limit: 100 },\n maxPasses = Infinity,\n ...drain_options\n } = options;\n\n if (this._timer) clearTimeout(this._timer);\n this._timer = setTimeout(() => {\n this._timer = undefined;\n // A cycle is already running. Record this wake-up as pending rather\n // than dropping it — the running cycle's `finally`\n // re-schedules it so armed controllers always get one more drain.\n if (this._running) {\n this._pending = options;\n return;\n }\n this._running = true;\n\n let settle_done!: () => void;\n this._inflight = new Promise<void>((done) => {\n settle_done = done;\n });\n\n (async () => {\n await this._deps.init();\n // Accumulated across every pass, so `settled` reports what the\n // SETTLE did rather than what its last pass did. The loop only\n // exits on a pass that made no progress, so emitting that pass\n // alone meant the payload was always empty — while the guide tells\n // operators to sum `drain.fetched` for throughput.\n let settled_drain: 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 after_before = this._deps.checkpoint();\n const { subscribed, last_id, scanned } = await this._deps.correlate({\n ...correlate_query,\n after: after_before,\n });\n // A scan that reached the store and came back is a real health\n // signal; a disarmed pass that returned without touching it is not.\n // Recording the latter would re-close an OPEN breaker mid-outage and\n // let the drain below hammer a store nobody has heard from — so the\n // question is asked per pass.\n if (scanned) this._deps.breaker.passed();\n const drain = await this._deps.drain(drain_options);\n settled_drain = settled_drain\n ? {\n fetched: [...settled_drain.fetched, ...drain.fetched],\n leased: [...settled_drain.leased, ...drain.leased],\n acked: [...settled_drain.acked, ...drain.acked],\n blocked: [...settled_drain.blocked, ...drain.blocked],\n }\n : drain;\n // Only a pass that read no events and leased nothing is idle: a\n // leased stream that deferred or failed may leave work behind. It\n // still ends, because ids are finite and every leased stream either\n // advances or leaves the claimable set (acked, blocked, scheduled).\n const made_progress =\n subscribed > 0 || drain.leased.length > 0 || last_id > after_before;\n if (!made_progress) break;\n }\n // `Act.emit` contains listener throws, so the store-failure catch\n // below never sees one.\n if (settled_drain) this._deps.on_settled(settled_drain);\n })()\n .catch((err) => {\n // correlate / init failed (a store op). Record on the shared\n // breaker, which logs it and surfaces the `error` event; the\n // drain loop reads the same breaker to pace itself.\n this._deps.breaker.failed(Date.now(), err);\n })\n .finally(() => {\n this._running = false;\n this._inflight = undefined;\n settle_done();\n // A wake-up arrived mid-cycle. Re-arm one more pass with its\n // options so the requested drain actually happens.\n const pending = this._pending;\n if (pending !== undefined) {\n this._pending = undefined;\n this.schedule(pending);\n }\n });\n }, debounceMs);\n }\n\n /**\n * The cycle currently in flight, or `undefined` when idle. A\n * graceful shutdown awaits this alongside the drain controllers so a\n * settle parked in `correlate` does not resume after teardown.\n */\n get inflight(): Promise<void> | undefined {\n return this._inflight;\n }\n\n /** Cancel any pending or active settle cycle. Idempotent. */\n stop(): void {\n // Drop a mid-cycle wake-up too — a stopped loop must not re-arm from\n // the running cycle's `finally`.\n this._pending = undefined;\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n","/**\n * @module reaction-builder\n * @category Internal\n *\n * Reaction dispatch — what runs inside the drain pipeline once `run_drain_cycle`\n * has fetched events for a leased stream. Two shapes:\n *\n * - per-event `handle`: walks payloads sequentially, running each handler\n * inside the reaction scope so `action()` threads `reactingTo`\n * - bulk `handle_batch`: hands every event for a static-target projection to\n * a single batch callback, enabling one-transaction replays\n *\n * Both finish through the drain's `finalize`, the one retry-or-block\n * decision for every per-stream failure.\n *\n * @internal\n */\n\nimport {\n CloseSignal,\n DeferSignal,\n finalize,\n type Handle,\n type HandleBatch,\n resolve_defer_at,\n} from \"../internal/index.js\";\n\nimport type { ReactionScope } from \"../scoped.js\";\nimport type {\n Actor,\n BatchHandler,\n Committed,\n Lease,\n Logger,\n ReactionPayload,\n Schemas,\n} from \"../types/index.js\";\n\n/**\n * What the dispatcher needs from the orchestrator: a logger for retry and\n * error breadcrumbs, and the scope a handler runs inside.\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 /**\n * What a handler runs inside — its `IAct` facade and its triggering-event\n * context — assembled by the orchestrator. How either half works is not\n * this module's business; it receives the scope whole and calls it.\n */\n readonly reaction_scope: ReactionScope<TEvents, TActions, TActor>;\n};\n\n/**\n * Builds the per-event reaction dispatcher passed to `run_drain_cycle`.\n *\n * The triggering event is installed as ambient context around each handler\n * call, so `action()` resolves it as `reactingTo`. Ambient\n * rather than bound to the `IAct` argument, so a handler that dispatches\n * through a captured `app` inherits the chain too.\n *\n * @internal\n */\nexport function build_handle<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n>(deps: ReactionDeps<TEvents, TActions, TActor>): Handle<TEvents> {\n const { logger, reaction_scope } = 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 // One event fans out to one payload per matching reaction, and the\n // watermark may only advance past an event once EVERY reaction on it\n // has handled it — acking mid-group would silently drop the remaining\n // reactions on redelivery. Track the last payload index per\n // event id (payloads arrive in event order) so `at` advances exactly\n // when a group completes; `handled` counts completed events, not\n // payloads, so a mid-group failure with no completed events is a\n // no-progress result (no ack, retry counter advances toward\n // `blockOnError` instead of resetting on every partial pass).\n const last_index_of = new Map<number, number>();\n for (let i = 0; i < payloads.length; i++)\n last_index_of.set(payloads[i].event.id, i);\n let at = lease.at;\n let handled = 0;\n\n if (lease.retry > 0)\n logger.warn(\n `Retrying ${stream}@${payloads.at(0)!.event.id} (${lease.retry}).`\n );\n\n for (let i = 0; i < payloads.length; i++) {\n const payload = payloads[i];\n const { event, handler } = payload;\n try {\n // Scoped per payload, not hoisted to the lease: the context has to\n // unwind with the handler so it never reaches the drain cycle, and\n // work a handler started without awaiting has to resume into its\n // own event's frame.\n await reaction_scope.run(event as Committed<Schemas, string>, () =>\n handler(event, stream, reaction_scope.app)\n );\n if (last_index_of.get(event.id) === i) {\n at = event.id;\n handled++;\n }\n } catch (error) {\n // A defer is not a failure: hold the triggering events pending\n // (exclude from ack via `defer`), don't bump `retry`, and re-visit\n // the stream at the carried due-time. `acked_at` is unused on\n // the defer path — drain never acks a deferred result.\n if (error instanceof DeferSignal)\n return {\n lease,\n handled,\n acked_at: at,\n defer: resolve_defer_at<TEvents>(error.when, event),\n };\n // A close request advances past the triggering event (so the\n // requesting reaction isn't counted as in-flight by the close-cycle\n // guard) and hands the target to the orchestrator's on_close.\n if (error instanceof CloseSignal)\n return {\n lease,\n handled: handled + 1,\n // Advance to the live head the handler evaluated against (when\n // provided) so the close-cycle guard sees this reaction caught up.\n acked_at: error.at ?? event.id,\n // Close the signalled stream (the autoclose reaction's aggregate,\n // which differs from its synthetic lease stream); a self-closing\n // user reaction omits it and closes its own lease stream. A\n // carried `before` makes it a windowed close (prune, not retire).\n close: {\n stream: error.stream ?? stream,\n archive: error.archive,\n before: error.before,\n },\n };\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 `run_drain_cycle`. 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 build_handle_batch<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 // One payload per (event, reaction) pair: an event with several\n // reactions on this target arrives several times in a row. The batch\n // handler gets each event once, in order — handing it the duplicates\n // made a non-idempotent batch count every event once per reaction.\n // The per-event path groups by id for the same reason.\n const events: Committed<TEvents, keyof TEvents & string>[] = [];\n const seen = new Set<number>();\n for (const p of payloads) {\n if (seen.has(p.event.id)) continue;\n seen.add(p.event.id);\n events.push(p.event as Committed<TEvents, keyof TEvents & string>);\n }\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 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 { Schema, State } from \"../types/index.js\";\nimport type { Projection } from \"./projection-builder.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 base_type_name(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()`. The same schema instance (one partial\n * re-registered through another slice) is kept as-is. Any other pair where\n * either side is not a ZodObject throws — there is no shape to extend, and\n * keeping one side would silently drop the other partial's fields.\n */\nfunction merge_schemas(\n existing: ZodType,\n incoming: ZodType,\n state_name: string\n): ZodType {\n if (existing === incoming) return existing;\n const existing_object = as_object(existing, \"existing\", state_name);\n const incoming_object = as_object(incoming, \"incoming\", state_name);\n const existing_shape = existing_object.shape as Record<string, ZodType>;\n const incoming_shape = incoming_object.shape as Record<string, ZodType>;\n for (const key of Object.keys(incoming_shape)) {\n if (key in existing_shape) {\n const existing_base = base_type_name(existing_shape[key]);\n const incoming_base = base_type_name(incoming_shape[key]);\n if (existing_base !== incoming_base) {\n throw new Error(\n `Schema conflict in \"${state_name}\": key \"${key}\" has type \"${existing_base}\" but incoming partial declares \"${incoming_base}\"`\n );\n }\n }\n }\n return existing_object.extend(incoming_shape);\n}\n\n/**\n * Narrows a partial's state schema to the ZodObject that merging needs, or\n * throws naming the state, which side failed, and what it is instead.\n */\nfunction as_object(\n schema: ZodType,\n side: \"existing\" | \"incoming\",\n state_name: string\n): ZodObject {\n if (schema instanceof ZodObject) return schema;\n throw new Error(\n `Cannot merge state schemas for \"${state_name}\": the ${side} partial's schema is a ${schema.constructor.name}, not a z.object. ` +\n `Partials of the same state are merged by extending their shapes, ` +\n `so declare every partial's state as a plain z.object({ ... }).`\n );\n}\n\n/**\n * Merges two init functions by spreading both results together.\n * Each partial only provides its own defaults.\n */\nfunction merge_inits<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 register_state(\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 merge_into_existing(state, existing, states, actions, events);\n } else {\n register_new_state(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 register_new_state(\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 * Picks the value of a field only one partial may declare. Mirrors the\n * `snap` rule: whichever partial declared it wins, and two different\n * declarations are a conflict rather than a silent first-wins.\n *\n * Without this, a spread of `existing` keeps the FIRST partial's value and\n * silently discards the incoming one, so a policy declared on a later slice\n * never runs.\n */\nfunction pick_declared<T>(\n existing: T | undefined,\n incoming: T | undefined,\n what: string,\n state_name: string\n): T | undefined {\n if (existing && incoming && existing !== incoming)\n throw new Error(`Duplicate ${what} for state \"${state_name}\"`);\n return incoming ?? existing;\n}\n\n/**\n * Resolves the `.autocloses(...)` triple. The predicate and its two day\n * fields are set together by the builder, so they move together — taking the\n * predicate from one partial and a day field from another would produce a\n * window the caller never declared.\n */\nfunction autoclose_of(\n existing: State<any, any, any>,\n state: State<any, any, any>\n): Pick<\n State<any, any, any>,\n \"autoclose\" | \"autoclose_after_days\" | \"autoclose_keep_days\"\n> {\n pick_declared(\n existing.autoclose,\n state.autoclose,\n \"autoclose policy\",\n state.name\n );\n const owner = state.autoclose ? state : existing;\n return {\n autoclose: owner.autoclose,\n autoclose_after_days: owner.autoclose_after_days,\n autoclose_keep_days: owner.autoclose_keep_days,\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 * (including the single-declaration policies, which a bare spread\n * would silently take from the first partial only)\n * 4. update action→state pointers and register new events\n */\nfunction merge_into_existing(\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 merged_patch = merge_patches(existing.patch, state.patch, state.name);\n\n // 3. Build merged state\n const merged = {\n ...existing,\n state: merge_schemas(existing.state, state.state, state.name),\n init: merge_inits(existing.init, state.init),\n events: { ...existing.events, ...state.events },\n actions: { ...existing.actions, ...state.actions },\n patch: merged_patch,\n on: { ...existing.on, ...state.on },\n given: { ...existing.given, ...state.given },\n snap: pick_declared(existing.snap, state.snap, \"snap strategy\", state.name),\n // Per-action retry policy is keyed by action name, so the two partials'\n // maps combine. Left `undefined` when neither declared one, so the\n // orchestrator's `me.options?.[action]` lookup is unchanged.\n options:\n existing.options || state.options\n ? { ...existing.options, ...state.options }\n : undefined,\n disclose: pick_declared(\n existing.disclose,\n state.disclose,\n \"disclosure predicate\",\n state.name\n ),\n archive: pick_declared(\n existing.archive,\n state.archive,\n \"archiver\",\n state.name\n ),\n // `.autocloses(...)` sets its two day fields alongside the predicate, so\n // the whole triple travels together from whichever partial declared it.\n ...autoclose_of(existing, state),\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 merge_patches(\n existing: Record<string, any>,\n incoming: Record<string, any>,\n state_name: string\n): Record<string, any> {\n const merged = { ...existing };\n for (const name of Object.keys(incoming)) {\n const existing_p = existing[name];\n const incoming_p = incoming[name];\n if (!existing_p) {\n merged[name] = incoming_p;\n continue;\n }\n const existing_is_default = existing_p._passthrough;\n const incoming_is_default = incoming_p._passthrough;\n if (\n !existing_is_default &&\n !incoming_is_default &&\n existing_p !== incoming_p\n ) {\n throw new Error(\n `Duplicate custom patch for event \"${name}\" in state \"${state_name}\"`\n );\n }\n // Keep whichever is custom; if both passthrough or existing custom, keep existing\n if (existing_is_default && !incoming_is_default) {\n merged[name] = incoming_p;\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). Reactions are keyed by `handler.name`;\n * two distinct handlers sharing a name on the same event throw rather than\n * silently overwriting. Re-merging the identical reaction object\n * is idempotent — mirrors {@link register_batch_handler}.\n */\nexport function merge_event_register(\n target: Record<string, { reactions: Map<string, unknown> }>,\n source: Record<string, { reactions: Map<string, unknown> }>\n): void {\n for (const [event_name, source_reg] of Object.entries(source)) {\n const target_reg = target[event_name];\n if (!target_reg) continue;\n for (const [name, reaction] of source_reg.reactions) {\n const existing = target_reg.reactions.get(name);\n if (existing !== undefined && existing !== reaction)\n throw new Error(\n `Duplicate reaction \"${name}\" for event \"${event_name}\". ` +\n `Reaction handlers are keyed by function name; rename one of them.`\n );\n target_reg.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 merge_projection(\n proj: Projection<any>,\n events: Record<string, any>\n): void {\n for (const event_name of Object.keys(proj.events)) {\n const proj_register = proj.events[event_name];\n const existing = events[event_name];\n if (!existing) {\n events[event_name] = {\n schema: proj_register.schema,\n reactions: new Map(proj_register.reactions),\n };\n } else {\n for (const [name, reaction] of proj_register.reactions) {\n // The `_p` rename resolves a NAME collision between two genuinely\n // different handlers. Registering the SAME reaction object again is\n // not a collision — it is the same projection reached along two\n // paths (exported from a module and embedded by two slices, or a\n // `.withProjection(p)` written twice) — and renaming it registered a\n // second copy under `name_p`, so the handler ran twice per event,\n // forever, frozen into the registry at build.\n //\n // Not the at-least-once redelivery contract: a structural duplicate,\n // deterministic on every event, with no signal anywhere. Both\n // siblings already guard on identity — `merge_event_register` throws\n // on a different handler under the same name, `register_batch_handler`\n // likewise — this one only lacked the check.\n if ([...existing.reactions.values()].includes(reaction)) continue;\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 builder-utils\n * @category Internal\n *\n * Shared builder machinery reused by both `act-builder.ts` and\n * `slice-builder.ts`. The two builders expose the same reaction-registration\n * and lane-declaration surface and differ only in the concrete builder type\n * they return (`ActBuilder` vs `SliceBuilder`) and the event register they\n * write into (`registry.events` vs the slice's `events`). This module owns the\n * one copy of that logic so the builders stay thin delegations.\n *\n * @internal\n */\n\nimport {\n assert_defer_when,\n DEFAULT_BLOCK_ON_ERROR,\n DEFAULT_MAX_RETRIES,\n type DeferSchedule,\n make_deferred,\n resolveReactionConfig,\n} from \"../internal/index.js\";\nimport { DEFAULT_LANE } from \"../ports.js\";\nimport type {\n Committed,\n EventRegister,\n LaneConfig,\n Reaction,\n ReactionHandler,\n ReactionOptions,\n ReactionResolver,\n Schemas,\n} from \"../types/index.js\";\nimport { _this_ } from \"./merge.js\";\n\n/**\n * Validate and register a drain lane: the `\"default\"` name is\n * reserved and each lane name must be unique. Mutates `lanes` in place; the\n * caller returns its own builder for chaining.\n *\n * @internal\n */\nexport function register_lane(config: LaneConfig, lanes: LaneConfig[]): void {\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}\n\n/**\n * Build the `.on(event)` step shared by both builders. Registers a reaction\n * (named-function + duplicate guards, fail-fast literal-schedule validation,\n * the default `_this_` resolver, and the `.defer` handler wrap) into\n * `events[event].reactions`, and hands back `builder` patched with `.to(...)`\n * for in-place resolver routing.\n *\n * The strict, builder-specific type is supplied by each builder's own `on`\n * signature ({@link ReactionOn}); the runtime here is builder-agnostic.\n *\n * @internal\n */\nexport function reaction_on<\n TEvents extends Schemas,\n TKey extends keyof TEvents,\n TBuilder,\n>(event: TKey, events: EventRegister<TEvents>, builder: TBuilder) {\n const register = (\n handler: ReactionHandler<TEvents, TKey>,\n options?: Partial<ReactionOptions>,\n schedule?: DeferSchedule<Committed<TEvents, TKey>>\n ) => {\n if (!handler.name)\n throw new Error(\n `Reaction handler for \"${String(event)}\" must be a named function`\n );\n if (events[event].reactions.has(handler.name))\n throw new Error(\n `Duplicate reaction \"${handler.name}\" for event \"${String(event)}\". ` +\n `Reaction handlers are keyed by function name; rename one of them.`\n );\n // Fail fast on a bad literal schedule; the function form is checked when it\n // runs (no event to resolve against at build time).\n if (schedule && typeof schedule !== \"function\") assert_defer_when(schedule);\n const reaction: Reaction<TEvents, TKey> = {\n handler: schedule ? make_deferred(handler, schedule) : handler,\n resolver: _this_,\n // Validate the whole bag at the declaration site so a bad\n // `maxRetries`/`backoff`/`blockOnError` throws ZodError at build,\n // not a NaN gate on the first retry.\n options: resolveReactionConfig({\n blockOnError: options?.blockOnError ?? DEFAULT_BLOCK_ON_ERROR,\n maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,\n backoff: options?.backoff,\n }),\n };\n // Register once with the default _this_ resolver. If `.to()` is chained\n // next, it patches the same reaction's resolver in place — no second\n // Map.set() round-trip.\n events[event].reactions.set(handler.name, reaction);\n return Object.assign(builder as object, {\n to(resolver: ReactionResolver<TEvents, TKey> | string) {\n reaction.resolver =\n typeof resolver === \"string\" ? { target: resolver } : resolver;\n return builder;\n },\n });\n };\n return {\n do: (\n handler: ReactionHandler<TEvents, TKey>,\n options?: Partial<ReactionOptions>\n ) => register(handler, options),\n defer: (schedule: DeferSchedule<Committed<TEvents, TKey>>) => ({\n do: (\n handler: ReactionHandler<TEvents, TKey>,\n options?: Partial<ReactionOptions>\n ) => register(handler, options, schedule),\n }),\n };\n}\n","/**\n * @module event-builder\n * @category Internal\n *\n * Everything `act().build()` derives from the registered events.\n *\n * This is the build-time half of the event lifecycle. `internal/sensitive.ts`\n * owns the other two halves — the `sensitive(...)` marker itself, and the\n * runtime transforms (`pii_gate`, `pii_strip`, `pii_split`) that a reader is\n * composed from. Nothing here runs per event at runtime; everything here runs\n * once, at build, and hands the orchestrator a prebuilt function.\n *\n * Three things are derived, all in ONE walk over the registered events:\n *\n * - **validation** — a reaction may not target a lane nobody declared, nor a\n * target a projection already serves. Both checks skip dynamic resolvers,\n * because a `.to(fn)` target is unknowable until an event arrives.\n * - **resolution** — each event's schema is read once into {@link EventTags}:\n * which fields are sensitive, and how to revive the dates in a stored\n * payload. Working out where the dates are is a Zod concern, so it lives in\n * `internal/date-reviver.ts`; this module composes what that returns.\n * - **composition** — the per-surface readers, each a single {@link EventGate}\n * that types the payload and applies disclosure in one call.\n *\n * Deliberately NOT here: deprecation. `Foo` is deprecated only because\n * `Foo_v2` exists beside it, so it is derived from event *names across a whole\n * state* rather than from one event's schema — and it governs *emitting* (a\n * static `.emit()` throws at build), not reading. Replay of a deprecated event\n * stays silent by design.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport { date_reviver_schema } from \"../internal/index.js\";\nimport {\n type EventGate,\n IDENTITY_GATE,\n make_gate,\n pii_schemas,\n pii_split,\n pii_strip,\n} from \"../internal/sensitive.js\";\nimport { DEFAULT_LANE, SNAP_EVENT } from \"../ports.js\";\nimport type { Actor, LaneConfig, Registry } from \"../types/index.js\";\n\n/** What one pass over an event's schema resolves. @internal */\nexport type EventTags = {\n /** Keys marked `sensitive(...)`, top level (and across union variants). */\n readonly sensitive: readonly string[];\n /**\n * Revives the dates in a stored `data` payload, or `undefined` when the\n * schema declares none.\n */\n readonly date_reviver: ((data: unknown) => unknown) | undefined;\n /**\n * Revives the dates in a stored `pii` sidecar, or `undefined` when no\n * sensitive field is a date.\n */\n readonly pii_date_reviver: ((pii: unknown) => unknown) | undefined;\n};\n\n/**\n * Resolve an event's schema in a single pass.\n *\n * Sensitive markers are read at the top level only — the documented carve-out\n * (`sensitive.ts`), since the write path splits whole top-level keys. A union\n * event has no top-level shape, so its variants are walked and unioned: a key\n * sensitive in any variant must be split, because the stored payload could be\n * that variant.\n *\n * @internal\n */\nexport function event_tags(schema: z.ZodType): EventTags {\n // Which fields are sensitive is `sensitive.ts`'s question and where the\n // dates are is `date-reviver.ts`'s; this composes the two answers. The\n // sidecar holds the split-out fields alone, so a date among them needs its\n // own reviver — without it a disclosed `sensitive(z.date())` arrives as text\n // beside a plain sibling that is a Date.\n const pii = pii_schemas(schema);\n const pii_dates: Record<string, z.ZodType> = {};\n for (const [key, field] of Object.entries(pii)) {\n const dates = date_reviver_schema(field);\n if (dates) pii_dates[key] = dates.optional();\n }\n\n const data_reviver_schema = date_reviver_schema(schema);\n // Reviving must never reject. A stored payload can disagree with the current\n // declaration in ways this schema deliberately does not describe, and handing\n // back what is stored beats refusing to read it.\n const revive = (schema: z.ZodType) => (data: unknown) => {\n const revived = schema.safeParse(data);\n return revived.success ? revived.data : data;\n };\n const dated_pii = Object.keys(pii_dates).length > 0;\n return {\n sensitive: Object.keys(pii),\n date_reviver: data_reviver_schema && revive(data_reviver_schema),\n pii_date_reviver: dated_pii ? revive(z.looseObject(pii_dates)) : undefined,\n };\n}\n\n/**\n * What the reader should do about sensitive fields.\n *\n * - `redact` — substitute `[REDACTED]` unless `disclose` authorizes the actor,\n * and drop the `pii` sidecar. The read surfaces (`query`, `query_array`,\n * `load`).\n * - `strip` — remove the keys entirely. Reaction and projection handlers,\n * which never see PII by framework rule, and shouldn't structurally observe\n * the keys either.\n *\n * @internal\n */\nexport type Disclosure = \"redact\" | \"strip\";\n\n/**\n * Compose one event's typing and disclosure into a single gate.\n *\n * Returns `undefined` when the event needs neither, so the caller can fall\n * back to the shared {@link IDENTITY_GATE} and the common path allocates\n * nothing.\n *\n * @internal\n */\nfunction make_event_reader(\n tags: EventTags,\n disclosure: Disclosure,\n predicate: ((event: never, actor: Actor) => boolean) | null = null\n): EventGate | undefined {\n const { sensitive, date_reviver, pii_date_reviver } = tags;\n if (!date_reviver && sensitive.length === 0) return undefined;\n\n const gate: EventGate =\n sensitive.length === 0\n ? IDENTITY_GATE\n : disclosure === \"strip\"\n ? (((event) => pii_strip(event as never, sensitive)) as EventGate)\n : make_gate(sensitive, predicate as never);\n\n if (!date_reviver) return gate;\n\n // The sidecar is only worth reviving for a reader that can be shown it.\n // A `strip` reader drops `pii` outright, and a redacting one discloses only\n // to an actor a predicate approves — so no actor and no predicate means the\n // values are on their way to REDACTED whatever they hold. The predicate\n // itself stays uncalled here: the gate owns that decision and calling it\n // twice would run a caller's code twice.\n const revive_pii =\n disclosure === \"redact\" && predicate ? pii_date_reviver : undefined;\n\n // Revive before disclosing: the gate copies, so reviving afterwards would\n // leave the consumer's value a string — and it substitutes REDACTED and\n // SHREDDED, which are not dates.\n return ((event, actor) => {\n const pii = (event as { pii?: unknown }).pii;\n return gate(\n {\n ...event,\n data: date_reviver(event.data),\n ...(revive_pii && actor && pii != null ? { pii: revive_pii(pii) } : {}),\n } as never,\n actor\n );\n }) as EventGate;\n}\n\n/**\n * Exactly what the registry serves, keyed by event name — no intermediates.\n *\n * The per-state `view` is installed directly on each state rather than\n * returned: it is event-derived wiring like the rest, and handing it back for\n * the caller to install would put the composition back where it came from.\n *\n * @internal\n */\nexport type BuiltEvents = {\n /** Backs `registry.sensitive_fields`. */\n readonly sensitive: Map<string, readonly string[]>;\n /** Backs `registry.query_gate` — the actor-less read surfaces. */\n readonly query_readers: Map<string, EventGate>;\n /** Readers for handlers — sensitive keys removed, payload typed. */\n readonly handler_readers: Map<string, EventGate>;\n};\n\n/** What validation needs to know about the projections already registered. */\nexport type TargetOwners = {\n readonly batch_handlers: ReadonlyMap<string, unknown>;\n readonly fold_targets: ReadonlySet<string>;\n /** A projection's own reactions legitimately target it — excluded by identity. */\n readonly projection_reactions: ReadonlySet<unknown>;\n};\n\ntype EventEntry = {\n schema: import(\"zod\").ZodType;\n reactions: Map<string, { handler: any; resolver: unknown }>;\n};\n\n/**\n * Validate every static reaction and wire every event, in a single walk.\n *\n * Ownership conflicts throw as they are found; lane violations are collected\n * and thrown afterwards. That ordering is deliberate — it preserves the\n * precedence the two separate passes had, where the ownership guard ran to\n * completion before lane references were checked, so a config violating both\n * reports the same error it always did.\n *\n * @internal\n */\nexport function build_events(\n registry: Registry<any, any, any>,\n states: ReadonlyMap<string, any>,\n lanes: ReadonlyArray<LaneConfig>,\n owners: TargetOwners\n): BuiltEvents {\n const declared = new Set<string>([DEFAULT_LANE, ...lanes.map((l) => l.name)]);\n const lane_errors: string[] = [];\n\n const tags = new Map<string, EventTags>();\n const sensitive = new Map<string, readonly string[]>();\n const query_readers = new Map<string, EventGate>();\n const handler_readers = new Map<string, EventGate>();\n\n for (const [event_name, def] of Object.entries(\n registry.events as Record<string, EventEntry>\n )) {\n for (const [handler_name, reaction] of def.reactions) {\n // A build-time guard can only see a static target: a `.to(fn)` target\n // is unknowable until an event arrives.\n if (typeof reaction.resolver === \"function\") continue;\n const resolver = reaction.resolver as { target: string; lane?: string };\n\n const claimed =\n owners.batch_handlers.has(resolver.target) ||\n owners.fold_targets.has(resolver.target);\n if (claimed && !owners.projection_reactions.has(reaction))\n throw new Error(\n `Reaction on target \"${resolver.target}\" conflicts with the projection that already serves it — a target is served by one batch handler or one state projection, and a reaction to it would never run`\n );\n\n if (resolver.lane && !declared.has(resolver.lane))\n lane_errors.push(\n `Reaction \"${handler_name}\" on \"${event_name}\" targets undeclared lane \"${resolver.lane}\". ` +\n `Declared lanes: ${[...declared].map((l) => `\"${l}\"`).join(\", \")}. ` +\n `Add \\`.withLane({ name: \"${resolver.lane}\", ... })\\` to act() or correct the .to() declaration.`\n );\n }\n\n // One resolution of the declared schema yields both facts a reader is\n // built from: which fields are sensitive, and how to type the payload.\n const event = event_tags(def.schema);\n tags.set(event_name, event);\n if (event.sensitive.length > 0) sensitive.set(event_name, event.sensitive);\n\n // An event needing neither typing nor redaction produces no reader and\n // falls back to the shared IDENTITY_GATE — zero per-event cost.\n const query_reader = make_event_reader(event, \"redact\", null);\n if (query_reader) query_readers.set(event_name, query_reader);\n\n // Handlers never see PII by framework rule, and shouldn't observe the\n // keys structurally either — so `strip`, not `redact`.\n const handler_reader = make_event_reader(event, \"strip\");\n if (handler_reader) {\n handler_readers.set(event_name, handler_reader);\n for (const [name, reaction] of def.reactions) {\n const inner = reaction.handler;\n const wrapped = (evt: any, stream: string, app: any) =>\n inner(handler_reader(evt), stream, app);\n // Preserve handler.name — build_handle asserts on named functions.\n Object.defineProperty(wrapped, \"name\", { value: inner.name });\n reaction.handler = wrapped;\n def.reactions.set(name, reaction as never);\n }\n }\n }\n\n if (lane_errors.length > 0) throw new Error(lane_errors[0]);\n\n // Per-state wiring, all of it derived from the same event resolution: the\n // read view, the write split, and the guard that refuses to combine the two\n // things that cannot coexist.\n for (const state of states.values()) {\n const state_fields = new Map<string, readonly string[]>();\n for (const event_name of Object.keys(state.events)) {\n const fields = sensitive.get(event_name);\n if (fields) state_fields.set(event_name, fields);\n }\n\n if (state_fields.size > 0) {\n // Snapshots write derived state into `__snapshot__.data`, which\n // `forget_pii` cannot reach. Reject the combination at build so the\n // misconfiguration surfaces in dev/CI, not as a silent leak past the\n // GDPR boundary months later.\n if (state.snap)\n throw new Error(\n `State \"${state.name}\" cannot snapshot — events {${[...state_fields.keys()].join(\", \")}} carry sensitive fields. ` +\n \"Snapshots write derived state into __snapshot__.data, which forget_pii cannot reach. \" +\n \"Remove .snap() or remove sensitive(...) markers.\"\n );\n state.pii_aware = true;\n // The write half: split declared fields into the `pii` sidecar on the\n // way to `Store.commit`.\n state.message = (validated: { name: string }) => {\n const fields = state_fields.get(validated.name);\n return fields ? pii_split(validated as never, fields) : validated;\n };\n }\n\n // The read half. A state's disclosure predicate is an input to the\n // reader, not a second gate layered over it. A `__snapshot__` carries\n // folded STATE rather than event data, so its typing comes from the state\n // schema — without that a restart from a snapshot loses every `z.date()`\n // the state holds.\n const readers = new Map<string, EventGate>();\n for (const event_name of Object.keys(state.events)) {\n const event = tags.get(event_name);\n const reader =\n event && make_event_reader(event, \"redact\", state.disclose ?? null);\n if (reader) readers.set(event_name, reader);\n }\n const snap = make_event_reader(event_tags(state.state), \"redact\", null);\n if (snap) readers.set(SNAP_EVENT, snap);\n if (readers.size === 0) continue;\n state.view = (event: { name: string }, actor: Actor) =>\n (readers.get(event.name) ?? IDENTITY_GATE)(event as never, actor);\n }\n\n return { sensitive, query_readers, handler_readers };\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 bare_patch,\n current_version_of,\n deprecated_event_names,\n type EventGate,\n FOLD_RESET,\n IDENTITY_GATE,\n make_fold_handler,\n type PatchFn,\n type ResettableBatchHandler,\n resolveActConfig,\n resolveLaneConfig,\n synthesize_autoclose_reactions,\n validating_patch,\n} from \"../internal/index.js\";\nimport { type DEFAULT_LANE, log } from \"../ports.js\";\nimport { current_autoclose_window } from \"../scoped.js\";\nimport type {\n Actor,\n BatchHandler,\n LaneConfig,\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport type { BuilderBase } from \"./builder-base.js\";\nimport { reaction_on, register_lane } from \"./builder-utils.js\";\nimport { build_events } from \"./event-builder.js\";\nimport {\n merge_event_register,\n merge_projection,\n register_state,\n} from \"./merge.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 already serves it. Folds (`.of(...)`) have no\n * batch handler; their side of the check is in `build()`.\n */\nfunction register_batch_handler(\n proj: Projection<any>,\n batch_handlers: Map<string, BatchHandler<any>>\n): void {\n if (!proj.batchHandler || !proj.target) return;\n const existing = batch_handlers.get(proj.target);\n if (existing && existing !== proj.batchHandler) {\n throw new Error(\n `Duplicate projection target \"${proj.target}\" — a target is served by one batch handler or one state projection, never both`\n );\n }\n batch_handlers.set(proj.target, proj.batchHandler);\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, ...})`\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. 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 interface 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> extends BuilderBase<\n ActBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>,\n TEvents,\n TActions,\n TActor,\n TLanes\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 * 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. 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 * 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\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 * @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 // Caches behind the registry's derived lookups, populated on the first\n // `.build()`. Each event schema is walked once.\n const _sf = new Map<string, readonly string[]>();\n // Prebuilt handler readers — sensitive keys removed, payload typed. Absent\n // when the event needs neither.\n const _hr = new Map<string, EventGate>();\n // Prebuilt default-deny read gates, one per sensitive event. Non-sensitive\n // events are absent → `query_gate` falls back to the shared IDENTITY_GATE.\n const _qg = new Map<string, EventGate>();\n const _dp = new Map<string, (event: any, actor: Actor) => boolean>();\n const _de = new Map<string, ReadonlySet<string>>();\n const _ac = new Map<\n string,\n (stream: string, head: any, count: number) => boolean\n >();\n const _aa = new Map<string, (stream: string, head: any) => Promise<void>>();\n const EMPTY_DEPRECATED: ReadonlySet<string> = new Set();\n const registry: Registry<TSchemaReg, TEvents, TActions> = {\n actions: {} as Registry<TSchemaReg, TEvents, TActions>[\"actions\"],\n events: {} as Registry<TSchemaReg, TEvents, TActions>[\"events\"],\n sensitive_fields: (event_name) => _sf.get(event_name) ?? [],\n query_gate: (event_name) => _qg.get(event_name) ?? IDENTITY_GATE,\n disclosure_predicate: (state_name) => _dp.get(state_name) ?? null,\n deprecated_events: (state_name) => _de.get(state_name) ?? EMPTY_DEPRECATED,\n autoclose_policy: (state_name) => _ac.get(state_name) ?? null,\n autoclose_archiver: (state_name) => _aa.get(state_name) ?? null,\n };\n const pending_projections: Projection<any>[] = [];\n /**\n * Reactions contributed by projections, recorded at registration. Only\n * these may target a projection's stream; anything else is a collision.\n */\n const projection_reactions = new Set<unknown>();\n const record_projection_reactions = (proj: Projection<any>) => {\n // Only a projection that SERVES its target (a batch handler or a fold)\n // owns it. A per-event projection naming the same target is just another\n // claimant: exempting it let it share a fold's or batch's target, where\n // its handler never ran and the fold wrote foreign rows.\n if (!proj.batchHandler && !proj.fold) return;\n for (const register of Object.values(\n proj.events as Record<string, { reactions: Map<string, unknown> }>\n ))\n for (const reaction of register.reactions.values())\n projection_reactions.add(reaction);\n };\n const fold_projections: Projection<any>[] = [];\n const batch_handlers = new Map<string, BatchHandler<any>>();\n const add_projection = (proj: Projection<any>) => {\n record_projection_reactions(proj);\n merge_projection(proj, registry.events as Record<string, any>);\n register_batch_handler(proj, batch_handlers);\n if (proj.fold) fold_projections.push(proj);\n };\n // Validated fold-projection ingredients, resolved once on the first\n // build. The HANDLERS themselves are built per `.build()` — see\n // `make_batch_handlers` — because a fold handler owns a mutable\n // per-stream cache that must never be shared across Acts.\n const fold_specs: {\n target: string;\n /** Identity of the registering projection, so a repeat registration of\n * the same object is recognized as one claim rather than two. */\n projection: Projection<any>;\n merged: any;\n flush: any;\n config: any;\n }[] = [];\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 /**\n * Wraps a batch handler so it receives events in handler form — payload\n * typed from the declared schema, sensitive keys removed — the same reader\n * `event-builder` gives per-event handlers. Resolved lazily at dispatch, by\n * when the events pass has populated it.\n */\n const read_wrap = (original: BatchHandler<any>): BatchHandler<any> => {\n const wrapped = async (events: readonly any[], stream: string) => {\n // The same prebuilt reader the per-event handlers get: typed payload,\n // sensitive keys removed. Absent → the event passes through untouched.\n const read = events.map((e) => _hr.get(e.name as string)?.(e) ?? e);\n return original(read as never, stream);\n };\n // Carry the fold's cache-reset handle through the wrapper. The\n // orchestrator only ever sees what this map holds, so a handle left on\n // the inner handler is a handle nobody can reach.\n const reset = (original as ResettableBatchHandler<any>)[FOLD_RESET];\n if (reset) Object.defineProperty(wrapped, FOLD_RESET, { value: reset });\n return wrapped;\n };\n\n /**\n * Per-Act batch-handler map. Stateless handlers are shared; fold\n * handlers own a per-stream cache, so each `.build()` gets fresh ones\n * (and its own `patch_fn`).\n */\n const make_batch_handlers = (patch_fn: PatchFn) => {\n const handlers = new Map(batch_handlers);\n for (const spec of fold_specs) {\n handlers.set(\n spec.target,\n read_wrap(\n make_fold_handler(\n spec.merged,\n spec.flush,\n spec.config,\n patch_fn,\n // Head loads strip sensitive keys like the warm path.\n registry.sensitive_fields\n )\n ) as never\n );\n }\n return handlers;\n };\n\n // Versioned events: per state, the highest `_v<n>` is current and lower\n // ones are deprecated (`registry.deprecated_events`). A static\n // `.emit(\"X\")` of a deprecated event throws; a one-line advisory lists\n // the legacy events kept for replay.\n const finalize_deprecations = () => {\n const deprecation_summary: Array<{\n state_name: string;\n deprecated: string;\n current: string;\n }> = [];\n for (const state of states.values()) {\n const event_names = Object.keys(state.events);\n const deprecated = deprecated_event_names(event_names);\n if (deprecated.size === 0) continue;\n _de.set(state.name, deprecated);\n for (const name of deprecated) {\n // `current_version_of` 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 = current_version_of(name, event_names) as string;\n deprecation_summary.push({\n state_name: state.name,\n deprecated: name,\n current,\n });\n }\n for (const [action_name, handler] of Object.entries(state.on)) {\n const static_target = (handler as { _static_emit?: string } | undefined)\n ?._static_emit;\n if (static_target && deprecated.has(static_target)) {\n const current = current_version_of(static_target, event_names);\n throw new Error(\n `Action \"${action_name}\" in state \"${state.name}\" emits deprecated event \"${static_target}\". ` +\n `A newer version exists: \"${current}\". Update the .emit() call ` +\n `to target the current version. The reducer (.patch) for ` +\n `\"${static_target}\" stays as-is — historical events still need it.`\n );\n }\n }\n }\n if (deprecation_summary.length > 0) {\n const list = deprecation_summary\n .map(\n (d) =>\n `\"${d.deprecated}\" (current: \"${d.current}\", state: \"${d.state_name}\")`\n )\n .join(\", \");\n log().info(\n `Act registered ${deprecation_summary.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 /**\n * Registration is closed once `build()` has classified the registry: every\n * mutating method throws a clear error after it. `build()` itself stays\n * callable repeatedly, since the multi-tenant pattern calls\n * `.build({scoped})` per tenant and registers nothing.\n */\n const closed = (method: string): never => {\n throw new Error(\n `act().${method}() was called after build(); the registry is already classified. Register everything before build() — build() itself may be called repeatedly (e.g. once per tenant with ActOptions.scoped).`\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 if (_built) closed(\"withState\");\n register_state(state, states, registry.actions, registry.events);\n return builder as never;\n },\n withSlice: (input) => {\n if (_built) closed(\"withSlice\");\n for (const s of input.states.values()) {\n register_state(s, states, registry.actions, registry.events);\n }\n merge_event_register(registry.events, input.events);\n pending_projections.push(...input.projections);\n for (const slice_lane of input.lanes) {\n const existing = lanes.find((l) => l.name === slice_lane.name);\n if (!existing) {\n lanes.push(slice_lane);\n continue;\n }\n if (\n existing.leaseMillis !== slice_lane.leaseMillis ||\n existing.streamLimit !== slice_lane.streamLimit ||\n existing.cycleMs !== slice_lane.cycleMs\n ) {\n throw new Error(\n `Lane \"${slice_lane.name}\" was already declared with a different config`\n );\n }\n }\n return builder as never;\n },\n withProjection: (proj) => {\n if (_built) closed(\"withProjection\");\n add_projection(proj as Projection<any>);\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 (_built) closed(\"withLane\");\n // Validate the lane bag at declaration (a bad leaseMillis/streamLimit\n // throws ZodError at build, not on the first cycle).\n register_lane(resolveLaneConfig(config), lanes);\n return builder as never;\n },\n on: <TKey extends keyof TEvents>(event: TKey) => {\n if (_built) closed(\"on\");\n return reaction_on(event, registry.events, builder) as never;\n },\n build: (options?: ActOptions) => {\n // Validate the top-level scalar knobs at build (the nested autoclose /\n // circuitBreaker bags are validated by their own resolvers). A bad\n // maxSubscribedStreams / settleDebounceMs throws ZodError here.\n resolveActConfig(options);\n // The one place the patch step is chosen; folds and `build_es` share\n // it.\n const patch_fn: PatchFn =\n options?.validateFoldedState === true ? validating_patch : bare_patch;\n // Finalize once: repeated builds (per tenant) share the registry.\n if (!_built) {\n for (const proj of pending_projections) add_projection(proj);\n // State projections fold the registry-merged FULL state — the\n // builder only recorded intent. Resolve here, where every\n // partial has merged, and refuse silently-partial folds: the\n // projection's register must cover the state's whole register.\n // The `patch_fn` selected once at the top of `build()` feeds the\n // fold handlers, matching the command/load paths.\n for (const proj of fold_projections) {\n const fold = proj.fold!;\n const merged = states.get(fold.name);\n if (!merged)\n throw new Error(\n `State projection \"${proj.target}\" folds \"${fold.name}\", which is not registered — add it via withState/withSlice before build()`\n );\n const missing = Object.keys(merged.events).filter(\n (event_name) => !(event_name in proj.events)\n );\n if (missing.length > 0)\n throw new Error(\n `State projection \"${proj.target}\" of \"${fold.name}\" is missing events ${missing.join(\", \")} — pass every partial of the state to .of()`\n );\n // A target is claimed once, by a batch handler or a fold; two\n // different projections on one target throw. The same projection\n // registered twice is fine.\n const claimed = fold_specs.find((s) => s.target === proj.target);\n if (claimed?.projection === proj) continue;\n if (batch_handlers.has(proj.target!) || claimed)\n throw new Error(\n `Duplicate projection target \"${proj.target}\" — a target is served by one batch handler or one state projection, never both`\n );\n // Record the validated ingredients only. The handler is\n // constructed per `.build()` (see `make_batch_handlers`) — it\n // owns a mutable per-stream fold cache, so one shared instance\n // would leak folded rows between Acts built from this builder.\n fold_specs.push({\n target: proj.target!,\n projection: proj,\n merged,\n flush: fold.flush,\n config: fold.config,\n });\n }\n // An ordinary reaction on a projection's target would never run and\n // would feed the fold another aggregate, so `build_events` rejects\n // it (the projection's own reactions are exempt).\n //\n // One walk over the registered events: validate every static\n // reaction, resolve each schema once, and compose the per-surface\n // readers from it. See `event-builder.ts`.\n const built = build_events(registry, states, lanes, {\n batch_handlers,\n fold_targets: new Set(fold_specs.map((f) => f.target)),\n projection_reactions,\n });\n for (const [name, fields] of built.sensitive) _sf.set(name, fields);\n for (const [name, gate] of built.query_readers) _qg.set(name, gate);\n for (const [name, gate] of built.handler_readers) _hr.set(name, gate);\n finalize_deprecations();\n\n for (const state of states.values()) {\n if (state.disclose) _dp.set(state.name, state.disclose);\n if (state.autoclose) _ac.set(state.name, state.autoclose);\n if (state.archive) _aa.set(state.name, state.archive);\n }\n for (const [target, original] of batch_handlers) {\n batch_handlers.set(target, read_wrap(original) as never);\n }\n // Synthesize the autoclose reactions last, once the registry is\n // fully merged — their dynamic resolvers must be present before\n // the orchestrator classifies the registry.\n //\n // Nothing per-Act is captured: repeat builds share these reactions,\n // and the off-hours window comes from the running Act's frame.\n synthesize_autoclose_reactions(\n registry,\n states,\n current_autoclose_window\n );\n // Freeze the registry shape; the `_built` latch on each method stops\n // later registration (freezing doesn't seal the reaction `Map`s).\n Object.freeze(registry.actions);\n Object.freeze(registry.events);\n Object.freeze(registry);\n _built = true;\n }\n\n return new Act<TSchemaReg, TEvents, TActions, TStateMap, TActor>(\n registry,\n states,\n make_batch_handlers(patch_fn),\n options,\n lanes,\n patch_fn\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 {\n DEFAULT_BLOCK_ON_ERROR,\n DEFAULT_MAX_RETRIES,\n type FoldConfig,\n resolveFoldConfig,\n} from \"../internal/index.js\";\nimport type {\n BatchHandler,\n CacheEntry,\n Committed,\n EventRegister,\n FoldOptions,\n Reaction,\n ReactionResolver,\n Schema,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport { _this_ } from \"./merge.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 * State-fold spec from `.of()`. The builder only records intent — the\n * orchestrator resolves the REGISTRY-MERGED full state at\n * `act().build()` and synthesizes the batch handler there, so the\n * fold always covers every reducer of the state, including partials\n * merged by slices the projection never saw.\n * @internal\n */\n readonly fold?: {\n readonly name: string;\n readonly flush: (rows: ReadonlyArray<CacheEntry<any>>) => Promise<void>;\n readonly config: FoldConfig;\n };\n};\n\n/**\n * The `.of()` continuation: state projections flush the cache layer\n * outward — the rows ARE the streams' {@link CacheEntry} values, one\n * per dirty stream per flush round. Must be an idempotent upsert keyed\n * on `stream` (guard with `event_id` for order safety when a rebuild\n * races a live worker).\n */\ntype FoldFlush<TState extends Schema, TE extends Schemas> = {\n flush: (\n handler: (rows: ReadonlyArray<CacheEntry<TState>>) => Promise<void>\n ) => {\n build: () => Projection<TE>;\n };\n};\n\n/**\n * `.of()` accepts the partials of ONE state (same name, enforced at the\n * type level via `TName`) purely for typing and event registration —\n * the fold itself always runs on the registry-merged full state,\n * resolved at `act().build()`. Passing every partial is required: the\n * orchestrator validates completeness at build and throws on missing\n * events.\n */\ntype OfSignatures = {\n <\n TS1 extends Schema,\n TE1 extends Schemas,\n TA1 extends Schemas,\n TN extends string,\n >(\n s1: State<TS1, TE1, TA1, TN>,\n options?: FoldOptions\n ): FoldFlush<TS1, TE1>;\n <\n TS1 extends Schema,\n TE1 extends Schemas,\n TA1 extends Schemas,\n TS2 extends Schema,\n TE2 extends Schemas,\n TA2 extends Schemas,\n TN extends string,\n >(\n s1: State<TS1, TE1, TA1, TN>,\n s2: State<TS2, TE2, TA2, TN>,\n options?: FoldOptions\n ): FoldFlush<TS1 & TS2, TE1 & TE2>;\n <\n TS1 extends Schema,\n TE1 extends Schemas,\n TA1 extends Schemas,\n TS2 extends Schema,\n TE2 extends Schemas,\n TA2 extends Schemas,\n TS3 extends Schema,\n TE3 extends Schemas,\n TA3 extends Schemas,\n TN extends string,\n >(\n s1: State<TS1, TE1, TA1, TN>,\n s2: State<TS2, TE2, TA2, TN>,\n s3: State<TS3, TE3, TA3, TN>,\n options?: FoldOptions\n ): FoldFlush<TS1 & TS2 & TS3, TE1 & TE2 & TE3>;\n <\n TS1 extends Schema,\n TE1 extends Schemas,\n TA1 extends Schemas,\n TS2 extends Schema,\n TE2 extends Schemas,\n TA2 extends Schemas,\n TS3 extends Schema,\n TE3 extends Schemas,\n TA3 extends Schemas,\n TS4 extends Schema,\n TE4 extends Schemas,\n TA4 extends Schemas,\n TN extends string,\n >(\n s1: State<TS1, TE1, TA1, TN>,\n s2: State<TS2, TE2, TA2, TN>,\n s3: State<TS3, TE3, TA3, TN>,\n s4: State<TS4, TE4, TA4, TN>,\n options?: FoldOptions\n ): FoldFlush<TS1 & TS2 & TS3 & TS4, TE1 & TE2 & TE3 & TE4>;\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, true> & {\n to: (\n resolver: ReactionResolver<TEvents & { [P in TKey]: TData }, TKey> | string\n ) => ProjectionBuilder<TEvents & { [P in TKey]: TData }, TTarget, true>;\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 THasHandlers extends boolean = false,\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 } & (THasHandlers extends false\n ? {\n /**\n * Declares a state projection: fold every event of the given\n * state through its own reducers and flush one row per stream —\n * the queryable list of the aggregates themselves.\n *\n * The state is the filter: the projection consumes exactly the\n * state's event register, so in a multi-state app only that\n * state's streams are folded — and every event of a folded\n * stream reaches the reducer. Write amplification tracks the\n * distinct stream count, not the event count; `app.reset`\n * rebuilds in O(streams) upserts.\n *\n * The fluent chain enforces the shape: `.of()` is only offered\n * before any `.on()` handler, and narrows to `.flush()` +\n * `.build()` — a projection either folds a state or declares\n * handlers, never both.\n */\n of: OfSignatures;\n }\n : // eslint-disable-next-line @typescript-eslint/no-empty-object-type\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 function openTicket({ stream, data }) {\n * await db.insert(tickets).values({ id: stream, ...data });\n * })\n * .on({ TicketClosed })\n * .do(async function closeTicket({ stream, data }) {\n * await db.update(tickets).set(data).where(eq(tickets.id, stream));\n * })\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 default_resolver: { 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,\n resolver: default_resolver ?? _this_,\n options: {\n blockOnError: DEFAULT_BLOCK_ON_ERROR,\n maxRetries: DEFAULT_MAX_RETRIES,\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 if (register.reactions.has(handler.name))\n throw new Error(\n `Duplicate projection handler \"${handler.name}\" for event \"${event}\". ` +\n `Projection handlers are keyed by function name; rename one of them.`\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() and .of() 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 of: (...args: unknown[]) => {\n if (Object.keys(events).length > 0)\n throw new Error(\n `Projection \"${target}\" mixes .of() with .on() handlers — a projection either folds a state or declares handlers, never both`\n );\n // Trailing options bag is the only non-State argument.\n const is_state = (a: unknown): a is State<Schema, Schemas, Schemas> =>\n !!a &&\n typeof (a as State<Schema, Schemas, Schemas>).init === \"function\";\n const partials = args.filter(is_state);\n const options = (args.find((a) => !is_state(a)) ?? {}) as FoldOptions;\n if (partials.length === 0)\n throw new Error(`Projection \"${target}\" .of() requires a state`);\n const name = partials[0].name;\n for (const partial of partials)\n if (partial.name !== name)\n throw new Error(\n `Projection \"${target}\" .of() partials must share one state name — got \"${name}\" and \"${partial.name}\"`\n );\n // Misconfiguration surfaces here, at startup — not on first drain.\n const config = resolveFoldConfig(options);\n // The partials' own schema instances register the events, so the\n // same-name declarations in slices pass the identity check in\n // merge_event_register. The named no-op reaction routes fetches\n // to this target; dispatch always goes through the batch handler\n // the orchestrator synthesizes from the registry-merged state.\n const fold_events = {} as EventRegister<Schemas>;\n for (const partial of partials)\n for (const [event_name, schema] of Object.entries(partial.events)) {\n if (event_name in fold_events) continue;\n const noop = {\n [`${target}_fold`]: async () => {},\n }[`${target}_fold`] as (\n event: Committed<Schemas, string>,\n stream: string\n ) => Promise<void>;\n (fold_events as Record<string, unknown>)[event_name] = {\n schema,\n reactions: new Map([\n [\n `${target}_fold`,\n {\n handler: noop,\n resolver: { target },\n options: {\n blockOnError: DEFAULT_BLOCK_ON_ERROR,\n maxRetries: DEFAULT_MAX_RETRIES,\n },\n },\n ],\n ]),\n };\n }\n return {\n flush: (\n handler: (rows: ReadonlyArray<CacheEntry<Schema>>) => Promise<void>\n ) => ({\n build: () => ({\n _tag: \"Projection\" as const,\n events: fold_events,\n target,\n fold: { name, flush: handler, config },\n }),\n }),\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 */\n\nimport { resolveLaneConfig } from \"../internal/index.js\";\nimport type { DEFAULT_LANE } from \"../ports.js\";\nimport type {\n Actor,\n EventRegister,\n LaneConfig,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"../types/index.js\";\nimport type { BuilderBase } from \"./builder-base.js\";\nimport { reaction_on, register_lane } from \"./builder-utils.js\";\nimport { register_state } from \"./merge.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(...)`.\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 interface 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> extends BuilderBase<\n SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>,\n TEvents,\n TActions,\n TActor,\n TLanes\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 * Declares a drain lane on this slice. 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 * Builds and returns the Slice data structure.\n */\n build: () => Slice<TSchemaReg, TEvents, TActions, TStateMap, TActor, TLanes>;\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 function resetCounter(event, _stream, app) {\n * await app.do(\"reset\", target, {});\n * })\n * .to(\"counter-target\")\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 register_state(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 // Validate at declaration, exactly as the `act()` path does. Without\n // this the slice path accepted a bag the act() path rejects — and a\n // lane carrying a bad streamLimit/leaseMillis/cycleMs drains nothing\n // for the life of the process, silently: no error, no log, and nothing\n // in `blocked_streams()` to find it by.\n register_lane(resolveLaneConfig(config), lanes);\n return builder as never;\n },\n on: <TKey extends keyof TEvents>(event: TKey) =>\n reaction_on(event, events, builder) as never,\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 {\n type AutoclosePolicy,\n compile_autoclose_policy,\n policy_keep_days,\n policy_min_after_days,\n resolveActionConfig,\n} from \"../internal/index.js\";\nimport type {\n ActionHandler,\n ActionOptions,\n Actor,\n AutocloseArchiver,\n AutoclosePredicate,\n Committed,\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 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 * @template TSnap - `true` once `.snap(...)` has been called. Gates the\n * `.autocloses({ keep })` rolling-window option — a windowed close is\n * meaningless without snapshots, so `keep` only typechecks after\n * `.snap` in the chain.\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 TSnap extends boolean = false,\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 * Pass an optional second argument to declare a per-action retry\n * policy — the orchestrator retries this action on\n * {@link ConcurrencyError} up to `maxRetries` extra times, applying\n * `backoff` between attempts when set. Omit the argument to keep the\n * current single-attempt behavior (`ConcurrencyError` surfaces on\n * first conflict).\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 * @param options - Optional per-action retry policy\n * ({@link ActionOptions}).\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 on: <TKey extends string, TNewActions extends Schema>(\n entry: ActionEntry<TKey, TNewActions>,\n options?: ActionOptions\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\n * events. Each invariant pairs a `description` with a `valid(state, actor?)`\n * predicate — when a predicate returns `false`, the action throws\n * `InvariantError` carrying the description. All invariants must pass for\n * the action to succeed.\n *\n * @param rules - Array of {@link Invariant} objects (`{ description, valid }`)\n * @returns An object with `.emit()` to finalize the action\n *\n * @example\n * ```typescript\n * .given([\n * { description: \"Must be active\", valid: (state) => state.status === \"active\" },\n * { description: \"Must be the owner\", valid: (state, actor) => state.ownerId === actor?.id }\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 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 TSnap\n >;\n /** Passthrough — the action payload becomes the event data\n * directly. Must reference an event declared in `.emits()`. */\n (\n event_name: keyof TEvents & string\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName,\n TSnap\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 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 TSnap\n >;\n (\n event_name: keyof TEvents & string\n ): ActionBuilder<\n TState,\n TEvents,\n TActions & { [P in TKey]: TNewActions },\n TName,\n TSnap\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 snap: (\n snap: (snapshot: Snapshot<TState, TEvents>) => boolean\n ) => ActionBuilder<TState, TEvents, TActions, TName, true>;\n /**\n * Declares the disclosure predicate for `sensitive(...)`-marked event\n * fields. Gates external reads: returning `true` allows the actor to see\n * plaintext on the event; returning `false` substitutes `\"[REDACTED]\"`.\n * When absent, the framework default-denies on every external read —\n * fail-safe.\n *\n * One predicate per state. A second `.discloses(...)` call replaces the\n * first (same shape as snapshots being state-level, not per-event).\n *\n * The predicate receives the full event including merged PII so it can\n * branch on the payload itself (e.g.\n * `event.data.ownerId === actor.id`). Reducers, projections, and\n * reactions are unaffected — they follow separate visibility rules.\n *\n * @param disclose - Predicate `(event, actor) => boolean`. `true` =\n * plaintext, `false` = `\"[REDACTED]\"` substitution.\n * @returns The ActionBuilder for chaining.\n *\n * @example Owner-or-admin disclosure\n * ```typescript\n * state({ User: userSchema })\n * .init(() => ({ ... }))\n * .emits({ UserRegistered: z.object({ email: sensitive(z.string()) }) })\n * .discloses((event, actor) =>\n * actor.id === event.stream || actor.roles?.includes(\"admin\"))\n * ```\n */\n discloses: (\n disclose: (\n event: Committed<TEvents, keyof TEvents & string>,\n actor: Actor\n ) => boolean\n ) => ActionBuilder<TState, TEvents, TActions, TName, TSnap>;\n /**\n * Declares the online close predicate for this state. The\n * orchestrator's autoclose cycle iterates the state's streams once\n * per tick and calls the predicate per candidate; truthy results are\n * scheduled for atomic truncate-and-seed via `Store.truncate` on the\n * next batch.\n *\n * One predicate per state. A second `.autocloses(...)` call replaces\n * the first (same shape as `.snap` / `.discloses` — state-level, not\n * per-event). Absent → the state opts out of online close entirely;\n * the cycle skips it and pays zero per-tick cost for it.\n *\n * Pass a declarative {@link AutoclosePolicy} object literal covering the\n * three operational pressure points (`after`, `is`, `reaches`). Top-level\n * fields combine with AND; an optional `or: {...}` block opens an\n * alternative OR path. Validated via Zod at build time; misconfiguration\n * throws before `act().build()` completes.\n *\n * Under the hood this compiles to a synthesized reaction that runs\n * on a per-aggregate synthetic stream: it defers to `head.created + the\n * policy's min after` while the cooldown holds and closes the stream once\n * the policy matches. There is no background sweep.\n *\n * **The function-predicate form was removed.** `.autocloses` no\n * longer accepts `(stream, head, count) => boolean`; an opaque predicate has\n * no derivable due-time or terminal event to react to. For conditions the\n * declarative form can't express, call `app.close(...)` from your own logic.\n *\n * @param policy The declarative {@link AutoclosePolicy} bag.\n * @returns The ActionBuilder for chaining.\n *\n * @example Declarative — cooldown after terminal (a Ticket closes\n * 90 days after resolution).\n * ```typescript\n * .autocloses({ is: \"TicketResolved\", after: { days: 90 } })\n * ```\n */\n autocloses: (\n policy: [TSnap] extends [true]\n ? AutoclosePolicy\n : Omit<AutoclosePolicy, \"keep\"> & {\n /** Rolling-window retention requires `.snap(...)` earlier in\n * the builder chain — a windowed close prunes behind a real\n * snapshot, so a state that never snapshots has nothing to\n * prune behind. */\n keep?: never;\n }\n ) => ActionBuilder<TState, TEvents, TActions, TName, TSnap>;\n /**\n * Declares the archiver the online close cycle runs **before**\n * truncating a stream this state's `.autocloses(...)` predicate\n * accepted. Hosts use it to write events to durable storage (S3,\n * an analytics warehouse, cold tier) before the tombstone lands,\n * so the truncate doesn't lose history that the operator still\n * needs.\n *\n * Threads into `CloseTarget.archive` via the same plumbing\n * `app.close({ stream, archive })` already uses — the cycle holds\n * the stream's guard while the archiver runs, and a thrown\n * archiver leaves the stream guarded but un-truncated. No partial\n * truncate state, no data loss. It is not retried automatically;\n * `app.close([{ stream, archive }])` resumes the guarded stream.\n *\n * One archiver per state. A second `.archives(...)` call replaces\n * the first (same shape as `.snap` / `.discloses` /\n * `.autocloses`). Absent → the cycle truncates without an archive\n * step.\n *\n * @param archive `(stream, head) => Promise<void>`. Runs while\n * the stream is locked against new writes; the truncate runs\n * immediately after a successful resolve.\n * @returns The ActionBuilder for chaining.\n *\n * @example Archive to S3 before truncate.\n * ```typescript\n * state({ Ticket: ticketSchema })\n * .emits({ TicketOpened, TicketResolved })\n * // ...\n * .autocloses({ is: \"TicketResolved\" })\n * .archives(async (stream) => {\n * const events = await loadEvents(stream);\n * await s3.upload(`tickets/${stream}.jsonl`, events);\n * })\n * ```\n */\n archives: (\n archive: AutocloseArchiver<TEvents>\n ) => ActionBuilder<TState, TEvents, TActions, TName, TSnap>;\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 * @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 state_schema = (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 default_patch = 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: state_schema,\n name,\n init,\n patch: default_patch,\n on: {},\n // Step delegates initialized as identity, `pii_aware` false.\n // `act().build()` flips both on states with `sensitive(...)`\n // events to bake in the gate / split and gate the cache write.\n pii_aware: false,\n view: (event) => event,\n message: (validated) => validated,\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 options?: ActionOptions\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 if (options) {\n // Validate the whole action bag at declaration so a bad\n // `maxRetries`/`backoff` throws ZodError at build, not a NaN gate.\n resolveActionConfig(options);\n internal.options ??= {};\n (internal.options as Record<string, ActionOptions>)[action] = options;\n }\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 event_name = 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. 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 emit_fn = Object.assign(\n (payload: any) => [event_name, payload],\n {\n _static_emit: event_name,\n }\n );\n (internal.on as Record<string, unknown>)[action] = emit_fn;\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 // Flip the type-level TSnap flag — same runtime object, the cast\n // unlocks `.autocloses({ keep })` for the rest of the chain.\n return builder as unknown as ActionBuilder<\n TState,\n TEvents,\n TActions,\n TName,\n true\n >;\n },\n\n discloses(\n disclose: (\n event: Committed<TEvents, keyof TEvents & string>,\n actor: Actor\n ) => boolean\n ) {\n // Replace on every call — matches snap's state-level semantics. Operators\n // who need per-event differences branch inside the predicate.\n internal.disclose = disclose;\n return builder;\n },\n\n autocloses(policy: AutoclosePolicy) {\n // Declarative policy only. The online path is a synthesized\n // reaction that defers to a derivable due-time and closes — an opaque\n // function predicate has no terminal event to react to nor a window to\n // derive, so it's no longer accepted online. Operators who need custom\n // logic call `app.close(...)` from their own reaction.\n if (typeof policy === \"function\") {\n throw new Error(\n \".autocloses(fn) is no longer supported — pass a declarative policy \" +\n \"({ after, is, reaches, or }) or call app.close(...) from your own \" +\n \"reaction for custom logic.\"\n );\n }\n if (policy === null || typeof policy !== \"object\") {\n throw new Error(\n \".autocloses(...) requires a policy object; got \" + typeof policy\n );\n }\n // The type gate (`TSnap`) already rejects `keep` before `.snap` at\n // compile time; this is the equivalent guard for untyped callers.\n if ((policy as AutoclosePolicy).keep && !internal.snap) {\n throw new Error(\n \".autocloses({ keep }) requires .snap(...) earlier in the chain — a rolling window prunes behind a real snapshot, so a state that never snapshots has nothing to prune behind.\"\n );\n }\n // Replace on every call — matches snap / discloses state-level\n // semantics. Compile to the predicate the reaction evaluates, and\n // cache the policy's min `after` window so the reaction knows whether\n // to park on a due-time or wait for the next event; `keep` resolves\n // to the rolling-window width the reaction prunes against.\n internal.autoclose = compile_autoclose_policy(\n policy\n ) as AutoclosePredicate<TEvents>;\n internal.autoclose_after_days = policy_min_after_days(policy);\n internal.autoclose_keep_days = policy_keep_days(policy);\n return builder;\n },\n\n archives(archive: AutocloseArchiver<TEvents>) {\n if (typeof archive !== \"function\") {\n throw new Error(\n \".archives(archive) requires a function; got \" + typeof archive\n );\n }\n internal.archive = archive;\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.\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 = parse_csv_line(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 // Revive dates like every Store adapter does — a Date in an event\n // payload must not depend on whether it came back through a store or\n // through a CSV restore. The `created` column below has\n // always been parsed explicitly; the JSON columns were missed.\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 next_id = 1;\n try {\n await write_line(writer, CSV_COLUMNS.join(\",\"));\n await driver(async (event) => {\n const id = next_id++;\n const row = [\n String(id),\n csv_escape(event.name as string),\n csv_escape(JSON.stringify(event.data)),\n csv_escape(event.stream),\n String(event.version),\n event.created.toISOString(),\n csv_escape(JSON.stringify(event.meta)),\n ].join(\",\");\n await write_line(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 parse_csv_line(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 csv_escape(value: string): string {\n if (/[\",\\n\\r]/.test(value)) return `\"${value.replace(/\"/g, '\"\"')}\"`;\n return value;\n}\n\nfunction write_line(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":["cache","store","action","import_zod","import_zod","import_zod","correlated_at","log","store","cache","store","state","sensitive","deps","import_zod","import_zod","store","config","store","catch_up_correlation","tombstone","load","snap","state","cache","store","import_node_crypto","state","action","import_zod","import_zod","import_node_crypto","store","state","cache","store","action","valid","action","block","config","cache","row","EventEmitter","store","action","cache","import_zod","state","config","import_zod","schema","sensitive","state","snap","state","config","config","noop","state","config","state","action","snap"]}