@demlik/tea 0.1.0 → 0.1.2

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 (243) hide show
  1. package/LICENSE +21 -0
  2. package/dist/agent/index.d.ts +907 -0
  3. package/dist/agent/index.js +20 -0
  4. package/dist/agent/index.js.map +1 -0
  5. package/dist/authed-call/index.d.ts +119 -0
  6. package/dist/authed-call/index.js +148 -0
  7. package/dist/authed-call/index.js.map +1 -0
  8. package/dist/await-terminal/index.d.ts +99 -0
  9. package/dist/await-terminal/index.js +75 -0
  10. package/dist/await-terminal/index.js.map +1 -0
  11. package/dist/batch-window/index.d.ts +259 -0
  12. package/dist/batch-window/index.js +43 -0
  13. package/dist/batch-window/index.js.map +1 -0
  14. package/dist/cache/index.d.ts +2 -2
  15. package/dist/cache/index.js +2 -50
  16. package/dist/cache/index.js.map +1 -1
  17. package/dist/chunk-27N2SPTN.js +222 -0
  18. package/dist/chunk-27N2SPTN.js.map +1 -0
  19. package/dist/chunk-2YOE5PIS.js +45 -0
  20. package/dist/chunk-2YOE5PIS.js.map +1 -0
  21. package/dist/chunk-3545BOYL.js +65 -0
  22. package/dist/chunk-3545BOYL.js.map +1 -0
  23. package/dist/chunk-3XJWC7VW.js +61 -0
  24. package/dist/chunk-3XJWC7VW.js.map +1 -0
  25. package/dist/chunk-5DEQ5I3U.js +132 -0
  26. package/dist/chunk-5DEQ5I3U.js.map +1 -0
  27. package/dist/chunk-5VNWZADP.js +49 -0
  28. package/dist/chunk-5VNWZADP.js.map +1 -0
  29. package/dist/chunk-6RGBKODV.js +268 -0
  30. package/dist/chunk-6RGBKODV.js.map +1 -0
  31. package/dist/{chunk-ZRUST6BK.js → chunk-7FYQGDMF.js} +2 -2
  32. package/dist/chunk-7FYQGDMF.js.map +1 -0
  33. package/dist/chunk-7W4LMPUW.js +186 -0
  34. package/dist/chunk-7W4LMPUW.js.map +1 -0
  35. package/dist/chunk-BYQUGDD3.js +16 -0
  36. package/dist/chunk-BYQUGDD3.js.map +1 -0
  37. package/dist/{chunk-PYBQREFU.js → chunk-DILMKOZ7.js} +22 -26
  38. package/dist/chunk-DILMKOZ7.js.map +1 -0
  39. package/dist/chunk-EHIX7NYZ.js +93 -0
  40. package/dist/chunk-EHIX7NYZ.js.map +1 -0
  41. package/dist/chunk-HCEVHFJ7.js +54 -0
  42. package/dist/chunk-HCEVHFJ7.js.map +1 -0
  43. package/dist/chunk-HJO6VNQI.js +15 -0
  44. package/dist/chunk-HJO6VNQI.js.map +1 -0
  45. package/dist/chunk-IN33Q4VJ.js +52 -0
  46. package/dist/chunk-IN33Q4VJ.js.map +1 -0
  47. package/dist/chunk-J6527VRQ.js +56 -0
  48. package/dist/chunk-J6527VRQ.js.map +1 -0
  49. package/dist/chunk-JELSZN25.js +47 -0
  50. package/dist/chunk-JELSZN25.js.map +1 -0
  51. package/dist/chunk-K575PT4S.js +58 -0
  52. package/dist/chunk-K575PT4S.js.map +1 -0
  53. package/dist/chunk-K7Q23EQ4.js +20 -0
  54. package/dist/chunk-K7Q23EQ4.js.map +1 -0
  55. package/dist/chunk-LEC4U6CX.js +91 -0
  56. package/dist/chunk-LEC4U6CX.js.map +1 -0
  57. package/dist/{chunk-PYOCUBQJ.js → chunk-LP7VQBRG.js} +22 -15
  58. package/dist/chunk-LP7VQBRG.js.map +1 -0
  59. package/dist/{chunk-CMG2KMWX.js → chunk-MMH7CW5K.js} +220 -189
  60. package/dist/chunk-MMH7CW5K.js.map +1 -0
  61. package/dist/{chunk-Y5JM3UUH.js → chunk-NSDFA6M6.js} +75 -3
  62. package/dist/chunk-NSDFA6M6.js.map +1 -0
  63. package/dist/chunk-ON24RKSE.js +60 -0
  64. package/dist/chunk-ON24RKSE.js.map +1 -0
  65. package/dist/chunk-PS23H6KQ.js +87 -0
  66. package/dist/chunk-PS23H6KQ.js.map +1 -0
  67. package/dist/chunk-QLA76GIT.js +162 -0
  68. package/dist/chunk-QLA76GIT.js.map +1 -0
  69. package/dist/chunk-S3FQN4SL.js +506 -0
  70. package/dist/chunk-S3FQN4SL.js.map +1 -0
  71. package/dist/chunk-SC3FAFZN.js +53 -0
  72. package/dist/chunk-SC3FAFZN.js.map +1 -0
  73. package/dist/chunk-SINXE47Y.js +55 -0
  74. package/dist/chunk-SINXE47Y.js.map +1 -0
  75. package/dist/chunk-SQTCS44W.js +33 -0
  76. package/dist/chunk-SQTCS44W.js.map +1 -0
  77. package/dist/chunk-TGG26XMK.js +52 -0
  78. package/dist/chunk-TGG26XMK.js.map +1 -0
  79. package/dist/chunk-UV6UWGEO.js +147 -0
  80. package/dist/chunk-UV6UWGEO.js.map +1 -0
  81. package/dist/chunk-UYWUVEP6.js +158 -0
  82. package/dist/chunk-UYWUVEP6.js.map +1 -0
  83. package/dist/chunk-VLGARN6H.js +202 -0
  84. package/dist/chunk-VLGARN6H.js.map +1 -0
  85. package/dist/circuit-breaker/index.js +1 -51
  86. package/dist/circuit-breaker/index.js.map +1 -1
  87. package/dist/core-BoB6t7dB.d.ts +188 -0
  88. package/dist/deadline/index.d.ts +24 -5
  89. package/dist/deadline/index.js +4 -18
  90. package/dist/deadline/index.js.map +1 -1
  91. package/dist/debounce/index.d.ts +6 -0
  92. package/dist/debounce/index.js +1 -54
  93. package/dist/debounce/index.js.map +1 -1
  94. package/dist/devtools/index.d.ts +1 -1
  95. package/dist/devtools/index.js +18 -6
  96. package/dist/devtools/index.js.map +1 -1
  97. package/dist/do/index.d.ts +1723 -92
  98. package/dist/do/index.js +673 -31
  99. package/dist/do/index.js.map +1 -1
  100. package/dist/durable-effects-CO9Uh971.d.ts +180 -0
  101. package/dist/extension/index.d.ts +31 -13
  102. package/dist/extension/index.js +5 -3
  103. package/dist/extension/index.js.map +1 -1
  104. package/dist/extension/react.js +8 -3
  105. package/dist/extension/react.js.map +1 -1
  106. package/dist/extension/subs/index.d.ts +2 -2
  107. package/dist/extension/subs/index.js.map +1 -1
  108. package/dist/extension/test-utils.js +11 -3
  109. package/dist/extension/test-utils.js.map +1 -1
  110. package/dist/fan-out/index.d.ts +239 -0
  111. package/dist/fan-out/index.js +5 -0
  112. package/dist/fan-out/index.js.map +1 -0
  113. package/dist/idempotency/adapter.d.ts +62 -0
  114. package/dist/idempotency/adapter.js +4 -0
  115. package/dist/idempotency/adapter.js.map +1 -0
  116. package/dist/idempotency/index.js +1 -56
  117. package/dist/idempotency/index.js.map +1 -1
  118. package/dist/idempotent-intake/index.d.ts +186 -0
  119. package/dist/idempotent-intake/index.js +7 -0
  120. package/dist/idempotent-intake/index.js.map +1 -0
  121. package/dist/index.d.ts +341 -191
  122. package/dist/index.js +2 -1
  123. package/dist/llm-call/index.d.ts +309 -0
  124. package/dist/llm-call/index.js +14 -0
  125. package/dist/llm-call/index.js.map +1 -0
  126. package/dist/machine-viz/index.d.ts +4 -4
  127. package/dist/machine-viz/index.js +5 -9
  128. package/dist/machine-viz/index.js.map +1 -1
  129. package/dist/mem/index.d.ts +1 -0
  130. package/dist/monitored-run/index.d.ts +253 -0
  131. package/dist/monitored-run/index.js +10 -0
  132. package/dist/monitored-run/index.js.map +1 -0
  133. package/dist/node/index.d.ts +5 -5
  134. package/dist/node/index.js.map +1 -1
  135. package/dist/paginated-walk/index.d.ts +234 -0
  136. package/dist/paginated-walk/index.js +15 -0
  137. package/dist/paginated-walk/index.js.map +1 -0
  138. package/dist/paginator/index.d.ts +271 -0
  139. package/dist/paginator/index.js +3 -0
  140. package/dist/paginator/index.js.map +1 -0
  141. package/dist/parity/index.d.ts +92 -0
  142. package/dist/parity/index.js +78 -0
  143. package/dist/parity/index.js.map +1 -0
  144. package/dist/pbt/arbitraries/index.d.ts +1 -1
  145. package/dist/pbt/arbitraries/index.js +1 -1
  146. package/dist/pbt/index.d.ts +15 -8
  147. package/dist/pbt/index.js +6 -11
  148. package/dist/pbt/index.js.map +1 -1
  149. package/dist/pbt/runners/index.d.ts +1 -1
  150. package/dist/pbt/runners/index.js +3 -2
  151. package/dist/poller/index.d.ts +288 -0
  152. package/dist/poller/index.js +79 -0
  153. package/dist/poller/index.js.map +1 -0
  154. package/dist/prediction/index.d.ts +130 -0
  155. package/dist/prediction/index.js +4 -0
  156. package/dist/prediction/index.js.map +1 -0
  157. package/dist/protocol-B5YmJr0d.d.ts +45 -0
  158. package/dist/pure/index.d.ts +2 -0
  159. package/dist/pure/index.js +4 -0
  160. package/dist/pure/index.js.map +1 -0
  161. package/dist/raft/demo.d.ts +105 -0
  162. package/dist/raft/demo.js +172 -0
  163. package/dist/raft/demo.js.map +1 -0
  164. package/dist/raft/index.d.ts +548 -0
  165. package/dist/raft/index.js +7 -0
  166. package/dist/raft/index.js.map +1 -0
  167. package/dist/raft/sim.d.ts +222 -0
  168. package/dist/raft/sim.js +8 -0
  169. package/dist/raft/sim.js.map +1 -0
  170. package/dist/raft/timeline.d.ts +46 -0
  171. package/dist/raft/timeline.js +62 -0
  172. package/dist/raft/timeline.js.map +1 -0
  173. package/dist/rate-limit/index.js +1 -43
  174. package/dist/rate-limit/index.js.map +1 -1
  175. package/dist/react/index.d.ts +2 -1
  176. package/dist/react/index.js +43 -20
  177. package/dist/react/index.js.map +1 -1
  178. package/dist/reconciler/index.d.ts +192 -0
  179. package/dist/reconciler/index.js +166 -0
  180. package/dist/reconciler/index.js.map +1 -0
  181. package/dist/recorder/index.d.ts +7 -3
  182. package/dist/recorder/index.js +1 -155
  183. package/dist/recorder/index.js.map +1 -1
  184. package/dist/resilient-call/index.d.ts +294 -0
  185. package/dist/resilient-call/index.js +13 -0
  186. package/dist/resilient-call/index.js.map +1 -0
  187. package/dist/retry-backoff/index.d.ts +42 -5
  188. package/dist/retry-backoff/index.js +1 -35
  189. package/dist/retry-backoff/index.js.map +1 -1
  190. package/dist/retry-to-success/index.d.ts +109 -0
  191. package/dist/retry-to-success/index.js +35 -0
  192. package/dist/retry-to-success/index.js.map +1 -0
  193. package/dist/saga/index.d.ts +238 -0
  194. package/dist/saga/index.js +150 -0
  195. package/dist/saga/index.js.map +1 -0
  196. package/dist/snapshot/index.d.ts +334 -0
  197. package/dist/snapshot/index.js +5 -0
  198. package/dist/snapshot/index.js.map +1 -0
  199. package/dist/subs/index.d.ts +48 -10
  200. package/dist/subs/index.js +1 -1
  201. package/dist/testing/index.d.ts +107 -2
  202. package/dist/testing/index.js +204 -6
  203. package/dist/testing/index.js.map +1 -1
  204. package/dist/throttle/index.d.ts +9 -0
  205. package/dist/throttle/index.js +1 -52
  206. package/dist/throttle/index.js.map +1 -1
  207. package/dist/throttled-input/index.d.ts +380 -0
  208. package/dist/throttled-input/index.js +88 -0
  209. package/dist/throttled-input/index.js.map +1 -0
  210. package/dist/token-refresh/index.d.ts +215 -0
  211. package/dist/token-refresh/index.js +6 -0
  212. package/dist/token-refresh/index.js.map +1 -0
  213. package/dist/trace-replay/index.d.ts +11 -2
  214. package/dist/trace-replay/index.js +3 -55
  215. package/dist/trace-replay/index.js.map +1 -1
  216. package/dist/{types-CwBC5wMn.d.ts → types-B-8bcAp8.d.ts} +1 -1
  217. package/dist/with-deadline/index.d.ts +196 -0
  218. package/dist/with-deadline/index.js +111 -0
  219. package/dist/with-deadline/index.js.map +1 -0
  220. package/dist/with-resilience/index.d.ts +205 -0
  221. package/dist/with-resilience/index.js +251 -0
  222. package/dist/with-resilience/index.js.map +1 -0
  223. package/dist/with-telemetry/index.d.ts +149 -0
  224. package/dist/with-telemetry/index.js +70 -0
  225. package/dist/with-telemetry/index.js.map +1 -0
  226. package/dist/work-queue/adapter.d.ts +82 -0
  227. package/dist/work-queue/adapter.js +4 -0
  228. package/dist/work-queue/adapter.js.map +1 -0
  229. package/dist/work-queue/index.d.ts +25 -11
  230. package/dist/work-queue/index.js +1 -46
  231. package/dist/work-queue/index.js.map +1 -1
  232. package/dist/work-queue/ops.d.ts +69 -0
  233. package/dist/work-queue/ops.js +3 -0
  234. package/dist/work-queue/ops.js.map +1 -0
  235. package/dist/workflow/index.d.ts +450 -0
  236. package/dist/workflow/index.js +225 -0
  237. package/dist/workflow/index.js.map +1 -0
  238. package/package.json +168 -25
  239. package/dist/chunk-CMG2KMWX.js.map +0 -1
  240. package/dist/chunk-PYBQREFU.js.map +0 -1
  241. package/dist/chunk-PYOCUBQJ.js.map +0 -1
  242. package/dist/chunk-Y5JM3UUH.js.map +0 -1
  243. package/dist/chunk-ZRUST6BK.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["state","opts"],"mappings":"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","file":"chunk-MMH7CW5K.js","sourcesContent":["/**\n * @demlik/tea — TEA-faithful state machine substrate.\n *\n * This module exposes the full Locked API Surface from the PRD as types and\n * implements `defineMachine` (identity, task 1), `run` (task 2), and\n * `replay` + `tryInterpret` (task 3).\n *\n * `replay` is the pure unit-test tool: it composes `init` + `update` only,\n * never touches `Store`, never calls `interpret`, never starts subscriptions.\n *\n * `tryInterpret` is Railway sugar — wraps a fallible async function and routes\n * Ok/Err to two Msg constructors via better-result.\n */\n\nimport { Result } from \"better-result\";\nimport type {\n Machine,\n Port,\n PortEmitter,\n Reducer,\n Sub,\n Transitions,\n} from \"./pure/core\";\nimport {\n __DEV__,\n applyCell,\n assertPureResult,\n type Cmd,\n deepFreeze,\n detectUpdateForm,\n foldUpdates,\n} from \"./pure/core\";\n\nexport type {\n ContextFree,\n Interpret,\n Machine,\n NoCtx,\n Port,\n PortEmitter,\n Reducer,\n Sub,\n SubId,\n Subscribe,\n SyncReturn,\n Transitions,\n UpdateForm,\n} from \"./pure/core\";\n// Re-export the pure-core surface so the root `@demlik/tea` entry is unchanged\n// (additive; the runtime-free guarantee lives on `@demlik/tea/pure`).\nexport {\n applyCell,\n Cmd,\n detectUpdateForm,\n foldMsgs,\n formOf,\n msgKeysOf,\n subId,\n} from \"./pure/core\";\n\n// The nominal brand minted ONLY through the validated construction path\n// (`asReducer` / `defineMachine`). Mirrors `retry-backoff`'s `RngBrand`: a raw\n// record of handlers is a structural `Reducer<S, M, C>`, but a `Reducer` that\n// also carries this phantom brand is one that has passed through the single\n// minting boundary. The brand is an *optional* phantom so the structural\n// `Reducer<S, M, C>` annotation form (`const update: Reducer<...> = { ... }`)\n// keeps accepting plain object literals — the guard that actually rejects an\n// async reducer is `SyncReturn`'s non-thenable return, enforced on every cell.\ndeclare const ReducerBrand: unique symbol;\n\n// A `Reducer` (or `Transitions`) that has been minted through `asReducer` /\n// `defineMachine`. Carries the phantom brand; otherwise identical to its\n// structural counterpart.\nexport type Branded<T> = T & { readonly [ReducerBrand]: true };\n\n// === absurd: compile-time exhaustiveness assertion ===\n//\n// Use in default branches of switches over discriminated unions where every\n// case should be handled explicitly. TS narrows the operand to `never` only\n// if every variant has been covered upstream; adding a new variant produces\n// a compile error at the `absurd(x)` site.\n//\n// The substrate's `Reducer<S, M, C>` and `Transitions<S, M, C>` forms cover\n// the reducer-side exhaustiveness with mapped types — no `absurd` needed\n// there. This helper exists for the OTHER boundaries where a discriminated\n// union is narrowed by hand: Sub handlers mapping a wire-protocol\n// discriminant to flat Msg variants, message-bridge dispatchers, port\n// fanouts, etc. Without it, consumers redeclare the same 3-line helper\n// across files; with it, the substrate owns the one canonical version.\n//\n// Strengthens invariant 7 (identity is explicit).\n/**\n * Compile-time exhaustiveness assertion. Use in default branches of\n * switches over discriminated unions where every case should be handled\n * explicitly — TS narrows the type to `never` only if every variant has\n * been covered. Strengthens invariant 7 (identity is explicit).\n *\n * @example\n * switch (msg.type) {\n * case \"a\": return ...;\n * case \"b\": return ...;\n * default: return absurd(msg); // compile error if a \"c\" is added\n * }\n */\nexport function absurd(x: never): never {\n throw new Error(`unreachable: ${JSON.stringify(x)}`);\n}\n\n// === noop: the explicit \"this cell ignores this msg\" helper ===\n//\n// Elm's fallback for unhandled (state × msg) pairs is implicit:\n// `_ -> (model, Cmd.none)` in a case expression. We make it explicit because\n// implicit no-ops are silent regressions waiting to happen — a future Msg\n// variant that *should* be handled gets swallowed by the wildcard.\n//\n// Naming the no-op forces the author to *decide*: \"this cell does nothing\"\n// is a real decision, distinct from \"I forgot to write this cell.\" The\n// mapped type rejects the second case; `noop` names the first.\n//\n// Assignable to any Transitions cell regardless of S/M/C concrete types\n// (the type parameters are free) — drop it into any cell without per-type\n// casts.\nexport const noop = <S, M, C extends Cmd>(\n state: S,\n _msg: M,\n): readonly [S, readonly C[]] => [state, []];\n\n// Module-level registry — process-scope, identity-by-name. The set is the\n// runtime witness that every port name in this process is unique. Cleared\n// only by the test-only `__resetPortRegistry()` helper.\nconst definedPortNames = new Set<string>();\n\n/**\n * Thrown by `definePort` when a name has already been registered in the\n * current process. Symmetric with the `Sub.id` collision assert in\n * `reconcileSubs` — both mechanize invariant 7 (identity is explicit) at the\n * runtime layer the type system cannot reach (string names compared at\n * runtime, not at compile time).\n */\nexport class PortNameCollisionError extends Error {\n override readonly name = \"PortNameCollisionError\";\n constructor(portName: string) {\n super(\n `definePort: a port named \"${portName}\" was already defined. ` +\n `Each definePort call must use a unique name. ` +\n `If two modules need the same port, export it from one module and import it.`,\n );\n }\n}\n\n/**\n * Test-only escape hatch — clears the module-level port-name registry so the\n * collision assert in `definePort` doesn't false-positive across vitest's\n * non-isolated runs. Production code MUST NOT call this; the registry is the\n * invariant-7 witness for the process lifetime.\n *\n * @internal test-only\n */\nexport function __resetPortRegistry(): void {\n definedPortNames.clear();\n}\n\n// === Runtime error sink (invariant 6 — no silent failures) ===\n//\n// The runtime has points where a failure has no natural caller to reject at:\n// a follow-up Msg an interpret handler enqueued (the original dispatcher\n// already resolved), and the final `store.save` during `stop()` (whose\n// contract is a resolved Promise). Historically both were swallowed —\n// `.catch(() => {})` and a bare `console.error` — which violates invariant 6:\n// the runtime must be inspectable; no silent failures.\n//\n// `RuntimeErrorContext` tags WHICH swallowed path produced the error so a sink\n// can route by phase. `OnError` is the sink itself, configured at `run(...)`.\n// When no sink is provided the runtime uses `defaultOnError`, which RE-THROWS\n// on a fresh macrotask — surfacing to the host's unhandled-rejection / global\n// error handler rather than vanishing. The default surfaces; it never swallows.\n\n/**\n * Which otherwise-unattributable runtime path produced an error.\n *\n * - `\"follow-up\"` — a follow-up Msg an interpret handler returned rejected\n * when re-dispatched. The original dispatcher already resolved, so this\n * rejection has no caller; without the sink it was swallowed.\n * - `\"stop-save\"` — the final `store.save(state)` inside `stop()` threw.\n * `stop()` resolves regardless (its contract), so without the sink this was\n * silent loss of the last write.\n * - `\"reduce\"` — the pure `update` (reducer) threw synchronously while folding\n * a Msg. #71's reentrancy brand makes a reducer provably synchronous, so this\n * throw is catchable in the dispatch loop; the configured `Supervision`\n * strategy decides what the runtime does next (`stop` / `escalate` /\n * `restart`), but the failure is ALWAYS surfaced here as data first.\n */\nexport type RuntimeErrorPhase = \"follow-up\" | \"stop-save\" | \"reduce\";\n\n/** Context handed to an `OnError` sink alongside the error itself. */\nexport interface RuntimeErrorContext {\n readonly phase: RuntimeErrorPhase;\n}\n\n/**\n * Sink for runtime failures that have no caller to reject at. Configured via\n * `run(machine, { onError })`. Should be total — a throw inside the sink is\n * itself surfaced via `defaultOnError`, so the sink can never re-introduce a\n * silent failure.\n */\nexport type OnError = (error: unknown, context: RuntimeErrorContext) => void;\n\n/**\n * Default `onError` sink: re-throw on a fresh macrotask so the failure reaches\n * the host's global error / unhandledRejection handler instead of vanishing.\n * Used whenever `run(...)` is called without an explicit `onError`. The least\n * surprising default — it surfaces rather than swallows (invariant 6) without\n * forcing every caller to wire a sink.\n */\nfunction defaultOnError(error: unknown, _context: RuntimeErrorContext): void {\n setTimeout(() => {\n throw error;\n }, 0);\n}\n\n// === Supervision: declared policy for a reducer throw (ADR 0003 #4) ===\n//\n// The resilience kit (retry, circuit-breaker, …) covers *effect* failures —\n// throws inside `interpret`. A throw inside the pure `update` (the reducer) had\n// no declared policy: it simply rejected the dispatch promise and left the\n// runtime in an ambiguous \"did we halt or not?\" state. #71's reentrancy brand\n// makes a reducer provably synchronous, so a reducer throw is now a synchronous\n// throw catchable in the dispatch loop. This is the seam Akka supervisor\n// strategies / Erlang-OTP supervision trees occupy: \"let it crash\" becomes\n// CONFIG, not hope.\n//\n// Every strategy routes the failure to the `onError` sink with `phase:\n// \"reduce\"` FIRST (invariant 6 — errors are data, never silently swallowed),\n// then differs in what the runtime does next:\n//\n// - `stop` — halt the runtime. State is NOT advanced; the dispatch promise\n// rejects with the reducer error; every subsequent dispatch\n// rejects (\"runtime stopped\"). The SAFE DEFAULT: a reducer that\n// violated its own invariants does not get to keep folding.\n// Never a silent resume.\n// - `escalate`— surface via `onError` AND propagate: the dispatch promise\n// rejects with the reducer error so the failure bubbles to the\n// caller/parent supervisor. The runtime is NOT halted (a parent\n// may choose to keep dispatching) — escalation is \"tell someone\n// above me\", not \"die\".\n// - `restart` — re-initialize from a host-provided last-known-good state and\n// keep folding. The core does NOT own snapshot logic; the host\n// supplies `rehydrate()`, the core invokes it, installs its\n// result as the new state, and continues the transition\n// (save → reconcile → interpret → fire) from there. The\n// original failure is still surfaced as data via `onError`.\n//\n// The restart rehydrate is a host callback by design: the core has no opinion\n// on where last-known-good state lives (a snapshot Store, an in-memory cache, a\n// recomputed default). Mirrors how `Store` keeps persistence out of core.\n\n/** The three declared reducer-throw supervision strategies. */\nexport type SupervisionStrategy = \"stop\" | \"escalate\" | \"restart\";\n\n/**\n * Declared supervision policy for a reducer (`update`) throw, configured at\n * `run(machine, { supervision })`.\n *\n * - `{ strategy: \"stop\" }` — halt + surface (the safe default; also the bare\n * shorthand `\"stop\"`).\n * - `{ strategy: \"escalate\" }` — surface + propagate, runtime stays live (also\n * the bare shorthand `\"escalate\"`).\n * - `{ strategy: \"restart\", rehydrate }` — surface, then re-init from the\n * host-supplied last-known-good `S` and keep folding. `rehydrate` receives\n * the failing `(state, msg, error)` so the host can log / pick a snapshot;\n * it MUST return a valid `S` synchronously (the reducer is synchronous, so\n * recovery is too — no suspension across the single-writer slot).\n *\n * The bare-string shorthands (`\"stop\"` / `\"escalate\"`) are accepted for the two\n * strategies that need no host data; `restart` MUST be the object form because\n * it carries the `rehydrate` callback.\n */\nexport type Supervision<S, M extends { type: string }> =\n | \"stop\"\n | \"escalate\"\n | { readonly strategy: \"stop\" }\n | { readonly strategy: \"escalate\" }\n | {\n readonly strategy: \"restart\";\n /**\n * Host-provided rehydration to last-known-good state. Invoked by the core\n * when the reducer throws; its return value becomes the new state and the\n * transition continues from there. Receives the pre-throw `state`, the\n * `msg` that triggered the throw, and the thrown `error` so the host can\n * route by cause.\n */\n readonly rehydrate: (state: S, msg: M, error: unknown) => S;\n };\n\n/**\n * Normalize the `Supervision` config (bare string or object) into a single\n * object shape so the dispatch loop branches on `.strategy` once. The default\n * — applied when `run(...)` is called without `supervision` — is `stop`: the\n * explicit, safe choice. It surfaces via `onError` and halts; it never silently\n * resumes a machine whose reducer just violated an invariant (invariant 6).\n */\ntype NormalizedSupervision<S, M extends { type: string }> =\n | { readonly strategy: \"stop\" }\n | { readonly strategy: \"escalate\" }\n | {\n readonly strategy: \"restart\";\n readonly rehydrate: (state: S, msg: M, error: unknown) => S;\n };\n\nfunction normalizeSupervision<S, M extends { type: string }>(\n supervision: Supervision<S, M> | undefined,\n): NormalizedSupervision<S, M> {\n if (supervision === undefined) return { strategy: \"stop\" };\n if (typeof supervision === \"string\") return { strategy: supervision };\n return supervision;\n}\n\n/**\n * Raised by `idle()` when the quiescence wait hits its iteration cap without\n * the dispatch tail stabilizing. Replaces the old silent fall-through-resolve\n * (which made \"the loop quiesced\" indistinguishable from \"we gave up\"):\n * `idle()` now REJECTS with this so a livelocking machine surfaces instead of\n * masquerading as quiescent.\n *\n * Mechanizes invariant 6 (no silent failures) at the runtime layer — the same\n * role `PortNameCollisionError` plays for invariant 7.\n */\nexport class QuiescenceTimeoutError extends Error {\n override readonly name = \"QuiescenceTimeoutError\";\n constructor(public readonly iterations: number) {\n super(\n `@demlik/tea: idle() did not reach quiescence after ${iterations} ` +\n `iterations — the dispatch tail kept advancing. The machine is ` +\n `likely livelocking (an interpret handler enqueues a follow-up Msg ` +\n `that enqueues another, without end). Bound the follow-up chain in ` +\n `the reducer, or stop the runtime.`,\n );\n }\n}\n\n/**\n * Define a typed port. `name` is metadata (shown in devtools / debug logs);\n * port identity is by reference. Each definePort call must use a unique\n * `name` — a second call with the same name throws\n * `PortNameCollisionError`. If two modules need the same port, export it\n * from one module and import it from the other.\n *\n * Use ports for \"data leaving the runtime selectively\" — e.g. cursor\n * announcements, DOM-mutation broadcasts, telemetry events that should NOT be\n * folded into State and should NOT be observed by every transition listener.\n *\n * Strengthens invariant 7 (identity is explicit) — the runtime assert is the\n * Port-side counterpart of `SubId`'s id collision check in `reconcileSubs`.\n */\nexport function definePort<T>(name: string): Port<T> {\n // HMR skip — Vite / dev servers re-import the module on hot reload, which\n // would otherwise false-positive on every definePort across reloads. The\n // try/catch is load-bearing for service-worker bundles: Vite polyfills\n // `import.meta.url` via `document.baseURI`, which throws ReferenceError in\n // an MV3 service worker. A throw here would abort SW install (Chrome\n // surfaces it as \"registration failed status 15\"). Catching it = \"no HMR\n // detected\" = the collision check applies, which is the correct SW\n // behavior (SWs reload via chrome.runtime.reload, not module HMR).\n let isHmr = false;\n try {\n const meta = import.meta as { hot?: unknown };\n isHmr = meta?.hot !== undefined && meta?.hot !== null;\n } catch {\n isHmr = false;\n }\n if (!isHmr && definedPortNames.has(name)) {\n throw new PortNameCollisionError(name);\n }\n definedPortNames.add(name);\n return { __brand: \"port\", name } as Port<T>;\n}\n\n// === Store: pluggable persistence adapter ===\n//\n// `load()` returns `unknown` because storage genuinely doesn't know `S` —\n// chrome.storage returns whatever JSON lives at the key, DurableObjectStorage\n// returns whatever bytes were serialized. Casting raw storage to `S` at the\n// adapter boundary is the exact `as S` move forbidden by invariant 8\n// everywhere else in the substrate. `load()` returning `unknown` makes the\n// substrate stop pretending.\n//\n// `migrate(raw)` is the boundary parse. Returns `S` on a recognized shape —\n// the substrate passes it to `init` as `loaded`. Returns `null` on any\n// unrecognized shape — the substrate passes `null` to `init`, fresh-boot\n// path. Must NOT throw: if a future shape is unrecognizable, returning\n// `null` boots clean from a known-good path. Throwing here would\n// indistinguishably collapse \"storage corruption\" and \"schema migration not\n// yet written\" — both are runtime decisions, not panics.\n//\n// Strengthens invariant 8 (the boundary parses; the core trusts) — the\n// substrate now enforces the parse instead of relying on every adapter\n// remembering to.\nexport interface Store<S> {\n load(): Promise<unknown>;\n save(state: S): Promise<void>;\n migrate(raw: unknown): S | null;\n}\n\n// === DispatchSettle: how far a dispatch awaits ===\n//\n// `dispatch(msg)` settles ONE transition by default would be the dangerous\n// choice (issue #50): an `interpret` handler that returns a follow-up Msg\n// enqueues a FRESH transition on the tail, and that follow-up is fire-and-\n// forget relative to the original `dispatch`. Callers that forgot to also\n// `await idle()` saw their dispatch resolve \"early\", before the consequences\n// of the Msg had run — which is why the codebase grew a dispatch+`idle()`\n// wrapper and tests fell back to `for (i<200) sleep(5)` polls.\n//\n// So the default is the SAFE one: `\"quiescent\"` — `dispatch` resolves only\n// once the entire transitive follow-up chain has drained (the same drain\n// `idle()` performs). The rare single-step case (a caller that genuinely wants\n// one transition and will await the tail itself) opts in with `\"once\"`, or\n// uses the `dispatchOnce` convenience.\nexport type DispatchSettle = \"quiescent\" | \"once\";\n\n// === RuntimeRef<M>: typed sibling-runtime handle ===\n//\n// A `RuntimeRef<M>` exposes only the inbox of a Runtime — `dispatch(msg)` (and\n// its single-step sibling `dispatchOnce(msg)`).\n// Use it as the field type when one runtime holds a reference to a *sibling*\n// runtime (composition by reduction across orthogonal lifecycles — invariant\n// 5). The holder learns the Msg shape it can send, nothing about the\n// referenced runtime's State, Cmd, Sub, Ctx, observers, listeners, or Port\n// fanout. That asymmetry is the point: cross-runtime coupling collapses to\n// \"I can put a Msg in your inbox\", which is the smallest coordination\n// surface that preserves typed cross-runtime calls.\n//\n// `Runtime<S, M>` extends `RuntimeRef<M>` structurally — every Runtime is\n// trivially a RuntimeRef. The narrowing happens at the *consumer's* Ctx\n// type, not via a runtime cast.\n//\n// Strengthens invariant 5 (composition by reduction — sibling runtimes\n// coordinate through the narrowest typed surface) and invariant 6 (runtime\n// is small and inspectable — what a holder *can* do to a sibling runtime is\n// exactly one method, not the full surface).\nexport interface RuntimeRef<M extends { type: string }> {\n /**\n * Put a Msg in the runtime's inbox and resolve once it has been processed.\n *\n * Runs to QUIESCENCE by default (issue #50): the returned promise settles\n * only after the dispatched Msg AND every follow-up Msg its `interpret`\n * handlers (transitively) returned have drained off the serial tail. This is\n * the safe default — `await dispatch(msg)` means \"the consequences have run\",\n * not \"one transition fired and the rest are racing\". Pass\n * `{ settle: \"once\" }` (or call `dispatchOnce`) for the rare single-step\n * case where the caller will await the tail itself.\n *\n * Rejection ordering: the ONE dispatched transition's own failure (a reducer\n * / save / sub-start / interpret throw) surfaces first, on this promise. If\n * that transition succeeds but the follow-up chain never stabilizes, the\n * quiescent drain rejects with `QuiescenceTimeoutError` (same cap and same\n * no-silent-give-up contract as `idle()` — issue #51). Follow-up Msg\n * rejections themselves route to the `onError` sink, never here.\n */\n dispatch(msg: M, opts?: { readonly settle?: DispatchSettle }): Promise<void>;\n /**\n * Dispatch `msg` and resolve after exactly ONE transition's effects settle,\n * WITHOUT draining the follow-up chain. Equivalent to\n * `dispatch(msg, { settle: \"once\" })`.\n *\n * This is the old (pre-#50) `dispatch` behavior, kept as an explicit escape\n * hatch: a caller that wants to interleave its own work between the first\n * transition and its follow-ups, then `await runtime.idle()` itself. Prefer\n * plain `dispatch` (run-to-quiescence) unless you specifically need the\n * single step — the un-awaited follow-up chain is exactly the footgun #50\n * removed from the default.\n */\n dispatchOnce(msg: M): Promise<void>;\n}\n\n// === BootingRuntime: handle returned SYNCHRONOUSLY from run() ===\n//\n// `run()` returns a `BootingRuntime<S, M>` the instant it is called — boot\n// (store.load → init → save → reconcile → interpret-of-init-cmds → first\n// fanout) is still in flight. A BootingRuntime exposes exactly the surface\n// that is TOTAL before boot completes: you may queue a dispatch, subscribe a\n// listener, attach an observer, wire a Port, or stop the runtime — none of\n// those need the initial State to exist yet. What you may NOT do is read the\n// State (`getState`) or wait for quiescence (`idle`): there is no State to\n// read until boot has run `init`, and a half-booted runtime has no meaningful\n// \"quiescence\" to await. Those two are the difference between a BootingRuntime\n// and a `Runtime` — and that difference is enforced at the type level.\n//\n// `ready` resolves to the FULL `Runtime<S, M>` once boot completes (or rejects\n// with the boot error). It is the ONLY way to obtain a `Runtime`:\n//\n// const runtime = await run(machine, opts).ready;\n// runtime.getState(); // total — boot has run, State exists\n//\n// This closes issue #45: `getState(): S` used to be declared on the handle\n// `run()` returned synchronously, yet it THREW before boot under a store. The\n// type claimed total; the value was partial, and only JSDoc told you to await.\n// Splitting the booting handle from the ready runtime makes \"read State before\n// boot\" a COMPILE error rather than a runtime throw — the type no longer lies.\n//\n// `subscribe(listener)` is the React-shaped change notifier (zero-arg, paired\n// with `getState()` via `useSyncExternalStore` on the ready Runtime).\n// `observe(observer)` is the devtools-shaped trace hook: it receives `(msg,\n// state)` for every COMPLETED, APPLIED transition. The boot transition is NOT\n// an applied Msg — there is no event there, only the initial State — so it does\n// NOT flow through `observe`. It is delivered once via `onBoot(handler)`\n// instead, so `observe`'s `msg` is total (`M`, never `null`): a consumer no\n// longer carries a `| null` boot arm it then ignores (#47). Both `observe` and\n// `onBoot` fire from the same point in the dispatch loop (after save →\n// reconcile → interpret), so what they see is consistent with what a subscriber\n// sees via the ready Runtime's `getState()`.\n//\n// Observe is separate from subscribe because the contracts differ: React\n// consumers want \"something changed, re-read state\"; devtools consumers want\n// \"here is the exact (msg, state) pair, append it to a log\". Folding them\n// would force every React subscriber to type-check a `msg` arg they will never\n// use, and would couple `useSyncExternalStore` to a particular Msg type at the\n// substrate.\n//\n// `on(type, handler)` is the SEMANTIC event channel (#47): a typed subscription\n// to the machine-level `AgentEvent`-style union `E` a machine projects off its\n// transitions (via `run`'s `events` projector). Where `observe` hands every\n// consumer the raw `(M, S)` firehose to hand-filter — coupling a UI to the\n// machine's PRIVATE Msg vocabulary (e.g. a retry plumbing's `resilient_ok`) —\n// `on` delivers only the public, named events, narrowed to the requested\n// `type`. `E` defaults to `never`: a machine that wires no `events` projector\n// has an empty event surface and `on` is uncallable (no `E[\"type\"]` to pass).\nexport interface BootingRuntime<\n S,\n M extends { type: string },\n E extends { type: string } = never,\n> extends RuntimeRef<M> {\n dispatch(msg: M, opts?: { readonly settle?: DispatchSettle }): Promise<void>;\n dispatchOnce(msg: M): Promise<void>;\n subscribe(listener: () => void): () => void;\n observe(observer: (msg: M, state: S) => void): () => void;\n /**\n * Subscribe to the INITIAL State — the boot transition the old `observe`\n * `msg === null` arm carried (#47). Fires exactly once: immediately if boot\n * has already completed when `onBoot` is called (so a late subscriber never\n * misses it), otherwise on the boot fanout. Returns a cleanup that detaches\n * the handler (a no-op once it has fired).\n *\n * This is where the boot case the `observe` firehose used to fold in went\n * once `observe`'s `msg` became total: a consumer that needs to seed a view\n * from the initial State wires `onBoot`; a consumer that only folds events\n * (the common case) wires `observe` (or `on`) and is no longer handed a boot\n * arm to skip.\n */\n onBoot(handler: (state: S) => void): () => void;\n /**\n * Subscribe to a SEMANTIC event of `type` (#47). Typed narrowing: the handler\n * receives exactly the `E` member whose `type` matches `K`, so a consumer\n * built on `on(\"TurnSettled\", …)` never touches another event's shape and —\n * critically — never references the machine's PRIVATE Msg names. Returns a\n * cleanup that detaches the handler. Multiple handlers per type are\n * supported; fanout is synchronous and throw-isolated (same discipline as\n * `observe`). Fires only when the machine's `events` projector (wired on\n * `run`) emits an event of that type for a transition.\n */\n on<K extends E[\"type\"]>(\n type: K,\n handler: (event: Extract<E, { type: K }>) => void,\n ): () => void;\n /**\n * Subscribe to a typed Port. Returns a cleanup function that removes the\n * listener. Multiple listeners per port are supported; fanout is synchronous\n * (same shape as `observe`) and isolated — one listener throw does not strand\n * the others.\n *\n * Ports are for \"data leaving the runtime selectively\" — see `definePort`.\n * Distinct from `observe` (every transition) and from State (the world).\n */\n subscribePort<T>(port: Port<T>, listener: (value: T) => void): () => void;\n /**\n * Emit a value on a Port from OUTSIDE an interpret handler. Same synchronous\n * fanout discipline as `ctx.emit` inside interpret — every subscriber\n * receives the value immediately; emitting to a port with no subscribers is\n * a no-op; listener throws are isolated.\n *\n * Use this for `observe`-driven Port emission: the canonical case is one\n * runtime publishing a state-derived signal (e.g. \"am I idle?\") that\n * another runtime subscribes to via `subscribePort`. Without\n * `runtime.emitPort`, the only way to emit a Port is from inside an\n * `interpret` handler — which forces the reducer to spawn a \"tell the\n * outside world\" Cmd on every transition that should signal. With it,\n * `runtime.observe((msg, state) => runtime.emitPort(port, derive(state)))`\n * keeps the reducer free of Port-plumbing Cmds and matches the \"every\n * transition is observable\" contract this invariant set already commits to.\n *\n * Strengthens invariant 6 (runtime is small and inspectable — Port emission\n * is no longer privileged to interpret handlers; `observe`-driven emission\n * is structurally supported).\n */\n emitPort<T>(port: Port<T>, value: T): void;\n /**\n * Resolves to the booted `Runtime<S, M>` after boot completes — i.e. after\n * `store.load()` (if any), `init`, `store.save()` of the initial state,\n * `reconcileSubs`, `interpret` of any init-emitted cmds, and the initial\n * listener / observer fanout. Rejects with the boot error if boot fails (the\n * same error every subsequent `dispatch` call rejects with).\n *\n * This is the ONLY way to obtain a `Runtime<S, M>` — and a `Runtime` is the\n * only handle whose `getState()` is total. Awaiting `ready` is therefore the\n * single gate between \"boot in flight\" and \"State exists\":\n *\n * ```ts\n * const runtime = await run(machine, opts).ready;\n * runtime.getState(); // total — never throws-before-boot\n * ```\n *\n * Idempotent — subsequent reads return the same settled promise. The runtime\n * holds exactly one `ready` promise per `run()` call; it resolves to the same\n * `Runtime` object every time.\n *\n * Closes issue #45 (the `getState()` lie) and the v1 boot-await gap once\n * documented in `stepBootEffects`: components that need synchronous initial\n * state under a store (e.g. `useSyncExternalStore` consumers) await `ready`\n * for the booted runtime instead of dispatching a no-op Msg.\n *\n * Expresses canon §2.3 (the `init` contract — boot is a named, awaitable\n * moment). Strengthens invariant 6 (runtime is small and inspectable).\n */\n ready: Promise<Runtime<S, M, E>>;\n stop(): Promise<void>;\n}\n\n// === Runtime: the BOOTED handle `ready` resolves to ===\n//\n// A `Runtime<S, M>` is a `BootingRuntime<S, M>` whose boot has completed. It\n// adds the two members that are only meaningful once the initial State exists:\n// `getState()` (total — boot ran `init`, so State is always present) and\n// `idle()` (quiescence is only definable on a runtime that has booted). It\n// also narrows `ready` to `Promise<Runtime<S, M>>` resolving to itself — a\n// booted runtime awaited again hands back the same booted runtime, so consumer\n// code that re-awaits (e.g. a cached `getRuntime()` accessor) keeps a total\n// `getState`.\n//\n// You never construct a `Runtime` directly from `run()`; you obtain it via\n// `await bootingRuntime.ready`. That asymmetry is the whole fix for #45 —\n// \"read State before boot\" is now unrepresentable, not merely discouraged.\nexport interface Runtime<\n S,\n M extends { type: string },\n E extends { type: string } = never,\n> extends BootingRuntime<S, M, E> {\n /**\n * The current State. TOTAL — never throws. Obtaining a `Runtime` requires\n * awaiting `ready`, which only resolves AFTER boot has run `init` and set the\n * initial State; a `Runtime` therefore always has a State to return. (Before\n * #45 this was declared on the synchronously-returned handle and threw under\n * a store until boot finished — the type lied. It no longer does.)\n */\n getState(): S;\n /**\n * Resolves to this same `Runtime` once boot completes. Idempotent.\n */\n ready: Promise<Runtime<S, M, E>>;\n /**\n * Resolves once the runtime has reached QUIESCENCE — every dispatched Msg AND\n * every follow-up Msg an interpret handler returned has been processed, with\n * no further step pending on the serial tail.\n *\n * Since #50, plain `dispatch(msg)` already runs to quiescence (it awaits this\n * same drain after its own transition), so a caller rarely needs `idle()`\n * directly. `idle()` is still the right tool to (a) settle follow-ups left in\n * flight by a `dispatchOnce` / `dispatch(msg, { settle: \"once\" })` single\n * step, or (b) wait out a follow-up chain kicked off by a Sub or by boot\n * `init` cmds where there was no `dispatch` call to await. It chains onto the\n * current tail and re-checks until the tail stops advancing, draining the\n * entire transitive follow-up chain.\n *\n * Idempotent and re-entrant-safe: each call reads the live tail; a tail that\n * advanced during the await (a follow-up landed) is awaited again until\n * stable. Tail rejections are NOT surfaced here — a failing dispatch\n * surfaces on its OWN returned promise (and follow-up rejections route to\n * the `onError` sink). The ONE rejection `idle()` itself produces is a\n * `QuiescenceTimeoutError` when the wait hits its iteration cap without the\n * tail stabilizing: that replaces the old silent fall-through-resolve so a\n * livelocking machine is distinguishable from a genuinely quiesced one\n * (invariant 6 — no silent failures).\n *\n * Use `idle()` for runtime-internal follow-ups; a poll is still correct when\n * waiting on an EXTERNAL event (a WS reply) the runtime cannot enqueue itself.\n *\n * Strengthens invariant 6 (runtime is small and inspectable — quiescence is a\n * first-class awaitable moment, not a poll the consumer re-derives).\n */\n idle(): Promise<void>;\n /**\n * The terminal State of the run, or `undefined` while it is still in flight.\n * A run is \"terminal\" exactly when the `terminal` predicate passed to `run()`\n * returns `true` for the current State; with no predicate supplied a run is\n * never terminal and this always returns `undefined`.\n *\n * This is the FIRST-CLASS result read (issue #46): the outcome of running the\n * thing, off the State the machine already owns — NOT scraped off the\n * `observe` firehose by matching an internal Msg name (`resilient_ok`) and\n * racing a state-clear. The consumer reads the run's product (e.g. an agent's\n * `state.output`) off the returned `S`, with no coupling to the machine's\n * private retry / loop vocabulary.\n *\n * Total — never throws (a `Runtime` always has a State; see `getState`).\n */\n result(): S | undefined;\n /**\n * Resolves with the terminal State the first time the run reaches a terminal\n * State (per the `terminal` predicate passed to `run()`). If the run is\n * ALREADY terminal when `done()` is called, resolves immediately with the\n * current State; otherwise resolves on the transition that first makes\n * `terminal` hold.\n *\n * The awaitable companion to `result()` — \"wait for the run to finish, then\n * hand me what it produced\" in one call, instead of polling `result()` or\n * hand-rolling an `observe` loop that watches for a private terminal Msg.\n * With no `terminal` predicate supplied the run is never terminal, so this\n * promise never resolves (a non-terminating machine has no result to await).\n *\n * Idempotent and multi-caller safe: every call observes the live State, so a\n * call made after the run already terminated resolves at once, and concurrent\n * callers all settle on the same terminal transition.\n */\n done(): Promise<S>;\n}\n\n// === defineMachine: identity-typed pass-through ===\n//\n// Overloads enforce exactly one `update` shape per call so consumers see a\n// concrete type for `update`, not the substrate-internal union. Implementation\n// is identity at runtime — the runtime (`run`) branches on the structural\n// shape of `update` (Reducer vs Transitions) when dispatching.\n//\n// - Reducer-form overload: `update: Reducer<S, M, C>` — flat record keyed by\n// Msg.type. Exhaustiveness is enforced by the mapped type; adding a Msg\n// variant without a matching key is a compile error.\n// - Transitions-form overload: `update: Transitions<S, M, C>` — 2D table\n// keyed by State.type then Msg.type. Only available when `S extends {\n// type: string }`.\n//\n// Distinguishing the two: TS overload resolution checks the literal shape of\n// the argument. Reducer values are functions; Transitions values are records\n// (of functions). Structurally distinct, so overload resolution picks the\n// right branch.\n//\n// Strengthens invariant 2 (record forms have no fall-through default) and\n// invariant 7 (the Msg variant set — and, for Transitions, the State variant\n// set — is load-bearing at the type level).\n\n// Transitions-form overload — `update` is a 2D table keyed by State.type\n// then Msg.type. Declared FIRST (most specific): the value shape (record of\n// records of functions) is structurally distinct from Reducer (record of\n// functions), so TS overload resolution picks this branch only when the\n// literal matches the table shape.\n//\n// The S constraint is expressed via a conditional `S extends { type: string\n// } ? Transitions<S, M, C> : never` instead of a generic-parameter\n// constraint. The conditional approach keeps `S` unconstrained at the\n// overload signature, so `Parameters<typeof defineMachine<NonDiscriminatedS,\n// ...>>` (the public `satisfies` pattern) doesn't fail at the first\n// overload — it just skips to the next one because `update` becomes\n// `never`.\nexport function defineMachine<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n>(\n m: Omit<Machine<S, M, C, U, Ctx>, \"update\"> & {\n // `[S]` tuple-wrap disables distributive conditional behavior — see\n // the comment on `Machine.update` for why distribution is wrong here.\n update: [S] extends [{ type: string }] ? Transitions<S, M, C> : never;\n },\n): Machine<S, M, C, U, Ctx>;\n// Reducer-form overload — `update` is a flat record keyed by Msg.type.\n// Object literals where every property is a function match this shape.\nexport function defineMachine<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n>(\n m: Omit<Machine<S, M, C, U, Ctx>, \"update\"> & {\n update: Reducer<S, M, C>;\n },\n): Machine<S, M, C, U, Ctx>;\n// Implementation signature — accepts both via the union on `Machine.update`.\nexport function defineMachine<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n>(m: Machine<S, M, C, U, Ctx>): Machine<S, M, C, U, Ctx> {\n // Tag the update form ONCE, here at the typed construction boundary, so no\n // downstream reader (`run`, `replay`, the `withX` wrappers) re-derives it\n // structurally. Non-enumerable: it must not serialize, must not show up in\n // `Object.keys(machine)`, and must not collide with any Msg.type key on a\n // flattened surface. Idempotent under re-wrap (`defineMachine(defineMachine(m))`).\n if (m.__form === undefined) {\n Object.defineProperty(m, \"__form\", {\n value: detectUpdateForm(m.update as object),\n enumerable: false,\n writable: false,\n configurable: true,\n });\n }\n return m;\n}\n\n// === asReducer: the validated minting path for a reducer (ADR 0003 #5) ===\n//\n// The single entry point that turns a raw record of handlers into a branded\n// `Reducer<S, M, C>` — the exact role `asRng` plays for `Rng` in\n// `retry-backoff`. The parameter type is `Reducer<S, M, C>`, whose every cell\n// returns the non-thenable `SyncReturn<S, C>`, so the reentrancy guard fires\n// HERE, at construction: an `async` cell (or one that inline-`await`s) returns\n// `Promise<...>`, which is not assignable to `SyncReturn`, and `tsc` rejects the\n// call at the offending cell. A pure synchronous reducer passes through\n// untouched and gains the phantom `ReducerBrand`.\n//\n// PURE: identity at runtime (the brand is phantom). `defineMachine` brands its\n// `update` internally the same way, so callers that pass an object literal\n// straight to `defineMachine` never need to call `asReducer` — it exists for\n// the standalone `const update = asReducer<...>({ ... })` form, mirroring how a\n// caller can mint an `Rng` with `asRng` before wiring it.\nexport function asReducer<S, M extends { type: string }, C extends Cmd>(\n reducer: Reducer<S, M, C>,\n): Branded<Reducer<S, M, C>> {\n return reducer as Branded<Reducer<S, M, C>>;\n}\n\n// === run: implemented in task 2 ===\n//\n// Returns a `Runtime<S, M>` synchronously. Boot (`store?.load()` + `init`) runs\n// asynchronously as the FIRST entry on the serial dispatch tail; every public\n// runtime method (`dispatch`, `stop`, `getState`) awaits the boot phase\n// implicitly through the queue. Failures inside `store.load` propagate via the\n// boot promise — subsequent calls reject/throw with that error. There is no\n// \"synchronous load\" branch because `Store#load` is async by contract.\n//\n// Save-then-effects ordering is structural: every transition mutates state,\n// awaits `store.save(newState)`, then reconciles subscriptions, then runs\n// `interpret` for emitted cmds, then fires external listeners. A throw in any\n// effect phase leaves the persisted state ahead of the host's belief about\n// what executed — the Railway discipline (`tryInterpret` in handlers) makes\n// that safe in practice.\n\n// === CtxArg<Ctx>: the `ctx` field of `run`'s opts, conditionally optional ===\n//\n// A PURE machine reads nothing from `ctx` — its `Ctx` is `NoCtx`\n// (`Record<never, never>`), `Record<string, never>` (the vortex arena grain,\n// #182), or `unknown`. Forcing such a machine to write `ctx: {}` is ceremony\n// for a value the type already pins as empty — the same friction the\n// `Machine.interpret` field removed for cmdless machines. So `ctx` is\n// CONDITIONALLY optional: when the empty object satisfies `Ctx` it may be\n// OMITTED (the runtime defaults it to `{}`), so a pure reducer runs as\n// `run(machine)`; when `Ctx` carries a field a handler reads, `ctx` stays\n// REQUIRED so a context-bearing machine can't silently forget it.\n//\n// `[Record<never, never>] extends [Ctx]` reads as \"is `{}` assignable to\n// `Ctx`\" — true for the context-free shapes above, false for `{ db: … }`. The\n// tuple-wrap disables distributive conditional behavior, the same trick the\n// `Machine.interpret`/`update` fields use. Existing callers that pass `ctx`\n// are unaffected — an optional field still accepts a present value.\nexport type CtxArg<Ctx> = [Record<never, never>] extends [Ctx]\n ? { ctx?: Ctx }\n : { ctx: Ctx };\n\nexport function run<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n E extends { type: string } = never,\n>(\n machine: Machine<S, M, C, U, Ctx>,\n opts: CtxArg<Ctx> & {\n store?: Store<S>;\n onError?: OnError;\n /**\n * The SEMANTIC event projector (#47). Maps one APPLIED transition `(msg,\n * state)` to zero-or-more public events of the machine-level union `E`.\n * Returning `[]` skips the transition (it produced no event the consumer's\n * `on(type, …)` cares about). This is where a machine maps its PRIVATE Msg\n * vocabulary (a retry plumbing's `resilient_ok`, a tool loop's\n * `agent_tool_ok`) to NAMED events — the private names live only inside this\n * closure and never reach `on`'s `E` surface. Omit → the run has no event\n * surface (`E = never`) and `on` is uncallable.\n *\n * PURE — called inside the dispatch loop on the freshly-folded `(msg,\n * state)`; it must not read the clock, mutate, or throw (a throw is\n * isolated like an observer throw, never stranding the transition).\n */\n events?: (msg: M, state: S) => readonly E[];\n /**\n * Declared policy for when the pure `update` (reducer) throws. The reducer\n * throw is always surfaced via `onError` (`phase: \"reduce\"`); the strategy\n * decides what the runtime does next. Defaults to `\"stop\"` — the explicit,\n * safe choice (surface + halt, never a silent resume). See `Supervision`.\n */\n supervision?: Supervision<S, M>;\n /**\n * The run-terminality predicate — what makes the run's outcome first-class\n * (issue #46). Returns `true` for a State the run has finished in (e.g. an\n * agent's `state.run.phase === \"done\"`). The runtime feeds it to\n * `Runtime.result()` (the terminal State, or `undefined` in flight) and\n * `Runtime.done()` (resolves with the terminal State when it first holds).\n *\n * PURE — the runtime calls it inside the dispatch loop on the freshly-folded\n * State; it must not read the clock, mutate, or throw. Omit → the run is\n * never terminal: `result()` always returns `undefined` and `done()` never\n * resolves (the right behavior for a machine with no natural completion).\n */\n terminal?: (state: S) => boolean;\n /**\n * Iteration cap for `idle()`'s quiescence wait. Defaults to 100_000. Test\n * seam only — lets a livelock test trip the `QuiescenceTimeoutError` reject\n * path in a handful of iterations instead of 100k. Production code must not\n * set it.\n *\n * @internal test-only\n */\n __idleCap?: number;\n },\n): BootingRuntime<S, M, E> {\n const { store } = opts;\n // `ctx` is conditionally optional (see `CtxArg`): a pure machine omits it.\n // Default the absent/nullish case to an empty object so the augmented-ctx\n // spread and `init(loaded, ctx)` get a value, never `undefined`. Callers that\n // pass a real `ctx` (or `ctx: undefined` for a `Ctx = undefined` machine that\n // ignores it) are unchanged.\n const ctx = (opts.ctx ?? {}) as Ctx;\n const idleCap = opts.__idleCap ?? 100_000;\n // The semantic-event projector (#47). Defaults to \"no events\" — a machine\n // that wires none has an empty event surface (`E = never`), so `on` is\n // uncallable and this projector never runs.\n const projectEvents: (msg: M, state: S) => readonly E[] =\n opts.events ?? (() => []);\n // The run-terminality predicate (#46). Defaults to \"never terminal\" so a\n // machine with no natural completion has a sound `result()`/`done()` (always\n // undefined / never resolves) rather than a missing one.\n const isTerminal: (state: S) => boolean = opts.terminal ?? (() => false);\n // The error sink for paths with no caller to reject at (follow-up dispatch\n // rejections, the final stop-save). Optional on `run`; when absent we fall\n // back to `defaultOnError`, which re-throws on a macrotask so the failure\n // still surfaces. Invariant 6: no silent failures.\n const onError: OnError = opts.onError ?? defaultOnError;\n // The sink must itself be total. If a consumer's sink throws, route THAT\n // throw through `defaultOnError` so a buggy sink can't re-create a silent\n // failure (or strand a teardown loop).\n const reportError = (error: unknown, context: RuntimeErrorContext): void => {\n try {\n onError(error, context);\n } catch (sinkError) {\n defaultOnError(sinkError, context);\n }\n };\n // The declared policy for a reducer throw (ADR 0003 #4). Default `stop`:\n // surface via `onError` + halt, never a silent resume. Normalized once here\n // so `stepDispatch` branches on `.strategy` without re-parsing the shorthand.\n const supervision = normalizeSupervision<S, M>(opts.supervision);\n\n // Holders are intentionally late-initialized: `state` is set inside the boot\n // step, which runs as the head of the tail. `getState()` before boot throws.\n let state: S | undefined;\n let bootError: unknown = null;\n let stopped = false;\n\n const subRegistry = new Map<string, () => void>();\n const listeners = new Set<() => void>();\n // Observers receive (msg, state) for every completed, APPLIED transition. The\n // boot transition has no applied Msg — it is delivered via `onBoot`, not here\n // — so `msg` is total (`M`, never `null`) (#47). Same throw-isolation\n // contract as listeners.\n const observers = new Set<(msg: M, state: S) => void>();\n // `onBoot` handlers receive the initial State once (#47). The boot case the\n // old `observe(msg === null)` arm carried lives here now. `booted` flips on\n // the boot fanout so a handler registered AFTER boot fires immediately with\n // the captured initial State (never misses it).\n const bootHandlers = new Set<(state: S) => void>();\n let booted = false;\n // Semantic-event handlers, keyed by event `type` (#47). Each `on(type, fn)`\n // adds `fn` to its type's bucket; the dispatch loop projects each transition\n // to `E[]` via `projectEvents` and fans each event to its type's handlers.\n // Stored as `(event: { type: string }) => void` to keep the registry\n // monomorphic; per-type safety lives at the `on` call site (the handler's `K`\n // narrows the event via `Extract<E, { type: K }>`).\n const eventHandlers = new Map<string, Set<(event: E) => void>>();\n // `done()` waiters (#46): each open `done()` call parks its resolver here.\n // The first transition that makes `isTerminal(state)` hold drains the set,\n // resolving every parked promise with the terminal State. A `done()` call\n // made AFTER the run is already terminal resolves immediately and never\n // parks (so it can never miss the terminal transition).\n const doneWaiters = new Set<(state: S) => void>();\n\n // Port subscriber registry. Keyed by Port reference (NOT name) — port\n // identity is nominal/by-reference per Elm semantics. Each port can have\n // many listeners; emissions fan out synchronously to all of them.\n // `Set<(value: unknown) => void>` is the storage shape; per-port type\n // safety is enforced at the `subscribePort` / `emit` call sites via the\n // phantom `__t` field on `Port<T>`.\n const portRegistry = new Map<Port<unknown>, Set<(value: unknown) => void>>();\n\n // The `emit` function injected onto ctx. Synchronous fanout — same shape as\n // `observe`. No-op when the port has no subscribers. Listener throws are\n // isolated + logged so one bad subscriber does not strand the others.\n function portEmit<T>(port: Port<T>, value: T): void {\n const subscribers = portRegistry.get(port as Port<unknown>);\n if (!subscribers || subscribers.size === 0) return;\n for (const listener of subscribers) {\n try {\n listener(value);\n } catch (err) {\n console.error(err);\n }\n }\n }\n\n // Augmented ctx passed to every Cmd handler. `ctx` is intentionally spread\n // into a fresh object so handlers receive a Ctx & PortEmitter without\n // mutating the caller's ctx (which may be shared across runtimes / tests).\n const augmentedCtx: Ctx & PortEmitter = { ...ctx, emit: portEmit };\n\n // === update dispatch ===\n //\n // The substrate accepts two `update` shapes (see `defineMachine` overloads);\n // dispatch goes through `applyCell`, the single reducer-vs-transitions\n // primitive keyed on `formOf` (see `pure/core.ts`, #275).\n function applyUpdate(state: S, msg: M): readonly [S, readonly C[]] {\n if (__DEV__) deepFreeze(state);\n const result = applyCell<S, M, C>(machine, state, msg);\n if (__DEV__) assertPureResult(result, msg.type);\n return result;\n }\n\n // The serial dispatch queue: every step is chained onto `tail`. New dispatch\n // calls (and re-entrant ones from interpret follow-ups) wait for the\n // previous step to fully resolve before running their reducer. This is the\n // single concurrency gate.\n let tail: Promise<void> = Promise.resolve();\n\n /**\n * Reconcile subscriptions against `state`. Called after every save.\n *\n * - Same id present in old + new → leave running.\n * - Removed id → call cleanup. Swallow cleanup throws + `console.error`.\n * - New id → call subscribe[type]; on success store cleanup. On throw, the\n * sub is NOT registered; throw is remembered and re-thrown after the loop\n * so all other new subs still register.\n */\n function reconcileSubs(): void {\n if (!machine.subscriptions) return;\n const desired = machine.subscriptions(state as S);\n const desiredIds = new Set<string>();\n\n // Collision assert: within a single desired set, two subs sharing an id\n // but declaring different types is the silent class of bug that Elm's\n // sub diffing relies on the user to avoid — we catch it explicitly here.\n // (Same id + same type within the desired set is a redundant declaration\n // — harmless, and the `subRegistry.has` check below dedupes it on the\n // start path. Same id across transitions is the no-churn case the\n // reconcile pass is designed for and MUST NOT throw.)\n const desiredTypeById = new Map<string, string>();\n for (const sub of desired) {\n const existing = desiredTypeById.get(sub.id);\n if (existing !== undefined && existing !== sub.type) {\n throw new Error(\n `@demlik/tea: Sub.id collision: id=\"${sub.id}\" declared as type=\"${existing}\" and type=\"${sub.type}\"`,\n );\n }\n desiredTypeById.set(sub.id, sub.type);\n }\n\n // Removals first — anything in the registry not in `desired` should stop.\n for (const sub of desired) desiredIds.add(sub.id);\n for (const [id, cleanup] of subRegistry) {\n if (!desiredIds.has(id)) {\n try {\n cleanup();\n } catch (err) {\n console.error(err);\n }\n subRegistry.delete(id);\n }\n }\n\n // Additions — anything in `desired` not in the registry should start.\n let firstStartError: unknown = null;\n for (const sub of desired) {\n if (subRegistry.has(sub.id)) continue;\n const handler = machine.subscribe?.[sub.type as U[\"type\"]];\n if (!handler) {\n // No handler for this sub type — programmer error; skip. (TS would\n // normally forbid this at compile time when `subscribe` is provided\n // and U has variants, but a runtime guard is cheap.)\n continue;\n }\n try {\n const cleanup = handler(\n sub as Extract<U, { type: U[\"type\"] }>,\n ctx,\n enqueueDispatch,\n );\n subRegistry.set(sub.id, cleanup);\n } catch (err) {\n if (firstStartError === null) firstStartError = err;\n // Do NOT register; continue to next sub so other starts still run.\n }\n }\n if (firstStartError !== null) throw firstStartError;\n }\n\n // `interpret` is optional at the type level when `C extends Cmd<never>`\n // (see `Machine<...>`). The runtime safely defaults a missing map to `{}`\n // because such a machine never emits cmds — the cmd loop below never\n // dereferences a handler. The defensive default also guards against a\n // miswired non-Cmd<never> consumer reaching this code path; the per-cmd\n // `if (!handler) continue` then preserves invariant-6 forward progress\n // instead of throwing on `undefined.foo`.\n type InterpretMap = {\n [K in C[\"type\"]]: (\n cmd: Extract<C, { type: K }>,\n ctx: Ctx & PortEmitter,\n // biome-ignore lint/suspicious/noConfusingVoidType: an interpret handler returns a follow-up Msg or nothing; `void` permits no-return bodies that `M | undefined` would reject\n ) => Promise<M | void>;\n };\n const interpretMap: InterpretMap =\n (machine as { interpret?: InterpretMap }).interpret ?? ({} as InterpretMap);\n\n /**\n * Run `interpret` for each emitted cmd. Each handler may return a follow-up\n * Msg — that Msg is enqueued onto the tail (NOT dispatched re-entrantly\n * inside the current transition).\n *\n * Throws propagate to the caller of `step`. The first error stops further\n * handlers in this transition.\n */\n async function runInterpret(cmds: readonly C[]): Promise<void> {\n for (const cmd of cmds) {\n const handler = interpretMap[cmd.type as C[\"type\"]];\n if (!handler) continue;\n const follow = await handler(\n cmd as Extract<C, { type: C[\"type\"] }>,\n augmentedCtx,\n );\n if (follow !== undefined && follow !== null) {\n // Schedule follow-up Msg on the tail. The current step resolves\n // first; the follow-up runs after, as a fresh transition. The\n // returned rejection has no caller (the original dispatcher already\n // resolved), so route it to the error sink instead of swallowing it —\n // invariant 6: no silent failures. If you want this failure folded\n // back into state, name a failure Msg via `tryInterpret` (Railway);\n // the sink is the last-resort observability hook for the rest.\n enqueueDispatch(follow as M).catch((error: unknown) => {\n reportError(error, { phase: \"follow-up\" });\n });\n }\n }\n }\n\n /**\n * Fire every external listener. Listener throws are isolated — one bad\n * listener does not strand the others. This is the dual of cleanup\n * semantics: the runtime guarantees forward progress for unrelated\n * observers.\n */\n function fireListeners(): void {\n for (const listener of listeners) {\n try {\n listener();\n } catch (err) {\n console.error(err);\n }\n }\n }\n\n /**\n * Fire every observer with the just-applied msg + post-transition state.\n * Same throw-isolation contract as `fireListeners`. Called immediately\n * after `fireListeners` so observers see exactly what subscribers see. Only\n * called for APPLIED transitions — `msg` is total (the boot case routes to\n * `fireBoot`, not here) (#47).\n */\n function fireObservers(msg: M): void {\n if (observers.size === 0 || state === undefined) return;\n const snapshot = state;\n for (const observer of observers) {\n try {\n observer(msg, snapshot);\n } catch (err) {\n console.error(err);\n }\n }\n }\n\n /**\n * Project the just-applied transition to semantic events and fan each to its\n * type's `on(...)` handlers (#47). The projector maps the machine's private\n * Msg vocabulary to public events; a throw in the projector OR a handler is\n * isolated (errors-are-data) so it never strands the transition. Called right\n * after `fireObservers` so an `on` handler sees the same post-transition State\n * an observer would.\n */\n function fireEvents(msg: M): void {\n if (eventHandlers.size === 0 || state === undefined) return;\n let events: readonly E[];\n try {\n events = projectEvents(msg, state);\n } catch (err) {\n console.error(err);\n return;\n }\n for (const event of events) {\n const bucket = eventHandlers.get(event.type);\n if (bucket === undefined) continue;\n for (const handler of bucket) {\n try {\n handler(event);\n } catch (err) {\n console.error(err);\n }\n }\n }\n }\n\n /**\n * Fire every `onBoot` handler with the initial State, ONCE, and flip `booted`\n * (#47). This carries the case the old `observe(msg === null)` arm did. Same\n * throw-isolation contract. A handler registered after this runs fires\n * immediately at its `onBoot` call site instead (it reads `booted`).\n */\n function fireBoot(): void {\n booted = true;\n if (bootHandlers.size === 0 || state === undefined) return;\n const snapshot = state;\n for (const handler of bootHandlers) {\n try {\n handler(snapshot);\n } catch (err) {\n console.error(err);\n }\n }\n }\n\n /**\n * Resolve every parked `done()` waiter iff the just-folded State is terminal\n * (#46). Called once per completed transition (including boot), right after\n * the observer fanout, so a `done()` promise settles on the SAME transition a\n * synchronous `result()` would first return non-`undefined`. Drains the set\n * before resolving (a resolver enqueued anew during the drain belongs to the\n * next call, not this one — but a terminal State stays terminal, so the new\n * waiter's own `done()` call already resolved it immediately).\n */\n function settleDoneWaiters(): void {\n if (doneWaiters.size === 0 || state === undefined) return;\n if (!isTerminal(state)) return;\n const snapshot = state;\n const parked = [...doneWaiters];\n doneWaiters.clear();\n for (const resolve of parked) resolve(snapshot);\n }\n\n /**\n * One full transition: update → save → reconcile subs → interpret → fire\n * listeners. Save-before-effects is the hard ordering; tests pin it.\n *\n * Throws from `update` propagate immediately (state unchanged). Throws from\n * `save` propagate after the in-memory `state` is advanced (PRD row: \"state\n * advanced; persisted state did not\"). Throws from reconcile or interpret\n * propagate after `save` has succeeded (PRD row: \"state already saved\").\n */\n async function stepDispatch(msg: M): Promise<void> {\n if (state === undefined) {\n // This should never happen — boot always runs before any dispatch.\n throw new Error(\"@demlik/tea: runtime not booted\");\n }\n // The reducer is the only synchronous user code in the step, and #71's\n // brand guarantees it cannot suspend — so a throw here is a clean,\n // catchable synchronous throw with `state` still at its pre-transition\n // value. Route it to the declared supervision strategy (ADR 0003 #4).\n let next: S;\n let cmds: readonly C[];\n try {\n [next, cmds] = applyUpdate(state, msg);\n } catch (reduceError) {\n // Invariant 6 — surface the failure as data FIRST, for every strategy.\n reportError(reduceError, { phase: \"reduce\" });\n switch (supervision.strategy) {\n case \"restart\": {\n // Host supplies last-known-good state; core installs it and KEEPS\n // FOLDING from there. State did not advance to the (never-produced)\n // reducer result — it is replaced by the rehydrated value. The\n // transition continues below with no cmds, since the throwing reduce\n // produced none. A throw inside `rehydrate` itself is NOT caught here\n // — it propagates as a genuine recovery failure (the host's\n // last-good source is broken), surfacing to the dispatch caller.\n state = supervision.rehydrate(state, msg, reduceError);\n if (store) await store.save(state);\n reconcileSubs();\n // No cmds to interpret — the reducer never returned a result.\n fireListeners();\n fireObservers(msg);\n fireEvents(msg);\n settleDoneWaiters();\n return;\n }\n case \"escalate\":\n // Surface + propagate. The runtime stays live (a parent supervisor\n // may keep dispatching); the failure bubbles out the dispatch\n // promise so the caller above sees it.\n throw reduceError;\n default:\n // `stop` (the safe default): halt the runtime. State is NOT advanced;\n // every subsequent dispatch rejects (\"runtime stopped\"). Propagate so\n // THIS dispatch promise also rejects — the halt is observable, never\n // a silent resume.\n stopped = true;\n throw reduceError;\n }\n }\n state = next;\n if (store) await store.save(state);\n // Subscriptions reconcile against the new state; throws propagate AFTER\n // the entire diff pass completes (so other subs still register / clean\n // up correctly). Cleanup throws are swallowed inside reconcileSubs.\n reconcileSubs();\n await runInterpret(cmds);\n fireListeners();\n fireObservers(msg);\n fireEvents(msg);\n settleDoneWaiters();\n }\n\n /**\n * Boot is split into two phases.\n *\n * - **Synchronous (`run()` call):** when `store` is absent, we know `loaded\n * = null` without an await — run `init(null, ctx)` IMMEDIATELY so that\n * `getState()` is observable synchronously. This is what\n * `useSyncExternalStore` consumers (e.g. `@demlik/tea/react`) need to render\n * on the first commit without an undefined-state flicker.\n * - **Asynchronous (`stepBootEffects` on the tail):** save + sub reconcile\n * + interpret-of-init-cmds + listener fire. These run as the first tail\n * entry; subsequent dispatches queue behind them.\n *\n * When `store` IS present we cannot do `init` synchronously (we'd be\n * inventing a loaded value), so we keep the full async path. Components\n * that want synchronous initial state in that case should omit the store\n * for the React mount and persist via a different mechanism (or accept the\n * default-snapshot story in a future v2).\n *\n * `store.load` throws propagate via the boot promise; subsequent calls\n * reject with the load error. (The PRD row \"run() throws synchronously\" is\n * imprecise relative to Store#load being async — we honor the intent: no\n * usable runtime is ever observable on load failure.)\n */\n // Synchronous init when there is NO store: `getState()` is observable\n // synchronously by `useSyncExternalStore` consumers. When a store IS\n // present, `init` must run AFTER `store.load()` (the contract: `init`\n // receives the loaded snapshot), and callers must await boot before\n // calling `getState()` — they do so implicitly via the first `dispatch()`\n // (which queues behind the boot step).\n //\n // The asymmetry is the substrate being honest about a real constraint: a\n // store is, by definition, an async boundary. Components that need\n // synchronous initial state under a store should await the runtime's boot\n // before mounting — `await runtime.ready` (not provided in v1; use `await\n // runtime.dispatch(noopMsg)` if needed, or a parent-level loading state).\n let pendingInitCmds: readonly C[] = [];\n if (!store) {\n const [initialState, initCmds] = machine.init(null, ctx);\n state = initialState;\n pendingInitCmds = initCmds;\n }\n\n async function stepBootEffects(): Promise<void> {\n if (store) {\n // Boundary parse (invariant 8). `store.load()` returns `unknown`\n // because storage doesn't know `S`; `store.migrate(raw)` is the\n // substrate's required parse — `S` on recognized shape, `null` on\n // unrecognized (which boots fresh, a known-good path). `migrate` MUST\n // NOT throw per its contract; if it does we surface the error via the\n // boot promise (same as a `load` throw — `runtime.ready` rejects and\n // every subsequent `dispatch` surfaces `bootError`).\n const raw = await store.load();\n const parsed = store.migrate(raw);\n const [initialState, initCmds] = machine.init(parsed, ctx);\n state = initialState;\n pendingInitCmds = initCmds;\n await store.save(state);\n }\n reconcileSubs();\n await runInterpret(pendingInitCmds);\n fireListeners();\n // The boot transition has no applied Msg — deliver the initial State via\n // `onBoot`, not `observe` (#47). No `fireEvents` either: boot is not an\n // applied event, so it projects no semantic event.\n fireBoot();\n // A rehydrated boot can land in a terminal State (the run finished before\n // the last eviction) — settle any `done()` waiter parked before boot.\n settleDoneWaiters();\n }\n\n /**\n * Enqueue a dispatch on the tail. Re-entrant calls from interpret or\n * subscribe handlers go through this same gate — guaranteeing serial\n * execution across the entire system.\n *\n * `dispatch` rejects when:\n * - the runtime is stopped (next dispatch always rejects after stop);\n * - boot failed (every dispatch surfaces the boot error);\n * - the reducer, save, sub start, or interpret throws.\n */\n function enqueueDispatch(msg: M): Promise<void> {\n if (stopped)\n return Promise.reject(new Error(\"@demlik/tea: runtime stopped\"));\n const next = tail.then(() => {\n if (bootError !== null) throw bootError;\n return stepDispatch(msg);\n });\n // Swallow the rejection on the tail so a single failing dispatch does NOT\n // poison every subsequent one. The original `next` promise still rejects\n // for the dispatch caller.\n tail = next.catch(() => {});\n return next;\n }\n\n /**\n * Drain the serial tail to quiescence. Quiescence = the tail stopped\n * advancing: every interpret follow-up calls `enqueueDispatch`, which\n * reassigns `tail` SYNCHRONOUSLY (before the parent step resolves), so\n * awaiting the current `tail` and re-reading it catches every transitively\n * enqueued follow-up. We loop until the reference is stable across an await.\n *\n * Bounded by `idleCap` — on cap we REJECT with `QuiescenceTimeoutError`\n * (never a silent fall-through-resolve), so a livelocking machine stays\n * distinguishable from a genuinely quiesced one (invariant 6 — issue #51).\n *\n * Shared by `runtime.idle()` and the quiescent `dispatch` default (#50): one\n * drain definition, one cap, one reject contract.\n */\n async function drainToQuiescence(): Promise<void> {\n for (let i = 0; i < idleCap; i++) {\n const observed = tail;\n await observed;\n if (tail === observed) return;\n }\n throw new QuiescenceTimeoutError(idleCap);\n }\n\n /**\n * The public `dispatch`: run-to-quiescence by default (#50). Enqueue the Msg\n * on the tail, await its OWN transition first (so a reducer / save / interpret\n * throw on THIS Msg surfaces here, before any drain), then — unless the caller\n * asked for a single step — drain the transitive follow-up chain.\n *\n * `{ settle: \"once\" }` (and the `dispatchOnce` alias) skip the drain: resolve\n * after the one transition and leave the follow-up chain racing on the tail\n * for a caller that will `await runtime.idle()` itself.\n */\n async function dispatchToQuiescence(\n msg: M,\n opts?: { readonly settle?: DispatchSettle },\n ): Promise<void> {\n await enqueueDispatch(msg);\n if (opts?.settle === \"once\") return;\n await drainToQuiescence();\n }\n\n // Kick off boot-effects immediately. Boot rejections are remembered on\n // `bootError`; they surface on every subsequent dispatch call. Note: when\n // `store` is absent the synchronous-init step above already set `state` —\n // `stepBootEffects` only runs save/sub/interpret/listener-fire. When\n // `store` is present, the full async path runs here.\n //\n // `bootPromise` is the original (un-swallowed) promise — it is what\n // `runtime.ready` chains off so callers see the boot error directly. `tail`\n // gets the swallowed branch so a boot failure does NOT poison every\n // subsequent dispatch's `.then` chain (each dispatch surfaces `bootError`\n // explicitly inside `enqueueDispatch`).\n const bootPromise = stepBootEffects();\n tail = bootPromise.catch((err) => {\n bootError = err;\n });\n\n // `ready` resolves to the booted `Runtime` (issue #45). It chains off the\n // un-swallowed `bootPromise` so boot failures reject it directly — meaning a\n // failed boot never hands out a `Runtime`, which is what keeps `getState()`\n // total. The `runtime` reference resolves at `.then` time (a later\n // microtask), well after the object literal below finishes initializing, so\n // the forward reference is safe. Built once → idempotent: the same settled\n // promise comes back on every `ready` read.\n const readyPromise: Promise<Runtime<S, M, E>> = bootPromise.then(\n () => runtime,\n );\n\n const runtime: Runtime<S, M, E> = {\n dispatch: dispatchToQuiescence,\n dispatchOnce: enqueueDispatch,\n getState(): S {\n // TOTAL (issue #45). A `Runtime` is only obtainable by awaiting `ready`,\n // which resolves AFTER boot has run `init` and set `state` — so by the\n // time any holder of this object can call `getState()`, `state` is\n // defined. No `state === undefined` throw branch: that was the old lie\n // (declared total on the synchronously-returned handle, threw under a\n // store pre-boot). Boot failures never reach here either — `ready`\n // rejects, so no `Runtime` is ever handed out on a failed boot.\n //\n // The cast encodes that invariant. The lone way to reach it with `state`\n // still undefined would be to cast the BootingRuntime to Runtime and call\n // `getState()` before `ready` — which the type system now forbids without\n // an explicit, deliberate cast.\n return state as S;\n },\n subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n observe(observer: (msg: M, state: S) => void): () => void {\n observers.add(observer);\n return () => {\n observers.delete(observer);\n };\n },\n onBoot(handler: (state: S) => void): () => void {\n // Already booted → fire immediately with the captured initial State so a\n // late subscriber never misses the one-shot boot (#47). It does not park\n // (boot is a single past event), so the returned cleanup is a no-op.\n if (booted && state !== undefined) {\n try {\n handler(state);\n } catch (err) {\n console.error(err);\n }\n return () => {};\n }\n bootHandlers.add(handler);\n return () => {\n bootHandlers.delete(handler);\n };\n },\n on<K extends E[\"type\"]>(\n type: K,\n handler: (event: Extract<E, { type: K }>) => void,\n ): () => void {\n // The registry is monomorphic (`Set<(event: E) => void>`); the per-type\n // narrowing lives at THIS call site — `handler` accepts the `K`-narrowed\n // event, and `fireEvents` only ever routes an event to its own type's\n // bucket, so the erased call is sound.\n let bucket = eventHandlers.get(type);\n if (bucket === undefined) {\n bucket = new Set<(event: E) => void>();\n eventHandlers.set(type, bucket);\n }\n const erased = handler as (event: E) => void;\n bucket.add(erased);\n return () => {\n const set = eventHandlers.get(type);\n if (set === undefined) return;\n set.delete(erased);\n if (set.size === 0) eventHandlers.delete(type);\n };\n },\n subscribePort<T>(port: Port<T>, listener: (value: T) => void): () => void {\n const key = port as Port<unknown>;\n let bucket = portRegistry.get(key);\n if (!bucket) {\n bucket = new Set<(value: unknown) => void>();\n portRegistry.set(key, bucket);\n }\n // The bucket stores `(value: unknown) => void` to keep the registry\n // monomorphic; per-port type safety lives at this call site (the\n // listener's `T` is bound to the port's phantom `__t`).\n const erased = listener as (value: unknown) => void;\n bucket.add(erased);\n return () => {\n const set = portRegistry.get(key);\n if (!set) return;\n set.delete(erased);\n if (set.size === 0) portRegistry.delete(key);\n };\n },\n emitPort<T>(port: Port<T>, value: T): void {\n // Same closure as `ctx.emit` inside interpret — synchronous fanout,\n // no-op on no subscribers, listener-throw isolation. Exposing it on\n // the Runtime interface lets `observe`-driven Port emission work\n // without spawning a \"tell the outside world\" Cmd per transition.\n portEmit(port, value);\n },\n // `ready` is assigned just below (it must resolve to `runtime` itself,\n // which can't be referenced inside its own object literal). See the\n // assignment + rationale after this block.\n ready: readyPromise,\n idle(): Promise<void> {\n // Quiescence = the tail stopped advancing (full rationale on\n // `drainToQuiescence`). `idle()` is the direct await of that drain; the\n // quiescent `dispatch` default reuses the SAME helper after its own\n // transition. The cap + `QuiescenceTimeoutError` reject (no silent\n // fall-through-resolve) keeps \"quiesced\" and \"gave up\" distinguishable —\n // invariant 6: no silent failures.\n return drainToQuiescence();\n },\n result(): S | undefined {\n // TOTAL — `state` is defined for any holder of a `Runtime` (see\n // `getState`). The terminal predicate is the ONLY thing that decides\n // \"finished\"; with none supplied `isTerminal` is `() => false`, so a\n // non-terminating machine reads `undefined` forever (#46).\n const current = state as S;\n return isTerminal(current) ? current : undefined;\n },\n done(): Promise<S> {\n // Already terminal → resolve at once with the live State (never parks, so\n // a post-termination call can't miss the terminal transition).\n const current = state as S;\n if (isTerminal(current)) return Promise.resolve(current);\n // Otherwise park a resolver; `settleDoneWaiters` drains it on the\n // transition that first makes `isTerminal` hold. With no predicate this\n // promise never resolves — the documented \"no natural completion\" case.\n return new Promise<S>((resolve) => {\n doneWaiters.add(resolve);\n });\n },\n async stop(): Promise<void> {\n stopped = true;\n // Drain whatever is in flight before tearing down. Any rejections in\n // the tail were already swallowed at enqueue time, so this await\n // always resolves.\n await tail;\n // Run every active sub cleanup. Throws are swallowed + logged so one\n // bad cleanup does not strand the others.\n for (const [id, cleanup] of subRegistry) {\n try {\n cleanup();\n } catch (err) {\n console.error(err);\n }\n subRegistry.delete(id);\n }\n // Flush final state. A save throw here does not reject `stop()` — the\n // contract is \"returns a resolved Promise\" — but it IS the loss of the\n // last write, so route it to the error sink rather than swallowing it\n // with a bare console.error. Invariant 6: no silent failures.\n if (store && state !== undefined && bootError === null) {\n try {\n await store.save(state);\n } catch (error) {\n reportError(error, { phase: \"stop-save\" });\n }\n }\n },\n };\n\n return runtime;\n}\n\n// === historyTracker: composable observability helper ===\n//\n// A bounded ring buffer of recent `(msg, state)` transitions, built on the\n// Runtime's public `observe` API. The substrate itself stays minimal — it\n// has no notion of history, no opt to enable one, no method on the Runtime\n// interface to read one. Anything that wants \"recent transitions\" composes\n// via this helper. The substrate provides the primitive (`observe`); this\n// is the bookkeeping that builds on it.\n//\n// Use cases:\n// - Bridge backlog replay for late subscribers (see `@demlik/tea/extension`).\n// - Debug inspectors showing recent traffic on attach.\n// - Sentry breadcrumb collection.\n// - Property/contract tests that want to assert \"these N transitions\n// happened in this order.\"\n//\n// Discipline:\n// - One-line creation: `const tr = historyTracker(runtime, 100);`\n// - Snapshot at any time: `tr.snapshot()` — shallow copy, oldest first.\n// - Detach when done: `tr.stop()` — unsubscribes the observer; the buffer\n// freezes at its current contents (snapshot() still works, useful for\n// post-hoc inspection in tests).\n//\n// Why not put this on the Runtime interface as `runtime.history()`?\n// Because history is derivable. Putting it on the Runtime privileges one\n// use case (debug inspectors) at the substrate level and grows the\n// interface for everyone. The composition shape stays out of the dispatch\n// loop entirely — the substrate's hot path doesn't pay any cost for a\n// feature it doesn't need to provide.\n// =============================================================================\n\nexport interface HistoryTracker<S, M extends { type: string }> {\n /**\n * Snapshot of recorded transitions, oldest first. Each entry is\n * `{ msg, state }` exactly as the underlying `observe` callback received\n * it — `msg` is `null` for the boot transition, a Msg for every other.\n *\n * Returns a shallow copy: the array is fresh on every call (callers may\n * iterate, slice, or replay without affecting the tracker's buffer).\n * Entry values are references to the originals (TEA states/msgs are\n * conventionally immutable; do not mutate them if your S/M is not).\n */\n snapshot(): readonly { readonly msg: M | null; readonly state: S }[];\n /**\n * Detach the underlying observer. After `stop()`:\n * - No new transitions are recorded.\n * - `snapshot()` continues to work and returns the buffer's contents\n * at the moment of stop (useful for post-hoc inspection in tests).\n * - The tracker holds no references that would prevent GC of the\n * `runtime` argument other than the entries already buffered.\n *\n * Idempotent — subsequent calls are no-ops.\n */\n stop(): void;\n}\n\n/**\n * Create a bounded history tracker over a Runtime. The tracker subscribes\n * to the runtime via `observe(...)` and retains the last `size` `(msg,\n * state)` transitions in a FIFO ring buffer.\n *\n * @param runtime Any `BootingRuntime<S, M>` (a full `Runtime` satisfies it).\n * The tracker uses only `observe`, which is total before boot —\n * attach it to the synchronous `run()` handle to record the\n * boot transition.\n * @param size Buffer cap. `size <= 0` produces an inert no-op tracker:\n * no observer is attached to the runtime, `snapshot()` is\n * always `[]`, and `stop()` is a no-op. (Prefer skipping the\n * tracker entirely in that case — this arm just makes a\n * non-positive `size` harmless rather than an error.)\n *\n * Memory cost: O(size × avg(msg + state size)). For audit-extension's\n * inspector use case (size 100, audit state ~5KB), ~500KB max — held\n * in-memory only, no persistence.\n */\nexport function historyTracker<S, M extends { type: string }>(\n runtime: BootingRuntime<S, M>,\n size: number,\n): HistoryTracker<S, M> {\n const buffer: { msg: M | null; state: S }[] = [];\n let stopped = false;\n\n const push = (entry: { msg: M | null; state: S }): void => {\n buffer.push(entry);\n if (buffer.length > size) buffer.shift();\n };\n\n // The boot transition (the `{ msg: null, state }` head entry the old\n // `observe(msg === null)` arm recorded) now arrives via `onBoot` (#47);\n // applied transitions arrive via `observe` with a total `msg`. The public\n // snapshot shape (`msg: M | null`) is unchanged — boot is still `msg: null`.\n const unobserve =\n size <= 0\n ? (): void => {}\n : runtime.observe((msg, state) => {\n push({ msg, state });\n });\n const unboot =\n size <= 0\n ? (): void => {}\n : runtime.onBoot((state) => {\n push({ msg: null, state });\n });\n\n return {\n snapshot() {\n // Shallow copy — callers may freely iterate or mutate the returned\n // array. Entry values are references; see HistoryTracker docs.\n return buffer.slice();\n },\n stop() {\n if (stopped) return;\n stopped = true;\n unobserve();\n unboot();\n },\n };\n}\n\n// === replay: pure unit-test helper ===\n//\n// Composes `init(loaded ?? null, ctx)` then `update(state, msg)` for each msg.\n// Returns the final state plus the cmds that *would* have been emitted and the\n// subs that *would* have been desired at the final state.\n//\n// Crucially:\n// - does NOT call any `interpret[type]` handler\n// - does NOT touch `Store`\n// - does NOT start any subscription via `machine.subscribe?.[type]`\n//\n// `subscriptions` (the description function) IS called to derive the returned\n// `subs` array. That's intentional — it lets tests assert what would be wired\n// up without actually wiring it.\nexport function replay<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n>(\n machine: Machine<S, M, C, U, Ctx>,\n opts: { msgs: readonly M[]; ctx: Ctx; loaded?: S | null },\n): { state: S; cmds: C[]; subs: U[] } {\n // `init` is `(loaded: S | null, ctx) => ...`; coerce undefined → null so the\n // AC \"`replay` with `loaded: undefined` calls `init(null, ctx)`\" holds.\n const loaded = opts.loaded ?? null;\n const [initialState, initCmds] = machine.init(loaded, opts.ctx);\n\n if (loaded !== null && initCmds.length > 0) {\n throw new Error(\n \"TEA contract violation: machine.init must return [state, []] (no Cmds) \" +\n \"when `loaded` is non-null. Init's rehydrate branch is a pure state \" +\n \"passthrough — the migration/parse boundary, not the boot-effect hook.\\n\\n\" +\n \"Routes for boot effects:\\n\" +\n \" - Stateless infrastructure (e.g. chrome.alarms ensure) → host module \" +\n \"top level, outside TEA.\\n\" +\n \" - State-conditional resume (e.g. re-attach a session) → a `boot` Msg \" +\n \"dispatched once from the host after `run(...)` returns, handled in update.\\n\\n\" +\n \"See .patterns/tea/tea-invariants.md (Invariant 2).\",\n );\n }\n\n // `replay` and `foldMsgs` share ONE internal fold (`foldUpdates`), keyed on\n // `formOf` — the same reader `run` uses — so all three agree on the\n // reducer-vs-transitions form by construction. `replay` wraps it with the\n // `init` entry + Cmd/Sub collection; `foldMsgs` calls it from a base state\n // and returns the state only.\n const { state, cmds: foldedCmds } = foldUpdates<S, M, C>(\n machine,\n initialState,\n opts.msgs,\n );\n const cmds: C[] = [...initCmds, ...foldedCmds];\n\n const subs: U[] = machine.subscriptions\n ? [...machine.subscriptions(state)]\n : [];\n\n return { state, cmds, subs };\n}\n\n// === tryInterpret: Railway sugar over `Result.tryPromise` ===\n//\n// Wraps a fallible `(cmd, ctx) => Promise<Ok>` and returns a handler suitable\n// for `interpret[type]`. On success the returned function resolves with\n// `onOk(value, cmd)`; on rejection it resolves with `onErr(error, cmd)`. It\n// NEVER rejects (assuming `onOk`/`onErr` are total — that's the caller's\n// contract).\n//\n// Implementation note: we use the `{try, catch: (e) => e}` form of\n// `Result.tryPromise` rather than the one-arg `(thunk)` form so the original\n// error passes through untouched. The one-arg form wraps errors in\n// `UnhandledException`, which would prevent callers from `instanceof`-checking\n// their own error types inside `onErr`.\n//\n// M is a Msg type (not a Cmd) — the helper routes Ok/Err to two Msg constructors.\nexport function tryInterpret<C extends Cmd, Ok, M, Ctx>(\n work: (cmd: C, ctx: Ctx) => Promise<Ok>,\n onOk: (value: Ok, cmd: C) => M,\n onErr: (error: unknown, cmd: C) => M,\n): (cmd: C, ctx: Ctx) => Promise<M> {\n return async (cmd, ctx) => {\n const result = await Result.tryPromise({\n try: () => work(cmd, ctx),\n catch: (error: unknown): unknown => error,\n });\n return result.match({\n ok: (value) => onOk(value, cmd),\n err: (error) => onErr(error, cmd),\n });\n };\n}\n"]}
