@demlik/tea 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (372) hide show
  1. package/README.md +11 -9
  2. package/dist/agent/index.d.ts +637 -45
  3. package/dist/agent/index.js +9 -19
  4. package/dist/{chunk-25LBDCBC.js → chunk-6IQPODUF.js} +2 -2
  5. package/dist/{chunk-25LBDCBC.js.map → chunk-6IQPODUF.js.map} +1 -1
  6. package/dist/chunk-AQ6ZIMEA.js +421 -0
  7. package/dist/chunk-AQ6ZIMEA.js.map +1 -0
  8. package/dist/{chunk-MUUROGIH.js → chunk-BLJ2JQSH.js} +62 -12
  9. package/dist/chunk-BLJ2JQSH.js.map +1 -0
  10. package/dist/{chunk-RH5EFRVJ.js → chunk-F2US5BW6.js} +25 -5
  11. package/dist/chunk-F2US5BW6.js.map +1 -0
  12. package/dist/{batch-window/index.js → chunk-F7FMAWLA.js} +4 -8
  13. package/dist/chunk-F7FMAWLA.js.map +1 -0
  14. package/dist/{chunk-O4MVQTEJ.js → chunk-HUKZQX6U.js} +20 -16
  15. package/dist/chunk-HUKZQX6U.js.map +1 -0
  16. package/dist/{chunk-EWJP3YYP.js → chunk-HWVW4AXC.js} +3 -3
  17. package/dist/chunk-HWVW4AXC.js.map +1 -0
  18. package/dist/{chunk-DMYGQB4O.js → chunk-HYDWG35Q.js} +23 -6
  19. package/dist/chunk-HYDWG35Q.js.map +1 -0
  20. package/dist/{chunk-YUXP55T2.js → chunk-I5MQMJDW.js} +57 -7
  21. package/dist/chunk-I5MQMJDW.js.map +1 -0
  22. package/dist/{chunk-J6527VRQ.js → chunk-LFZUK6J2.js} +3 -3
  23. package/dist/chunk-LFZUK6J2.js.map +1 -0
  24. package/dist/{chunk-ZVJZ72HY.js → chunk-LYLTKJWM.js} +25 -11
  25. package/dist/chunk-LYLTKJWM.js.map +1 -0
  26. package/dist/{chunk-D736QUGF.js → chunk-MYXFNWAJ.js} +4 -5
  27. package/dist/chunk-MYXFNWAJ.js.map +1 -0
  28. package/dist/{chunk-K575PT4S.js → chunk-PR6TB3BL.js} +15 -4
  29. package/dist/chunk-PR6TB3BL.js.map +1 -0
  30. package/dist/chunk-RQULHGYH.js +1804 -0
  31. package/dist/chunk-RQULHGYH.js.map +1 -0
  32. package/dist/{chunk-FV3Z5MBE.js → chunk-TXN2KFHF.js} +14 -4
  33. package/dist/chunk-TXN2KFHF.js.map +1 -0
  34. package/dist/{chunk-Q2UM7BXU.js → chunk-VBDU4JL6.js} +2 -2
  35. package/dist/chunk-VBDU4JL6.js.map +1 -0
  36. package/dist/chunk-Z2L3LSNV.js +1470 -0
  37. package/dist/chunk-Z2L3LSNV.js.map +1 -0
  38. package/dist/{core-Co0LWkIA.d.ts → core-CTzMJ82M.d.ts} +72 -23
  39. package/dist/devtools/index.d.ts +2 -2
  40. package/dist/devtools/index.js +207 -2
  41. package/dist/devtools/index.js.map +1 -1
  42. package/dist/do/index.d.ts +42 -29
  43. package/dist/do/index.js +36 -25
  44. package/dist/do/index.js.map +1 -1
  45. package/dist/{durable-effects-C6uwzjb5.d.ts → durable-effects-B0-qGQDy.d.ts} +2 -2
  46. package/dist/extension/index.d.ts +300 -3
  47. package/dist/extension/index.js +596 -5
  48. package/dist/extension/index.js.map +1 -1
  49. package/dist/flow/index.d.ts +1295 -0
  50. package/dist/flow/index.js +732 -0
  51. package/dist/flow/index.js.map +1 -0
  52. package/dist/idempotency/index.d.ts +90 -116
  53. package/dist/idempotency/index.js +4 -1
  54. package/dist/{batch-window/index.d.ts → index-4vZzljCD.d.ts} +7 -12
  55. package/dist/{fan-out/index.d.ts → index-6A7dB8f6.d.ts} +7 -9
  56. package/dist/index-B5BZ-_cT.d.ts +616 -0
  57. package/dist/index-Bc40JWVl.d.ts +131 -0
  58. package/dist/{debounce/index.d.ts → index-DHSUmQTR.d.ts} +7 -7
  59. package/dist/index-DJWIER_3.d.ts +69 -0
  60. package/dist/{snapshot/index.d.ts → index-DMCeMPMJ.d.ts} +15 -78
  61. package/dist/{monitored-run/index.d.ts → index-NjrT3fL2.d.ts} +37 -13
  62. package/dist/{recorder/index.d.ts → index-TvRb1KVf.d.ts} +4 -7
  63. package/dist/{deadline/index.d.ts → index-q0hXFeZ0.d.ts} +155 -9
  64. package/dist/index.d.ts +711 -6
  65. package/dist/index.js +1 -2
  66. package/dist/jev/index.d.ts +634 -0
  67. package/dist/jev/index.js +433 -0
  68. package/dist/jev/index.js.map +1 -0
  69. package/dist/machine-CdIcN2Xm.d.ts +1773 -0
  70. package/dist/machine-viz/index.d.ts +1 -1
  71. package/dist/machine-viz/index.js +12 -5
  72. package/dist/machine-viz/index.js.map +1 -1
  73. package/dist/mem/index.d.ts +18 -3
  74. package/dist/mem/index.js +22 -2
  75. package/dist/mem/index.js.map +1 -1
  76. package/dist/node/index.d.ts +104 -6
  77. package/dist/node/index.js +132 -9
  78. package/dist/node/index.js.map +1 -1
  79. package/dist/{paginator → paginate}/index.d.ts +151 -6
  80. package/dist/paginate/index.js +7 -0
  81. package/dist/parity/index.d.ts +4 -10
  82. package/dist/parity/index.js +4 -7
  83. package/dist/parity/index.js.map +1 -1
  84. package/dist/pbt/index.d.ts +247 -5
  85. package/dist/pbt/index.js +124 -5
  86. package/dist/pbt/index.js.map +1 -1
  87. package/dist/{trace-replay → persistence}/index.d.ts +7 -5
  88. package/dist/persistence/index.js +6 -0
  89. package/dist/react/index.d.ts +2 -2
  90. package/dist/react/index.js +1 -2
  91. package/dist/react/index.js.map +1 -1
  92. package/dist/resilience/index.d.ts +743 -0
  93. package/dist/resilience/index.js +657 -0
  94. package/dist/resilience/index.js.map +1 -0
  95. package/dist/retry-backoff/index.d.ts +3 -2
  96. package/dist/retry-backoff/index.js +1 -1
  97. package/dist/runtime-types-LWDoi943.d.ts +998 -0
  98. package/dist/testing/index.d.ts +2 -2
  99. package/dist/testing/index.js +1 -2
  100. package/dist/testing/index.js.map +1 -1
  101. package/dist/{throttled-input → timing}/index.d.ts +143 -12
  102. package/dist/{throttled-input → timing}/index.js +57 -12
  103. package/dist/timing/index.js.map +1 -0
  104. package/dist/{types-XS_miRnB.d.ts → types-DP3f5NIl.d.ts} +1 -1
  105. package/dist/work-queue/index.d.ts +130 -54
  106. package/dist/work-queue/index.js +3 -2
  107. package/dist/work-queue/index.js.map +1 -1
  108. package/package.json +45 -218
  109. package/dist/authed-call/index.d.ts +0 -120
  110. package/dist/authed-call/index.js +0 -134
  111. package/dist/authed-call/index.js.map +0 -1
  112. package/dist/await-terminal/index.d.ts +0 -101
  113. package/dist/await-terminal/index.js +0 -76
  114. package/dist/await-terminal/index.js.map +0 -1
  115. package/dist/batch-window/index.js.map +0 -1
  116. package/dist/cache/index.d.ts +0 -152
  117. package/dist/cache/index.js +0 -8
  118. package/dist/chart/index.d.ts +0 -218
  119. package/dist/chart/index.js +0 -16
  120. package/dist/chart/index.js.map +0 -1
  121. package/dist/chart/inspect/index.d.ts +0 -86
  122. package/dist/chart/inspect/index.js +0 -5
  123. package/dist/chart/inspect/react.d.ts +0 -113
  124. package/dist/chart/inspect/react.js +0 -11
  125. package/dist/chart/inspect/react.js.map +0 -1
  126. package/dist/chart/inspect/styles.css +0 -286
  127. package/dist/chart/lane/index.d.ts +0 -362
  128. package/dist/chart/lane/index.js +0 -9
  129. package/dist/chart/lane/index.js.map +0 -1
  130. package/dist/chart/lane/react.d.ts +0 -84
  131. package/dist/chart/lane/react.js +0 -559
  132. package/dist/chart/lane/react.js.map +0 -1
  133. package/dist/chart/lane/server.d.ts +0 -148
  134. package/dist/chart/lane/server.js +0 -209
  135. package/dist/chart/lane/server.js.map +0 -1
  136. package/dist/chart/lane/styles.css +0 -498
  137. package/dist/chart/lane/viewer/assets/abnfDiagram-N423BO3Z-C729LI31.js +0 -1
  138. package/dist/chart/lane/viewer/assets/architectureDiagram-T3A2C74G-C729LI31.js +0 -1
  139. package/dist/chart/lane/viewer/assets/blockDiagram-VBNYF7ZC-C729LI31.js +0 -1
  140. package/dist/chart/lane/viewer/assets/c4Diagram-5PPSVZJV-C729LI31.js +0 -1
  141. package/dist/chart/lane/viewer/assets/chunk-2GRJ4B5K-HdDf8SI3.js +0 -1
  142. package/dist/chart/lane/viewer/assets/chunk-5RXB4S5H-CcNtpUd7.js +0 -231
  143. package/dist/chart/lane/viewer/assets/chunk-5VM5RSS4-BP4fRS_5.js +0 -15
  144. package/dist/chart/lane/viewer/assets/chunk-KBJHAD2P-DZOw7xU6.js +0 -1
  145. package/dist/chart/lane/viewer/assets/chunk-NSK5VX7P-CBCyTZMs.js +0 -128
  146. package/dist/chart/lane/viewer/assets/classDiagram-JCYQIIEL-C729LI31.js +0 -1
  147. package/dist/chart/lane/viewer/assets/classDiagram-v2-OCEON4UE-D4uAiFr8.js +0 -206
  148. package/dist/chart/lane/viewer/assets/cose-bilkent-JH36ORCC-DOwCrGXH.js +0 -1
  149. package/dist/chart/lane/viewer/assets/cynefinDiagram-MW4NZA55-C729LI31.js +0 -1
  150. package/dist/chart/lane/viewer/assets/dagre-K_PewWfS.js +0 -1
  151. package/dist/chart/lane/viewer/assets/dagre-VZM6K2ZE-831qZcA8.js +0 -4
  152. package/dist/chart/lane/viewer/assets/diagram-7IWD3JNH-C729LI31.js +0 -1
  153. package/dist/chart/lane/viewer/assets/diagram-B4RE2ZJO-C729LI31.js +0 -1
  154. package/dist/chart/lane/viewer/assets/diagram-LBJQPF4R-C729LI31.js +0 -1
  155. package/dist/chart/lane/viewer/assets/diagram-Q27KOJAE-C729LI31.js +0 -1
  156. package/dist/chart/lane/viewer/assets/diagram-UB23O5K3-C729LI31.js +0 -1
  157. package/dist/chart/lane/viewer/assets/ebnfDiagram-BXEA7PRR-C729LI31.js +0 -1
  158. package/dist/chart/lane/viewer/assets/erDiagram-JOGREHBK-C729LI31.js +0 -1
  159. package/dist/chart/lane/viewer/assets/flowDiagram-UKHOOZJN-C729LI31.js +0 -1
  160. package/dist/chart/lane/viewer/assets/ganttDiagram-PKOTCBZU-C729LI31.js +0 -1
  161. package/dist/chart/lane/viewer/assets/gitGraphDiagram-DS77QQ5N-C729LI31.js +0 -1
  162. package/dist/chart/lane/viewer/assets/index-9SkH5NA3.css +0 -1
  163. package/dist/chart/lane/viewer/assets/index-Bgt4sXpW.js +0 -195
  164. package/dist/chart/lane/viewer/assets/infoDiagram-6WML65LV-C729LI31.js +0 -1
  165. package/dist/chart/lane/viewer/assets/ishikawaDiagram-WSZJBQD7-C729LI31.js +0 -1
  166. package/dist/chart/lane/viewer/assets/journeyDiagram-NVQOT4AX-C729LI31.js +0 -1
  167. package/dist/chart/lane/viewer/assets/kanban-definition-27J2QSJJ-G7PaPzy-.js +0 -89
  168. package/dist/chart/lane/viewer/assets/katex-DOwCrGXH.js +0 -1
  169. package/dist/chart/lane/viewer/assets/mindmap-definition-FAOFIHXS-CGj9nrVk.js +0 -96
  170. package/dist/chart/lane/viewer/assets/path-fybaL0A-.js +0 -1
  171. package/dist/chart/lane/viewer/assets/pegDiagram-VL7TDLO6-C729LI31.js +0 -1
  172. package/dist/chart/lane/viewer/assets/pieDiagram-7S7Q4E2Y-C729LI31.js +0 -1
  173. package/dist/chart/lane/viewer/assets/quadrantDiagram-CIZ2JOQS-C729LI31.js +0 -1
  174. package/dist/chart/lane/viewer/assets/railroadDiagram-AXF67PYL-C729LI31.js +0 -1
  175. package/dist/chart/lane/viewer/assets/requirementDiagram-LRYGKXZP-C729LI31.js +0 -1
  176. package/dist/chart/lane/viewer/assets/sankeyDiagram-W5VNT64P-C729LI31.js +0 -1
  177. package/dist/chart/lane/viewer/assets/sequenceDiagram-SI44F4Z6-C729LI31.js +0 -1
  178. package/dist/chart/lane/viewer/assets/stateDiagram-OKZ733FA-B_88AzBS.js +0 -1
  179. package/dist/chart/lane/viewer/assets/stateDiagram-v2-UEYNNEHI-CR5gcgq6.js +0 -1
  180. package/dist/chart/lane/viewer/assets/swimlanes-SLNWSIFB-B4xK-rwg.js +0 -1
  181. package/dist/chart/lane/viewer/assets/swimlanesDiagram-ULZ7WXOC-C729LI31.js +0 -1
  182. package/dist/chart/lane/viewer/assets/timeline-definition-Z64GVDOM-CCv52MfY.js +0 -120
  183. package/dist/chart/lane/viewer/assets/vennDiagram-T6HMQDX7-C729LI31.js +0 -1
  184. package/dist/chart/lane/viewer/assets/wardleyDiagram-T6FBY63Y-C729LI31.js +0 -1
  185. package/dist/chart/lane/viewer/assets/xychartDiagram-ELKLHX3M-C729LI31.js +0 -1
  186. package/dist/chart/lane/viewer/index.html +0 -15
  187. package/dist/chart/report/index.d.ts +0 -117
  188. package/dist/chart/report/index.js +0 -32
  189. package/dist/chart/report/index.js.map +0 -1
  190. package/dist/chunk-2YFLOCWX.js +0 -15
  191. package/dist/chunk-2YFLOCWX.js.map +0 -1
  192. package/dist/chunk-3I52QZZ5.js +0 -519
  193. package/dist/chunk-3I52QZZ5.js.map +0 -1
  194. package/dist/chunk-3ZAFFRRB.js +0 -457
  195. package/dist/chunk-3ZAFFRRB.js.map +0 -1
  196. package/dist/chunk-4EQZ76JC.js +0 -33
  197. package/dist/chunk-4EQZ76JC.js.map +0 -1
  198. package/dist/chunk-4KLG43GY.js +0 -223
  199. package/dist/chunk-4KLG43GY.js.map +0 -1
  200. package/dist/chunk-7FRZ2CT2.js +0 -424
  201. package/dist/chunk-7FRZ2CT2.js.map +0 -1
  202. package/dist/chunk-AZZLE7XR.js +0 -62
  203. package/dist/chunk-AZZLE7XR.js.map +0 -1
  204. package/dist/chunk-BYQUGDD3.js +0 -16
  205. package/dist/chunk-BYQUGDD3.js.map +0 -1
  206. package/dist/chunk-CIQG5L42.js +0 -685
  207. package/dist/chunk-CIQG5L42.js.map +0 -1
  208. package/dist/chunk-CLM6ERNO.js +0 -61
  209. package/dist/chunk-CLM6ERNO.js.map +0 -1
  210. package/dist/chunk-COS5MSTO.js +0 -88
  211. package/dist/chunk-COS5MSTO.js.map +0 -1
  212. package/dist/chunk-CRPZJVD2.js +0 -71
  213. package/dist/chunk-CRPZJVD2.js.map +0 -1
  214. package/dist/chunk-D62FDQKE.js +0 -53
  215. package/dist/chunk-D62FDQKE.js.map +0 -1
  216. package/dist/chunk-D736QUGF.js.map +0 -1
  217. package/dist/chunk-DGE4PV4A.js +0 -26
  218. package/dist/chunk-DGE4PV4A.js.map +0 -1
  219. package/dist/chunk-DMYGQB4O.js.map +0 -1
  220. package/dist/chunk-EWJP3YYP.js.map +0 -1
  221. package/dist/chunk-FV3Z5MBE.js.map +0 -1
  222. package/dist/chunk-HCEVHFJ7.js +0 -54
  223. package/dist/chunk-HCEVHFJ7.js.map +0 -1
  224. package/dist/chunk-J6527VRQ.js.map +0 -1
  225. package/dist/chunk-JELSZN25.js +0 -47
  226. package/dist/chunk-JELSZN25.js.map +0 -1
  227. package/dist/chunk-K575PT4S.js.map +0 -1
  228. package/dist/chunk-L57ZOT5K.js +0 -184
  229. package/dist/chunk-L57ZOT5K.js.map +0 -1
  230. package/dist/chunk-MU6MCIAC.js +0 -15
  231. package/dist/chunk-MU6MCIAC.js.map +0 -1
  232. package/dist/chunk-MUUROGIH.js.map +0 -1
  233. package/dist/chunk-NR7BU22N.js +0 -758
  234. package/dist/chunk-NR7BU22N.js.map +0 -1
  235. package/dist/chunk-O4MVQTEJ.js.map +0 -1
  236. package/dist/chunk-OOYD44JI.js +0 -317
  237. package/dist/chunk-OOYD44JI.js.map +0 -1
  238. package/dist/chunk-Q2UM7BXU.js.map +0 -1
  239. package/dist/chunk-RH5EFRVJ.js.map +0 -1
  240. package/dist/chunk-S2EGRPCM.js +0 -47
  241. package/dist/chunk-S2EGRPCM.js.map +0 -1
  242. package/dist/chunk-SINXE47Y.js +0 -55
  243. package/dist/chunk-SINXE47Y.js.map +0 -1
  244. package/dist/chunk-UF4MZSLT.js +0 -53
  245. package/dist/chunk-UF4MZSLT.js.map +0 -1
  246. package/dist/chunk-UOC2PL46.js +0 -13
  247. package/dist/chunk-UOC2PL46.js.map +0 -1
  248. package/dist/chunk-VYFAZN3F.js +0 -372
  249. package/dist/chunk-VYFAZN3F.js.map +0 -1
  250. package/dist/chunk-WRAA7GVZ.js +0 -209
  251. package/dist/chunk-WRAA7GVZ.js.map +0 -1
  252. package/dist/chunk-XGELA764.js +0 -163
  253. package/dist/chunk-XGELA764.js.map +0 -1
  254. package/dist/chunk-YUXP55T2.js.map +0 -1
  255. package/dist/chunk-YWIKDKHY.js +0 -307
  256. package/dist/chunk-YWIKDKHY.js.map +0 -1
  257. package/dist/chunk-ZJ5AOYBH.js +0 -8
  258. package/dist/chunk-ZJ5AOYBH.js.map +0 -1
  259. package/dist/chunk-ZSUUOEPL.js +0 -731
  260. package/dist/chunk-ZSUUOEPL.js.map +0 -1
  261. package/dist/chunk-ZVJZ72HY.js.map +0 -1
  262. package/dist/circuit-breaker/index.d.ts +0 -197
  263. package/dist/circuit-breaker/index.js +0 -3
  264. package/dist/circuit-breaker/index.js.map +0 -1
  265. package/dist/deadline/index.js +0 -6
  266. package/dist/deadline/index.js.map +0 -1
  267. package/dist/debounce/index.js +0 -3
  268. package/dist/debounce/index.js.map +0 -1
  269. package/dist/extension/react.d.ts +0 -121
  270. package/dist/extension/react.js +0 -75
  271. package/dist/extension/react.js.map +0 -1
  272. package/dist/extension/subs/index.d.ts +0 -45
  273. package/dist/extension/subs/index.js +0 -80
  274. package/dist/extension/subs/index.js.map +0 -1
  275. package/dist/extension/test-utils.d.ts +0 -128
  276. package/dist/extension/test-utils.js +0 -277
  277. package/dist/extension/test-utils.js.map +0 -1
  278. package/dist/fan-out/index.js +0 -5
  279. package/dist/fan-out/index.js.map +0 -1
  280. package/dist/fold-BJPdjc9w.d.ts +0 -435
  281. package/dist/graph-B3L5e0N1.d.ts +0 -923
  282. package/dist/idempotency/adapter.d.ts +0 -62
  283. package/dist/idempotency/adapter.js +0 -4
  284. package/dist/idempotency/adapter.js.map +0 -1
  285. package/dist/idempotent-intake/index.d.ts +0 -188
  286. package/dist/idempotent-intake/index.js +0 -7
  287. package/dist/idempotent-intake/index.js.map +0 -1
  288. package/dist/journal/index.d.ts +0 -373
  289. package/dist/journal/index.js +0 -3
  290. package/dist/journal/index.js.map +0 -1
  291. package/dist/llm-call/index.d.ts +0 -311
  292. package/dist/llm-call/index.js +0 -16
  293. package/dist/llm-call/index.js.map +0 -1
  294. package/dist/machine-BtFWQmmq.d.ts +0 -804
  295. package/dist/monitored-run/index.js +0 -10
  296. package/dist/monitored-run/index.js.map +0 -1
  297. package/dist/paginated-walk/index.d.ts +0 -235
  298. package/dist/paginated-walk/index.js +0 -16
  299. package/dist/paginated-walk/index.js.map +0 -1
  300. package/dist/paginator/index.js +0 -3
  301. package/dist/paginator/index.js.map +0 -1
  302. package/dist/pbt/arbitraries/index.d.ts +0 -136
  303. package/dist/pbt/arbitraries/index.js +0 -3
  304. package/dist/pbt/arbitraries/index.js.map +0 -1
  305. package/dist/pbt/runners/index.d.ts +0 -118
  306. package/dist/pbt/runners/index.js +0 -5
  307. package/dist/pbt/runners/index.js.map +0 -1
  308. package/dist/poller/index.d.ts +0 -352
  309. package/dist/poller/index.js +0 -115
  310. package/dist/poller/index.js.map +0 -1
  311. package/dist/prediction/index.d.ts +0 -131
  312. package/dist/prediction/index.js +0 -4
  313. package/dist/prediction/index.js.map +0 -1
  314. package/dist/protocol-B5YmJr0d.d.ts +0 -45
  315. package/dist/pure/index.d.ts +0 -3
  316. package/dist/pure/index.js +0 -4
  317. package/dist/pure/index.js.map +0 -1
  318. package/dist/rate-limit/index.d.ts +0 -115
  319. package/dist/rate-limit/index.js +0 -3
  320. package/dist/rate-limit/index.js.map +0 -1
  321. package/dist/reconciler/index.d.ts +0 -193
  322. package/dist/reconciler/index.js +0 -164
  323. package/dist/reconciler/index.js.map +0 -1
  324. package/dist/recorder/index.js +0 -3
  325. package/dist/recorder/index.js.map +0 -1
  326. package/dist/reducer-4GNR6b8B.d.ts +0 -447
  327. package/dist/resilient-call/index.d.ts +0 -320
  328. package/dist/resilient-call/index.js +0 -14
  329. package/dist/resilient-call/index.js.map +0 -1
  330. package/dist/retry-to-success/index.d.ts +0 -109
  331. package/dist/retry-to-success/index.js +0 -37
  332. package/dist/retry-to-success/index.js.map +0 -1
  333. package/dist/run-pAcmBpah.d.ts +0 -713
  334. package/dist/runtime-types-CNLmhWif.d.ts +0 -517
  335. package/dist/saga/index.d.ts +0 -241
  336. package/dist/saga/index.js +0 -150
  337. package/dist/saga/index.js.map +0 -1
  338. package/dist/samples-B3My5oh2.d.ts +0 -59
  339. package/dist/snapshot/index.js +0 -5
  340. package/dist/snapshot/index.js.map +0 -1
  341. package/dist/subs/index.d.ts +0 -472
  342. package/dist/subs/index.js +0 -7
  343. package/dist/subs/index.js.map +0 -1
  344. package/dist/throttle/index.d.ts +0 -134
  345. package/dist/throttle/index.js +0 -3
  346. package/dist/throttle/index.js.map +0 -1
  347. package/dist/throttled-input/index.js.map +0 -1
  348. package/dist/token-refresh/index.d.ts +0 -216
  349. package/dist/token-refresh/index.js +0 -6
  350. package/dist/token-refresh/index.js.map +0 -1
  351. package/dist/trace-replay/index.js +0 -6
  352. package/dist/trace-replay/index.js.map +0 -1
  353. package/dist/with-deadline/index.d.ts +0 -197
  354. package/dist/with-deadline/index.js +0 -111
  355. package/dist/with-deadline/index.js.map +0 -1
  356. package/dist/with-resilience/index.d.ts +0 -225
  357. package/dist/with-resilience/index.js +0 -240
  358. package/dist/with-resilience/index.js.map +0 -1
  359. package/dist/with-telemetry/index.d.ts +0 -150
  360. package/dist/with-telemetry/index.js +0 -70
  361. package/dist/with-telemetry/index.js.map +0 -1
  362. package/dist/work-queue/adapter.d.ts +0 -84
  363. package/dist/work-queue/adapter.js +0 -4
  364. package/dist/work-queue/adapter.js.map +0 -1
  365. package/dist/work-queue/ops.d.ts +0 -71
  366. package/dist/work-queue/ops.js +0 -3
  367. package/dist/work-queue/ops.js.map +0 -1
  368. package/dist/workflow/index.d.ts +0 -485
  369. package/dist/workflow/index.js +0 -244
  370. package/dist/workflow/index.js.map +0 -1
  371. /package/dist/{cache → paginate}/index.js.map +0 -0
  372. /package/dist/{chart/inspect → persistence}/index.js.map +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internal/flow/await-terminal/index.ts","../../src/internal/flow/poller/index.ts","../../src/internal/flow/reconciler/index.ts","../../src/internal/flow/saga/index.ts","../../src/internal/flow/workflow/route.ts","../../src/internal/flow/workflow/index.ts"],"names":["tick","w","applied","isComplete","id"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * internal/flow/await-terminal — run a ONE-SHOT / decision-procedure machine to a\n * terminal state and hand the caller a `Promise<State>` that resolves the moment\n * the machine FIRST enters a terminal state.\n *\n * This is the ~10 lines both audit suitability probes hand-wired at their\n * integration seam: a one-shot decision machine (a credibility check, an auth\n * mint, a validation pass — run to a terminal state, then throw-or-proceed at the\n * caller boundary) has no built-in \"await the terminal\", so each consumer re-wires\n * a promise off `observe` that resolves when the state is terminal. This helper\n * lifts that boilerplate into `@demlik/tea` once.\n *\n * It rides the EXISTING observation surface (`packages/tea/src/index.ts`) and adds\n * NO new runtime capability:\n * - `runtime.getState()` (total on a booted `Runtime`) covers the\n * already-terminal-at-attach case — resolve synchronously rather than wait for\n * a transition that may never come.\n * - `runtime.observe((msg, state) => void): () => void` fires on EVERY transition\n * and returns an unsubscribe — the \"first terminal transition\" signal, detached\n * the instant it resolves (no leak, no busy-wait / polling loop).\n * - `runtime.stop()` is the teardown the fire-and-await `runToTerminal` owns.\n *\n * `isTerminal` is caller-supplied — tea has no built-in terminal-set concept and\n * this helper does NOT invent one; the caller names their own terminal states.\n *\n * The optional `timeoutMs` is a plain caller-boundary timer (not an in-loop\n * progress deadline — see `../deadline` / `../with-deadline` for that shape): it\n * clears on resolve and REJECTS with the `instanceof`-checkable\n * {@link TerminalTimeoutError} if the deadline elapses first, never silently\n * resolving.\n */\n\nimport {\n type Cmd,\n type CtxArg,\n type Machine,\n type Runtime,\n run,\n type Sub,\n} from \"../../../index\";\n\n/**\n * Raised when `awaitTerminal` / `runToTerminal` is wired with a `timeoutMs` and\n * the deadline elapses before any terminal state is reached. Follows the tea\n * error dialect (`override readonly name`) and carries a `_tag` discriminant, so\n * a caller can branch on it either by `instanceof` or on the tag — the timeout is\n * a distinct, checkable rejection, never a silent resolve.\n */\nexport class TerminalTimeoutError extends Error {\n override readonly name = \"TerminalTimeoutError\";\n readonly _tag = \"TerminalTimeoutError\" as const;\n constructor(public readonly timeoutMs: number) {\n super(\n `@demlik/tea: awaitTerminal did not reach a terminal state within ` +\n `${timeoutMs}ms — no transition satisfied isTerminal before the deadline.`,\n );\n }\n}\n\n/** Options shared by `awaitTerminal` and `runToTerminal`. */\nexport interface AwaitTerminalOptions {\n /**\n * Optional bounded deadline in milliseconds. When set, the returned promise\n * REJECTS with {@link TerminalTimeoutError} if no terminal state is reached\n * within the window; the timer is cleared on the resolve path so a resolved\n * await never later rejects or leaves a dangling timer. Omit for an unbounded\n * await (never rejects for time).\n */\n readonly timeoutMs?: number;\n}\n\n/**\n * Attach to an ALREADY-RUNNING `Runtime<S, M, E>` and resolve with the terminal\n * `S` on the first transition for which `isTerminal(state)` is true.\n *\n * If the runtime is ALREADY terminal at attach time (`isTerminal(getState())`),\n * resolves immediately — it never hangs waiting for a transition that will not\n * come. Otherwise it subscribes via `observe` and detaches that subscription the\n * instant it resolves (or times out), so there is no observer leak and no\n * further callbacks fire.\n *\n * @param runtime a booted `Runtime` (from `await run(machine, opts).ready`).\n * @param isTerminal caller-supplied terminal predicate over the machine's state.\n * @param opts optional bounded `timeoutMs` deadline (see {@link AwaitTerminalOptions}).\n */\nexport function awaitTerminal<\n S,\n M extends { type: string },\n E extends { type: string } = never,\n>(\n runtime: Runtime<S, M, E>,\n isTerminal: (state: S) => boolean,\n opts: AwaitTerminalOptions = {},\n): Promise<S> {\n return new Promise<S>((resolve, reject) => {\n // Already-terminal-at-attach: resolve now. Returning here attaches neither an\n // observer nor a timer, so the immediate case cannot leak either.\n const current = runtime.getState();\n if (isTerminal(current)) {\n resolve(current);\n return;\n }\n\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let detach: (() => void) | undefined;\n\n const cleanup = (): void => {\n if (timer !== undefined) {\n clearTimeout(timer);\n timer = undefined;\n }\n if (detach !== undefined) {\n detach();\n detach = undefined;\n }\n };\n\n detach = runtime.observe((_msg, state) => {\n if (settled) return;\n if (isTerminal(state)) {\n settled = true;\n cleanup();\n resolve(state);\n }\n });\n\n // Narrow into a const so the closure keeps the `number` narrowing (the field\n // itself is `number | undefined`).\n const timeoutMs = opts.timeoutMs;\n if (timeoutMs !== undefined) {\n timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(new TerminalTimeoutError(timeoutMs));\n }, timeoutMs);\n }\n });\n}\n\n/**\n * Fire-and-await convenience: `run()` the machine, dispatch the seed `msgs`, and\n * resolve with the terminal state — then tear the runtime down (`runtime.stop()`)\n * on BOTH the resolve and reject paths. Wraps {@link awaitTerminal}.\n *\n * The seed carries the machine's `ctx` (conditionally optional, exactly as\n * `run`'s `ctx` — a pure machine omits it) and the `msgs` to dispatch once\n * booted. A `timeoutMs` in `opts` bounds the await identically to `awaitTerminal`.\n *\n * @param machine the machine to boot.\n * @param seed `{ ctx?, msgs }` — the boot context and the seed messages.\n * @param isTerminal caller-supplied terminal predicate over the machine's state.\n * @param opts optional bounded `timeoutMs` deadline (see {@link AwaitTerminalOptions}).\n */\nexport async function runToTerminal<\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 seed: CtxArg<Ctx> & { readonly msgs: readonly M[] },\n isTerminal: (state: S) => boolean,\n opts: AwaitTerminalOptions = {},\n): Promise<S> {\n // Split the seed messages out from the boot context: `run`'s opts don't carry\n // `msgs`, so what remains is exactly the conditionally-optional `ctx` arg. The\n // cast is because `CtxArg<Ctx>` is a deferred generic conditional TS won't\n // verify against `run`'s all-optional opts (its weak-type check) — the value\n // is structurally valid; `run` defaults an absent `ctx` to `{}`.\n const { msgs, ...ctxArg } = seed;\n const runtime = await run<S, M, C, U, Ctx>(\n machine,\n ctxArg as Parameters<typeof run<S, M, C, U, Ctx>>[1],\n ).ready;\n try {\n // Attach the terminal await BEFORE dispatching so a terminal transition that\n // lands during a seed dispatch is caught (and the immediate-terminal check\n // inside awaitTerminal covers a machine that boots already terminal).\n const terminal = awaitTerminal(runtime, isTerminal, opts);\n // Dispatch runs serially on the runtime's tail; fire all seeds and let a\n // dispatch failure (a reducer/interpret throw) surface by racing it against\n // the terminal await rather than floating as an unhandled rejection.\n const seeding = Promise.all(msgs.map((msg) => runtime.dispatch(msg)));\n const state = await Promise.race([terminal, seeding.then(() => terminal)]);\n await runtime.stop();\n return state;\n } catch (err) {\n // Tear down on the reject path too (timeout, dispatch failure) — a rejected\n // runToTerminal never leaves the runtime running.\n await runtime.stop().catch(() => {});\n throw err;\n }\n}\n","/**\n * internal/flow/poller — \"poll a source every N ms until a predicate holds, with\n * backoff on failure\" as a TEA knob: one config object + a few pre-wired hooks\n * you spread into your machine.\n *\n * The recipe (which bricks it composes):\n *\n * - `../deadline` — the recurring tick is an ABSOLUTE-deadline Sub.\n * Each successful tick computes the NEXT absolute\n * fire time (`at + everyMs`) and the knob re-arms a\n * deadline against it. Absolute (not relative) so a\n * poller resumed after a DO eviction / page reload\n * fires at the correct wall-clock moment, not\n * `everyMs` after the reload (`../deadline`'s late-\n * subscribe property).\n * - `../retry-backoff` — a failed tick does NOT reschedule on the steady\n * cadence; it backs off. The next attempt is armed\n * `nextDelayMs(retry, policy)` from now, the retry\n * counter advances, and `shouldRetry` decides whether\n * the poller keeps trying or gives up. The bound may\n * be a COUNT or a wall-clock OUTAGE DURATION — see\n * `PollerConfig.retry`; `tickErr`'s `at` is the\n * streak clock, so both flow through unchanged.\n * - `../idempotency` — successive ticks against a flaky source can deliver\n * the SAME observation twice (a retried fetch, a\n * duplicate webhook the poll re-reads). `dedupeKey`\n * lets the consumer key each tick result; a duplicate\n * key is recorded but emits no fresh `onTick` follow-\n * up Cmd, so the side effect runs once per distinct\n * observation.\n *\n * Typical wiring (spread the knob's hooks into your machine):\n *\n * const poll = createPoller<MyState, MyResult>({\n * everyMs: 5_000,\n * until: (s) => s.poll.lastResult?.status === \"ready\",\n * onTick: () => ({ type: \"fetch_status\" }),\n * retry: { ...defaultRetryPolicy, maxAttempts: 4 },\n * });\n *\n * // Model slice:\n * init: (loaded) => [loaded ?? { poll: poll.init(), ... }, []],\n *\n * // The deadline Sub fires `deadline_exceeded` on the cadence/backoff target;\n * // route it to `tick`, the ONLY place the `onTick` fetch is emitted:\n * deadline_exceeded: (s) => {\n * const [slice, cmds] = poll.tick(s.poll);\n * return [{ ...s, poll: slice }, cmds];\n * },\n *\n * // update cells (thread `at` in from the firing Msg / the runtime clock):\n * poll_result: (s, m) => {\n * const untilHeld = config.until({ ...s, ...folded });\n * const [slice, cmds] = poll.tickResult(s.poll, m.result, m.at, untilHeld);\n * return [{ ...s, poll: slice }, cmds];\n * },\n * poll_error: (s, m) => {\n * const [slice, cmds] = poll.tickErr(s.poll, m.error, m.at);\n * return [{ ...s, poll: slice }, cmds];\n * },\n *\n * // Subs — the knob owns the interval/backoff deadline:\n * subscriptions: (s) => poll.subs(s.poll),\n *\n * The cadence has exactly ONE source: the `everyMs` deadline Sub. `start`,\n * `tickResult`, and `tickErr` only RE-ARM the deadline (they emit no cadence\n * Cmd); the fetch fires solely from `tick`, which the consumer routes the\n * deadline's `deadline_exceeded` Msg to. No verb performs an immediate\n * \"fire now\" observation, so the poller never polls faster than `everyMs`.\n *\n * The two non-negotiables every knob preserves hold here:\n * - **Durable** — `tick`, `lastResult`, `retry`, and the next-fire target all\n * live in the Model slice, so a poller survives eviction and resumes its\n * cadence from the persisted target.\n * - **Replayable** — every transition is a pure verb returning new state; the\n * clock is never read inside a verb (the firing Msg carries `at`), and the\n * retry RNG is injected ONCE at `createPoller` and threaded internally (no\n * verb body names the global RNG). `replay` reconstructs a poll run exactly.\n *\n * NOT a substrate primitive: it depends only on sibling subpaths\n * (`../deadline`, `../retry-backoff`, `../idempotency`) and the core `Cmd` /\n * `Sub` types. Internal since #48 — not published on any subpath; reached from\n * inside the package as `internal/flow/poller`. The L1 escape hatch is those\n * three siblings threaded by hand.\n */\n\nimport type { Cmd, Sub } from \"../../../index\";\nimport {\n type AnyRetryPolicy,\n asRng,\n defaultRetryPolicy,\n initRetry,\n nextDelayMs,\n type RetryState,\n recordFailure,\n shouldRetry,\n} from \"../../../retry-backoff\";\nimport type { IdempotencyStore } from \"../../idempotency/idempotency\";\nimport { idempotencyMemory } from \"../../idempotency/idempotency/adapter\";\nimport { type DeadlineSub, deadlineSub } from \"../../resilience/deadline\";\n\n/**\n * The poller knob's config — the single object you hand `createPoller`.\n *\n * `State` is the consumer's WHOLE Model (so `until` can read any field), `R` is\n * the shape of one tick observation (`lastResult` carries it forward).\n */\nexport interface PollerConfig<State, R> {\n /**\n * The steady cadence, in milliseconds, between successful ticks. The next\n * tick is armed at the absolute target `at + everyMs` (computed from the\n * `at` the prior tick's Msg carried), NOT `everyMs` from when the Sub\n * happens to be reconciled — so the cadence does not drift across resumes.\n */\n readonly everyMs: number;\n /**\n * The stop predicate, read against the consumer's whole Model. When it\n * returns `true`, the poller is DONE: `subs` returns `[]` (the timer\n * disarms) and no further tick is scheduled. Pure — it must not read the\n * clock or mutate; the substrate calls it inside `subscriptions(state)`.\n */\n readonly until: (state: State) => boolean;\n /**\n * The effect to run on each tick — the actual \"go observe the source\" Cmd\n * (a fetch, a status read, a list call). The knob returns it from\n * `tickResult` when the run continues; the consumer's `interpret` performs\n * it and routes the observation back as the next tick-result Msg.\n *\n * Nullary by contract: a tick carries no per-call argument (the poller\n * re-reads the same source every cadence). Capture any target in the Cmd\n * literal the consumer's `onTick` returns.\n */\n readonly onTick: () => Cmd;\n /**\n * Backoff policy for FAILED ticks. Omit to use `defaultRetryPolicy`\n * (full-jitter, 5 attempts). A success resets the retry counter, so the\n * policy only governs consecutive failures.\n *\n * Any bound the `../retry-backoff` union admits: a count (`RetryPolicy`), a\n * wall-clock outage budget (`DurationRetryPolicy`), or explicit\n * `unbounded: true`. The duration bound needs no extra wiring here — every\n * failure already arrives through `tickErr(state, error, at)` carrying the\n * instant it was observed, so the streak clock is fed from the Msg's own\n * data and the poller never reads a clock of its own (invariant 2).\n */\n readonly retry?: AnyRetryPolicy;\n /**\n * Optional dedupe key derived from a tick result. When provided, a result\n * whose key was already `seen` records the observation but emits NO fresh\n * `onTick` follow-up — the side effect runs once per distinct observation.\n * Omit to treat every tick result as fresh (no dedupe). The dedupe store is\n * bounded by `dedupeTtlMs` if set; otherwise it grows with distinct keys.\n */\n readonly dedupeKey?: (result: R) => string;\n /**\n * TTL for the dedupe store, in milliseconds. Only meaningful when\n * `dedupeKey` is set. An observation older than `dedupeTtlMs` is forgotten,\n * so a key seen long ago is treated as fresh again. Omit for an unbounded\n * dedupe window (every distinct key remembered for the poller's lifetime).\n */\n readonly dedupeTtlMs?: number;\n}\n\n/**\n * The bookkeeping every poller phase carries in common, split out so each arm of\n * the `PollerState` discriminated union names only what it adds (`nextAtMs` on\n * `polling`) — the same discipline the sibling `PaginatorState` uses.\n *\n * - `tick` — count of ticks recorded so far (success or failure). Doubles\n * as an observability cursor and a stable per-tick discriminant.\n * - `lastResult` — the most recent successful observation, or `undefined`\n * before the first success. `until` typically reads it (via the\n * consumer's Model), but the knob never interprets it.\n * - `retry` — the `../retry-backoff` counter for consecutive failures.\n * Reset to `initRetry()` on every success. Once a failure has\n * been recorded it is a `TimedRetryState` (it carries the\n * streak's `firstFailureAtMs`, minted from `tickErr`'s `at`);\n * the field is typed at the `RetryState` supertype because a\n * poller that has never failed has no streak, and a slice\n * persisted before the origin existed rehydrates without one.\n * - `dedupe` — the `../idempotency` store backing `dedupeKey`. An empty,\n * unbounded store when `dedupeKey` is unset (never written).\n */\ninterface PollerCore<R> {\n readonly tick: number;\n readonly lastResult?: R;\n readonly retry: RetryState;\n readonly dedupe: IdempotencyStore<true>;\n}\n\n/**\n * The Model field the poller knob owns — its visible slice (the knob principle:\n * managed state lives in the Model, never a closure, so it is durable and\n * replayable). A discriminated union on `phase` so the armed-timer target lives\n * ONLY where it is meaningful and impossible combinations are unrepresentable\n * (pattern 11), the sibling `PaginatorState` idiom:\n *\n * - `polling` — ticks are scheduled. Carries `nextAtMs`, the ABSOLUTE target\n * the interval/backoff timer is armed against (persisted so a\n * resumed poller re-arms the same moment), or `null` before the\n * first `start` primes it.\n * - `done` — `until` held; the poll is finished. Carries NO `nextAtMs` — a\n * finished poll can never sit on an armed target.\n * - `gave_up` — backoff exhausted `maxAttempts`. Carries NO `nextAtMs` either.\n *\n * Because only `polling` carries `nextAtMs`, `subs` guards on `phase` alone to\n * decide whether a timer is desired — a `done`/`gave_up` state with a live target\n * (the old flat record's hazard) simply cannot be built.\n */\nexport type PollerState<R> =\n | (PollerCore<R> & {\n readonly phase: \"polling\";\n readonly nextAtMs: number | null;\n })\n | (PollerCore<R> & { readonly phase: \"done\" })\n | (PollerCore<R> & { readonly phase: \"gave_up\" });\n\n/**\n * The three arms, named — so a verb can DECLARE the phases it can actually\n * reach instead of the whole union.\n *\n * A verb whose return type is the full `PollerState<R>` tells a caller nothing\n * about where the poller went, and a caller that needs to know (an exhaustive\n * `switch`, say) has to re-derive it by reading the verb's body. Every one of these narrowings is already true of the\n * implementation — `start` only ever builds a `polling` arm, `tickResult` never\n * builds `gave_up`, `tickErr` never builds `done` — so naming them costs\n * nothing at runtime and moves a fact out of the source and into the signature.\n */\nexport type PollerPolling<R> = Extract<PollerState<R>, { phase: \"polling\" }>;\nexport type PollerDone<R> = Extract<PollerState<R>, { phase: \"done\" }>;\nexport type PollerGaveUp<R> = Extract<PollerState<R>, { phase: \"gave_up\" }>;\n\n/**\n * The poller Sub type — a `../deadline` Sub under a fixed id family. One id per\n * knob instance keeps the reconcile pass from churning the timer: the same id\n * across transitions means \"same armed deadline\", even as `nextAtMs` advances.\n */\nexport type PollerSub = DeadlineSub;\n\n/**\n * The Sub id the poller arms its tick deadline under, keyed on the absolute\n * target. The id ROTATES per target because a one-shot deadline timer is\n * exhausted once it fires and the substrate reconciles subs by `id` alone: a\n * fixed id would leave the fired timer registered and never re-arm, so the\n * cadence would die after exactly one tick. Encoding `atMs` in the id makes each\n * cadence/backoff target a distinct identity — the reconcile pass retires the\n * spent timer and arms the next — while a resumed poller re-arms the SAME id\n * from its persisted `nextAtMs` (eviction is idempotent).\n *\n * A single poller machine arms exactly one tick timer at a time; a consumer\n * running several pollers on one machine namespaces them by composing the knob\n * under distinct slices (a future multi-poller config would thread a prefix).\n */\nfunction pollerSubId(atMs: number): string {\n return `poller:tick:${atMs}`;\n}\n\n/**\n * The knob handle returned by `createPoller`. Spread its hooks into your\n * machine: `init()` seeds the slice, `start(...)` arms the first tick,\n * `tickResult` / `tickErr` are the two update verbs, and `subs(...)` returns the\n * timer Sub while the poller is live.\n *\n * Pure-ops + subs module: there is no `handlers(ports)` cell. The poller's I/O\n * is the consumer's own `onTick` Cmd run by the consumer's `interpret` — the\n * knob never owns a port. (Compare `../deadline`, which ships a `subscribe`\n * cell; the poller reuses `../deadline`'s, so it has nothing of its own to\n * splice into `interpret`.)\n */\nexport interface Poller<\n // State is a phantom-style parameter — present so consumers can spell\n // `Poller<MyState, MyResult>` matching `createPoller<State, R>`. It is\n // consumed by the config's `until` predicate, not by any handle method, so\n // it does not appear in the interface body. Same discipline as\n // `BoundMachine`'s `Ctx`.\n // biome-ignore lint/correctness/noUnusedVariables: phantom type parameter (see above)\n State,\n R,\n> {\n /** Seed the Model slice. Idle until `start(...)` arms the first tick. */\n init(): PollerPolling<R>;\n /**\n * Arm the first tick. `at` is the current clock (carried in from the Msg /\n * runtime that kicks the poller off — never read inside the verb). Returns\n * the slice with the first deadline target set to `at + everyMs` and emits NO\n * Cmd. The cadence has ONE source — the deadline Sub — so `start` does not\n * perform the first observation itself (an immediate `onTick` here would race\n * the timer and poll as fast as the source responds). The first observation\n * fires when the deadline crosses `at + everyMs` and the consumer routes\n * `deadline_exceeded` → `tick`.\n */\n start(\n state: PollerState<R>,\n at: number,\n ): readonly [PollerPolling<R>, readonly Cmd[]];\n /**\n * Perform one observation — the cadence verb. The consumer routes the\n * deadline Sub's `deadline_exceeded` Msg here; `tick` emits the single\n * `config.onTick()` Cmd that goes and reads the source. This is the ONLY\n * next-tick mechanism: the timer fires, the consumer calls `tick`, the fetch\n * runs, and the observation comes back through `tickResult` / `tickErr`\n * (which re-arm the next deadline). A no-op on a finished poller — a stale\n * deadline fire racing a terminal transition the reconcile pass has not yet\n * retired emits nothing.\n *\n * Takes no `at`: `tick` does not touch the schedule (the just-fired deadline\n * is exhausted; the next target is set when the result lands), so it needs no\n * clock — keeping it trivially pure.\n */\n tick(state: PollerState<R>): readonly [PollerState<R>, readonly Cmd[]];\n /**\n * Record a successful tick observation at clock `at`.\n *\n * - Resets the retry counter (a success clears consecutive-failure state).\n * - Stores `result` as `lastResult` and bumps `tick`.\n * - Re-arms the next tick at the absolute target `at + everyMs` (the steady\n * cadence). It emits NO cadence `onTick` — the next observation fires from\n * the deadline Sub via `tick`, never immediately from a result.\n * - Dedupe (opt-in, orthogonal to cadence): when `dedupeKey` is set, a FRESH\n * observation emits one `onTick` FOLLOW-UP (the consumer's \"run the\n * downstream side effect once per distinct observation\" hook) and a\n * DUPLICATE key records the sighting but suppresses the follow-up. With no\n * `dedupeKey`, `tickResult` emits nothing — the cadence `tick` is the only\n * `onTick`, so an unconfigured poller never double-fetches.\n * - UNLESS `untilHeld` is `true` (the consumer evaluated `config.until`\n * against the post-result Model) — then the poller enters `\"done\"`,\n * disarms (`nextAtMs: null`), and emits no Cmd, dedupe or otherwise.\n *\n * `untilHeld` is passed in rather than computed here because `until` reads\n * the consumer's WHOLE Model, which this verb does not hold — the consumer\n * evaluates it at the call site after folding `result` into its Model and\n * passes the boolean. (`subs` re-checks `phase` to decide arming, so a\n * mis-passed `untilHeld` cannot leave a \"done\" poller arming timers.)\n */\n tickResult(\n state: PollerState<R>,\n result: R,\n at: number,\n untilHeld: boolean,\n ): readonly [PollerPolling<R> | PollerDone<R>, readonly Cmd[]];\n /**\n * Record a FAILED tick at clock `at`. Backs off instead of holding the\n * steady cadence:\n *\n * - Advances the retry counter (`recordFailure`).\n * - If `shouldRetry` still permits another attempt, arms the next tick at\n * `at + nextDelayMs(retry, policy)` (the backoff curve) and emits NO Cmd —\n * the retry observation fires when that backoff deadline crosses and the\n * consumer routes `deadline_exceeded` → `tick`. The timer is the single\n * next-tick mechanism, on the backoff curve here instead of `everyMs`.\n * - If backoff is exhausted (`!shouldRetry`), enters `\"gave_up\"`, disarms\n * (`nextAtMs: null`), and emits no Cmd.\n *\n * `at` is both the backoff anchor AND the streak clock: it is passed to\n * `recordFailure` (starting / preserving `firstFailureAtMs`) and to\n * `shouldRetry`, so a `DurationRetryPolicy` on `config.retry` is honoured\n * with no extra wiring. Under a duration bound the poller keeps retrying\n * however many attempts the outage takes, and stops at the declared\n * wall-clock budget measured from the streak's FIRST failure.\n *\n * The backoff jitter uses the `rng` injected ONCE at `createPoller` (default\n * `Math.random` at the effect boundary, a fixed value in tests); the verb\n * body never names the global RNG, so a poller built with a fixed `rng`\n * replays a failure-and-backoff run bit-for-bit.\n */\n tickErr(\n state: PollerState<R>,\n error: unknown,\n at: number,\n ): readonly [PollerPolling<R> | PollerGaveUp<R>, readonly Cmd[]];\n /**\n * The pre-wired subscriptions cell. Returns the single tick-deadline Sub\n * while the poller is `\"polling\"` with an armed `nextAtMs`; returns `[]`\n * once `\"done\"` / `\"gave_up\"` (the timer disarms) or before `start`. Assign\n * directly: `subscriptions: (s) => poll.subs(s.poll)`.\n *\n * The `DeadlineSub` it returns is consumed by `../deadline`'s\n * `subscribeDeadline` cell, which the consumer wires into `subscribe` —\n * the poller does not redraw the timer lifecycle.\n */\n subs(state: PollerState<R>): readonly Sub[];\n}\n\n/**\n * Build a poller knob from `config`. Returns the hook bag to spread into a\n * machine (see the module doc-comment for the wiring). Pure factory — no clock\n * read, no timer; everything happens when the consumer calls the returned\n * verbs / `subs` with an injected `at`.\n *\n * `rng` is injected ONCE here (default `Math.random` at the effect boundary, a\n * fixed value in tests) and threaded internally into the backoff jitter. No\n * verb body ever names the global RNG, so a poller built with a fixed `rng`\n * replays a failure-and-backoff run bit-for-bit (invariant 2: the verbs are\n * pure given the injected `rng`).\n */\nexport function createPoller<State, R>(\n config: PollerConfig<State, R>,\n rng: () => number = Math.random,\n): Poller<State, R> {\n // Re-affirm the `[0, 1)` contract at the seam where the injected generator\n // enters the backoff math (brand from `../retry-backoff`). The factory's\n // public param stays a plain `() => number` so transitive callers are\n // unchanged; `asRng` is the single point where it's branded for `nextDelayMs`.\n const rngBranded = asRng(rng);\n const policy: AnyRetryPolicy = config.retry ?? defaultRetryPolicy;\n\n // The dedupe store seam, bound once. The poller delegates its dedupe-window\n // reads (`memory.isSeen`) and the per-sighting touch (`memory.remember`) to\n // the verbs, so the `IdempotencyStore` shape stays insulated.\n const memory = idempotencyMemory<true>();\n\n function init(): PollerPolling<R> {\n return {\n phase: \"polling\",\n tick: 0,\n retry: initRetry(),\n nextAtMs: null,\n // The dedupe store is created regardless; it is only WRITTEN when\n // `dedupeKey` is set, so an unconfigured poller carries an inert empty\n // store (no per-op cost, JSON-serializable, durable like the rest of\n // the slice).\n dedupe: memory.init({ ttlMs: config.dedupeTtlMs }),\n };\n }\n\n function start(\n state: PollerState<R>,\n at: number,\n ): readonly [PollerPolling<R>, readonly Cmd[]] {\n // Arm the first deadline at `at + everyMs` and emit NOTHING. The cadence has\n // ONE source — the `everyMs` deadline Sub. `start` does not perform the\n // first observation itself: that would be a second, immediate next-tick\n // mechanism racing the timer (it would fire as fast as the source responds,\n // never honoring `everyMs`). The first observation fires when the deadline\n // crosses `at + everyMs` and the consumer routes `deadline_exceeded` → the\n // `tick` verb (which emits `onTick`). No drift, no double-fire. Build the\n // `polling` arm explicitly so a (re)start from a terminal state adopts a live\n // target rather than spreading a terminal arm that never had one.\n return [\n {\n phase: \"polling\",\n tick: state.tick,\n lastResult: state.lastResult,\n retry: state.retry,\n nextAtMs: at + config.everyMs,\n dedupe: state.dedupe,\n },\n [],\n ];\n }\n\n function tick(\n state: PollerState<R>,\n ): readonly [PollerState<R>, readonly Cmd[]] {\n // The deadline fired. Perform the observation — this is the ONLY place the\n // `onTick` Cmd is emitted, so the timer is the single next-tick mechanism.\n // No schedule change here: the just-fired deadline is exhausted, and the\n // NEXT target is re-armed when the observation lands (`tickResult` /\n // `tickErr`). A no-op on a finished poller (a stale fire racing a terminal\n // transition the reconcile pass has not yet retired).\n if (state.phase !== \"polling\") return [state, []];\n return [state, [config.onTick()]];\n }\n\n function tickResult(\n state: PollerState<R>,\n result: R,\n at: number,\n untilHeld: boolean,\n ): readonly [PollerPolling<R> | PollerDone<R>, readonly Cmd[]] {\n // A success always clears consecutive-failure state and records the datum.\n // The next arm is built explicitly (not spread from `state`) so `done`\n // carries no `nextAtMs` — a finished poll can never sit on an armed target.\n const tick = state.tick + 1;\n\n // Stop condition first: if the consumer's `until` held against the\n // post-result Model, we are DONE — disarm and emit nothing, regardless of\n // dedupe (the final observation is still recorded as `lastResult`).\n if (untilHeld) {\n return [\n {\n phase: \"done\",\n tick,\n lastResult: result,\n retry: initRetry(),\n dedupe: state.dedupe,\n },\n [],\n ];\n }\n\n // Re-arm the steady cadence: the next observation fires when THIS deadline\n // (`at + everyMs`) crosses and the consumer routes `deadline_exceeded` →\n // `tick`. `tickResult` itself never emits the cadence `onTick` — the timer\n // is the single next-tick mechanism (recording a result is not a reason to\n // immediately re-fetch; that would poll as fast as the source responds).\n const next: PollerPolling<R> = {\n phase: \"polling\",\n tick,\n lastResult: result,\n retry: initRetry(),\n nextAtMs: at + config.everyMs,\n dedupe: state.dedupe,\n };\n\n // Dedupe is an OPT-IN follow-up, orthogonal to the cadence above. When\n // `dedupeKey` is set, a FRESH observation emits one `onTick` follow-up (the\n // consumer's \"run the downstream side effect once per distinct observation\"\n // hook); a DUPLICATE key records the sighting but suppresses that follow-up.\n // With no `dedupeKey` there is no follow-up at all — the cadence `tick` is\n // the only `onTick`, so an unconfigured poller never double-fetches.\n if (!config.dedupeKey) return [next, []];\n\n const key = config.dedupeKey(result);\n const suppress = memory.isSeen(next.dedupe, key, at);\n // `remember` refreshes the key's TTL clock on every sighting (the\n // idempotency \"touch\" semantics), so a steadily-repeating observation never\n // ages out mid-poll. The stored value is the unit `true` — the poller only\n // needs presence, not a payload.\n const deduped: PollerPolling<R> = {\n ...next,\n dedupe: memory.remember(next.dedupe, key, true, at),\n };\n return [deduped, suppress ? [] : [config.onTick()]];\n }\n\n function tickErr(\n state: PollerState<R>,\n error: unknown,\n at: number,\n ): readonly [PollerPolling<R> | PollerGaveUp<R>, readonly Cmd[]] {\n // `at` is the failure's OBSERVATION instant, already carried in from the\n // Msg — so it doubles as the streak clock a duration bound is measured\n // against. The first failure of a streak sets `firstFailureAtMs`; every\n // later one preserves it, and a success resets to `initRetry()` (dropping\n // the origin with it). Nothing here reads a clock: `at` is Msg data,\n // exactly as `rng` is factory-injected data (invariant 2).\n const retry = recordFailure(state.retry, error, at);\n const tick = state.tick + 1;\n\n // Backoff exhausted → give up: emit nothing. `shouldRetry` reads the\n // just-advanced `retry`, so under a count bound the (maxAttempts)-th\n // failure is the one that stops the poller, and under a duration bound the\n // first failure observed at or past `firstFailureAtMs + maxElapsedMs` is.\n // The `gave_up` arm carries no `nextAtMs` — there is no next attempt to arm.\n if (!shouldRetry(retry, policy, at)) {\n return [\n {\n phase: \"gave_up\",\n tick,\n lastResult: state.lastResult,\n retry,\n dedupe: state.dedupe,\n },\n [],\n ];\n }\n\n // Back off: arm the next attempt at `at + backoff(retry)` rather than the\n // steady cadence, and emit NOTHING. The retry observation fires when this\n // backoff deadline crosses and the consumer routes `deadline_exceeded` →\n // `tick` — the timer is the single next-tick mechanism, on the backoff\n // curve here instead of `everyMs`. `rng` is the value injected once at\n // `createPoller`; the verb body never names the global RNG, so a fixed\n // `rng` makes the backoff target replay bit-for-bit.\n const delayMs = nextDelayMs(retry, policy, rngBranded);\n return [\n {\n phase: \"polling\",\n tick,\n lastResult: state.lastResult,\n retry,\n nextAtMs: at + delayMs,\n dedupe: state.dedupe,\n },\n [],\n ];\n }\n\n function subs(state: PollerState<R>): readonly Sub[] {\n // Arm the tick deadline only while live. `phase` is the authority (so a\n // mis-passed `untilHeld` into `tickResult` cannot resurrect a finished\n // poller); `nextAtMs` is the absolute target `../deadline` translates to a\n // remaining delay at subscribe time — a resumed poller re-arms the exact\n // persisted moment.\n if (state.phase !== \"polling\" || state.nextAtMs === null) return [];\n // The Sub id ROTATES with the target. A one-shot deadline timer is\n // exhausted once it fires, and the substrate's reconcile pass keys identity\n // by `id` alone — a fixed id would leave the fired timer in the registry and\n // NEVER re-arm for the next cadence (cadence dies after one tick). Folding\n // `nextAtMs` into the id makes each successive target a distinct identity:\n // the reconcile pass retires the spent timer (old id absent from the desired\n // set) and arms the next one (new id). A resumed poller re-arms the SAME id\n // from its persisted `nextAtMs`, so eviction is idempotent.\n return [deadlineSub(pollerSubId(state.nextAtMs), state.nextAtMs)];\n }\n\n return { init, start, tick, tickResult, tickErr, subs };\n}\n","/**\n * internal/flow/reconciler — the desired-vs-actual sync loop (the \"fleet-sync /\n * coverage-gap\" shape): walk the ACTUAL world end to end, diff it against the\n * DESIRED spec, then apply each resulting `Change` one at a time until the two\n * agree. The control-plane reconcile pattern (Kubernetes controllers, fleet\n * config rollout, accessibility coverage-gap remediation) lifted to the uniform\n * L2 knob contract.\n *\n * ## The recipe (which bricks it composes)\n *\n * - **`../paginated-walk`** owns the SCAN. The actual world is rarely a single\n * fetch — it is a paginated list (every node in a fleet, every page of an\n * audit, every row of a table). `reconciler` does not re-implement that walk:\n * it embeds a `paginated-walk` slice and lets it sequence the actual-state\n * fetch (gated, retried, rate-limited, resumable across eviction). The walk's\n * own `onPage` hook stays empty (`() => []`) — `reconciler` accumulates each\n * fetched page's items into the running `actual` snapshot inside its OWN\n * `pageOk` verb, where it holds its slice and so can extend the accumulator\n * the walk cannot see; when the walk reports `isComplete`, the full actual\n * snapshot is in hand.\n * - **`../cache`** owns the APPLIED ledger. Every `Change` that settles is\n * written into a TTL cache keyed by the change's id, so a re-`applyNext`\n * after an eviction skips changes already applied (idempotent re-apply — the\n * reconcile is safe to resume from any point). The cache is the durable\n * \"what have I already done?\" memory the apply loop reads before re-issuing.\n *\n * Because the scan IS a `paginated-walk` slice (which itself IS a\n * `resilient-call` slice), this knob **inherits that contract verbatim**: the\n * slice is flat plain data, every verb returns `readonly [State, Cmd[]]`, time\n * is always an `at` parameter, and the jitter RNG is injected once at\n * `createReconciler(config, rng)` — never read inside a verb (the spec:\n * `reconciler` *extends* `paginated-walk`).\n *\n * ## Why the run lifecycle is INLINE (run-tracker not extracted)\n *\n * The reconcile phase union (`idle` / `scanning` / `applying` / `done` /\n * `failed`) and its bookkeeping (`plan`, `appliedCursor`, the `actual`\n * accumulator) live directly on this slice rather than behind a `run-tracker`\n * sub-knob — exactly as `monitored-run` keeps its lifecycle inline. Extraction\n * earns its keep when two independent axes vary; here the lifecycle has one\n * anchoring axis (this reconcile pass). The genuinely independent axes — the\n * paginated SCAN and the applied LEDGER — ARE extracted (`../paginated-walk`,\n * `../cache`). The lifecycle is the glue that sequences scan → plan → apply.\n *\n * ## The two non-negotiables (canon)\n *\n * - **Durable** — the slice is plain data: the paginated-walk slice, the\n * accumulated `actual` items, the planned `Change[]`, the applied cursor, and\n * the applied-ledger cache (all JSON-serializable). A reconcile survives DO\n * eviction mid-scan or mid-apply and resumes from the exact position.\n * - **Replayable** — every transition is a verb returning new state + Cmds.\n * `diff` / `apply` are pure config functions applied at the verb boundary;\n * the Cmds they yield are plain data. `replay` reconstructs the whole pass\n * exactly. Nothing here closes over time or RNG.\n *\n * ## Where the clock / RNG live\n *\n * Inside the verbs: nowhere. `at` arrives on `scan` / `pageOk` / `pageErr` /\n * `applied` / `onTimer` and threads into the underlying paginated-walk gate (so a\n * retried / rate-limited page measures backoff from that `at`) and into the\n * applied-ledger cache writes. The jitter RNG is injected at construction. The\n * only clock read is `Date.now()` inside the inherited paginated-walk `handlers`\n * port (the effect boundary).\n *\n * ## Typical wiring\n *\n * const rec = createReconciler<FleetNode, NodeSpec, Page, SyncChange, ApplyCmd>({\n * desired: targetSpecs, // the spec to converge on\n * firstPage: null, // actual-list page-one sentinel\n * nextCursor: (page) => page.next ?? null,\n * itemsOf: (page) => page.nodes, // page → actual items\n * diff: (desired, actual) => planChanges(desired, actual),\n * apply: (change) => ({ type: \"apply_change\", change }),\n * idOf: (change) => change.nodeId, // applied-ledger key\n * rateLimit: { capacity: 10, refillPerSec: 5 },\n * retry: defaultRetryPolicy,\n * });\n *\n * // in the machine:\n * init: () => [{ rec: rec.init() }, []],\n * update: {\n * reconcile: (s, m) => lift(s, rec.scan(s.rec, m.at)),\n * page_ok: (s, m) => lift(s, rec.pageOk(s.rec, m.result, m.at)),\n * page_err: (s, m) => lift(s, rec.pageErr(s.rec, m.error, m.at)),\n * change_done: (s, m) => lift(s, rec.applied(s.rec, m.change, m.at)),\n * retry_due: (s, m) => lift(s, rec.onTimer(s.rec, m)),\n * },\n * subscriptions: (s) => rec.subs(s.rec),\n * subscribe: { deadline: subscribeDeadline },\n * interpret: rec.handlers({ run: (cursor) => api.listActual(cursor) }),\n */\n\nimport type { Cmd } from \"../../../index\";\nimport type { RetryPolicy } from \"../../../retry-backoff\";\nimport {\n createPaginatedWalk,\n type DeadlineSub,\n deadlineSub,\n type FetchPageCmd,\n PAGE_KEY,\n type PageErrMsg,\n type PageOkMsg,\n type PaginatedWalkState,\n type PaginatedWalkTimerMsg,\n subscribeDeadline,\n} from \"../../paginate/paginated-walk\";\nimport {\n get as cacheGet,\n set as cacheSet,\n initCache,\n type TtlCache,\n} from \"../../resilience/cache\";\nimport type {\n CircuitConfig,\n DeadlineConfig,\n RateLimitConfig,\n ResilientPorts,\n} from \"../../resilience/resilient-call\";\n\n// ===========================================================================\n// Config — the knob. `desired` / `diff` / `apply` / `idOf` describe the\n// reconcile; the SCAN knobs (firstPage / nextCursor / itemsOf) describe how the\n// actual world is walked; the resilience bricks are inherited from\n// paginated-walk (every one optional — omit a brick, omit its gate).\n// ===========================================================================\n\n/**\n * The reconciler knob. Generic in:\n * - `Actual` — one item of the ACTUAL world (a fleet node, an audited page, a\n * table row). The scan accumulates these.\n * - `Desired` — the DESIRED spec value the diff converges toward. Opaque to\n * this module; only `diff` reads it.\n * - `Page` — the shape one actual-list page fetch resolves with.\n * - `Change` — one unit of remediation the diff produces and `apply` realizes.\n * - `ApplyCmd`— the Cmd `apply(change)` yields (the effect that mutates the\n * actual world toward desired).\n *\n * `diff` / `apply` / `idOf` / `nextCursor` / `itemsOf` are PURE config functions\n * applied at the verb boundary, never stored in the slice or in a Cmd (Cmds are\n * plain data, not closures). The resilience bricks (`retry` / `circuit` /\n * `rateLimit` / `deadline`) are the SAME optional knobs `paginated-walk` /\n * `resilient-call` expose — reconciler extends them; `rateLimit` keeps the scan\n * from 429-ing the upstream listing API.\n */\nexport interface ReconcilerConfig<\n Actual,\n Desired,\n Page,\n Change,\n ApplyCmd extends Cmd,\n Cursor = number,\n> {\n /**\n * The DESIRED spec to converge on. Held verbatim and handed to `diff` once the\n * scan completes. Any JSON-serializable value — a list of specs, a target map,\n * a single target object — `diff` alone interprets it.\n */\n readonly desired: Desired;\n /**\n * Compute the remediation plan: the ordered `Change[]` that moves `actual` to\n * `desired`. Called once when the scan finishes (the full actual snapshot is in\n * hand). An empty plan means \"already in sync — nothing to apply\". PURE +\n * consumer-specific (only the consumer knows the domain's reconcile rules).\n */\n readonly diff: (\n desired: Desired,\n actual: readonly Actual[],\n ) => readonly Change[];\n /**\n * Realize one `Change` as the Cmd that mutates the actual world. Returns plain\n * data (a `{ type, ... }` Cmd the consumer's interpret handler performs).\n * PURE — the side effect happens when the runtime performs the emitted Cmd,\n * never here.\n */\n readonly apply: (change: Change) => ApplyCmd;\n /**\n * Stable identity for a `Change` — the applied-ledger cache key. A re-`applyNext`\n * after eviction (or after a re-plan) skips a change whose id is already in the\n * ledger (idempotent re-apply). MUST be a property of the change itself, NOT its\n * position in the plan: the ledger has to survive re-planning. When omitted the\n * default keys by the change's serialized CONTENT (`JSON.stringify(change)`) —\n * a stable per-change identity that is unchanged by where the change sits in the\n * plan. Supply a domain id (the target node id, the resource key) when one\n * exists; it is cheaper than serializing and dedupes two changes that differ\n * only in fields irrelevant to identity. PURE.\n *\n * Why NOT positional: keying by index silently drops changes on the documented\n * re-plan path. After applying the index-0 change, its `\"0\"` ledger entry would\n * match WHATEVER different, never-applied change lands at index 0 in the next\n * plan — the apply loop skips it as \"already done\". Identity must be intrinsic\n * to the change so the ledger means \"this change settled\", not \"slot N settled\".\n */\n readonly idOf?: (change: Change) => string;\n\n // --- scan knobs (the actual-world walk), inherited from paginated-walk ---\n /**\n * The cursor the actual-list scan fetches first. For an offset API typically\n * `0`; for a token API whatever sentinel the API treats as page one.\n */\n readonly firstPage: Cursor;\n /**\n * Extract the next scan cursor from a fetched page — a `Cursor` to keep\n * scanning, or `null` when the actual listing is exhausted (scan finishes,\n * plan computed). PURE + consumer-specific.\n */\n readonly nextCursor: (page: Page) => Cursor | null;\n /**\n * Extract the actual items from one fetched page. Each page's items are\n * appended to the running `actual` accumulator. PURE.\n */\n readonly itemsOf: (page: Page) => readonly Actual[];\n\n // --- resilience bricks, inherited from paginated-walk (all optional) ---\n /** Exponential-backoff retry policy for a transient scan-page failure. */\n readonly retry?: RetryPolicy;\n /** Circuit breaker around the scan fetch (one upstream → one breaker). */\n readonly circuit?: CircuitConfig;\n /** Token-bucket rate limit on the scan — the \"don't 429 the listing API\" knob. */\n readonly rateLimit?: RateLimitConfig;\n /** Overall wall-clock deadline per individual scan-page fetch. */\n readonly deadline?: DeadlineConfig;\n}\n\n// ===========================================================================\n// Slice — the Model field this knob owns. The paginated-walk scan slice + the\n// accumulated actual snapshot + the inline reconcile lifecycle (plan, applied\n// cursor, ledger). All flat plain data.\n// ===========================================================================\n\n/**\n * Reconcile lifecycle phase. Discriminated on `phase`:\n *\n * - `idle` — created, never scanned. `scan` starts the actual-world walk.\n * - `scanning` — the paginated-walk is traversing the actual listing; pages\n * fold into `actual` as they arrive. The scan owns the `walk`\n * sub-slice; this phase ends when the walk finishes.\n * - `applying` — the scan finished, `diff` produced the `plan`, and changes are\n * being applied one at a time. `appliedCursor` is the index of\n * the next change to apply.\n * - `done` — every planned change applied (or an empty plan: already in\n * sync). Terminal.\n * - `failed` — the scan failed terminally (the page-fetch retries were\n * exhausted / a deadline fired). `error` carries why. Terminal.\n */\nexport type ReconcilePhase =\n | \"idle\"\n | \"scanning\"\n | \"applying\"\n | \"done\"\n | \"failed\";\n\n/**\n * The slice. Plain data end to end:\n * - `phase` — the lifecycle discriminant.\n * - `walk` — the `../paginated-walk` scan slice (cursor + resilience).\n * Drives the actual-world traversal; POSITION survives\n * eviction.\n * - `actual` — the accumulated actual items, appended page by page during\n * the scan. The full snapshot `diff` is computed against.\n * - `plan` — the `Change[]` `diff` produced. Empty until the scan\n * finishes; the apply loop walks it by `appliedCursor`.\n * - `appliedCursor` — index of the NEXT change to apply (0 ≤ cursor ≤ plan.length).\n * `cursor === plan.length` means every change applied.\n * - `applied` — the applied-ledger cache: `idOf(change) → change`, written\n * as each change settles. The idempotency memory the apply\n * loop reads to skip already-applied changes after eviction.\n */\nexport interface ReconcilerState<Actual, Change, Page, Cursor = number> {\n readonly phase: ReconcilePhase;\n readonly walk: PaginatedWalkState<Cursor, Page>;\n readonly actual: readonly Actual[];\n readonly plan: readonly Change[];\n readonly appliedCursor: number;\n readonly applied: TtlCache<Change>;\n}\n\n// ===========================================================================\n// Cmds + Msgs the knob speaks. The scan emits the inherited page-fetch effect;\n// the apply loop emits the consumer's `apply(change)` Cmds.\n// ===========================================================================\n\n/**\n * The actual-list page-fetch effect: the inherited `resilient_run` Cmd from\n * paginated-walk, whose `input` is the `Cursor` to fetch and whose `key` is the\n * fixed `PAGE_KEY`. The consumer's `handlers(ports)` interprets it.\n */\nexport type ScanPageCmd<Cursor> = FetchPageCmd<Cursor>;\n\n/** Page-settled Msgs the scan `handlers` port dispatches back (inherited verbatim). */\nexport type ScanPageOkMsg<Page> = PageOkMsg<Page>;\nexport type ScanPageErrMsg = PageErrMsg;\n\n/** The scan retry / deadline timer Msg — inherited from paginated-walk. */\nexport type ReconcilerTimerMsg = PaginatedWalkTimerMsg;\n\n/**\n * Ports the consumer supplies to `handlers`. `run(cursor)` fetches ONE page of\n * the ACTUAL listing for the given cursor; throwing routes to `pageErr` (and\n * thus the scan backoff). Same shape as paginated-walk's port.\n */\nexport interface ReconcilerPorts<Cursor, Page>\n extends ResilientPorts<Cursor, Page> {}\n\n// ===========================================================================\n// The knob factory.\n// ===========================================================================\n\n/**\n * Build a reconciler knob from `config`. `rng` is injected for the underlying\n * scan-retry jitter — pass a fixed `() => 0` in tests to pin backoff; defaults\n * to `Math.random` (read at the verb boundary inside resilient-call, never in a\n * reconciler verb). Inherited straight from paginated-walk.\n *\n * Returns the uniform L2 knob contract: `init()`, the verbs `scan` / `pageOk` /\n * `pageErr` / `planned` / `applyNext` / `applied` / `onTimer`, the derived\n * `isComplete`, `subs(state)`, and `handlers(ports)`.\n */\nexport function createReconciler<\n Actual,\n Desired,\n Page,\n Change,\n ApplyCmd extends Cmd = Cmd,\n Cursor = number,\n>(\n config: ReconcilerConfig<Actual, Desired, Page, Change, ApplyCmd, Cursor>,\n rng: () => number = Math.random,\n) {\n type State = ReconcilerState<Actual, Change, Page, Cursor>;\n // The combined Cmd type the verbs can emit: the inherited scan page-fetch\n // effect plus whatever `apply(change)` yields.\n type OutCmd = ScanPageCmd<Cursor> | ApplyCmd;\n\n // The scan is a paginated-walk over the actual listing. We feed it the scan\n // cursor knobs + the resilience bricks; `onPage` is OURS — it is a pure marker\n // (we accumulate items in `pageOk` instead, where we hold the reconciler\n // slice). The walk's `Page` payload is the consumer's `Page`; the reconciler\n // slice stores the walk as `PaginatedWalkState<Cursor, unknown>` so its own\n // type does not have to thread `Page` (the page never lands in the slice — only\n // the extracted `actual` items do).\n const walk = createPaginatedWalk<Cursor, Page, never>(\n {\n firstPage: config.firstPage,\n nextCursor: config.nextCursor,\n // The walk's per-page hook emits no Cmds — the reconciler accumulates the\n // page's items itself in `pageOk` (where it holds its own slice), so the\n // walk's onPage stays empty.\n onPage: () => [],\n retry: config.retry,\n circuit: config.circuit,\n rateLimit: config.rateLimit,\n deadline: config.deadline,\n },\n rng,\n );\n\n /**\n * The applied-ledger key for a change. Custom `idOf` when supplied; otherwise\n * the change's serialized CONTENT — a stable per-change identity. NEVER the\n * positional index: an index-keyed ledger drops a never-applied change that\n * happens to land at a slot a different, already-applied change once occupied\n * (the re-plan defect). Identity is intrinsic to the change, so the ledger\n * means \"this change settled\", surviving a re-plan that reorders the slots.\n */\n function changeId(change: Change): string {\n return config.idOf ? config.idOf(change) : JSON.stringify(change);\n }\n\n /** Replace the walk sub-slice, leaving the rest of the reconciler untouched. */\n function withWalk(s: State, w: State[\"walk\"]): State {\n return { ...s, walk: w };\n }\n\n /** The starting slice: idle, fresh walk + empty accumulator / plan / ledger. */\n function init(): State {\n return {\n phase: \"idle\",\n walk: walk.init(),\n actual: [],\n plan: [],\n appliedCursor: 0,\n applied: initCache<Change>(),\n };\n }\n\n // === Verb: scan ==========================================================\n\n /**\n * Begin the reconcile: start the paginated walk over the ACTUAL world and\n * enter `scanning`. Issues the first scan-page fetch (gated through the\n * inherited resilience). A no-op on any non-`idle` phase — re-scanning a\n * reconcile already in flight would restart the actual walk and double-count,\n * so a stray `scan` is absorbed. PURE — `at` threads into the fetch gate.\n */\n function scan(s: State, at: number): readonly [State, readonly OutCmd[]] {\n if (s.phase !== \"idle\") return [s, []];\n const [w, cmds] = walk.start(s.walk, at);\n const next: State = { ...s, phase: \"scanning\", walk: w };\n return [next, cmds];\n }\n\n // === Verb: pageOk ========================================================\n\n /**\n * Record a successfully fetched actual-list `page`: append its items to the\n * `actual` accumulator and advance the walk. When the walk finishes (the\n * listing is exhausted), the full actual snapshot is in hand → compute the\n * plan (`planned`) and start applying. PURE — `at` is the scan clock.\n *\n * A stray `pageOk` while not `scanning` (a late duplicate after the scan\n * completed) is absorbed by the walk (no cursor advance) and contributes no\n * items — the reconcile never re-accumulates after the plan is computed.\n */\n function pageOk(\n s: State,\n page: Page,\n at: number,\n ): readonly [State, readonly OutCmd[]] {\n // Once we are past scanning, the actual snapshot is frozen — absorb stray pages.\n if (s.phase !== \"scanning\") {\n const [w] = walk.pageOk(s.walk, page, at);\n return [withWalk(s, w), []];\n }\n\n const [w, walkCmds] = walk.pageOk(s.walk, page, at);\n const actual = [...s.actual, ...config.itemsOf(page)];\n const scanned: State = { ...s, walk: w, actual };\n\n // The walk emits the next scan-page fetch while it stays fetching. When it\n // finishes (done / paused with no fetch), `walkCmds` is empty.\n const cmds: readonly OutCmd[] = walkCmds;\n\n // Scan exhausted → plan + begin applying. `walk.isComplete` is the honest\n // \"the API returned a null next cursor\" signal.\n if (walk.isComplete(scanned.walk)) {\n const [plannedState, applyCmds] = planned(scanned, at);\n return [plannedState, [...cmds, ...applyCmds]];\n }\n\n return [scanned, cmds];\n }\n\n // === Verb: pageErr =======================================================\n\n /**\n * Record a failed scan-page fetch and back off via the inherited resilience:\n * schedule a retry (the scan cursor stays parked — no advance) or, once the\n * page-fetch retries are exhausted, the underlying call settles `failed`. When\n * the scan call is terminally failed, the whole reconcile enters `failed`.\n * PURE — `at` stamps the breaker trip + the retry-delay base.\n */\n function pageErr(\n s: State,\n error: unknown,\n at: number,\n ): readonly [State, readonly OutCmd[]] {\n const [w, cmds] = walk.pageErr(s.walk, error, at);\n let next = withWalk(s, w);\n // The page-fetch call settling `failed` (retries exhausted) is a terminal\n // scan failure → the reconcile cannot trust an incomplete actual snapshot.\n if (\n s.phase === \"scanning\" &&\n w.resilience.calls[PAGE_KEY]?.phase === \"failed\"\n ) {\n next = { ...next, phase: \"failed\" };\n }\n return [next, cmds];\n }\n\n // === Verb: planned =======================================================\n\n /**\n * Compute the remediation plan from the accumulated `actual` snapshot and the\n * configured `desired`, store it, and enter `applying`. Normally driven\n * internally by `pageOk` when the scan finishes, but exposed as a\n * verb so a consumer can force planning from an externally-supplied actual\n * snapshot (e.g. a single-shot actual fetch outside the paginated scan), or\n * re-plan after a desired change. An empty plan settles straight to `done`\n * (already in sync). PURE — `at` only stamps the (empty) apply-loop clock.\n *\n * `changes` is optional: omit it to diff the slice's own accumulated `actual`\n * against `config.desired`; pass an explicit plan to install it directly\n * (skipping the diff — the consumer computed it elsewhere).\n */\n function planned(\n s: State,\n at: number,\n changes?: readonly Change[],\n ): readonly [State, readonly OutCmd[]] {\n const plan = changes ?? config.diff(config.desired, s.actual);\n const planning: State = {\n ...s,\n phase: \"applying\",\n plan,\n appliedCursor: 0,\n };\n return applyNext(planning, at);\n }\n\n // === Verb: applyNext =====================================================\n\n /**\n * Emit the apply Cmd for the next not-yet-applied change in the plan, skipping\n * any whose id is already in the applied ledger (idempotent re-apply after\n * eviction). Advances `appliedCursor` past skipped + the emitted change. When\n * the cursor reaches the end of the plan, settles `done`. A no-op unless\n * `applying`. PURE — `at` is read only for the ledger lookup clock; `idOf`\n * keys the skip check.\n *\n * Emits at most ONE apply Cmd per call (the loop is sequential: each `applied`\n * drives the next `applyNext`). This keeps the actual-world mutation\n * one-at-a-time, matching a controller's serial reconcile.\n */\n function applyNext(\n s: State,\n at: number,\n ): readonly [State, readonly OutCmd[]] {\n if (s.phase !== \"applying\") return [s, []];\n\n let cursor = s.appliedCursor;\n // Skip changes already in the ledger (a resumed reconcile re-issues from the\n // cursor but must not re-apply what already settled).\n while (cursor < s.plan.length) {\n const change = s.plan[cursor];\n // `cursor < plan.length` guarantees an element under normal indexing; the\n // explicit `undefined` narrow (vs a non-null assertion) keeps the access\n // typed without a suppression and tolerates a sparse hole by skipping it.\n if (change === undefined) {\n cursor++;\n continue;\n }\n const id = changeId(change);\n if (cacheGet(s.applied, id, at) === undefined) {\n // This change is not yet applied — emit its Cmd and park the cursor here\n // (it advances to cursor+1 only once `applied` confirms the change).\n const advanced: State = { ...s, appliedCursor: cursor };\n return [advanced, [config.apply(change)]];\n }\n cursor++;\n }\n\n // Every change applied → reconcile complete.\n const done: State = { ...s, phase: \"done\", appliedCursor: cursor };\n return [done, []];\n }\n\n // === Verb: applied =======================================================\n\n /**\n * Record that `change` finished applying: write it into the applied ledger,\n * advance the cursor past it, and drive the next `applyNext`. PURE — `at` is\n * the ledger-write clock (the entry never expires in practice; a large TTL\n * keeps the idempotency window open for the reconcile's lifetime).\n *\n * `change` is the SAME change the consumer's apply handler settled (echoed back\n * on the settle Msg) — its id is computed from the change's own identity (NOT a\n * cursor position), so the ledger key matches the skip check in `applyNext`\n * regardless of where the change sits in the plan. A no-op unless `applying` (a\n * late settle after `done` is ignored). PURE.\n */\n function applied(\n s: State,\n change: Change,\n at: number,\n ): readonly [State, readonly OutCmd[]] {\n if (s.phase !== \"applying\") return [s, []];\n const id = changeId(change);\n // A very large TTL: the ledger entry must outlive the whole reconcile pass.\n // `get(..., at)` treats it as fresh for `at < expiresAtMs`, which holds for\n // any realistic reconcile (the cache exists to dedupe within one pass).\n const applied = cacheSet(\n s.applied,\n id,\n change,\n at,\n Number.MAX_SAFE_INTEGER,\n );\n const advanced: State = {\n ...s,\n applied,\n appliedCursor: s.appliedCursor + 1,\n };\n return applyNext(advanced, at);\n }\n\n // === Verb: onTimer =======================================================\n\n /**\n * A scan retry / deadline timer fired. Defers to paginated-walk's `onTimer`: a\n * retry timer re-issues the SAME scan-page fetch (re-fetching the parked\n * cursor); a deadline timer settles the scan call failed. A deadline-driven\n * terminal scan failure escalates the whole reconcile to `failed`. A stale fire\n * is a pure no-op (inherited identity). PURE.\n */\n function onTimer(\n s: State,\n msg: ReconcilerTimerMsg,\n ): readonly [State, readonly OutCmd[]] {\n const [w, cmds] = walk.onTimer(s.walk, msg);\n if (w === s.walk) {\n // Inherited no-op identity → keep our slice identity too.\n return [s, []];\n }\n let next = withWalk(s, w);\n if (\n s.phase === \"scanning\" &&\n w.resilience.calls[PAGE_KEY]?.phase === \"failed\"\n ) {\n next = { ...next, phase: \"failed\" };\n }\n return [next, cmds];\n }\n\n // === Derived predicate ===================================================\n\n /**\n * Whether the reconcile has fully settled — every planned change applied (or an\n * empty plan: already in sync). PURE, read-only. Lets a consumer's reducer fire\n * a \"reconcile complete\" Cmd without re-checking the phase by hand.\n */\n function isComplete(s: State): boolean {\n return s.phase === \"done\";\n }\n\n // === Subs ================================================================\n\n /**\n * Pre-wired subscriptions: exactly the scan's paginated-walk subs — a retry\n * timer while a scan page is `waiting_retry`, and (with the `deadline` brick) a\n * per-page deadline timer while a scan fetch is active. The apply loop emits no\n * timers (each apply settles via the consumer's own Msg), so once the scan\n * finishes the desired sub set empties. Reconciled by id; wire `subscribe: {\n * deadline: subscribeDeadline }` (re-exported below).\n */\n function subs(s: State): readonly DeadlineSub[] {\n return walk.subs(s.walk);\n }\n\n // === Handlers ============================================================\n\n /**\n * Pre-wired interpret handler for the scan page-fetch effect. Inherited from\n * paginated-walk (`resilient_run`): wraps the consumer's `run(cursor)` actual-\n * list port via `tryInterpret` (Railway) — success → `resilient_ok` (handled by\n * `pageOk`), failure → `resilient_err` (handled by `pageErr`), each stamped\n * with `Date.now()` at the effect boundary (the ONE permitted clock read).\n *\n * interpret: rec.handlers({ run: (cursor) => api.listActual(cursor) })\n *\n * The apply-Cmd side is the CONSUMER's interpret handler (it knows how to\n * realize `apply(change)`); the consumer routes its settle Msg back through\n * `applied`. This knob only owns the scan's interpret cell.\n */\n function handlers(ports: ReconcilerPorts<Cursor, Page>) {\n return walk.handlers(ports);\n }\n\n return {\n init,\n scan,\n pageOk,\n pageErr,\n planned,\n applyNext,\n applied,\n onTimer,\n isComplete,\n subs,\n handlers,\n };\n}\n\n/**\n * Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the slice\n * lives at `state.rec`. Convenience for the common single-slice host; hosts with\n * a differently-named field spread by hand. PURE — a thin record rebuild, no\n * clock / RNG.\n */\nexport function liftReconciler<\n S extends { rec: ReconcilerState<Actual, Change, Page, Cursor> },\n Actual,\n Change,\n Page,\n Cursor,\n C extends Cmd,\n>(\n state: S,\n [slice, cmds]: readonly [\n ReconcilerState<Actual, Change, Page, Cursor>,\n readonly C[],\n ],\n): readonly [S, readonly C[]] {\n return [{ ...state, rec: slice }, cmds];\n}\n\n/**\n * Re-export the deadline Sub primitives (inherited from paginated-walk) so\n * consumers wire one import: `subscribeDeadline` is the `subscribe` cell,\n * `deadlineSub` builds the Sub literal this knob's `subs` emits.\n */\nexport { subscribeDeadline, deadlineSub };\nexport type { DeadlineSub };\n","/**\n * @packageDocumentation\n * internal/flow/saga — a forward-then-compensate transaction over an ordered list\n * of reversible steps.\n *\n * The Level-2 combinator for \"run these N steps in order; if any step fails,\n * undo the steps that already succeeded, in reverse.\" It is the distributed-\n * transaction / compensation knob: each step is a `{ do, undo }` pair of Cmds,\n * the saga drives `do` forward one step at a time, and on the first failure it\n * pivots and drives `undo` backward over exactly the steps that completed.\n *\n * **Boundary with the workflow module (`../workflow/`) — the compensation\n * test.** Both drive\n * an ordered multi-step transaction with reverse-order compensation; the line\n * between them is whether every step carries a true inverse. Here\n * `SagaStep<D, U>` REQUIRES both `do` and `undo` — a step without its inverse\n * is unrepresentable, so full reversibility is a type-level guarantee.\n * Workflow's `WorkflowStep.compensation` is OPTIONAL — an irreversible step (a\n * sent email) is skipped during the unwind. Pick by the test: **every step\n * must be reversible → saga; some steps are irreversible but the run must\n * finish → workflow.** Cross to workflow when the transaction includes steps\n * that can't be undone (or when you want each activity recorded as a durable\n * owed effect on the `../do` ledger); stay here when the type system should\n * enforce that every step can be undone.\n *\n * The recipe (which bricks it composes):\n * - `../work-queue/adapter` — the saga's forward progress IS a work-queue\n * lifecycle. Each step's record carries the same `{ id, status, input }`\n * vocabulary (`pending → running → done | failed | cancelled`), so the step\n * taxonomy is the substrate's status enum rather than a parallel invention.\n * We reuse the pure `QueueItem` / `QueueItemStatus` types AND delegate every\n * status flip to the `QueueAdapter` verbs: `wq.enqueue` stamps each fresh\n * ledger record, and `wq.patch` performs every\n * `pending → running → done | failed | cancelled` transition. The status\n * transitions are NOT re-rolled here — they live in exactly one place\n * behind the adapter, per the package's one-shape rule. The async\n * `createQueue(store)` adapter is NOT used: its `load → mutate → save` reads\n * the clock and lives at an I/O boundary, while a combinator's verbs must be\n * pure (invariant 2). We bind the same ops to the in-Model ledger instead —\n * durable + replayable, the two non-negotiables every knob preserves.\n *\n * The compensation log is the spec's `done: StepId[]` — the indices of the\n * steps that completed forward, in the order they completed. On `stepErr` the\n * saga walks that log in reverse, emitting one `undo` per `undoOk`, so the\n * unwind is the exact mirror of the wind. If an `undo` ITSELF fails, `undoErr`\n * pivots to the terminal `compensation_failed` phase: a failed compensation is\n * a real-world fact (a refund that bounced, a hold that won't release) that the\n * consumer must see and reconcile by hand — never a saga wedged in\n * `compensating` forever.\n *\n * Typical wiring (combinator form — splice the hooks into your machine):\n *\n * const saga = createSaga<BookFlight | ChargeCard | ..., Cancel | Refund | ...>({\n * steps: [\n * { do: { type: \"book_flight\" }, undo: { type: \"cancel_flight\" } },\n * { do: { type: \"charge_card\" }, undo: { type: \"refund_card\" } },\n * { do: { type: \"reserve_hotel\" },undo: { type: \"release_hotel\" } },\n * ],\n * });\n *\n * // in `update`:\n * begin: (s) => lift(s, saga.start(s.saga)),\n * step_ok: (s) => lift(s, saga.stepOk(s.saga)),\n * step_err: (s, m) => lift(s, saga.stepErr(s.saga, m.error)),\n * undo_ok: (s) => lift(s, saga.undoOk(s.saga)),\n * undo_err: (s, m) => lift(s, saga.undoErr(s.saga, m.error)),\n *\n * Every verb is PURE: it returns a NEW slice plus the Cmds to perform (the next\n * `do` going forward, or the next `undo` rolling back). The reducer never reads\n * a clock or RNG — step identity is positional (the index into `config.steps`),\n * so progress survives a round-trip through the durable slice and resumes\n * exactly where it left off after a DO eviction.\n *\n * There is no `subs` and no `handlers`: a saga runs no timers, and the `do` /\n * `undo` Cmds are fully caller-defined (the consumer's own `interpret` performs\n * each effect and routes Ok/Err back to the `stepOk` / `stepErr` / `undoOk`\n * verbs — the same shape `resilient-fetch` uses with `tryInterpret`). The saga\n * owns the ORDER; the consumer owns the I/O. Pure-ops module, like\n * `retry-backoff`.\n *\n * NOT a substrate primitive: it depends only on `../work-queue`'s pure types\n * and the core `Cmd` type. Internal since #48 — not published on any subpath;\n * reached from inside the package as `internal/flow/saga`.\n */\n\nimport type { Cmd } from \"../../../index\";\nimport type { QueueItem, QueueItemStatus } from \"../../work-queue\";\nimport { queueAdapter } from \"../../work-queue/adapter\";\n\n/**\n * A step's stable identity. Positional: the 0-based index into\n * `config.steps`. Positional ids are PURE (no clock, no RNG) and survive a\n * round-trip through the durable slice, so `done` can be replayed to resume an\n * interrupted saga exactly. The compensation log is a list of these.\n */\nexport type StepId = number;\n\n/**\n * One step of the saga: the forward effect and its compensating inverse, both\n * as data (plain Cmds). `do` runs while winding forward; `undo` runs while\n * unwinding after a failure. The pair is the unit of reversibility — a step\n * that completed (`do` succeeded) is exactly a step whose `undo` must run if a\n * later step fails.\n */\nexport interface SagaStep<D extends Cmd, U extends Cmd> {\n /** The forward effect, performed while the saga winds forward. */\n readonly do: D;\n /** The compensating inverse, performed (in reverse) while the saga unwinds. */\n readonly undo: U;\n}\n\n/**\n * The knob. The ordered list of reversible steps. The list is fixed for the\n * life of one saga instance (a saga drives a known transaction); per-run inputs\n * ride on the consumer's Msgs, not here.\n */\nexport interface SagaConfig<D extends Cmd, U extends Cmd> {\n /** The steps, in forward order. `do` runs `0 → n-1`; `undo` runs the completed prefix `n-1 → 0`. */\n readonly steps: readonly SagaStep<D, U>[];\n}\n\n/**\n * The lifecycle phase of a saga, narrowed at the type level so a consumer can\n * branch on `state.phase` (and a Transitions-table reducer can key on it).\n *\n * - `\"idle\"` — created, not started. No step has run.\n * - `\"running\"` — winding forward; `position` is the in-flight step.\n * - `\"compensating\"` — a step failed; unwinding `done` in reverse.\n * - `\"committed\"` — every step completed forward. Terminal success.\n * - `\"aborted\"` — compensation finished (every completed step undone, or\n * the first step itself failed with nothing to undo).\n * Terminal failure, fully unwound.\n * - `\"compensation_failed\"` — an `undo` itself failed mid-rollback. Terminal\n * failure, PARTIALLY unwound: the steps still in `done`\n * were never compensated and must be reconciled by hand.\n * Distinguished from `aborted` precisely so a stuck\n * rollback is visible state, not a saga wedged in\n * `compensating` forever.\n */\nexport type SagaPhase =\n | \"idle\"\n | \"running\"\n | \"compensating\"\n | \"committed\"\n | \"aborted\"\n | \"compensation_failed\";\n\n/**\n * The slice this knob owns.\n *\n * The spec's three fields are load-bearing:\n * - `position` — the index of the step currently in flight while `running`,\n * or the index being compensated while `compensating`. Survives eviction,\n * so `boot` resumes mid-saga from the durable slice.\n * - `done` — the compensation log: the ids of steps that completed forward,\n * in completion order. `undo` walks this in reverse. This is the single\n * source of truth for what must be unwound.\n * - `compensating` — the direction bit. `false` while winding forward, `true`\n * once a failure has pivoted the saga into rollback.\n *\n * Plus:\n * - `phase` — the derived lifecycle tag (see `SagaPhase`). Kept in the slice\n * (not recomputed) so a consumer's view and Transitions reducer can key on\n * `state.phase` directly, and the terminal states (`committed` / `aborted`)\n * are explicit facts rather than \"position past the end\" arithmetic.\n * - `error` — the forward failure that triggered compensation, carried\n * forward verbatim (`unknown`) for the consumer to read, never interpreted\n * (same discipline as `retry-backoff`'s `lastError` and `fan-out`'s\n * `error`).\n * - `compensationError` — the failure of an `undo` itself, set only when the\n * saga reaches `compensation_failed`. Kept distinct from `error` (the\n * forward failure) so a consumer reconciling a stuck rollback can read both\n * \"what broke the transaction\" and \"which compensation then bounced\".\n * Carried verbatim, never interpreted, same as `error`.\n * - `items` — the work-queue ledger, one `QueueItem` per step, keyed by the\n * step's positional id. The single source of truth for each step's status;\n * `phase` / `position` / `done` are the projection the verbs keep in\n * lockstep with it.\n *\n * Every field is `readonly` and JSON-serializable (plain numbers, arrays, and\n * the work-queue's plain `QueueItem` records), so the slice round-trips through\n * a consumer's `Store<S>` unchanged — durable across DO eviction.\n */\nexport interface SagaState<I = StepId> {\n /** The step in flight (`running`) or being compensated (`compensating`). */\n readonly position: number;\n /** The compensation log: ids of completed-forward steps, in completion order. */\n readonly done: readonly StepId[];\n /** Direction bit: `false` winding forward, `true` unwinding. */\n readonly compensating: boolean;\n /** The derived lifecycle tag (see `SagaPhase`). */\n readonly phase: SagaPhase;\n /** The forward failure that triggered compensation, if any. Carried, never interpreted. */\n readonly error?: unknown;\n /** The failure of an `undo` itself (only when `compensation_failed`). Carried, never interpreted. */\n readonly compensationError?: unknown;\n /** The work-queue ledger: one record per step, keyed by positional id. */\n readonly items: readonly QueueItem<I>[];\n}\n\n/** Whether the saga has terminated successfully (every step committed). */\nexport function isCommitted<I>(state: SagaState<I>): boolean {\n return state.phase === \"committed\";\n}\n\n/** Whether the saga has terminated in failure, fully unwound (every completed step undone). */\nexport function isAborted<I>(state: SagaState<I>): boolean {\n return state.phase === \"aborted\";\n}\n\n/**\n * Whether the saga has terminated in failure with an UNFINISHED rollback: an\n * `undo` itself failed, so some completed steps were never compensated and need\n * hand reconciliation. Terminal, but distinct from `aborted` (fully unwound).\n */\nexport function isCompensationFailed<I>(state: SagaState<I>): boolean {\n return state.phase === \"compensation_failed\";\n}\n\n/**\n * Whether the saga has reached a terminal phase (success, fully-unwound\n * failure, or compensation-failed). Derived — reads the slice, never mutates.\n * Consumers branch their own phase off this; no further verb has any effect\n * once it holds (the verbs guard on phase and no-op).\n */\nexport function isSettled<I>(state: SagaState<I>): boolean {\n return (\n state.phase === \"committed\" ||\n state.phase === \"aborted\" ||\n state.phase === \"compensation_failed\"\n );\n}\n\n/**\n * The starting slice: idle, nothing run, winding-forward direction. `items` is\n * empty until `start` stamps one ledger record per configured step — the slice\n * is generic in the ledger payload `I`, defaulting to the positional `StepId`\n * since a saga's \"input\" per step is just its index (the consumer's real inputs\n * ride on its own Msgs).\n */\nexport function initSaga<I = StepId>(): SagaState<I> {\n return {\n position: 0,\n done: [],\n compensating: false,\n phase: \"idle\",\n items: [],\n };\n}\n\n/**\n * Build the saga knob from `config`. Returns the uniform combinator contract:\n * `init` for the owned slice and the five lifecycle verbs (`start`, `stepOk`,\n * `stepErr`, `undoOk`, `undoErr`).\n *\n * No `subs` and no `handlers` — a saga runs no timers, and each step's `do` /\n * `undo` effect is owned by the consumer's `interpret` (the saga emits the Cmd;\n * the consumer performs it and routes the outcome back to a verb). The saga's\n * sole job is the ORDER: which Cmd to emit next, and when to pivot from winding\n * to unwinding (and when a failed `undo` ends the rollback). Pure-ops module —\n * matches `retry-backoff`'s shape.\n */\nexport function createSaga<D extends Cmd, U extends Cmd>(\n config: SagaConfig<D, U>,\n) {\n // The ledger seam, bound once. The saga delegates ledger construction to\n // `wq.enqueue` and every status flip to `wq.patch`, so the `QueueItem<StepId>`\n // shape stays insulated behind the verbs.\n const wq = queueAdapter<StepId>();\n\n /**\n * One ledger record per configured step, keyed by its positional id. Each\n * record is stamped by the `QueueAdapter`'s `enqueue` (the saga delegates\n * ledger construction to the verb rather than building records inline).\n *\n * The positional id is stringified — `QueueItem.id` is a string, the saga's\n * step identity is the index; `String(index)` keeps both the ledger's\n * string-id contract and the positional identity. `enqueuedAt` is `0`: saga\n * verbs are pure and the saga makes no timestamp-based decision (ordering is\n * positional), so there is no clock to read here.\n */\n function freshLedger(): QueueItem<StepId>[] {\n let items: QueueItem<StepId>[] = [];\n config.steps.forEach((_step, index) => {\n items = wq.enqueue(items, index, 0, String(index)).next;\n });\n return items;\n }\n\n /**\n * Flip the ledger record for step `index` to `status`, delegating the\n * transition to the `QueueAdapter`'s `patch` (keyed by the record's string\n * id, `String(index)`) so the status flip is NOT re-rolled here. PURE —\n * `patch` returns a new array; an unknown id returns a copy unchanged (the\n * verbs guard against out-of-range, but the helper is total).\n */\n function setStatus(\n items: readonly QueueItem<StepId>[],\n index: number,\n status: QueueItemStatus,\n ): QueueItem<StepId>[] {\n return wq.patch(items, String(index), (item) => ({\n ...item,\n status,\n })).next;\n }\n\n /**\n * The step at `index`, or `undefined` if out of range. Centralizes the bounds\n * check so the verbs read a step through a narrowing guard instead of a\n * non-null assertion: `const step = stepAt(i); if (step === undefined) …`.\n */\n function stepAt(index: number): SagaStep<D, U> | undefined {\n return config.steps[index];\n }\n\n /** The most-recently-completed step id (tail of `done`), or `undefined` if the log is empty. */\n function lastDone(done: readonly StepId[]): StepId | undefined {\n return done[done.length - 1];\n }\n\n /**\n * Begin the saga: stamp a `pending` ledger record per step, mark step 0\n * `running`, and emit step 0's `do` Cmd. PURE.\n *\n * A saga with zero configured steps commits immediately (nothing to do, so\n * the empty transaction trivially succeeds) and emits no Cmd. Calling `start`\n * on an already-started saga (phase ≠ `\"idle\"`) is a no-op: the slice is\n * returned unchanged with no Cmds, so a stray re-`start` after a boot/replay\n * can't relaunch step 0 on top of an in-flight saga.\n */\n function start(\n state: SagaState<StepId>,\n ): readonly [SagaState<StepId>, readonly D[]] {\n if (state.phase !== \"idle\") return [state, []];\n\n const items = freshLedger();\n const first = stepAt(0);\n if (first === undefined) {\n // Empty transaction: trivially committed, no effect.\n return [{ ...state, phase: \"committed\", items }, []];\n }\n\n const next: SagaState<StepId> = {\n ...state,\n position: 0,\n phase: \"running\",\n items: setStatus(items, 0, \"running\"),\n };\n return [next, [first.do]];\n }\n\n /**\n * Record the in-flight step as committed and advance. PURE.\n *\n * Flips the current step's ledger record `running → done`, appends its id to\n * the compensation log, and:\n * - if a next step exists, marks it `running` and emits its `do` Cmd;\n * - if this was the last step, transitions to `committed` (terminal\n * success) and emits no Cmd.\n *\n * `stepOk` while not `running` (idle, compensating, or already terminal) is a\n * no-op — the runtime's serial dispatch makes a true double-`stepOk`\n * impossible, but a stale success Msg after a boot/replay is real, and\n * swallowing it is the safe direction (the step's outcome is already recorded\n * in the ledger).\n */\n function stepOk(\n state: SagaState<StepId>,\n ): readonly [SagaState<StepId>, readonly D[]] {\n if (state.phase !== \"running\") return [state, []];\n\n const completed = state.position;\n const itemsDone = setStatus(state.items, completed, \"done\");\n const done = [...state.done, completed];\n const nextPosition = completed + 1;\n const nextStep = stepAt(nextPosition);\n\n if (nextStep === undefined) {\n // No next step — the last step committed, so the whole transaction\n // succeeded.\n return [{ ...state, done, items: itemsDone, phase: \"committed\" }, []];\n }\n\n const next: SagaState<StepId> = {\n ...state,\n position: nextPosition,\n done,\n items: setStatus(itemsDone, nextPosition, \"running\"),\n };\n return [next, [nextStep.do]];\n }\n\n /**\n * Pivot from winding to unwinding: the in-flight step failed. PURE.\n *\n * Flips the failed step's ledger record `running → failed`, records the\n * `error`, sets the direction bit, and begins compensation by emitting the\n * `undo` of the MOST-recently-completed step (the tail of the compensation\n * log) — rollback is the mirror of progress, so the last step that succeeded\n * is the first to be undone.\n *\n * If nothing completed forward (the first step itself failed), there is\n * nothing to compensate: the saga goes straight to `aborted` (terminal\n * failure) and emits no `undo`.\n *\n * `stepErr` while not `running` is a no-op (same stale-Msg reasoning as\n * `stepOk`): once a saga is already compensating or terminal, a late failure\n * Msg for an old step must not restart or re-pivot the unwind.\n */\n function stepErr(\n state: SagaState<StepId>,\n error: unknown,\n ): readonly [SagaState<StepId>, readonly U[]] {\n if (state.phase !== \"running\") return [state, []];\n\n const failed = state.position;\n const items = setStatus(state.items, failed, \"failed\");\n\n // Compensate the most-recently-completed step first. `lastDone === undefined`\n // means nothing completed forward (the first step itself failed) — there is\n // nothing to undo, so the saga aborts straight away. The guard narrows\n // `undoIndex` to `StepId` and `undoStep` to a present step without a\n // non-null assertion.\n const undoIndex = lastDone(state.done);\n const undoStep = undoIndex === undefined ? undefined : stepAt(undoIndex);\n if (undoIndex === undefined || undoStep === undefined) {\n return [\n { ...state, items, error, compensating: true, phase: \"aborted\" },\n [],\n ];\n }\n\n const next: SagaState<StepId> = {\n ...state,\n items,\n error,\n compensating: true,\n phase: \"compensating\",\n position: undoIndex,\n };\n return [next, [undoStep.undo]];\n }\n\n /**\n * Continue the rollback: the `undo` for the current compensation position\n * succeeded. PURE.\n *\n * Pops the just-undone step off the tail of the compensation log (flipping\n * its ledger record `done → cancelled` to mark it rolled back), and:\n * - if more completed steps remain, emits the next one's `undo` (continuing\n * in reverse) and moves `position` to it;\n * - if the log is now empty, transitions to `aborted` (terminal failure —\n * the saga is fully unwound) and emits no Cmd.\n *\n * `undoOk` while not `compensating` is a no-op (same stale-Msg reasoning as\n * the forward verbs): an `undo`-success Msg that arrives after the saga has\n * already finished unwinding must not pop a step that isn't there.\n */\n function undoOk(\n state: SagaState<StepId>,\n ): readonly [SagaState<StepId>, readonly U[]] {\n if (state.phase !== \"compensating\") return [state, []];\n\n // The tail of the log is the step we just compensated — mark it cancelled.\n // `undone === undefined` cannot happen while `compensating` (the phase is\n // only entered with a non-empty log), but the guard keeps the lookup total\n // and narrows `undone` to `StepId` without a non-null assertion.\n const undone = lastDone(state.done);\n if (undone === undefined) return [state, []];\n const remaining = state.done.slice(0, -1);\n const items = setStatus(state.items, undone, \"cancelled\");\n\n // The next step to compensate is the new tail of the log. `nextUndo`\n // narrows to `StepId` here and to a present step via `stepAt`, so the\n // continue-vs-terminate branch needs no non-null assertion.\n const nextUndo = lastDone(remaining);\n const nextStep = nextUndo === undefined ? undefined : stepAt(nextUndo);\n if (nextUndo === undefined || nextStep === undefined) {\n // Fully unwound — terminal failure.\n return [{ ...state, done: remaining, items, phase: \"aborted\" }, []];\n }\n\n const next: SagaState<StepId> = {\n ...state,\n done: remaining,\n items,\n position: nextUndo,\n };\n return [next, [nextStep.undo]];\n }\n\n /**\n * Halt the rollback: the `undo` for the current compensation position itself\n * FAILED. PURE.\n *\n * A failed compensation is a real-world fact — a refund that bounced, a hold\n * that won't release — and it must become visible terminal state, never leave\n * the saga wedged in `compensating` forever waiting for an `undoOk` that will\n * never come. So `undoErr`:\n * - flips the in-flight compensation step's ledger record `done → failed`\n * (its `undo` did not take, so it is NOT `cancelled`);\n * - records the undo failure in `compensationError` (distinct from `error`,\n * the forward failure that started the rollback);\n * - transitions to the terminal `compensation_failed` phase and emits no\n * Cmd. The compensation log is LEFT INTACT (`done` keeps the steps that\n * were never rolled back) so the consumer can see exactly which steps\n * still need hand reconciliation.\n *\n * `undoErr` while not `compensating` is a no-op (same stale-Msg reasoning as\n * the other verbs): an `undo`-failure Msg that arrives after the saga has\n * already settled must not re-pivot a terminal saga.\n */\n function undoErr(\n state: SagaState<StepId>,\n error: unknown,\n ): readonly [SagaState<StepId>, readonly U[]] {\n if (state.phase !== \"compensating\") return [state, []];\n\n // The step whose `undo` just failed is the current compensation position.\n // Its forward effect stands un-reversed, so its record goes `done → failed`,\n // not `cancelled`.\n const items = setStatus(state.items, state.position, \"failed\");\n return [\n {\n ...state,\n items,\n compensationError: error,\n phase: \"compensation_failed\",\n },\n [],\n ];\n }\n\n return {\n init: initSaga<StepId>,\n start,\n stepOk,\n stepErr,\n undoOk,\n undoErr,\n isCommitted,\n isAborted,\n isCompensationFailed,\n isSettled,\n };\n}\n","// ---------------------------------------------------------------------------\n// routeWorkflowMsg — the ONE WorkflowMsg → verb routing table.\n//\n// Two call sites fold a `WorkflowMsg` into a workflow's next step: the pure\n// replay `foldWorkflow` (a `switch`) and the durable grain's `defineMachine`\n// update map in `do.ts` (one cell per Msg tag). Both encode the SAME mapping\n// (`activity_ok` → `onActivityOk`, `activity_err` → `onActivityErr`,\n// `compensation_ok` → `onCompensationOk`, `compensation_err` →\n// `onCompensationErr`). Left duplicated, adding a fifth Msg variant meant\n// editing the routing decision in two places. This dispatcher owns the table\n// once; each call site delegates. The `switch` is exhaustive over the\n// `WorkflowMsg` union, so a new variant is a compile error here until routed.\n// ---------------------------------------------------------------------------\n\nimport type {\n Workflow,\n WorkflowMsg,\n WorkflowReducerStep,\n WorkflowState,\n} from \"./index\";\n\nexport function routeWorkflowMsg<A, R, F>(\n wf: Workflow<A, R, F>,\n state: WorkflowState<A, R, F>,\n msg: WorkflowMsg<R, F>,\n): WorkflowReducerStep<A, R, F> {\n switch (msg.type) {\n case \"activity_ok\":\n return wf.onActivityOk(state, msg);\n case \"activity_err\":\n return wf.onActivityErr(state, msg);\n case \"compensation_ok\":\n return wf.onCompensationOk(state, msg);\n case \"compensation_err\":\n return wf.onCompensationErr(state, msg);\n }\n}\n","/**\n * @packageDocumentation\n * internal/flow/workflow — the durable-workflow runtime core (#124, the first\n * Phase-1 slice of the Temporal-style durable-workflow engine, epic #118).\n *\n * A workflow is a long-running, multi-step transaction whose every step (an\n * **activity**) is a side effect that may evict the actor mid-flight. The\n * substrate already solves \"a state survives eviction\" (the event-sourced\n * store) and \"an owed effect survives eviction\" (the `do/` pending-effects\n * ledger, #67). This module composes those two into the third primitive: a\n * **pure TEA reducer over a workflow's progress**, where each step is dispatched\n * as a durable owed effect and the next step is decided only after the previous\n * one's result is folded back in. That is exactly Temporal's contract — a\n * deterministic workflow function whose activities are the only impurity, so a\n * replay of the event log re-decides every step identically.\n *\n * The mapping onto TEA, mirroring `../raft`:\n *\n * - **Reducer** — {@link createWorkflow}'s verbs (`init`, `onActivityOk`,\n * `onActivityErr`) are the transition function over {@link WorkflowState}.\n * PURE: they read no clock and no RNG. Wall time, randomness, retries — all\n * impurity lives in the consumer's injected *interpret cell* (the thing that\n * actually performs the activity `Cmd` and dispatches its result `Msg`).\n * A workflow driven by a recorded result schedule re-decides bit-for-bit —\n * the headline replay-determinism payoff (acceptance criterion 4).\n * - **Cmd** — the activity dispatch is an {@link ActivityCmd}, recorded on the\n * #67 ledger as an `effect_owed` BEFORE it is performed and `effect_confirmed`\n * on its result. This module emits the Cmd literals; it performs NO side\n * effects. The owed/confirmed events are persisted into the same log the\n * reducer folds, so the ledger (and thus \"which activity is still owed\")\n * rebuilds for free on cold wake — re-emit-on-wake is idempotent by the\n * ledger's monotonic delivery id (acceptance criterion 3).\n * - **Msg** — an activity result (`activity_ok` / `activity_err`) is a `Msg`\n * the consumer routes back into a verb. The verb folds the result, records\n * the completed step, and advances to the next activity (or to `completed`\n * when the sequence is exhausted).\n *\n * **Invalid states unrepresentable.** The in-flight activity (`current`, with\n * its delivery id) lives ONLY on the `running` variant of {@link WorkflowState}.\n * A `completed` workflow carries its final output and no current activity; a\n * `failed` one carries its failure and no current activity. So \"the current\n * activity exists only while running\" is a type-level guarantee, not a runtime\n * convention (acceptance criterion 1).\n *\n * **Boundary with the saga module (`../saga/`) — the compensation test.**\n * Both drive an\n * ordered multi-step transaction with reverse-order compensation (#125 here);\n * the line between them is whether every step carries a true inverse. Here\n * {@link WorkflowStep.compensation} is OPTIONAL — an irreversible step (a sent\n * email) is simply SKIPPED during the unwind, and the run still reaches a\n * terminal state. Saga's `SagaStep<D, U>` REQUIRES both `do` and `undo` — a\n * step without its inverse is unrepresentable, so full reversibility is a\n * type-level guarantee. Pick by the test: **every step must be reversible →\n * saga; some steps are irreversible but the run must finish → workflow.**\n * Cross to saga when you want the type system to enforce that every step can\n * be undone; stay here when the transaction includes steps that can't be.\n *\n * This module is the pure reducer only — like `../raft/index.ts` is the pure\n * Raft reducer with the DO grain deferred to its `./do` sibling (here #126).\n *\n * Generic over three opaque payloads, like raft's command generic: the activity\n * descriptor `A` (what a step asks to do — the consumer's interpret cell knows\n * how to perform it), the activity result `R`, and the failure `F`. The reducer\n * never inspects them; it only sequences them.\n *\n * NOT a substrate primitive: it depends only on the core `Cmd` type and the\n * `do` durable-effects ledger. Internal since #48 — not published on any\n * subpath; reached from inside the package as `internal/flow/workflow`.\n */\n\nimport { z } from \"zod\";\nimport {\n type DeliveryId,\n type EffectConfirmed,\n type EffectLedgerEvent,\n type EffectOwed,\n emptyLedger,\n foldLedger,\n type PendingEffectsLedger,\n pendingEffectsLedger,\n survivingEffects,\n} from \"../../../do/durable-effects\";\nimport { Cmd, type CmdOf } from \"../../../index\";\nimport { routeWorkflowMsg } from \"./route\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Steps — the static definition of a workflow.\n//\n// A workflow is defined by an ordered sequence of steps. A step is an activity\n// descriptor: a stable `name` (for readability + correlation in the event log)\n// plus the opaque `activity` payload the consumer's interpret cell performs.\n// Steps are inert data; the reducer walks them in order.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * One step of a workflow: a named activity descriptor. `A` is the opaque\n * payload the consumer's interpret cell knows how to perform (an HTTP call, a\n * sibling-grain message, a tool round-trip). The reducer never inspects\n * `activity` — it only sequences the steps and correlates results.\n *\n * A step may declare a **compensation** — the inverse activity that undoes the\n * forward one (cancel the reservation, refund the charge). Compensation is the\n * `{ do, undo }` pair of `../saga/` mapped onto the workflow: the step's\n * `activity` is the `do`, its `compensation` is the `undo`. The pair is the unit\n * of reversibility — a step that completed (its forward activity succeeded) is\n * exactly a step whose `compensation` must run, in reverse order, if a LATER\n * step fails (#125). A step WITHOUT a compensation contributes nothing to the\n * unwind: it is skipped during the reverse walk (an irreversible step — a sent\n * email — that the saga model treats as a no-op `undo`).\n */\nexport interface WorkflowStep<A> {\n /** Stable, human-readable step name — appears in the completed-step record. */\n readonly name: string;\n /** The opaque activity this step performs. Interpreted by the consumer. */\n readonly activity: A;\n /**\n * The opaque compensating (inverse) activity, performed in reverse order on a\n * downstream failure (#125). Optional: a step with no compensation is skipped\n * during the unwind. Interpreted by the consumer's interpret cell, exactly\n * like {@link activity}.\n */\n readonly compensation?: A;\n}\n\n/**\n * A workflow's step sequence at construction — a NON-EMPTY tuple. A workflow\n * with nothing to do reaches `completed` only by carrying a final result, and an\n * empty sequence produces none, so \"≥ 1 step\" is a precondition. Encoding it as\n * `readonly [WorkflowStep<A>, ...WorkflowStep<A>[]]` makes the empty case a\n * COMPILE error at every construction boundary (`init`, `foldWorkflow`,\n * `workflowGrain`) — parse-don't-validate, so the reducer never needs a runtime\n * throw to reject a resultless workflow.\n */\nexport type WorkflowSteps<A> = readonly [WorkflowStep<A>, ...WorkflowStep<A>[]];\n\n/**\n * A completed step: the step that ran plus the result its activity produced.\n * The `running` state accumulates these in execution order, so the full\n * forward history is available to the consumer (and to #125's compensation,\n * which will walk it in reverse).\n */\nexport interface CompletedStep<A, R> {\n readonly step: WorkflowStep<A>;\n readonly result: R;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// The in-flight activity — the bridge between the reducer and the #67 ledger.\n//\n// While `running`, exactly one activity is in flight. It carries the step it is\n// performing AND the monotonic `deliveryId` the #67 ledger issued for it. The\n// delivery id is the single correlation key: an `activity_ok`/`activity_err`\n// Msg names the id it answers, the reducer matches it against `current.id`, and\n// the ledger confirms that same id. Re-emit-on-wake re-fires the SAME id, so a\n// duplicate result is a no-op (idempotent by delivery id, acceptance crit. 3).\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** The activity currently in flight on a `running` workflow. */\nexport interface InFlightActivity<A> {\n /** The 0-based index of this step in the workflow's step sequence. */\n readonly index: number;\n /** The step whose activity is in flight. */\n readonly step: WorkflowStep<A>;\n /** The #67 ledger delivery id this activity was owed under (the dedup key). */\n readonly id: DeliveryId;\n}\n\n/**\n * The compensation currently in flight on a `compensating` workflow (#125). The\n * mirror of {@link InFlightActivity} for the reverse walk: exactly one\n * compensation is owed at a time, on the SAME #67 ledger, with its own monotonic\n * delivery id. `index` is the index (into `completed`/`steps`) of the step being\n * undone — the unwind walks these from high to low (strict reverse order).\n */\nexport interface InFlightCompensation<A> {\n /** The 0-based index (into the step sequence) of the step being compensated. */\n readonly index: number;\n /** The step whose compensation is in flight. */\n readonly step: WorkflowStep<A>;\n /** The #67 ledger delivery id this compensation was owed under (the dedup key). */\n readonly id: DeliveryId;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// WorkflowState — the discriminated union. Invalid states unrepresentable.\n//\n// `status` is the discriminant. The in-flight `current` activity exists ONLY on\n// `running` and `compensating`; `completed` carries the final `output`;\n// `failed` / `failed_compensated` / `compensation_failed` carry the failure.\n// There is no representable state with a current activity that is neither\n// running nor compensating, nor a terminal state still holding one\n// (acceptance crit. 1).\n//\n// The failure path (#125), mirroring `../saga/`'s phases:\n//\n// running ──activity_err with completed steps──▶ compensating\n// running ──activity_err with NO completed steps──▶ failed (empty rollback)\n// compensating ──all compensations confirmed──▶ failed_compensated\n// compensating ──a compensation itself fails──▶ compensation_failed\n//\n// `compensating` is the analogue of saga's `compensating`; `failed_compensated`\n// of saga's `aborted` (fully unwound); `compensation_failed` of saga's\n// `compensation_failed` (an `undo` bounced, partially unwound — visible state,\n// never a workflow wedged in `compensating` forever).\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * A workflow in progress. Carries the ordered `completed` steps (forward\n * history), the `steps` it is sequencing, and the `current` in-flight activity\n * (with its ledger delivery id). `completed.length === current.index` always\n * holds — the current activity is the next step after the last completed one.\n */\nexport interface RunningWorkflow<A, R> {\n readonly status: \"running\";\n /** The full, static step sequence this workflow runs. */\n readonly steps: readonly WorkflowStep<A>[];\n /** Steps that have produced a result, in execution order. */\n readonly completed: readonly CompletedStep<A, R>[];\n /** The single activity in flight right now. */\n readonly current: InFlightActivity<A>;\n}\n\n/**\n * A workflow that ran every step to completion. `output` is the result of the\n * final step — the workflow's overall output. No activity is in flight.\n */\nexport interface CompletedWorkflow<A, R> {\n readonly status: \"completed\";\n readonly steps: readonly WorkflowStep<A>[];\n /** Every step, in execution order, with its result. */\n readonly completed: readonly CompletedStep<A, R>[];\n /** The final step's result — the workflow's output. */\n readonly output: R;\n}\n\n/**\n * A workflow that failed on an activity with NOTHING to compensate — the\n * forward failure happened with zero completed steps (the first activity\n * failed). `failedStep` is the step whose activity reported the failure;\n * `failure` is the opaque failure payload. `completed` is empty by construction:\n * a failure WITH completed steps pivots into {@link CompensatingWorkflow}\n * instead, so `failed` is precisely the empty-rollback terminal (the analogue\n * of saga's `aborted` reached straight from the first step). No activity is in\n * flight; this is terminal (#125 acceptance criterion 3).\n */\nexport interface FailedWorkflow<A, R, F> {\n readonly status: \"failed\";\n readonly steps: readonly WorkflowStep<A>[];\n /** Empty by construction — a failure with completed steps compensates instead. */\n readonly completed: readonly CompletedStep<A, R>[];\n /** The step whose activity failed. */\n readonly failedStep: WorkflowStep<A>;\n /** The opaque failure the activity reported. */\n readonly failure: F;\n}\n\n/**\n * A workflow unwinding after a forward failure (#125): the compensations of the\n * `completed` steps are being emitted in STRICT REVERSE order, one at a time, on\n * the same #67 ledger. The analogue of saga's `compensating` phase.\n *\n * `current` is the single compensation in flight (the mirror of `running`'s\n * in-flight activity). `compensated` records, in unwind order, the completed\n * steps whose compensation has confirmed — the reverse-walk's progress log, so\n * a cold wake resumes mid-rollback exactly. `failedStep`/`failure` carry the\n * forward failure that triggered the unwind (verbatim, never interpreted),\n * preserved for the consumer to read and to fold onto the terminal state.\n *\n * Invariant: the unwind walks `completed` from its tail toward index 0, skipping\n * steps with no compensation, so `current.index` is strictly below the index of\n * every entry in `compensated`.\n */\nexport interface CompensatingWorkflow<A, R, F> {\n readonly status: \"compensating\";\n readonly steps: readonly WorkflowStep<A>[];\n /** The completed forward steps, in execution order — the history being unwound. */\n readonly completed: readonly CompletedStep<A, R>[];\n /** The step whose forward activity failed, triggering the unwind. */\n readonly failedStep: WorkflowStep<A>;\n /** The opaque forward failure that triggered the unwind. Carried, never interpreted. */\n readonly failure: F;\n /** The single compensation in flight right now. */\n readonly current: InFlightCompensation<A>;\n /** Completed steps whose compensation has confirmed, in unwind (reverse) order. */\n readonly compensated: readonly CompletedStep<A, R>[];\n}\n\n/**\n * A workflow that failed forward and then fully unwound: every completed step's\n * compensation confirmed, in reverse order. Terminal. The analogue of saga's\n * `aborted` (fully unwound) — named `failed_compensated` to align with #125's\n * vocabulary. No activity or compensation is in flight.\n */\nexport interface FailedCompensatedWorkflow<A, R, F> {\n readonly status: \"failed_compensated\";\n readonly steps: readonly WorkflowStep<A>[];\n /** The forward steps that completed (and were each compensated), in execution order. */\n readonly completed: readonly CompletedStep<A, R>[];\n /** The step whose forward activity failed, triggering the (now-finished) unwind. */\n readonly failedStep: WorkflowStep<A>;\n /** The opaque forward failure that triggered compensation. Carried, never interpreted. */\n readonly failure: F;\n}\n\n/**\n * A workflow whose ROLLBACK itself failed: a compensation activity reported a\n * failure mid-unwind. Terminal, PARTIALLY unwound — the analogue of saga's\n * `compensation_failed`. A failed compensation is a real-world fact (a refund\n * that bounced, a hold that won't release) that must become visible terminal\n * state, never a workflow wedged in `compensating` forever.\n *\n * `compensated` is left intact (the steps already rolled back); `uncompensated`\n * is the step whose compensation bounced PLUS the steps still owed a\n * compensation behind it — exactly what the consumer must reconcile by hand.\n * `compensationFailure` is the rollback failure (distinct from `failure`, the\n * forward failure that started the unwind), carried verbatim.\n */\nexport interface CompensationFailedWorkflow<A, R, F> {\n readonly status: \"compensation_failed\";\n readonly steps: readonly WorkflowStep<A>[];\n /** The full completed-forward history, in execution order. */\n readonly completed: readonly CompletedStep<A, R>[];\n /** The step whose forward activity failed, triggering the unwind. */\n readonly failedStep: WorkflowStep<A>;\n /** The opaque forward failure that triggered compensation. Carried, never interpreted. */\n readonly failure: F;\n /** Completed steps successfully compensated before the rollback broke, in unwind order. */\n readonly compensated: readonly CompletedStep<A, R>[];\n /** The step whose compensation bounced. Its forward effect stands un-reversed. */\n readonly failedCompensationStep: WorkflowStep<A>;\n /** The opaque rollback failure (distinct from {@link failure}). Carried, never interpreted. */\n readonly compensationFailure: F;\n}\n\n/**\n * The workflow's state — a discriminated union on `status`. The current\n * in-flight activity is reachable ONLY through `running`, and the in-flight\n * compensation ONLY through `compensating`, making \"an in-flight effect exists\n * only while the workflow is actively driving one\" unrepresentable to violate.\n */\nexport type WorkflowState<A, R, F> =\n | RunningWorkflow<A, R>\n | CompletedWorkflow<A, R>\n | FailedWorkflow<A, R, F>\n | CompensatingWorkflow<A, R, F>\n | FailedCompensatedWorkflow<A, R, F>\n | CompensationFailedWorkflow<A, R, F>;\n\n/** Every `status` discriminant of the {@link WorkflowState} union. */\nexport type WorkflowStatus = WorkflowState<unknown, unknown, unknown>[\"status\"];\n\n/**\n * The runtime accept-set of every {@link WorkflowStatus} — the single source of\n * truth the boundary snapshot parse keys off (see `do.ts`). Built from an\n * exhaustive `Record<WorkflowStatus, true>`, so adding a variant to the union\n * above without listing it here is a COMPILE error: the set can never silently\n * drift from the union again (the #312 regression, where the #125 compensation\n * statuses were missing and evicted-mid-rollback grains re-seeded fresh).\n */\nexport const WORKFLOW_STATUSES: ReadonlySet<string> = new Set(\n Object.keys({\n running: true,\n completed: true,\n failed: true,\n compensating: true,\n failed_compensated: true,\n compensation_failed: true,\n } satisfies Record<WorkflowStatus, true>),\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Cmds — the activity dispatch. Recorded on the #67 ledger as an owed effect.\n//\n// `ActivityCmd` is the single Cmd this module emits: \"perform the activity for\n// step `index`, and the result you dispatch back must carry delivery id `id`\".\n// The consumer's interpret cell performs `activity` and dispatches an\n// `ActivityOk`/`ActivityErr` Msg carrying the SAME id. The owed/confirmed\n// ledger events ride alongside (see {@link WorkflowReducerStep}/the step tuple).\n// ─────────────────────────────────────────────────────────────────────────────\n\n// Both are `Cmd.define`d (ADR 0014). The activity payload `A` is the\n// workflow's own type parameter, so each def is minted per workflow by a\n// factory (`createWorkflow` calls it once) rather than a module-scope constant\n// — the same shape `idempotent-intake`'s `intakeProcessDef<P>()` takes. The\n// consumer's interpret cell performs the dispatch and answers through this\n// module's OWN result Msgs (`activity_ok` / `compensation_err` … carrying the\n// delivery id), never through the minted `_ok` / `_err`, hence `ok: z.void()`\n// and an empty `err` list.\n\n/**\n * Dispatch the in-flight activity. Routed through the consumer's `interpret`\n * over an injected activity port. The reducer emits this record; it performs\n * no side effect. The result MUST be dispatched back as a Msg carrying `id`.\n */\nexport function workflowActivityDef<A>() {\n return Cmd.define(\"workflow_activity\", {\n input: z.custom<{\n /** The 0-based step index this activity belongs to. */\n readonly index: number;\n /** The #67 delivery id the result Msg must echo (the dedup key). */\n readonly id: DeliveryId;\n /** The opaque activity to perform. */\n readonly activity: A;\n }>(),\n ok: z.void(),\n err: [],\n });\n}\nexport type ActivityCmd<A> = CmdOf<ReturnType<typeof workflowActivityDef<A>>>;\n\n/**\n * Dispatch a compensation (#125). Same shape + ledger discipline as\n * {@link ActivityCmd} — a compensation is just another durable owed effect on\n * the same #67 ledger, with its own delivery id — but the consumer's interpret\n * cell performs the inverse `compensation` payload, and the result is dispatched\n * back as a {@link CompensationOk}/{@link CompensationErr} carrying the SAME id.\n * Distinguished by `type` so the consumer routes forward vs. inverse work to the\n * right port, and the re-emit-on-wake stays type-correct.\n */\nexport function workflowCompensationDef<A>() {\n return Cmd.define(\"workflow_compensation\", {\n input: z.custom<{\n /** The 0-based step index whose compensation this is. */\n readonly index: number;\n /** The #67 delivery id the result Msg must echo (the dedup key). */\n readonly id: DeliveryId;\n /** The opaque compensating (inverse) activity to perform. */\n readonly compensation: A;\n }>(),\n ok: z.void(),\n err: [],\n });\n}\nexport type CompensationCmd<A> = CmdOf<\n ReturnType<typeof workflowCompensationDef<A>>\n>;\n\n/** The Cmd union this module emits: forward activity dispatches AND (#125)\n * reverse compensation dispatches. The owed/confirmed ledger events are not\n * `WorkflowCmd`s — they are Msg variants persisted into the event log (see\n * {@link EffectLedgerEvent}); the {@link WorkflowReducerStep} tuple carries them out\n * alongside the dispatch Cmd so the host persists owed-before-dispatch. Both\n * Cmd kinds are owed effects on the same ledger, so `survivingActivities`\n * re-emits either kind on cold wake. */\nexport type WorkflowCmd<A> = ActivityCmd<A> | CompensationCmd<A>;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Msgs — activity results the consumer routes back into the reducer.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** An activity succeeded: `id` echoes the {@link ActivityCmd} it answers; the\n * reducer matches it against `current.id`, records the completed step, and\n * advances. */\nexport interface ActivityOk<R> {\n readonly type: \"activity_ok\";\n readonly id: DeliveryId;\n readonly result: R;\n}\n\n/** An activity failed (retries already exhausted by the consumer's interpret\n * cell — this module does not retry). `id` echoes the {@link ActivityCmd};\n * the reducer begins compensation (or settles `failed` when nothing has\n * completed). */\nexport interface ActivityErr<F> {\n readonly type: \"activity_err\";\n readonly id: DeliveryId;\n readonly failure: F;\n}\n\n/** A compensation succeeded (#125): the inverse activity took. `id` echoes the\n * {@link CompensationCmd} it answers; the reducer matches it against the\n * in-flight compensation's id, records the step as compensated, and either\n * emits the next compensation (continuing in reverse) or settles\n * `failed_compensated` when the unwind is complete. A compensation produces no\n * result the workflow carries — its only signal is \"the undo took\". */\nexport interface CompensationOk {\n readonly type: \"compensation_ok\";\n readonly id: DeliveryId;\n}\n\n/** A compensation itself failed (#125): the inverse activity bounced (a refund\n * that won't go through). `id` echoes the {@link CompensationCmd}; the reducer\n * halts the rollback at the terminal `compensation_failed` state — never wedged\n * in `compensating` forever. */\nexport interface CompensationErr<F> {\n readonly type: \"compensation_err\";\n readonly id: DeliveryId;\n readonly failure: F;\n}\n\n/** The Msg union the reducer folds: forward activity results AND (#125) reverse\n * compensation results. */\nexport type WorkflowMsg<R, F> =\n | ActivityOk<R>\n | ActivityErr<F>\n | CompensationOk\n | CompensationErr<F>;\n\n/** Every `type` discriminant tag of the {@link WorkflowMsg} union. */\nexport type WorkflowMsgType = WorkflowMsg<unknown, unknown>[\"type\"];\n\n/**\n * The runtime accept-set of every {@link WorkflowMsgType} — the single source of\n * truth the boundary replay parse keys off (see `do.ts`). Built from an\n * exhaustive `Record<WorkflowMsgType, true>`, so adding a Msg variant to the\n * union above without listing it here is a COMPILE error: the set can never\n * silently drift from the union again (the #312 regression, where the #125\n * compensation result tags were missing and dropped from replay).\n */\nexport const WORKFLOW_MSG_TYPES: ReadonlySet<string> = new Set(\n Object.keys({\n activity_ok: true,\n activity_err: true,\n compensation_ok: true,\n compensation_err: true,\n } satisfies Record<WorkflowMsgType, true>),\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// The step tuple — the reducer's output shape.\n//\n// A verb returns the next `WorkflowState` PLUS the side-effect intents the host\n// must enact, in the ORDER they must be enacted (owed-before-dispatch):\n//\n// - `ledger` — the `effect_owed` / `effect_confirmed` events to PERSIST into\n// the same event log the reducer folds. A `running`-emitting verb owes the\n// new activity (and a verb that folded a prior result confirms it). Persist\n// these BEFORE the dispatch Cmd (the #67 \"persist the intent before deliver\"\n// rule) so an eviction between persist and dispatch re-fires on wake.\n// - `cmds` — the activity dispatch Cmd(s). Empty on a terminal transition.\n//\n// This is the same `readonly [state, cmds]` discipline as raft's `RaftStep`,\n// extended with the ledger-events channel because activities ARE owed effects.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** A workflow reducer step: the next state, the ledger events to persist\n * (owed-before-dispatch), and the activity Cmds to dispatch. */\nexport interface WorkflowReducerStep<A, R, F> {\n readonly state: WorkflowState<A, R, F>;\n /** Ledger events to persist into the event log, in order, BEFORE `cmds`. */\n readonly ledger: readonly EffectLedgerEvent<WorkflowCmd<A>>[];\n /** Activity dispatch Cmds, after the ledger events are durable. */\n readonly cmds: readonly WorkflowCmd<A>[];\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// createWorkflow — the factory. Returns the hook bag (init/verbs), mirroring\n// how `createRaftNode` / `createAgent` shape their knobs. The factory owns the\n// #67 monotonic-id recorder so every dispatched activity gets a gap-free\n// delivery id; the recorder is rehydrated from the persisted ledger events on\n// cold wake (see `restore`) so ids resume without gaps.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** The hook bag returned by {@link createWorkflow}. Spread its verbs into a\n * machine; `init(steps)` seeds a fresh workflow and emits the first activity,\n * the verbs fold results and advance, and `survivingActivities` re-emits the\n * owed-but-unconfirmed dispatch on cold wake (idempotent by delivery id). */\nexport interface Workflow<A, R, F> {\n /**\n * Seed a fresh workflow over `steps` (a NON-EMPTY {@link WorkflowSteps}) and\n * dispatch its first activity → `running` with `current` = step 0, owed on the\n * ledger. The \"≥ 1 step\" precondition is carried by the tuple type: an empty\n * sequence is a compile error at the call site, not a runtime throw here — a\n * workflow with nothing to do could never reach `completed` (no final result\n * to carry), so it is unrepresentable by construction.\n */\n init(steps: WorkflowSteps<A>): WorkflowReducerStep<A, R, F>;\n\n /**\n * Fold an activity success. If `msg.id` does not match the in-flight\n * activity's id (a stale/duplicate result from re-emit-on-wake, or a result\n * for an already-advanced step), the state is returned UNCHANGED with no\n * effects — idempotent by delivery id (acceptance criterion 3). Otherwise:\n * record the completed step, confirm the owed activity on the ledger, and\n * either advance to the next step (owing its activity) or transition to\n * `completed` carrying the final result.\n *\n * Only meaningful on `running`; a result arriving for a terminal workflow is\n * a no-op (the workflow is done — at-least-once tolerates the late echo).\n */\n onActivityOk(\n state: WorkflowState<A, R, F>,\n msg: ActivityOk<R>,\n ): WorkflowReducerStep<A, R, F>;\n\n /**\n * Fold an activity failure (#125). Same id-match idempotency guard as\n * {@link onActivityOk}. On a match: confirm the owed activity on the ledger,\n * then PIVOT into compensation — walk the completed-step history in strict\n * reverse and owe the first declared compensation as a durable effect on the\n * same ledger, transitioning to `compensating`. If NO completed step declares\n * a compensation (the empty-rollback edge — the first activity failed, or\n * every completed step is irreversible), settle `failed` directly with\n * nothing to unwind.\n */\n onActivityErr(\n state: WorkflowState<A, R, F>,\n msg: ActivityErr<F>,\n ): WorkflowReducerStep<A, R, F>;\n\n /**\n * Fold a compensation success (#125). Same id-match idempotency guard against\n * the in-flight compensation. On a match: confirm the owed compensation,\n * record the step as compensated, and continue the reverse walk — owe the\n * next declared compensation strictly below the step just undone, or settle\n * `failed_compensated` when the unwind is complete. Only meaningful on\n * `compensating`; a result for a terminal/forward workflow is a no-op.\n */\n onCompensationOk(\n state: WorkflowState<A, R, F>,\n msg: CompensationOk,\n ): WorkflowReducerStep<A, R, F>;\n\n /**\n * Fold a compensation failure (#125). Same id-match idempotency guard. On a\n * match: confirm the owed compensation and HALT the rollback at the terminal\n * `compensation_failed` state — a bounced compensation is visible terminal\n * state to reconcile by hand, never a workflow wedged in `compensating`\n * forever. Mirrors `../saga/`'s `undoErr`.\n */\n onCompensationErr(\n state: WorkflowState<A, R, F>,\n msg: CompensationErr<F>,\n ): WorkflowReducerStep<A, R, F>;\n\n /**\n * The owed-but-unconfirmed dispatch(es) to re-emit on activation — a forward\n * activity OR (#125) a compensation, rebuilt by folding the persisted ledger\n * events. On a fresh / fully-settled workflow this is empty. The re-fired Cmd\n * carries the SAME delivery id, so a duplicate result is a no-op at the\n * reducer (the id-match guard). This is the cold-wake re-emit that makes both\n * activities AND compensations exactly-once-observable despite the\n * at-least-once transport (acceptance criterion 2 & 3) — including a\n * compensation owed mid-rollback when the actor was evicted.\n */\n survivingActivities(\n ledgerEvents: Iterable<EffectLedgerEvent<WorkflowCmd<A>>>,\n ): readonly WorkflowCmd<A>[];\n}\n\n/**\n * Build a workflow hook bag. The factory captures NO clock and NO RNG — pure\n * bookkeeping over the injected #67 recorder, exactly like\n * `pendingEffectsLedger`. `restore` rehydrates the monotonic delivery-id\n * counter from the persisted ledger events on cold wake, so re-dispatched\n * activities resume their ids without gaps.\n *\n * @param restore - the persisted ledger events (read back from the log) and/or\n * the last issued delivery id, so the id counter resumes gap-free. Omit for a\n * fresh workflow.\n */\nexport function createWorkflow<A, R, F>(restore?: {\n readonly events?: Iterable<EffectLedgerEvent<WorkflowCmd<A>>>;\n readonly lastId?: DeliveryId;\n}): Workflow<A, R, F> {\n // The #67 monotonic-id recorder. It owns the gap-free `deliveryId` and folds\n // an in-memory mirror of the ledger from the same owed/confirmed events the\n // host persists. Reused verbatim — activities AND compensations ARE owed\n // effects on this one ledger (do NOT reinvent the ledger).\n const recorder = pendingEffectsLedger<WorkflowCmd<A>>(restore);\n\n // The two Cmd constructors, minted once for this workflow's `A`.\n const activityCmd = workflowActivityDef<A>();\n const compensationCmd = workflowCompensationDef<A>();\n\n /**\n * Owe + dispatch the activity for `step` at `index`: allocate its delivery\n * id, build the dispatch Cmd, and emit BOTH the `effect_owed` ledger event\n * (to persist first) and the dispatch Cmd. The owed effect IS the dispatch\n * Cmd, so a cold wake re-emits the identical dispatch by folding the ledger.\n *\n * Returns the running state's `current` plus the owed event + dispatch Cmd.\n */\n /** Index into a step sequence with a bounds-check narrowing away `undefined`\n * (`noUncheckedIndexedAccess`). Every call site has already proven the index\n * in range — this converts that proof into the non-optional type, throwing\n * only on a logic error that should be unreachable. */\n function stepAt(\n steps: readonly WorkflowStep<A>[],\n index: number,\n ): WorkflowStep<A> {\n const step = steps[index];\n if (step === undefined) {\n throw new Error(\n `createWorkflow: step index ${index} out of range (length ` +\n `${steps.length}) — a reducer bounds proof was violated.`,\n );\n }\n return step;\n }\n\n /**\n * Predict the next delivery id, build the FINAL dispatch Cmd with it via\n * `build`, owe that exact Cmd on the #67 ledger, and assert the issued id\n * equals the prediction.\n *\n * The dispatch Cmd needs the delivery id, and the ledger event carries that\n * Cmd as its `effect` payload — so the id and the Cmd are mutually dependent.\n * Resolve the cycle by predicting the next id (`lastId() + 1`, the recorder's\n * gap-free monotonic rule), building the final Cmd, then handing that exact\n * Cmd to `recorder.owe`. The recorder issues the predicted id and folds the\n * final Cmd into its mirror — so the mirror, the persisted `effect_owed`\n * event, and the dispatch Cmd all carry one identical id and payload (no\n * placeholder, no rebuild). Shared by the forward owe ({@link oweActivity})\n * and the reverse owe ({@link oweCompensation}) so both halves of the\n * transaction allocate ids on the SAME monotonic ledger.\n */\n function oweOnLedger<C extends WorkflowCmd<A>>(\n build: (id: DeliveryId) => C,\n ): {\n readonly id: DeliveryId;\n readonly owed: EffectOwed<WorkflowCmd<A>>;\n readonly cmd: C;\n } {\n const id = (recorder.lastId() + 1) as DeliveryId;\n const cmd = build(id);\n const { id: issued, event } = recorder.owe(cmd);\n // Defensive: the prediction must equal the issued id, or the ledger mirror\n // and the dispatch Cmd would diverge. This holds by the recorder's gap-free\n // monotonic contract; assert it rather than silently carry a mismatch.\n if (issued !== id) {\n throw new Error(\n `createWorkflow: delivery-id prediction (${id}) diverged from the ` +\n `recorder's issued id (${issued}). The #67 recorder's monotonic ` +\n \"counter is not gap-free as assumed — this is a substrate invariant \" +\n \"violation, not a recoverable condition.\",\n );\n }\n return { id, owed: event, cmd };\n }\n\n function oweActivity(\n step: WorkflowStep<A>,\n index: number,\n ): {\n readonly current: InFlightActivity<A>;\n readonly owed: EffectOwed<WorkflowCmd<A>>;\n readonly cmd: ActivityCmd<A>;\n } {\n const { id, owed, cmd } = oweOnLedger<ActivityCmd<A>>((id) =>\n activityCmd({ index, id, activity: step.activity }),\n );\n const current: InFlightActivity<A> = { index, step, id };\n return { current, owed, cmd };\n }\n\n /**\n * Owe + dispatch the COMPENSATION for the completed step at `index` (#125):\n * the reverse-walk mirror of {@link oweActivity}. The compensation is a\n * durable owed effect on the SAME #67 ledger, so a cold wake mid-rollback\n * re-emits the identical compensation dispatch by folding the ledger\n * (acceptance criterion 2). `step.compensation` is required to be present —\n * the caller (the reverse walk) only owes compensations for steps that\n * declared one, skipping the rest.\n */\n function oweCompensation(\n step: WorkflowStep<A>,\n compensation: A,\n index: number,\n ): {\n readonly current: InFlightCompensation<A>;\n readonly owed: EffectOwed<WorkflowCmd<A>>;\n readonly cmd: CompensationCmd<A>;\n } {\n const { id, owed, cmd } = oweOnLedger<CompensationCmd<A>>((id) =>\n compensationCmd({ index, id, compensation }),\n );\n const current: InFlightCompensation<A> = { index, step, id };\n return { current, owed, cmd };\n }\n\n /**\n * Begin (or continue) the reverse walk from `completed`, owing the next\n * compensation strictly BELOW `belowIndex` (exclusive) that declares one. The\n * single source of truth for \"what to undo next\", shared by the failure pivot\n * ({@link Workflow.onActivityErr}) and each `compensation_ok` step\n * ({@link Workflow.onCompensationOk}). Steps with no compensation are SKIPPED\n * (they contribute nothing to the unwind — saga's no-op `undo`).\n *\n * Returns the next compensation to owe (its in-flight record + ledger event +\n * dispatch Cmd), or `null` when no compensable step remains below `belowIndex`\n * — the unwind is complete and the caller settles `failed_compensated`.\n */\n function oweNextCompensation(\n completed: readonly CompletedStep<A, R>[],\n belowIndex: number,\n ): {\n readonly current: InFlightCompensation<A>;\n readonly owed: EffectOwed<WorkflowCmd<A>>;\n readonly cmd: CompensationCmd<A>;\n } | null {\n // Walk the completed history from just below `belowIndex` toward 0 (strict\n // reverse order), stopping at the first step that declares a compensation.\n for (let i = belowIndex - 1; i >= 0; i--) {\n const entry = completed[i];\n // `completed[i]` is the i-th completed step; `i` is also its step index\n // (completed is in execution order, contiguous from 0 up to the failure).\n if (entry !== undefined && entry.step.compensation !== undefined) {\n return oweCompensation(entry.step, entry.step.compensation, i);\n }\n }\n return null;\n }\n\n /**\n * Assemble the next `compensating` step from a `base` (everything but the\n * in-flight compensation — carried identically from the failure pivot OR from\n * the prior compensating state) and the `next` compensation to owe. Both the\n * failure pivot ({@link Workflow.onActivityErr}) and each `compensation_ok`\n * advance ({@link Workflow.onCompensationOk}) continue the unwind the same way,\n * so the confirm-then-owe ledger discipline (`[confirmed, next.owed]`, dispatch\n * `[next.cmd]`) lives here once instead of mirrored at both call sites.\n */\n function continueCompensating(\n base: Omit<CompensatingWorkflow<A, R, F>, \"current\">,\n next: {\n readonly current: InFlightCompensation<A>;\n readonly owed: EffectOwed<WorkflowCmd<A>>;\n readonly cmd: CompensationCmd<A>;\n },\n confirmed: EffectConfirmed,\n ): WorkflowReducerStep<A, R, F> {\n const compensating: CompensatingWorkflow<A, R, F> = {\n ...base,\n current: next.current,\n };\n return {\n state: compensating,\n ledger: [confirmed, next.owed],\n cmds: [next.cmd],\n };\n }\n\n return {\n init(steps) {\n // `steps` is a non-empty `WorkflowSteps` (the empty case is a compile\n // error at the call site), so step 0 always exists — no runtime guard.\n const { current, owed, cmd } = oweActivity(stepAt(steps, 0), 0);\n const state: RunningWorkflow<A, R> = {\n status: \"running\",\n steps,\n completed: [],\n current,\n };\n return { state, ledger: [owed], cmds: [cmd] };\n },\n\n onActivityOk(state, msg) {\n // A result for a terminal workflow, or one whose id does not match the\n // in-flight activity, is a no-op — idempotent by delivery id. This is the\n // guard that makes re-emit-on-wake safe: a re-fired (already-folded)\n // activity's result arrives with an id that is no longer `current.id`.\n if (state.status !== \"running\" || msg.id !== state.current.id) {\n return { state, ledger: [], cmds: [] };\n }\n\n // Record the completed step and confirm the owed activity on the ledger.\n const confirmed: EffectConfirmed = confirm(state.current.id);\n const completedStep: CompletedStep<A, R> = {\n step: state.current.step,\n result: msg.result,\n };\n const completed = [...state.completed, completedStep];\n\n const nextIndex = state.current.index + 1;\n if (nextIndex >= state.steps.length) {\n // The final step's result is the workflow's output → `completed`.\n const done: CompletedWorkflow<A, R> = {\n status: \"completed\",\n steps: state.steps,\n completed,\n output: msg.result,\n };\n return { state: done, ledger: [confirmed], cmds: [] };\n }\n\n // Advance: owe + dispatch the next activity.\n const { current, owed, cmd } = oweActivity(\n stepAt(state.steps, nextIndex),\n nextIndex,\n );\n const running: RunningWorkflow<A, R> = {\n status: \"running\",\n steps: state.steps,\n completed,\n current,\n };\n // Persist the confirm of the prior activity AND the owe of the next, in\n // that order, before dispatching the next. (Confirm-then-owe keeps the\n // ledger holding at most one in-flight activity per workflow.)\n return { state: running, ledger: [confirmed, owed], cmds: [cmd] };\n },\n\n onActivityErr(state, msg) {\n if (state.status !== \"running\" || msg.id !== state.current.id) {\n return { state, ledger: [], cmds: [] };\n }\n const confirmed: EffectConfirmed = confirm(state.current.id);\n\n // #125: the forward failure PIVOTS into compensation. Mirroring saga's\n // `stepErr`: walk the completed history in strict reverse, owing the\n // first declared compensation as a durable effect on this SAME ledger.\n // `state.completed` is preserved precisely so this reverse walk has its\n // history.\n const next = oweNextCompensation(state.completed, state.completed.length);\n\n if (next === null) {\n // Empty rollback: no completed step declares a compensation (the first\n // activity failed, OR every completed step is irreversible). The\n // analogue of saga aborting straight from the first step — settle\n // `failed` directly, nothing to unwind (acceptance criterion 3).\n const failed: FailedWorkflow<A, R, F> = {\n status: \"failed\",\n steps: state.steps,\n completed: state.completed,\n failedStep: state.current.step,\n failure: msg.failure,\n };\n return { state: failed, ledger: [confirmed], cmds: [] };\n }\n\n // Pivot to `compensating`, emitting the first compensation. Confirm the\n // failed forward activity AND owe the first compensation, in that order,\n // before dispatching it (the same confirm-then-owe ledger discipline as\n // the forward advance — at most one in-flight effect per workflow). The\n // `base` here is FRESH from the failing activity (failedStep/failure from\n // `state.current`/`msg`, empty `compensated`).\n return continueCompensating(\n {\n status: \"compensating\",\n steps: state.steps,\n completed: state.completed,\n failedStep: state.current.step,\n failure: msg.failure,\n compensated: [],\n },\n next,\n confirmed,\n );\n },\n\n onCompensationOk(state, msg) {\n // A compensation result for a non-compensating workflow, or one whose id\n // does not match the in-flight compensation, is a no-op — idempotent by\n // delivery id, the same re-emit-on-wake guard as the forward verbs.\n if (state.status !== \"compensating\" || msg.id !== state.current.id) {\n return { state, ledger: [], cmds: [] };\n }\n\n // Confirm the owed compensation and record the step as compensated.\n const confirmed: EffectConfirmed = confirm(state.current.id);\n const undoneStep = state.completed[state.current.index];\n if (undoneStep === undefined) {\n throw new Error(\n `createWorkflow.onCompensationOk: compensation index ` +\n `${state.current.index} has no completed step — a reverse-walk ` +\n \"bounds proof was violated.\",\n );\n }\n const compensated = [...state.compensated, undoneStep];\n\n // Continue the reverse walk strictly below the step just undone, skipping\n // steps with no compensation.\n const next = oweNextCompensation(state.completed, state.current.index);\n\n if (next === null) {\n // Fully unwound → `failed_compensated` (saga's `aborted`).\n const settled: FailedCompensatedWorkflow<A, R, F> = {\n status: \"failed_compensated\",\n steps: state.steps,\n completed: state.completed,\n failedStep: state.failedStep,\n failure: state.failure,\n };\n return { state: settled, ledger: [confirmed], cmds: [] };\n }\n\n // Continue the unwind. The `base` here CARRIES failedStep/failure from the\n // prior compensating `state` and the accumulated `compensated` list.\n return continueCompensating(\n {\n status: \"compensating\",\n steps: state.steps,\n completed: state.completed,\n failedStep: state.failedStep,\n failure: state.failure,\n compensated,\n },\n next,\n confirmed,\n );\n },\n\n onCompensationErr(state, msg) {\n // Same id-match idempotency guard as the other verbs.\n if (state.status !== \"compensating\" || msg.id !== state.current.id) {\n return { state, ledger: [], cmds: [] };\n }\n // Confirm the owed compensation (the dispatch is no longer owed — it was\n // delivered and answered, just with a failure), then HALT the rollback at\n // the terminal `compensation_failed` state. Mirroring saga's `undoErr`: a\n // bounced compensation is a real-world fact the consumer must reconcile by\n // hand, never a workflow wedged in `compensating` forever. `compensated`\n // (already rolled back) is left intact for the consumer to read.\n const confirmed: EffectConfirmed = confirm(state.current.id);\n const halted: CompensationFailedWorkflow<A, R, F> = {\n status: \"compensation_failed\",\n steps: state.steps,\n completed: state.completed,\n failedStep: state.failedStep,\n failure: state.failure,\n compensated: state.compensated,\n failedCompensationStep: state.current.step,\n compensationFailure: msg.failure,\n };\n return { state: halted, ledger: [confirmed], cmds: [] };\n },\n\n survivingActivities(ledgerEvents) {\n // Rebuild the ledger by folding the persisted events (NOT a side table),\n // then the surviving owed effects ARE the dispatch Cmds to re-fire — each\n // owed effect's payload is its dispatch Cmd (a forward activity OR a\n // compensation), carrying the same id.\n const ledger: PendingEffectsLedger<WorkflowCmd<A>> =\n foldLedger(ledgerEvents);\n return survivingEffects(ledger).map((owed) => owed.effect);\n },\n };\n\n /** Confirm an owed activity (or compensation) on the recorder's ledger,\n * returning the `effect_confirmed` event to persist. The boolean (was-owed)\n * is not needed by the reducer — the id-match guard above already gates on\n * the in-flight effect — so it is discarded here. */\n function confirm(id: DeliveryId): EffectConfirmed {\n return recorder.confirm(id).event;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// foldWorkflow — the pure replay fold. The determinism contract (acceptance\n// criterion 4) in one function: fold a workflow's full event log — its `init`\n// steps plus the ordered activity-result Msgs — back into a `WorkflowState`,\n// reading no clock and no RNG. Two folds of the same log produce byte-identical\n// state, because every decision is a pure function of (state, msg) and the\n// delivery ids are reissued in the same order from the same fresh recorder.\n//\n// This is the workflow-level twin of `foldLedger`: the host's `replay()` over\n// the event-sourced store re-runs exactly this fold to rebuild a workflow on\n// cold wake. Kept here (not only in the host, #126) so the determinism contract\n// is provable against the pure core alone.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Replay a workflow from its event log: seed over `steps`, then fold each\n * activity-result `Msg` in order. Returns the final {@link WorkflowState}.\n *\n * Determinism: a freshly-constructed {@link createWorkflow} reissues delivery\n * ids monotonically from 0, and the reducer reads no ambient state — so two\n * calls with the same `steps` + `msgs` return deeply-equal states (and equal\n * `JSON.stringify`). This is the byte-identity property #124 pins.\n *\n * Note this folds ONLY the result Msgs; the `init` dispatch + per-step\n * owe/confirm ledger events are an internal effect channel reconstructed by the\n * fresh recorder, not part of the replayed Msg log — exactly as the activity\n * results are the only thing the consumer records and replays.\n */\nexport function foldWorkflow<A, R, F>(\n steps: WorkflowSteps<A>,\n msgs: Iterable<WorkflowMsg<R, F>>,\n): WorkflowState<A, R, F> {\n const wf = createWorkflow<A, R, F>();\n let { state } = wf.init(steps);\n for (const msg of msgs) {\n // Route each result Msg to its verb via the shared dispatcher. The forward\n // results (`activity_*`) and the reverse compensation results\n // (`compensation_*`, #125) are folded by the same fresh recorder, so a\n // replay across a failure+compensation sequence re-issues every delivery id\n // in identical order — byte-identity holds end to end (acceptance\n // criterion 4).\n state = routeWorkflowMsg(wf, state, msg).state;\n }\n return state;\n}\n\n// Re-export the durable-effects types a consumer needs to persist + replay a\n// workflow's ledger (the owed/confirmed events, the delivery id, the empty\n// seed) without reaching into the `../do` subpath directly.\nexport {\n type DeliveryId,\n type EffectConfirmed,\n type EffectLedgerEvent,\n type EffectOwed,\n emptyLedger,\n};\n// The ONE WorkflowMsg → verb routing table, exported because a consumer driving\n// a workflow from its own host — rather than through `./do`'s grain — otherwise\n// has to re-derive the same four-way mapping by hand, and a fifth Msg variant\n// would then break it silently instead of at compile time.\nexport { routeWorkflowMsg } from \"./route\";\n"]}