@@ -82,6 +82,78 @@ function fromPort(selectRuntime, port, msgFn) {
82
82
  };
83
83
  }
84
84
 
85
+ // src/subs/from-reconnecting-web-socket.ts
86
+ var defaultConnect = (url) => new WebSocket(url);
87
+ var defaultSchedule = (fn, ms) => {
88
+ const handle = setTimeout(fn, ms);
89
+ return () => clearTimeout(handle);
90
+ };
91
+ function fromReconnectingWebSocket(opts) {
92
+ const backoffBaseMs = opts.backoffBaseMs ?? 250;
93
+ const backoffMaxMs = opts.backoffMaxMs ?? 5e3;
94
+ const connect = opts.connect ?? defaultConnect;
95
+ const schedule = opts.schedule ?? defaultSchedule;
96
+ const { onMessage, onOpen, onError, onClose, onReconnect } = opts;
97
+ return (sub, _ctx, dispatch) => {
98
+ let ws = null;
99
+ let attempt = 0;
100
+ let opened = false;
101
+ let closedByCaller = false;
102
+ let cancelReconnect = null;
103
+ const emit = (msg) => {
104
+ if (msg !== null) dispatch(msg);
105
+ };
106
+ const handleClose = (code, reason) => {
107
+ ws = null;
108
+ if (onClose) emit(onClose(code, reason, sub));
109
+ if (closedByCaller) return;
110
+ const delay = Math.min(backoffBaseMs * 2 ** attempt, backoffMaxMs);
111
+ attempt += 1;
112
+ cancelReconnect = schedule(() => {
113
+ cancelReconnect = null;
114
+ if (!closedByCaller) open();
115
+ }, delay);
116
+ };
117
+ function open() {
118
+ const socket = connect(sub.wsUrl);
119
+ ws = socket;
120
+ socket.onopen = () => {
121
+ const reconnected = opened;
122
+ const reconnectCount = attempt;
123
+ attempt = 0;
124
+ opened = true;
125
+ if (onOpen) emit(onOpen(sub));
126
+ if (reconnected && onReconnect) emit(onReconnect(reconnectCount, sub));
127
+ };
128
+ socket.onmessage = (event) => {
129
+ emit(onMessage(event.data, sub));
130
+ };
131
+ socket.onerror = onError ? (event) => emit(onError(event, sub)) : () => {
132
+ };
133
+ socket.onclose = (event) => {
134
+ handleClose(event.code, event.reason);
135
+ };
136
+ }
137
+ open();
138
+ return () => {
139
+ closedByCaller = true;
140
+ if (cancelReconnect !== null) {
141
+ cancelReconnect();
142
+ cancelReconnect = null;
143
+ }
144
+ const socket = ws;
145
+ ws = null;
146
+ if (socket !== null) {
147
+ socket.onopen = null;
148
+ socket.onmessage = null;
149
+ socket.onerror = null;
150
+ socket.onclose = null;
151
+ socket.close(1e3);
152
+ }
153
+ };
154
+ };
155
+ }
156
+
85
157
  // src/subs/from-web-socket.ts
86
158
  function fromWebSocket(opts) {
87
159
  return (sub, _ctx, dispatch) => {
@@ -121,6 +193,6 @@ function fromWebSocket(opts) {
121
193
  };
122
194
  }
123
195
 
124
- export { fromBroadcastChannel, fromEventSource, fromEventTarget, fromInterval, fromPort, fromWebSocket };
125
- //# sourceMappingURL=chunk-Y5JM3UUH.js.map
126
- //# sourceMappingURL=chunk-Y5JM3UUH.js.map
196
+ export { fromBroadcastChannel, fromEventSource, fromEventTarget, fromInterval, fromPort, fromReconnectingWebSocket, fromWebSocket };
197
+ //# sourceMappingURL=chunk-NSDFA6M6.js.map
198
+ //# sourceMappingURL=chunk-NSDFA6M6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/subs/from-broadcast-channel.ts","../src/subs/from-event-source.ts","../src/subs/from-event-target.ts","../src/subs/from-interval.ts","../src/subs/from-port.ts","../src/subs/from-reconnecting-web-socket.ts","../src/subs/from-web-socket.ts"],"names":[],"mappings":"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","file":"chunk-NSDFA6M6.js","sourcesContent":["// ---------------------------------------------------------------------------\n// fromBroadcastChannel — universal `BroadcastChannel`-shaped Sub factory.\n//\n// `BroadcastChannel` is a same-origin pub/sub primitive available in\n// every modern browser context (window, worker, service worker) AND in\n// Cloudflare Workers (with origin scoped to the worker isolate). The\n// constructor opens the channel; the `message` event fires whenever\n// another participant on the same channel name posts a message; the\n// `close()` method releases the OS resource.\n//\n// The factory carries `channelName` on the Sub itself (not in the\n// closure) so the same factory instance handles every BroadcastChannel\n// Sub in a machine — one Sub per channel, named by id, sharing the\n// factory's lifecycle code. Renaming a channel requires a new Sub.id\n// (the reconcile pass otherwise leaves the existing channel open).\n//\n// `msgFn` returns `M | null` — same drop-on-null pattern as\n// `fromEventTarget`. The MessageEvent's `data` is `unknown` from the\n// platform's perspective; the caller decides whether the payload is a\n// recognizable shape, and returns `null` to drop unknown messages\n// without polluting the reducer with parse-discard cells.\n//\n// Cleanup calls `channel.close()`, which removes the listener AND\n// releases the channel reference — `removeEventListener` alone would\n// leak the BroadcastChannel handle. The pair is intentional.\n// ---------------------------------------------------------------------------\n\nimport type { Sub } from \"../index\";\nimport type {\n MinimalBroadcastChannelCtor,\n MinimalMessageEvent,\n} from \"./platform\";\nimport type { SubscribeHandler } from \"./types\";\n\ntype BroadcastSubData = { channelName: string };\n\ndeclare const BroadcastChannel: MinimalBroadcastChannelCtor;\n\nexport function fromBroadcastChannel<S extends Sub & BroadcastSubData, M>(\n msgFn: (event: MinimalMessageEvent, sub: S) => M | null,\n): SubscribeHandler<S, M, unknown> {\n return (sub, _ctx, dispatch) => {\n const channel = new BroadcastChannel(sub.channelName);\n const listener = (event: MinimalMessageEvent): void => {\n const msg = msgFn(event, sub);\n if (msg !== null) dispatch(msg);\n };\n channel.addEventListener(\"message\", listener);\n return () => {\n channel.removeEventListener(\"message\", listener);\n channel.close();\n };\n };\n}\n","// ---------------------------------------------------------------------------\n// fromEventSource — universal `EventSource` (server-sent events) Sub\n// factory.\n//\n// SSE is the asymmetric streaming protocol used by the agent log /\n// audit log pipelines: HTTP-shaped open, server pushes events forever,\n// client receives until close. `EventSource` is the standard browser\n// API; the constructor opens the connection, `message` fires per\n// server-pushed event, `error` fires on disconnect or non-2xx, `open`\n// fires once on initial handshake, `close()` tears the connection\n// down.\n//\n// Three callbacks because three observable events ARE three concerns\n// the caller routinely cares about:\n//\n// - `onMessage(data, sub)` — required. The SSE payload's `data` field\n// is `string` from the platform; the caller decides parse + Msg\n// shape. Returns `M | null`; null drops the dispatch.\n//\n// - `onError(event, sub)` — optional. SSE's `error` event fires both\n// on transient network drops (the browser auto-reconnects) AND on\n// permanent failures. Most consumers want to surface ONE of these\n// as a Msg (e.g. \"stream-disconnected\") without folding both into\n// `onMessage`'s discriminant. Omitting the callback drops error\n// events silently.\n//\n// - `onOpen(sub)` — optional. The connection's initial handshake\n// succeeded. Useful for \"show 'connected' indicator\" Msgs. Omitting\n// drops open events silently. NOT fired on auto-reconnect by every\n// browser implementation — treat the event as best-effort.\n//\n// `url` lives on the Sub itself (`EventSourceSubData`). Same id +\n// different url = the substrate's reconcile pass leaves the existing\n// connection alone (the URL change is silent). Changing the URL\n// requires a new Sub.id.\n//\n// Cleanup is `close()` + `removeEventListener` for all three —\n// belt-and-suspenders against EventSource implementations that\n// dispatch events into already-closed sources.\n// ---------------------------------------------------------------------------\n\nimport type { Sub } from \"../index\";\nimport type {\n MinimalEvent,\n MinimalEventSourceCtor,\n MinimalMessageEvent,\n} from \"./platform\";\nimport type { SubscribeHandler } from \"./types\";\n\ntype EventSourceSubData = { url: string };\n\ndeclare const EventSource: MinimalEventSourceCtor;\n\nexport interface EventSourceFactoryOpts<S, M> {\n onMessage: (data: string, sub: S) => M | null;\n onError?: (event: MinimalEvent, sub: S) => M | null;\n onOpen?: (sub: S) => M | null;\n}\n\nexport function fromEventSource<S extends Sub & EventSourceSubData, M>(\n opts: EventSourceFactoryOpts<S, M>,\n): SubscribeHandler<S, M, unknown> {\n return (sub, _ctx, dispatch) => {\n const source = new EventSource(sub.url);\n\n const messageListener = (event: MinimalMessageEvent): void => {\n // The SSE `data` payload is a string per the platform contract.\n // Cast at the boundary: callers express `(data: string) => M | null`\n // and never see `unknown` flowing in from the platform global.\n const msg = opts.onMessage(event.data as string, sub);\n if (msg !== null) dispatch(msg);\n };\n source.addEventListener(\"message\", messageListener);\n\n const onError = opts.onError;\n const errorListener = onError\n ? (event: MinimalEvent): void => {\n const msg = onError(event, sub);\n if (msg !== null) dispatch(msg);\n }\n : undefined;\n if (errorListener) source.addEventListener(\"error\", errorListener);\n\n const onOpen = opts.onOpen;\n const openListener = onOpen\n ? (): void => {\n const msg = onOpen(sub);\n if (msg !== null) dispatch(msg);\n }\n : undefined;\n if (openListener) source.addEventListener(\"open\", openListener);\n\n return () => {\n source.removeEventListener(\"message\", messageListener);\n if (errorListener) source.removeEventListener(\"error\", errorListener);\n if (openListener) source.removeEventListener(\"open\", openListener);\n source.close();\n };\n };\n}\n","// ---------------------------------------------------------------------------\n// fromEventTarget — universal addEventListener/removeEventListener Sub\n// factory over any `EventTarget` (DOM nodes, `window`, `document`,\n// `BroadcastChannel`, `MessagePort`, `Worker`, `ServiceWorker`, etc.).\n//\n// Two non-obvious shape choices:\n//\n// - `getTarget: () => EventTarget` is a thunk, not a direct value. The\n// factory MUST work in environments where the target is not available\n// at module-load time — service workers run before any `document`\n// exists; some targets are constructed lazily from `ctx`. Deferring\n// the lookup to subscribe time also means a state-driven swap of the\n// target requires only a new Sub.id; the factory pulls the current\n// target on subscribe.\n//\n// - `msgFn` may return `null` — that emission is *dropped*. The event\n// fired, the factory called `msgFn`, but the caller decided \"this\n// event is not interesting given current state.\" No dispatch is made;\n// the listener stays armed for the next event. This is the explicit\n// filter point at the Sub boundary — the alternative (filtering inside\n// the reducer via a noop cell) costs a transition + reconcile pass per\n// filtered event.\n//\n// Cleanup uses the SAME `getTarget()` instance captured at subscribe time\n// so a target swap mid-Sub doesn't leak the listener on the old target.\n// We close over the resolved target rather than calling `getTarget()`\n// again at cleanup — the alternative (re-resolving) is the cause of\n// silent listener leaks in long-lived runtimes.\n// ---------------------------------------------------------------------------\n\nimport type { Sub } from \"../index\";\nimport type { MinimalEvent, MinimalEventTarget } from \"./platform\";\nimport type { SubscribeHandler } from \"./types\";\n\nexport function fromEventTarget<S extends Sub, M>(\n getTarget: () => MinimalEventTarget,\n eventName: string,\n msgFn: (event: MinimalEvent, sub: S) => M | null,\n): SubscribeHandler<S, M, unknown> {\n return (sub, _ctx, dispatch) => {\n const target = getTarget();\n const listener = (event: MinimalEvent): void => {\n const msg = msgFn(event, sub);\n if (msg !== null) dispatch(msg);\n };\n target.addEventListener(eventName, listener);\n return () => {\n target.removeEventListener(eventName, listener);\n };\n };\n}\n","// ---------------------------------------------------------------------------\n// fromInterval — universal `setInterval`-shaped Sub factory.\n//\n// The recurring shape at every `subscribe[type]` cell that wraps a periodic\n// timer is the same five lines: `setInterval` the dispatch, return a\n// `clearInterval` cleanup. The factory absorbs both halves of the lifecycle\n// (subscribe + cleanup); the caller keeps the intent — which Sub variant,\n// which Msg to dispatch.\n//\n// Timing data (`intervalMs`) lives on the Sub itself, not in the closure.\n// The substrate already reconciles Subs by id on every transition; carrying\n// the period on the Sub means a `subscriptions(state)` function that\n// returns `{ id, type, intervalMs: 30_000 }` in one state and the same id\n// with `intervalMs: 60_000` later... will NOT re-wire the interval (the id\n// is unchanged, the reconcile pass leaves it running). That's a tradeoff\n// the substrate's reconcile contract pins, not this factory — if you want\n// the interval to change, change the Sub's id too.\n//\n// Strengthens invariant 9 (named, small surface) and invariant 2 (the Sub\n// carries the data; the lifecycle is in the factory; the reducer never\n// sees the timer).\n// ---------------------------------------------------------------------------\n\nimport type { Sub } from \"../index\";\nimport type { SubscribeHandler } from \"./types\";\n\ntype IntervalSubData = { intervalMs: number };\n\nexport function fromInterval<S extends Sub & IntervalSubData, M>(\n msgFn: (sub: S) => M,\n): SubscribeHandler<S, M, unknown> {\n return (sub, _ctx, dispatch) => {\n const handle = setInterval(() => {\n dispatch(msgFn(sub));\n }, sub.intervalMs);\n return () => {\n clearInterval(handle);\n };\n };\n}\n","// ---------------------------------------------------------------------------\n// fromPort — universal `Runtime.subscribePort`-shaped Sub factory.\n//\n// The canonical cross-runtime coordination pattern in @demlik/tea: one\n// runtime emits to a typed Port; another runtime's machine declares an\n// `audit-idle`-shaped Sub whose subscribe handler attaches to the\n// publisher's Port. The recurring 4-line shape at every such cell:\n//\n// \"audit-idle\": (_sub, ctx, dispatch) =>\n// ctx.auditRuntime.subscribePort(auditIdlePort, (value) => {\n// dispatch(buildMsg(value));\n// });\n//\n// The factory absorbs the cleanup-returning subscribePort call AND the\n// dispatch-on-emit wiring. The caller keeps the three pieces of intent:\n//\n// 1. `selectRuntime(ctx)` — which sibling Runtime publishes the Port.\n// This is a selector (not a direct ctx.auditRuntime reference) so\n// the factory does NOT pin the ctx shape — any machine whose ctx\n// exposes some Runtime<...> reference is compatible by selecting it.\n// A direct `Runtime` parameter would have made the factory shape\n// depend on having that Runtime in scope at machine-definition\n// time, which is a worse match for the \"ctx is the boundary\"\n// contract this substrate already commits to.\n//\n// 2. `port: Port<T>` — the typed channel itself. Identity is by\n// reference (the substrate enforces unique names at definePort\n// time); pass the same `Port<T>` value the publisher emits to.\n//\n// 3. `msgFn(value, sub) => M | null` — the value-to-Msg mapping, with\n// drop-on-null semantics matching every other factory in this\n// subpath. The published value's type `T` flows through to `msgFn`'s\n// first param so the caller never re-asserts the payload shape.\n//\n// Strengthens invariant 9 (the cross-runtime Port topology is named at\n// one factory site instead of redrawn at every subscribe cell).\n// ---------------------------------------------------------------------------\n\nimport type { Port, Runtime, Sub } from \"../index\";\nimport type { SubscribeHandler } from \"./types\";\n\n// `RS` / `RM` carry the sibling Runtime's concrete State and Msg through the\n// selector: a caller that selects a `Runtime<AuditState, AuditMsg>` keeps that\n// type at the seam instead of collapsing it to `Runtime<unknown, {type:string}>`.\n// They default to the prior broad pair so existing call sites that select a\n// less-specific Runtime still compile — the factory still only ever calls\n// `subscribePort`, so it does not read RS/RM, but the boundary no longer\n// hardcodes the widest type when the caller knows a narrower one.\nexport function fromPort<\n S extends Sub,\n M,\n Ctx,\n T,\n RS = unknown,\n RM extends { type: string } = { type: string },\n>(\n selectRuntime: (ctx: Ctx) => Runtime<RS, RM>,\n port: Port<T>,\n msgFn: (value: T, sub: S) => M | null,\n): SubscribeHandler<S, M, Ctx> {\n return (sub, ctx, dispatch) => {\n const runtime = selectRuntime(ctx);\n return runtime.subscribePort(port, (value) => {\n const msg = msgFn(value, sub);\n if (msg !== null) dispatch(msg);\n });\n };\n}\n","// ---------------------------------------------------------------------------\n// fromReconnectingWebSocket — a `WebSocket` Sub factory that survives drops.\n//\n// `fromWebSocket` is the SSE-sibling ONE-SHOT factory: its cleanup `close()`s\n// the socket and it never re-opens on an unexpected drop (issue #188). That is\n// the right shape for a connection the caller manages, but any tea client over\n// an unreliable transport — games, presence, collab — needs the connection to\n// recover transparently, without a page reload. Rather than re-roll a backoff\n// loop in every consumer (vortex's `ReconnectingSocket` is the proven shape,\n// services/vortex/src/reconnecting-socket.ts), this is the reconnecting variant\n// folded into the substrate's Sub surface.\n//\n// The reconnect contract, mirroring vortex's wrapper:\n//\n// - On an UNEXPECTED close (`onclose` the substrate didn't initiate) it\n// re-opens after a CAPPED exponential backoff: `min(base * 2^attempt, max)`.\n// A successful handshake resets `attempt` to 0, so the next drop retries\n// fast again.\n//\n// - A CALLER-INITIATED close (the Sub's cleanup, e.g. the machine\n// transitioned the Sub away) suppresses reconnect: handlers are detached\n// BEFORE `close(1000)` so the teardown can't fire `onClose` or schedule a\n// reconnect. After cleanup the factory never re-opens.\n//\n// - `connect` and `schedule` are INJECTABLE (defaulting to the global\n// `WebSocket` and `setTimeout`/`clearTimeout`), the test seam that lets the\n// reconnect/backoff behavior be unit-tested with a fake socket + a manual\n// clock — no DOM, no real network, no timers — exactly as vortex's wrapper\n// is tested.\n//\n// Callback contract (same `M | null` \"null drops the dispatch\" shape as\n// `fromWebSocket`, plus one reconnect-specific hook):\n//\n// - `onMessage(data, sub)` — required. Raw `unknown` frame; the caller parses.\n// - `onOpen(sub)` — optional. Fires on EVERY successful handshake — the first\n// open AND every reconnect — so a \"connected\" indicator stays accurate.\n// - `onError(event, sub)` — optional. The `error` event; `close` still drives\n// the reconnect (one path), so this is purely a notification.\n// - `onClose(code, reason, sub)` — optional. Fires on every close the\n// substrate observes (a drop that will be retried, too) — NOT on the\n// caller's own teardown, whose handlers are detached first.\n// - `onReconnect(attempt, sub)` — optional. Fires when a RE-open (any open\n// after the first) succeeds, carrying the 1-based reconnect count. This is\n// the resync hook: the place to dispatch a \"re-fetch the authoritative\n// snapshot, discard predicted state\" Msg after the transport recovered.\n//\n// Like `fromWebSocket`, `wsUrl` lives on the Sub (`WebSocketSubData`); every\n// reconnect reads `sub.wsUrl` afresh, so a reconcile that re-subscribes with a\n// new url reconnects to the new endpoint.\n// ---------------------------------------------------------------------------\n\nimport type { Sub } from \"../index\";\nimport type { WebSocketSubData } from \"./from-web-socket\";\nimport type {\n MinimalEvent,\n MinimalWebSocket,\n MinimalWebSocketCtor,\n} from \"./platform\";\nimport type { SubscribeHandler } from \"./types\";\n\ndeclare const WebSocket: MinimalWebSocketCtor;\n\n/** Cancels a scheduled reconnect timer (the inverse of `schedule`). */\nexport type CancelTimer = () => void;\n\nexport interface ReconnectingWebSocketFactoryOpts<S, M> {\n onMessage: (data: unknown, sub: S) => M | null;\n onOpen?: (sub: S) => M | null;\n onError?: (event: MinimalEvent, sub: S) => M | null;\n onClose?: (code: number, reason: string, sub: S) => M | null;\n /**\n * Fires when a reconnection (any open after the first) succeeds, carrying the\n * 1-based reconnect count — the resync hook. Omitting drops reconnect events\n * silently.\n */\n onReconnect?: (attempt: number, sub: S) => M | null;\n /** First backoff delay in ms (doubles each failed attempt). Default 250. */\n backoffBaseMs?: number;\n /** Backoff ceiling in ms. Default 5000. */\n backoffMaxMs?: number;\n /** Inject the socket constructor (defaults to the global `WebSocket`); the test seam. */\n connect?: (url: string) => MinimalWebSocket;\n /** Inject the timer (defaults to `setTimeout`/`clearTimeout`); the test seam. */\n schedule?: (fn: () => void, ms: number) => CancelTimer;\n}\n\nconst defaultConnect = (url: string): MinimalWebSocket => new WebSocket(url);\n\nconst defaultSchedule = (fn: () => void, ms: number): CancelTimer => {\n const handle = setTimeout(fn, ms);\n return () => clearTimeout(handle);\n};\n\nexport function fromReconnectingWebSocket<S extends Sub & WebSocketSubData, M>(\n opts: ReconnectingWebSocketFactoryOpts<S, M>,\n): SubscribeHandler<S, M, unknown> {\n const backoffBaseMs = opts.backoffBaseMs ?? 250;\n const backoffMaxMs = opts.backoffMaxMs ?? 5000;\n const connect = opts.connect ?? defaultConnect;\n const schedule = opts.schedule ?? defaultSchedule;\n\n const { onMessage, onOpen, onError, onClose, onReconnect } = opts;\n\n return (sub, _ctx, dispatch) => {\n let ws: MinimalWebSocket | null = null;\n let attempt = 0;\n let opened = false;\n let closedByCaller = false;\n let cancelReconnect: CancelTimer | null = null;\n\n const emit = (msg: M | null): void => {\n if (msg !== null) dispatch(msg);\n };\n\n const handleClose = (code: number, reason: string): void => {\n ws = null;\n if (onClose) emit(onClose(code, reason, sub));\n // A teardown the substrate initiated detaches handlers first, so this\n // path only runs for an UNEXPECTED close — reconnect with capped backoff.\n if (closedByCaller) return;\n const delay = Math.min(backoffBaseMs * 2 ** attempt, backoffMaxMs);\n attempt += 1;\n cancelReconnect = schedule(() => {\n cancelReconnect = null;\n if (!closedByCaller) open();\n }, delay);\n };\n\n function open(): void {\n const socket = connect(sub.wsUrl);\n ws = socket;\n\n socket.onopen = (): void => {\n // `opened` BEFORE this open marks it a reconnect; `attempt` is the\n // pending count for the drop that triggered it (1-based once we reset).\n const reconnected = opened;\n const reconnectCount = attempt;\n attempt = 0;\n opened = true;\n if (onOpen) emit(onOpen(sub));\n if (reconnected && onReconnect) emit(onReconnect(reconnectCount, sub));\n };\n\n socket.onmessage = (event): void => {\n emit(onMessage(event.data, sub));\n };\n\n // `error` precedes `close`; let `close` drive the reconnect so there is\n // one path. The handler is still wired (as a no-op when the caller didn't\n // supply `onError`) so a platform error event has a sink.\n socket.onerror = onError\n ? (event): void => emit(onError(event, sub))\n : (): void => {};\n\n socket.onclose = (event): void => {\n handleClose(event.code, event.reason);\n };\n }\n\n open();\n\n return () => {\n // Deliberate teardown: cancel any pending reconnect, detach handlers so\n // the cleanup `close()` can't fire `onClose` or schedule a reconnect,\n // then close the live socket. After this the factory never re-opens.\n closedByCaller = true;\n if (cancelReconnect !== null) {\n cancelReconnect();\n cancelReconnect = null;\n }\n const socket = ws;\n ws = null;\n if (socket !== null) {\n socket.onopen = null;\n socket.onmessage = null;\n socket.onerror = null;\n socket.onclose = null;\n // 1000 = \"normal closure\" per RFC 6455 §7.4.1.\n socket.close(1000);\n }\n };\n };\n}\n","// ---------------------------------------------------------------------------\n// fromWebSocket — universal `WebSocket` Sub factory. The symmetric sibling\n// of `fromEventSource`.\n//\n// WebSocket is the bidirectional streaming protocol used wherever the\n// server pushes events AND the client pushes commands on the same\n// connection. The constructor opens the connection, `onopen` fires once\n// on handshake, `onmessage` fires per server-pushed frame, `onerror`\n// fires on transient or permanent failure, `onclose` fires once on\n// teardown carrying `code` + `reason`. `close(code)` initiates a clean\n// shutdown from the client side.\n//\n// Four callbacks because four observable events ARE four concerns the\n// caller routinely cares about. The Sub's `wsUrl` lives on the Sub itself\n// (`WebSocketSubData`) — same id + different `wsUrl` is silent under the\n// reconcile pass, identical to `fromEventSource`'s `url` contract.\n//\n// - `onMessage(data, sub)` — required. The platform delivers `data` as\n// `string | Blob | ArrayBuffer` depending on `binaryType` and the\n// server's frame type. The factory does NOT bake in a parse contract:\n// the callback receives the raw `unknown` and decides parse + Msg\n// shape. Returns `M | null`; null drops the dispatch.\n//\n// - `onOpen(sub)` — optional. Connection handshake succeeded. Useful\n// for \"show 'connected' indicator\" Msgs. Omitting drops open events\n// silently.\n//\n// - `onError(event, sub)` — optional. WebSocket's `error` event fires\n// on transient drops AND permanent failures; like SSE, most consumers\n// want one Msg (\"connection-errored\") without folding both into\n// `onMessage`'s discriminant. Omitting drops error events silently.\n//\n// - `onClose(code, reason, sub)` — optional. The connection is gone.\n// `code` is the WebSocket close code (1000 = clean, 1006 = abnormal,\n// etc.). `reason` is the server-supplied string (often empty).\n// Omitting drops close events silently.\n//\n// Cleanup is `close(1000)` — the IANA-registered clean-shutdown code.\n// The factory intentionally does NOT bake in registry semantics (e.g.\n// the extension's `ctx.wsRegistry` so `interpret.send_ws` can reach the\n// live socket): that's consumer glue. A consumer that needs the live\n// socket for outbound sends wires it from inside the subscribe handler\n// or keeps a hand-written Sub alongside this factory.\n// ---------------------------------------------------------------------------\n\nimport type { Sub } from \"../index\";\nimport type {\n MinimalCloseEvent,\n MinimalEvent,\n MinimalMessageEvent,\n MinimalWebSocketCtor,\n} from \"./platform\";\nimport type { SubscribeHandler } from \"./types\";\n\nexport type WebSocketSubData = { wsUrl: string };\n\ndeclare const WebSocket: MinimalWebSocketCtor;\n\nexport interface WebSocketFactoryOpts<S, M> {\n onMessage: (data: unknown, sub: S) => M | null;\n onOpen?: (sub: S) => M | null;\n onError?: (event: MinimalEvent, sub: S) => M | null;\n onClose?: (code: number, reason: string, sub: S) => M | null;\n}\n\nexport function fromWebSocket<S extends Sub & WebSocketSubData, M>(\n opts: WebSocketFactoryOpts<S, M>,\n): SubscribeHandler<S, M, unknown> {\n return (sub, _ctx, dispatch) => {\n const ws = new WebSocket(sub.wsUrl);\n\n ws.onmessage = (event: MinimalMessageEvent): void => {\n // The platform delivers `data` as `unknown` — the factory hands it\n // through untouched and the caller chooses the parse strategy.\n const msg = opts.onMessage(event.data, sub);\n if (msg !== null) dispatch(msg);\n };\n\n const onOpen = opts.onOpen;\n if (onOpen) {\n ws.onopen = (): void => {\n const msg = onOpen(sub);\n if (msg !== null) dispatch(msg);\n };\n }\n\n const onError = opts.onError;\n if (onError) {\n ws.onerror = (event: MinimalEvent): void => {\n const msg = onError(event, sub);\n if (msg !== null) dispatch(msg);\n };\n }\n\n const onClose = opts.onClose;\n if (onClose) {\n ws.onclose = (event: MinimalCloseEvent): void => {\n const msg = onClose(event.code, event.reason, sub);\n if (msg !== null) dispatch(msg);\n };\n }\n\n return () => {\n // Detach the lifecycle handlers BEFORE close() so the consumer's\n // `onClose` Msg isn't fired from a teardown the substrate initiated.\n // Mirrors fromEventSource's removeEventListener pass.\n ws.onmessage = null;\n ws.onopen = null;\n ws.onerror = null;\n ws.onclose = null;\n // 1000 = \"normal closure\" per RFC 6455 §7.4.1.\n ws.close(1000);\n };\n };\n}\n"]}
@@ -0,0 +1,60 @@
1
+ import { replay } from './chunk-MMH7CW5K.js';
2
+
3
+ // src/trace-replay/index.ts
4
+ function replayTrace(machine, trace, ctx) {
5
+ const result = replay(machine, {
6
+ msgs: trace.msgs,
7
+ ctx,
8
+ loaded: trace.loaded
9
+ });
10
+ const actual = result.state;
11
+ const expected = trace.finalState;
12
+ const divergence = firstDivergence(expected, actual, "state");
13
+ if (divergence === null) {
14
+ return { matches: true, expected, actual };
15
+ }
16
+ return { matches: false, expected, actual, divergence };
17
+ }
18
+ function deepEqual(a, b) {
19
+ return firstDivergence(a, b, "state") === null;
20
+ }
21
+ function firstDivergence(expected, actual, path) {
22
+ if (Object.is(expected, actual)) return null;
23
+ const te = typeOf(expected);
24
+ const ta = typeOf(actual);
25
+ if (te !== ta) return { path, expected, actual };
26
+ if (te === "array") {
27
+ const ae = expected;
28
+ const aa = actual;
29
+ if (ae.length !== aa.length) {
30
+ return { path, expected, actual };
31
+ }
32
+ for (let i = 0; i < ae.length; i++) {
33
+ const d = firstDivergence(ae[i], aa[i], `${path}[${i}]`);
34
+ if (d !== null) return d;
35
+ }
36
+ return null;
37
+ }
38
+ if (te === "object") {
39
+ const oe = expected;
40
+ const oa = actual;
41
+ const keys = [.../* @__PURE__ */ new Set([...Object.keys(oe), ...Object.keys(oa)])].sort();
42
+ for (const key of keys) {
43
+ const d = firstDivergence(oe[key], oa[key], `${path}.${key}`);
44
+ if (d !== null) return d;
45
+ }
46
+ return null;
47
+ }
48
+ return { path, expected, actual };
49
+ }
50
+ function typeOf(v) {
51
+ if (v === null) return "null";
52
+ if (v === void 0) return "undefined";
53
+ if (Array.isArray(v)) return "array";
54
+ if (typeof v === "object") return "object";
55
+ return "primitive";
56
+ }
57
+
58
+ export { deepEqual, replayTrace };
59
+ //# sourceMappingURL=chunk-ON24RKSE.js.map
60
+ //# sourceMappingURL=chunk-ON24RKSE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/trace-replay/index.ts"],"names":[],"mappings":"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","file":"chunk-ON24RKSE.js","sourcesContent":["// ---------------------------------------------------------------------------\n// trace-replay — replay a recorded Trace against a machine and diff the state.\n//\n// This is the back half of the record/replay feature. `../recorder` captures\n// a run (`loaded` + `msgs` + `finalState`); this module feeds that input\n// through the core `replay(machine, { msgs, ctx, loaded })` fold and asks:\n//\n// does the current reducer still produce the SAME final state for this\n// recorded input?\n//\n// Equal ⇒ the reducer is behavior-compatible with the recording. Diverged ⇒\n// the reducer changed for that input, and the divergence path\n// (`state.queue[2].status`) points at exactly the cell that drifted. This is\n// the regression / production-repro tool: record a prod incident, replay it\n// against the fixed reducer locally, confirm the fix changes the state at the\n// path you expected — or catch an unintended drift before it ships.\n//\n// Standalone by design. It imports ONLY the `Trace` type from `../recorder`\n// and the `replay` engine from `../index`. The deep-equal + first-divergence\n// path finder is self-contained (no external diff lib) — a richer pretty-diff\n// lands in `../devtools` later; trace-replay stays dependency-free so it can\n// run anywhere a machine runs (CI, a Worker, a Node script).\n// ---------------------------------------------------------------------------\n\nimport { type Cmd, type Machine, replay, type Sub } from \"../index\";\nimport type { Trace } from \"../recorder\";\n\n/**\n * The outcome of {@link replayTrace}.\n *\n * @typeParam S - the machine's State type.\n */\nexport interface ReplayResult<S> {\n /** `true` iff the recomputed final state deep-equals the trace's `finalState`. */\n matches: boolean;\n /** The trace's recorded `finalState` — what the run originally produced. */\n expected: S;\n /** The state the current reducer produced for the same input. */\n actual: S;\n /**\n * Present iff `matches` is `false`. The FIRST point of divergence found by\n * a deterministic pre-order walk:\n * - `path` — a dotted/indexed access path from the state root, e.g.\n * `state.queue[2].status` or `state` for a root-level\n * scalar mismatch.\n * - `expected` — the recorded value at that path.\n * - `actual` — the recomputed value at that path.\n */\n divergence?: { path: string; expected: unknown; actual: unknown };\n}\n\n/**\n * Replay a recorded {@link Trace} against `machine` and diff the recomputed\n * final state against the recorded one.\n *\n * Runs the core pure fold `replay(machine, { msgs: trace.msgs, ctx,\n * loaded: trace.loaded })` — init + update only, never `interpret`, never a\n * `Store`, never a live subscription (see `replay` in ../index). The `ctx` is\n * supplied fresh by the caller: the trace is the INPUT (loaded + msgs); ctx is\n * the ENVIRONMENT the reducer runs against now.\n *\n * @param machine - the machine to replay against. Mutating its reducer (the\n * whole point of a regression check) is what makes a recorded\n * trace diverge.\n * @param trace - a Trace from `../recorder` (live `dump()` or a re-hydrated\n * `parseJSONL(...)`).\n * @param ctx - the runtime ctx, supplied fresh at replay time.\n */\nexport function replayTrace<\n S,\n M extends { type: string },\n C extends Cmd,\n U extends Sub,\n Ctx,\n>(\n machine: Machine<S, M, C, U, Ctx>,\n trace: Trace<S, M>,\n ctx: Ctx,\n): ReplayResult<S> {\n const result = replay(machine, {\n msgs: trace.msgs,\n ctx,\n loaded: trace.loaded,\n });\n const actual = result.state;\n const expected = trace.finalState;\n\n const divergence = firstDivergence(expected, actual, \"state\");\n if (divergence === null) {\n return { matches: true, expected, actual };\n }\n return { matches: false, expected, actual, divergence };\n}\n\n/**\n * Order-insensitive structural deep-equality — the single comparator this\n * package owns, exposed so consumers (e.g. `@demlik/tea/parity`'s `diff`)\n * reuse it rather than adding a second deep-compare. `true` iff `a` and `b`\n * are structurally equal under {@link firstDivergence}'s walk (object keys\n * compared order-insensitively, arrays index-by-index).\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n return firstDivergence(a, b, \"state\") === null;\n}\n\n// === self-contained deep-equal + first-divergence path finder ===\n//\n// One walk does both jobs: it returns the FIRST point where `expected` and\n// `actual` differ (as a path + the two values), or `null` when they are\n// deeply equal. \"First\" is defined by a deterministic pre-order traversal:\n// the node itself, then its children in a stable key order (array index\n// order; object keys sorted so the result does not depend on insertion\n// order — two states with the same data but different key order are equal,\n// and the reported path for a real mismatch is reproducible run-to-run).\n//\n// Scope: TEA state is plain JSON-shaped data (the substrate's __DEV__ guards\n// reject closures in Cmds, and states are conventionally serializable). So\n// the walk handles: primitives, null/undefined, arrays, and plain objects.\n// It treats other object kinds (Date, Map, Set, class instances) by reference\n// identity + a structural fallback via Object.entries — sufficient for the\n// JSON-shaped states this tool targets; a richer differ lives in ../devtools.\n\n/** A divergence record, or `null` when the two values are deeply equal. */\ntype Divergence = { path: string; expected: unknown; actual: unknown } | null;\n\nfunction firstDivergence(\n expected: unknown,\n actual: unknown,\n path: string,\n): Divergence {\n // Identity / primitive fast path. Handles same-reference, and equal\n // primitives. `Object.is` so NaN === NaN and +0 ≠ -0 (matches structural\n // equality intent better than ===).\n if (Object.is(expected, actual)) return null;\n\n const te = typeOf(expected);\n const ta = typeOf(actual);\n // Different kinds at this node (e.g. object vs array, number vs string,\n // present vs null) — this node IS the divergence.\n if (te !== ta) return { path, expected, actual };\n\n if (te === \"array\") {\n const ae = expected as unknown[];\n const aa = actual as unknown[];\n if (ae.length !== aa.length) {\n // Length mismatch reported at the array node itself — the shape differs,\n // which is more informative than an arbitrary element index.\n return { path, expected, actual };\n }\n for (let i = 0; i < ae.length; i++) {\n const d = firstDivergence(ae[i], aa[i], `${path}[${i}]`);\n if (d !== null) return d;\n }\n return null;\n }\n\n if (te === \"object\") {\n const oe = expected as Record<string, unknown>;\n const oa = actual as Record<string, unknown>;\n // Union of keys, sorted for deterministic traversal. A key present in one\n // but absent in the other diverges at that child path (its value is\n // `undefined` on the missing side).\n const keys = [...new Set([...Object.keys(oe), ...Object.keys(oa)])].sort();\n for (const key of keys) {\n const d = firstDivergence(oe[key], oa[key], `${path}.${key}`);\n if (d !== null) return d;\n }\n return null;\n }\n\n // Primitives (string/number/boolean/bigint/symbol/function) that failed the\n // Object.is fast path, or null/undefined that differ — this node diverges.\n return { path, expected, actual };\n}\n\n/** Coarse type tag used by the divergence walk to decide how to recurse. */\nfunction typeOf(\n v: unknown,\n): \"null\" | \"undefined\" | \"array\" | \"object\" | \"primitive\" {\n if (v === null) return \"null\";\n if (v === undefined) return \"undefined\";\n if (Array.isArray(v)) return \"array\";\n if (typeof v === \"object\") return \"object\";\n return \"primitive\";\n}\n"]}
@@ -0,0 +1,87 @@
1
+ import { createResilientCall, liftResilience } from './chunk-27N2SPTN.js';
2
+ import { MsgType } from './chunk-JELSZN25.js';
3
+
4
+ // src/llm-call/index.ts
5
+ function createLlmCall(config, rng = Math.random) {
6
+ const resilientConfig = {
7
+ ...config.retry === void 0 ? {} : { retry: config.retry }
8
+ };
9
+ const rc = createResilientCall(resilientConfig, rng);
10
+ function init() {
11
+ return rc.init();
12
+ }
13
+ function attempt(s, input, at, key = input.purpose) {
14
+ return rc.attempt(s, key, input, at);
15
+ }
16
+ function succeed(s, key, msg) {
17
+ return rc.succeed(s, key, msg);
18
+ }
19
+ function fail(s, key, msg) {
20
+ return rc.fail(s, key, msg);
21
+ }
22
+ function onTimer(s, msg) {
23
+ return rc.onTimer(s, msg);
24
+ }
25
+ function subs(s) {
26
+ return rc.subs(s);
27
+ }
28
+ async function invokeOne(input) {
29
+ const model = config.model(input.model);
30
+ const messages = config.loadMessages ? await config.loadMessages(input) : [];
31
+ const schema = config.schemas[input.purpose];
32
+ const structured = model.withStructuredOutput(schema);
33
+ const raw = await structured.invoke(messages);
34
+ const output = schema.parse(raw);
35
+ return { key: input.purpose, purpose: input.purpose, output };
36
+ }
37
+ const resilientRunHandler = rc.handlers({
38
+ run: (input) => invokeOne(input)
39
+ }).resilient_run;
40
+ async function settleOf(cmd) {
41
+ const settle = await resilientRunHandler(cmd, {});
42
+ if (settle.type === MsgType.ResilientOk) {
43
+ return settle;
44
+ }
45
+ const rawError = settle.error;
46
+ const err = {
47
+ key: cmd.key,
48
+ purpose: cmd.input.purpose,
49
+ reason: rawError instanceof Error ? rawError.message : String(rawError),
50
+ error: rawError
51
+ };
52
+ return {
53
+ type: MsgType.ResilientErr,
54
+ key: settle.key,
55
+ error: err,
56
+ at: settle.at
57
+ };
58
+ }
59
+ function handlers(ports) {
60
+ if (ports === void 0) {
61
+ return { resilient_run: (cmd) => settleOf(cmd) };
62
+ }
63
+ return {
64
+ resilient_run: (cmd, ctx) => {
65
+ const fired = (async () => {
66
+ const settle = await settleOf(cmd);
67
+ if (settle.type === MsgType.ResilientOk) {
68
+ const msg2 = ports.onOk(settle.result);
69
+ if (msg2 !== void 0) await ctx.dispatch(msg2);
70
+ return;
71
+ }
72
+ const msg = ports.onErr(settle.error);
73
+ if (msg !== void 0) await ctx.dispatch(msg);
74
+ })();
75
+ ctx.waitUntil(fired);
76
+ }
77
+ };
78
+ }
79
+ return { init, attempt, succeed, fail, onTimer, subs, handlers, invokeOne };
80
+ }
81
+ function liftLlmCall(state, result) {
82
+ return liftResilience(state, result);
83
+ }
84
+
85
+ export { createLlmCall, liftLlmCall };
86
+ //# sourceMappingURL=chunk-PS23H6KQ.js.map
87
+ //# sourceMappingURL=chunk-PS23H6KQ.js.map