@graphrefly/graphrefly 0.27.0 → 0.28.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 (428) hide show
  1. package/dist/backoff-HPZMEZNF.js +1 -0
  2. package/dist/cascading-B-5zmAUv.d.cts +180 -0
  3. package/dist/cascading-D9WG1-9L.d.ts +180 -0
  4. package/dist/chunk-2FOAM3OR.js +1 -0
  5. package/dist/chunk-2PMCKKRK.js +1 -0
  6. package/dist/chunk-3JXNEPCD.js +2 -0
  7. package/dist/chunk-3R5HFPX7.js +78 -0
  8. package/dist/chunk-4GKB4OUJ.js +1 -0
  9. package/dist/chunk-4VVTGLXJ.js +1 -0
  10. package/dist/chunk-5QDBSZBV.js +1 -0
  11. package/dist/chunk-6QZNQS5B.js +1 -0
  12. package/dist/chunk-6V3SEX2I.js +1 -0
  13. package/dist/chunk-76A3HVQE.js +9 -0
  14. package/dist/chunk-7H6LGFUG.js +64 -0
  15. package/dist/chunk-CK2E7BTU.js +1 -0
  16. package/dist/chunk-CKCSDI7T.js +6 -0
  17. package/dist/chunk-CRXTH3SH.js +1 -0
  18. package/dist/chunk-CWLN3X3N.js +1 -0
  19. package/dist/chunk-D7A7DBE4.js +1 -0
  20. package/dist/chunk-DBGGMN3D.js +1 -0
  21. package/dist/chunk-DQA3UIQ2.js +1 -0
  22. package/dist/chunk-ERLIRFPA.js +1 -0
  23. package/dist/chunk-ESMPEKEV.js +1 -0
  24. package/dist/chunk-ETWTCCJI.js +1 -0
  25. package/dist/chunk-FNYWM6JC.js +1 -0
  26. package/dist/chunk-GHJJR5P4.js +1 -0
  27. package/dist/chunk-GPW2V3RE.js +1 -0
  28. package/dist/chunk-I6VIH3VA.js +1 -0
  29. package/dist/chunk-K2GNMCQT.js +1 -0
  30. package/dist/chunk-LBTDSCCO.js +3 -0
  31. package/dist/chunk-LQ3Y5NJS.js +1 -0
  32. package/dist/chunk-MIQTDPY4.js +5 -0
  33. package/dist/chunk-MTTAAPCK.js +1 -0
  34. package/dist/chunk-OAWLCNJJ.js +1 -0
  35. package/dist/chunk-OBKQQA5I.js +1 -0
  36. package/dist/chunk-OYHGKYQM.js +1 -0
  37. package/dist/chunk-PIOGHC63.js +1 -0
  38. package/dist/chunk-QWAPKG3O.js +2 -0
  39. package/dist/chunk-QYADASLV.js +1 -0
  40. package/dist/chunk-RHESUC3V.js +43 -0
  41. package/dist/chunk-S35VARIR.js +1 -0
  42. package/dist/chunk-SC3U7ETD.js +1 -0
  43. package/dist/chunk-U3AICJKU.js +1 -0
  44. package/dist/chunk-UMBIDLJ4.js +1 -0
  45. package/dist/chunk-UPHHLMHE.js +1 -0
  46. package/dist/chunk-UPXUCFMX.js +1 -0
  47. package/dist/chunk-UWJE5FQA.js +18 -0
  48. package/dist/chunk-V6YQICXZ.js +1 -0
  49. package/dist/chunk-VIMF6LGM.js +1 -0
  50. package/dist/chunk-VJLMUKOI.js +1 -0
  51. package/dist/chunk-VPYBOXVT.js +1 -0
  52. package/dist/chunk-VTPVOGHH.js +1 -0
  53. package/dist/chunk-WQ2BN6X6.js +1 -0
  54. package/dist/chunk-XAUNPIMX.js +1 -0
  55. package/dist/chunk-Y2EMPB3I.js +1 -0
  56. package/dist/chunk-Z4HDAS2Q.js +1 -0
  57. package/dist/chunk-ZB5EHBIO.js +1 -0
  58. package/dist/chunk-ZV2DXV5A.js +23 -0
  59. package/dist/compat/index.cjs +14 -7656
  60. package/dist/compat/index.d.cts +15 -14
  61. package/dist/compat/index.d.ts +15 -14
  62. package/dist/compat/index.js +1 -50
  63. package/dist/compat/jotai/index.cjs +1 -2048
  64. package/dist/compat/jotai/index.d.cts +2 -2
  65. package/dist/compat/jotai/index.d.ts +2 -2
  66. package/dist/compat/jotai/index.js +1 -9
  67. package/dist/compat/nanostores/index.cjs +1 -2175
  68. package/dist/compat/nanostores/index.d.cts +2 -2
  69. package/dist/compat/nanostores/index.d.ts +2 -2
  70. package/dist/compat/nanostores/index.js +1 -23
  71. package/dist/compat/nestjs/index.cjs +14 -6782
  72. package/dist/compat/nestjs/index.d.cts +7 -6
  73. package/dist/compat/nestjs/index.d.ts +7 -6
  74. package/dist/compat/nestjs/index.js +1 -83
  75. package/dist/compat/react/index.cjs +1 -141
  76. package/dist/compat/react/index.d.cts +2 -2
  77. package/dist/compat/react/index.d.ts +2 -2
  78. package/dist/compat/react/index.js +1 -12
  79. package/dist/compat/solid/index.cjs +1 -128
  80. package/dist/compat/solid/index.d.cts +2 -2
  81. package/dist/compat/solid/index.d.ts +2 -2
  82. package/dist/compat/solid/index.js +1 -12
  83. package/dist/compat/svelte/index.cjs +1 -131
  84. package/dist/compat/svelte/index.d.cts +2 -2
  85. package/dist/compat/svelte/index.d.ts +2 -2
  86. package/dist/compat/svelte/index.js +1 -12
  87. package/dist/compat/vue/index.cjs +1 -146
  88. package/dist/compat/vue/index.d.cts +2 -2
  89. package/dist/compat/vue/index.d.ts +2 -2
  90. package/dist/compat/vue/index.js +1 -12
  91. package/dist/compat/zustand/index.cjs +6 -4931
  92. package/dist/compat/zustand/index.d.cts +5 -5
  93. package/dist/compat/zustand/index.d.ts +5 -5
  94. package/dist/compat/zustand/index.js +1 -12
  95. package/dist/composite-B-xqw4Kk.d.cts +69 -0
  96. package/dist/composite-BhbKHbOS.d.ts +69 -0
  97. package/dist/core/index.cjs +1 -2271
  98. package/dist/core/index.d.cts +4 -4
  99. package/dist/core/index.d.ts +4 -4
  100. package/dist/core/index.js +1 -110
  101. package/dist/extra/browser.cjs +1 -0
  102. package/dist/extra/browser.d.cts +3 -0
  103. package/dist/extra/browser.d.ts +3 -0
  104. package/dist/extra/browser.js +1 -0
  105. package/dist/extra/index.cjs +23 -9971
  106. package/dist/extra/index.d.cts +13 -6
  107. package/dist/extra/index.d.ts +13 -6
  108. package/dist/extra/index.js +1 -381
  109. package/dist/extra/node.cjs +3 -0
  110. package/dist/extra/node.d.cts +81 -0
  111. package/dist/extra/node.d.ts +81 -0
  112. package/dist/extra/node.js +2 -0
  113. package/dist/extra/operators.cjs +1 -0
  114. package/dist/extra/operators.d.cts +910 -0
  115. package/dist/extra/operators.d.ts +910 -0
  116. package/dist/extra/operators.js +1 -0
  117. package/dist/extra/reactive.cjs +1 -0
  118. package/dist/extra/reactive.d.cts +352 -0
  119. package/dist/extra/reactive.d.ts +352 -0
  120. package/dist/extra/reactive.js +1 -0
  121. package/dist/extra/sources.cjs +1 -2486
  122. package/dist/extra/sources.d.cts +6 -2
  123. package/dist/extra/sources.d.ts +6 -2
  124. package/dist/extra/sources.js +1 -57
  125. package/dist/extra/storage-browser.cjs +1 -0
  126. package/dist/extra/storage-browser.d.cts +71 -0
  127. package/dist/extra/storage-browser.d.ts +71 -0
  128. package/dist/extra/storage-browser.js +1 -0
  129. package/dist/extra/storage-core.cjs +1 -0
  130. package/dist/extra/storage-core.d.cts +98 -0
  131. package/dist/extra/storage-core.d.ts +98 -0
  132. package/dist/extra/storage-core.js +1 -0
  133. package/dist/extra/storage-node.cjs +2 -0
  134. package/dist/extra/storage-node.d.cts +60 -0
  135. package/dist/extra/storage-node.d.ts +60 -0
  136. package/dist/extra/storage-node.js +1 -0
  137. package/dist/fallback-BaTS7vVY.d.cts +258 -0
  138. package/dist/fallback-eOm3LNxP.d.ts +258 -0
  139. package/dist/graph/index.cjs +6 -5030
  140. package/dist/graph/index.d.cts +6 -5
  141. package/dist/graph/index.d.ts +6 -5
  142. package/dist/graph/index.js +1 -50
  143. package/dist/{graph-CCwGKLCm.d.ts → graph-BZGRXwOm.d.ts} +134 -31
  144. package/dist/{graph-DNCrvZSn.d.cts → graph-D48Qw9Cg.d.cts} +134 -31
  145. package/dist/index-8FSVk4Uf.d.ts +135 -0
  146. package/dist/index-9oDeHH2u.d.cts +291 -0
  147. package/dist/{messaging-XDoYablx.d.ts → index-B0c4cmIO.d.ts} +31 -93
  148. package/dist/{index-VdHQMPy1.d.ts → index-B1AmmSlb.d.ts} +1 -1
  149. package/dist/{index-VHqptjhu.d.cts → index-B2pwesl9.d.cts} +1 -1
  150. package/dist/index-BHvIquRZ.d.ts +1957 -0
  151. package/dist/{index-Dzk2hrlR.d.ts → index-BVHOrDwO.d.ts} +1 -1
  152. package/dist/{index-CxFrXH4m.d.ts → index-BWJV63ti.d.ts} +1 -1
  153. package/dist/{index-Xi3u0HCQ.d.cts → index-B_agccPe.d.cts} +1 -1
  154. package/dist/index-BgyGlizc.d.ts +163 -0
  155. package/dist/index-BpA5c4G9.d.ts +357 -0
  156. package/dist/index-BpIFjILY.d.cts +357 -0
  157. package/dist/{index-3lsddbbS.d.ts → index-Bqachn9_.d.ts} +1 -1
  158. package/dist/index-Btib9rsU.d.ts +607 -0
  159. package/dist/{index-wEn0eFe8.d.ts → index-BwM9BEkt.d.ts} +1 -1
  160. package/dist/index-BxJ86YZZ.d.cts +105 -0
  161. package/dist/{audit-DRlSzBu9.d.ts → index-C73n7lo-.d.cts} +27 -21
  162. package/dist/index-CEXXwWVH.d.cts +192 -0
  163. package/dist/index-CHEswufn.d.cts +163 -0
  164. package/dist/{index-C0svESO4.d.ts → index-CMn8S8Hw.d.ts} +1 -1
  165. package/dist/{index-ByQxazQJ.d.cts → index-CRO83MmV.d.cts} +1 -1
  166. package/dist/{index-BuEoe-Qu.d.ts → index-CloUk1kY.d.ts} +9 -9
  167. package/dist/index-CpgYhnrG.d.ts +291 -0
  168. package/dist/{index-DO_6JN9Z.d.cts → index-Cyojz0AE.d.cts} +1 -1
  169. package/dist/{demo-shell-BDkOptd6.d.ts → index-CzobVSMr.d.ts} +14 -14
  170. package/dist/index-Czq6ynh8.d.ts +143 -0
  171. package/dist/{index-BaSM3aYt.d.ts → index-D-YB-Vl3.d.ts} +3 -3
  172. package/dist/index-DAlweici.d.ts +231 -0
  173. package/dist/index-DEwTb_fm.d.cts +1957 -0
  174. package/dist/{index-DYme44FM.d.cts → index-DL-rYJrx.d.cts} +1 -1
  175. package/dist/{memory-li6FL5RM.d.ts → index-DP4ZTkdw.d.ts} +26 -26
  176. package/dist/{index-BwfLUNw4.d.ts → index-DUqMOlKZ.d.cts} +173 -2040
  177. package/dist/{index-B1tloyhO.d.cts → index-D_NwnRYS.d.cts} +1 -1
  178. package/dist/index-DaLJvH8Z.d.ts +105 -0
  179. package/dist/index-DcXZBF5a.d.cts +135 -0
  180. package/dist/index-DfyOkTvs.d.ts +321 -0
  181. package/dist/{index-B9B7_HEY.d.ts → index-DiOXyAwt.d.ts} +1 -1
  182. package/dist/index-DpHe5e0Q.d.ts +186 -0
  183. package/dist/index-DraikLjn.d.ts +86 -0
  184. package/dist/{index-D8wS_PeY.d.cts → index-DxsnAMWD.d.cts} +9 -9
  185. package/dist/{messaging-Gt4LPbyA.d.cts → index-DyxjtScX.d.cts} +31 -93
  186. package/dist/{audit-ClmqGOCx.d.cts → index-HDpJe9hX.d.ts} +27 -21
  187. package/dist/{index-DVGiGFGT.d.cts → index-O6TgGUBV.d.cts} +3 -3
  188. package/dist/{index-B6EhDnjH.d.cts → index-Oi8d8w4R.d.cts} +1 -1
  189. package/dist/{index-C8oil6M6.d.ts → index-ROpQmGjE.d.ts} +30 -6
  190. package/dist/index-RukJ4DLS.d.cts +607 -0
  191. package/dist/{index-BHlKbUwO.d.cts → index-ZftwfxJM.d.ts} +173 -2040
  192. package/dist/{index-BPVt8kqc.d.ts → index-cByzxQIC.d.cts} +10 -195
  193. package/dist/index-dtN7YA2x.d.cts +143 -0
  194. package/dist/{index-CI3DprxP.d.cts → index-fM6y00vT.d.cts} +30 -6
  195. package/dist/{index-DlLp-2Xn.d.cts → index-m-yHof5p.d.ts} +10 -195
  196. package/dist/index-pXrDMpRO.d.cts +231 -0
  197. package/dist/index-rHJSKsU8.d.cts +186 -0
  198. package/dist/index-rX8HBM5h.d.cts +321 -0
  199. package/dist/{index-CO8uBlUh.d.cts → index-rnwQly8X.d.cts} +147 -20
  200. package/dist/index-sm373fsH.d.ts +192 -0
  201. package/dist/{memory-C6Z2tGpC.d.cts → index-tbf2gKHd.d.cts} +26 -26
  202. package/dist/{demo-shell-Crid1WdR.d.cts → index-u15meRxL.d.cts} +14 -14
  203. package/dist/{index-B6D3QNSA.d.ts → index-umtoWT8K.d.ts} +147 -20
  204. package/dist/index-vscRDkjW.d.cts +86 -0
  205. package/dist/index.cjs +150 -24142
  206. package/dist/index.d.cts +69 -2099
  207. package/dist/index.d.ts +69 -2099
  208. package/dist/index.js +1 -3868
  209. package/dist/{meta-CbznRPYJ.d.ts → meta-Cgj6zeji.d.cts} +5 -5
  210. package/dist/{meta-BxCA7rcr.d.cts → meta-CwesDrMD.d.ts} +5 -5
  211. package/dist/{node-BmerH3kS.d.cts → node-Cc1TniY8.d.cts} +36 -9
  212. package/dist/{node-BmerH3kS.d.ts → node-Cc1TniY8.d.ts} +36 -9
  213. package/dist/{observable-BgGUwcqp.d.ts → observable-Ct-gJ9jI.d.ts} +1 -1
  214. package/dist/{observable-DJt_AxzQ.d.cts → observable-glXQoGj2.d.cts} +1 -1
  215. package/dist/patterns/ai/browser.cjs +25 -0
  216. package/dist/patterns/ai/browser.d.cts +127 -0
  217. package/dist/patterns/ai/browser.d.ts +127 -0
  218. package/dist/patterns/ai/browser.js +3 -0
  219. package/dist/patterns/ai/index.cjs +91 -0
  220. package/dist/patterns/ai/index.d.cts +17 -0
  221. package/dist/patterns/ai/index.d.ts +17 -0
  222. package/dist/patterns/ai/index.js +1 -0
  223. package/dist/patterns/ai/node.cjs +2 -0
  224. package/dist/patterns/ai/node.d.cts +58 -0
  225. package/dist/patterns/ai/node.d.ts +58 -0
  226. package/dist/patterns/ai/node.js +1 -0
  227. package/dist/patterns/audit/index.cjs +6 -0
  228. package/dist/patterns/audit/index.d.cts +6 -0
  229. package/dist/patterns/audit/index.d.ts +6 -0
  230. package/dist/patterns/audit/index.js +1 -0
  231. package/dist/patterns/cqrs/index.cjs +6 -0
  232. package/dist/patterns/cqrs/index.d.cts +5 -0
  233. package/dist/patterns/cqrs/index.d.ts +5 -0
  234. package/dist/patterns/cqrs/index.js +1 -0
  235. package/dist/patterns/demo-shell/index.cjs +7 -0
  236. package/dist/patterns/demo-shell/index.d.cts +6 -0
  237. package/dist/patterns/demo-shell/index.d.ts +6 -0
  238. package/dist/patterns/demo-shell/index.js +1 -0
  239. package/dist/patterns/domain-templates/index.cjs +6 -0
  240. package/dist/patterns/domain-templates/index.d.cts +5 -0
  241. package/dist/patterns/domain-templates/index.d.ts +5 -0
  242. package/dist/patterns/domain-templates/index.js +1 -0
  243. package/dist/patterns/graphspec/index.cjs +83 -0
  244. package/dist/patterns/graphspec/index.d.cts +7 -0
  245. package/dist/patterns/graphspec/index.d.ts +7 -0
  246. package/dist/patterns/graphspec/index.js +1 -0
  247. package/dist/patterns/guarded-execution/index.cjs +6 -0
  248. package/dist/patterns/guarded-execution/index.d.cts +7 -0
  249. package/dist/patterns/guarded-execution/index.d.ts +7 -0
  250. package/dist/patterns/guarded-execution/index.js +1 -0
  251. package/dist/patterns/harness/index.cjs +48 -0
  252. package/dist/patterns/harness/index.d.cts +8 -0
  253. package/dist/patterns/harness/index.d.ts +8 -0
  254. package/dist/patterns/harness/index.js +1 -0
  255. package/dist/patterns/job-queue/index.cjs +6 -0
  256. package/dist/patterns/job-queue/index.d.cts +5 -0
  257. package/dist/patterns/job-queue/index.d.ts +5 -0
  258. package/dist/patterns/job-queue/index.js +1 -0
  259. package/dist/patterns/lens/index.cjs +6 -0
  260. package/dist/patterns/lens/index.d.cts +7 -0
  261. package/dist/patterns/lens/index.d.ts +7 -0
  262. package/dist/patterns/lens/index.js +1 -0
  263. package/dist/patterns/memory/index.cjs +6 -0
  264. package/dist/patterns/memory/index.d.cts +5 -0
  265. package/dist/patterns/memory/index.d.ts +5 -0
  266. package/dist/patterns/memory/index.js +1 -0
  267. package/dist/patterns/messaging/index.cjs +6 -0
  268. package/dist/patterns/messaging/index.d.cts +5 -0
  269. package/dist/patterns/messaging/index.d.ts +5 -0
  270. package/dist/patterns/messaging/index.js +1 -0
  271. package/dist/patterns/orchestration/index.cjs +6 -0
  272. package/dist/patterns/orchestration/index.d.cts +6 -0
  273. package/dist/patterns/orchestration/index.d.ts +6 -0
  274. package/dist/patterns/orchestration/index.js +1 -0
  275. package/dist/patterns/reactive-layout/index.cjs +7 -6444
  276. package/dist/patterns/reactive-layout/index.d.cts +6 -6
  277. package/dist/patterns/reactive-layout/index.d.ts +6 -6
  278. package/dist/patterns/reactive-layout/index.js +1 -56
  279. package/dist/patterns/reduction/index.cjs +6 -0
  280. package/dist/patterns/reduction/index.d.cts +5 -0
  281. package/dist/patterns/reduction/index.d.ts +5 -0
  282. package/dist/patterns/reduction/index.js +1 -0
  283. package/dist/patterns/refine-loop/index.cjs +8 -0
  284. package/dist/patterns/refine-loop/index.d.cts +7 -0
  285. package/dist/patterns/refine-loop/index.d.ts +7 -0
  286. package/dist/patterns/refine-loop/index.js +1 -0
  287. package/dist/patterns/resilient-pipeline/index.cjs +1 -0
  288. package/dist/patterns/resilient-pipeline/index.d.cts +7 -0
  289. package/dist/patterns/resilient-pipeline/index.d.ts +7 -0
  290. package/dist/patterns/resilient-pipeline/index.js +1 -0
  291. package/dist/patterns/surface/index.cjs +14 -0
  292. package/dist/patterns/surface/index.d.cts +8 -0
  293. package/dist/patterns/surface/index.d.ts +8 -0
  294. package/dist/patterns/surface/index.js +1 -0
  295. package/dist/{reactive-layout-MQP--J3F.d.cts → reactive-layout-CpYb5qLP.d.cts} +2 -2
  296. package/dist/{reactive-layout-u5Ulnqag.d.ts → reactive-layout-D8u4wuUR.d.ts} +2 -2
  297. package/dist/reactive-log-DPzuUDj5.d.cts +190 -0
  298. package/dist/reactive-log-YuH9VYN8.d.ts +190 -0
  299. package/dist/{composite-aUCvjZVR.d.ts → reactive-map-CdbNoSgP.d.ts} +2 -67
  300. package/dist/{composite-C7PcQvcs.d.cts → reactive-map-DUeRmb9d.d.cts} +2 -67
  301. package/dist/resilience-Ba5-b4WD.d.cts +493 -0
  302. package/dist/resilience-CGRzhnD3.d.ts +493 -0
  303. package/dist/resilience-QAHKANT5.js +1 -0
  304. package/dist/{sugar-D02n5JjF.d.cts → sugar-BV0htudb.d.cts} +8 -4
  305. package/dist/{sugar-CCOxXK1e.d.ts → sugar-Dtyrq2_q.d.ts} +8 -4
  306. package/dist/topology-tree-CYHOwQZ_.d.ts +25 -0
  307. package/dist/topology-tree-DROUdq5B.d.cts +25 -0
  308. package/dist/types-O3GzJY2U.d.cts +401 -0
  309. package/dist/types-u64Ose53.d.ts +401 -0
  310. package/package.json +252 -22
  311. package/dist/ai-CaR_912Q.d.cts +0 -1033
  312. package/dist/ai-WlRltJV7.d.ts +0 -1033
  313. package/dist/chunk-3ZWCKRHX.js +0 -117
  314. package/dist/chunk-3ZWCKRHX.js.map +0 -1
  315. package/dist/chunk-7TAQJHQV.js +0 -103
  316. package/dist/chunk-7TAQJHQV.js.map +0 -1
  317. package/dist/chunk-APFNLIRG.js +0 -62
  318. package/dist/chunk-APFNLIRG.js.map +0 -1
  319. package/dist/chunk-AT5LKYNL.js +0 -395
  320. package/dist/chunk-AT5LKYNL.js.map +0 -1
  321. package/dist/chunk-BQ6RQQFF.js +0 -5087
  322. package/dist/chunk-BQ6RQQFF.js.map +0 -1
  323. package/dist/chunk-BVZYTZ5H.js +0 -599
  324. package/dist/chunk-BVZYTZ5H.js.map +0 -1
  325. package/dist/chunk-DST5DKZS.js +0 -1371
  326. package/dist/chunk-DST5DKZS.js.map +0 -1
  327. package/dist/chunk-GTE6PWRZ.js +0 -866
  328. package/dist/chunk-GTE6PWRZ.js.map +0 -1
  329. package/dist/chunk-HXZEYDUR.js +0 -94
  330. package/dist/chunk-HXZEYDUR.js.map +0 -1
  331. package/dist/chunk-J22W6HV3.js +0 -107
  332. package/dist/chunk-J22W6HV3.js.map +0 -1
  333. package/dist/chunk-J2VBW3DZ.js +0 -302
  334. package/dist/chunk-J2VBW3DZ.js.map +0 -1
  335. package/dist/chunk-JSCT3CR4.js +0 -38
  336. package/dist/chunk-JSCT3CR4.js.map +0 -1
  337. package/dist/chunk-JWBCY4NC.js +0 -330
  338. package/dist/chunk-JWBCY4NC.js.map +0 -1
  339. package/dist/chunk-K2AUJHVP.js +0 -2251
  340. package/dist/chunk-K2AUJHVP.js.map +0 -1
  341. package/dist/chunk-MJ2NKQQL.js +0 -119
  342. package/dist/chunk-MJ2NKQQL.js.map +0 -1
  343. package/dist/chunk-N6UR7YVY.js +0 -198
  344. package/dist/chunk-N6UR7YVY.js.map +0 -1
  345. package/dist/chunk-NC6S43JJ.js +0 -456
  346. package/dist/chunk-NC6S43JJ.js.map +0 -1
  347. package/dist/chunk-OFVJBJXR.js +0 -98
  348. package/dist/chunk-OFVJBJXR.js.map +0 -1
  349. package/dist/chunk-OHISZPOJ.js +0 -97
  350. package/dist/chunk-OHISZPOJ.js.map +0 -1
  351. package/dist/chunk-OU5CQKNW.js +0 -102
  352. package/dist/chunk-OU5CQKNW.js.map +0 -1
  353. package/dist/chunk-PF7GRZMW.js +0 -2712
  354. package/dist/chunk-PF7GRZMW.js.map +0 -1
  355. package/dist/chunk-PHOUUNK7.js +0 -2291
  356. package/dist/chunk-PHOUUNK7.js.map +0 -1
  357. package/dist/chunk-RNHBMHKA.js +0 -1665
  358. package/dist/chunk-RNHBMHKA.js.map +0 -1
  359. package/dist/chunk-SX52TAR4.js +0 -110
  360. package/dist/chunk-SX52TAR4.js.map +0 -1
  361. package/dist/chunk-VYPWMZ6H.js +0 -98
  362. package/dist/chunk-VYPWMZ6H.js.map +0 -1
  363. package/dist/chunk-WBZOVTYK.js +0 -171
  364. package/dist/chunk-WBZOVTYK.js.map +0 -1
  365. package/dist/chunk-WKNUIZOY.js +0 -354
  366. package/dist/chunk-WKNUIZOY.js.map +0 -1
  367. package/dist/chunk-X3VMZYBT.js +0 -713
  368. package/dist/chunk-X3VMZYBT.js.map +0 -1
  369. package/dist/chunk-X5R3GL6H.js +0 -525
  370. package/dist/chunk-X5R3GL6H.js.map +0 -1
  371. package/dist/chunk-XGPU467M.js +0 -136
  372. package/dist/chunk-XGPU467M.js.map +0 -1
  373. package/dist/compat/index.cjs.map +0 -1
  374. package/dist/compat/index.js.map +0 -1
  375. package/dist/compat/jotai/index.cjs.map +0 -1
  376. package/dist/compat/jotai/index.js.map +0 -1
  377. package/dist/compat/nanostores/index.cjs.map +0 -1
  378. package/dist/compat/nanostores/index.js.map +0 -1
  379. package/dist/compat/nestjs/index.cjs.map +0 -1
  380. package/dist/compat/nestjs/index.js.map +0 -1
  381. package/dist/compat/react/index.cjs.map +0 -1
  382. package/dist/compat/react/index.js.map +0 -1
  383. package/dist/compat/solid/index.cjs.map +0 -1
  384. package/dist/compat/solid/index.js.map +0 -1
  385. package/dist/compat/svelte/index.cjs.map +0 -1
  386. package/dist/compat/svelte/index.js.map +0 -1
  387. package/dist/compat/vue/index.cjs.map +0 -1
  388. package/dist/compat/vue/index.js.map +0 -1
  389. package/dist/compat/zustand/index.cjs.map +0 -1
  390. package/dist/compat/zustand/index.js.map +0 -1
  391. package/dist/core/index.cjs.map +0 -1
  392. package/dist/core/index.js.map +0 -1
  393. package/dist/extra/index.cjs.map +0 -1
  394. package/dist/extra/index.js.map +0 -1
  395. package/dist/extra/sources.cjs.map +0 -1
  396. package/dist/extra/sources.js.map +0 -1
  397. package/dist/graph/index.cjs.map +0 -1
  398. package/dist/graph/index.js.map +0 -1
  399. package/dist/index.cjs.map +0 -1
  400. package/dist/index.js.map +0 -1
  401. package/dist/patterns/ai.cjs +0 -7930
  402. package/dist/patterns/ai.cjs.map +0 -1
  403. package/dist/patterns/ai.d.cts +0 -10
  404. package/dist/patterns/ai.d.ts +0 -10
  405. package/dist/patterns/ai.js +0 -71
  406. package/dist/patterns/ai.js.map +0 -1
  407. package/dist/patterns/audit.cjs +0 -5805
  408. package/dist/patterns/audit.cjs.map +0 -1
  409. package/dist/patterns/audit.d.cts +0 -6
  410. package/dist/patterns/audit.d.ts +0 -6
  411. package/dist/patterns/audit.js +0 -29
  412. package/dist/patterns/audit.js.map +0 -1
  413. package/dist/patterns/demo-shell.cjs +0 -5604
  414. package/dist/patterns/demo-shell.cjs.map +0 -1
  415. package/dist/patterns/demo-shell.d.cts +0 -6
  416. package/dist/patterns/demo-shell.d.ts +0 -6
  417. package/dist/patterns/demo-shell.js +0 -15
  418. package/dist/patterns/demo-shell.js.map +0 -1
  419. package/dist/patterns/memory.cjs +0 -5283
  420. package/dist/patterns/memory.cjs.map +0 -1
  421. package/dist/patterns/memory.d.cts +0 -5
  422. package/dist/patterns/memory.d.ts +0 -5
  423. package/dist/patterns/memory.js +0 -20
  424. package/dist/patterns/memory.js.map +0 -1
  425. package/dist/patterns/reactive-layout/index.cjs.map +0 -1
  426. package/dist/patterns/reactive-layout/index.js.map +0 -1
  427. package/dist/storage-CMjUUuxn.d.ts +0 -190
  428. package/dist/storage-DdWlZo6U.d.cts +0 -190
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/patterns/ai.ts","../../src/core/batch.ts","../../src/core/clock.ts","../../src/core/messages.ts","../../src/graph/codec.ts","../../src/core/actor.ts","../../src/core/config.ts","../../src/core/guard.ts","../../src/core/versioning.ts","../../src/core/node.ts","../../src/core/sugar.ts","../../src/extra/sources.ts","../../src/extra/operators.ts","../../src/extra/reactive-map.ts","../../src/extra/composite.ts","../../src/extra/reactive-log.ts","../../src/extra/timer.ts","../../src/core/meta.ts","../../src/extra/utils/ring-buffer.ts","../../src/graph/explain.ts","../../src/extra/utils/sizeof.ts","../../src/graph/profile.ts","../../src/graph/graph.ts","../../src/patterns/memory.ts","../../src/patterns/_internal.ts","../../src/patterns/messaging.ts","../../src/patterns/orchestration.ts"],"sourcesContent":["/**\n * AI surface patterns (roadmap §4.4).\n *\n * Domain-layer factories for LLM-backed agents, chat, tool registries, and\n * agentic memory. Composed from core + extra + Phase 3–4.3 primitives.\n */\n\nimport type { Actor } from \"../core/actor.js\";\nimport { batch } from \"../core/batch.js\";\nimport { monotonicNs } from \"../core/clock.js\";\nimport { COMPLETE, DATA, ERROR } from \"../core/messages.js\";\nimport type { Node } from \"../core/node.js\";\nimport { derived, effect, producer, state } from \"../core/sugar.js\";\nimport {\n\ttype DistillBundle,\n\ttype DistillOptions,\n\tdistill,\n\ttype Extraction,\n} from \"../extra/composite.js\";\nimport { switchMap } from \"../extra/operators.js\";\nimport { type ReactiveLogBundle, reactiveLog } from \"../extra/reactive-log.js\";\nimport { fromAny, fromTimer, type NodeInput } from \"../extra/sources.js\";\nimport type { StorageHandle, StorageTier } from \"../extra/storage.js\";\nimport { ResettableTimer } from \"../extra/timer.js\";\nimport {\n\tGraph,\n\ttype GraphAttachStorageOptions,\n\ttype GraphOptions,\n\ttype GraphPersistSnapshot,\n} from \"../graph/graph.js\";\nimport {\n\tdecay,\n\ttype KnowledgeGraphGraph,\n\tknowledgeGraph,\n\ttype LightCollectionBundle,\n\tlightCollection,\n\ttype VectorIndexBundle,\n\ttype VectorSearchResult,\n\tvectorIndex,\n} from \"./memory.js\";\nimport { type TopicGraph, topic } from \"./messaging.js\";\nimport { type GateController, type GateOptions, gate } from \"./orchestration.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A single chat message in a conversation. */\nexport type ChatMessage = {\n\treadonly role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n\treadonly content: string;\n\treadonly name?: string;\n\treadonly toolCallId?: string;\n\treadonly toolCalls?: readonly ToolCall[];\n\treadonly metadata?: Record<string, unknown>;\n};\n\n/** A tool invocation request from an LLM. */\nexport type ToolCall = {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly arguments: Record<string, unknown>;\n};\n\n/** The response from an LLM invocation. */\nexport type LLMResponse = {\n\treadonly content: string;\n\treadonly toolCalls?: readonly ToolCall[];\n\treadonly usage?: { readonly inputTokens: number; readonly outputTokens: number };\n\treadonly finishReason?: string;\n\treadonly metadata?: Record<string, unknown>;\n};\n\n/** Provider-agnostic LLM client adapter protocol. */\nexport type LLMAdapter = {\n\tinvoke(messages: readonly ChatMessage[], opts?: LLMInvokeOptions): NodeInput<LLMResponse>;\n\tstream(messages: readonly ChatMessage[], opts?: LLMInvokeOptions): AsyncIterable<string>;\n};\n\nexport type LLMInvokeOptions = {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\ttools?: readonly ToolDefinition[];\n\tsystemPrompt?: string;\n\tsignal?: AbortSignal;\n};\n\n/** A tool definition for LLM consumption. */\nexport type ToolDefinition = {\n\treadonly name: string;\n\treadonly description: string;\n\treadonly parameters: Record<string, unknown>; // JSON Schema\n\treadonly handler: (args: Record<string, unknown>) => NodeInput<unknown>;\n\t/**\n\t * V0 version of the backing node at `knobsAsTools()` call time (§6.0b).\n\t * Snapshot — re-call `knobsAsTools()` to refresh.\n\t */\n\treadonly version?: { id: string; version: number };\n};\n\nexport type AgentLoopStatus = \"idle\" | \"thinking\" | \"acting\" | \"done\" | \"error\";\n\n/**\n * A single chunk from any streaming source (LLM tokens, WebSocket, SSE, file tail).\n * Generic enough for any streaming source, not just LLM.\n */\nexport type StreamChunk = {\n\t/** Identifier for the stream source (adapter name, URL, etc.). */\n\treadonly source: string;\n\t/** This chunk's content. */\n\treadonly token: string;\n\t/** Full accumulated text so far. */\n\treadonly accumulated: string;\n\t/** 0-based chunk counter. */\n\treadonly index: number;\n};\n\n// ---------------------------------------------------------------------------\n// Meta helpers\n// ---------------------------------------------------------------------------\n\nimport { domainMeta, keepalive } from \"./_internal.js\";\n\nfunction aiMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"ai\", kind, extra);\n}\n\nfunction isPromiseLike(x: unknown): x is PromiseLike<unknown> {\n\treturn x != null && typeof (x as PromiseLike<unknown>).then === \"function\";\n}\n\nfunction isNodeLike(x: unknown): x is Node<unknown> {\n\treturn (\n\t\ttypeof x === \"object\" &&\n\t\tx !== null &&\n\t\t\"subscribe\" in x &&\n\t\ttypeof (x as Node<unknown>).subscribe === \"function\" &&\n\t\t\"cache\" in x\n\t);\n}\n\nfunction isAsyncIterableLike(x: unknown): x is AsyncIterable<unknown> {\n\treturn (\n\t\tx != null &&\n\t\ttypeof x === \"object\" &&\n\t\tSymbol.asyncIterator in x &&\n\t\ttypeof (x as AsyncIterable<unknown>)[Symbol.asyncIterator] === \"function\"\n\t);\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** First settled `DATA` from a `Node` (do not pass plain strings — `fromAny` would iterate chars). */\nfunction firstDataFromNode(\n\tresolved: Node<unknown>,\n\topts?: { timeoutMs?: number },\n): Promise<unknown> {\n\t// Only trust get() when node is in settled state\n\tif ((resolved as { status?: string }).status === \"settled\") {\n\t\tconst immediate = resolved.cache;\n\t\tif (immediate !== undefined) {\n\t\t\treturn Promise.resolve(immediate);\n\t\t}\n\t}\n\tconst timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\treturn new Promise((resolve, reject) => {\n\t\tconst timer = new ResettableTimer();\n\t\tconst unsub = resolved.subscribe((messages) => {\n\t\t\tfor (const msg of messages) {\n\t\t\t\tif (msg[0] === DATA) {\n\t\t\t\t\ttimer.cancel();\n\t\t\t\t\tunsub();\n\t\t\t\t\tresolve(msg[1]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (msg[0] === ERROR) {\n\t\t\t\t\ttimer.cancel();\n\t\t\t\t\tunsub();\n\t\t\t\t\treject(msg[1]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (msg[0] === COMPLETE) {\n\t\t\t\t\ttimer.cancel();\n\t\t\t\t\tunsub();\n\t\t\t\t\treject(new Error(\"firstDataFromNode: completed without producing a value\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\ttimer.start(timeoutMs, () => {\n\t\t\tunsub();\n\t\t\treject(new Error(`firstDataFromNode: timed out after ${timeoutMs}ms`));\n\t\t});\n\t});\n}\n\n/** Await Promise-likes, then resolve `Node` / async-iterable inputs via `fromAny` + first `DATA`. */\nasync function resolveToolHandlerResult(value: unknown): Promise<unknown> {\n\tif (isPromiseLike(value)) {\n\t\treturn resolveToolHandlerResult(await value);\n\t}\n\tif (isNodeLike(value)) {\n\t\treturn firstDataFromNode(value);\n\t}\n\tif (isAsyncIterableLike(value)) {\n\t\treturn firstDataFromNode(fromAny(value as NodeInput<unknown>));\n\t}\n\treturn value;\n}\n\n// ---------------------------------------------------------------------------\n// fromLLM\n// ---------------------------------------------------------------------------\n\nexport type FromLLMOptions = {\n\tname?: string;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\ttools?: readonly ToolDefinition[];\n\tsystemPrompt?: string;\n};\n\n/**\n * Reactive LLM invocation adapter. Returns a derived node that re-invokes\n * the LLM whenever the messages dep changes.\n *\n * Uses `switchMap` internally — new invocations cancel stale in-flight ones.\n */\nexport function fromLLM(\n\tadapter: LLMAdapter,\n\tmessages: NodeInput<readonly ChatMessage[]>,\n\topts?: FromLLMOptions,\n): Node<LLMResponse | null> {\n\tconst msgsNode = fromAny(messages);\n\tconst result = switchMap(msgsNode, (msgs) => {\n\t\tif (!msgs || (msgs as readonly ChatMessage[]).length === 0) {\n\t\t\treturn state<LLMResponse | null>(null) as NodeInput<LLMResponse | null>;\n\t\t}\n\t\tconst tools = opts?.tools;\n\t\treturn adapter.invoke(msgs as readonly ChatMessage[], {\n\t\t\tmodel: opts?.model,\n\t\t\ttemperature: opts?.temperature,\n\t\t\tmaxTokens: opts?.maxTokens,\n\t\t\ttools,\n\t\t\tsystemPrompt: opts?.systemPrompt,\n\t\t}) as NodeInput<LLMResponse | null>;\n\t});\n\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// streamingPromptNode\n// ---------------------------------------------------------------------------\n\nexport type StreamingPromptNodeOptions = {\n\tname?: string;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Output format — `\"json\"` attempts JSON.parse on the final accumulated text. Default: `\"text\"`. */\n\tformat?: \"text\" | \"json\";\n\tsystemPrompt?: string;\n};\n\n/**\n * Bundle returned by {@link streamingPromptNode}.\n */\nexport type StreamingPromptNodeHandle<T> = {\n\t/** Final parsed result (emits once per invocation, after stream completes). */\n\toutput: Node<T | null>;\n\t/** Live stream topic — subscribe to `stream.latest` or `stream.events` for chunks. */\n\tstream: TopicGraph<StreamChunk>;\n\t/** Tear down the keepalive subscription and release resources. */\n\tdispose: () => void;\n};\n\n/**\n * Streaming LLM transform: wraps a prompt template + adapter into a reactive\n * streaming pipeline. Re-invokes the LLM whenever any dep changes; the\n * previous in-flight stream is canceled automatically via `switchMap`.\n *\n * Each token chunk is published to a {@link TopicGraph} as a {@link StreamChunk}.\n * Extractors can mount on the topic independently (see {@link streamExtractor}).\n * Zero overhead if nobody subscribes to the stream topic.\n *\n * The `output` node emits the final parsed result (like {@link promptNode}).\n * The async boundary is handled by `fromAny` (spec §5.10 compliant).\n */\nexport function streamingPromptNode<T = string>(\n\tadapter: LLMAdapter,\n\tdeps: readonly Node<unknown>[],\n\tprompt: string | ((...depValues: unknown[]) => string),\n\topts?: StreamingPromptNodeOptions,\n): StreamingPromptNodeHandle<T> {\n\tconst sourceName = opts?.name ?? \"llm\";\n\tconst format = opts?.format ?? \"text\";\n\tconst streamTopic = topic<StreamChunk>(`${sourceName}/stream`);\n\n\tconst messagesNode = derived<readonly ChatMessage[]>(deps as Node<unknown>[], (values) => {\n\t\tif (values.some((v) => v == null)) return [];\n\t\tconst text = typeof prompt === \"string\" ? prompt : prompt(...values);\n\t\tif (!text) return [];\n\t\tconst msgs: ChatMessage[] = [];\n\t\tif (opts?.systemPrompt) msgs.push({ role: \"system\", content: opts.systemPrompt });\n\t\tmsgs.push({ role: \"user\", content: text });\n\t\treturn msgs;\n\t});\n\n\tconst output = switchMap(messagesNode, (msgs) => {\n\t\tconst chatMsgs = msgs as readonly ChatMessage[];\n\t\tif (!chatMsgs || chatMsgs.length === 0) {\n\t\t\treturn state<T | null>(null) as NodeInput<T | null>;\n\t\t}\n\n\t\tconst ac = new AbortController();\n\n\t\tasync function* pumpAndCollect(): AsyncGenerator<T | null> {\n\t\t\tlet accumulated = \"\";\n\t\t\tlet index = 0;\n\t\t\ttry {\n\t\t\t\tfor await (const token of adapter.stream(chatMsgs, {\n\t\t\t\t\tmodel: opts?.model,\n\t\t\t\t\ttemperature: opts?.temperature,\n\t\t\t\t\tmaxTokens: opts?.maxTokens,\n\t\t\t\t\tsystemPrompt: opts?.systemPrompt,\n\t\t\t\t\tsignal: ac.signal,\n\t\t\t\t})) {\n\t\t\t\t\taccumulated += token;\n\t\t\t\t\tstreamTopic.publish({\n\t\t\t\t\t\tsource: sourceName,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\taccumulated,\n\t\t\t\t\t\tindex: index++,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tlet result: T | null;\n\t\t\t\tif (format === \"json\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = JSON.parse(stripFences(accumulated)) as T;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tresult = null;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult = accumulated as unknown as T;\n\t\t\t\t}\n\t\t\t\tyield result;\n\t\t\t} finally {\n\t\t\t\tac.abort();\n\t\t\t}\n\t\t}\n\n\t\treturn fromAny(pumpAndCollect());\n\t});\n\n\tconst unsub = keepalive(output);\n\n\treturn {\n\t\toutput,\n\t\tstream: streamTopic,\n\t\tdispose: () => {\n\t\t\tunsub();\n\t\t\tstreamTopic.destroy();\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// streamExtractor\n// ---------------------------------------------------------------------------\n\n/**\n * Mounts an extractor function on a streaming topic. Returns a derived node\n * that emits extracted values as chunks arrive.\n *\n * `extractFn` receives the accumulated text from the latest chunk and returns\n * the extracted value, or `null` if nothing detected yet. This is the building\n * block for keyword flags, tool call detection, cost metering, etc.\n *\n * @param streamTopic - The stream topic to extract from.\n * @param extractFn - `(accumulated: string) => T | null`.\n * @param opts - Optional name.\n * @returns Derived node emitting extracted values.\n */\nexport function streamExtractor<T>(\n\tstreamTopic: TopicGraph<StreamChunk>,\n\textractFn: (accumulated: string) => T | null,\n\topts?: {\n\t\tname?: string;\n\t\t/**\n\t\t * Optional structural equals for the extractor output. When two\n\t\t * consecutive chunks produce structurally-equal outputs, the framework\n\t\t * emits `RESOLVED` instead of `DATA`, saving downstream work. Default:\n\t\t * reference equality (`Object.is`). The library cannot know your\n\t\t * output shape — supply this when your `extractFn` returns structured\n\t\t * objects or arrays.\n\t\t */\n\t\tequals?: (a: T | null, b: T | null) => boolean;\n\t},\n): Node<T | null> {\n\treturn derived<T | null>(\n\t\t[streamTopic.latest as Node<StreamChunk | null>],\n\t\t([chunk]) => {\n\t\t\tif (chunk == null) return null;\n\t\t\treturn extractFn((chunk as StreamChunk).accumulated);\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"extractor\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: null,\n\t\t\tmeta: aiMeta(\"stream_extractor\"),\n\t\t\t...(opts?.equals ? { equals: opts.equals } : {}),\n\t\t},\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// keywordFlagExtractor\n// ---------------------------------------------------------------------------\n\n/** A keyword match detected in the stream. */\nexport type KeywordFlag = {\n\treadonly label: string;\n\treadonly pattern: RegExp;\n\treadonly match: string;\n\treadonly position: number;\n};\n\nexport type KeywordFlagExtractorOptions = {\n\tpatterns: readonly { pattern: RegExp; label: string }[];\n\tname?: string;\n\t/**\n\t * Maximum length of any pattern's literal text. Used as an overlap window\n\t * when cursoring through the accumulated stream so matches that span\n\t * chunk boundaries aren't missed. Default: 128.\n\t */\n\tmaxPatternLength?: number;\n};\n\nconst keywordFlagsEqual = (\n\ta: readonly KeywordFlag[] | null,\n\tb: readonly KeywordFlag[] | null,\n): boolean => {\n\tif (a === b) return true;\n\tif (a == null || b == null) return a === b;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst x = a[i];\n\t\tconst y = b[i];\n\t\tif (\n\t\t\tx.label !== y.label ||\n\t\t\tx.pattern !== y.pattern ||\n\t\t\tx.match !== y.match ||\n\t\t\tx.position !== y.position\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n};\n\n/**\n * Mounts a keyword-flag extractor on a streaming topic. Scans accumulated text\n * for all configured patterns and emits an array of matches.\n *\n * Use cases: design invariant violations (`setTimeout`, `EventEmitter`), PII\n * detection (SSN, email, phone), toxicity keywords, off-track reasoning.\n *\n * **Streaming optimization.** Maintains a cursor across chunks in `ctx.store`\n * so each chunk scans only the delta region `accumulated.slice(scannedTo -\n * maxPatternLength)` — not the full string. Default structural equals\n * suppresses DATA emission when no new flags were found this chunk.\n */\nexport function keywordFlagExtractor(\n\tstreamTopic: TopicGraph<StreamChunk>,\n\topts: KeywordFlagExtractorOptions,\n): Node<readonly KeywordFlag[]> {\n\tconst maxPatternLength = opts.maxPatternLength ?? 128;\n\treturn derived<readonly KeywordFlag[]>(\n\t\t[streamTopic.latest as Node<StreamChunk | null>],\n\t\t([chunk], ctx) => {\n\t\t\tif (chunk == null) return [];\n\t\t\tconst accumulated = (chunk as StreamChunk).accumulated;\n\n\t\t\tif (!(\"flags\" in ctx.store)) {\n\t\t\t\tctx.store.flags = [] as KeywordFlag[];\n\t\t\t\tctx.store.scannedTo = 0;\n\t\t\t}\n\t\t\tconst flags = ctx.store.flags as KeywordFlag[];\n\t\t\tconst scannedTo = ctx.store.scannedTo as number;\n\n\t\t\t// Scan the delta plus an overlap window so matches that span\n\t\t\t// chunk boundaries (e.g. \"EventE\" + \"mitter\") are still found.\n\t\t\tconst startOffset = Math.max(0, scannedTo - maxPatternLength);\n\t\t\tconst region = accumulated.slice(startOffset);\n\t\t\tlet added = false;\n\t\t\tfor (const { pattern, label } of opts.patterns) {\n\t\t\t\tconst re = new RegExp(pattern.source, `${pattern.flags.replace(\"g\", \"\")}g`);\n\t\t\t\tfor (const m of region.matchAll(re)) {\n\t\t\t\t\tconst pos = startOffset + m.index!;\n\t\t\t\t\t// Skip matches that end inside the already-scanned prefix.\n\t\t\t\t\tif (pos + m[0].length <= scannedTo) continue;\n\t\t\t\t\tflags.push({ label, pattern, match: m[0], position: pos });\n\t\t\t\t\tadded = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tctx.store.scannedTo = accumulated.length;\n\n\t\t\t// Always return a fresh copy so downstream never holds a live\n\t\t\t// reference to ctx.store.flags. Structural equals suppresses the\n\t\t\t// emission when no new flag was added this chunk.\n\t\t\treturn added ? [...flags] : flags.slice();\n\t\t},\n\t\t{\n\t\t\tname: opts.name ?? \"keyword-flag-extractor\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: [],\n\t\t\tmeta: aiMeta(\"keyword_flag_extractor\"),\n\t\t\tequals: keywordFlagsEqual,\n\t\t},\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// toolCallExtractor\n// ---------------------------------------------------------------------------\n\n/** A tool call detected in the stream. */\nexport type ExtractedToolCall = {\n\treadonly name: string;\n\treadonly arguments: Record<string, unknown>;\n\treadonly raw: string;\n\treadonly startIndex: number;\n};\n\nconst toolCallsEqual = (\n\ta: readonly ExtractedToolCall[] | null,\n\tb: readonly ExtractedToolCall[] | null,\n): boolean => {\n\tif (a === b) return true;\n\tif (a == null || b == null) return a === b;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst x = a[i];\n\t\tconst y = b[i];\n\t\tif (x.startIndex !== y.startIndex || x.name !== y.name || x.raw !== y.raw) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n};\n\n/**\n * Mounts a tool-call extractor on a streaming topic. Scans accumulated text\n * for complete JSON objects containing `\"name\"` and `\"arguments\"` keys (the\n * standard tool_call shape). Partial JSON is ignored until the closing brace.\n *\n * Feeds into the tool interception chain for reactive tool gating mid-stream.\n *\n * **Streaming optimization.** Maintains a cursor (`scanFrom`) in `ctx.store`\n * so each chunk resumes brace-scanning from the position after the last\n * complete parse (or the last incomplete open brace). Already-parsed objects\n * are not re-parsed. Default structural equals suppresses DATA emission when\n * no new tool call completed this chunk.\n */\nexport function toolCallExtractor(\n\tstreamTopic: TopicGraph<StreamChunk>,\n\topts?: { name?: string },\n): Node<readonly ExtractedToolCall[]> {\n\treturn derived<readonly ExtractedToolCall[]>(\n\t\t[streamTopic.latest as Node<StreamChunk | null>],\n\t\t([chunk], ctx) => {\n\t\t\tif (chunk == null) return [];\n\t\t\tconst accumulated = (chunk as StreamChunk).accumulated;\n\n\t\t\tif (!(\"calls\" in ctx.store)) {\n\t\t\t\tctx.store.calls = [] as ExtractedToolCall[];\n\t\t\t\tctx.store.scanFrom = 0;\n\t\t\t}\n\t\t\tconst calls = ctx.store.calls as ExtractedToolCall[];\n\t\t\tlet i = ctx.store.scanFrom as number;\n\t\t\tlet added = false;\n\n\t\t\twhile (i < accumulated.length) {\n\t\t\t\tconst start = accumulated.indexOf(\"{\", i);\n\t\t\t\tif (start === -1) {\n\t\t\t\t\tctx.store.scanFrom = accumulated.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlet depth = 0;\n\t\t\t\tlet end = -1;\n\t\t\t\tlet inString = false;\n\t\t\t\tfor (let j = start; j < accumulated.length; j++) {\n\t\t\t\t\tconst ch = accumulated[j];\n\t\t\t\t\tif (inString) {\n\t\t\t\t\t\tif (ch === \"\\\\\" && j + 1 < accumulated.length) {\n\t\t\t\t\t\t\tj++; // skip escaped character\n\t\t\t\t\t\t} else if (ch === '\"') {\n\t\t\t\t\t\t\tinString = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (ch === '\"') {\n\t\t\t\t\t\tinString = true;\n\t\t\t\t\t} else if (ch === \"{\") {\n\t\t\t\t\t\tdepth++;\n\t\t\t\t\t} else if (ch === \"}\") {\n\t\t\t\t\t\tdepth--;\n\t\t\t\t\t\tif (depth === 0) {\n\t\t\t\t\t\t\tend = j;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (end === -1) {\n\t\t\t\t\t// Incomplete — resume brace-scanning from this open brace\n\t\t\t\t\t// next chunk. Do NOT advance past it.\n\t\t\t\t\tctx.store.scanFrom = start;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tconst raw = accumulated.slice(start, end + 1);\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw) as Record<string, unknown>;\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof parsed.name === \"string\" &&\n\t\t\t\t\t\tparsed.arguments != null &&\n\t\t\t\t\t\ttypeof parsed.arguments === \"object\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tcalls.push({\n\t\t\t\t\t\t\tname: parsed.name,\n\t\t\t\t\t\t\targuments: parsed.arguments as Record<string, unknown>,\n\t\t\t\t\t\t\traw,\n\t\t\t\t\t\t\tstartIndex: start,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tadded = true;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Not valid JSON — skip\n\t\t\t\t}\n\t\t\t\ti = end + 1;\n\t\t\t\tctx.store.scanFrom = i;\n\t\t\t}\n\n\t\t\t// Always return a fresh copy so downstream never holds a live\n\t\t\t// reference to ctx.store.calls.\n\t\t\treturn added ? [...calls] : calls.slice();\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"tool-call-extractor\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: [],\n\t\t\tmeta: aiMeta(\"tool_call_extractor\"),\n\t\t\tequals: toolCallsEqual,\n\t\t},\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// costMeterExtractor\n// ---------------------------------------------------------------------------\n\n/** A cost meter reading from the stream. */\nexport type CostMeterReading = {\n\treadonly chunkCount: number;\n\treadonly charCount: number;\n\treadonly estimatedTokens: number;\n};\n\nexport type CostMeterOptions = {\n\t/** Characters per token approximation. Default: 4 (GPT-family). */\n\tcharsPerToken?: number;\n\tname?: string;\n};\n\nconst costMeterEqual = (a: CostMeterReading, b: CostMeterReading): boolean => {\n\tif (a === b) return true;\n\treturn (\n\t\ta.chunkCount === b.chunkCount &&\n\t\ta.charCount === b.charCount &&\n\t\ta.estimatedTokens === b.estimatedTokens\n\t);\n};\n\n/**\n * Mounts a cost meter on a streaming topic. Counts chunks, characters, and\n * estimates token count. Compose with `budgetGate` for hard-stop when LLM\n * output exceeds budget mid-generation.\n *\n * Default structural equals suppresses DATA emission when two consecutive\n * readings are identical (same chunk count + char count + token estimate).\n */\nexport function costMeterExtractor(\n\tstreamTopic: TopicGraph<StreamChunk>,\n\topts?: CostMeterOptions,\n): Node<CostMeterReading> {\n\tconst charsPerToken = opts?.charsPerToken ?? 4;\n\treturn derived<CostMeterReading>(\n\t\t[streamTopic.latest as Node<StreamChunk | null>],\n\t\t([chunk]) => {\n\t\t\tif (chunk == null) return { chunkCount: 0, charCount: 0, estimatedTokens: 0 };\n\t\t\tconst c = chunk as StreamChunk;\n\t\t\tconst charCount = c.accumulated.length;\n\t\t\treturn {\n\t\t\t\tchunkCount: c.index + 1,\n\t\t\t\tcharCount,\n\t\t\t\testimatedTokens: Math.ceil(charCount / charsPerToken),\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"cost-meter\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: { chunkCount: 0, charCount: 0, estimatedTokens: 0 },\n\t\t\tmeta: aiMeta(\"cost_meter_extractor\"),\n\t\t\tequals: costMeterEqual,\n\t\t},\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Composition B: Content safety pipeline\n// ---------------------------------------------------------------------------\n\n/** Options for {@link redactor}. */\nexport type RedactorOptions = {\n\tname?: string;\n};\n\n/**\n * Stream extractor that replaces matched patterns in the accumulated text.\n *\n * Returns a derived node emitting a sanitized `StreamChunk` on every chunk:\n * `accumulated` and `token` have matched substrings replaced by `replaceFn`.\n * The default `replaceFn` replaces with `\"[REDACTED]\"`.\n *\n * Compose with `contentGate` for in-flight safety pipelines.\n *\n * @param streamTopic - Streaming topic to monitor.\n * @param patterns - Array of RegExps to match against accumulated text.\n * @param replaceFn - Replacement producer (default: always `\"[REDACTED]\"`).\n */\nexport function redactor(\n\tstreamTopic: TopicGraph<StreamChunk>,\n\tpatterns: RegExp[],\n\treplaceFn?: (match: string, pattern: RegExp) => string,\n\topts?: RedactorOptions,\n): Node<StreamChunk> {\n\tconst replace = replaceFn ?? (() => \"[REDACTED]\");\n\n\tfunction sanitize(text: string): string {\n\t\tlet result = text;\n\t\tfor (const pat of patterns) {\n\t\t\tconst global = pat.global ? pat : new RegExp(pat.source, `${pat.flags}g`);\n\t\t\tresult = result.replace(global, (m) => replace(m, pat));\n\t\t}\n\t\treturn result;\n\t}\n\n\treturn derived<StreamChunk>(\n\t\t[streamTopic.latest as Node<StreamChunk | null>],\n\t\t([chunk]) => {\n\t\t\tif (chunk == null) {\n\t\t\t\treturn { source: \"\", token: \"\", accumulated: \"\", index: -1 };\n\t\t\t}\n\t\t\tconst c = chunk as StreamChunk;\n\t\t\tconst sanitizedAccumulated = sanitize(c.accumulated);\n\t\t\tconst sanitizedToken = sanitize(c.token);\n\t\t\treturn {\n\t\t\t\tsource: c.source,\n\t\t\t\ttoken: sanitizedToken,\n\t\t\t\taccumulated: sanitizedAccumulated,\n\t\t\t\tindex: c.index,\n\t\t\t};\n\t\t},\n\t\t{ name: opts?.name ?? \"redactor\" },\n\t);\n}\n\n// ---------------------------------------------------------------------------\n\n/** Content safety decision. */\nexport type ContentDecision = \"allow\" | \"block\" | \"review\";\n\n/** Options for {@link contentGate}. */\nexport type ContentGateOptions = {\n\t/**\n\t * Hard-block threshold multiplier (default 1.5).\n\t * Scores above `threshold * hardMultiplier` emit `\"block\"`.\n\t * Scores between `threshold` and that emit `\"review\"`.\n\t */\n\thardMultiplier?: number;\n\tname?: string;\n};\n\n/**\n * Derived node that classifies accumulated stream text as `\"allow\"`,\n * `\"review\"`, or `\"block\"` based on a classifier score.\n *\n * Emits a three-way decision on every new chunk:\n * - `\"allow\"` — score below `threshold`\n * - `\"review\"` — score in `[threshold, threshold × hardMultiplier)`\n * - `\"block\"` — score at or above `threshold × hardMultiplier`\n *\n * Wire the output into a `valve` (automatic) or `gate` (human approval).\n * This node does not itself control flow — it just classifies.\n *\n * @param streamTopic - Streaming topic to classify.\n * @param classifier - `(accumulated: string) => number` scoring function, or\n * a `Node<number>` for live scores.\n * @param threshold - Score at which output becomes \"review\" or \"block\".\n */\nexport function contentGate(\n\tstreamTopic: TopicGraph<StreamChunk>,\n\tclassifier: ((accumulated: string) => number) | Node<number>,\n\tthreshold: number,\n\topts?: ContentGateOptions,\n): Node<ContentDecision> {\n\tconst hardThreshold = threshold * (opts?.hardMultiplier ?? 1.5);\n\tconst isNodeClassifier = typeof classifier !== \"function\";\n\n\tconst deps: Node<unknown>[] = [streamTopic.latest as Node<StreamChunk | null>];\n\tif (isNodeClassifier) deps.push(classifier as Node<unknown>);\n\n\treturn derived<ContentDecision>(\n\t\tdeps,\n\t\t(values) => {\n\t\t\tconst chunk = values[0] as StreamChunk | undefined;\n\t\t\tif (chunk == null) return \"allow\";\n\n\t\t\tconst score = isNodeClassifier\n\t\t\t\t? ((values[1] as number | undefined) ?? 0)\n\t\t\t\t: (classifier as (text: string) => number)(chunk.accumulated);\n\n\t\t\tif (score >= hardThreshold) return \"block\";\n\t\t\tif (score >= threshold) return \"review\";\n\t\t\treturn \"allow\";\n\t\t},\n\t\t{ name: opts?.name ?? \"content-gate\", initial: \"allow\" },\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// gatedStream\n// ---------------------------------------------------------------------------\n\nexport type GatedStreamOptions = StreamingPromptNodeOptions & {\n\t/** Gate options (maxPending, startOpen). */\n\tgate?: Omit<GateOptions, \"meta\">;\n};\n\n/**\n * Bundle returned by {@link gatedStream}.\n */\nexport type GatedStreamHandle<T> = {\n\t/** Final parsed result (after gate approval). */\n\toutput: Node<T | null>;\n\t/** Live stream topic — subscribe to `stream.latest` for chunks. */\n\tstream: TopicGraph<StreamChunk>;\n\t/** Gate controller — approve, reject (aborts in-flight stream), modify. */\n\tgate: GateController<T | null>;\n\t/** Tear down everything. */\n\tdispose: () => void;\n};\n\n/**\n * Streaming LLM transform with human-in-the-loop gate integration.\n *\n * Composes {@link streamingPromptNode} with {@link gate} so that:\n * - `gate.reject()` discards the pending value **and** aborts the in-flight\n * stream (cancels the `AbortController`).\n * - `gate.modify()` transforms the pending value before forwarding downstream.\n * - `gate.approve()` forwards the final result as normal.\n *\n * The abort-on-reject works by toggling an internal cancel signal that causes\n * the `switchMap` inside `streamingPromptNode` to restart with an empty message\n * list, which triggers the `AbortController.abort()` in the async generator's\n * `finally` block.\n */\nexport function gatedStream<T = string>(\n\tgraph: Graph,\n\tname: string,\n\tadapter: LLMAdapter,\n\tdeps: readonly Node<unknown>[],\n\tprompt: string | ((...depValues: unknown[]) => string),\n\topts?: GatedStreamOptions,\n): GatedStreamHandle<T> {\n\t// Cancel signal: toggling this forces switchMap to restart (aborting stream).\n\tconst cancelSignal = state<number>(0, { name: `${name}/cancel` });\n\tlet cancelCounter = 0;\n\n\t// Build the streaming prompt node with cancelSignal as an extra dep.\n\t// The cancel dep is excluded from prompt template arguments.\n\tconst allDeps = [...deps, cancelSignal] as readonly Node<unknown>[];\n\n\tconst sourceName = opts?.name ?? name;\n\tconst format = opts?.format ?? \"text\";\n\tconst streamTopic = topic<StreamChunk>(`${sourceName}/stream`);\n\n\tconst messagesNode = derived<readonly ChatMessage[]>(allDeps as Node<unknown>[], (values) => {\n\t\t// Last dep is the cancel signal — exclude from prompt args\n\t\tconst depValues = values.slice(0, -1);\n\t\tif (depValues.some((v) => v == null)) return [];\n\t\tconst text = typeof prompt === \"string\" ? prompt : prompt(...depValues);\n\t\tif (!text) return [];\n\t\tconst msgs: ChatMessage[] = [];\n\t\tif (opts?.systemPrompt) msgs.push({ role: \"system\", content: opts.systemPrompt });\n\t\tmsgs.push({ role: \"user\", content: text });\n\t\treturn msgs;\n\t});\n\n\tconst output = switchMap(messagesNode, (msgs) => {\n\t\tconst chatMsgs = msgs as readonly ChatMessage[];\n\t\tif (!chatMsgs || chatMsgs.length === 0) {\n\t\t\treturn state<T | null>(null) as NodeInput<T | null>;\n\t\t}\n\n\t\tconst ac = new AbortController();\n\n\t\tasync function* pumpAndCollect(): AsyncGenerator<T | null> {\n\t\t\tlet accumulated = \"\";\n\t\t\tlet index = 0;\n\t\t\ttry {\n\t\t\t\tfor await (const token of adapter.stream(chatMsgs, {\n\t\t\t\t\tmodel: opts?.model,\n\t\t\t\t\ttemperature: opts?.temperature,\n\t\t\t\t\tmaxTokens: opts?.maxTokens,\n\t\t\t\t\tsystemPrompt: opts?.systemPrompt,\n\t\t\t\t\tsignal: ac.signal,\n\t\t\t\t})) {\n\t\t\t\t\taccumulated += token;\n\t\t\t\t\tstreamTopic.publish({\n\t\t\t\t\t\tsource: sourceName,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\taccumulated,\n\t\t\t\t\t\tindex: index++,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tlet result: T | null;\n\t\t\t\tif (format === \"json\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = JSON.parse(stripFences(accumulated)) as T;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tresult = null;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult = accumulated as unknown as T;\n\t\t\t\t}\n\t\t\t\tyield result;\n\t\t\t} finally {\n\t\t\t\tac.abort();\n\t\t\t}\n\t\t}\n\n\t\treturn fromAny(pumpAndCollect());\n\t});\n\n\tconst unsub = keepalive(output);\n\n\t// Filter: only forward non-null results to the gate. Null is the switchMap\n\t// initial/cancel state — not a real LLM result worth gating. Returning\n\t// undefined from a derived fn means \"no auto-emit\" (spec §2.4), so null\n\t// values are silently suppressed.\n\tconst nonNullOutput = derived<T>(\n\t\t[output],\n\t\t([v]) => {\n\t\t\tif (v == null) return undefined;\n\t\t\treturn v as T;\n\t\t},\n\t\t{\n\t\t\tname: `${name}/filter`,\n\t\t},\n\t);\n\n\t// Register the filtered output so gate() can find it as a dep\n\tgraph.add(`${name}/raw`, nonNullOutput);\n\n\t// Wire gate on the output\n\tconst gateCtrl = gate<T | null>(graph, `${name}/gate`, `${name}/raw`, opts?.gate);\n\n\t// Wrap reject to also abort the in-flight stream\n\tconst originalReject = gateCtrl.reject.bind(gateCtrl);\n\tconst gateWithAbort: GateController<T | null> = {\n\t\t...gateCtrl,\n\t\treject(count = 1) {\n\t\t\toriginalReject(count);\n\t\t\t// Toggle cancel signal to force switchMap restart → abort\n\t\t\tcancelSignal.down([[DATA, ++cancelCounter]]);\n\t\t},\n\t};\n\n\treturn {\n\t\toutput: gateCtrl.node,\n\t\tstream: streamTopic,\n\t\tgate: gateWithAbort,\n\t\tdispose: () => {\n\t\t\tunsub();\n\t\t\tstreamTopic.destroy();\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// promptNode\n// ---------------------------------------------------------------------------\n\nexport type PromptNodeOptions = {\n\tname?: string;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Output format — `\"json\"` attempts JSON.parse on the response. Default: `\"text\"`. */\n\tformat?: \"text\" | \"json\";\n\t/** Number of retries on transient errors. Default: 0. */\n\tretries?: number;\n\t/** Cache LLM responses for identical inputs. Default: false. */\n\tcache?: boolean;\n\tsystemPrompt?: string;\n\tmeta?: Record<string, unknown>;\n};\n\n/** Extract text content from an LLM response, handling various response shapes. */\nfunction extractContent(resp: unknown): string {\n\tif (resp != null && typeof resp === \"object\" && \"content\" in resp) {\n\t\treturn String((resp as LLMResponse).content);\n\t}\n\tif (typeof resp === \"string\") return resp;\n\treturn String(resp);\n}\n\n/**\n * Universal LLM transform: wraps a prompt template + model adapter into a reactive derived node.\n * Re-invokes the LLM whenever any dep changes. Suitable for triage, QA, hypothesis, parity, etc.\n *\n * @param adapter - LLM adapter (provider-agnostic).\n * @param deps - Input nodes whose values feed the prompt.\n * @param prompt - Static string or template function receiving dep values.\n * @param opts - Optional configuration.\n * @returns `Node` emitting LLM responses (string or parsed JSON).\n */\nexport function promptNode<T = string>(\n\tadapter: LLMAdapter,\n\tdeps: readonly Node<unknown>[],\n\tprompt: string | ((...depValues: unknown[]) => string),\n\topts?: PromptNodeOptions,\n): Node<T | null> {\n\tconst format = opts?.format ?? \"text\";\n\tconst retries = opts?.retries ?? 0;\n\tconst useCache = opts?.cache ?? false;\n\tconst cache = useCache ? new Map<string, T>() : null;\n\n\t// Seed with `initial: []` so `switchMap` below fires with `[]` during the\n\t// initial activation pass and emits null (composition guide §8 — promptNode\n\t// gates on nullish deps). Dep-level null guarding is done inside the fn.\n\tconst messagesNode = derived<readonly ChatMessage[]>(\n\t\tdeps as Node<unknown>[],\n\t\t(values) => {\n\t\t\t// Dep-level null guard (composition guide §8): if any dep is\n\t\t\t// nullish, return empty messages → switchMap emits null.\n\t\t\tif (values.some((v) => v == null)) return [];\n\t\t\tconst text = typeof prompt === \"string\" ? prompt : prompt(...values);\n\t\t\tif (!text) return [];\n\t\t\tconst msgs: ChatMessage[] = [];\n\t\t\tif (opts?.systemPrompt) msgs.push({ role: \"system\", content: opts.systemPrompt });\n\t\t\tmsgs.push({ role: \"user\", content: text });\n\t\t\treturn msgs;\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ? `${opts.name}::messages` : \"prompt_node::messages\",\n\t\t\tmeta: aiMeta(\"prompt_node\"),\n\t\t\tinitial: [] as readonly ChatMessage[],\n\t\t},\n\t);\n\n\tconst result = switchMap<readonly ChatMessage[], T | null>(messagesNode, (msgs) => {\n\t\tif (!msgs || msgs.length === 0) {\n\t\t\treturn state<T | null>(null) as NodeInput<T | null>;\n\t\t}\n\n\t\tconst cacheKey = useCache ? JSON.stringify(msgs.map((m) => [m.role, m.content])) : \"\";\n\t\tif (cache?.has(cacheKey)) {\n\t\t\treturn state<T | null>(cache.get(cacheKey)!) as NodeInput<T | null>;\n\t\t}\n\n\t\tasync function attempt(remaining: number): Promise<T | null> {\n\t\t\ttry {\n\t\t\t\tconst resp = await new Promise<LLMResponse>((resolve, reject) => {\n\t\t\t\t\tconst input = adapter.invoke(msgs, {\n\t\t\t\t\t\tmodel: opts?.model,\n\t\t\t\t\t\ttemperature: opts?.temperature,\n\t\t\t\t\t\tmaxTokens: opts?.maxTokens,\n\t\t\t\t\t\tsystemPrompt: opts?.systemPrompt,\n\t\t\t\t\t});\n\t\t\t\t\t// NodeInput may be a Node, Promise, or raw value\n\t\t\t\t\tif (input && typeof (input as PromiseLike<LLMResponse>).then === \"function\") {\n\t\t\t\t\t\t(input as PromiseLike<LLMResponse>).then(resolve, reject);\n\t\t\t\t\t} else if (input && typeof (input as Node<LLMResponse>).subscribe === \"function\") {\n\t\t\t\t\t\tresolve((input as Node<LLMResponse>).cache as LLMResponse);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresolve(input as LLMResponse);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tconst content = extractContent(resp);\n\t\t\t\tlet parsed: T;\n\t\t\t\tif (format === \"json\") {\n\t\t\t\t\tparsed = JSON.parse(stripFences(content)) as T;\n\t\t\t\t} else {\n\t\t\t\t\tparsed = content as unknown as T;\n\t\t\t\t}\n\t\t\t\tcache?.set(cacheKey, parsed);\n\t\t\t\treturn parsed;\n\t\t\t} catch (err) {\n\t\t\t\tif (remaining > 0) return attempt(remaining - 1);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\n\t\treturn attempt(retries) as NodeInput<T | null>;\n\t});\n\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// chatStream\n// ---------------------------------------------------------------------------\n\nexport type ChatStreamOptions = {\n\tgraph?: GraphOptions;\n\tmaxMessages?: number;\n};\n\nexport class ChatStreamGraph extends Graph {\n\tprivate readonly _log: ReactiveLogBundle<ChatMessage>;\n\treadonly messages: Node<readonly ChatMessage[]>;\n\treadonly latest: Node<ChatMessage | null>;\n\treadonly messageCount: Node<number>;\n\n\tconstructor(name: string, opts: ChatStreamOptions = {}) {\n\t\tsuper(name, opts.graph);\n\n\t\tthis._log = reactiveLog<ChatMessage>([], {\n\t\t\tname: \"messages\",\n\t\t\tmaxSize: opts.maxMessages,\n\t\t});\n\t\tthis.messages = this._log.entries;\n\t\tthis.add(\"messages\", this.messages);\n\n\t\tthis.latest = derived<ChatMessage | null>(\n\t\t\t[this.messages],\n\t\t\t([snapshot]) => {\n\t\t\t\tconst entries = snapshot as readonly ChatMessage[];\n\t\t\t\treturn entries.length === 0 ? null : (entries[entries.length - 1] as ChatMessage);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"latest\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"chat_latest\"),\n\t\t\t},\n\t\t);\n\t\tthis.add(\"latest\", this.latest);\n\t\tthis.addDisposer(keepalive(this.latest));\n\n\t\tthis.messageCount = derived<number>(\n\t\t\t[this.messages],\n\t\t\t([snapshot]) => (snapshot as readonly ChatMessage[]).length,\n\t\t\t{\n\t\t\t\tname: \"messageCount\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"chat_message_count\"),\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t);\n\t\tthis.add(\"messageCount\", this.messageCount);\n\t\tthis.addDisposer(keepalive(this.messageCount));\n\t}\n\n\tappend(role: ChatMessage[\"role\"], content: string, extra?: Partial<ChatMessage>): void {\n\t\tthis._log.append({ role, content, ...extra });\n\t}\n\n\tappendToolResult(callId: string, content: string): void {\n\t\tthis._log.append({ role: \"tool\", content, toolCallId: callId });\n\t}\n\n\tclear(): void {\n\t\tthis._log.clear();\n\t}\n\n\tallMessages(): readonly ChatMessage[] {\n\t\treturn this.messages.cache as readonly ChatMessage[];\n\t}\n}\n\nexport function chatStream(name: string, opts?: ChatStreamOptions): ChatStreamGraph {\n\treturn new ChatStreamGraph(name, opts);\n}\n\n// ---------------------------------------------------------------------------\n// toolRegistry\n// ---------------------------------------------------------------------------\n\nexport type ToolRegistryOptions = {\n\tgraph?: GraphOptions;\n};\n\nexport class ToolRegistryGraph extends Graph {\n\treadonly definitions: Node<ReadonlyMap<string, ToolDefinition>>;\n\treadonly schemas: Node<readonly ToolDefinition[]>;\n\n\tconstructor(name: string, opts: ToolRegistryOptions = {}) {\n\t\tsuper(name, opts.graph);\n\n\t\tthis.definitions = state<ReadonlyMap<string, ToolDefinition>>(new Map(), {\n\t\t\tname: \"definitions\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"tool_definitions\"),\n\t\t});\n\t\tthis.add(\"definitions\", this.definitions);\n\n\t\tthis.schemas = derived<readonly ToolDefinition[]>(\n\t\t\t[this.definitions],\n\t\t\t([defs]) => [...((defs ?? new Map()) as ReadonlyMap<string, ToolDefinition>).values()],\n\t\t\t{\n\t\t\t\tname: \"schemas\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"tool_schemas\"),\n\t\t\t\tinitial: [],\n\t\t\t},\n\t\t);\n\t\tthis.add(\"schemas\", this.schemas);\n\t\tthis.addDisposer(keepalive(this.schemas));\n\t}\n\n\tregister(tool: ToolDefinition): void {\n\t\tconst current = this.definitions.cache as ReadonlyMap<string, ToolDefinition>;\n\t\tconst next = new Map(current);\n\t\tnext.set(tool.name, tool);\n\t\tthis.definitions.down([[DATA, next]]);\n\t}\n\n\tunregister(name: string): void {\n\t\tconst current = this.definitions.cache as ReadonlyMap<string, ToolDefinition>;\n\t\tif (!current.has(name)) return;\n\t\tconst next = new Map(current);\n\t\tnext.delete(name);\n\t\tthis.definitions.down([[DATA, next]]);\n\t}\n\n\tasync execute(name: string, args: Record<string, unknown>): Promise<unknown> {\n\t\tconst defs = this.definitions.cache as ReadonlyMap<string, ToolDefinition>;\n\t\tconst tool = defs.get(name);\n\t\tif (!tool) throw new Error(`toolRegistry: unknown tool \"${name}\"`);\n\t\tconst raw = tool.handler(args);\n\t\treturn resolveToolHandlerResult(raw);\n\t}\n\n\tgetDefinition(name: string): ToolDefinition | undefined {\n\t\treturn (this.definitions.cache as ReadonlyMap<string, ToolDefinition>)?.get(name);\n\t}\n}\n\nexport function toolRegistry(name: string, opts?: ToolRegistryOptions): ToolRegistryGraph {\n\treturn new ToolRegistryGraph(name, opts);\n}\n\n// ---------------------------------------------------------------------------\n// systemPromptBuilder\n// ---------------------------------------------------------------------------\n\n/**\n * Assembles a system prompt from reactive sections. Each section is a\n * `NodeInput<string>` — the prompt updates when any section changes.\n */\nexport type SystemPromptHandle = Node<string> & { dispose: () => void };\n\nexport function systemPromptBuilder(\n\tsections: readonly NodeInput<string>[],\n\topts?: { separator?: string; name?: string },\n): SystemPromptHandle {\n\tconst separator = opts?.separator ?? \"\\n\\n\";\n\tconst sectionNodes = sections.map((s) => (typeof s === \"string\" ? state(s) : fromAny(s)));\n\tconst prompt = derived(\n\t\tsectionNodes,\n\t\t(values) => (values as string[]).filter((v) => v != null && v !== \"\").join(separator),\n\t\t{\n\t\t\tname: opts?.name ?? \"systemPrompt\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: aiMeta(\"system_prompt\"),\n\t\t\tinitial: \"\",\n\t\t},\n\t);\n\tconst unsub = keepalive(prompt);\n\treturn Object.assign(prompt, { dispose: unsub });\n}\n\n// ---------------------------------------------------------------------------\n// llmExtractor / llmConsolidator\n// ---------------------------------------------------------------------------\n\nexport type LLMExtractorOptions = {\n\tadapter: LLMAdapter;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n};\n\n/**\n * Returns an `extractFn` callback for `distill()` that invokes an LLM to\n * extract structured memories from raw input.\n *\n * The system prompt should instruct the LLM to return JSON matching\n * `Extraction<TMem>` shape: `{ upsert: [{ key, value }], remove?: [key] }`.\n */\nexport function llmExtractor<TRaw, TMem>(\n\tsystemPrompt: string,\n\topts: LLMExtractorOptions,\n): (raw: TRaw, existing: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>> {\n\treturn (raw: TRaw, existing: ReadonlyMap<string, TMem>) => {\n\t\tconst existingKeys = [...existing.keys()].slice(0, 100); // sample for dedup\n\t\tconst messages: ChatMessage[] = [\n\t\t\t{ role: \"system\", content: systemPrompt },\n\t\t\t{\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: JSON.stringify({\n\t\t\t\t\tinput: raw,\n\t\t\t\t\texistingKeys,\n\t\t\t\t}),\n\t\t\t},\n\t\t];\n\t\t// Wrap the adapter call in a producer that parses the JSON response\n\t\treturn producer<Extraction<TMem>>((actions) => {\n\t\t\tlet active = true;\n\t\t\tconst result = opts.adapter.invoke(messages, {\n\t\t\t\tmodel: opts.model,\n\t\t\t\ttemperature: opts.temperature ?? 0,\n\t\t\t\tmaxTokens: opts.maxTokens,\n\t\t\t});\n\t\t\t// result is NodeInput — could be a Promise, Node, etc.\n\t\t\tconst resolved = fromAny(result);\n\t\t\tconst unsub = resolved.subscribe((msgs) => {\n\t\t\t\tif (!active) return;\n\t\t\t\tlet done = false;\n\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\tif (done) break;\n\t\t\t\t\tif (msg[0] === DATA) {\n\t\t\t\t\t\tconst response = msg[1] as LLMResponse;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst parsed = JSON.parse(response.content) as Extraction<TMem>;\n\t\t\t\t\t\t\tactions.emit(parsed);\n\t\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tactions.down([\n\t\t\t\t\t\t\t\t[ERROR, new Error(\"llmExtractor: failed to parse LLM response as JSON\")],\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t} else if (msg[0] === ERROR) {\n\t\t\t\t\t\tactions.down([[ERROR, msg[1]]]);\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t} else if (msg[0] === COMPLETE) {\n\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Forward unknown message types (spec §1.3.6)\n\t\t\t\t\t\tactions.down([[msg[0], msg[1]]]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tunsub();\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t});\n\t};\n}\n\nexport type LLMConsolidatorOptions = LLMExtractorOptions;\n\n/**\n * Returns a `consolidateFn` callback for `distill()` that invokes an LLM to\n * cluster and merge related memories.\n */\nexport function llmConsolidator<TMem>(\n\tsystemPrompt: string,\n\topts: LLMConsolidatorOptions,\n): (entries: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>> {\n\treturn (entries: ReadonlyMap<string, TMem>) => {\n\t\tconst entriesArray = [...entries.entries()].map(([key, value]) => ({ key, value }));\n\t\tconst messages: ChatMessage[] = [\n\t\t\t{ role: \"system\", content: systemPrompt },\n\t\t\t{ role: \"user\", content: JSON.stringify({ memories: entriesArray }) },\n\t\t];\n\t\treturn producer<Extraction<TMem>>((actions) => {\n\t\t\tlet active = true;\n\t\t\tconst result = opts.adapter.invoke(messages, {\n\t\t\t\tmodel: opts.model,\n\t\t\t\ttemperature: opts.temperature ?? 0,\n\t\t\t\tmaxTokens: opts.maxTokens,\n\t\t\t});\n\t\t\tconst resolved = fromAny(result);\n\t\t\tconst unsub = resolved.subscribe((msgs) => {\n\t\t\t\tif (!active) return;\n\t\t\t\tlet done = false;\n\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\tif (done) break;\n\t\t\t\t\tif (msg[0] === DATA) {\n\t\t\t\t\t\tconst response = msg[1] as LLMResponse;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst parsed = JSON.parse(response.content) as Extraction<TMem>;\n\t\t\t\t\t\t\tactions.emit(parsed);\n\t\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tactions.down([\n\t\t\t\t\t\t\t\t[ERROR, new Error(\"llmConsolidator: failed to parse LLM response as JSON\")],\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t} else if (msg[0] === ERROR) {\n\t\t\t\t\t\tactions.down([[ERROR, msg[1]]]);\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t} else if (msg[0] === COMPLETE) {\n\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Forward unknown message types (spec §1.3.6)\n\t\t\t\t\t\tactions.down([[msg[0], msg[1]]]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tunsub();\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t});\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// 3D Admission Scoring\n// ---------------------------------------------------------------------------\n\n/** Scores for the three admission dimensions. Each 0–1. */\nexport type AdmissionScores = {\n\treadonly persistence: number;\n\treadonly structure: number;\n\treadonly personalValue: number;\n};\n\nexport type AdmissionScore3DOptions = {\n\t/** Custom scoring function. Default: rule-based (all dimensions 0.5). */\n\tscoreFn?: (raw: unknown) => AdmissionScores;\n\t/** Minimum persistence score to admit (default 0.3). */\n\tpersistenceThreshold?: number;\n\t/** Minimum personalValue score to admit (default 0.3). */\n\tpersonalValueThreshold?: number;\n\t/** Require structure score > 0 to admit (default false). */\n\trequireStructured?: boolean;\n};\n\n/**\n * Default 3D admission scorer. Returns middle scores for all dimensions.\n * Override with `scoreFn` for LLM-backed or domain-specific scoring.\n */\nfunction defaultAdmissionScorer(_raw: unknown): AdmissionScores {\n\treturn { persistence: 0.5, structure: 0.5, personalValue: 0.5 };\n}\n\n/**\n * Creates a 3D admission filter function compatible with `agentMemory`'s\n * `admissionFilter` option. Scores each candidate on persistence, structure,\n * and personalValue, then applies thresholds.\n */\nexport function admissionFilter3D(opts: AdmissionScore3DOptions = {}): (raw: unknown) => boolean {\n\tconst scoreFn = opts.scoreFn ?? defaultAdmissionScorer;\n\tconst pThresh = opts.persistenceThreshold ?? 0.3;\n\tconst pvThresh = opts.personalValueThreshold ?? 0.3;\n\tconst reqStructured = opts.requireStructured ?? false;\n\treturn (raw: unknown): boolean => {\n\t\tconst scores = scoreFn(raw);\n\t\tif (scores.persistence < pThresh) return false;\n\t\tif (scores.personalValue < pvThresh) return false;\n\t\tif (reqStructured && scores.structure <= 0) return false;\n\t\treturn true;\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Memory Tiers\n// ---------------------------------------------------------------------------\n\nexport type MemoryTier = \"permanent\" | \"active\" | \"archived\";\n\nexport type MemoryTiersOptions<TMem> = {\n\t/** Exponential decay rate per second for active tier.\n\t * Default: 7-day half-life ≈ ln(2)/(7×86400) ≈ 0.00000114. */\n\tdecayRate?: number;\n\t/** Max entries in the active tier before archiving lowest-scored (default 1000). */\n\tmaxActive?: number;\n\t/** Score threshold below which active entries get archived (default 0.1). */\n\tarchiveThreshold?: number;\n\t/** Predicate: true → entry belongs in permanent tier (default: never). */\n\tpermanentFilter?: (key: string, mem: TMem) => boolean;\n\t/** Storage tier for the archive. Omit to disable archiving. */\n\tarchiveTier?: StorageTier;\n\t/** Options forwarded to `graph.attachStorage` for the archive tier. */\n\tarchiveStorageOptions?: GraphAttachStorageOptions;\n};\n\nconst DEFAULT_DECAY_RATE = Math.LN2 / (7 * 86_400); // 7-day half-life\n\nexport type MemoryTiersBundle<TMem> = {\n\t/** Permanent tier: never evicted. */\n\treadonly permanent: LightCollectionBundle<TMem>;\n\t/** Active entries node (reactive, holds ReadonlyMap). */\n\treadonly activeEntries: Node<unknown>;\n\t/** Archive storage handle (null if no tier configured). */\n\treadonly archiveHandle: StorageHandle | null;\n\t/** Classify a key into its current tier. */\n\ttierOf: (key: string) => MemoryTier;\n\t/** Move a key to the permanent tier. */\n\tmarkPermanent: (key: string, value: TMem) => void;\n};\n\n// ---------------------------------------------------------------------------\n// Retrieval Pipeline\n// ---------------------------------------------------------------------------\n\nexport type RetrievalQuery = {\n\treadonly text?: string;\n\treadonly vector?: readonly number[];\n\treadonly entityIds?: readonly string[];\n};\n\nexport type RetrievalPipelineOptions<TMem> = {\n\t/** Max candidates from vector search (default 20). */\n\ttopK?: number;\n\t/** KG expansion depth in hops (default 1). */\n\tgraphDepth?: number;\n\t/** Token budget for final packing (default 2000). */\n\tbudget?: number;\n\t/** Cost function for budget packing. */\n\tcost: (mem: TMem) => number;\n\t/** Score function for ranking. */\n\tscore: (mem: TMem, context: unknown) => number;\n};\n\n/** A single entry in the retrieval result, with causal trace metadata. */\nexport type RetrievalEntry<TMem> = {\n\treadonly key: string;\n\treadonly value: TMem;\n\treadonly score: number;\n\treadonly sources: ReadonlyArray<\"vector\" | \"graph\" | \"store\">;\n};\n\n/** Causal trace for a retrieval run. */\nexport type RetrievalTrace<TMem> = {\n\treadonly vectorCandidates: ReadonlyArray<VectorSearchResult<TMem>>;\n\treadonly graphExpanded: ReadonlyArray<string>;\n\treadonly ranked: ReadonlyArray<RetrievalEntry<TMem>>;\n\treadonly packed: ReadonlyArray<RetrievalEntry<TMem>>;\n};\n\n// ---------------------------------------------------------------------------\n// agentMemory\n// ---------------------------------------------------------------------------\n\nexport type AgentMemoryOptions<TMem = unknown> = {\n\tgraph?: GraphOptions;\n\t/** LLM adapter for extraction and consolidation. */\n\tadapter?: LLMAdapter;\n\t/** System prompt for the extractor LLM. */\n\textractPrompt?: string;\n\t/** Custom extractFn (overrides adapter + extractPrompt). */\n\textractFn?: (raw: unknown, existing: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>;\n\t/** System prompt for the consolidation LLM. */\n\tconsolidatePrompt?: string;\n\t/** Custom consolidateFn (overrides adapter + consolidatePrompt). */\n\tconsolidateFn?: (entries: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>;\n\t/** Reactive trigger for consolidation (caller supplies e.g. `fromTimer`). */\n\tconsolidateTrigger?: NodeInput<unknown>;\n\t/** Score function for budget packing (required). */\n\tscore: (mem: TMem, context: unknown) => number;\n\t/** Cost function for budget packing (required). */\n\tcost: (mem: TMem) => number;\n\t/** Token budget for compact view (default 2000). */\n\tbudget?: number;\n\t/** Context node for scoring. */\n\tcontext?: NodeInput<unknown>;\n\t/** Admission filter (default: admit all). */\n\tadmissionFilter?: (candidate: unknown) => boolean;\n\t/** Vector index dimensions (> 0 enables vector index for retrieval). */\n\tvectorDimensions?: number;\n\n\t// --- In-factory composition (new) ---\n\n\t/** Extract embedding vector from a memory entry (enables vector index). */\n\tembedFn?: (mem: TMem) => readonly number[] | undefined;\n\t/** Enable knowledge graph for entity/relation tracking. */\n\tenableKnowledgeGraph?: boolean;\n\t/** Extract entities and relations from a memory entry. */\n\tentityFn?: (\n\t\tkey: string,\n\t\tmem: TMem,\n\t) =>\n\t\t| {\n\t\t\t\tentities?: Array<{ id: string; value: unknown }>;\n\t\t\t\trelations?: Array<{ from: string; to: string; relation: string; weight?: number }>;\n\t\t }\n\t\t| undefined;\n\n\t/** 3-tier storage configuration. Omit to use single-tier (existing behavior). */\n\ttiers?: MemoryTiersOptions<TMem>;\n\n\t/** Retrieval pipeline configuration. Requires vector index or knowledge graph. */\n\tretrieval?: {\n\t\t/** Max candidates from vector search (default 20). */\n\t\ttopK?: number;\n\t\t/** KG expansion depth in hops (default 1). */\n\t\tgraphDepth?: number;\n\t};\n\n\t/** Periodic reflection/consolidation configuration. */\n\treflection?: {\n\t\t/** Interval in ms between consolidation runs (default 300_000 = 5 min). */\n\t\tinterval?: number;\n\t\t/** Enable/disable periodic reflection (default true when consolidateFn is available). */\n\t\tenabled?: boolean;\n\t};\n};\n\nexport type AgentMemoryGraph<TMem = unknown> = Graph & {\n\treadonly distillBundle: DistillBundle<TMem>;\n\treadonly compact: Node<Array<{ key: string; value: TMem; score: number }>>;\n\treadonly size: Node<number>;\n\t/** Vector index bundle (null if not enabled). */\n\treadonly vectors: VectorIndexBundle<TMem> | null;\n\t/** Knowledge graph (null if not enabled). */\n\treadonly kg: KnowledgeGraphGraph<unknown, string> | null;\n\t/** Memory tiers bundle (null if not configured). */\n\treadonly memoryTiers: MemoryTiersBundle<TMem> | null;\n\t/** Retrieval result node (null if no retrieval pipeline configured). */\n\treadonly retrieval: Node<ReadonlyArray<RetrievalEntry<TMem>>> | null;\n\t/** Latest retrieval trace for observability (null if no retrieval pipeline). */\n\treadonly retrievalTrace: Node<RetrievalTrace<TMem> | null> | null;\n\t/**\n\t * Execute a retrieval query (null if no retrieval pipeline).\n\t *\n\t * **Synchronous consumer API** — returns the result immediately and batch-writes\n\t * `retrieval` and `retrievalTrace` state nodes for observers. Reads the store\n\t * snapshot and context value **at call time** (external-boundary read).\n\t *\n\t * **Do not call from inside a reactive fn body** (derived fn, subscribe callback,\n\t * effect body). The cache reads would become transitive protocol violations and\n\t * may observe wave-progressive rather than wave-final state.\n\t *\n\t * **Caller-batch caveat:** if invoked inside a caller's `batch(() => ...)` alongside\n\t * upstream store mutations, the store snapshot reflects what has been committed to\n\t * `store.entries.cache` at call time. State-backed stores update cache synchronously\n\t * so batched inserts are visible; derived-backed store transforms may defer. If you\n\t * need fresh state after batched mutations, call `retrieve` after the batch returns.\n\t */\n\treadonly retrieve: ((query: RetrievalQuery) => ReadonlyArray<RetrievalEntry<TMem>>) | null;\n};\n\n/**\n * Pre-wired agentic memory graph. Composes `distill()` with optional\n * `knowledgeGraph()`, `vectorIndex()`, `lightCollection()` (permanent tier),\n * `decay()`, and `attachStorage()` (archive tier). Supports 3D admission\n * scoring, a default retrieval pipeline, periodic reflection, and\n * retrieval observability traces.\n */\n\n/** Extract the key→value map from a reactive_map snapshot. */\nfunction extractStoreMap<TMem>(snapshot: unknown): ReadonlyMap<string, TMem> {\n\tif (snapshot instanceof Map) return snapshot as ReadonlyMap<string, TMem>;\n\treturn new Map<string, TMem>();\n}\n\nexport function agentMemory<TMem = unknown>(\n\tname: string,\n\tsource: NodeInput<unknown>,\n\topts: AgentMemoryOptions<TMem>,\n): AgentMemoryGraph<TMem> {\n\tconst graph = new Graph(name, opts.graph);\n\tconst keepaliveSubs: Array<() => void> = [];\n\n\t// --- Extract function resolution ---\n\tlet rawExtractFn: (\n\t\traw: unknown,\n\t\texisting: ReadonlyMap<string, TMem>,\n\t) => NodeInput<Extraction<TMem>>;\n\tif (opts.extractFn) {\n\t\trawExtractFn = opts.extractFn;\n\t} else if (opts.adapter && opts.extractPrompt) {\n\t\trawExtractFn = llmExtractor<unknown, TMem>(opts.extractPrompt, { adapter: opts.adapter });\n\t} else {\n\t\tthrow new Error(\"agentMemory: provide either extractFn or adapter + extractPrompt\");\n\t}\n\tconst extractFn = (\n\t\traw: unknown,\n\t\texisting: ReadonlyMap<string, TMem>,\n\t): NodeInput<Extraction<TMem>> => {\n\t\tif (raw == null) return { upsert: [] };\n\t\treturn rawExtractFn(raw, existing);\n\t};\n\n\t// --- Admission filter ---\n\tlet filteredSource = source;\n\tif (opts.admissionFilter) {\n\t\tconst srcNode = fromAny(source);\n\t\tconst filter = opts.admissionFilter;\n\t\tfilteredSource = derived(\n\t\t\t[srcNode],\n\t\t\t([raw]) => {\n\t\t\t\tif (filter(raw)) return raw;\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\t{ name: \"admissionFilter\", describeKind: \"derived\" },\n\t\t);\n\t}\n\n\t// --- Consolidation ---\n\tlet consolidateFn:\n\t\t| ((entries: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>)\n\t\t| undefined;\n\tif (opts.consolidateFn) {\n\t\tconsolidateFn = opts.consolidateFn;\n\t} else if (opts.adapter && opts.consolidatePrompt) {\n\t\tconsolidateFn = llmConsolidator<TMem>(opts.consolidatePrompt, { adapter: opts.adapter });\n\t}\n\n\t// --- Reflection: default consolidateTrigger from fromTimer ---\n\tlet consolidateTrigger = opts.consolidateTrigger;\n\tif (!consolidateTrigger && consolidateFn && opts.reflection?.enabled !== false) {\n\t\tconst interval = opts.reflection?.interval ?? 300_000;\n\t\tconsolidateTrigger = fromTimer(interval, { period: interval });\n\t}\n\n\t// --- Build distill bundle ---\n\tconst distillOpts: DistillOptions<TMem> = {\n\t\tscore: opts.score,\n\t\tcost: opts.cost,\n\t\tbudget: opts.budget ?? 2000,\n\t\tcontext: opts.context,\n\t\tconsolidate: consolidateFn,\n\t\tconsolidateTrigger,\n\t};\n\tconst distillBundle = distill<unknown, TMem>(filteredSource, extractFn, distillOpts);\n\n\tgraph.add(\"store\", distillBundle.store.entries);\n\tgraph.add(\"compact\", distillBundle.compact);\n\tgraph.add(\"size\", distillBundle.size);\n\n\t// --- Vector index (optional) ---\n\tlet vectors: VectorIndexBundle<TMem> | null = null;\n\tif (opts.vectorDimensions && opts.vectorDimensions > 0 && opts.embedFn) {\n\t\tvectors = vectorIndex<TMem>({ dimension: opts.vectorDimensions });\n\t\tgraph.add(\"vectorIndex\", vectors.entries);\n\t}\n\n\t// --- Knowledge graph (optional) ---\n\tlet kg: KnowledgeGraphGraph<unknown, string> | null = null;\n\tif (opts.enableKnowledgeGraph) {\n\t\tkg = knowledgeGraph<unknown, string>(`${name}-kg`);\n\t\tgraph.mount(\"kg\", kg);\n\t}\n\n\t// --- 3-tier storage (optional) ---\n\tlet memoryTiersBundle: MemoryTiersBundle<TMem> | null = null;\n\tif (opts.tiers) {\n\t\tconst tiersOpts = opts.tiers;\n\t\tconst decayRate = tiersOpts.decayRate ?? DEFAULT_DECAY_RATE;\n\t\tconst maxActive = tiersOpts.maxActive ?? 1000;\n\t\tconst archiveThreshold = tiersOpts.archiveThreshold ?? 0.1;\n\t\tconst permanentFilter = tiersOpts.permanentFilter ?? (() => false);\n\n\t\t// Permanent tier\n\t\tconst permanent = lightCollection<TMem>({ name: \"permanent\" });\n\t\tgraph.add(\"permanent\", permanent.entries);\n\n\t\t// Track which keys are permanent\n\t\tconst permanentKeys = new Set<string>();\n\n\t\tconst tierOf = (key: string): MemoryTier => {\n\t\t\tif (permanentKeys.has(key)) return \"permanent\";\n\t\t\tconst storeMap = extractStoreMap<TMem>(distillBundle.store.entries.cache);\n\t\t\tif (storeMap.has(key)) return \"active\";\n\t\t\treturn \"archived\";\n\t\t};\n\n\t\tconst markPermanent = (key: string, value: TMem): void => {\n\t\t\tpermanentKeys.add(key);\n\t\t\tpermanent.upsert(key, value);\n\t\t};\n\n\t\t// Track entry creation times for accurate decay age calculation\n\t\tconst entryCreatedAtNs = new Map<string, number>();\n\n\t\t// Post-extraction hook: classify into tiers and archive low-scored entries\n\t\tconst storeNode = distillBundle.store.entries;\n\t\tconst contextNode = opts.context ? fromAny(opts.context) : state<unknown>(null);\n\t\tconst tierClassifier = effect([storeNode, contextNode], ([snapshot, ctx]) => {\n\t\t\tconst storeMap = extractStoreMap<TMem>(snapshot);\n\t\t\tconst nowNs = monotonicNs();\n\t\t\tconst toArchive: string[] = [];\n\t\t\tconst toPermanent: Array<{ key: string; value: TMem }> = [];\n\n\t\t\tfor (const [key, mem] of storeMap) {\n\t\t\t\t// Track creation time for new entries\n\t\t\t\tif (!entryCreatedAtNs.has(key)) {\n\t\t\t\t\tentryCreatedAtNs.set(key, nowNs);\n\t\t\t\t}\n\n\t\t\t\t// Check permanent classification\n\t\t\t\tif (permanentFilter(key, mem)) {\n\t\t\t\t\ttoPermanent.push({ key, value: mem });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// Compute decayed score for active tier\n\t\t\t\tconst baseScore = opts.score(mem, ctx);\n\t\t\t\tconst createdNs = entryCreatedAtNs.get(key) ?? nowNs;\n\t\t\t\tconst ageSeconds = Number(nowNs - createdNs) / 1e9;\n\t\t\t\tconst decayed = decay(baseScore, ageSeconds, decayRate);\n\t\t\t\tif (decayed < archiveThreshold) {\n\t\t\t\t\ttoArchive.push(key);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Clean up creation times for removed entries\n\t\t\tfor (const key of entryCreatedAtNs.keys()) {\n\t\t\t\tif (!storeMap.has(key)) entryCreatedAtNs.delete(key);\n\t\t\t}\n\n\t\t\t// Move to permanent\n\t\t\tfor (const { key, value } of toPermanent) {\n\t\t\t\tif (!permanentKeys.has(key)) {\n\t\t\t\t\tmarkPermanent(key, value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Archive and evict from active (respect maxActive, excluding permanent keys)\n\t\t\tconst activeCount = storeMap.size - permanentKeys.size;\n\t\t\tif (activeCount > maxActive) {\n\t\t\t\tconst scored = [...storeMap.entries()]\n\t\t\t\t\t.filter(([k]) => !permanentKeys.has(k))\n\t\t\t\t\t.map(([k, m]) => ({ key: k, score: opts.score(m, ctx) }))\n\t\t\t\t\t.sort((a, b) => a.score - b.score);\n\t\t\t\tconst excess = activeCount - maxActive;\n\t\t\t\tfor (let i = 0; i < excess && i < scored.length; i++) {\n\t\t\t\t\tconst sk = scored[i]!.key;\n\t\t\t\t\tif (!toArchive.includes(sk)) toArchive.push(sk);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Evict archived keys from active store\n\t\t\tif (toArchive.length > 0) {\n\t\t\t\tbatch(() => {\n\t\t\t\t\tfor (const key of toArchive) {\n\t\t\t\t\t\tdistillBundle.store.delete(key);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tkeepaliveSubs.push(tierClassifier.subscribe(() => undefined));\n\n\t\t// Archive checkpoint\n\t\tlet archiveHandle: StorageHandle | null = null;\n\t\tif (tiersOpts.archiveTier) {\n\t\t\tarchiveHandle = graph.attachStorage(\n\t\t\t\t[tiersOpts.archiveTier],\n\t\t\t\ttiersOpts.archiveStorageOptions ?? {},\n\t\t\t);\n\t\t}\n\n\t\tmemoryTiersBundle = {\n\t\t\tpermanent,\n\t\t\tactiveEntries: storeNode,\n\t\t\tarchiveHandle,\n\t\t\ttierOf,\n\t\t\tmarkPermanent,\n\t\t};\n\t}\n\n\t// --- Post-extraction hooks: vector + KG indexing ---\n\tif (vectors || kg) {\n\t\tconst embedFn = opts.embedFn;\n\t\tconst entityFn = opts.entityFn;\n\t\tconst storeNode = distillBundle.store.entries;\n\n\t\tconst indexer = effect([storeNode], ([snapshot]) => {\n\t\t\tconst storeMap = extractStoreMap<TMem>(snapshot);\n\t\t\tfor (const [key, mem] of storeMap) {\n\t\t\t\t// Vector indexing\n\t\t\t\tif (vectors && embedFn) {\n\t\t\t\t\tconst vec = embedFn(mem);\n\t\t\t\t\tif (vec) vectors.upsert(key, vec, mem);\n\t\t\t\t}\n\t\t\t\t// Knowledge graph entity/relation extraction\n\t\t\t\tif (kg && entityFn) {\n\t\t\t\t\tconst extracted = entityFn(key, mem);\n\t\t\t\t\tif (extracted) {\n\t\t\t\t\t\tfor (const ent of extracted.entities ?? []) {\n\t\t\t\t\t\t\tkg.upsertEntity(ent.id, ent.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (const rel of extracted.relations ?? []) {\n\t\t\t\t\t\t\tkg.link(rel.from, rel.to, rel.relation as string, rel.weight);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tkeepaliveSubs.push(indexer.subscribe(() => undefined));\n\t}\n\n\t// --- Retrieval pipeline (optional) ---\n\tlet retrievalNode: Node<ReadonlyArray<RetrievalEntry<TMem>>> | null = null;\n\tlet retrievalTraceNode: Node<RetrievalTrace<TMem> | null> | null = null;\n\tlet retrieveFn: ((query: RetrievalQuery) => ReadonlyArray<RetrievalEntry<TMem>>) | null = null;\n\n\tif (vectors || kg) {\n\t\tconst topK = opts.retrieval?.topK ?? 20;\n\t\tconst graphDepth = opts.retrieval?.graphDepth ?? 1;\n\t\tconst budget = opts.budget ?? 2000;\n\t\tconst costFn = opts.cost;\n\t\tconst scoreFn = opts.score;\n\n\t\tconst contextNode = opts.context ? fromAny(opts.context) : state<unknown>(null);\n\n\t\t// Observer-facing state nodes. `retrieve()` writes both in a batch on every call.\n\t\t// (Option W from the 2026-04-12 P3 audit — retrieveFn is a sync consumer API that\n\t\t// reads store/context at call time, computes inline, and publishes results via\n\t\t// state writes. No derived, no queryInput, no closure side-channel.)\n\t\tconst retrievalOutput = state<ReadonlyArray<RetrievalEntry<TMem>>>([], {\n\t\t\tname: \"retrieval\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"retrieval_pipeline\"),\n\t\t});\n\t\tgraph.add(\"retrieval\", retrievalOutput);\n\t\tretrievalNode = retrievalOutput;\n\n\t\tconst traceState = state<RetrievalTrace<TMem> | null>(null, {\n\t\t\tname: \"retrievalTrace\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"retrieval_trace\"),\n\t\t});\n\t\tgraph.add(\"retrievalTrace\", traceState);\n\t\tretrievalTraceNode = traceState;\n\n\t\t// Sync consumer API. Reads `store.entries.cache` and `contextNode.cache` at\n\t\t// call time — these are external-boundary reads, allowed per the foundation\n\t\t// redesign. **Do not call from inside a reactive fn body**: the cache reads\n\t\t// would become transitive P3 violations.\n\t\tretrieveFn = (query: RetrievalQuery): ReadonlyArray<RetrievalEntry<TMem>> => {\n\t\t\tconst storeMap = extractStoreMap<TMem>(distillBundle.store.entries.cache);\n\t\t\tconst ctx = contextNode.cache;\n\n\t\t\tconst candidateMap = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ value: TMem; sources: Set<\"vector\" | \"graph\" | \"store\"> }\n\t\t\t>();\n\n\t\t\t// Stage 1: Vector search\n\t\t\tlet vectorCandidates: VectorSearchResult<TMem>[] = [];\n\t\t\tif (vectors && query.vector) {\n\t\t\t\tvectorCandidates = vectors.search(query.vector, topK) as VectorSearchResult<TMem>[];\n\t\t\t\tfor (const vc of vectorCandidates) {\n\t\t\t\t\tconst mem = storeMap.get(vc.id);\n\t\t\t\t\tif (mem) {\n\t\t\t\t\t\tcandidateMap.set(vc.id, { value: mem, sources: new Set([\"vector\"]) });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Stage 2: KG expansion\n\t\t\tconst graphExpanded: string[] = [];\n\t\t\tif (kg) {\n\t\t\t\tconst seedIds = [...(query.entityIds ?? []), ...[...candidateMap.keys()]];\n\t\t\t\tconst visited = new Set<string>();\n\t\t\t\tlet frontier = seedIds;\n\t\t\t\tfor (let depth = 0; depth < graphDepth; depth++) {\n\t\t\t\t\tconst nextFrontier: string[] = [];\n\t\t\t\t\tfor (const id of frontier) {\n\t\t\t\t\t\tif (visited.has(id)) continue;\n\t\t\t\t\t\tvisited.add(id);\n\t\t\t\t\t\tconst related = kg.related(id);\n\t\t\t\t\t\tfor (const edge of related) {\n\t\t\t\t\t\t\tconst targetId = edge.to;\n\t\t\t\t\t\t\tif (!visited.has(targetId)) {\n\t\t\t\t\t\t\t\tnextFrontier.push(targetId);\n\t\t\t\t\t\t\t\tconst mem = storeMap.get(targetId);\n\t\t\t\t\t\t\t\tif (mem) {\n\t\t\t\t\t\t\t\t\tconst existing = candidateMap.get(targetId);\n\t\t\t\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\t\t\t\texisting.sources.add(\"graph\");\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tcandidateMap.set(targetId, { value: mem, sources: new Set([\"graph\"]) });\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tgraphExpanded.push(targetId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfrontier = nextFrontier;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Also include direct store matches not yet in candidates\n\t\t\tfor (const [key, mem] of storeMap) {\n\t\t\t\tif (!candidateMap.has(key)) {\n\t\t\t\t\tcandidateMap.set(key, { value: mem, sources: new Set([\"store\"]) });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Stage 3: Score and rank\n\t\t\tconst ranked: RetrievalEntry<TMem>[] = [];\n\t\t\tfor (const [key, { value, sources }] of candidateMap) {\n\t\t\t\tconst score = scoreFn(value, ctx);\n\t\t\t\tranked.push({ key, value, score, sources: [...sources] });\n\t\t\t}\n\t\t\tranked.sort((a, b) => b.score - a.score);\n\n\t\t\t// Stage 4: Budget packing\n\t\t\tconst packed: RetrievalEntry<TMem>[] = [];\n\t\t\tlet usedBudget = 0;\n\t\t\tfor (const entry of ranked) {\n\t\t\t\tconst c = costFn(entry.value);\n\t\t\t\tif (usedBudget + c > budget && packed.length > 0) break;\n\t\t\t\tpacked.push(entry);\n\t\t\t\tusedBudget += c;\n\t\t\t}\n\n\t\t\tconst trace: RetrievalTrace<TMem> = {\n\t\t\t\tvectorCandidates,\n\t\t\t\tgraphExpanded,\n\t\t\t\tranked,\n\t\t\t\tpacked,\n\t\t\t};\n\n\t\t\tbatch(() => {\n\t\t\t\tretrievalOutput.down([[DATA, packed]]);\n\t\t\t\ttraceState.down([[DATA, trace]]);\n\t\t\t});\n\n\t\t\treturn packed;\n\t\t};\n\t}\n\n\t// --- Cleanup ---\n\tgraph.addDisposer(() => {\n\t\tfor (const unsub of keepaliveSubs) unsub();\n\t\tkeepaliveSubs.length = 0;\n\t});\n\n\treturn Object.assign(graph, {\n\t\tdistillBundle,\n\t\tcompact: distillBundle.compact,\n\t\tsize: distillBundle.size,\n\t\tvectors,\n\t\tkg,\n\t\tmemoryTiers: memoryTiersBundle,\n\t\tretrieval: retrievalNode,\n\t\tretrievalTrace: retrievalTraceNode,\n\t\tretrieve: retrieveFn,\n\t}) as AgentMemoryGraph<TMem>;\n}\n\n// ---------------------------------------------------------------------------\n// agentLoop\n// ---------------------------------------------------------------------------\n\nexport type AgentLoopOptions = {\n\tgraph?: GraphOptions;\n\tadapter: LLMAdapter;\n\ttools?: readonly ToolDefinition[];\n\tsystemPrompt?: string;\n\tmaxTurns?: number;\n\tstopWhen?: (response: LLMResponse) => boolean;\n\tonToolCall?: (call: ToolCall) => void;\n\tmaxMessages?: number;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n};\n\nexport class AgentLoopGraph extends Graph {\n\treadonly chat: ChatStreamGraph;\n\treadonly tools: ToolRegistryGraph;\n\treadonly status: Node<AgentLoopStatus>;\n\treadonly turnCount: Node<number>;\n\treadonly lastResponse: Node<LLMResponse | null>;\n\tprivate readonly _statusState: Node<AgentLoopStatus>;\n\tprivate readonly _turnCountState: Node<number>;\n\tprivate readonly _adapter: LLMAdapter;\n\tprivate readonly _maxTurns: number;\n\tprivate readonly _stopWhen?: (response: LLMResponse) => boolean;\n\tprivate readonly _onToolCall?: (call: ToolCall) => void;\n\tprivate readonly _systemPrompt?: string;\n\tprivate readonly _model?: string;\n\tprivate readonly _temperature?: number;\n\tprivate readonly _maxTokens?: number;\n\tprivate _running = false;\n\tprivate _abortController: AbortController | null = null;\n\n\tconstructor(name: string, opts: AgentLoopOptions) {\n\t\tsuper(name, opts.graph);\n\n\t\tthis._adapter = opts.adapter;\n\t\tthis._maxTurns = opts.maxTurns ?? 10;\n\t\tthis._stopWhen = opts.stopWhen;\n\t\tthis._onToolCall = opts.onToolCall;\n\t\tthis._systemPrompt = opts.systemPrompt;\n\t\tthis._model = opts.model;\n\t\tthis._temperature = opts.temperature;\n\t\tthis._maxTokens = opts.maxTokens;\n\n\t\t// Mount chat subgraph\n\t\tthis.chat = chatStream(`${name}-chat`, { maxMessages: opts.maxMessages });\n\t\tthis.mount(\"chat\", this.chat);\n\n\t\t// Mount tool registry subgraph\n\t\tthis.tools = toolRegistry(`${name}-tools`);\n\t\tthis.mount(\"tools\", this.tools);\n\n\t\t// Register initial tools\n\t\tif (opts.tools) {\n\t\t\tfor (const tool of opts.tools) {\n\t\t\t\tthis.tools.register(tool);\n\t\t\t}\n\t\t}\n\n\t\t// Status state\n\t\tthis._statusState = state<AgentLoopStatus>(\"idle\", {\n\t\t\tname: \"status\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_status\"),\n\t\t});\n\t\tthis.status = this._statusState;\n\t\tthis.add(\"status\", this.status);\n\n\t\t// Turn count\n\t\tthis._turnCountState = state<number>(0, {\n\t\t\tname: \"turnCount\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_turn_count\"),\n\t\t});\n\t\tthis.turnCount = this._turnCountState;\n\t\tthis.add(\"turnCount\", this.turnCount);\n\n\t\t// Last LLM response\n\t\tthis.lastResponse = state<LLMResponse | null>(null, {\n\t\t\tname: \"lastResponse\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_last_response\"),\n\t\t});\n\t\tthis.add(\"lastResponse\", this.lastResponse);\n\t}\n\n\t/**\n\t * Start the agent loop with a user message. The loop runs reactively:\n\t * think (LLM call) → act (tool execution) → repeat until done.\n\t *\n\t * Messages accumulate across calls. Call `chat.clear()` before `run()`\n\t * to reset conversation history.\n\t */\n\tasync run(userMessage: string): Promise<LLMResponse | null> {\n\t\tif (this._running) throw new Error(\"agentLoop: already running\");\n\t\tthis._running = true;\n\t\tthis._abortController = new AbortController();\n\t\tconst { signal } = this._abortController;\n\n\t\tbatch(() => {\n\t\t\tthis._statusState.down([[DATA, \"idle\" as AgentLoopStatus]]);\n\t\t\tthis._turnCountState.down([[DATA, 0]]);\n\t\t});\n\t\tthis.chat.append(\"user\", userMessage);\n\n\t\ttry {\n\t\t\tlet turns = 0;\n\t\t\twhile (turns < this._maxTurns) {\n\t\t\t\tif (signal.aborted) throw new Error(\"agentLoop: aborted\");\n\t\t\t\tturns++;\n\t\t\t\tbatch(() => {\n\t\t\t\t\tthis._turnCountState.down([[DATA, turns]]);\n\t\t\t\t\tthis._statusState.down([[DATA, \"thinking\" as AgentLoopStatus]]);\n\t\t\t\t});\n\n\t\t\t\t// Invoke LLM\n\t\t\t\tconst msgs = this.chat.allMessages();\n\t\t\t\tconst toolSchemas = (this.tools.schemas.cache as readonly ToolDefinition[]) ?? [];\n\t\t\t\tconst response = await this._invokeLLM(msgs, toolSchemas, signal);\n\t\t\t\tif (signal.aborted) throw new Error(\"agentLoop: aborted\");\n\n\t\t\t\t(this.lastResponse as Node<LLMResponse | null>).down([[DATA, response]]);\n\n\t\t\t\t// Append assistant message\n\t\t\t\tthis.chat.append(\"assistant\", response.content, {\n\t\t\t\t\ttoolCalls: response.toolCalls,\n\t\t\t\t});\n\n\t\t\t\t// Check stop conditions\n\t\t\t\tif (this._shouldStop(response)) {\n\t\t\t\t\tthis._statusState.down([[DATA, \"done\" as AgentLoopStatus]]);\n\t\t\t\t\tthis._running = false;\n\t\t\t\t\tthis._abortController = null;\n\t\t\t\t\treturn response;\n\t\t\t\t}\n\n\t\t\t\t// Execute tool calls if present\n\t\t\t\tif (response.toolCalls && response.toolCalls.length > 0) {\n\t\t\t\t\tthis._statusState.down([[DATA, \"acting\" as AgentLoopStatus]]);\n\t\t\t\t\tfor (const call of response.toolCalls) {\n\t\t\t\t\t\tif (signal.aborted) throw new Error(\"agentLoop: aborted\");\n\t\t\t\t\t\tthis._onToolCall?.(call);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await this.tools.execute(call.name, call.arguments);\n\t\t\t\t\t\t\tthis.chat.appendToolResult(call.id, JSON.stringify(result));\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tthis.chat.appendToolResult(call.id, JSON.stringify({ error: String(err) }));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// No tool calls and not explicitly stopped → done\n\t\t\t\t\tthis._statusState.down([[DATA, \"done\" as AgentLoopStatus]]);\n\t\t\t\t\tthis._running = false;\n\t\t\t\t\tthis._abortController = null;\n\t\t\t\t\treturn response;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Max turns reached\n\t\t\tthis._statusState.down([[DATA, \"done\" as AgentLoopStatus]]);\n\t\t\tthis._running = false;\n\t\t\tthis._abortController = null;\n\t\t\treturn this.lastResponse.cache as LLMResponse | null;\n\t\t} catch (err) {\n\t\t\tthis._statusState.down([[DATA, \"error\" as AgentLoopStatus]]);\n\t\t\tthis._running = false;\n\t\t\tthis._abortController = null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tprivate async _invokeLLM(\n\t\tmsgs: readonly ChatMessage[],\n\t\ttools: readonly ToolDefinition[],\n\t\tsignal?: AbortSignal,\n\t): Promise<LLMResponse> {\n\t\tconst result = this._adapter.invoke(msgs, {\n\t\t\ttools: tools.length > 0 ? tools : undefined,\n\t\t\tsystemPrompt: this._systemPrompt,\n\t\t\tmodel: this._model,\n\t\t\ttemperature: this._temperature,\n\t\t\tmaxTokens: this._maxTokens,\n\t\t\tsignal,\n\t\t});\n\t\t// Null/undefined guard\n\t\tif (result == null) {\n\t\t\tthrow new Error(\"_invokeLLM: adapter.invoke() returned null or undefined\");\n\t\t}\n\t\t// String guard — fromAny would iterate characters\n\t\tif (typeof result === \"string\") {\n\t\t\tthrow new Error(\"_invokeLLM: adapter.invoke() returned a string, expected LLMResponse\");\n\t\t}\n\t\t// If result is already an LLMResponse (sync adapter), return directly\n\t\tif (\n\t\t\ttypeof result === \"object\" &&\n\t\t\t\"content\" in result &&\n\t\t\t!(\"subscribe\" in result) &&\n\t\t\t!(\"then\" in result)\n\t\t) {\n\t\t\treturn result as LLMResponse;\n\t\t}\n\t\t// If result is a Promise, await it then check for LLMResponse\n\t\tif (isPromiseLike(result)) {\n\t\t\tconst awaited = await result;\n\t\t\tif (\n\t\t\t\ttypeof awaited === \"object\" &&\n\t\t\t\tawaited !== null &&\n\t\t\t\t\"content\" in awaited &&\n\t\t\t\t!(\"subscribe\" in awaited)\n\t\t\t) {\n\t\t\t\treturn awaited as LLMResponse;\n\t\t\t}\n\t\t\treturn firstDataFromNode(fromAny(awaited as NodeInput<LLMResponse>)) as Promise<LLMResponse>;\n\t\t}\n\t\t// If result is a Node or async iterable, resolve via fromAny + firstDataFromNode\n\t\treturn firstDataFromNode(fromAny(result)) as Promise<LLMResponse>;\n\t}\n\n\tprivate _shouldStop(response: LLMResponse): boolean {\n\t\tif (\n\t\t\tresponse.finishReason === \"end_turn\" &&\n\t\t\t(!response.toolCalls || response.toolCalls.length === 0)\n\t\t)\n\t\t\treturn true;\n\t\tif (this._stopWhen?.(response)) return true;\n\t\treturn false;\n\t}\n\n\toverride destroy(): void {\n\t\tif (this._abortController) {\n\t\t\tthis._abortController.abort();\n\t\t\tthis._abortController = null;\n\t\t}\n\t\tthis._running = false;\n\t\tsuper.destroy();\n\t}\n}\n\nexport function agentLoop(name: string, opts: AgentLoopOptions): AgentLoopGraph {\n\treturn new AgentLoopGraph(name, opts);\n}\n\n// ---------------------------------------------------------------------------\n// 5.4 — LLM tool integration\n// ---------------------------------------------------------------------------\n\n/** OpenAI function-calling tool schema. */\nexport type OpenAIToolSchema = {\n\treadonly type: \"function\";\n\treadonly function: {\n\t\treadonly name: string;\n\t\treadonly description: string;\n\t\treadonly parameters: Record<string, unknown>;\n\t};\n};\n\n/** MCP (Model Context Protocol) tool schema. */\nexport type McpToolSchema = {\n\treadonly name: string;\n\treadonly description: string;\n\treadonly inputSchema: Record<string, unknown>;\n};\n\n/** Result of {@link knobsAsTools}. */\nexport type KnobsAsToolsResult = {\n\t/** OpenAI function-calling tool schemas. */\n\treadonly openai: readonly OpenAIToolSchema[];\n\t/** MCP tool schemas. */\n\treadonly mcp: readonly McpToolSchema[];\n\t/** GraphReFly ToolDefinitions with handlers that call `graph.set()`. */\n\treadonly definitions: readonly ToolDefinition[];\n};\n\n/**\n * Build a JSON Schema `properties.value` descriptor from a node's meta fields.\n *\n * Maps `meta.type`, `meta.range`, `meta.values`, `meta.format`, and `meta.unit`\n * to a JSON Schema property definition.\n */\nfunction metaToJsonSchema(meta: Record<string, unknown>): Record<string, unknown> {\n\tconst schema: Record<string, unknown> = {};\n\n\tconst metaType = meta.type as string | undefined;\n\tif (metaType === \"enum\" && Array.isArray(meta.values)) {\n\t\tschema.type = \"string\";\n\t\tschema.enum = meta.values;\n\t} else if (metaType === \"integer\") {\n\t\tschema.type = \"integer\";\n\t} else if (metaType === \"number\") {\n\t\tschema.type = \"number\";\n\t} else if (metaType === \"boolean\") {\n\t\tschema.type = \"boolean\";\n\t} else if (metaType === \"string\") {\n\t\tschema.type = \"string\";\n\t} else {\n\t\t// Unknown or unspecified — accept anything\n\t\tschema.type = [\"string\", \"number\", \"boolean\"];\n\t}\n\n\tif (Array.isArray(meta.range) && meta.range.length === 2) {\n\t\tschema.minimum = meta.range[0];\n\t\tschema.maximum = meta.range[1];\n\t}\n\n\tif (typeof meta.format === \"string\") {\n\t\tschema.description = `Format: ${meta.format}`;\n\t}\n\n\tif (typeof meta.unit === \"string\") {\n\t\tif (schema.description) {\n\t\t\tschema.description += ` (${meta.unit})`;\n\t\t} else {\n\t\t\tschema.description = `Unit: ${meta.unit}`;\n\t\t}\n\t}\n\n\treturn schema;\n}\n\n/**\n * Derive tool schemas from a graph's writable (knob) nodes.\n *\n * Knobs are state nodes whose `meta.access` is `\"llm\"`, `\"both\"`, or absent\n * (default: writable). Each knob becomes a tool that calls `graph.set()`.\n *\n * Speaks **domain language** (spec §5.4): the returned schemas use node names\n * and meta descriptions — no protocol internals exposed.\n *\n * @param graph - The graph to introspect.\n * @param actor - Optional actor for guard-scoped describe.\n * @returns OpenAI, MCP, and GraphReFly tool schemas.\n */\nexport function knobsAsTools(graph: Graph, actor?: Actor): KnobsAsToolsResult {\n\tconst described = graph.describe({ actor, detail: \"full\" });\n\tconst openai: OpenAIToolSchema[] = [];\n\tconst mcp: McpToolSchema[] = [];\n\tconst definitions: ToolDefinition[] = [];\n\n\tfor (const [path, node] of Object.entries(described.nodes)) {\n\t\t// Only state nodes are writable knobs\n\t\tif (node.type !== \"state\") continue;\n\n\t\t// Skip meta companion nodes (§2.3)\n\t\tif (path.includes(\"::__meta__::\")) continue;\n\n\t\t// Skip terminal-state nodes (§1.3.4 — no further messages after COMPLETE/ERROR)\n\t\tif (node.status === \"completed\" || node.status === \"errored\") continue;\n\n\t\t// Skip if access explicitly excludes LLM\n\t\tconst meta = node.meta ?? {};\n\t\tconst access = meta.access as string | undefined;\n\t\tif (access === \"human\" || access === \"system\") continue;\n\n\t\tconst description = (meta.description as string) ?? `Set the value of ${path}`;\n\t\tconst valueSchema = metaToJsonSchema(meta);\n\n\t\tconst parameterSchema: Record<string, unknown> = {\n\t\t\ttype: \"object\",\n\t\t\trequired: [\"value\"],\n\t\t\tproperties: {\n\t\t\t\tvalue: valueSchema,\n\t\t\t},\n\t\t\tadditionalProperties: false,\n\t\t};\n\n\t\t// OpenAI requires [a-zA-Z0-9_-] in function names; sanitize :: separators\n\t\tconst sanitizedName = path.replace(/::/g, \"__\");\n\n\t\topenai.push({\n\t\t\ttype: \"function\",\n\t\t\tfunction: {\n\t\t\t\tname: sanitizedName,\n\t\t\t\tdescription,\n\t\t\t\tparameters: parameterSchema,\n\t\t\t},\n\t\t});\n\n\t\tmcp.push({\n\t\t\tname: path,\n\t\t\tdescription,\n\t\t\tinputSchema: parameterSchema,\n\t\t});\n\n\t\tconst graphRef = graph;\n\t\tconst actorRef = actor;\n\t\tconst nv = node.v;\n\t\tdefinitions.push({\n\t\t\tname: path,\n\t\t\tdescription,\n\t\t\tparameters: parameterSchema,\n\t\t\thandler(args: Record<string, unknown>) {\n\t\t\t\tgraphRef.set(path, args.value, actorRef ? { actor: actorRef } : undefined);\n\t\t\t\treturn args.value;\n\t\t\t},\n\t\t\t...(nv != null ? { version: { id: nv.id, version: nv.version } } : {}),\n\t\t});\n\t}\n\n\treturn { openai, mcp, definitions };\n}\n\n// ---------------------------------------------------------------------------\n// gaugesAsContext\n// ---------------------------------------------------------------------------\n\nexport type GaugesAsContextOptions = {\n\t/** Group gauges by `meta.tags` (default true). */\n\tgroupByTags?: boolean;\n\t/** Separator between gauge lines (default \"\\n\"). */\n\tseparator?: string;\n\t/**\n\t * V0 delta mode (§6.0b): only include nodes whose `v.version` exceeds\n\t * the corresponding entry in this map. Nodes without V0 or not in the\n\t * map are always included. Callers maintain this map across calls.\n\t *\n\t * The `id` field guards against node replacement: if a node is removed\n\t * and re-added under the same name (new id), it is always included.\n\t */\n\tsinceVersion?: ReadonlyMap<string, { id: string; version: number }>;\n};\n\n/**\n * Format a graph's readable (gauge) nodes as a context string for LLM\n * system prompts.\n *\n * Gauges are nodes with `meta.description` or `meta.format`. Values are\n * formatted using `meta.format` and `meta.unit` hints.\n *\n * @param graph - The graph to introspect.\n * @param actor - Optional actor for guard-scoped describe.\n * @param options - Formatting options.\n * @returns A formatted string ready for system prompt injection.\n */\nexport function gaugesAsContext(\n\tgraph: Graph,\n\tactor?: Actor,\n\toptions?: GaugesAsContextOptions,\n): string {\n\tconst described = graph.describe({ actor, detail: \"full\" });\n\tconst groupByTags = options?.groupByTags ?? true;\n\tconst separator = options?.separator ?? \"\\n\";\n\n\ttype GaugeEntry = { path: string; description: string; formatted: string };\n\tconst entries: GaugeEntry[] = [];\n\n\tconst sinceVersion = options?.sinceVersion;\n\tfor (const [path, node] of Object.entries(described.nodes)) {\n\t\tconst meta = node.meta ?? {};\n\t\tconst desc = meta.description as string | undefined;\n\t\tconst format = meta.format as string | undefined;\n\t\t// Must have description or format to be a gauge\n\t\tif (!desc && !format) continue;\n\t\t// V0 delta filter: skip nodes unchanged since last seen version (§6.0b).\n\t\tif (sinceVersion != null && node.v != null) {\n\t\t\tconst lastSeen = sinceVersion.get(path);\n\t\t\tif (lastSeen != null && lastSeen.id === node.v.id && node.v.version <= lastSeen.version)\n\t\t\t\tcontinue;\n\t\t}\n\n\t\tconst label = desc ?? path;\n\t\tconst value = node.value;\n\t\tconst unit = meta.unit as string | undefined;\n\n\t\tlet formatted: string;\n\t\tif (format === \"currency\" && typeof value === \"number\") {\n\t\t\tformatted = `$${value.toFixed(2)}`;\n\t\t} else if (format === \"percentage\" && typeof value === \"number\") {\n\t\t\tformatted = `${(value * 100).toFixed(1)}%`;\n\t\t} else if (value === undefined || value === null) {\n\t\t\tformatted = \"(no value)\";\n\t\t} else {\n\t\t\tformatted = String(value);\n\t\t}\n\n\t\tif (unit && format !== \"currency\" && format !== \"percentage\") {\n\t\t\tformatted = `${formatted} ${unit}`;\n\t\t}\n\n\t\tentries.push({ path, description: label, formatted });\n\t}\n\n\tif (entries.length === 0) return \"\";\n\n\tif (groupByTags) {\n\t\tconst tagGroups = new Map<string, GaugeEntry[]>();\n\t\tconst ungrouped: GaugeEntry[] = [];\n\n\t\tfor (const entry of entries) {\n\t\t\tconst node = described.nodes[entry.path]!;\n\t\t\tconst tags = node.meta?.tags as string[] | undefined;\n\t\t\tif (tags && tags.length > 0) {\n\t\t\t\t// Use first tag for grouping to avoid duplicating entries across groups\n\t\t\t\tconst tag = tags[0]!;\n\t\t\t\tlet group = tagGroups.get(tag);\n\t\t\t\tif (!group) {\n\t\t\t\t\tgroup = [];\n\t\t\t\t\ttagGroups.set(tag, group);\n\t\t\t\t}\n\t\t\t\tgroup.push(entry);\n\t\t\t} else {\n\t\t\t\tungrouped.push(entry);\n\t\t\t}\n\t\t}\n\n\t\tif (tagGroups.size === 0) {\n\t\t\treturn entries.map((e) => `- ${e.description}: ${e.formatted}`).join(separator);\n\t\t}\n\n\t\tconst sections: string[] = [];\n\t\tfor (const [tag, group] of [...tagGroups.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {\n\t\t\tsections.push(\n\t\t\t\t`[${tag}]${separator}${group.map((e) => `- ${e.description}: ${e.formatted}`).join(separator)}`,\n\t\t\t);\n\t\t}\n\t\tif (ungrouped.length > 0) {\n\t\t\tsections.push(ungrouped.map((e) => `- ${e.description}: ${e.formatted}`).join(separator));\n\t\t}\n\t\treturn sections.join(separator + separator);\n\t}\n\n\treturn entries.map((e) => `- ${e.description}: ${e.formatted}`).join(separator);\n}\n\n// ---------------------------------------------------------------------------\n// validateGraphDef\n// ---------------------------------------------------------------------------\n\n/** Validation result from {@link validateGraphDef}. */\nexport type GraphDefValidation = {\n\treadonly valid: boolean;\n\treadonly errors: readonly string[];\n};\n\nconst VALID_NODE_TYPES = new Set([\"state\", \"derived\", \"producer\", \"operator\", \"effect\"]);\n\n/**\n * Validate an LLM-generated graph definition before passing to\n * `Graph.fromSnapshot()`.\n *\n * Checks:\n * - Required fields: `name`, `nodes`, `edges`\n * - Node types are valid enum values\n * - Edge `from`/`to` reference existing nodes\n * - No duplicate edge entries\n *\n * @param def - The graph definition to validate (parsed JSON).\n * @returns Validation result with errors array.\n */\nexport function validateGraphDef(def: unknown): GraphDefValidation {\n\tconst errors: string[] = [];\n\n\tif (def == null || typeof def !== \"object\") {\n\t\treturn { valid: false, errors: [\"Definition must be a non-null object\"] };\n\t}\n\n\tconst d = def as Record<string, unknown>;\n\n\tif (typeof d.name !== \"string\" || d.name.length === 0) {\n\t\terrors.push(\"Missing or empty 'name' field\");\n\t}\n\n\tif (d.nodes == null || typeof d.nodes !== \"object\" || Array.isArray(d.nodes)) {\n\t\terrors.push(\"Missing or invalid 'nodes' field (must be an object)\");\n\t\treturn { valid: false, errors };\n\t}\n\n\tconst nodeNames = new Set(Object.keys(d.nodes as object));\n\n\tfor (const [name, raw] of Object.entries(d.nodes as Record<string, unknown>)) {\n\t\tif (raw == null || typeof raw !== \"object\") {\n\t\t\terrors.push(`Node \"${name}\": must be an object`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst node = raw as Record<string, unknown>;\n\t\tif (typeof node.type !== \"string\" || !VALID_NODE_TYPES.has(node.type)) {\n\t\t\terrors.push(\n\t\t\t\t`Node \"${name}\": invalid type \"${String(node.type)}\" (expected: ${[...VALID_NODE_TYPES].join(\", \")})`,\n\t\t\t);\n\t\t}\n\t\tif (Array.isArray(node.deps)) {\n\t\t\tfor (const dep of node.deps) {\n\t\t\t\tif (typeof dep === \"string\" && !nodeNames.has(dep)) {\n\t\t\t\t\terrors.push(`Node \"${name}\": dep \"${dep}\" does not reference an existing node`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!Array.isArray(d.edges)) {\n\t\tif (d.edges !== undefined) {\n\t\t\terrors.push(\"'edges' must be an array\");\n\t\t}\n\t\t// edges are optional — no error if absent\n\t} else {\n\t\tconst seen = new Set<string>();\n\t\tfor (let i = 0; i < (d.edges as unknown[]).length; i++) {\n\t\t\tconst edge = (d.edges as unknown[])[i];\n\t\t\tif (edge == null || typeof edge !== \"object\") {\n\t\t\t\terrors.push(`Edge [${i}]: must be an object`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst e = edge as Record<string, unknown>;\n\t\t\tif (typeof e.from !== \"string\" || !nodeNames.has(e.from)) {\n\t\t\t\terrors.push(`Edge [${i}]: 'from' \"${String(e.from)}\" does not reference an existing node`);\n\t\t\t}\n\t\t\tif (typeof e.to !== \"string\" || !nodeNames.has(e.to)) {\n\t\t\t\terrors.push(`Edge [${i}]: 'to' \"${String(e.to)}\" does not reference an existing node`);\n\t\t\t}\n\t\t\tconst key = `${e.from}->${e.to}`;\n\t\t\tif (seen.has(key)) {\n\t\t\t\terrors.push(`Edge [${i}]: duplicate edge ${key}`);\n\t\t\t}\n\t\t\tseen.add(key);\n\t\t}\n\t}\n\n\treturn { valid: errors.length === 0, errors };\n}\n\n// ---------------------------------------------------------------------------\n// graphFromSpec\n// ---------------------------------------------------------------------------\n\nexport type GraphFromSpecOptions = {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Callback to construct topology before values are applied (passed to `Graph.fromSnapshot`). */\n\tbuild?: (g: Graph) => void;\n\t/** Extra instructions appended to the system prompt. */\n\tsystemPromptExtra?: string;\n};\n\n/** Strip markdown code fences, handling trailing commentary after closing fence. */\nfunction stripFences(text: string): string {\n\tconst match = text.match(/^```(?:json)?\\s*([\\s\\S]*?)\\s*```[\\s\\S]*$/);\n\treturn match ? match[1]! : text;\n}\n\nconst GRAPH_FROM_SPEC_SYSTEM_PROMPT = `You are a graph architect for GraphReFly, a reactive graph protocol.\n\nGiven a natural-language description, produce a JSON graph definition with this structure:\n\n{\n \"name\": \"<graph_name>\",\n \"nodes\": {\n \"<node_name>\": {\n \"type\": \"state\" | \"derived\" | \"producer\" | \"operator\" | \"effect\",\n \"value\": <initial_value_or_null>,\n \"deps\": [\"<dep_node_name>\", ...],\n \"meta\": {\n \"description\": \"<human-readable purpose>\",\n \"type\": \"string\" | \"number\" | \"boolean\" | \"integer\" | \"enum\",\n \"range\": [min, max],\n \"values\": [\"a\", \"b\"],\n \"format\": \"currency\" | \"percentage\" | \"status\",\n \"access\": \"human\" | \"llm\" | \"both\" | \"system\",\n \"unit\": \"<unit>\",\n \"tags\": [\"<tag>\"]\n }\n }\n },\n \"edges\": [\n { \"from\": \"<source_node>\", \"to\": \"<target_node>\" }\n ]\n}\n\nRules:\n- \"state\" nodes have no deps and hold user/LLM-writable values (knobs).\n- \"derived\" nodes have deps and compute from them.\n- \"effect\" nodes have deps but produce side effects (no return value).\n- \"producer\" nodes have no deps but generate values asynchronously.\n- Edges wire output of one node as input to another. They must match deps.\n- meta.description is required for every node.\n- Return ONLY valid JSON, no markdown fences or commentary.`;\n\n/**\n * Ask an LLM to compose a Graph from a natural-language description.\n *\n * The LLM returns a JSON graph definition which is validated and then\n * constructed via `Graph.fromSnapshot()`.\n *\n * @param naturalLanguage - The problem/use-case description.\n * @param adapter - LLM adapter for the generation call.\n * @param opts - Model options and optional `build` callback for node factories.\n * @returns A constructed Graph.\n * @throws On invalid LLM output or validation failure.\n */\nexport async function graphFromSpec(\n\tnaturalLanguage: string,\n\tadapter: LLMAdapter,\n\topts?: GraphFromSpecOptions,\n): Promise<Graph> {\n\tconst systemPrompt = opts?.systemPromptExtra\n\t\t? `${GRAPH_FROM_SPEC_SYSTEM_PROMPT}\\n\\n${opts.systemPromptExtra}`\n\t\t: GRAPH_FROM_SPEC_SYSTEM_PROMPT;\n\n\tconst messages: ChatMessage[] = [\n\t\t{ role: \"system\", content: systemPrompt },\n\t\t{ role: \"user\", content: naturalLanguage },\n\t];\n\n\tconst rawResult = adapter.invoke(messages, {\n\t\tmodel: opts?.model,\n\t\ttemperature: opts?.temperature ?? 0,\n\t\tmaxTokens: opts?.maxTokens,\n\t});\n\n\tconst response = (await resolveToolHandlerResult(rawResult)) as LLMResponse;\n\tlet content = response.content.trim();\n\n\t// Strip markdown fences if present (handles trailing commentary after ```)\n\tif (content.startsWith(\"```\")) {\n\t\tcontent = stripFences(content);\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(content);\n\t} catch {\n\t\tthrow new Error(`graphFromSpec: LLM response is not valid JSON: ${content.slice(0, 200)}`);\n\t}\n\n\tconst validation = validateGraphDef(parsed);\n\tif (!validation.valid) {\n\t\tthrow new Error(`graphFromSpec: invalid graph definition:\\n${validation.errors.join(\"\\n\")}`);\n\t}\n\n\tconst def = parsed as Record<string, unknown>;\n\t// Ensure version field is present for fromSnapshot envelope check\n\tif (def.version === undefined) def.version = 1;\n\tif (!Array.isArray(def.subgraphs)) def.subgraphs = [];\n\treturn Graph.fromSnapshot(def as GraphPersistSnapshot, opts?.build);\n}\n\n// ---------------------------------------------------------------------------\n// suggestStrategy\n// ---------------------------------------------------------------------------\n\n/** A single operation in a strategy plan. */\nexport type StrategyOperation =\n\t| {\n\t\t\treadonly type: \"add_node\";\n\t\t\treadonly name: string;\n\t\t\treadonly nodeType: string;\n\t\t\treadonly meta?: Record<string, unknown>;\n\t\t\treadonly initial?: unknown;\n\t }\n\t| { readonly type: \"remove_node\"; readonly name: string }\n\t| { readonly type: \"connect\"; readonly from: string; readonly to: string }\n\t| { readonly type: \"disconnect\"; readonly from: string; readonly to: string }\n\t| { readonly type: \"set_value\"; readonly name: string; readonly value: unknown }\n\t| {\n\t\t\treadonly type: \"update_meta\";\n\t\t\treadonly name: string;\n\t\t\treadonly key: string;\n\t\t\treadonly value: unknown;\n\t };\n\n/** Structured strategy plan returned by {@link suggestStrategy}. */\nexport type StrategyPlan = {\n\treadonly summary: string;\n\treadonly operations: readonly StrategyOperation[];\n\treadonly reasoning: string;\n};\n\nexport type SuggestStrategyOptions = {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\tactor?: Actor;\n};\n\nconst SUGGEST_STRATEGY_SYSTEM_PROMPT = `You are a reactive graph optimizer for GraphReFly.\n\nGiven a graph's current structure (from describe()) and a problem statement, suggest topology and parameter changes to solve the problem.\n\nReturn ONLY valid JSON with this structure:\n{\n \"summary\": \"<one-line summary of the strategy>\",\n \"reasoning\": \"<explanation of why these changes help>\",\n \"operations\": [\n { \"type\": \"add_node\", \"name\": \"<name>\", \"nodeType\": \"state|derived|effect|producer|operator\", \"meta\": {...}, \"initial\": <value> },\n { \"type\": \"remove_node\", \"name\": \"<name>\" },\n { \"type\": \"connect\", \"from\": \"<source>\", \"to\": \"<target>\" },\n { \"type\": \"disconnect\", \"from\": \"<source>\", \"to\": \"<target>\" },\n { \"type\": \"set_value\", \"name\": \"<name>\", \"value\": <new_value> },\n { \"type\": \"update_meta\", \"name\": \"<name>\", \"key\": \"<meta_key>\", \"value\": <new_value> }\n ]\n}\n\nRules:\n- Only suggest operations that reference existing nodes (for remove/disconnect/set_value/update_meta) or new nodes you define (for add_node).\n- Keep changes minimal — prefer the smallest set of operations that solves the problem.\n- Return ONLY valid JSON, no markdown fences or commentary.`;\n\n/**\n * Ask an LLM to analyze a graph and suggest topology/parameter changes\n * to solve a stated problem.\n *\n * Returns a structured plan — does NOT auto-apply. The caller reviews\n * and selectively applies operations.\n *\n * @param graph - The graph to analyze.\n * @param problem - Natural-language problem statement.\n * @param adapter - LLM adapter for the analysis call.\n * @param opts - Model and actor options.\n * @returns A structured strategy plan.\n * @throws On invalid LLM output.\n */\nexport async function suggestStrategy(\n\tgraph: Graph,\n\tproblem: string,\n\tadapter: LLMAdapter,\n\topts?: SuggestStrategyOptions,\n): Promise<StrategyPlan> {\n\tconst { expand: _, ...described } = graph.describe({ actor: opts?.actor, detail: \"standard\" });\n\n\tconst messages: ChatMessage[] = [\n\t\t{ role: \"system\", content: SUGGEST_STRATEGY_SYSTEM_PROMPT },\n\t\t{\n\t\t\trole: \"user\",\n\t\t\tcontent: JSON.stringify({\n\t\t\t\tgraph: described,\n\t\t\t\tproblem,\n\t\t\t}),\n\t\t},\n\t];\n\n\tconst rawResult = adapter.invoke(messages, {\n\t\tmodel: opts?.model,\n\t\ttemperature: opts?.temperature ?? 0,\n\t\tmaxTokens: opts?.maxTokens,\n\t});\n\n\tconst response = (await resolveToolHandlerResult(rawResult)) as LLMResponse;\n\tlet content = response.content.trim();\n\n\tif (content.startsWith(\"```\")) {\n\t\tcontent = content.replace(/^```(?:json)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(content);\n\t} catch {\n\t\tthrow new Error(`suggestStrategy: LLM response is not valid JSON: ${content.slice(0, 200)}`);\n\t}\n\n\tconst plan = parsed as Record<string, unknown>;\n\n\tif (typeof plan.summary !== \"string\") {\n\t\tthrow new Error(\"suggestStrategy: missing 'summary' in response\");\n\t}\n\tif (typeof plan.reasoning !== \"string\") {\n\t\tthrow new Error(\"suggestStrategy: missing 'reasoning' in response\");\n\t}\n\tif (!Array.isArray(plan.operations)) {\n\t\tthrow new Error(\"suggestStrategy: missing 'operations' array in response\");\n\t}\n\n\treturn {\n\t\tsummary: plan.summary,\n\t\treasoning: plan.reasoning,\n\t\toperations: plan.operations as readonly StrategyOperation[],\n\t};\n}\n","/**\n * Batch deferral for tier-3+ messages, plus per-node emit coalescing inside\n * explicit `batch()` scopes.\n *\n * **Canonical invariant:** GRAPHREFLY-SPEC.md §1.3.7 — inside a batch,\n * tier 0–2 signals propagate immediately; tier 3 (DATA/RESOLVED), tier 4\n * (COMPLETE/ERROR), and tier 5 (TEARDOWN) are queued and drained in ascending\n * phase order after the outermost `batch()` callback returns.\n *\n * **Per-node emit coalescing (Bug 2 fix, 2026-04-17).** Inside an explicit\n * `batch()` scope, consecutive emissions from the same node accumulate in\n * `NodeImpl._batchPendingMessages` (see JSDoc there) instead of each producing\n * a separate downstream wave. K `.emit()` calls to the same source collapse to\n * one coalesced `downWithBatch` call per child edge at batch end. Outside batch\n * (or during drain), coalescing does NOT apply — each emit produces its own wave.\n *\n * **Phase vocabulary:**\n * - Phase 1 = tiers 0–2 — immediate, never queued.\n * - Phase 2 = tier 3 — {@link drainPhase2}. Value settlements.\n * - Phase 3 = tier 4 — {@link drainPhase3}. Terminal signals.\n * - Phase 4 = tier 5 — {@link drainPhase4}. TEARDOWN (unified deferral).\n *\n * Drain rule: fire any pending flush hooks first, then the lowest non-empty\n * phase. Re-enqueues during drain (and hooks registered by reentrant batches\n * inside subscriber callbacks) bump the loop back to the top so newly-added\n * hooks and closures get processed.\n */\n\nimport type { Messages } from \"./messages.js\";\n\nconst MAX_DRAIN_ITERATIONS = 1000;\n\nlet batchDepth = 0;\nlet flushInProgress = false;\n\n/** Tier 3 (DATA/RESOLVED) deferral queue — drained first. */\nconst drainPhase2: Array<() => void> = [];\n/** Tier 4 (COMPLETE/ERROR) deferral queue — drained after phase 2. */\nconst drainPhase3: Array<() => void> = [];\n/** Tier 5 (TEARDOWN) deferral queue — drained last. */\nconst drainPhase4: Array<() => void> = [];\n\n/**\n * Per-batch flush hooks. Each hook is registered by a node the first time\n * it accumulates an emission inside an explicit `batch()` scope (Bug 2 —\n * per-node emit coalescing). Hooks fire at the head of `drainPending`,\n * before the standard tier-3/4/5 drain queues — they call `downWithBatch`\n * with the node's accumulated multi-message batch, which enqueues the\n * tier-3+ portion into `drainPhase2/3/4` for the standard loop.\n *\n * On a `batch()` throw, hooks still fire so each node clears its pending\n * state (they're idempotent — the side-effects are wiped because the\n * drainPhase queues that they enqueue into are cleared in the same finally\n * block).\n */\nconst flushHooks: Array<() => void> = [];\n\n/**\n * Returns whether the current call stack is inside a batch scope **or** while\n * a deferred drain is in progress. Nested `downWithBatch` calls during drain\n * still defer (they bump the drain loop).\n */\nexport function isBatching(): boolean {\n\treturn batchDepth > 0 || flushInProgress;\n}\n\n/**\n * Returns whether the current call stack is inside an **explicit** `batch()`\n * scope. Excludes `flushInProgress` — i.e. emissions that happen during a\n * drain (e.g. inside a fn callback) are NOT explicitly batched and should\n * not trigger per-node coalescing (Bug 2).\n */\nexport function isExplicitlyBatching(): boolean {\n\treturn batchDepth > 0;\n}\n\n/**\n * Register a hook to fire at the head of the next `drainPending`. Used by\n * `NodeImpl._emit` to flush its per-batch accumulator (Bug 2). If called\n * outside an explicit batch the hook fires immediately, since there's no\n * drain coming.\n */\nexport function registerBatchFlushHook(hook: () => void): void {\n\tif (batchDepth > 0) {\n\t\tflushHooks.push(hook);\n\t} else {\n\t\thook();\n\t}\n}\n\n/**\n * Runs `fn` inside a batch scope. Nested `batch()` calls share one deferral\n * queue. If `fn` throws, deferred work for the outer frame is discarded\n * (unless a drain is already in progress — cross-language decision A4).\n */\nexport function batch(fn: () => void): void {\n\tbatchDepth += 1;\n\tlet threw = false;\n\ttry {\n\t\tfn();\n\t} catch (e) {\n\t\tthrew = true;\n\t\tthrow e;\n\t} finally {\n\t\tbatchDepth -= 1;\n\t\tif (batchDepth === 0) {\n\t\t\tif (threw) {\n\t\t\t\tif (!flushInProgress) {\n\t\t\t\t\t// Fire any per-node flush hooks so nodes clear their\n\t\t\t\t\t// pending state. The downWithBatch calls those hooks\n\t\t\t\t\t// make enqueue into drainPhase queues — those queues\n\t\t\t\t\t// are cleared right after, so the side-effects are\n\t\t\t\t\t// wiped. Net result: clean node state, no delivery.\n\t\t\t\t\tconst hooks = flushHooks.splice(0);\n\t\t\t\t\tfor (const h of hooks) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\th();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* best-effort */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdrainPhase2.length = 0;\n\t\t\t\t\tdrainPhase3.length = 0;\n\t\t\t\t\tdrainPhase4.length = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdrainPending();\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction drainPending(): void {\n\tconst ownsFlush = !flushInProgress;\n\tif (ownsFlush) flushInProgress = true;\n\n\tconst errors: unknown[] = [];\n\n\tlet iterations = 0;\n\ttry {\n\t\t// Loop while EITHER tier-3+ deferred work OR pending flush hooks exist.\n\t\t// Hooks can be re-registered mid-drain by reentrant `batch()` calls\n\t\t// inside subscriber callbacks; checking `flushHooks` each iteration\n\t\t// (not just before the loop) ensures those late hooks fire too.\n\t\twhile (\n\t\t\tdrainPhase2.length > 0 ||\n\t\t\tdrainPhase3.length > 0 ||\n\t\t\tdrainPhase4.length > 0 ||\n\t\t\t(ownsFlush && flushHooks.length > 0)\n\t\t) {\n\t\t\t// Fire any pending flush hooks FIRST so their downWithBatch calls\n\t\t\t// enqueue tier-3+ work into drainPhase before we process it.\n\t\t\tif (ownsFlush && flushHooks.length > 0) {\n\t\t\t\tconst hooks = flushHooks.splice(0);\n\t\t\t\tfor (const h of hooks) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\th();\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\terrors.push(e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue; // restart loop — hooks may have enqueued tier-3+ work or more hooks\n\t\t\t}\n\t\t\titerations += 1;\n\t\t\tif (iterations > MAX_DRAIN_ITERATIONS) {\n\t\t\t\tdrainPhase2.length = 0;\n\t\t\t\tdrainPhase3.length = 0;\n\t\t\t\tdrainPhase4.length = 0;\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`batch drain exceeded ${MAX_DRAIN_ITERATIONS} iterations — likely a reactive cycle`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Always drain the lowest non-empty phase. Re-enqueues at any level\n\t\t\t// cause the next iteration to restart from phase 2 if needed.\n\t\t\tconst queue =\n\t\t\t\tdrainPhase2.length > 0 ? drainPhase2 : drainPhase3.length > 0 ? drainPhase3 : drainPhase4;\n\t\t\tconst ops = queue.splice(0);\n\t\t\tfor (const run of ops) {\n\t\t\t\ttry {\n\t\t\t\t\trun();\n\t\t\t\t} catch (e) {\n\t\t\t\t\terrors.push(e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tif (ownsFlush) flushInProgress = false;\n\t}\n\n\tif (errors.length === 1) throw errors[0];\n\tif (errors.length > 1) {\n\t\tthrow new AggregateError(errors, \"batch drain: multiple callbacks threw\");\n\t}\n}\n\n/**\n * Deliver pre-sorted messages through `sink` with tier-based deferral applied.\n *\n * `messages` MUST be in ascending tier order (produced by `_frameBatch` in\n * `node.ts`); the walker exploits that invariant to find phase cuts in one\n * pass without re-sorting.\n *\n * Behavior:\n * - Tier 0–2 — delivered synchronously.\n * - Tier 3 — deferred to {@link drainPhase2} when batching, else synchronous.\n * - Tier 4 — deferred to {@link drainPhase3} when batching, else synchronous.\n * - Tier 5 — deferred to {@link drainPhase4} when batching, else synchronous.\n *\n * Tier-classification uses the caller-supplied `tierOf` so that batch stays\n * decoupled from `GraphReFlyConfig`. NodeImpl passes `config.tierOf` (a\n * pre-bound closure built once in the config constructor) at the emit site;\n * alternate configs can pass their own lookup.\n */\nexport function downWithBatch(\n\tsink: (messages: Messages) => void,\n\tmessages: Messages,\n\ttierOf: (t: symbol) => number,\n): void {\n\tif (messages.length === 0) return;\n\n\t// Fast path: single message (hot in propagation).\n\tif (messages.length === 1) {\n\t\tconst tier = tierOf(messages[0][0]);\n\t\tif (tier < 3 || !isBatching()) {\n\t\t\tsink(messages);\n\t\t\treturn;\n\t\t}\n\t\tconst queue = tier >= 5 ? drainPhase4 : tier === 4 ? drainPhase3 : drainPhase2;\n\t\tqueue.push(() => sink(messages));\n\t\treturn;\n\t}\n\n\t// Multi-message: walk once over pre-sorted input, find phase cuts.\n\t// Monotone tier order means `phase2Start <= phase3Start <= phase4Start`.\n\tconst n = messages.length;\n\tlet phase2Start = n;\n\tlet phase3Start = n;\n\tlet phase4Start = n;\n\n\tlet i = 0;\n\twhile (i < n && tierOf(messages[i][0]) < 3) i++;\n\tphase2Start = i;\n\twhile (i < n && tierOf(messages[i][0]) === 3) i++;\n\tphase3Start = i;\n\twhile (i < n && tierOf(messages[i][0]) === 4) i++;\n\tphase4Start = i;\n\t// Anything from phase4Start..n has tier >= 5.\n\n\tconst batching = isBatching();\n\n\tif (phase2Start > 0) {\n\t\t// Immediate tier 0–2 region.\n\t\tconst immediate = messages.slice(0, phase2Start);\n\t\tsink(immediate);\n\t}\n\n\tif (phase3Start > phase2Start) {\n\t\tconst phase2 = messages.slice(phase2Start, phase3Start);\n\t\tif (batching) drainPhase2.push(() => sink(phase2));\n\t\telse sink(phase2);\n\t}\n\n\tif (phase4Start > phase3Start) {\n\t\tconst phase3 = messages.slice(phase3Start, phase4Start);\n\t\tif (batching) drainPhase3.push(() => sink(phase3));\n\t\telse sink(phase3);\n\t}\n\n\tif (n > phase4Start) {\n\t\tconst phase4 = messages.slice(phase4Start, n);\n\t\tif (batching) drainPhase4.push(() => sink(phase4));\n\t\telse sink(phase4);\n\t}\n}\n","/**\n * Centralised timestamp utilities.\n *\n * Convention: all graphrefly-ts timestamps use nanoseconds (`_ns` suffix).\n *\n * - {@link monotonicNs} — monotonic clock (ordering, durations, timeline events).\n * - {@link wallClockNs} — wall-clock (mutation attribution, cron emission).\n *\n * **Precision limits (JS platform):**\n *\n * - `monotonicNs`: effective ~microsecond precision. `performance.now()` returns\n * milliseconds with ~5µs resolution; the last 3 digits of the nanosecond value\n * are always zero. Python's `time.monotonic_ns()` gives true nanoseconds.\n *\n * - `wallClockNs`: ~256ns precision loss at current epoch. `Date.now() * 1e6`\n * produces values around 1.8×10¹⁸ which exceed IEEE 754's 2⁵³ safe integer\n * limit. Python's `time.time_ns()` (arbitrary-precision `int`) has no loss.\n * In practice this is irrelevant — JS is single-threaded, so sub-microsecond\n * timestamp collisions cannot occur.\n */\n\n/** Monotonic nanosecond timestamp via `performance.now()`. */\nexport function monotonicNs(): number {\n\treturn Math.trunc(performance.now() * 1_000_000);\n}\n\n/** Wall-clock nanosecond timestamp via `Date.now()`. */\nexport function wallClockNs(): number {\n\treturn Date.now() * 1_000_000;\n}\n","/**\n * GraphReFly message protocol — §1 `~/src/graphrefly/GRAPHREFLY-SPEC.md`.\n * Emissions are always `[[Type, Data?], ...]` (no single-tuple shorthand).\n *\n * This file is protocol-pure:\n * - Message type symbols (10 built-ins).\n * - `Message` / `Messages` tuple types.\n * - `MessageTypeRegistration` interface (shape of a registry entry).\n *\n * It does NOT own the registry, tier lookups, or any cross-cutting singleton\n * state — that lives in `GraphReFlyConfig` (see `config.ts`) so custom\n * protocols can build isolated instances. Import this module when you need\n * the symbol constants or the tuple types; import `config.ts` when you need\n * tier / wire-crossing / registry lookups.\n */\n\n/** Subscribe-time handshake. Delivered to each new sink at the top of `subscribe()`. Tier 0. */\nexport const START = Symbol.for(\"graphrefly/START\");\n/** Value delivery (`DATA`, value). Tier 3 — deferred inside `batch()`. */\nexport const DATA = Symbol.for(\"graphrefly/DATA\");\n/** Phase 1: value about to change. Tier 1 — immediate. */\nexport const DIRTY = Symbol.for(\"graphrefly/DIRTY\");\n/** Phase 2: dirty pass completed, value unchanged. Tier 3 — deferred inside `batch()`. */\nexport const RESOLVED = Symbol.for(\"graphrefly/RESOLVED\");\n/** Clear cached state; do not auto-emit. Tier 1 — immediate. */\nexport const INVALIDATE = Symbol.for(\"graphrefly/INVALIDATE\");\n/** Suspend activity. Tier 2 — immediate. */\nexport const PAUSE = Symbol.for(\"graphrefly/PAUSE\");\n/** Resume after pause. Tier 2 — immediate. */\nexport const RESUME = Symbol.for(\"graphrefly/RESUME\");\n/** Permanent cleanup. Tier 5 — deferred to batch phase 4. */\nexport const TEARDOWN = Symbol.for(\"graphrefly/TEARDOWN\");\n/** Clean termination. Tier 4 — deferred to batch phase 3. */\nexport const COMPLETE = Symbol.for(\"graphrefly/COMPLETE\");\n/** Error termination. Tier 4 — deferred to batch phase 3. */\nexport const ERROR = Symbol.for(\"graphrefly/ERROR\");\n\n/** One protocol tuple: `[Type, optional payload]`. */\nexport type Message = readonly [symbol, unknown?];\n\n/** A batch of tuples — the wire shape for `node.down()` / `node.up()`. */\nexport type Messages = readonly Message[];\n\n// ---------------------------------------------------------------------------\n// Interned singletons for payload-free tuples\n// ---------------------------------------------------------------------------\n//\n// Every emission path used to allocate fresh `[[DIRTY]]`, `[[RESOLVED]]`,\n// etc. — two arrays per emit in the hot path. Since none of these tuples\n// carry a payload, one frozen instance is indistinguishable from a\n// fresh one. We intern them at module load and reuse forever. Only\n// `[DATA, v]`, `[ERROR, e]`, `[PAUSE, lockId]`, `[RESUME, lockId]` still\n// allocate per-call because they carry payloads.\n//\n// Downstream code MUST treat these as immutable. `Object.freeze` makes\n// accidental mutation throw in strict mode. Do not `push`, splice, or\n// otherwise mutate a Messages array that came from one of these.\n\n/** Singleton `[DIRTY]` tuple — payload-free, interned. */\nexport const DIRTY_MSG: Message = Object.freeze([DIRTY]) as Message;\n/** Singleton `[RESOLVED]` tuple — payload-free, interned. */\nexport const RESOLVED_MSG: Message = Object.freeze([RESOLVED]) as Message;\n/** Singleton `[INVALIDATE]` tuple — payload-free, interned. */\nexport const INVALIDATE_MSG: Message = Object.freeze([INVALIDATE]) as Message;\n/** Singleton `[START]` tuple — payload-free, interned. */\nexport const START_MSG: Message = Object.freeze([START]) as Message;\n/** Singleton `[COMPLETE]` tuple — payload-free, interned. */\nexport const COMPLETE_MSG: Message = Object.freeze([COMPLETE]) as Message;\n/** Singleton `[TEARDOWN]` tuple — payload-free, interned. */\nexport const TEARDOWN_MSG: Message = Object.freeze([TEARDOWN]) as Message;\n\n/** Pre-wrapped `[[DIRTY]]` for `_emit([DIRTY_ONLY_BATCH])`-style callers. */\nexport const DIRTY_ONLY_BATCH: Messages = Object.freeze([DIRTY_MSG]) as Messages;\n/** Pre-wrapped `[[RESOLVED]]`. */\nexport const RESOLVED_ONLY_BATCH: Messages = Object.freeze([RESOLVED_MSG]) as Messages;\n/** Pre-wrapped `[[INVALIDATE]]`. */\nexport const INVALIDATE_ONLY_BATCH: Messages = Object.freeze([INVALIDATE_MSG]) as Messages;\n/** Pre-wrapped `[[COMPLETE]]`. */\nexport const COMPLETE_ONLY_BATCH: Messages = Object.freeze([COMPLETE_MSG]) as Messages;\n/** Pre-wrapped `[[TEARDOWN]]`. */\nexport const TEARDOWN_ONLY_BATCH: Messages = Object.freeze([TEARDOWN_MSG]) as Messages;\n\n// ---------------------------------------------------------------------------\n// Registry entry shape\n// ---------------------------------------------------------------------------\n\n/**\n * Per-type record stored in a {@link GraphReFlyConfig}'s registry.\n *\n * - `tier` — signal tier (0–5 built-in; custom tiers allowed but should fit\n * the phase model used by `batch.ts`).\n * - `wireCrossing` — when `true`, forwarded across SSE/WebSocket/worker\n * adapters. Defaults to `tier >= 3` if omitted in registration input.\n * - `metaPassthrough` — when `false`, this message type is filtered out of\n * `Graph.signal` deliveries to meta companion nodes (spec §2.3). Meta\n * companions still receive everything via their primary's own cascade.\n * Defaults to `true` (meta receives the message).\n */\nexport interface MessageTypeRegistration {\n\ttier: number;\n\twireCrossing: boolean;\n\tmetaPassthrough: boolean;\n}\n\n/**\n * Input accepted by {@link GraphReFlyConfig.registerMessageType}. Only `tier`\n * is required; `wireCrossing` defaults to `tier >= 3`; `metaPassthrough`\n * defaults to `true`.\n */\nexport interface MessageTypeRegistrationInput {\n\ttier: number;\n\twireCrossing?: boolean;\n\tmetaPassthrough?: boolean;\n}\n","/**\n * GraphCodec — pluggable serialization for graph snapshots (Phase 8.6).\n *\n * Design reference: `archive/docs/SESSION-serialization-memory-footprint.md`\n *\n * The codec interface decouples snapshot format from graph internals.\n * Default is JSON (current behavior). DAG-CBOR and compressed variants\n * ship as optional codecs. FlatBuffers/Arrow for advanced tiers.\n *\n * Tiered representation:\n * HOT — JS objects (live propagation, no codec involved)\n * WARM — DAG-CBOR in-memory buffer (lazy hydration, delta checkpoints)\n * COLD — Arrow/Parquet (bulk storage, ML pipelines, archival)\n * PEEK — FlatBuffers (zero-copy read from dormant graph)\n *\n * Wire-protocol envelope (v1):\n *\n * [envelope_v=1: u8][name_len: u8][name: utf8][codec_v: u16 BE][payload: rest]\n *\n * `graph.snapshot({format: \"bytes\", codec: name})` wraps the codec's\n * `encode` output in this envelope; `Graph.decode(bytes)` auto-dispatches\n * via the config's codec registry — no out-of-band content-type needed.\n */\n\nimport type { GraphReFlyConfig } from \"../core/config.js\";\nimport type { GraphCheckpointRecord, GraphPersistSnapshot } from \"./graph.js\";\n\n// ---------------------------------------------------------------------------\n// Core codec interface\n// ---------------------------------------------------------------------------\n\n/**\n * Encode/decode graph snapshots to/from binary.\n *\n * Implementations must be deterministic: `encode(x)` always produces the\n * same bytes for the same input. This is critical for CID computation (V1)\n * and snapshot hash-comparison.\n */\nexport interface GraphCodec {\n\t/** Human-readable name; used as the lookup key in the envelope and config registry. */\n\treadonly name: string;\n\n\t/**\n\t * Codec version. Bumps on breaking wire format changes; `decode` receives\n\t * this via the envelope so codecs can dispatch on historical layouts.\n\t * Must fit in a `u16` (0–65535).\n\t */\n\treadonly version: number;\n\n\t/** MIME-like content type identifier (e.g. `\"application/dag-cbor+zstd\"`). */\n\treadonly contentType: string;\n\n\t/** Encode a snapshot to binary. */\n\tencode(snapshot: GraphPersistSnapshot): Uint8Array;\n\n\t/**\n\t * Decode binary back to a snapshot.\n\t *\n\t * `codecVersion` is the version that produced `buffer` (read from the\n\t * envelope). Omit when the caller is sure of the version (tests, one-shot\n\t * round-trips). Codecs that support multiple historical layouts dispatch\n\t * on this value.\n\t *\n\t * For lazy codecs, this may return a proxy that decodes nodes on access\n\t * (see {@link LazyGraphCodec}).\n\t */\n\tdecode(buffer: Uint8Array, codecVersion?: number): GraphPersistSnapshot;\n}\n\n/**\n * Extended codec that supports lazy (on-demand) node decoding.\n *\n * `decodeLazy` returns a snapshot where `nodes` is a Proxy — individual\n * nodes are decoded only when accessed. This enables near-zero cold-start\n * for large graphs (decode envelope + topology, skip node values until read).\n */\nexport interface LazyGraphCodec extends GraphCodec {\n\t/** Decode envelope and topology; defer node value decoding to access time. */\n\tdecodeLazy(buffer: Uint8Array, codecVersion?: number): GraphPersistSnapshot;\n}\n\n// ---------------------------------------------------------------------------\n// Delta checkpoint types (requires V0 — Phase 6.0)\n// ---------------------------------------------------------------------------\n\n/**\n * WAL entry. Unified with {@link GraphCheckpointRecord} — every record\n * already carries `mode` / `seq` / `timestamp_ns` / `format_version`, so the\n * WAL is just an ordered list of records. `replayWAL` walks this list.\n */\nexport type WALEntry = GraphCheckpointRecord;\n\n// ---------------------------------------------------------------------------\n// Eviction policy (dormant subgraph management)\n// ---------------------------------------------------------------------------\n\n/**\n * Policy for evicting dormant subgraphs to reduce memory.\n *\n * When a subgraph hasn't propagated for `idleTimeoutMs`, it is serialized\n * using the graph's codec and JS objects are released. Re-hydrated on next\n * access (read, propagation, describe).\n */\nexport interface EvictionPolicy {\n\t/** Milliseconds of inactivity before eviction. */\n\tidleTimeoutMs: number;\n\t/** Codec to use for serializing evicted subgraphs (default: graph's codec). */\n\tcodec?: GraphCodec;\n}\n\n/** Metadata about an evicted subgraph, exposed via describe(). */\nexport interface EvictedSubgraphInfo {\n\t/** True if currently evicted (serialized, JS objects released). */\n\tevicted: true;\n\t/** Wall-clock ns of last propagation before eviction. */\n\tlastActiveNs: bigint;\n\t/** Size of serialized buffer in bytes. */\n\tserializedBytes: number;\n\t/** Codec used for serialization. */\n\tcodecName: string;\n}\n\n// ---------------------------------------------------------------------------\n// JSON codec (default — wraps current behavior)\n// ---------------------------------------------------------------------------\n\n/**\n * Default JSON codec. Wraps `JSON.stringify`/`JSON.parse` with deterministic\n * key ordering (matching current `snapshot()` behavior).\n */\nexport const JsonCodec: GraphCodec = {\n\tname: \"json\",\n\tversion: 1,\n\tcontentType: \"application/json\",\n\n\tencode(snapshot: GraphPersistSnapshot): Uint8Array {\n\t\t// Deterministic: snapshot() already sorts keys.\n\t\tconst json = JSON.stringify(snapshot);\n\t\treturn new TextEncoder().encode(json);\n\t},\n\n\tdecode(buffer: Uint8Array, _codecVersion?: number): GraphPersistSnapshot {\n\t\tconst json = new TextDecoder().decode(buffer);\n\t\treturn JSON.parse(json) as GraphPersistSnapshot;\n\t},\n};\n\n// ---------------------------------------------------------------------------\n// DAG-CBOR codec (factory — requires @ipld/dag-cbor DI)\n// ---------------------------------------------------------------------------\n\n/**\n * Create a DAG-CBOR codec.\n *\n * Requires `@ipld/dag-cbor` as a peer dependency. ~40-50% smaller than JSON,\n * deterministic encoding (required for V1 CID), CID links as native type.\n *\n * @example\n * ```ts\n * import * as dagCbor from \"@ipld/dag-cbor\";\n * const codec = createDagCborCodec(dagCbor);\n * config.registerCodec(codec);\n * const bytes = graph.snapshot({ format: \"bytes\", codec: \"dag-cbor\" });\n * ```\n */\nexport function createDagCborCodec(dagCbor: {\n\tencode: (value: unknown) => Uint8Array;\n\tdecode: (bytes: Uint8Array) => unknown;\n}): GraphCodec {\n\treturn {\n\t\tname: \"dag-cbor\",\n\t\tversion: 1,\n\t\tcontentType: \"application/dag-cbor\",\n\t\tencode: (snapshot) => dagCbor.encode(snapshot),\n\t\tdecode: (buffer, _codecVersion) => dagCbor.decode(buffer) as GraphPersistSnapshot,\n\t};\n}\n\n/**\n * Create a DAG-CBOR + zstd codec. ~80-90% smaller than JSON.\n *\n * Requires `@ipld/dag-cbor` and a zstd implementation (e.g. `fzstd` for\n * browser, `node:zlib` for Node.js).\n *\n * @example\n * ```ts\n * import * as dagCbor from \"@ipld/dag-cbor\";\n * import { compressSync, decompressSync } from \"fzstd\";\n * const codec = createDagCborZstdCodec(dagCbor, { compressSync, decompressSync });\n * config.registerCodec(codec);\n * ```\n */\nexport function createDagCborZstdCodec(\n\tdagCbor: {\n\t\tencode: (value: unknown) => Uint8Array;\n\t\tdecode: (bytes: Uint8Array) => unknown;\n\t},\n\tzstd: {\n\t\tcompressSync: (data: Uint8Array) => Uint8Array;\n\t\tdecompressSync: (data: Uint8Array) => Uint8Array;\n\t},\n): GraphCodec {\n\treturn {\n\t\tname: \"dag-cbor-zstd\",\n\t\tversion: 1,\n\t\tcontentType: \"application/dag-cbor+zstd\",\n\t\tencode: (snapshot) => zstd.compressSync(dagCbor.encode(snapshot)),\n\t\tdecode: (buffer, _codecVersion) =>\n\t\t\tdagCbor.decode(zstd.decompressSync(buffer)) as GraphPersistSnapshot,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Envelope (v1) — self-describing codec metadata prepended to payload bytes\n// ---------------------------------------------------------------------------\n\n/** Current envelope format version. Bump on breaking layout changes. */\nexport const ENVELOPE_VERSION = 1;\n\nconst ENVELOPE_MIN_LEN = 4; // env_v(1) + name_len(1) + codec_v(2) + name/payload(≥0)\n\n/**\n * Prepend the v1 envelope to `payload` identifying `codec`. The resulting\n * bytes are self-describing — any caller with access to the registering\n * {@link GraphReFlyConfig} can {@link decodeEnvelope} without knowing the\n * codec up front.\n *\n * Layout:\n * `[envelope_v=1: u8][name_len: u8][name: utf8][codec_v: u16 BE][payload: rest]`\n *\n * @throws If `codec.name` encodes to more than 255 UTF-8 bytes or\n * `codec.version` doesn't fit in a u16.\n */\nexport function encodeEnvelope(\n\tcodec: Pick<GraphCodec, \"name\" | \"version\">,\n\tpayload: Uint8Array,\n): Uint8Array {\n\tconst nameBytes = new TextEncoder().encode(codec.name);\n\tif (nameBytes.length === 0 || nameBytes.length > 255) {\n\t\tthrow new Error(\n\t\t\t`encodeEnvelope: codec name \"${codec.name}\" encodes to ${nameBytes.length} bytes (must be 1–255)`,\n\t\t);\n\t}\n\tconst cv = codec.version;\n\tif (!Number.isInteger(cv) || cv < 0 || cv > 0xffff) {\n\t\tthrow new Error(\n\t\t\t`encodeEnvelope: codec.version ${cv} out of u16 range (expected integer 0–65535)`,\n\t\t);\n\t}\n\t// Guard against RangeError-on-alloc for very large payloads — we need\n\t// `Number.isSafeInteger` math on `1 + 1 + nameBytes.length + 2 +\n\t// payload.length` and the resulting Uint8Array must fit within the\n\t// platform limit (2³² − 1 bytes on 64-bit JS engines).\n\tconst totalLen = 1 + 1 + nameBytes.length + 2 + payload.length;\n\tif (totalLen > 0xffffffff) {\n\t\tthrow new Error(\n\t\t\t`encodeEnvelope: total envelope size ${totalLen} exceeds 2^32-1 bytes (payload ${payload.length} bytes)`,\n\t\t);\n\t}\n\tconst out = new Uint8Array(totalLen);\n\tlet i = 0;\n\tout[i++] = ENVELOPE_VERSION;\n\tout[i++] = nameBytes.length;\n\tout.set(nameBytes, i);\n\ti += nameBytes.length;\n\tout[i++] = (cv >>> 8) & 0xff;\n\tout[i++] = cv & 0xff;\n\tout.set(payload, i);\n\treturn out;\n}\n\n/**\n * Inverse of {@link encodeEnvelope}. Reads the header, resolves the codec\n * via `config.lookupCodec(name)`, and returns the codec + its version + the\n * inner payload slice. The caller feeds `payload` to `codec.decode(payload,\n * codecVersion)` — or uses {@link Graph.decode} which does both steps.\n *\n * @throws If the envelope is truncated, the version is unsupported, or the\n * named codec isn't registered on `config`.\n */\nexport function decodeEnvelope(\n\tbytes: Uint8Array,\n\tconfig: GraphReFlyConfig,\n): { codec: GraphCodec; codecVersion: number; payload: Uint8Array } {\n\tif (bytes.length < ENVELOPE_MIN_LEN) {\n\t\tthrow new Error(`decodeEnvelope: bytes too short (${bytes.length} < ${ENVELOPE_MIN_LEN})`);\n\t}\n\tlet i = 0;\n\tconst envVersion = bytes[i++]!;\n\tif (envVersion !== ENVELOPE_VERSION) {\n\t\tthrow new Error(\n\t\t\t`decodeEnvelope: unsupported envelope version ${envVersion} (expected ${ENVELOPE_VERSION})`,\n\t\t);\n\t}\n\tconst nameLen = bytes[i++]!;\n\tif (nameLen === 0) {\n\t\tthrow new Error(\"decodeEnvelope: name_len must be >= 1\");\n\t}\n\tif (i + nameLen + 2 > bytes.length) {\n\t\tthrow new Error(\n\t\t\t`decodeEnvelope: envelope truncated (need ${i + nameLen + 2} bytes, have ${bytes.length})`,\n\t\t);\n\t}\n\tconst name = new TextDecoder().decode(bytes.subarray(i, i + nameLen));\n\ti += nameLen;\n\tconst codecVersion = ((bytes[i]! << 8) | bytes[i + 1]!) >>> 0;\n\ti += 2;\n\tconst payload = bytes.subarray(i);\n\tconst codec = config.lookupCodec<GraphCodec>(name);\n\tif (codec == null) {\n\t\tthrow new Error(\n\t\t\t`decodeEnvelope: codec \"${name}\" not registered (envelope codec_v=${codecVersion})`,\n\t\t);\n\t}\n\treturn { codec, codecVersion, payload };\n}\n\n/**\n * Register the built-in {@link JsonCodec} on a config. Called once on\n * `defaultConfig` at module load so `graph.snapshot({format: \"bytes\", codec:\n * \"json\"})` works out of the box. Test / isolated configs should call this\n * manually before the first node is created.\n */\nexport function registerBuiltinCodecs(config: GraphReFlyConfig): void {\n\tconfig.registerCodec(JsonCodec);\n}\n\n// ---------------------------------------------------------------------------\n// WAL helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Reconstruct a snapshot from a WAL (sequence of {@link GraphCheckpointRecord}s).\n *\n * - Must start with a `\"full\"` record carrying a baseline snapshot — that's\n * the anchor {@link Graph.attachStorage} always emits on the first flush\n * of any tier (and every `compactEvery`-th flush thereafter).\n * - Subsequent `\"full\"` entries (compaction points) **replace** the result\n * wholesale.\n * - `\"diff\"` entries roll forward by applying the structural diff —\n * added nodes (via `nodesAddedFull`), removed nodes, and changed fields\n * are reflected into the accumulated snapshot.\n *\n * Validates monotonic `seq` progression across entries.\n */\nexport function replayWAL(entries: readonly WALEntry[]): GraphPersistSnapshot {\n\tif (entries.length === 0) {\n\t\tthrow new Error(\"WAL is empty — need at least one full snapshot\");\n\t}\n\n\tconst first = entries[0]!;\n\tif (first.mode !== \"full\") {\n\t\tthrow new Error(\"WAL must start with a full record carrying a baseline snapshot\");\n\t}\n\n\tlet result: GraphPersistSnapshot = JSON.parse(JSON.stringify(first.snapshot));\n\tlet prevSeq: number = first.seq;\n\n\tfor (let i = 1; i < entries.length; i++) {\n\t\tconst entry = entries[i]!;\n\t\tif (entry.seq <= prevSeq) {\n\t\t\tthrow new Error(\n\t\t\t\t`WAL chain broken at index ${i}: seq=${entry.seq} must exceed prev seq=${prevSeq}`,\n\t\t\t);\n\t\t}\n\n\t\tif (entry.mode === \"full\") {\n\t\t\t// Replace baseline wholesale (Unit 23 D fix — Object.assign left\n\t\t\t// stale keys from pre-compact state visible).\n\t\t\tresult = JSON.parse(JSON.stringify(entry.snapshot));\n\t\t\tprevSeq = entry.seq;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// mode === \"diff\": apply structural diff to the accumulated snapshot.\n\t\tconst diff = entry.diff;\n\t\t// Apply removes first so a path reused across a remove+add in a single\n\t\t// diff lands on the `nodesAddedFull` slice rather than being wiped.\n\t\tfor (const path of diff.nodesRemoved) {\n\t\t\tdelete result.nodes[path];\n\t\t}\n\t\t// Reinstate added nodes from the full-slice payload carried by\n\t\t// GraphWALDiff. Deep-clone so later mutations don't alias the WAL\n\t\t// entry's source slice.\n\t\tconst addedFull = diff.nodesAddedFull;\n\t\tif (addedFull != null) {\n\t\t\tfor (const [path, slice] of Object.entries(addedFull)) {\n\t\t\t\tresult.nodes[path] = JSON.parse(JSON.stringify(slice));\n\t\t\t}\n\t\t}\n\t\tfor (const change of diff.nodesChanged) {\n\t\t\tconst existing = result.nodes[change.path];\n\t\t\tif (existing == null) continue;\n\t\t\t(existing as Record<string, unknown>)[change.field] = change.to;\n\t\t}\n\n\t\t// Edges are derived from node `_deps` at restore time (Unit 7) — no\n\t\t// separate edge-patch pass.\n\t\tprevSeq = entry.seq;\n\t}\n\n\treturn result;\n}\n","/**\n * Who is performing an operation (attribution + ABAC input).\n *\n * @see GRAPHREFLY-SPEC — roadmap Phase 1.5 (Actor & Guard).\n */\nexport type Actor = {\n\ttype: \"human\" | \"llm\" | \"wallet\" | \"system\" | string;\n\tid: string;\n} & Record<string, unknown>;\n\n/** Default actor when none is passed ({@link normalizeActor}). */\nexport const DEFAULT_ACTOR: Actor = { type: \"system\", id: \"\" };\n\n/**\n * Fills missing `type` / `id` on an actor and returns {@link DEFAULT_ACTOR} when input is undefined.\n *\n * @param actor - Optional partial actor from a transport hint.\n * @returns A normalized `Actor` safe to pass to guards and graph APIs.\n *\n * @example\n * ```ts\n * import { normalizeActor } from \"@graphrefly/graphrefly-ts\";\n *\n * normalizeActor({ type: \"human\", id: \"u1\" });\n * ```\n */\nexport function normalizeActor(actor?: Actor): Actor {\n\tif (actor == null) return DEFAULT_ACTOR;\n\tconst { type, id, ...rest } = actor;\n\treturn {\n\t\ttype: type ?? \"system\",\n\t\tid: id ?? \"\",\n\t\t...rest,\n\t} as Actor;\n}\n","/**\n * Singleton protocol config. Holds the message-type registry, the\n * `onMessage` / `onSubscribe` hooks, versioning defaults, and the freeze flag.\n *\n * Layering: this file is protocol-pure. It imports only from `messages.ts`\n * and declares opaque type shapes for handlers — the concrete default\n * implementations and the `defaultConfig` instance live in `node.ts` so that\n * handler bodies can touch `NodeImpl` internals without creating a cycle.\n *\n * Two access paths:\n * 1. **Default instance** (`defaultConfig` in `node.ts`) — use\n * `configure((cfg) => ...)` at app startup; every node implicitly binds to it.\n * 2. **Isolated instance** (`new GraphReFlyConfig(...)`) — pass via\n * `opts.config` for test isolation or custom protocol stacks.\n *\n * A config **freezes on first getter read** of any hook (`onMessage`,\n * `onSubscribe`). `NodeImpl`'s constructor intentionally touches one of these\n * on first use so configuration cannot drift once nodes exist.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tINVALIDATE,\n\ttype Message,\n\ttype Messages,\n\ttype MessageTypeRegistration,\n\ttype MessageTypeRegistrationInput,\n\tPAUSE,\n\tRESOLVED,\n\tRESUME,\n\tSTART,\n\tTEARDOWN,\n} from \"./messages.js\";\nimport type { HashFn, VersioningLevel } from \"./versioning.js\";\n\n// ---------------------------------------------------------------------------\n// Handler type shapes\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal node surface visible to default handlers. Concrete `NodeImpl`\n * implements this plus a large set of package-private fields; handlers that\n * need the richer surface cast to the concrete type in `node.ts`.\n */\nexport interface NodeCtx {\n\treadonly name?: string;\n\treadonly status: string;\n\treadonly cache: unknown;\n}\n\n/** Imperative actions available inside a node's compute function (§5). */\nexport interface NodeActions {\n\t/**\n\t * Sugar for `down([[DATA, value]])`. One call = one wave with a\n\t * single DATA payload. The emit pipeline auto-prefixes `[DIRTY]`,\n\t * runs equals substitution against the live cache, and dispatches\n\t * to sinks with phase deferral. Diamond-safe by construction.\n\t */\n\temit(value: unknown): void;\n\t/**\n\t * Send one or more messages downstream. Accepts either a single\n\t * {@link Message} tuple or a {@link Messages} array of tuples. One\n\t * call = one wave: the emit pipeline tier-sorts the input,\n\t * auto-prefixes `[DIRTY]` when a tier-3 payload is present and the\n\t * node isn't already dirty, runs equals substitution, then\n\t * dispatches. Multiple calls produce multiple waves.\n\t */\n\tdown(messageOrMessages: Message | Messages): void;\n\t/**\n\t * Send one or more messages upstream. Accepts the same shapes as\n\t * {@link down}. Tier 3 (DATA/RESOLVED) and tier 4 (COMPLETE/ERROR)\n\t * are downstream-only and will throw — up is for DIRTY, INVALIDATE,\n\t * PAUSE, RESUME, and TEARDOWN only. No cache advance, no equals,\n\t * no framing — a plain forward to every dep.\n\t */\n\tup(messageOrMessages: Message | Messages): void;\n}\n\n/**\n * Message-flow context passed to {@link OnMessageHandler}.\n *\n * - `\"down-in\"` — message arriving from a dep (identified by `depIndex`).\n * - `\"up-in\"` — message arriving from a sink.\n */\nexport type MessageContext = { direction: \"down-in\"; depIndex: number } | { direction: \"up-in\" };\n\n/**\n * Per-sink context passed to {@link OnSubscribeHandler}.\n */\nexport interface SubscribeContext {\n\t/** Post-subscribe sink count. `1` means first subscriber after 0. */\n\tsinkCount: number;\n\t/** True when this subscribe cleared a resubscribable terminal state. */\n\tafterTerminalReset: boolean;\n}\n\n/**\n * Singleton message interceptor. Called for every message in either direction\n * before the default per-tier dispatch runs. Return `\"consume\"` to suppress\n * default handling.\n */\nexport type OnMessageHandler = (\n\tnode: NodeCtx,\n\tmsg: Message,\n\tctx: MessageContext,\n\tactions: NodeActions,\n) => \"consume\" | undefined;\n\n/**\n * Singleton subscribe ceremony. Fires for every sink subscribe on every node.\n * Default implementation emits the START handshake (+ cached DATA when\n * present) to the new sink. Return a cleanup function to run on unsubscribe.\n */\nexport type OnSubscribeHandler = (\n\tnode: NodeCtx,\n\tsink: (messages: Messages) => void,\n\tctx: SubscribeContext,\n\tactions: NodeActions,\n) => (() => void) | undefined;\n\n/**\n * Event payload for {@link GlobalInspectorHook}. One event fires per outgoing\n * message batch from any node bound to the config.\n *\n * - `kind: \"emit\"` — fires after equals substitution (`finalMessages`) and\n * before sink dispatch. `messages` is the exact batch sinks see.\n */\nexport type GlobalInspectorEvent = {\n\tkind: \"emit\";\n\tnode: NodeCtx;\n\tmessages: Messages;\n};\n\n/**\n * Process-global observability hook for full-graph tracing\n * (Redux-DevTools-style action history). Fires from every node's `_emit`\n * waist whenever {@link GraphReFlyConfig.inspectorEnabled} is `true`.\n *\n * Distinct from per-node `_setInspectorHook` (which is the dep-message /\n * fn-run causal trace used by `Graph.observe(path, { causal, derived })`).\n * Use the global hook to record every emission across every node — useful for\n * time-travel debuggers, tracers, and replay tooling. Use the per-node hook\n * to attribute a single subscribed path's wave to its driving deps.\n *\n * Errors thrown from the hook are swallowed — instrumentation must not break\n * the data plane.\n */\nexport type GlobalInspectorHook = (event: GlobalInspectorEvent) => void;\n\n// ---------------------------------------------------------------------------\n// GraphReFlyConfig\n// ---------------------------------------------------------------------------\n\n/**\n * Singleton protocol config.\n *\n * A config freezes on first getter read of any hook. After freeze, any\n * attempt to mutate (register a message type, set a hook) throws.\n */\nexport class GraphReFlyConfig {\n\tprivate _messageTypes = new Map<symbol, MessageTypeRegistration>();\n\tprivate _codecs = new Map<string, { readonly name: string; readonly version: number }>();\n\tprivate _onMessage: OnMessageHandler;\n\tprivate _onSubscribe: OnSubscribeHandler;\n\tprivate _defaultVersioning: VersioningLevel | undefined;\n\tprivate _defaultHashFn: HashFn | undefined;\n\tprivate _inspectorEnabled: boolean = !(\n\t\ttypeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\"\n\t);\n\tprivate _globalInspector?: GlobalInspectorHook;\n\tprivate _frozen = false;\n\n\t/**\n\t * Pre-bound tier lookup — shared by every node bound to this config. Since\n\t * the registry is frozen on first hook access, this closure can be built\n\t * once in the constructor and handed directly to `downWithBatch` /\n\t * `_frameBatch` paths without per-node or per-emission `.bind(config)`\n\t * allocation.\n\t */\n\treadonly tierOf: (t: symbol) => number;\n\n\tconstructor(init: {\n\t\tonMessage: OnMessageHandler;\n\t\tonSubscribe: OnSubscribeHandler;\n\t\tdefaultVersioning?: VersioningLevel;\n\t\tdefaultHashFn?: HashFn;\n\t}) {\n\t\tthis._onMessage = init.onMessage;\n\t\tthis._onSubscribe = init.onSubscribe;\n\t\tthis._defaultVersioning = init.defaultVersioning;\n\t\tthis._defaultHashFn = init.defaultHashFn;\n\t\t// Captured once. Calls back into `this._messageTypes` — still returns\n\t\t// the current registration, but post-freeze the registry is immutable\n\t\t// so the closure is effectively constant.\n\t\tthis.tierOf = (t: symbol): number => {\n\t\t\tconst reg = this._messageTypes.get(t);\n\t\t\treturn reg != null ? reg.tier : 1;\n\t\t};\n\t}\n\n\t// --- Hook getters (freeze on read) ---\n\n\tget onMessage(): OnMessageHandler {\n\t\tthis._frozen = true;\n\t\treturn this._onMessage;\n\t}\n\n\tget onSubscribe(): OnSubscribeHandler {\n\t\tthis._frozen = true;\n\t\treturn this._onSubscribe;\n\t}\n\n\t// --- Hook setters (throw when frozen) ---\n\n\tset onMessage(v: OnMessageHandler) {\n\t\tthis._assertUnfrozen();\n\t\tthis._onMessage = v;\n\t}\n\n\tset onSubscribe(v: OnSubscribeHandler) {\n\t\tthis._assertUnfrozen();\n\t\tthis._onSubscribe = v;\n\t}\n\n\t/**\n\t * Default versioning level applied to every node bound to this config,\n\t * unless the node's own `opts.versioning` provides an explicit override.\n\t * Setting this is only allowed before the config freezes (i.e., before\n\t * the first node is created) so every node in the graph sees a\n\t * consistent starting level. Individual nodes can still opt into a\n\t * higher level via `opts.versioning`, or post-hoc via\n\t * `NodeImpl._applyVersioning(level)` when the node is quiescent.\n\t *\n\t * v0 is the minimum opt-in — unversioned nodes (`undefined`) skip\n\t * the version counter entirely. v1 adds content-addressed cid.\n\t * Future levels (v2, v3) are reserved for linked-history and\n\t * cryptographic attestation extensions.\n\t */\n\tget defaultVersioning(): VersioningLevel | undefined {\n\t\treturn this._defaultVersioning;\n\t}\n\tset defaultVersioning(v: VersioningLevel | undefined) {\n\t\tthis._assertUnfrozen();\n\t\tthis._defaultVersioning = v;\n\t}\n\n\t/**\n\t * Default content-hash function applied to every versioned node bound\n\t * to this config, unless the node's own `opts.versioningHash` provides\n\t * an explicit override. Use this when a graph needs a non-default hash\n\t * — e.g., swap the vendored sync SHA-256 for a faster non-crypto hash\n\t * (xxHash, FNV-1a) in hot-path workloads, or a stronger hash when\n\t * versioning v1 cids are used as audit anchors.\n\t *\n\t * Only settable before the config freezes. Individual nodes can still\n\t * override via `opts.versioningHash`.\n\t */\n\tget defaultHashFn(): HashFn | undefined {\n\t\treturn this._defaultHashFn;\n\t}\n\tset defaultHashFn(v: HashFn | undefined) {\n\t\tthis._assertUnfrozen();\n\t\tthis._defaultHashFn = v;\n\t}\n\n\t/**\n\t * When `false`, structured observation options (`causal`, `timeline`)\n\t * and `Graph.trace()` writes are no-ops. Raw `Graph.observe()` always\n\t * works. Default: `true` outside production (`NODE_ENV !== \"production\"`).\n\t *\n\t * Settable at any time — inspector gating is an operational concern, not\n\t * a protocol invariant, so it does NOT require freeze before node creation.\n\t */\n\tget inspectorEnabled(): boolean {\n\t\treturn this._inspectorEnabled;\n\t}\n\tset inspectorEnabled(v: boolean) {\n\t\tthis._inspectorEnabled = v;\n\t}\n\n\t/**\n\t * Process-global observability hook (Redux-DevTools-style full-graph\n\t * tracer). Fires once per outgoing batch from every node bound to this\n\t * config, gated by {@link inspectorEnabled}. See {@link GlobalInspectorHook}.\n\t *\n\t * Settable at any time — like {@link inspectorEnabled} this is operational,\n\t * not protocol-shaping, so it does NOT trigger config freeze.\n\t */\n\tget globalInspector(): GlobalInspectorHook | undefined {\n\t\treturn this._globalInspector;\n\t}\n\tset globalInspector(v: GlobalInspectorHook | undefined) {\n\t\tthis._globalInspector = v;\n\t}\n\n\t// --- Registry (writes require unfrozen; reads are free lookups) ---\n\n\t/**\n\t * Register a custom message type. Must be called before any node that\n\t * uses this config has been created — otherwise throws. Default\n\t * `wireCrossing` is `tier >= 3`.\n\t */\n\tregisterMessageType(t: symbol, input: MessageTypeRegistrationInput): this {\n\t\tthis._assertUnfrozen();\n\t\tthis._messageTypes.set(t, {\n\t\t\ttier: input.tier,\n\t\t\twireCrossing: input.wireCrossing ?? input.tier >= 3,\n\t\t\tmetaPassthrough: input.metaPassthrough ?? true,\n\t\t});\n\t\treturn this;\n\t}\n\n\t/** Tier for `t`. Unknown types default to tier 1 (immediate, after START). */\n\tmessageTier(t: symbol): number {\n\t\tconst reg = this._messageTypes.get(t);\n\t\treturn reg != null ? reg.tier : 1;\n\t}\n\n\t/**\n\t * Whether `t` is registered as wire-crossing. Unknown types default to\n\t * `true` (spec §1.3.6 forward-compat — unknowns cross the wire).\n\t */\n\tisWireCrossing(t: symbol): boolean {\n\t\tconst reg = this._messageTypes.get(t);\n\t\treturn reg != null ? reg.wireCrossing : true;\n\t}\n\n\t/** Convenience inverse of {@link isWireCrossing}. */\n\tisLocalOnly(t: symbol): boolean {\n\t\treturn !this.isWireCrossing(t);\n\t}\n\n\t/**\n\t * Whether `t` is forwarded to meta companions by `Graph.signal`. Defaults\n\t * to `true` for unknowns (forward-compat — new types pass through meta by\n\t * default; opt-in filter via `registerMessageType({metaPassthrough: false})`).\n\t */\n\tisMetaPassthrough(t: symbol): boolean {\n\t\tconst reg = this._messageTypes.get(t);\n\t\treturn reg != null ? reg.metaPassthrough : true;\n\t}\n\n\t/** Whether `t` is a registered (built-in or custom) type. */\n\tisKnownMessageType(t: symbol): boolean {\n\t\treturn this._messageTypes.has(t);\n\t}\n\n\t// --- Codec registry (writes require unfrozen; reads are free lookups) ---\n\n\t/**\n\t * Register a graph codec by `codec.name`. Used by the envelope-based\n\t * `graph.snapshot({format: \"bytes\", codec: name})` path and\n\t * `Graph.decode(bytes)` auto-dispatch. Must be called before any node\n\t * bound to this config is created — otherwise throws.\n\t *\n\t * Re-registering the same name overwrites, so user codecs can shadow\n\t * built-in ones before freeze (e.g., to swap a zstd-wrapped dag-cbor in\n\t * for `\"dag-cbor\"`).\n\t */\n\tregisterCodec<T extends { readonly name: string; readonly version: number }>(codec: T): this {\n\t\tthis._assertUnfrozen();\n\t\tthis._codecs.set(codec.name, codec);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resolve a registered codec by name. Returns `undefined` for unknown\n\t * names. Typed callers cast to their concrete codec interface (e.g.,\n\t * `config.lookupCodec<GraphCodec>(\"json\")`) — this method stays\n\t * layer-pure (no import of graph-layer types into `core/`).\n\t */\n\tlookupCodec<T = { readonly name: string; readonly version: number }>(\n\t\tname: string,\n\t): T | undefined {\n\t\treturn this._codecs.get(name) as T | undefined;\n\t}\n\n\t/** @internal Used by tests and dev tooling — check freeze state without triggering it. */\n\t_isFrozen(): boolean {\n\t\treturn this._frozen;\n\t}\n\n\tprivate _assertUnfrozen(): void {\n\t\tif (this._frozen) {\n\t\t\tthrow new Error(\n\t\t\t\t\"GraphReFlyConfig is frozen: a node has already captured this config. \" +\n\t\t\t\t\t\"Register custom types and set hooks before creating any node.\",\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Built-in registration\n// ---------------------------------------------------------------------------\n\n/**\n * Register the 10 built-in message types on a fresh config. Called by\n * `node.ts` when it constructs `defaultConfig` and by test code / advanced\n * users after `new GraphReFlyConfig(...)`.\n */\nexport function registerBuiltins(cfg: GraphReFlyConfig): void {\n\tcfg.registerMessageType(START, { tier: 0, wireCrossing: false });\n\tcfg.registerMessageType(DIRTY, { tier: 1, wireCrossing: false });\n\t// INVALIDATE, COMPLETE, ERROR, TEARDOWN do NOT pass through to meta\n\t// companions via Graph.signal (spec §2.3). Meta still sees them via the\n\t// primary's own down-cascade.\n\tcfg.registerMessageType(INVALIDATE, {\n\t\ttier: 1,\n\t\twireCrossing: false,\n\t\tmetaPassthrough: false,\n\t});\n\tcfg.registerMessageType(PAUSE, { tier: 2, wireCrossing: false });\n\tcfg.registerMessageType(RESUME, { tier: 2, wireCrossing: false });\n\tcfg.registerMessageType(DATA, { tier: 3, wireCrossing: true });\n\tcfg.registerMessageType(RESOLVED, { tier: 3, wireCrossing: true });\n\tcfg.registerMessageType(COMPLETE, {\n\t\ttier: 4,\n\t\twireCrossing: true,\n\t\tmetaPassthrough: false,\n\t});\n\tcfg.registerMessageType(ERROR, {\n\t\ttier: 4,\n\t\twireCrossing: true,\n\t\tmetaPassthrough: false,\n\t});\n\tcfg.registerMessageType(TEARDOWN, {\n\t\ttier: 5,\n\t\twireCrossing: true,\n\t\tmetaPassthrough: false,\n\t});\n}\n","import type { Actor } from \"./actor.js\";\n\n/**\n * Actions checked by {@link NodeGuard}. `write` covers both {@link Node.down} and\n * {@link Node.up} today; finer-grained strings may be added later (e.g. `\"write.data\"`).\n */\nexport type GuardAction = \"write\" | \"signal\" | \"observe\" | (string & {});\n\nexport type NodeGuard = (actor: Actor, action: GuardAction) => boolean;\n\nexport type GuardDeniedDetails = {\n\tactor: Actor;\n\taction: GuardAction;\n\t/** Registry or options name when known */\n\tnodeName?: string;\n};\n\n/**\n * Thrown when a {@link NodeGuard} denies an action for a given actor.\n *\n * Carries the rejected `actor`, `action`, and optional `nodeName` for diagnostic\n * messages and middleware error handling.\n *\n * @example\n * ```ts\n * import { GuardDenied, policy } from \"@graphrefly/graphrefly-ts\";\n *\n * const guard = policy((allow) => { allow(\"observe\"); });\n * try {\n * if (!guard({ type: \"llm\", id: \"agent-1\" }, \"write\")) {\n * throw new GuardDenied(\n * { actor: { type: \"llm\", id: \"agent-1\" }, action: \"write\", nodeName: \"userInput\" },\n * );\n * }\n * } catch (e) {\n * if (e instanceof GuardDenied) console.error(e.action, e.actor.type); // \"write\" \"llm\"\n * }\n * ```\n */\nexport class GuardDenied extends Error {\n\treadonly actor: Actor;\n\treadonly action: GuardAction;\n\treadonly nodeName?: string;\n\n\t/**\n\t * @param details - Actor, action, and optional node name for the denial.\n\t * @param message - Optional override for the default error message.\n\t */\n\tconstructor(details: GuardDeniedDetails, message?: string) {\n\t\tsuper(\n\t\t\tmessage ??\n\t\t\t\t`GuardDenied: action \"${String(details.action)}\" denied for actor type \"${String(details.actor.type)}\"`,\n\t\t);\n\t\tthis.name = \"GuardDenied\";\n\t\tthis.actor = details.actor;\n\t\tthis.action = details.action;\n\t\tthis.nodeName = details.nodeName;\n\t}\n\n\t/** Qualified registry path when known (roadmap diagnostics: same as {@link nodeName}). */\n\tget node(): string | undefined {\n\t\treturn this.nodeName;\n\t}\n}\n\ntype Where = (actor: Actor) => boolean;\n\ntype Rule = {\n\tkind: \"allow\" | \"deny\";\n\tactions: Set<GuardAction>;\n\twhere: Where;\n};\n\nfunction normalizeActions(action: GuardAction | readonly GuardAction[]): GuardAction[] {\n\tif (Array.isArray(action)) {\n\t\treturn [...action];\n\t}\n\treturn [action as GuardAction];\n}\n\nfunction matchesActions(set: Set<GuardAction>, action: GuardAction): boolean {\n\treturn set.has(action) || set.has(\"*\" as GuardAction);\n}\n\nexport type PolicyAllow = (\n\taction: GuardAction | readonly GuardAction[],\n\topts?: { where?: Where },\n) => void;\n\nexport type PolicyDeny = (\n\taction: GuardAction | readonly GuardAction[],\n\topts?: { where?: Where },\n) => void;\n\nexport type PolicyRuleData = {\n\teffect: \"allow\" | \"deny\";\n\taction: GuardAction | readonly GuardAction[];\n\tactorType?: string | readonly string[];\n\tactorId?: string | readonly string[];\n\tclaims?: Record<string, unknown>;\n};\n\n/**\n * Declarative guard builder. Precedence: any matching **deny** blocks even if an allow also matches.\n * If no rule matches, the guard returns `false` (deny-by-default). Aligned with graphrefly-py `policy()`.\n *\n * @param build - Callback that registers `allow(...)` / `deny(...)` rules in order.\n * @returns A `NodeGuard` for use as `node({ guard })`.\n *\n * @example\n * ```ts\n * const guard = policy((allow, deny) => {\n * allow(\"observe\");\n * deny(\"write\", { where: (a) => a.type === \"llm\" });\n * });\n * ```\n */\nexport function policy(build: (allow: PolicyAllow, deny: PolicyDeny) => void): NodeGuard {\n\tconst rules: Rule[] = [];\n\tconst allow: PolicyAllow = (action, opts) => {\n\t\trules.push({\n\t\t\tkind: \"allow\",\n\t\t\tactions: new Set(normalizeActions(action)),\n\t\t\twhere: opts?.where ?? (() => true),\n\t\t});\n\t};\n\tconst deny: PolicyDeny = (action, opts) => {\n\t\trules.push({\n\t\t\tkind: \"deny\",\n\t\t\tactions: new Set(normalizeActions(action)),\n\t\t\twhere: opts?.where ?? (() => true),\n\t\t});\n\t};\n\tbuild(allow, deny);\n\treturn (actor, action) => {\n\t\tlet denied = false;\n\t\tlet allowed = false;\n\t\tfor (const r of rules) {\n\t\t\tif (!matchesActions(r.actions, action)) continue;\n\t\t\tif (!r.where(actor)) continue;\n\t\t\tif (r.kind === \"deny\") {\n\t\t\t\tdenied = true;\n\t\t\t} else {\n\t\t\t\tallowed = true;\n\t\t\t}\n\t\t}\n\t\tif (denied) return false;\n\t\treturn allowed;\n\t};\n}\n\n/**\n * Rebuild a declarative guard from persisted policy data (snapshot-safe).\n *\n * Rules are deny-overrides, same semantics as {@link policy}.\n */\nexport function policyFromRules(rules: readonly PolicyRuleData[]): NodeGuard {\n\treturn policy((allow, deny) => {\n\t\tfor (const rule of rules) {\n\t\t\tconst actorTypes =\n\t\t\t\trule.actorType == null\n\t\t\t\t\t? null\n\t\t\t\t\t: new Set(Array.isArray(rule.actorType) ? rule.actorType : [rule.actorType]);\n\t\t\tconst actorIds =\n\t\t\t\trule.actorId == null\n\t\t\t\t\t? null\n\t\t\t\t\t: new Set(Array.isArray(rule.actorId) ? rule.actorId : [rule.actorId]);\n\t\t\tconst claimEntries = Object.entries(rule.claims ?? {});\n\t\t\tconst where: Where = (actor) => {\n\t\t\t\tif (actorTypes !== null && !actorTypes.has(String(actor.type))) return false;\n\t\t\t\tif (actorIds !== null && !actorIds.has(String(actor.id ?? \"\"))) return false;\n\t\t\t\tfor (const [key, value] of claimEntries) {\n\t\t\t\t\tif ((actor as Record<string, unknown>)[key] !== value) return false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t};\n\t\t\tif (rule.effect === \"deny\") {\n\t\t\t\tdeny(rule.action, { where });\n\t\t\t} else {\n\t\t\t\tallow(rule.action, { where });\n\t\t\t}\n\t\t}\n\t});\n}\n\nconst STANDARD_WRITE_TYPES = [\"human\", \"llm\", \"wallet\", \"system\"] as const;\n\n/**\n * Derives a best-effort `meta.access` hint string by probing `guard` with the\n * standard actor types `human`, `llm`, `wallet`, `system` for the `\"write\"` action\n * (roadmap 1.5). Aligned with graphrefly-py `access_hint_for_guard`.\n *\n * @param guard - Guard function to probe (typically from {@link policy}).\n * @returns `\"restricted\"` when no standard type is allowed; `\"both\"` when both\n * `human` and `llm` are allowed (plus optionally `system`); the single allowed\n * type name when only one passes; or a `\"+\"` joined list otherwise.\n *\n * @example\n * ```ts\n * import { policy, accessHintForGuard } from \"@graphrefly/graphrefly-ts\";\n *\n * const guardBoth = policy((allow) => { allow(\"write\"); });\n * accessHintForGuard(guardBoth); // \"both\"\n *\n * const guardHuman = policy((allow) => {\n * allow(\"write\", { where: (a) => a.type === \"human\" });\n * });\n * accessHintForGuard(guardHuman); // \"human\"\n * ```\n */\nexport function accessHintForGuard(guard: NodeGuard): string {\n\tconst allowed = STANDARD_WRITE_TYPES.filter((t) => guard({ type: t, id: \"\" }, \"write\"));\n\tif (allowed.length === 0) return \"restricted\";\n\tif (\n\t\tallowed.includes(\"human\") &&\n\t\tallowed.includes(\"llm\") &&\n\t\tallowed.every((t) => t === \"human\" || t === \"llm\" || t === \"system\")\n\t) {\n\t\treturn \"both\";\n\t}\n\tif (allowed.length === 1) return allowed[0];\n\treturn allowed.join(\"+\");\n}\n","/**\n * Node versioning — GRAPHREFLY-SPEC §7.\n *\n * Progressive, optional versioning for node identity and change tracking.\n *\n * - **V0**: `id` + `version` — identity & change detection (~16 bytes overhead)\n * - **V1**: + `cid` + `prev` — content addressing & linked history (~60 bytes overhead)\n *\n * **Lifecycle notes:**\n * - Version advances only on DATA (not RESOLVED, INVALIDATE, or TEARDOWN).\n * - `resetOnTeardown` clears the cached value but does NOT reset versioning state.\n * After teardown, `v.cid` still reflects the last DATA value, not the cleared cache.\n * The invariant `hash(node.cache) === v.cid` only holds in `settled`/`resolved` status.\n * - Resubscribable nodes preserve versioning across subscription lifetimes (monotonic counter).\n */\n\n// Runtime-agnostic — no `node:crypto` import. `randomUUID` comes from Web\n// Crypto (`globalThis.crypto.randomUUID()`), available in Node 14.17+,\n// browsers, Deno, Bun, and Cloudflare Workers. The default content hash is a\n// vendored sync SHA-256 (see `sha256Hex` below) so versioning stays callable\n// from any runtime — `crypto.subtle.digest` is async and can't back a\n// synchronous `defaultHash`.\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** V0: identity + monotonic version counter. */\nexport type V0 = {\n\treadonly id: string;\n\tversion: number;\n};\n\n/** V1: V0 + content-addressed identifier + previous cid link. */\nexport type V1 = V0 & {\n\tcid: string;\n\tprev: string | null;\n};\n\n/** Union of all versioning info shapes. */\nexport type NodeVersionInfo = V0 | V1;\n\n/** Supported versioning levels (extensible to 2, 3 later). */\nexport type VersioningLevel = 0 | 1;\n\n/** Function that hashes a value to a hex string (for V1 cid). */\nexport type HashFn = (value: unknown) => string;\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface VersioningOptions {\n\t/** Override auto-generated id. */\n\tid?: string;\n\t/** Custom hash function for V1 cid (default: SHA-256 truncated to 16 hex chars). */\n\thash?: HashFn;\n}\n\n// ---------------------------------------------------------------------------\n// Default hash\n// ---------------------------------------------------------------------------\n\n/**\n * Canonicalize a value for deterministic cross-language hashing.\n *\n * - Integer-valued floats normalize to integer strings (`1.0` → `1`).\n * - `NaN`, `Infinity`, `-Infinity` are rejected (no JSON equivalent).\n * - `undefined` normalizes to `null`.\n * - Object keys are sorted lexicographically.\n *\n * This ensures TS `JSON.stringify` and Python `json.dumps(sort_keys=True)`\n * produce identical output for the same logical value.\n */\nexport function canonicalizeForHash(value: unknown): unknown {\n\tif (value === undefined) return null;\n\tif (typeof value === \"number\") {\n\t\tif (!Number.isFinite(value)) {\n\t\t\tthrow new TypeError(`Cannot hash non-finite number: ${value}`);\n\t\t}\n\t\tif (Number.isInteger(value) && !Number.isSafeInteger(value)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Cannot hash integer outside safe range (|n| > 2^53-1): ${value}. ` +\n\t\t\t\t\t\"Cross-language cid parity is not guaranteed for unsafe integers.\",\n\t\t\t);\n\t\t}\n\t\treturn value;\n\t}\n\tif (typeof value === \"string\" || typeof value === \"boolean\" || value === null) {\n\t\treturn value;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map(canonicalizeForHash);\n\t}\n\tif (typeof value === \"object\" && value !== null) {\n\t\tconst sorted: Record<string, unknown> = {};\n\t\tfor (const k of Object.keys(value as Record<string, unknown>).sort()) {\n\t\t\tsorted[k] = canonicalizeForHash((value as Record<string, unknown>)[k]);\n\t\t}\n\t\treturn sorted;\n\t}\n\t// Fallback: coerce to null (bigint, symbol, function)\n\treturn null;\n}\n\n// SHA-256 round constants (FIPS 180-4).\nconst SHA256_K = /* @__PURE__ */ new Uint32Array([\n\t0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n\t0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n\t0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n\t0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n\t0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n\t0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n\t0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n\t0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n]);\n\nconst UTF8_ENCODER = /* @__PURE__ */ new TextEncoder();\n\n/**\n * Sync SHA-256 of a UTF-8 string, returned as a lowercase hex digest. Matches\n * Node `crypto.createHash(\"sha256\").update(msg).digest(\"hex\")` byte-for-byte.\n *\n * Runtime-agnostic (no `node:crypto`, no `crypto.subtle`). Small enough to\n * inline rather than pulling a dependency; called only from `defaultHash`,\n * which runs once per DATA on versioned nodes, so per-call allocation is\n * acceptable. Callers that need a faster path override via\n * `NodeOptions.versioningHash`.\n */\nfunction sha256Hex(msg: string): string {\n\tconst bytes = UTF8_ENCODER.encode(msg);\n\tconst msgLen = bytes.length;\n\tconst bitLen = msgLen * 8;\n\t// Pad to multiple of 64: 0x80 byte + zeros + 8-byte big-endian bit length.\n\tconst totalLen = (msgLen + 9 + 63) & ~63;\n\tconst padded = new Uint8Array(totalLen);\n\tpadded.set(bytes);\n\tpadded[msgLen] = 0x80;\n\tconst dv = new DataView(padded.buffer);\n\t// Bit length as big-endian 64-bit int. JS numbers are 53-bit safe, so we\n\t// split into two 32-bit halves; messages up to 2^53 bits are supported.\n\tdv.setUint32(totalLen - 4, bitLen >>> 0, false);\n\tdv.setUint32(totalLen - 8, Math.floor(bitLen / 0x100000000) >>> 0, false);\n\n\t// Initial hash values (first 32 bits of fractional parts of sqrt of first 8 primes).\n\tlet h0 = 0x6a09e667;\n\tlet h1 = 0xbb67ae85;\n\tlet h2 = 0x3c6ef372;\n\tlet h3 = 0xa54ff53a;\n\tlet h4 = 0x510e527f;\n\tlet h5 = 0x9b05688c;\n\tlet h6 = 0x1f83d9ab;\n\tlet h7 = 0x5be0cd19;\n\n\tconst W = new Uint32Array(64);\n\tconst rotr = (x: number, n: number): number => (x >>> n) | (x << (32 - n));\n\n\tfor (let off = 0; off < totalLen; off += 64) {\n\t\tfor (let i = 0; i < 16; i++) W[i] = dv.getUint32(off + i * 4, false);\n\t\tfor (let i = 16; i < 64; i++) {\n\t\t\tconst w15 = W[i - 15];\n\t\t\tconst w2 = W[i - 2];\n\t\t\tconst s0 = rotr(w15, 7) ^ rotr(w15, 18) ^ (w15 >>> 3);\n\t\t\tconst s1 = rotr(w2, 17) ^ rotr(w2, 19) ^ (w2 >>> 10);\n\t\t\tW[i] = (W[i - 16] + s0 + W[i - 7] + s1) >>> 0;\n\t\t}\n\n\t\tlet a = h0;\n\t\tlet b = h1;\n\t\tlet c = h2;\n\t\tlet d = h3;\n\t\tlet e = h4;\n\t\tlet f = h5;\n\t\tlet g = h6;\n\t\tlet h = h7;\n\n\t\tfor (let i = 0; i < 64; i++) {\n\t\t\tconst S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);\n\t\t\tconst ch = (e & f) ^ (~e & g);\n\t\t\tconst t1 = (h + S1 + ch + SHA256_K[i] + W[i]) >>> 0;\n\t\t\tconst S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);\n\t\t\tconst mj = (a & b) ^ (a & c) ^ (b & c);\n\t\t\tconst t2 = (S0 + mj) >>> 0;\n\t\t\th = g;\n\t\t\tg = f;\n\t\t\tf = e;\n\t\t\te = (d + t1) >>> 0;\n\t\t\td = c;\n\t\t\tc = b;\n\t\t\tb = a;\n\t\t\ta = (t1 + t2) >>> 0;\n\t\t}\n\n\t\th0 = (h0 + a) >>> 0;\n\t\th1 = (h1 + b) >>> 0;\n\t\th2 = (h2 + c) >>> 0;\n\t\th3 = (h3 + d) >>> 0;\n\t\th4 = (h4 + e) >>> 0;\n\t\th5 = (h5 + f) >>> 0;\n\t\th6 = (h6 + g) >>> 0;\n\t\th7 = (h7 + h) >>> 0;\n\t}\n\n\tconst toHex = (x: number): string => x.toString(16).padStart(8, \"0\");\n\treturn (\n\t\ttoHex(h0) + toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4) + toHex(h5) + toHex(h6) + toHex(h7)\n\t);\n}\n\n/**\n * Default content hash: SHA-256 of deterministic JSON, truncated to 16 hex\n * chars (~64-bit). Uses {@link canonicalizeForHash} for cross-language parity\n * with Python `default_hash`.\n */\nexport function defaultHash(value: unknown): string {\n\tconst canonical = canonicalizeForHash(value ?? null);\n\tconst json = JSON.stringify(canonical);\n\treturn sha256Hex(json).slice(0, 16);\n}\n\n/**\n * Cross-runtime UUID generator. Uses Web Crypto (`globalThis.crypto.randomUUID`)\n * when available. Falls back to a tiny `Math.random`-seeded RFC 4122 v4\n * generator for environments that omit `crypto.randomUUID` — identity only,\n * not cryptographic.\n */\nfunction randomUuid(): string {\n\tconst c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n\tif (c?.randomUUID) return c.randomUUID();\n\t// Fallback (extremely rare — only hits on very old runtimes that expose no\n\t// Web Crypto at all). Not cryptographically strong.\n\tconst r = () =>\n\t\tMath.floor(Math.random() * 0x100000000)\n\t\t\t.toString(16)\n\t\t\t.padStart(8, \"0\");\n\tconst hex = r() + r() + r() + r();\n\treturn (\n\t\t`${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-` +\n\t\t`${((parseInt(hex.slice(16, 17), 16) & 0x3) | 0x8).toString(16)}${hex.slice(17, 20)}-${hex.slice(20, 32)}`\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create initial versioning state for a node.\n *\n * @param level - 0 for V0, 1 for V1.\n * @param initialValue - The node's initial cached value (used for V1 cid).\n * @param opts - Optional overrides (id, hash).\n */\nexport function createVersioning(\n\tlevel: VersioningLevel,\n\tinitialValue: unknown,\n\topts?: VersioningOptions,\n): NodeVersionInfo {\n\tconst id = opts?.id ?? randomUuid();\n\tif (level === 0) {\n\t\treturn { id, version: 0 } satisfies V0;\n\t}\n\tconst hash = opts?.hash ?? defaultHash;\n\tconst cid = hash(initialValue);\n\treturn { id, version: 0, cid, prev: null } satisfies V1;\n}\n\n// ---------------------------------------------------------------------------\n// Advance\n// ---------------------------------------------------------------------------\n\n/**\n * Advance versioning state after a DATA emission (value changed).\n *\n * Mutates `info` in place for performance (called on every DATA).\n * Only call when the cached value has actually changed (not on RESOLVED).\n *\n * @param info - The node's current versioning state.\n * @param newValue - The new cached value.\n * @param hashFn - Hash function (only used for V1).\n */\nexport function advanceVersion(info: NodeVersionInfo, newValue: unknown, hashFn: HashFn): void {\n\tinfo.version += 1;\n\tif (\"cid\" in info) {\n\t\t(info as V1).prev = (info as V1).cid;\n\t\t(info as V1).cid = hashFn(newValue);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Guards\n// ---------------------------------------------------------------------------\n\n/** Type guard: is this V1 versioning info? */\nexport function isV1(info: NodeVersionInfo): info is V1 {\n\treturn \"cid\" in info;\n}\n","/**\n * `NodeImpl` — the single GraphReFly node primitive.\n *\n * Per-dep state lives in a `DepRecord[]` — one entry per declared dep —\n * consolidating subscription cleanup, latest-data tracking, dirty/settled\n * flags, and terminal state into a single structure per dep.\n *\n * This file also owns the default singleton handlers (`defaultOnMessage`,\n * `defaultOnSubscribe`), the `defaultConfig` instance, and the public\n * `configure(...)` entry point. They live here because their bodies touch\n * `NodeImpl` internals; `config.ts` stays NodeImpl-agnostic.\n *\n * See GRAPHREFLY-SPEC §2 and COMPOSITION-GUIDE §1/§9 for the behavior\n * contract. See SESSION-foundation-redesign.md §§1–10 for design history.\n */\n\nimport { registerBuiltinCodecs } from \"../graph/codec.js\";\nimport type { Actor } from \"./actor.js\";\nimport { normalizeActor } from \"./actor.js\";\nimport { downWithBatch, isExplicitlyBatching, registerBatchFlushHook } from \"./batch.js\";\nimport { wallClockNs } from \"./clock.js\";\nimport type {\n\tMessageContext,\n\tNodeActions,\n\tNodeCtx,\n\tOnMessageHandler,\n\tOnSubscribeHandler,\n\tSubscribeContext,\n} from \"./config.js\";\nimport { GraphReFlyConfig, registerBuiltins } from \"./config.js\";\nimport type { GuardAction, NodeGuard } from \"./guard.js\";\nimport { GuardDenied } from \"./guard.js\";\nimport {\n\tCOMPLETE,\n\tCOMPLETE_ONLY_BATCH,\n\tDATA,\n\tDIRTY,\n\tDIRTY_MSG,\n\tDIRTY_ONLY_BATCH,\n\tERROR,\n\tINVALIDATE,\n\tINVALIDATE_ONLY_BATCH,\n\ttype Message,\n\ttype Messages,\n\tPAUSE,\n\tRESOLVED,\n\tRESOLVED_MSG,\n\tRESOLVED_ONLY_BATCH,\n\tRESUME,\n\tSTART,\n\tSTART_MSG,\n\tTEARDOWN,\n\tTEARDOWN_ONLY_BATCH,\n} from \"./messages.js\";\nimport {\n\tadvanceVersion,\n\tcreateVersioning,\n\tdefaultHash,\n\ttype HashFn,\n\ttype NodeVersionInfo,\n\ttype VersioningLevel,\n} from \"./versioning.js\";\n\n// ---------------------------------------------------------------------------\n// Internal sentinel + type helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Placeholder unsubscribe used to mark a dep subscription as \"pending\" during\n * the synchronous window between `dep.unsub = noopUnsub` and the return of\n * `dep.node.subscribe(...)`. Ensures the liveness check `dep.unsub === null`\n * in the subscription callback correctly passes for synchronous push-on-\n * subscribe deliveries, while still blocking stale drainPhase2 closures that\n * fire after deactivation has set `dep.unsub = null`.\n */\nconst noopUnsub: () => void = () => {};\n\n/**\n * Maximum `_pendingRerun` depth before we give up and emit ERROR. Bounds\n * autoTrackNode / `_addDep` discovery loops — a well-formed discovery\n * converges in O(n) total rounds for n deps, so 100 is ample.\n */\nconst MAX_RERUN_DEPTH = 100;\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Lifecycle status of a node.\n *\n * @see GRAPHREFLY-SPEC.md §2.2\n */\nexport type NodeStatus =\n\t| \"sentinel\"\n\t| \"pending\"\n\t| \"dirty\"\n\t| \"settled\"\n\t| \"resolved\"\n\t| \"completed\"\n\t| \"errored\";\n\n/** Callback that receives downstream message batches. */\nexport type NodeSink = (messages: Messages) => void;\n\n/**\n * Observability hook events fired by a per-node inspector. Used by\n * `Graph.observe(path, { causal, derived })` to build causal traces.\n *\n * - `\"dep_message\"` — fires in `_onDepMessage` before default dispatch,\n * one event per message received from a dep. Includes `depIndex` and\n * the raw `Message` tuple.\n * - `\"run\"` — fires in `_execFn` just before the user fn runs. Includes\n * the per-dep `prevData` snapshot that will be passed to fn.\n */\nexport type NodeInspectorHookEvent =\n\t| { kind: \"dep_message\"; depIndex: number; message: Message }\n\t| {\n\t\t\tkind: \"run\";\n\t\t\tbatchData: readonly (readonly unknown[] | undefined)[];\n\t\t\tprevData: readonly unknown[];\n\t };\n\n/** Callback attached to a node for per-message/per-run inspection. */\nexport type NodeInspectorHook = (event: NodeInspectorHookEvent) => void;\n\n/** Describe `type` for `Graph.describe` (GRAPHREFLY-SPEC Appendix B). */\nexport type NodeDescribeKind = \"state\" | \"derived\" | \"producer\" | \"effect\";\n\n/** Actor/delivery context for {@link Node.down} and {@link Node.up}. */\nexport type NodeTransportOptions = {\n\tactor?: Actor;\n\t/** When `true`, skips guard checks. */\n\tinternal?: boolean;\n\t/** `signal` for `Graph.signal` deliveries; default `write`. */\n\tdelivery?: \"write\" | \"signal\";\n};\n\n/**\n * Cleanup return shape from a node {@link NodeFn}.\n * - `() => void` — fires before the next fn run AND on deactivation (default).\n * - `{ deactivation: () => void }` — fires only on deactivation (persistent\n * resources that should survive across fn re-runs).\n */\nexport type NodeFnCleanup = (() => void) | { deactivation: () => void };\n\n/**\n * Fn-time context exposing per-wave metadata and a per-node persistent\n * scratch pad.\n *\n * - `prevData[i]` — last DATA value from dep `i` as of the END of the\n * previous wave (i.e. the value that was stable before this wave started).\n * Use as the fallback when `data[i]` is `undefined` (not involved) or\n * `[]` (RESOLVED, no new values this wave).\n * `undefined` means dep `i` has never produced DATA (sentinel state).\n * `null` is a valid DATA value. `undefined` is not a valid DATA value —\n * the protocol reserves it as the \"never sent\" sentinel.\n * - `ctx.prevData[i] === undefined` → dep has never produced DATA\n * - `ctx.prevData[i] !== undefined` → last DATA value (may be `null`)\n * - `terminalDeps[i]` — runtime shape:\n * - `undefined` → dep `i` is still live.\n * - `true` → dep `i` sent COMPLETE.\n * - anything else → dep `i` sent ERROR, value is the error payload.\n * Type is `readonly unknown[]` because `true | unknown` collapses to\n * `unknown` anyway; the three states are documented contract, not type.\n * - `store` — mutable bag that persists across fn runs within one activation\n * cycle. Wiped on deactivation and on resubscribable terminal reset.\n */\nexport interface FnCtx {\n\treadonly prevData: readonly unknown[];\n\treadonly terminalDeps: readonly unknown[];\n\treadonly store: Record<string, unknown>;\n}\n\n/**\n * Compute function passed to `node(deps, fn, opts?)`.\n *\n * `data[i]` holds the batch of DATA values received from dep `i` during the\n * current wave. Shape contract:\n * - `undefined` — dep `i` was not involved in this wave (no DIRTY received).\n * - `[]` — dep `i` was involved (dirtied), but settled as RESOLVED (value\n * unchanged). Use `ctx.prevData[i]` to read its last known value from the\n * previous wave.\n * - `[v1, v2, ...]` — dep `i` sent one or more DATA values. `at(-1)` gives\n * the latest; iterate for multi-emission processing.\n *\n * Emission is explicit via `actions.emit(v)` (sugar: equals + framing) or\n * `actions.down(msgs)` (raw). Return a cleanup function (or\n * `{ deactivation }`) to register teardown — any non-cleanup return value\n * is ignored. The `| void` leg lets arrow-block bodies satisfy `NodeFn`\n * without an explicit `return undefined`.\n *\n * Sugar constructors (`derived`, `effect`, `dynamicNode`) unwrap `data[i]`\n * to a single scalar (`at(-1)` with `ctx.prevData[i]` fallback) so their\n * user-facing fn signatures stay unchanged. Use raw `node()` when you need\n * the full batch array.\n */\nexport type NodeFn = (\n\tdata: readonly (readonly unknown[] | undefined)[],\n\tactions: NodeActions,\n\tctx: FnCtx,\n\t// biome-ignore lint/suspicious/noConfusingVoidType: see JSDoc above.\n) => NodeFnCleanup | void;\n\n/** Options accepted by every node constructor. */\nexport interface NodeOptions<T = unknown> {\n\tname?: string;\n\tdescribeKind?: NodeDescribeKind;\n\tequals?: (a: T, b: T) => boolean;\n\t/**\n\t * Pre-populate the cache at construction. `null` is a valid initial value.\n\t * `undefined` is treated as absent (not a valid DATA payload).\n\t */\n\tinitial?: T | null;\n\tmeta?: Record<string, unknown>;\n\tresubscribable?: boolean;\n\tresetOnTeardown?: boolean;\n\t/** Auto-emit `[[COMPLETE]]` when all deps complete. Default `true`. */\n\tcompleteWhenDepsComplete?: boolean;\n\t/**\n\t * Auto-propagate `[[ERROR]]` when any dep errors. Default `true`.\n\t * Set `false` only for rescue/catchError operators that handle errors\n\t * explicitly via `ctx.terminalDeps`.\n\t */\n\terrorWhenDepsError?: boolean;\n\t/**\n\t * Tier-2 PAUSE/RESUME handling.\n\t * - `true` (default): wave completion suppressed while paused; fn fires\n\t * once on RESUME if gate is satisfied.\n\t * - `false`: node ignores PAUSE (sources like timers that must keep running).\n\t * - `\"resumeAll\"`: on RESUME, replay every buffered DATA (future).\n\t */\n\tpausable?: boolean | \"resumeAll\";\n\tguard?: NodeGuard;\n\tversioning?: VersioningLevel;\n\tversioningId?: string;\n\tversioningHash?: HashFn;\n\t/**\n\t * Override the config instance this node binds to. Defaults to\n\t * {@link defaultConfig}. Useful for test isolation and custom protocol\n\t * stacks. The first node that reads any hook on the config freezes it.\n\t */\n\tconfig?: GraphReFlyConfig;\n}\n\n/** A reactive node in the GraphReFly protocol. */\nexport interface Node<T = unknown> {\n\treadonly name?: string;\n\treadonly status: NodeStatus;\n\t/**\n\t * Current cached value. Returns `undefined` when the node is in\n\t * `\"sentinel\"` state (no DATA ever emitted). v5 reserves `undefined`\n\t * globally as the sentinel value — the valid DATA type is `T | null`.\n\t * Therefore `node.cache === undefined` is a valid \"never emitted\" guard.\n\t * `node.status` distinguishes the richer states (`\"sentinel\"`,\n\t * `\"settled\"`, `\"errored\"`, etc.) when you need more than has-value.\n\t */\n\treadonly cache: T | null | undefined;\n\treadonly meta: Record<string, Node>;\n\treadonly lastMutation: Readonly<{ actor: Actor; timestamp_ns: number }> | undefined;\n\treadonly v: Readonly<NodeVersionInfo> | undefined;\n\t/**\n\t * Send one or more messages downstream. Accepts either a single\n\t * {@link Message} tuple (e.g. `node.down([DATA, 42])`) or a\n\t * {@link Messages} array of tuples (e.g.\n\t * `node.down([[DIRTY], [DATA, 42]])`). One call = one wave: the\n\t * emit pipeline tier-sorts the input, auto-prefixes `[DIRTY]` when\n\t * any tier-3 payload is present and the node is not already dirty,\n\t * runs equals substitution against the live cache (§3.5.1), then\n\t * dispatches to sinks with phase deferral.\n\t */\n\tdown(messageOrMessages: Message | Messages, options?: NodeTransportOptions): void;\n\t/**\n\t * Sugar for `down([[DATA, value]])`. One wave with a single DATA\n\t * payload — the pipeline adds the synthetic DIRTY prefix and runs\n\t * equals substitution against the live cache.\n\t */\n\temit(value: T | undefined | null, options?: NodeTransportOptions): void;\n\t/**\n\t * Send one or more messages upstream. Accepts the same shapes as\n\t * {@link down}. Upstream messages are tier <3 + tier 5 only\n\t * (DIRTY, INVALIDATE, PAUSE, RESUME, TEARDOWN); tier-3/4 payloads\n\t * throw — DATA/RESOLVED/COMPLETE/ERROR are downstream-only in this\n\t * protocol. No equals substitution, no cache advance, no DIRTY\n\t * auto-prefix — the up direction just forwards to every dep.\n\t */\n\tup?(messageOrMessages: Message | Messages, options?: NodeTransportOptions): void;\n\tsubscribe(sink: NodeSink, actor?: Actor): () => void;\n\tallowsObserve(actor: Actor): boolean;\n\thasGuard(): boolean;\n}\n\n// ---------------------------------------------------------------------------\n// DepRecord — per-dep state (§8.2)\n// ---------------------------------------------------------------------------\n\n/**\n * Per-dep runtime state. One entry per upstream node.\n *\n * `terminal` is the single terminal-state slot, shaped to match\n * {@link FnCtx.terminalDeps}:\n * - `undefined` — dep is still live.\n * - `true` — dep sent COMPLETE.\n * - anything else — dep sent ERROR with that payload.\n *\n * Edge case: an ERROR carrying an `undefined` payload is indistinguishable\n * from \"live\". Pass meaningful error values (Error objects, domain tags).\n */\nexport interface DepRecord {\n\treadonly node: Node;\n\tunsub: (() => void) | null;\n\t/**\n\t * Last DATA value from this dep as of the end of the previous completed\n\t * wave. `undefined` until dep has produced at least one DATA (sentinel).\n\t * Committed by `_execFn` after snapshotting `ctx.prevData` and before\n\t * `_clearWaveFlags`. `undefined` is reserved as the \"never sent\" sentinel —\n\t * `undefined` is not a valid DATA payload.\n\t */\n\tprevData: unknown;\n\t/** True while awaiting DATA/RESOLVED for the current wave. */\n\tdirty: boolean;\n\t/**\n\t * True if this dep was dirtied in the current wave (set in `_depDirtied`,\n\t * cleared in `_clearWaveFlags`). Distinguishes \"RESOLVED\" (`involvedThisWave\n\t * && dataBatch.length === 0`) from \"not involved\" (`!involvedThisWave`) in\n\t * the `data[i]` batch snapshot passed to fn.\n\t */\n\tinvolvedThisWave: boolean;\n\t/**\n\t * DATA values accumulated from this dep during the current wave.\n\t * Populated by `_depSettledAsData`, cleared by `_clearWaveFlags`.\n\t * Snapshotted (copied) by `_execFn` before `_clearWaveFlags` runs so\n\t * that fn always sees the full wave batch.\n\t */\n\tdataBatch: unknown[];\n\t/** Terminal-state slot — see JSDoc on {@link DepRecord}. */\n\tterminal: unknown;\n}\n\nfunction createDepRecord(n: Node): DepRecord {\n\treturn {\n\t\tnode: n,\n\t\tunsub: null,\n\t\tprevData: undefined,\n\t\tdirty: false,\n\t\tinvolvedThisWave: false,\n\t\tdataBatch: [],\n\t\tterminal: undefined,\n\t};\n}\n\nfunction resetDepRecord(d: DepRecord): void {\n\td.prevData = undefined;\n\td.dirty = false;\n\td.involvedThisWave = false;\n\td.dataBatch.length = 0;\n\td.terminal = undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Normalization helper\n// ---------------------------------------------------------------------------\n\n/**\n * Accept either a single `Message` tuple or a `Messages` array and return\n * a `Messages` array. The discriminator is the type of the first element:\n * a `Message` has a symbol at index 0, while a `Messages` array has a\n * nested array at index 0. This lets `node.down(...)` and `actions.down(...)`\n * take either shape without a wrapper allocation on the common single-msg\n * path.\n */\nfunction normalizeMessages(input: Message | Messages): Messages {\n\tif (input.length === 0) return input as Messages;\n\treturn typeof (input as Message)[0] === \"symbol\" ? [input as Message] : (input as Messages);\n}\n\n// ---------------------------------------------------------------------------\n// Default handlers\n// ---------------------------------------------------------------------------\n\n/**\n * Default {@link OnMessageHandler}. For `\"down-in\"` messages (from a dep),\n * routes to `NodeImpl._onDepMessage`. For `\"up-in\"` messages (from a sink),\n * the up-path is wired directly via `Node.up()` and never passes through\n * onMessage — this hook is reserved for future P5 symmetry.\n */\nconst defaultOnMessage: OnMessageHandler = (\n\tnode: NodeCtx,\n\tmsg: Message,\n\tctx: MessageContext,\n\t_actions: NodeActions,\n): \"consume\" | undefined => {\n\tif (ctx.direction === \"down-in\") {\n\t\t(node as NodeImpl)._onDepMessage(ctx.depIndex, msg);\n\t}\n\t// up-in is currently unused; default is to do nothing.\n\treturn undefined;\n};\n\n/**\n * Default {@link OnSubscribeHandler}. Delivers the subscribe handshake —\n * `[[START]]` for a sentinel cache, or `[[START], [DATA, cached]]` when a\n * value exists. Terminal nodes skip entirely so absence of START tells the\n * sink the stream is over (spec §2.2). Delivered through `downWithBatch` so\n * `subscribe()` inside `batch()` still defers the paired DATA correctly.\n */\nconst defaultOnSubscribe: OnSubscribeHandler = (\n\tnode: NodeCtx,\n\tsink: NodeSink,\n\t_ctx: SubscribeContext,\n\t_actions: NodeActions,\n): (() => void) | undefined => {\n\tconst impl = node as NodeImpl;\n\tif (impl._status === \"completed\" || impl._status === \"errored\") return;\n\tconst cached = impl._cached;\n\tconst initial: Message[] =\n\t\tcached === undefined ? [START_MSG] : [START_MSG, [DATA, cached] as Message];\n\t// When the node is mid-wave (`\"dirty\"`), append a DIRTY so the late\n\t// joiner participates in the in-flight wave. Without this, the next\n\t// DATA/RESOLVED the sink receives lacks the preceding DIRTY required\n\t// by spec §1.3.1 — the emit-side DIRTY auto-prefix is suppressed when\n\t// `_status` is already `\"dirty\"`.\n\tif (impl._status === \"dirty\") initial.push(DIRTY_MSG);\n\tdownWithBatch(sink, initial, impl._config.tierOf);\n};\n\n// ---------------------------------------------------------------------------\n// defaultConfig + configure\n// ---------------------------------------------------------------------------\n\n/**\n * Default {@link GraphReFlyConfig} instance. Every `NodeImpl` constructed\n * without an explicit `opts.config` binds to this instance and freezes it\n * on first hook access.\n */\nexport const defaultConfig = new GraphReFlyConfig({\n\tonMessage: defaultOnMessage,\n\tonSubscribe: defaultOnSubscribe,\n});\nregisterBuiltins(defaultConfig);\nregisterBuiltinCodecs(defaultConfig);\n\n/**\n * Apply configuration to {@link defaultConfig}. Must be called before the\n * first node is created — otherwise throws. Custom message types, hook\n * overrides, etc. go through here at app startup.\n *\n * ```ts\n * configure((cfg) => {\n * cfg.registerMessageType(MY_TYPE, { tier: 3 });\n * cfg.onMessage = (node, msg, ctx, actions) => { ... };\n * });\n * ```\n */\nexport function configure(fn: (cfg: GraphReFlyConfig) => void): void {\n\tif (defaultConfig._isFrozen()) {\n\t\tthrow new Error(\n\t\t\t\"configure() called after a node was created — the default \" +\n\t\t\t\t\"GraphReFlyConfig is frozen. Call configure(...) at application \" +\n\t\t\t\t\"startup, before any node factories run.\",\n\t\t);\n\t}\n\tfn(defaultConfig);\n}\n\n// Re-export the class for advanced callers that want an isolated instance.\nexport { GraphReFlyConfig };\n\n// ---------------------------------------------------------------------------\n// NodeImpl\n// ---------------------------------------------------------------------------\n\n/**\n * Single-class node implementation. Covers state, producer, derived, effect,\n * and passthrough shapes. See `sugar.ts` for ergonomic factories and\n * `dynamicNode()` (sugar-level wrapper around plain `NodeImpl`).\n */\nexport class NodeImpl<T = unknown> implements Node<T> {\n\t// --- Identity ---\n\treadonly _optsName: string | undefined;\n\treadonly _describeKind: NodeDescribeKind | undefined;\n\treadonly meta: Record<string, Node>;\n\t/**\n\t * Cached `Object.keys(meta).length > 0` check. `meta` is frozen at\n\t * construction so this boolean never flips. Used by `_emit` to skip\n\t * the meta TEARDOWN fan-out block allocation on the common \"no meta\"\n\t * hot path.\n\t */\n\treadonly _hasMeta: boolean;\n\n\t// --- Config ---\n\treadonly _config: GraphReFlyConfig;\n\n\t// --- Topology ---\n\t/** Mutable for autoTrackNode / Graph.connect() post-construction dep addition. */\n\t_deps: DepRecord[];\n\t_sinks: NodeSink | Set<NodeSink> | null = null;\n\t_sinkCount = 0;\n\n\t// --- State ---\n\t_cached: T | undefined;\n\t_status: NodeStatus;\n\t_cleanup: NodeFnCleanup | undefined;\n\t_store: Record<string, unknown> = {};\n\t_waveHasNewData = false;\n\t_hasNewTerminal = false;\n\t_hasCalledFnOnce = false;\n\t_paused = false;\n\t_pendingWave = false;\n\t_isExecutingFn = false;\n\t_pendingRerun = false;\n\t_rerunDepth = 0;\n\n\t// --- Settlement counter (A3) ---\n\t/**\n\t * Count of deps currently in `dirty === true`. `_maybeRunFnOnSettlement`\n\t * treats `0` as \"wave settled\" — O(1) check for full dep settlement.\n\t */\n\t_dirtyDepCount = 0;\n\n\t// --- Per-batch emit accumulator (Bug 2: K+1 fan-in fix) ---\n\t/**\n\t * Inside an explicit `batch(() => ...)` scope, every `_emit` accumulates\n\t * its already-framed messages here instead of dispatching synchronously.\n\t * At batch end, `_flushBatchPending` runs (registered via\n\t * `registerBatchFlushHook`) and delivers the whole accumulated batch as\n\t * one `downWithBatch` call — collapsing what would otherwise be K\n\t * separate sink invocations into one. This is the fix for the diamond\n\t * fan-in K+1 over-fire.\n\t *\n\t * `null` outside batch (or after flush). Only ever appended to within\n\t * a single explicit batch lifetime; reset to `null` on flush. State\n\t * updates (cache, version, status) still happen per-emit via\n\t * `_updateState` — only the downstream delivery is coalesced.\n\t */\n\t_batchPendingMessages: Message[] | null = null;\n\n\t// --- PAUSE/RESUME lock tracking (C0) ---\n\t/**\n\t * Set of active pause locks held against this node. Every `[PAUSE, lockId]`\n\t * adds its `lockId` to the set; every `[RESUME, lockId]` removes it.\n\t * `_paused` is a derived quantity: `_pauseLocks.size > 0`. Multi-pauser\n\t * correctness — one controller releasing its lock does NOT resume the\n\t * node while another controller still holds its lock.\n\t */\n\t_pauseLocks: Set<unknown> | null = null;\n\t/**\n\t * Buffered DATA messages held while paused. Only populated when\n\t * `_pausable === \"resumeAll\"` (bufferAll mode). On final lock release\n\t * the buffer is replayed through the node's outgoing pipeline in the\n\t * order received. Non-bufferAll pause mode drops DATA on the floor\n\t * (upstream is expected to honor PAUSE by suppressing production).\n\t */\n\t_pauseBuffer: Message[] | null = null;\n\n\t// --- Options (frozen at construction) ---\n\treadonly _fn: NodeFn | undefined;\n\treadonly _equals: (a: T, b: T) => boolean;\n\treadonly _resubscribable: boolean;\n\treadonly _resetOnTeardown: boolean;\n\treadonly _autoComplete: boolean;\n\treadonly _autoError: boolean;\n\treadonly _pausable: boolean | \"resumeAll\";\n\treadonly _guard: NodeGuard | undefined;\n\t/**\n\t * @internal Additional guards stacked at runtime via {@link NodeImpl._pushGuard}\n\t * (e.g. by `policyEnforcer({ mode: \"enforce\" })`, roadmap §9.2). Effective\n\t * write/signal/observe checks AND the original `_guard` with every entry here.\n\t */\n\t_extraGuards: Set<NodeGuard> | undefined;\n\t_hashFn: HashFn;\n\t_versioning: NodeVersionInfo | undefined;\n\t/**\n\t * Explicit versioning level, tracked separately from `_versioning` so\n\t * monotonicity checks and future v2/v3 extensions don't rely on the\n\t * fragile `\"cid\" in _versioning` shape discriminator. `undefined` means\n\t * the node has no versioning attached; `0` / `1` / future levels name\n\t * the tier. Mutated in lockstep with `_versioning` by the constructor\n\t * and by `_applyVersioning`.\n\t */\n\t_versioningLevel: VersioningLevel | undefined;\n\n\t// --- ABAC ---\n\t_lastMutation: { actor: Actor; timestamp_ns: number } | undefined;\n\n\t/**\n\t * @internal Per-node inspector hooks for `Graph.observe(path,\n\t * { causal, derived })`. Fires in `_onDepMessage` and `_execFn`.\n\t * Attached via `_setInspectorHook` (returns a disposer). Multiple\n\t * observers can attach simultaneously — all registered hooks fire for\n\t * every event.\n\t */\n\t_inspectorHooks: Set<NodeInspectorHook> | undefined;\n\n\t// --- Actions (built once in the constructor) ---\n\treadonly _actions: NodeActions;\n\n\tconstructor(deps: readonly Node[], fn: NodeFn | undefined, opts: NodeOptions<T>) {\n\t\t// Bind to config FIRST so meta nodes inherit it. Touching a hook\n\t\t// getter below freezes the config on first node creation.\n\t\tthis._config = opts.config ?? defaultConfig;\n\t\tvoid this._config.onMessage;\n\n\t\tthis._optsName = opts.name;\n\t\tthis._describeKind = opts.describeKind;\n\t\tthis._equals = (opts.equals ?? (Object.is as (a: T, b: T) => boolean)) as (\n\t\t\ta: T,\n\t\t\tb: T,\n\t\t) => boolean;\n\t\tthis._resubscribable = opts.resubscribable ?? false;\n\t\tthis._resetOnTeardown = opts.resetOnTeardown ?? false;\n\t\tthis._autoComplete = opts.completeWhenDepsComplete ?? true;\n\t\tthis._autoError = opts.errorWhenDepsError ?? true;\n\t\tthis._pausable = opts.pausable ?? true;\n\t\tthis._guard = opts.guard;\n\t\tthis._fn = fn;\n\n\t\t// `undefined` is the sentinel (\"no cached value\") so `initial: undefined`\n\t\t// is treated as absent. `null` is a valid DATA value and sets the cache.\n\t\tthis._cached = opts.initial !== undefined ? (opts.initial as T) : undefined;\n\t\t// State-with-initial starts \"settled\"; everything else starts \"sentinel\".\n\t\tthis._status =\n\t\t\tdeps.length === 0 && fn == null && this._cached !== undefined ? \"settled\" : \"sentinel\";\n\n\t\t// Versioning\n\t\t// Hash resolution: per-node `opts.versioningHash` wins; then the\n\t\t// bound config's `defaultHashFn`; then the vendored sync SHA-256.\n\t\t// Hot-path workloads that want a faster hash (xxHash, FNV-1a) can\n\t\t// set it once at app init via `configure(cfg => { cfg.defaultHashFn = ... })`.\n\t\tthis._hashFn = opts.versioningHash ?? this._config.defaultHashFn ?? defaultHash;\n\t\t// Versioning level resolution: per-node `opts.versioning` wins; if\n\t\t// absent, fall back to the bound config's `defaultVersioning`. `null`\n\t\t// stays unversioned. Explicit levels (0, 1, …) attach the versioning\n\t\t// info at construction so the next DATA emit advances it.\n\t\tconst versioningLevel: VersioningLevel | undefined =\n\t\t\topts.versioning ?? this._config.defaultVersioning;\n\t\tthis._versioningLevel = versioningLevel;\n\t\tthis._versioning =\n\t\t\tversioningLevel != null\n\t\t\t\t? createVersioning(versioningLevel, this._cached === undefined ? undefined : this._cached, {\n\t\t\t\t\t\tid: opts.versioningId,\n\t\t\t\t\t\thash: this._hashFn,\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\n\t\t// Per-dep records: one DepRecord per declared dep.\n\t\tthis._deps = deps.map(createDepRecord);\n\n\t\t// Meta companions (simple state children; inherit config + guard).\n\t\tconst meta: Record<string, Node> = {};\n\t\tfor (const [k, v] of Object.entries(opts.meta ?? {})) {\n\t\t\tconst metaOpts: NodeOptions<unknown> = {\n\t\t\t\tinitial: v,\n\t\t\t\tname: `${opts.name ?? \"node\"}:meta:${k}`,\n\t\t\t\tdescribeKind: \"state\",\n\t\t\t\tconfig: this._config,\n\t\t\t};\n\t\t\tif (opts.guard != null) metaOpts.guard = opts.guard;\n\t\t\tmeta[k] = new NodeImpl<unknown>([], undefined, metaOpts);\n\t\t}\n\t\tObject.freeze(meta);\n\t\tthis.meta = meta;\n\t\tthis._hasMeta = Object.keys(meta).length > 0;\n\n\t\t// Actions: built once, closure over `this`. Every call goes through\n\t\t// `_emit` which owns the full dispatch invariant — tier sort,\n\t\t// synthetic DIRTY prefix, equals substitution, and phase dispatch.\n\t\t// One call = one wave. Multiple calls produce multiple waves.\n\t\t// No accumulation, no user-facing bundle builder.\n\t\tconst self = this;\n\t\tthis._actions = {\n\t\t\temit(value: unknown): void {\n\t\t\t\tself._emit([[DATA, value] as Message]);\n\t\t\t},\n\t\t\tdown(messageOrMessages: Message | Messages): void {\n\t\t\t\tself._emit(normalizeMessages(messageOrMessages));\n\t\t\t},\n\t\t\tup(messageOrMessages: Message | Messages): void {\n\t\t\t\tself._emitUp(normalizeMessages(messageOrMessages));\n\t\t\t},\n\t\t};\n\n\t\t// Bind commonly detached protocol methods.\n\t\tthis.down = this.down.bind(this);\n\t\tthis.up = this.up.bind(this);\n\t}\n\n\t// --- Derived state ---\n\n\tprivate get _isTerminal(): boolean {\n\t\treturn this._status === \"completed\" || this._status === \"errored\";\n\t}\n\n\t// --- Public getters ---\n\n\tget name(): string | undefined {\n\t\treturn this._optsName;\n\t}\n\n\tget status(): NodeStatus {\n\t\treturn this._status;\n\t}\n\n\tget cache(): T | undefined | null {\n\t\treturn this._cached === undefined ? undefined : (this._cached as T);\n\t}\n\n\tget lastMutation(): Readonly<{ actor: Actor; timestamp_ns: number }> | undefined {\n\t\treturn this._lastMutation;\n\t}\n\n\tget v(): Readonly<NodeVersionInfo> | undefined {\n\t\treturn this._versioning;\n\t}\n\n\thasGuard(): boolean {\n\t\treturn this._guard != null;\n\t}\n\n\t/**\n\t * @internal Retroactively attach (or upgrade) versioning state on this\n\t * node. Intended for `Graph.setVersioning(level)` bulk application and\n\t * for rare cases where a specific node needs to be bumped to a higher\n\t * level (e.g., `v0 → v1`) after construction.\n\t *\n\t * **Safety:** the mutation is rejected mid-wave. Specifically,\n\t * throws if the node is currently executing its fn (`_isExecutingFn`).\n\t * Callers at quiescent points — before the first sink subscribes, or\n\t * after all sinks unsubscribe, or between external `down()` / `emit()`\n\t * invocations — are safe. The re-entrance window that motivated §10.6.4\n\t * removal was the \"transition `_versioning` from `undefined` to a fresh\n\t * object mid-`_updateState`\" case; that path is now guarded.\n\t *\n\t * **Monotonicity:** levels can only go up. Downgrade (e.g., `v1 → v0`)\n\t * is a no-op — once a node carries higher-level metadata, dropping it\n\t * mid-graph would tear the linked-history invariant for v1 and above.\n\t *\n\t * **Linked-history boundary (D1, 2026-04-13):** upgrading v0 → v1\n\t * produces a **fresh history root**. The new v1 state has `cid =\n\t * hash(currentCachedValue)` and `prev = null`, not a synthetic `prev`\n\t * anchored to any previous v0 value. The v0 monotonic `version` counter\n\t * is preserved across the upgrade, but the linked-cid chain (spec §7)\n\t * starts fresh at the upgrade point. Downstream audit tools that walk\n\t * `v.cid.prev` backwards through time will see a `null` boundary at\n\t * the upgrade — **this is intentional**: v0 had no cid to link to, and\n\t * fabricating one would lie about the hash. Callers that require an\n\t * unbroken cid chain from birth must attach versioning at construction\n\t * via `opts.versioning` or `config.defaultVersioning`, not retroactively.\n\t *\n\t * @param level - New minimum versioning level.\n\t * @param opts - Optional id / hash overrides; applied only if the\n\t * node currently has no versioning state.\n\t */\n\t_applyVersioning(level: VersioningLevel, opts?: { id?: string; hash?: HashFn }): void {\n\t\tif (this._isExecutingFn) {\n\t\t\tthrow new Error(\n\t\t\t\t`Node \"${this.name}\": _applyVersioning cannot run mid-fn — ` +\n\t\t\t\t\t\"call it outside of `_execFn` (typically at graph setup time \" +\n\t\t\t\t\t\"before the first subscribe).\",\n\t\t\t);\n\t\t}\n\t\tconst currentLevel = this._versioningLevel;\n\t\tif (currentLevel != null && level <= currentLevel) {\n\t\t\t// Downgrade or no-op. Monotonic: higher levels only.\n\t\t\treturn;\n\t\t}\n\t\tconst hash = opts?.hash ?? this._hashFn;\n\t\tif (hash !== this._hashFn) this._hashFn = hash;\n\t\tconst initialValue = this._cached === undefined ? undefined : this._cached;\n\t\t// Preserve the existing id + version counter across upgrades so\n\t\t// downstream consumers watching `v.id` don't see an identity jump.\n\t\tconst current = this._versioning;\n\t\tconst preservedId = current?.id ?? opts?.id;\n\t\tconst preservedVersion = current?.version ?? 0;\n\t\tconst fresh = createVersioning(level, initialValue, {\n\t\t\tid: preservedId,\n\t\t\thash,\n\t\t});\n\t\tfresh.version = preservedVersion;\n\t\tthis._versioning = fresh;\n\t\tthis._versioningLevel = level;\n\t}\n\n\t/**\n\t * @internal Attach an inspector hook. Returns a disposer that removes\n\t * the hook. Used by `Graph.observe(path, { causal, derived })` to build\n\t * causal traces. Multiple hooks may be attached concurrently — all fire\n\t * for every event in registration order. Passing `undefined` is a no-op\n\t * and returns a no-op disposer.\n\t */\n\t_setInspectorHook(hook?: NodeInspectorHook): () => void {\n\t\tif (hook == null) return () => {};\n\t\tif (this._inspectorHooks == null) this._inspectorHooks = new Set();\n\t\tthis._inspectorHooks.add(hook);\n\t\treturn () => {\n\t\t\tthis._inspectorHooks?.delete(hook);\n\t\t\tif (this._inspectorHooks?.size === 0) this._inspectorHooks = undefined;\n\t\t};\n\t}\n\n\t/**\n\t * @internal Push an additional guard onto this node. Effective enforcement\n\t * is the AND of `_guard` and every guard pushed via this hook — any one\n\t * rejecting throws {@link GuardDenied}. Returns a disposer that removes\n\t * the pushed guard. Multiple guards may be stacked simultaneously.\n\t *\n\t * Used by `policyEnforcer({ mode: \"enforce\" })` (roadmap §9.2) to overlay\n\t * runtime constraint enforcement onto an existing graph without rebuilding\n\t * its nodes. Pre-1.0 internal API; not part of the public surface.\n\t *\n\t * **Identity semantics:** guards are tracked in a `Set`, so pushing the\n\t * same `NodeGuard` reference twice is a single registration. Wrap each\n\t * push in a unique closure if independent stacking is needed.\n\t *\n\t * **Iteration order:** insertion-ordered (`Set` semantics). Determinism\n\t * follows from single-threaded JS execution; nested re-entry from inside\n\t * a guard body (push/pop while iterating) is undefined-but-survivable.\n\t */\n\t_pushGuard(guard: NodeGuard): () => void {\n\t\tif (this._extraGuards == null) this._extraGuards = new Set();\n\t\tthis._extraGuards.add(guard);\n\t\treturn () => {\n\t\t\tthis._extraGuards?.delete(guard);\n\t\t\tif (this._extraGuards?.size === 0) this._extraGuards = undefined;\n\t\t};\n\t}\n\n\tallowsObserve(actor: Actor): boolean {\n\t\tif (this._guard == null && this._extraGuards == null) return true;\n\t\tconst a = normalizeActor(actor);\n\t\tif (this._guard != null && !this._guard(a, \"observe\")) return false;\n\t\tif (this._extraGuards != null) {\n\t\t\tfor (const eg of this._extraGuards) {\n\t\t\t\tif (!eg(a, \"observe\")) return false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t// --- Guard helper ---\n\n\tprivate _checkGuard(options?: NodeTransportOptions): void {\n\t\tif (options?.internal) return;\n\t\tconst hasGuard = this._guard != null || this._extraGuards != null;\n\t\tconst hasActor = options?.actor != null;\n\t\t// Skip work entirely when there's nothing to check or attribute.\n\t\tif (!hasGuard && !hasActor) return;\n\t\tconst actor = normalizeActor(options?.actor);\n\t\tconst action: GuardAction = options?.delivery === \"signal\" ? \"signal\" : \"write\";\n\t\tif (this._guard != null && !this._guard(actor, action)) {\n\t\t\tthrow new GuardDenied({ actor, action, nodeName: this.name });\n\t\t}\n\t\tif (this._extraGuards != null) {\n\t\t\tfor (const eg of this._extraGuards) {\n\t\t\t\tif (!eg(actor, action)) {\n\t\t\t\t\tthrow new GuardDenied({ actor, action, nodeName: this.name });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Populate `_lastMutation` whenever guards ran OR an explicit actor was\n\t\t// passed — `auditTrail` (roadmap §9.2) relies on this for attribution\n\t\t// on graphs without ABAC. Internal writes (no actor, no guard) skip\n\t\t// attribution to avoid recording derived recompute storms.\n\t\tthis._lastMutation = { actor, timestamp_ns: wallClockNs() };\n\t}\n\n\t// --- Public transport ---\n\n\tdown(messageOrMessages: Message | Messages, options?: NodeTransportOptions): void {\n\t\tconst messages = normalizeMessages(messageOrMessages);\n\t\tif (messages.length === 0) return;\n\t\tthis._checkGuard(options);\n\t\tthis._emit(messages);\n\t}\n\n\temit(value: T | undefined | null, options?: NodeTransportOptions): void {\n\t\tthis._checkGuard(options);\n\t\tthis._emit([[DATA, value] as Message]);\n\t}\n\n\tup(messageOrMessages: Message | Messages, options?: NodeTransportOptions): void {\n\t\tif (this._deps.length === 0) return;\n\t\tconst messages = normalizeMessages(messageOrMessages);\n\t\tif (messages.length === 0) return;\n\t\tthis._checkGuard(options);\n\t\tconst forwardOpts: NodeTransportOptions = options ?? { internal: true };\n\t\t// Validate tier constraint before fanning out (B1.4 option a).\n\t\tthis._validateUpTiers(messages);\n\t\tfor (const d of this._deps) {\n\t\t\td.node.up?.(messages, forwardOpts);\n\t\t}\n\t}\n\n\t/**\n\t * @internal Internal up-path used by `actions.up(...)` from inside fn.\n\t * Same tier validation as public `up`, but bypasses the guard check\n\t * since the fn context is already inside an authorized operation.\n\t */\n\tprivate _emitUp(messages: Messages): void {\n\t\tif (this._deps.length === 0) return;\n\t\tif (messages.length === 0) return;\n\t\tthis._validateUpTiers(messages);\n\t\tfor (const d of this._deps) {\n\t\t\td.node.up?.(messages, { internal: true });\n\t\t}\n\t}\n\n\t/**\n\t * @internal Enforce spec §1.2 — up-direction messages are restricted to\n\t * tier 0–2 and tier 5 (START, DIRTY, INVALIDATE, PAUSE, RESUME,\n\t * TEARDOWN). Tier 3 (DATA/RESOLVED) and tier 4 (COMPLETE/ERROR) are\n\t * downstream-only. Emitting tier-3/4 via `up` would bypass equals\n\t * substitution and cache advance entirely and is a protocol bug.\n\t */\n\tprivate _validateUpTiers(messages: Messages): void {\n\t\tconst tierOf = this._config.tierOf;\n\t\tfor (const m of messages) {\n\t\t\tconst tier = tierOf(m[0]);\n\t\t\tif (tier === 3 || tier === 4) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Node \"${this.name}\": tier-${tier} messages cannot flow up — ` +\n\t\t\t\t\t\t\"DATA/RESOLVED/COMPLETE/ERROR are downstream-only. Use \" +\n\t\t\t\t\t\t\"`down(...)` for value delivery; `up(...)` is for control \" +\n\t\t\t\t\t\t\"signals (DIRTY, INVALIDATE, PAUSE, RESUME, TEARDOWN).\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tsubscribe(sink: NodeSink, actor?: Actor): () => void {\n\t\tif (actor != null && this._guard != null) {\n\t\t\tconst a = normalizeActor(actor);\n\t\t\tif (!this._guard(a, \"observe\")) {\n\t\t\t\tthrow new GuardDenied({ actor: a, action: \"observe\", nodeName: this.name });\n\t\t\t}\n\t\t}\n\n\t\t// Resubscribable terminal reset.\n\t\tconst wasTerminal = this._isTerminal;\n\t\tconst afterTerminalReset = wasTerminal && this._resubscribable;\n\t\tif (afterTerminalReset) {\n\t\t\tthis._cached = undefined;\n\t\t\tthis._status = \"sentinel\";\n\t\t\tthis._store = {};\n\t\t\tthis._hasCalledFnOnce = false;\n\t\t\tthis._waveHasNewData = false;\n\t\t\tthis._hasNewTerminal = false;\n\t\t\tthis._paused = false;\n\t\t\tthis._pendingWave = false;\n\t\t\tthis._pendingRerun = false;\n\t\t\tthis._isExecutingFn = false;\n\t\t\tthis._rerunDepth = 0;\n\t\t\tthis._dirtyDepCount = 0;\n\t\t\t// C0: clear pause state so a new subscriber after terminal-reset\n\t\t\t// starts from a clean pause lockset — otherwise a lockId from\n\t\t\t// the previous lifecycle would leave the node stuck paused and\n\t\t\t// swallow every emit.\n\t\t\tthis._pauseLocks = null;\n\t\t\tthis._pauseBuffer = null;\n\t\t\tfor (const d of this._deps) resetDepRecord(d);\n\t\t}\n\n\t\tthis._sinkCount += 1;\n\n\t\t// Subscribe ceremony via singleton.\n\t\t// Rollback on throw: undo the sinkCount bump — sink is not yet registered,\n\t\t// no _activate() has run, nothing else to clean up.\n\t\tlet subCleanup: (() => void) | undefined;\n\t\ttry {\n\t\t\tsubCleanup = this._config.onSubscribe(\n\t\t\t\tthis as unknown as NodeCtx,\n\t\t\t\tsink,\n\t\t\t\t{ sinkCount: this._sinkCount, afterTerminalReset },\n\t\t\t\tthis._actions,\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthis._sinkCount -= 1;\n\t\t\tthrow err;\n\t\t}\n\n\t\t// Register sink AFTER START delivery (spec §2.2).\n\t\tif (this._sinks == null) {\n\t\t\tthis._sinks = sink;\n\t\t} else if (typeof this._sinks === \"function\") {\n\t\t\tthis._sinks = new Set<NodeSink>([this._sinks, sink]);\n\t\t} else {\n\t\t\tthis._sinks.add(sink);\n\t\t}\n\n\t\t// First-subscriber activation.\n\t\t// Rollback on throw: undo sink registration, sinkCount bump, and subCleanup.\n\t\t// _activate() rolls back its own partial dep subscriptions before re-throwing.\n\t\tconst isTerminalNow = this._isTerminal;\n\t\tif (this._sinkCount === 1 && !isTerminalNow) {\n\t\t\ttry {\n\t\t\t\tthis._activate();\n\t\t\t} catch (err) {\n\t\t\t\tthis._sinkCount -= 1;\n\t\t\t\tthis._removeSink(sink);\n\t\t\t\t// Restore status: onSubscribe emitted START which set _status to\n\t\t\t\t// \"pending\". With zero sinks the node is back to its pre-subscribe\n\t\t\t\t// state; reset so node.status reflects no active subscription.\n\t\t\t\tif (this._sinkCount === 0) this._status = \"sentinel\";\n\t\t\t\tif (typeof subCleanup === \"function\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsubCleanup();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* best-effort: subCleanup errors are secondary */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\n\t\t// Reflect \"activated but no value yet\" as pending.\n\t\tif (this._status === \"sentinel\" && this._cached === undefined) {\n\t\t\tthis._status = \"pending\";\n\t\t}\n\n\t\tlet removed = false;\n\t\treturn (): void => {\n\t\t\tif (removed) return;\n\t\t\tremoved = true;\n\t\t\tthis._sinkCount -= 1;\n\t\t\tthis._removeSink(sink);\n\t\t\tif (typeof subCleanup === \"function\") subCleanup();\n\t\t\tif (this._sinks == null) this._deactivate();\n\t\t};\n\t}\n\n\tprivate _removeSink(sink: NodeSink): void {\n\t\tif (this._sinks === sink) {\n\t\t\tthis._sinks = null;\n\t\t} else if (this._sinks != null && typeof this._sinks !== \"function\") {\n\t\t\tthis._sinks.delete(sink);\n\t\t\tif (this._sinks.size === 1) {\n\t\t\t\tconst [only] = this._sinks;\n\t\t\t\tthis._sinks = only;\n\t\t\t} else if (this._sinks.size === 0) {\n\t\t\t\tthis._sinks = null;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Lifecycle ---\n\n\t/**\n\t * @internal First-sink activation. For a producer (no deps + fn),\n\t * invokes fn once. For a compute node (has deps), subscribes to every\n\t * dep with the pre-set-dirty trick so the first-run gate waits for\n\t * every dep to settle at least once.\n\t */\n\t_activate(): void {\n\t\tif (this._deps.length === 0) {\n\t\t\tif (this._fn) this._execFn();\n\t\t\treturn;\n\t\t}\n\t\t// Pre-set every dep as sentinel BEFORE subscribing. If the first dep\n\t\t// delivers DATA synchronously during its subscribe callback, the\n\t\t// sentinel gate holds fn until all deps have contributed at least one\n\t\t// value. _dirtyDepCount starts at 0 — actual DIRTY messages from deps\n\t\t// drive it; pre-dirtying all deps would cause any dep that only delivers\n\t\t// [[START]] (no DATA) to appear permanently \"mid-wave\", which blocks\n\t\t// terminal propagation from other deps incorrectly.\n\t\tthis._dirtyDepCount = 0;\n\t\t// Capture the initial length BEFORE subscribing. `_addDep` can fire\n\t\t// synchronously during a dep's subscribe callback (e.g., via\n\t\t// `autoTrackNode` discovery in `_execFn`) and push new DepRecords.\n\t\t// Iterating `this._deps.length` live would mean this loop also\n\t\t// subscribes the new dep that `_addDep` already subscribed — a\n\t\t// double-subscribe bug. Snapshot the length instead; `_addDep`\n\t\t// owns the subscribe + counter bump for any dep it adds.\n\t\tconst initialLen = this._deps.length;\n\t\t// subscribedCount tracks how many deps were successfully subscribed.\n\t\t// On failure, only those deps need to be rolled back.\n\t\tlet subscribedCount = 0;\n\t\ttry {\n\t\t\tfor (let i = 0; i < initialLen; i++) {\n\t\t\t\tconst depIdx = i;\n\t\t\t\tconst dep = this._deps[i];\n\t\t\t\t// Pre-set to noopUnsub so the liveness check inside the callback\n\t\t\t\t// passes during synchronous push-on-subscribe (dep.unsub is non-null),\n\t\t\t\t// while still blocking stale drainPhase2 closures that fire after\n\t\t\t\t// _deactivate sets dep.unsub = null.\n\t\t\t\tdep.unsub = noopUnsub;\n\t\t\t\tdep.unsub = dep.node.subscribe((msgs) => {\n\t\t\t\t\t// Liveness check: dep.unsub === null means this subscription was\n\t\t\t\t\t// cancelled by _deactivate. Drop deliveries from stale drainPhase2\n\t\t\t\t\t// closures that outlived the subscription.\n\t\t\t\t\tif (dep.unsub === null) return;\n\t\t\t\t\t// Track whether any tier-3+ settlement-class message arrived\n\t\t\t\t\t// (DATA/RESOLVED at tier 3, COMPLETE/ERROR at tier 4). Fire\n\t\t\t\t\t// `_maybeRunFnOnSettlement` once at the end of the iteration\n\t\t\t\t\t// loop when at least one settlement was seen — one invocation\n\t\t\t\t\t// per dep batch, not per message, so `fn` sees the full wave\n\t\t\t\t\t// (Bug 1 fix, 2026-04-17). Guarded by `config.tierOf(m[0])\n\t\t\t\t\t// >= 3` per spec §5.11 — never hardcode message-type checks.\n\t\t\t\t\tconst tierOf = this._config.tierOf;\n\t\t\t\t\tlet sawSettlement = false;\n\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\tif (tierOf(m[0]) >= 3) sawSettlement = true;\n\t\t\t\t\t\tthis._config.onMessage(\n\t\t\t\t\t\t\tthis as unknown as NodeCtx,\n\t\t\t\t\t\t\tm,\n\t\t\t\t\t\t\t{ direction: \"down-in\", depIndex: depIdx },\n\t\t\t\t\t\t\tthis._actions,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (sawSettlement) this._maybeRunFnOnSettlement();\n\t\t\t\t});\n\t\t\t\tsubscribedCount++;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\t// Dep at index `subscribedCount` failed — its dep.unsub is still noopUnsub.\n\t\t\t// Mark it null so the liveness check treats any queued closures as stale.\n\t\t\tthis._deps[subscribedCount].unsub = null;\n\t\t\t// Unsubscribe all deps that DID subscribe successfully (0..subscribedCount-1).\n\t\t\tfor (let j = 0; j < subscribedCount; j++) {\n\t\t\t\tconst d = this._deps[j];\n\t\t\t\tif (d.unsub != null) {\n\t\t\t\t\tconst u = d.unsub;\n\t\t\t\t\td.unsub = null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tu();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* best-effort: dep unsub errors are secondary */\n\t\t\t\t\t}\n\t\t\t\t\tresetDepRecord(d);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._dirtyDepCount = 0;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t/**\n\t * @internal Append a dep post-construction. Used by `autoTrackNode`\n\t * (runtime dep discovery) and `Graph.connect()` (post-construction\n\t * wiring). Subscribes immediately — if DATA arrives synchronously\n\t * during subscribe and fn is currently executing, the re-run is\n\t * deferred via `_pendingRerun` flag (see `_execFn` guard).\n\t *\n\t * **Dedup:** idempotent on duplicate `depNode` — if `depNode` is\n\t * already in `_deps`, returns the existing index without mutating\n\t * state. Callers can safely invoke `_addDep` without their own\n\t * \"already added\" check. `autoTrackNode` still keeps a `depIndexMap`\n\t * as a fast-path lookup for known deps (returning cached `data[idx]`\n\t * without calling `_addDep` at all); this internal dedup is the\n\t * backstop for any caller that doesn't track its own dep set.\n\t *\n\t * @returns The index of the new dep in `_deps`, or the existing index\n\t * if the dep was already present.\n\t */\n\t_addDep(depNode: Node): number {\n\t\t// Dedup: idempotent on repeated adds of the same dep. Matches\n\t\t// reference equality — the DepRecord is keyed by `node` identity,\n\t\t// so a caller with a fresh `depNode` that observes as equal but\n\t\t// is a distinct object is treated as a new dep.\n\t\tfor (let i = 0; i < this._deps.length; i++) {\n\t\t\tif (this._deps[i].node === depNode) return i;\n\t\t}\n\t\tconst depIdx = this._deps.length;\n\t\tconst record = createDepRecord(depNode);\n\t\tthis._deps.push(record);\n\n\t\t// If the node is inactive (no subscribers yet), defer subscribe to\n\t\t// _activate(). Subscribing here would create a duplicate subscription\n\t\t// because _activate() unconditionally subscribes to all _deps entries.\n\t\t// _activate() resets _dirtyDepCount to 0 before subscribing, so pre-\n\t\t// dirtying is wasted work and causes counter underflow on the first DATA.\n\t\tif (this._sinks == null) return depIdx;\n\n\t\trecord.dirty = true;\n\t\t// New dep starts dirty — bump the A3 counter to match the pre-set flag.\n\t\t// Skipping the helper here because the record isn't in the array yet when\n\t\t// the helper would early-return on `dep.dirty === true`.\n\t\tthis._dirtyDepCount++;\n\t\t// Topology change → downstream sees a new wave. Skip when already\n\t\t// dirty (we're inside an in-flight wave and have already emitted).\n\t\t// `_depDirtied` can't do this for us because `record.dirty` was\n\t\t// pre-set above, which short-circuits its DIRTY-emit path.\n\t\tif (this._status !== \"dirty\") this._emit(DIRTY_ONLY_BATCH);\n\t\trecord.unsub = noopUnsub;\n\t\ttry {\n\t\t\trecord.unsub = depNode.subscribe((msgs) => {\n\t\t\t\tif (record.unsub === null) return;\n\t\t\t\t// Tier-3+ classification via central `tierOf` per spec §5.11\n\t\t\t\t// (Bug 1 fix — see _activate for details).\n\t\t\t\tconst tierOf = this._config.tierOf;\n\t\t\t\tlet sawSettlement = false;\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (tierOf(m[0]) >= 3) sawSettlement = true;\n\t\t\t\t\tthis._config.onMessage(\n\t\t\t\t\t\tthis as unknown as NodeCtx,\n\t\t\t\t\t\tm,\n\t\t\t\t\t\t{ direction: \"down-in\", depIndex: depIdx },\n\t\t\t\t\t\tthis._actions,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (sawSettlement) this._maybeRunFnOnSettlement();\n\t\t\t});\n\t\t} catch (err) {\n\t\t\t// Rollback: remove the dep record we just pushed and undo the dirty\n\t\t\t// counter. record.unsub stays null (already cleared below) so any\n\t\t\t// drainPhase2 closures queued by subscribe before it threw are\n\t\t\t// treated as stale and dropped by the liveness check.\n\t\t\trecord.unsub = null;\n\t\t\tthis._deps.pop();\n\t\t\tthis._dirtyDepCount--;\n\t\t\t// Propagate: _execFn's catch block will emit ERROR, which settles\n\t\t\t// downstream nodes that received the DIRTY we emitted above.\n\t\t\tthrow err;\n\t\t}\n\t\treturn depIdx;\n\t}\n\n\t/**\n\t * @internal Unsubscribes from deps, fires fn cleanup (both shapes),\n\t * clears wave/store state, and (for compute nodes) drops `_cached` per\n\t * the ROM/RAM rule. Idempotent: second call is a no-op.\n\t *\n\t * @param skipStatusUpdate — When `true`, the caller takes responsibility\n\t * for setting `_status` after deactivation (e.g. TEARDOWN always sets\n\t * `\"sentinel\"` unconditionally). When `false` (default), deactivation\n\t * applies the ROM rule: compute nodes → `\"sentinel\"`, state nodes\n\t * preserve their current status.\n\t */\n\t_deactivate(skipStatusUpdate = false): void {\n\t\t// Fn cleanup — both () => void and { deactivation } forms fire here.\n\t\t// Note on cleanup-throw ERRORs: when deactivation runs as part of\n\t\t// last-sink-unsubscribe, `_sinks` is already `null` by the time this\n\t\t// method is reached, so any ERROR emitted here lands on\n\t\t// `_deliverToSinks`'s null-guard and is dropped by design. Cleanup\n\t\t// errors during teardown are best-effort — callers that need to\n\t\t// observe them should install a host-level error channel via\n\t\t// `configure()`.\n\t\tconst cleanup = this._cleanup;\n\t\tthis._cleanup = undefined;\n\t\tif (typeof cleanup === \"function\") {\n\t\t\ttry {\n\t\t\t\tcleanup();\n\t\t\t} catch (err) {\n\t\t\t\tthis._emit([[ERROR, this._wrapFnError(\"cleanup threw\", err)]]);\n\t\t\t}\n\t\t} else if (\n\t\t\tcleanup != null &&\n\t\t\ttypeof (cleanup as { deactivation?: unknown }).deactivation === \"function\"\n\t\t) {\n\t\t\ttry {\n\t\t\t\t(cleanup as { deactivation: () => void }).deactivation();\n\t\t\t} catch (err) {\n\t\t\t\tthis._emit([[ERROR, this._wrapFnError(\"cleanup.deactivation threw\", err)]]);\n\t\t\t}\n\t\t}\n\n\t\t// Disconnect from deps.\n\t\tfor (const d of this._deps) {\n\t\t\tif (d.unsub != null) {\n\t\t\t\tconst u = d.unsub;\n\t\t\t\td.unsub = null;\n\t\t\t\ttry {\n\t\t\t\t\tu();\n\t\t\t\t} catch {\n\t\t\t\t\t/* best-effort teardown of upstream subscription */\n\t\t\t\t}\n\t\t\t}\n\t\t\tresetDepRecord(d);\n\t\t}\n\n\t\t// Clear wave + store state.\n\t\tthis._waveHasNewData = false;\n\t\tthis._hasNewTerminal = false;\n\t\tthis._hasCalledFnOnce = false;\n\t\tthis._paused = false;\n\t\tthis._pendingWave = false;\n\t\tthis._pendingRerun = false;\n\t\tthis._rerunDepth = 0;\n\t\tthis._store = {};\n\t\t// A3 counter reset with DepRecord bulk-reset.\n\t\tthis._dirtyDepCount = 0;\n\t\t// C0 pause state: TEARDOWN is a hard reset. Buffered tier-3/4\n\t\t// messages from a paused `resumeAll` node are DISCARDED rather than\n\t\t// drained, matching \"teardown wipes in-flight state\" semantics.\n\t\t// Clearing both structures also prevents a memory leak on\n\t\t// non-resubscribable teardown, and guarantees a resubscribable\n\t\t// re-activation starts from `_paused === false` with no stale\n\t\t// lockset carried over from the previous lifecycle.\n\t\tthis._pauseLocks = null;\n\t\tthis._pauseBuffer = null;\n\n\t\t// ROM/RAM: compute nodes clear cache; pure state nodes preserve it.\n\t\tif (this._fn != null) {\n\t\t\tthis._cached = undefined;\n\t\t}\n\n\t\tif (!skipStatusUpdate) {\n\t\t\t// Compute nodes → \"sentinel\" (cache cleared, no value).\n\t\t\t// - Non-terminal: always reset.\n\t\t\t// - Terminal + resubscribable: reset (resubscribable means\n\t\t\t// \"can be re-activated after terminal\" — the terminal state\n\t\t\t// doesn't persist across subscription cycles).\n\t\t\t// - Terminal + non-resubscribable: preserve (stream is over).\n\t\t\t// State nodes preserve status (ROM rule, value is intrinsic).\n\t\t\tif (this._fn != null || this._deps.length > 0) {\n\t\t\t\tif (!this._isTerminal || this._resubscribable) {\n\t\t\t\t\tthis._status = \"sentinel\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Dep message dispatch (§3.5 singleton default) ---\n\n\t/**\n\t * @internal Default per-tier dispatch for incoming dep messages. Called\n\t * by `defaultOnMessage`. Updates the DepRecord, triggers wave\n\t * completion, and forwards passthrough traffic.\n\t */\n\t_onDepMessage(depIndex: number, msg: Message): void {\n\t\tconst dep = this._deps[depIndex];\n\t\tconst t = msg[0];\n\n\t\t// Fire inspector hooks before default dispatch. Common case: no hooks\n\t\t// (undefined slot). Multiple observers can attach simultaneously.\n\t\tif (this._inspectorHooks != null) {\n\t\t\tconst ev: NodeInspectorHookEvent = { kind: \"dep_message\", depIndex, message: msg };\n\t\t\tfor (const hook of this._inspectorHooks) hook(ev);\n\t\t}\n\n\t\t// Tier 0 (START) — informational, no state change.\n\t\tif (t === START) return;\n\n\t\t// Tier 1\n\t\tif (t === DIRTY) {\n\t\t\tthis._depDirtied(dep);\n\t\t\treturn;\n\t\t}\n\t\tif (t === INVALIDATE) {\n\t\t\tthis._depInvalidated(dep);\n\t\t\tthis._emit(INVALIDATE_ONLY_BATCH);\n\t\t\treturn;\n\t\t}\n\n\t\t// Tier 2 — PAUSE / RESUME flow downstream (spec §1.2). Lock bookkeeping\n\t\t// happens inside `_emit` so both `_onDepMessage` (PAUSE received from\n\t\t// a dep) and external `node.down([[PAUSE, lockId]])` (source\n\t\t// directly issuing PAUSE) hit the same path. Here we just forward —\n\t\t// `_emit` will consume the lock, update `_paused`, and broadcast.\n\t\tif (t === PAUSE || t === RESUME) {\n\t\t\tthis._emit([msg]);\n\t\t\treturn;\n\t\t}\n\n\t\t// Tier 5\n\t\tif (t === TEARDOWN) {\n\t\t\tthis._emit(TEARDOWN_ONLY_BATCH);\n\t\t\treturn;\n\t\t}\n\n\t\t// Tier 3 / 4 — centralized transitions keep the settlement counters\n\t\t// (`_dirtyDepCount`, `_sentinelDepCount`) in sync with the flags on\n\t\t// every DepRecord. A3 optimization: the two counters let\n\t\t// `_maybeRunFnOnSettlement` check wave completion in O(1) instead\n\t\t// of two `every(...)` scans.\n\t\tif (t === DATA) {\n\t\t\tthis._depSettledAsData(dep, msg[1]);\n\t\t} else if (t === RESOLVED) {\n\t\t\tthis._depSettledAsResolved(dep);\n\t\t} else if (t === COMPLETE) {\n\t\t\tthis._depSettledAsTerminal(dep, true);\n\t\t} else if (t === ERROR) {\n\t\t\tthis._depSettledAsTerminal(dep, msg[1]);\n\t\t} else {\n\t\t\t// Unknown type: forward as-is (spec §1.3.6 forward-compat).\n\t\t\tthis._emit([msg]);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this._fn) {\n\t\t\t// Passthrough: forward DATA/RESOLVED 1:1 through the unified\n\t\t\t// emit pipeline. `_emit` owns tier sort + synthetic DIRTY\n\t\t\t// prefix + equals substitution uniformly — no manual framing.\n\t\t\tif (t === DATA || t === RESOLVED) {\n\t\t\t\tthis._emit([msg]);\n\t\t\t}\n\t\t\tif (t === COMPLETE || t === ERROR) {\n\t\t\t\tthis._maybeAutoTerminalAfterWave();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// NOTE: `_maybeRunFnOnSettlement()` is intentionally NOT called here.\n\t\t// It fires at the end of the dep-subscribe callback's message-iteration\n\t\t// loop in `_activate`/`_addDep`, guarded by `config.tierOf(m[0]) >= 3`\n\t\t// — one invocation per dep batch so `fn` sees the full wave (Bug 1).\n\t}\n\n\t// --- Centralized dep-state transitions (A3 settlement counters) ---\n\t//\n\t// Every mutation to `DepRecord.dirty` / `DepRecord.prevData` /\n\t// `DepRecord.terminal` must go through one of these helpers so the\n\t// `_dirtyDepCount` and `_sentinelDepCount` counters stay in sync with\n\t// the per-record flags. `_maybeRunFnOnSettlement` reads the counters\n\t// and never re-scans the `_deps` array.\n\n\t/**\n\t * Called when a dep transitions `dirty: false → true` (either from an\n\t * incoming DIRTY, or pre-set during `_activate` / `_addDep` /\n\t * `_depInvalidated`). No-op if the dep is already dirty. Fires the\n\t * downstream DIRTY emit if we're the first to dirty this wave.\n\t */\n\tprivate _depDirtied(dep: DepRecord): void {\n\t\tif (dep.dirty) return;\n\t\tdep.dirty = true;\n\t\tdep.involvedThisWave = true;\n\t\tthis._dirtyDepCount++;\n\t\t// First dep to dirty this wave → propagate DIRTY to our own sinks.\n\t\tif (this._status !== \"dirty\") {\n\t\t\tthis._emit(DIRTY_ONLY_BATCH);\n\t\t}\n\t}\n\n\t/**\n\t * Called when a dep delivers new DATA: clears dirty, stores the payload,\n\t * marks wave-has-data, and — if this is the dep's first DATA — clears\n\t * its sentinel slot so the first-run gate can open.\n\t */\n\tprivate _depSettledAsData(dep: DepRecord, value: unknown): void {\n\t\tif (dep.dirty) {\n\t\t\tdep.dirty = false;\n\t\t\tthis._dirtyDepCount--;\n\t\t}\n\t\tdep.involvedThisWave = true;\n\t\tdep.dataBatch.push(value);\n\t\tthis._waveHasNewData = true;\n\t}\n\n\t/**\n\t * Called when a dep emits RESOLVED (wave settled, value unchanged).\n\t * Clears dirty; does NOT touch `prevData` / `terminal` / sentinel\n\t * count — sentinel only exits on first DATA or terminal, not RESOLVED.\n\t */\n\tprivate _depSettledAsResolved(dep: DepRecord): void {\n\t\tif (dep.dirty) {\n\t\t\tdep.dirty = false;\n\t\t\tthis._dirtyDepCount--;\n\t\t}\n\t}\n\n\t/**\n\t * Called when a dep delivers COMPLETE (`terminal = true`) or ERROR\n\t * (`terminal = errorPayload`). Clears dirty, stores the terminal, and\n\t * — if the dep had never contributed a DATA yet — leaves sentinel\n\t * since the gate treats \"terminated without data\" as gate-open too.\n\t */\n\tprivate _depSettledAsTerminal(dep: DepRecord, terminal: unknown): void {\n\t\tif (dep.dirty) {\n\t\t\tdep.dirty = false;\n\t\t\tthis._dirtyDepCount--;\n\t\t}\n\t\tdep.terminal = terminal;\n\t\tdep.involvedThisWave = true;\n\t\tthis._hasNewTerminal = true;\n\t}\n\n\t/**\n\t * Called when a dep emits INVALIDATE: clears prevData, terminal, and\n\t * dataBatch. The dep is now back in the \"never delivered a real value\"\n\t * state — `prevData === undefined` so the sentinel check in fn will fire.\n\t */\n\tprivate _depInvalidated(dep: DepRecord): void {\n\t\tdep.prevData = undefined;\n\t\tdep.terminal = undefined;\n\t\tdep.dataBatch.length = 0;\n\t\tif (!dep.dirty) {\n\t\t\tdep.dirty = true;\n\t\t\tdep.involvedThisWave = true;\n\t\t\tthis._dirtyDepCount++;\n\t\t} else {\n\t\t\tdep.involvedThisWave = false; // cancel prior wave involvement\n\t\t}\n\t}\n\n\tprivate _maybeRunFnOnSettlement(): void {\n\t\tif (this._isTerminal && !this._resubscribable) return;\n\t\t// O(1) gate: `_dirtyDepCount === 0` means every dep has delivered its\n\t\t// settlement for this wave (DATA, RESOLVED, or terminal).\n\t\tif (this._dirtyDepCount > 0) return;\n\t\tif (this._paused) {\n\t\t\tthis._pendingWave = true;\n\t\t\treturn;\n\t\t}\n\t\t// Pre-fn skip: when no dep sent DATA this wave (all RESOLVED), skip\n\t\t// fn and emit RESOLVED directly. Transitive-skip optimization — leaf\n\t\t// fn is not re-run when a mid-chain node produces the same value.\n\t\tif (!this._waveHasNewData && !this._hasNewTerminal && this._hasCalledFnOnce) {\n\t\t\tthis._clearWaveFlags();\n\t\t\tthis._emit(RESOLVED_ONLY_BATCH);\n\t\t\tthis._maybeAutoTerminalAfterWave();\n\t\t\treturn;\n\t\t}\n\t\tif (this._fn) this._execFn();\n\t\tthis._maybeAutoTerminalAfterWave();\n\t}\n\n\tprivate _maybeAutoTerminalAfterWave(): void {\n\t\tif (this._deps.length === 0) return;\n\t\tif (this._isTerminal) return;\n\t\t// ERROR always propagates (unless rescue operator opts out via\n\t\t// errorWhenDepsError: false). Checked independently of _autoComplete\n\t\t// so operators with completeWhenDepsComplete: false still get\n\t\t// automatic error forwarding.\n\t\tconst erroredDep = this._deps.find((d) => d.terminal !== undefined && d.terminal !== true);\n\t\tif (erroredDep != null) {\n\t\t\tif (this._autoError) {\n\t\t\t\tthis._emit([[ERROR, erroredDep.terminal]]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t// COMPLETE only when autoComplete is true and ALL deps are terminal.\n\t\tif (this._autoComplete && this._deps.every((d) => d.terminal !== undefined)) {\n\t\t\tthis._emit(COMPLETE_ONLY_BATCH);\n\t\t}\n\t}\n\n\t// --- Fn execution ---\n\n\t/**\n\t * @internal Runs the node fn once. Default cleanup (function form) fires\n\t * before the new run; `{ deactivation }` cleanup survives.\n\t */\n\tprivate _execFn(): void {\n\t\tif (!this._fn) return;\n\t\tif (this._isTerminal && !this._resubscribable) return;\n\t\t// Re-entrance guard: if fn is currently executing (e.g. _addDep\n\t\t// triggered a synchronous DATA delivery → _maybeRunFnOnSettlement\n\t\t// → _execFn), defer the re-run until the current fn returns.\n\t\tif (this._isExecutingFn) {\n\t\t\tthis._pendingRerun = true;\n\t\t\treturn;\n\t\t}\n\n\t\t// Pre-run cleanup — only the function-form cleanup fires here.\n\t\tconst prevCleanup = this._cleanup;\n\t\tif (typeof prevCleanup === \"function\") {\n\t\t\tthis._cleanup = undefined;\n\t\t\ttry {\n\t\t\t\tprevCleanup();\n\t\t\t} catch (err) {\n\t\t\t\tthis._emit([[ERROR, this._wrapFnError(\"cleanup threw\", err)]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t// { deactivation } cleanup is preserved across runs.\n\n\t\t// Snapshot dep state BEFORE clearing wave flags so the snapshot\n\t\t// reflects \"this wave\" rather than \"next wave\".\n\t\t// dataBatch is copied here because _clearWaveFlags truncates the live\n\t\t// array in-place (length = 0) — the fn must see the full wave batch.\n\t\tconst batchData: (readonly unknown[] | undefined)[] = this._deps.map((d) =>\n\t\t\t!d.involvedThisWave ? undefined : d.dataBatch.length > 0 ? [...d.dataBatch] : [],\n\t\t);\n\t\t// Snapshot prevData BEFORE committing this wave's values — fn sees the\n\t\t// stable values from the end of the previous wave, not the current wave.\n\t\t// undefined = \"never sent DATA\". null is a valid DATA value.\n\t\tconst prevData: unknown[] = this._deps.map((d) => d.prevData);\n\t\t// Commit: advance each dep's prevData to this wave's last DATA so the\n\t\t// NEXT wave's fn snapshot sees the current wave as \"previous\".\n\t\t// Use the already-copied batchData rather than dep.dataBatch to avoid\n\t\t// any ordering dependency with _clearWaveFlags.\n\t\tfor (let i = 0; i < this._deps.length; i++) {\n\t\t\tconst batch = batchData[i];\n\t\t\tif (batch != null && batch.length > 0) {\n\t\t\t\tthis._deps[i].prevData = batch[batch.length - 1] as unknown;\n\t\t\t}\n\t\t}\n\t\tconst terminalDeps = this._deps.map((d) => d.terminal);\n\t\tconst ctx: FnCtx = { prevData, terminalDeps, store: this._store };\n\n\t\tthis._hasCalledFnOnce = true;\n\t\tthis._clearWaveFlags();\n\n\t\t// Fire inspector hooks before fn runs — for Graph.observe causal traces.\n\t\tif (this._inspectorHooks != null) {\n\t\t\tconst ev: NodeInspectorHookEvent = { kind: \"run\", batchData, prevData };\n\t\t\tfor (const hook of this._inspectorHooks) hook(ev);\n\t\t}\n\n\t\tthis._isExecutingFn = true;\n\t\ttry {\n\t\t\tconst result = this._fn(batchData, this._actions, ctx);\n\t\t\tif (typeof result === \"function\") {\n\t\t\t\tthis._cleanup = result;\n\t\t\t} else if (\n\t\t\t\tresult != null &&\n\t\t\t\ttypeof result === \"object\" &&\n\t\t\t\ttypeof (result as { deactivation?: unknown }).deactivation === \"function\"\n\t\t\t) {\n\t\t\t\tthis._cleanup = result as { deactivation: () => void };\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthis._emit([[ERROR, this._wrapFnError(\"fn threw\", err)]]);\n\t\t} finally {\n\t\t\tthis._isExecutingFn = false;\n\t\t\t// Run any pending rerun BEFORE clearing wave flags so the\n\t\t\t// rerun's settlement check sees \"this wave had new data\" and\n\t\t\t// skips the pre-fn-skip optimization. Without this ordering,\n\t\t\t// autoTrackNode discovery's second pass gets swallowed by\n\t\t\t// the pre-fn-skip path.\n\t\t\tif (this._pendingRerun) {\n\t\t\t\tthis._pendingRerun = false;\n\t\t\t\tthis._rerunDepth += 1;\n\t\t\t\tif (this._rerunDepth > MAX_RERUN_DEPTH) {\n\t\t\t\t\tthis._rerunDepth = 0;\n\t\t\t\t\tthis._emit([\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tERROR,\n\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t`Node \"${this.name}\": _pendingRerun depth exceeded ${MAX_RERUN_DEPTH} — likely a reactive cycle`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t],\n\t\t\t\t\t]);\n\t\t\t\t} else {\n\t\t\t\t\tthis._maybeRunFnOnSettlement();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Chain converged — reset the depth counter for the next wave.\n\t\t\t\tthis._rerunDepth = 0;\n\t\t\t}\n\t\t\t// Clear flags after rerun so any involvedThisWave/dataBatch set by\n\t\t\t// fn's _addDep subscribe handshakes doesn't leak into the next\n\t\t\t// wave's snapshot. The inner _execFn (if any) already did\n\t\t\t// its own pre-snapshot clear; this is for the case where\n\t\t\t// fn added deps but no rerun fired.\n\t\t\tthis._clearWaveFlags();\n\t\t}\n\t}\n\n\tprivate _clearWaveFlags(): void {\n\t\tthis._waveHasNewData = false;\n\t\tthis._hasNewTerminal = false;\n\t\tfor (const d of this._deps) {\n\t\t\td.involvedThisWave = false;\n\t\t\td.dataBatch.length = 0;\n\t\t}\n\t}\n\n\tprivate _wrapFnError(label: string, err: unknown): Error {\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\treturn new Error(`Node \"${this.name}\": ${label}: ${msg}`, { cause: err });\n\t}\n\n\t// --- Framing (tier sort + synthetic DIRTY prefix) ---\n\n\t/**\n\t * @internal Stable tier sort + synthetic DIRTY prefix for an outgoing\n\t * batch. Fast path: already-monotone single-tier batches (the common\n\t * case from interned singletons like `DIRTY_ONLY_BATCH`) return the\n\t * input unchanged. General path: decorate-sort-undecorate into a new\n\t * array, then prepend `[DIRTY]` after any tier-0 START entries when\n\t * a tier-3 payload is present and the node isn't already dirty.\n\t *\n\t * Single source of truth for the spec §1.3.1 framing invariant. Every\n\t * outgoing path hits `_frameBatch` exactly once via `_emit`.\n\t */\n\tprivate _frameBatch(messages: Messages): Messages {\n\t\tconst tierOf = this._config.tierOf;\n\t\t// Fast path: single message.\n\t\tif (messages.length === 1) {\n\t\t\tconst t = tierOf(messages[0][0]);\n\t\t\tif (t === 3 && this._status !== \"dirty\") {\n\t\t\t\treturn [DIRTY_MSG, messages[0]];\n\t\t\t}\n\t\t\treturn messages;\n\t\t}\n\t\t// Check monotonicity and tier-3 presence in a single pass.\n\t\tlet monotone = true;\n\t\tlet hasTier3 = false;\n\t\tlet hasDirty = false;\n\t\tlet prevTier = -1;\n\t\tfor (const m of messages) {\n\t\t\tconst tier = tierOf(m[0]);\n\t\t\tif (tier < prevTier) monotone = false;\n\t\t\tif (tier === 3) hasTier3 = true;\n\t\t\tif (m[0] === DIRTY) hasDirty = true;\n\t\t\tprevTier = tier;\n\t\t}\n\t\tlet sorted: Messages = messages;\n\t\tif (!monotone) {\n\t\t\t// Stable sort via index-keyed decoration.\n\t\t\tconst indexed = messages.map((m, i) => ({ m, i, tier: tierOf(m[0]) }));\n\t\t\tindexed.sort((a, b) => a.tier - b.tier || a.i - b.i);\n\t\t\tsorted = indexed.map((x) => x.m);\n\t\t}\n\t\tif (hasTier3 && !hasDirty && this._status !== \"dirty\") {\n\t\t\t// Insert DIRTY after any tier-0 START entries to preserve\n\t\t\t// monotonicity.\n\t\t\tlet insertAt = 0;\n\t\t\twhile (insertAt < sorted.length && tierOf(sorted[insertAt][0]) === 0) insertAt++;\n\t\t\tif (insertAt === 0) return [DIRTY_MSG, ...sorted];\n\t\t\treturn [...sorted.slice(0, insertAt), DIRTY_MSG, ...sorted.slice(insertAt)];\n\t\t}\n\t\treturn sorted;\n\t}\n\n\t// --- Emit pipeline ---\n\n\t/**\n\t * @internal The unified dispatch waist — one call = one wave.\n\t * See `GRAPHREFLY-SPEC.md` §1.3.1 for protocol context — the stages\n\t * below are the implementation order.\n\t *\n\t * Pipeline stages, in order:\n\t *\n\t * 1. Terminal filter — post-COMPLETE/ERROR only TEARDOWN/INVALIDATE\n\t * still propagate so graph teardown and cache-clear still work.\n\t * 2. Tier sort (stable) — the batch can be in any order when it\n\t * arrives; the walker downstream (`downWithBatch`) assumes\n\t * ascending tier monotone, and so does `_updateState`'s tier-3\n\t * slice walk. This is the single source of truth for ordering.\n\t * 3. Synthetic DIRTY prefix — if a tier-3 payload is present, no\n\t * DIRTY is already in the batch, and the node isn't already in\n\t * `\"dirty\"` status, prepend `[DIRTY]` after any tier-0 START\n\t * entries. Guarantees spec §1.3.1 (DIRTY precedes DATA within\n\t * the same batch) uniformly across every entry point.\n\t * 4. PAUSE/RESUME lock bookkeeping (C0) — update `_pauseLocks`,\n\t * derive `_paused`, filter unknown-lockId RESUME, replay\n\t * bufferAll buffer on final lock release.\n\t * 5. Meta TEARDOWN fan-out — notify meta children before\n\t * `_updateState`'s TEARDOWN branch calls `_deactivate`. Hoisted\n\t * out of the walk to keep `_updateState` re-entrance-free.\n\t * 6. `_updateState` — walk the batch in tier order, advancing\n\t * `_cached` / `_status` / `_versioning` and running equals\n\t * substitution on tier-3 DATA (§3.5.1). Returns\n\t * `{finalMessages, equalsError?}`.\n\t * 7. `downWithBatch` dispatch (or bufferAll capture if paused with\n\t * `pausable: \"resumeAll\"`).\n\t * 8. Recursive ERROR emission if equals threw mid-walk.\n\t */\n\t_emit(messages: Messages): void {\n\t\tif (messages.length === 0) return;\n\n\t\t// Terminal filter: after COMPLETE/ERROR (non-resubscribable), only\n\t\t// TEARDOWN / INVALIDATE still propagate so graph teardown and cache-\n\t\t// clear still work.\n\t\tlet deliverable = messages;\n\t\tconst terminal = this._isTerminal;\n\t\tif (terminal && !this._resubscribable) {\n\t\t\tconst pass = messages.filter((m) => m[0] === TEARDOWN || m[0] === INVALIDATE);\n\t\t\tif (pass.length === 0) return;\n\t\t\tdeliverable = pass;\n\t\t}\n\n\t\t// Tier sort + synthetic DIRTY prefix (stages 3 + 4 of the emit\n\t\t// pipeline). `_frameBatch` is a no-op for pre-sorted single-msg\n\t\t// batches (the common case from the tuple-interning A2 call sites);\n\t\t// otherwise it produces a stable tier-sorted copy with `[DIRTY]`\n\t\t// auto-prepended after any tier-0 messages when a tier-3 payload\n\t\t// is present and the node isn't already dirty.\n\t\tdeliverable = this._frameBatch(deliverable);\n\n\t\t// C0 — PAUSE/RESUME lock tracking. Every tier-2 tuple MUST carry a\n\t\t// `lockId` payload. Each PAUSE / RESUME updates `_pauseLocks` and\n\t\t// derives `_paused` from set size — multi-pauser correctness\n\t\t// guarantees a node only resumes when every lock it holds is\n\t\t// released. All tier-2 messages are forwarded unconditionally so\n\t\t// downstream nodes on the propagation path keep their own lock\n\t\t// sets consistent (subscribers that joined the graph before any\n\t\t// PAUSE see the full lock history). `pausable: false` sources\n\t\t// forward PAUSE/RESUME but do not track locks — appropriate for\n\t\t// reactive timers that must keep ticking. Unknown-lockId RESUME\n\t\t// is swallowed to keep `dispose()` idempotent.\n\t\tlet filtered: Message[] | null = null;\n\t\tfor (let i = 0; i < deliverable.length; i++) {\n\t\t\tconst m = deliverable[i];\n\t\t\tconst t = m[0];\n\t\t\tif (t !== PAUSE && t !== RESUME) {\n\t\t\t\tif (filtered != null) filtered.push(m);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (m.length < 2) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Node \"${this.name}\": [[${t === PAUSE ? \"PAUSE\" : \"RESUME\"}]] must ` +\n\t\t\t\t\t\t\"carry a lockId payload — bare PAUSE/RESUME is a protocol \" +\n\t\t\t\t\t\t\"violation (C0 rule). Use `[[PAUSE, lockId]]` / \" +\n\t\t\t\t\t\t\"`[[RESUME, lockId]]`.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tlet forward = true;\n\t\t\tif (this._pausable !== false) {\n\t\t\t\tconst lockId = m[1];\n\t\t\t\tif (t === PAUSE) {\n\t\t\t\t\tif (this._pauseLocks == null) this._pauseLocks = new Set();\n\t\t\t\t\tthis._pauseLocks.add(lockId);\n\t\t\t\t\tthis._paused = true;\n\t\t\t\t\tif (this._pausable === \"resumeAll\" && this._pauseBuffer == null) {\n\t\t\t\t\t\tthis._pauseBuffer = [];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// RESUME\n\t\t\t\t\tif (this._pauseLocks == null || !this._pauseLocks.has(lockId)) {\n\t\t\t\t\t\t// Unknown lockId — swallow to keep dispose idempotent.\n\t\t\t\t\t\tforward = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._pauseLocks.delete(lockId);\n\t\t\t\t\t\tif (this._pauseLocks.size === 0) {\n\t\t\t\t\t\t\tthis._paused = false;\n\t\t\t\t\t\t\t// Replay bufferAll buffer through the outgoing\n\t\t\t\t\t\t\t// pipeline BEFORE forwarding RESUME — subscribers\n\t\t\t\t\t\t\t// observe the deferred DATAs as part of the\n\t\t\t\t\t\t\t// pre-RESUME wake-up.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// D2 (2026-04-13) semantic note: the recursive\n\t\t\t\t\t\t\t// `_emit(drain)` goes through the full pipeline\n\t\t\t\t\t\t\t// including `_updateState`'s equals substitution.\n\t\t\t\t\t\t\t// A buffered `[DATA, v]` whose value matches the\n\t\t\t\t\t\t\t// *pre-pause* cache will collapse to RESOLVED on\n\t\t\t\t\t\t\t// replay — producer \"pulses\" that write the same\n\t\t\t\t\t\t\t// value while paused are absorbed. This matches\n\t\t\t\t\t\t\t// diamond-safety intent: `.cache` stays coherent\n\t\t\t\t\t\t\t// with \"the last DATA actually delivered to\n\t\t\t\t\t\t\t// sinks\". Producers that need pulse semantics\n\t\t\t\t\t\t\t// (every write observable regardless of value)\n\t\t\t\t\t\t\t// should set `equals: () => false` on the node.\n\t\t\t\t\t\t\tif (this._pauseBuffer != null && this._pauseBuffer.length > 0) {\n\t\t\t\t\t\t\t\tconst drain = this._pauseBuffer;\n\t\t\t\t\t\t\t\tthis._pauseBuffer = [];\n\t\t\t\t\t\t\t\tthis._emit(drain);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Kick the held wave forward if one was pending.\n\t\t\t\t\t\t\tif (this._pendingWave) {\n\t\t\t\t\t\t\t\tthis._pendingWave = false;\n\t\t\t\t\t\t\t\tthis._maybeRunFnOnSettlement();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!forward) {\n\t\t\t\tif (filtered == null) filtered = deliverable.slice(0, i) as Message[];\n\t\t\t} else if (filtered != null) {\n\t\t\t\tfiltered.push(m);\n\t\t\t}\n\t\t}\n\t\tif (filtered != null) {\n\t\t\tif (filtered.length === 0) return;\n\t\t\tdeliverable = filtered;\n\t\t}\n\n\t\t// Meta TEARDOWN fan-out happens BEFORE `_updateState` so the walk\n\t\t// stays re-entrance-free: a meta node's own dispatch must not\n\t\t// re-enter the parent's outgoing pipeline while `this._cached` /\n\t\t// `this._status` are mid-commit. This preserves the spec ordering\n\t\t// \"meta propagates before deactivation\" — `_updateState`'s TEARDOWN\n\t\t// branch still runs `_deactivate` AFTER the meta children\n\t\t// have already been notified here.\n\t\tif (this._hasMeta && deliverable.some((m) => m[0] === TEARDOWN)) {\n\t\t\tfor (const k of Object.keys(this.meta)) {\n\t\t\t\ttry {\n\t\t\t\t\t(this.meta[k] as NodeImpl)._emit(TEARDOWN_ONLY_BATCH);\n\t\t\t\t} catch {\n\t\t\t\t\t/* best-effort */\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// State update + equals substitution (§3.5.1 invariant). Returns the\n\t\t// possibly-rewritten batch and an optional equals-throw error. When\n\t\t// equals throws mid-walk we still deliver the successfully-walked\n\t\t// prefix to sinks before emitting ERROR, preserving cache/wire\n\t\t// coherence (user P2 option (i)).\n\t\tconst { finalMessages, equalsError } = this._updateState(deliverable);\n\n\t\t// Global inspector fan-out (Redux-DevTools-style tracer). Fires once\n\t\t// per outgoing batch, gated by `inspectorEnabled` so production paths\n\t\t// pay one boolean check. Hook errors are swallowed — instrumentation\n\t\t// must not break the data plane.\n\t\tif (finalMessages.length > 0 && this._config.inspectorEnabled) {\n\t\t\tconst inspector = this._config.globalInspector;\n\t\t\tif (inspector != null) {\n\t\t\t\ttry {\n\t\t\t\t\tinspector({ kind: \"emit\", node: this, messages: finalMessages });\n\t\t\t\t} catch {\n\t\t\t\t\t/* best-effort */\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (finalMessages.length > 0) {\n\t\t\t// BufferAll: while paused with `pausable: \"resumeAll\"`, buffer\n\t\t\t// tier-3/4 payloads in order. Tier 0–2 and tier 5 continue to\n\t\t\t// dispatch synchronously — START/DIRTY/RESUME/PAUSE/TEARDOWN\n\t\t\t// must stay live so subscribers, downstream pausers, and graph\n\t\t\t// teardown all observe them. Cache/status advance has already\n\t\t\t// happened via `_updateState`, so the replay later just pushes\n\t\t\t// the deferred messages back through `downWithBatch`.\n\t\t\tif (this._paused && this._pausable === \"resumeAll\" && this._pauseBuffer != null) {\n\t\t\t\tconst tierOf = this._config.tierOf;\n\t\t\t\tconst immediate: Message[] = [];\n\t\t\t\tfor (const m of finalMessages) {\n\t\t\t\t\tconst tier = tierOf(m[0]);\n\t\t\t\t\tif (tier < 3 || tier === 5) {\n\t\t\t\t\t\timmediate.push(m);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._pauseBuffer.push(m);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (immediate.length > 0) {\n\t\t\t\t\tthis._dispatchOrAccumulate(immediate);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis._dispatchOrAccumulate(finalMessages);\n\t\t\t}\n\t\t}\n\n\t\tif (equalsError != null) {\n\t\t\tthis._emit([[ERROR, equalsError]]);\n\t\t}\n\t}\n\n\t/**\n\t * @internal Walk an outgoing (already-framed) batch, updating own\n\t * cache / status / versioning and running equals substitution on\n\t * every tier-3 DATA (§3.5.1). Framing — tier sort and synthetic\n\t * DIRTY prefix — has already happened upstream in `_frameBatch`.\n\t * This walk trusts the input is in monotone tier order and that the\n\t * spec §1.3.1 DIRTY/RESOLVED precedence invariant is already\n\t * satisfied by the frame.\n\t *\n\t * Equals substitution: every DATA payload is compared against the\n\t * live `_cached`; when equal, the tuple is rewritten to `[RESOLVED]`\n\t * in a per-call copy and cache is not re-advanced. `.cache` remains\n\t * coherent with \"the last DATA payload this node actually sent\n\t * downstream\".\n\t *\n\t * Returns `{ finalMessages, equalsError? }`:\n\t * - `finalMessages` — the array to deliver to sinks (may be\n\t * `messages` unchanged, a rewritten copy with DATA→RESOLVED\n\t * substitutions, or a truncated prefix when equals throws mid-walk).\n\t * - `equalsError` — present only when the configured `equals` function\n\t * threw on some DATA message. `_emit` delivers the prefix first,\n\t * then emits a fresh ERROR batch via a recursive `_emit` call so\n\t * subscribers observe `[...walked_prefix, ERROR]` in order.\n\t */\n\tprivate _updateState(messages: Messages): {\n\t\tfinalMessages: Messages;\n\t\tequalsError?: Error;\n\t} {\n\t\tconst tierOf = this._config.tierOf;\n\t\tlet rewritten: Message[] | undefined;\n\t\tlet equalsError: Error | undefined;\n\t\tlet abortedAt = -1;\n\t\t// Count tier-3 messages (DATA + RESOLVED) in the batch. Equals\n\t\t// substitution is only worthwhile for a single tier-3 message —\n\t\t// an unchanged value can be rewritten to RESOLVED, enabling the\n\t\t// downstream pre-fn skip. With multiple tier-3 messages the\n\t\t// downstream fn must run regardless, so equals on each is wasted.\n\t\tlet dataCount = 0;\n\t\tfor (const m of messages) {\n\t\t\tif (tierOf(m[0]) === 3) dataCount++;\n\t\t}\n\t\tconst checkEquals = dataCount <= 1;\n\t\t// Version advances once per batch wave, not per DATA in the batch.\n\t\t// _cached only retains the last DATA value, so intermediate version\n\t\t// entries would reference values that can never be retrieved from cache.\n\t\t// Pre-scan for the last DATA index so we know when to fire advanceVersion.\n\t\tlet lastDataIdx = -1;\n\t\tif (this._versioning != null && dataCount > 1) {\n\t\t\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\t\t\tif (messages[i][0] === DATA) {\n\t\t\t\t\tlastDataIdx = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = 0; i < messages.length; i++) {\n\t\t\tconst m = messages[i];\n\t\t\tconst t = m[0];\n\t\t\tif (t === DATA) {\n\t\t\t\tif (m.length >= 2) {\n\t\t\t\t\tlet unchanged = false;\n\t\t\t\t\tif (checkEquals && this._cached !== undefined) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tunchanged = this._equals(this._cached as T, m[1] as T);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t// Abort walk on equals throw: deliver successfully-walked\n\t\t\t\t\t\t\t// prefix, then caller emits ERROR. Excludes the throwing\n\t\t\t\t\t\t\t// message from the prefix.\n\t\t\t\t\t\t\tequalsError = this._wrapFnError(\"equals threw\", err);\n\t\t\t\t\t\t\tabortedAt = i;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (unchanged) {\n\t\t\t\t\t\tif (rewritten == null) rewritten = messages.slice(0, i) as Message[];\n\t\t\t\t\t\trewritten.push(RESOLVED_MSG);\n\t\t\t\t\t\tthis._status = \"resolved\";\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tthis._cached = m[1] as T;\n\t\t\t\t\tif (this._versioning != null) {\n\t\t\t\t\t\t// dataCount <= 1: lastDataIdx is -1; advance unconditionally\n\t\t\t\t\t\t// (single DATA, correct as before).\n\t\t\t\t\t\t// dataCount > 1: only advance on the last DATA in the batch.\n\t\t\t\t\t\tif (lastDataIdx < 0 || i === lastDataIdx) {\n\t\t\t\t\t\t\tadvanceVersion(this._versioning, m[1], this._hashFn);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis._status = \"settled\";\n\t\t\t\tif (rewritten != null) rewritten.push(m);\n\t\t\t} else {\n\t\t\t\tif (rewritten != null) rewritten.push(m);\n\t\t\t\tif (t === DIRTY) {\n\t\t\t\t\tthis._status = \"dirty\";\n\t\t\t\t} else if (t === RESOLVED) {\n\t\t\t\t\tthis._status = \"resolved\";\n\t\t\t\t} else if (t === COMPLETE) {\n\t\t\t\t\tthis._status = \"completed\";\n\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\tthis._status = \"errored\";\n\t\t\t\t} else if (t === INVALIDATE) {\n\t\t\t\t\tthis._cached = undefined;\n\t\t\t\t\tthis._status = \"dirty\";\n\t\t\t\t\t// Function-form cleanup fires on invalidate (treats as \"re-run\").\n\t\t\t\t\tconst c = this._cleanup;\n\t\t\t\t\tif (typeof c === \"function\") {\n\t\t\t\t\t\tthis._cleanup = undefined;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tc();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* best-effort */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (t === TEARDOWN) {\n\t\t\t\t\tif (this._resetOnTeardown) this._cached = undefined;\n\t\t\t\t\t// Meta TEARDOWN fan-out was already performed by `_emit`\n\t\t\t\t\t// before this walk. Deactivate now that meta children\n\t\t\t\t\t// have been notified.\n\t\t\t\t\tthis._deactivate(/* skipStatusUpdate */ true);\n\t\t\t\t\t// TEARDOWN is a hard reset — unconditionally \"sentinel\",\n\t\t\t\t\t// even if the node was previously completed/errored.\n\t\t\t\t\tthis._status = \"sentinel\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst base: Messages =\n\t\t\tabortedAt >= 0\n\t\t\t\t? ((rewritten ?? (messages.slice(0, abortedAt) as Messages)) as Messages)\n\t\t\t\t: (rewritten ?? messages);\n\t\treturn equalsError != null ? { finalMessages: base, equalsError } : { finalMessages: base };\n\t}\n\n\tprivate _deliverToSinks = (messages: Messages): void => {\n\t\tif (this._sinks == null) return;\n\t\tif (typeof this._sinks === \"function\") {\n\t\t\tthis._sinks(messages);\n\t\t\treturn;\n\t\t}\n\t\t// Snapshot: a sink callback may unsubscribe itself or others\n\t\t// mid-iteration. Iterating the live Set would skip not-yet-visited\n\t\t// sinks that were removed.\n\t\tconst snapshot = [...this._sinks];\n\t\tfor (const sink of snapshot) sink(messages);\n\t};\n\n\t/**\n\t * @internal Dispatch entry point that respects the per-batch emit\n\t * accumulator (Bug 2). Inside an explicit `batch()` scope, append to\n\t * `_batchPendingMessages` and register a flush hook on first append.\n\t * Outside batch — or during a drain (where `flushInProgress` is true\n\t * but `batchDepth` is 0) — dispatch synchronously through `downWithBatch`.\n\t *\n\t * Per-emit state updates (`_frameBatch`, `_updateState`) have already\n\t * happened by the time we reach here; only the **downstream delivery**\n\t * is coalesced. Cache, version, and status are visible mid-batch on\n\t * the emitting node itself.\n\t */\n\tprivate _dispatchOrAccumulate(messages: Messages): void {\n\t\tif (isExplicitlyBatching()) {\n\t\t\tif (this._batchPendingMessages === null) {\n\t\t\t\tthis._batchPendingMessages = [];\n\t\t\t\tregisterBatchFlushHook(() => this._flushBatchPending());\n\t\t\t}\n\t\t\tfor (const m of messages) this._batchPendingMessages.push(m);\n\t\t\treturn;\n\t\t}\n\t\tdownWithBatch(this._deliverToSinks, messages, this._config.tierOf);\n\t}\n\n\t/**\n\t * @internal Flushes the accumulated batch through `downWithBatch` and\n\t * clears the pending state. Idempotent — safe to call when pending is\n\t * already null or empty (e.g. on a `batch()` throw, where the hook\n\t * fires for cleanup but the drainPhase queues are wiped after).\n\t *\n\t * Critical: the accumulated batch is interleaved per-emit framings like\n\t * `[DIRTY, DATA(1), DIRTY, DATA(2)]` — non-monotone tier order. We must\n\t * re-frame to sort by tier before handing to `downWithBatch`, which\n\t * assumes pre-sorted input. `_frameBatch` also handles the synthetic\n\t * DIRTY prepend rule (no-op here — `hasDirty` is true since each\n\t * accumulated emit already carries its own DIRTY prefix).\n\t */\n\tprivate _flushBatchPending(): void {\n\t\tconst pending = this._batchPendingMessages;\n\t\tif (pending === null) return;\n\t\tthis._batchPendingMessages = null;\n\t\tif (pending.length === 0) return;\n\t\tconst framed = this._frameBatch(pending);\n\t\tdownWithBatch(this._deliverToSinks, framed, this._config.tierOf);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nconst isNodeArray = (value: unknown): value is readonly Node[] => Array.isArray(value);\nconst isNodeOptionsObject = (value: unknown): value is NodeOptions<unknown> =>\n\ttypeof value === \"object\" && value != null && !Array.isArray(value);\n\n/**\n * Creates a reactive {@link Node} — the single GraphReFly primitive (§2).\n *\n * Typical shapes:\n * - `node([])` / `node({ initial: v })` — a manual source (state node).\n * - `node(producerFn, opts)` — a producer that runs on first-subscribe.\n * - `node(deps, computeFn, opts)` — a derived / effect node.\n *\n * For value-returning computations, prefer the sugar factories in `sugar.ts`\n * (`state`, `derived`, `effect`, `producer`, `dynamicNode`), which wrap user\n * fns with `actions.emit(userFn(data))`. Calling `node()` directly gives you\n * the raw `NodeFn` contract: explicit emission via `actions`, cleanup return.\n */\nexport function node<T = unknown>(\n\tdepsOrFn?: readonly Node[] | NodeFn | NodeOptions<T>,\n\tfnOrOpts?: NodeFn | NodeOptions<T>,\n\toptsArg?: NodeOptions<T>,\n): Node<T> {\n\tconst deps: readonly Node[] = isNodeArray(depsOrFn) ? depsOrFn : [];\n\tconst fn: NodeFn | undefined =\n\t\ttypeof depsOrFn === \"function\"\n\t\t\t? depsOrFn\n\t\t\t: typeof fnOrOpts === \"function\"\n\t\t\t\t? fnOrOpts\n\t\t\t\t: undefined;\n\tlet opts: NodeOptions<T> = {};\n\tif (isNodeArray(depsOrFn)) {\n\t\topts = ((isNodeOptionsObject(fnOrOpts) ? fnOrOpts : optsArg) ?? {}) as NodeOptions<T>;\n\t} else if (isNodeOptionsObject(depsOrFn)) {\n\t\topts = depsOrFn as NodeOptions<T>;\n\t} else {\n\t\topts = ((isNodeOptionsObject(fnOrOpts) ? fnOrOpts : optsArg) ?? {}) as NodeOptions<T>;\n\t}\n\treturn new NodeImpl<T>(deps, fn, opts);\n}\n","/**\n * Sugar constructors over the raw `node()` primitive.\n *\n * Each factory wraps a user-friendly function into the canonical\n * `NodeFn = (data, actions, ctx) => cleanup | void` shape, then calls\n * `node(...)`. This is the only place `actions.emit(...)` is invoked\n * on behalf of the user — if you need finer control (multi-emission,\n * raw `actions.down` / `actions.up`, cleanup return), use the raw\n * `node()` factory from `./node.js` directly.\n *\n * See SESSION-foundation-redesign.md §8.5 + §10.6 for the rewrite.\n */\n\nimport type { NodeActions } from \"./config.js\";\nimport { RESOLVED } from \"./messages.js\";\nimport {\n\ttype FnCtx,\n\ttype Node,\n\ttype NodeFn,\n\ttype NodeFnCleanup,\n\tNodeImpl,\n\ttype NodeOptions,\n\tnode,\n} from \"./node.js\";\n\n// ---------------------------------------------------------------------------\n// Shared sentinel guard\n// ---------------------------------------------------------------------------\n\n/**\n * Returns `true` when fn should be suppressed (RESOLVED emitted instead).\n *\n * Fires when `allowPartial` is `false` and any dep has never delivered DATA:\n * `data[i]` absent this wave AND `ctx.prevData[i] === undefined`.\n *\n * `undefined` is the protocol-reserved \"never sent DATA\" sentinel. `null` is\n * a valid DATA value and will NOT trigger the guard.\n */\nfunction sentinelGuard(\n\tbatchData: readonly (readonly unknown[] | undefined)[],\n\tctx: FnCtx,\n\tallowPartial: boolean,\n): boolean {\n\tif (allowPartial) return false;\n\treturn batchData.some(\n\t\t(batch, i) => !(batch != null && batch.length > 0) && ctx.prevData[i] === undefined,\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// state — manual source with an optional initial value\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a manual source node. Drive it with `state.emit(v)` (framed,\n * diamond-safe) or `state.down([[DATA, v]])` (raw compat path).\n *\n * @param initial - Starting cached value. Pass `undefined` or `null`\n * explicitly to cache that value; omit to leave the node in `\"sentinel\"`.\n * @param opts - Optional {@link NodeOptions} (excluding `initial`).\n */\nexport function state<T>(initial: T, opts?: Omit<NodeOptions<T>, \"initial\">): Node<T> {\n\treturn node<T>([], { ...opts, initial });\n}\n\n// ---------------------------------------------------------------------------\n// producer — no-deps source with a compute body\n// ---------------------------------------------------------------------------\n\n/**\n * User-level producer compute: runs once on first-subscriber activation.\n * Receives `actions` for imperative emission and `ctx` for FnCtx (typically\n * only `store` is useful on a producer — no deps means `prevData` and\n * `terminalDeps` are empty).\n */\nexport type ProducerFn = (\n\tactions: NodeActions,\n\tctx: FnCtx,\n\t// biome-ignore lint/suspicious/noConfusingVoidType: matches NodeFn — see its JSDoc.\n) => NodeFnCleanup | void;\n\n/**\n * Creates a producer node with no deps; `fn` runs once when the first\n * subscriber connects. Return a cleanup function (`() => void`) or\n * `{ deactivation: () => void }` to register teardown.\n *\n * @example\n * ```ts\n * const ticker = producer((actions) => {\n * const id = setInterval(() => actions.emit(Date.now()), 1000);\n * return () => clearInterval(id);\n * });\n * ```\n */\nexport function producer<T = unknown>(fn: ProducerFn, opts?: NodeOptions<T>): Node<T> {\n\tconst wrapped: NodeFn = (_data, actions, ctx) => fn(actions, ctx) ?? undefined;\n\treturn node<T>(wrapped, { describeKind: \"producer\", ...opts });\n}\n\n// ---------------------------------------------------------------------------\n// derived — dep-driven pure compute\n// ---------------------------------------------------------------------------\n\n/**\n * User-level derived compute: receives the latest DATA from each dep and\n * returns the new value. The sugar wraps it with `actions.emit(fn(...))`\n * so the return value flows through the framed emit pipeline.\n *\n * For derived nodes that need to inspect `ctx.prevData` / `ctx.terminalDeps`\n * / `ctx.store`, accept the optional second parameter.\n */\nexport type DerivedFn<T> = (data: readonly unknown[], ctx: FnCtx) => T | undefined | null;\n\n/**\n * Creates a derived node that computes **one output per wave** from the latest\n * value of each dependency — **snapshot / combine semantics**.\n *\n * `fn` receives one scalar per dep (the last DATA value seen this wave, or the\n * prior-wave value as fallback). It is called once per settled wave and emits\n * a single value via `actions.emit`. The equals check then suppresses the\n * emission as `RESOLVED` if the output has not changed.\n *\n * **Not for streaming one-to-one transforms.** If each DATA value in a batch\n * must produce a corresponding output (e.g. transforming every item emitted by\n * `fromIter` individually), use {@link map} or raw `node()` with full batch\n * iteration instead. `derived` only sees the *last* value per dep when a batch\n * carries multiple DATAs.\n *\n * @example\n * ```ts\n * const a = state(1);\n * const b = derived([a], ([x]) => (x as number) * 2);\n * ```\n */\nexport function derived<T = unknown>(\n\tdeps: readonly Node[],\n\tfn: DerivedFn<T>,\n\topts?: NodeOptions<T> & { partial?: boolean },\n): Node<T> {\n\tconst allowPartial = opts?.partial ?? false;\n\tconst wrapped: NodeFn = (batchData, actions, ctx) => {\n\t\t// Sentinel guard: if any dep has never sent DATA, emit RESOLVED.\n\t\t// Uses ctx.prevData[i] === undefined (the \"never sent\" sentinel).\n\t\t// null is valid DATA and won't trigger this. Skipped when partial:true.\n\t\tif (sentinelGuard(batchData, ctx, allowPartial)) {\n\t\t\tactions.down([[RESOLVED]]);\n\t\t\treturn undefined;\n\t\t}\n\t\t// Unwrap batch-per-dep to single latest scalar per dep.\n\t\t// Batch non-null+non-empty → take last value from this wave;\n\t\t// otherwise fall back to ctx.prevData[i] (last value from prior wave).\n\t\t// undefined means \"never sent DATA\" — sentinelGuard already blocks this\n\t\t// fn when partial:false and any dep is unset, so partial:true callers\n\t\t// receive undefined for uninitiated deps (same as JS convention).\n\t\tconst data = batchData.map((batch, i) =>\n\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t);\n\t\tactions.emit(fn(data, ctx));\n\t\treturn undefined;\n\t};\n\treturn node<T>(deps, wrapped, { describeKind: \"derived\", ...opts });\n}\n\n// ---------------------------------------------------------------------------\n// effect — dep-driven side effect, no auto-emit\n// ---------------------------------------------------------------------------\n\n/**\n * User-level effect compute: fires when deps settle. Return value is NOT\n * auto-emitted — use `actions.emit(v)` / `actions.down(msgs)` explicitly if\n * the effect also wants to produce downstream messages. Return a cleanup\n * function or `{ deactivation }` to register teardown.\n */\nexport type EffectFn = (\n\tdata: readonly unknown[],\n\tactions: NodeActions,\n\tctx: FnCtx,\n\t// biome-ignore lint/suspicious/noConfusingVoidType: matches NodeFn — see its JSDoc.\n) => NodeFnCleanup | void;\n\n/**\n * Runs a side-effect when deps settle. Return value is not auto-emitted.\n *\n * @example\n * ```ts\n * effect([source], ([v]) => {\n * console.log(v);\n * });\n * ```\n */\nexport function effect(\n\tdeps: readonly Node[],\n\tfn: EffectFn,\n\topts?: NodeOptions<unknown> & { partial?: boolean },\n): Node<unknown> {\n\tconst allowPartial = opts?.partial ?? false;\n\tconst wrapped: NodeFn = (batchData, actions, ctx) => {\n\t\t// Sentinel guard: hold effect until all deps have initialised.\n\t\t// Matches pre-wave2 framework gate behaviour. Use partial:true to allow\n\t\t// the effect to fire before all deps have delivered their first value.\n\t\tif (sentinelGuard(batchData, ctx, allowPartial)) {\n\t\t\tactions.down([[RESOLVED]]);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst data = batchData.map((batch, i) =>\n\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t);\n\t\treturn fn(data, actions, ctx) ?? undefined;\n\t};\n\treturn node(deps, wrapped, { describeKind: \"effect\", ...opts });\n}\n\n// ---------------------------------------------------------------------------\n// dynamicNode — track-proxy wrapper over `derived`\n// ---------------------------------------------------------------------------\n\n/**\n * Proxy handed to a {@link DynamicFn}. `track(dep)` returns the dep's\n * latest DATA payload, as delivered through the protocol. Reading from\n * `track` does NOT bypass the message protocol — it reads the internal\n * `DepRecord.prevData` (the stable end-of-previous-wave value) that\n * `_onDepMessage` already populated. If a dep has not yet sent DATA,\n * `track` returns `undefined`.\n */\nexport type TrackFn = (dep: Node) => unknown;\n\n/** User-level dynamicNode compute. */\nexport type DynamicFn<T> = (track: TrackFn, ctx: FnCtx) => T | undefined | null;\n\n/**\n * Sugar over `derived(...)` that exposes dep values via a `track(dep)`\n * proxy instead of positional `data[i]`. All declared `allDeps` participate\n * in wave tracking, so the first fn run waits for every dep to settle.\n * Unused deps that update just re-run fn; `equals` absorbs unchanged\n * outputs as RESOLVED.\n *\n * P3-compliant: `track(dep)` reads from the framework-managed\n * `DepRecord.prevData` populated by the protocol, never from\n * `dep.cache`.\n *\n * @example\n * ```ts\n * const a = state(1);\n * const b = state(10);\n * const sum = dynamicNode([a, b], (track) => (track(a) as number) + (track(b) as number));\n * ```\n */\nexport function dynamicNode<T = unknown>(\n\tallDeps: readonly Node[],\n\tfn: DynamicFn<T>,\n\topts?: NodeOptions<T> & { partial?: boolean },\n): Node<T> {\n\tconst depIndex = new Map<Node, number>();\n\tallDeps.forEach((d, i) => {\n\t\tdepIndex.set(d, i);\n\t});\n\treturn derived<T>(\n\t\tallDeps,\n\t\t// data[i] is already sugar-unwrapped to a scalar by derived()'s wrapper.\n\t\t(data, ctx) => {\n\t\t\tconst track: TrackFn = (dep) => {\n\t\t\t\tconst i = depIndex.get(dep);\n\t\t\t\tif (i == null) {\n\t\t\t\t\tthrow new Error(`dynamicNode: untracked dep \"${dep.name ?? \"<unnamed>\"}\"`);\n\t\t\t\t}\n\t\t\t\treturn data[i];\n\t\t\t};\n\t\t\treturn fn(track, ctx);\n\t\t},\n\t\topts,\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// pipe — left-to-right operator composition\n// ---------------------------------------------------------------------------\n// autoTrackNode — runtime dep discovery (Jotai/signals compat)\n// ---------------------------------------------------------------------------\n\n/**\n * Like {@link dynamicNode} but deps are discovered at runtime via `track()`\n * calls — no upfront `allDeps` array needed. Designed for pull-based compat\n * layers (Jotai atoms, TC39 Signals) where deps are unknown until fn runs.\n *\n * **Two-phase discovery:**\n * 1. fn runs. Each `track(dep)` for an unknown dep: subscribes immediately\n * via `_addDep`, returns `dep.cache` as a stub (P3 boundary exception).\n * Result is discarded (discovery run).\n * 2. New deps settle (DATA from subscribe handshake). Wave machinery\n * re-triggers fn. `track(dep)` now returns protocol-delivered `data[i]`.\n * If MORE unknown deps appear, repeat step 1.\n * 3. Converges when no new deps found → real run → `actions.emit(result)`.\n *\n * P3 violation is limited to discovery runs. Once all deps are known,\n * subsequent waves use protocol-delivered values exclusively.\n *\n * Re-entrance safety: `_addDep` subscribes immediately. If the dep delivers\n * DATA synchronously during fn execution, `_execFn`'s re-entrance guard\n * defers the re-run to after the current fn returns.\n *\n * @param opts - Optional {@link AutoTrackOptions}. Pass `{ partial: true }` to\n * allow fn to run before all known deps have delivered their first value\n * (useful for optional/secondary deps).\n *\n * @example\n * ```ts\n * const a = state(1), b = state(2);\n * const sum = autoTrackNode((track) => track(a) + track(b));\n * // deps [a, b] discovered automatically on first run\n * ```\n */\n/**\n * Options for {@link autoTrackNode}.\n */\nexport interface AutoTrackOptions<T> extends NodeOptions<T> {\n\t/**\n\t * When `true`, fn may run before all known deps have delivered their first\n\t * DATA. Unknown deps return `undefined` via `track()`, which the fn must\n\t * handle explicitly. Useful when some deps are \"nice-to-have\" — e.g. a\n\t * primary computation should continue while a secondary dep is still\n\t * initialising.\n\t *\n\t * When `false` (default), fn is held until every known dep has delivered at\n\t * least one DATA value — a RESOLVED is emitted for the wave instead.\n\t * This matches `derived()` semantics and is the correct default for\n\t * pull-based compat layers (Signals, Jotai) where all deps must be\n\t * initialised before the computation is meaningful.\n\t *\n\t * @default false\n\t */\n\tpartial?: boolean;\n}\n\nexport function autoTrackNode<T = unknown>(\n\tfn: (track: TrackFn, ctx: FnCtx) => T | undefined | null,\n\topts?: AutoTrackOptions<T>,\n): Node<T> {\n\tlet implRef: NodeImpl<T>;\n\tconst depIndexMap = new Map<Node, number>();\n\tconst allowPartial = opts?.partial ?? false;\n\n\tconst wrappedFn: NodeFn = (batchData, actions, ctx) => {\n\t\tlet foundNew = false;\n\t\tconst track: TrackFn = (dep) => {\n\t\t\tconst idx = depIndexMap.get(dep);\n\t\t\tif (idx !== undefined) {\n\t\t\t\t// Known dep — return latest protocol-delivered value.\n\t\t\t\t// batch non-null+non-empty → latest from this wave;\n\t\t\t\t// otherwise fall back to ctx.prevData (last known value).\n\t\t\t\tif (idx < batchData.length) {\n\t\t\t\t\tconst batch = batchData[idx];\n\t\t\t\t\tif (batch != null && batch.length > 0) return batch.at(-1);\n\t\t\t\t\treturn ctx.prevData[idx];\n\t\t\t\t}\n\t\t\t\treturn dep.cache;\n\t\t\t}\n\t\t\t// Unknown dep — discovery phase.\n\t\t\tfoundNew = true;\n\t\t\tconst newIdx = implRef._addDep(dep);\n\t\t\tdepIndexMap.set(dep, newIdx);\n\t\t\treturn dep.cache; // P3 boundary exception (discovery stub)\n\t\t};\n\n\t\t// Sentinel guard (skipped when partial:true): if any known dep has never\n\t\t// delivered DATA (no DATA this wave AND ctx.prevData[idx] === undefined), emit RESOLVED\n\t\t// and defer. Mirrors derived()'s guard for the same sequential-handshake\n\t\t// scenario: when a node re-activates outside a batch and dep A delivers\n\t\t// synchronously before dep B is even subscribed, this holds fn until all\n\t\t// known deps have initialised rather than running with B=undefined.\n\t\t// Uses ctx.prevData[idx] === undefined — the protocol sentinel for\n\t\t// \"dep never sent DATA\". null is valid DATA and won't trigger this.\n\t\t// Only active when depIndexMap is non-empty (initial discovery runs are\n\t\t// unaffected) and when partial:false (default).\n\t\tif (!allowPartial && depIndexMap.size > 0) {\n\t\t\tfor (const [, idx] of depIndexMap) {\n\t\t\t\tif (idx < batchData.length) {\n\t\t\t\t\tconst batch = batchData[idx];\n\t\t\t\t\tif (!(batch != null && batch.length > 0) && ctx.prevData[idx] === undefined) {\n\t\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = fn(track, ctx);\n\t\t\tif (!foundNew) {\n\t\t\t\t// Real run — all deps known, protocol-delivered values.\n\t\t\t\tactions.emit(result);\n\t\t\t\t// Clear any stale discovery error from a prior run.\n\t\t\t\tif (ctx.store.__autoTrackLastDiscoveryError != null) {\n\t\t\t\t\tdelete ctx.store.__autoTrackLastDiscoveryError;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discovery run — result discarded. New deps are subscribed via\n\t\t\t// _addDep. Their DATA delivery triggers _maybeRunFnOnSettlement\n\t\t\t// via the _pendingRerun mechanism, which will re-call fn.\n\t\t} catch (err) {\n\t\t\tif (!foundNew) throw err;\n\t\t\t// Discovery run threw — most likely a stale `.cache` read (P3\n\t\t\t// boundary exception), which the protocol-delivered retry will\n\t\t\t// not hit. Preserve the error on `ctx.store` for inspection; if\n\t\t\t// the retry succeeds, the flag is cleared above. If fn has a\n\t\t\t// real bug unrelated to cache, the non-discovery retry will\n\t\t\t// re-throw it out of `_execFn`.\n\t\t\tctx.store.__autoTrackLastDiscoveryError = err;\n\t\t}\n\t\treturn undefined;\n\t};\n\n\timplRef = new NodeImpl<T>([], wrappedFn, {\n\t\tdescribeKind: \"derived\",\n\t\t...opts,\n\t});\n\treturn implRef;\n}\n\n// ---------------------------------------------------------------------------\n// pipe — left-to-right operator composition\n// ---------------------------------------------------------------------------\n\n/** Unary operator used by {@link pipe}. */\nexport type PipeOperator = (n: Node) => Node;\n\n/**\n * Composes unary operators left-to-right; returns the final node.\n *\n * @example\n * ```ts\n * const out = pipe(\n * source,\n * (n) => map(n, (x) => x + 1),\n * (n) => filter(n, (x) => x > 0),\n * );\n * ```\n */\nexport function pipe(source: Node, ...ops: PipeOperator[]): Node {\n\tlet current = source;\n\tfor (const op of ops) current = op(current);\n\treturn current;\n}\n","/**\n * Core reactive sources, sinks, and utilities (roadmap §2.3).\n *\n * Each API returns a {@link Node} built with {@link node}, {@link producer},\n * {@link derived}, or {@link effect} — no second protocol.\n *\n * Protocol/system/ingest adapters (fromHTTP, fromWebSocket, fromKafka, etc.)\n * live in {@link ./adapters.ts}.\n */\n\nimport { wallClockNs } from \"../core/clock.js\";\nimport { COMPLETE, DATA, DIRTY, ERROR, RESOLVED } from \"../core/messages.js\";\nimport { type Node, type NodeOptions, type NodeSink, node } from \"../core/node.js\";\nimport { producer, state } from \"../core/sugar.js\";\nimport { type CronSchedule, matchesCron, parseCron } from \"./cron.js\";\n\ntype ExtraOpts = Omit<NodeOptions<unknown>, \"describeKind\">;\n\nfunction sourceOpts<T = unknown>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"producer\", ...opts } as NodeOptions<T>;\n}\n\n/** Options for {@link fromTimer} / {@link fromPromise} / {@link fromAsyncIter}. */\nexport type AsyncSourceOpts = ExtraOpts & { signal?: AbortSignal };\n\n/**\n * Values accepted by {@link fromAny}.\n *\n * @category extra\n */\nexport type NodeInput<T> = Node<T> | PromiseLike<T> | AsyncIterable<T> | Iterable<T> | T;\n\n/** Options for {@link fromCron}. */\nexport type FromCronOptions = ExtraOpts & {\n\t/** Polling interval in ms. Default `60_000`. */\n\ttickMs?: number;\n\t/** Output format: `\"timestamp_ns\"` (default) emits wall-clock nanoseconds; `\"date\"` emits a `Date` object. */\n\toutput?: \"timestamp_ns\" | \"date\";\n};\n\n/** DOM-style event target (browser or `node:events`). */\nexport type EventTargetLike = {\n\taddEventListener(\n\t\ttype: string,\n\t\tlistener: (ev: unknown) => void,\n\t\toptions?: boolean | { capture?: boolean; passive?: boolean; once?: boolean },\n\t): void;\n\tremoveEventListener(\n\t\ttype: string,\n\t\tlistener: (ev: unknown) => void,\n\t\toptions?: boolean | { capture?: boolean; passive?: boolean; once?: boolean },\n\t): void;\n};\n\n/** @internal Shared with adapters.ts and sources-fs.ts for glob matching. */\nexport function escapeRegexChar(ch: string): string {\n\treturn /[\\\\^$+?.()|[\\]{}]/.test(ch) ? `\\\\${ch}` : ch;\n}\n\n/** @internal */\nexport function globToRegExp(glob: string): RegExp {\n\tlet out = \"^\";\n\tfor (let i = 0; i < glob.length; i += 1) {\n\t\tconst ch = glob[i];\n\t\tif (ch === \"*\") {\n\t\t\tconst next = glob[i + 1];\n\t\t\tif (next === \"*\") {\n\t\t\t\tout += \".*\";\n\t\t\t\ti += 1;\n\t\t\t} else {\n\t\t\t\tout += \"[^/]*\";\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tout += escapeRegexChar(ch);\n\t}\n\tout += \"$\";\n\treturn new RegExp(out);\n}\n\n/** @internal */\nexport function matchesAnyPattern(path: string, patterns: RegExp[]): boolean {\n\tfor (const pattern of patterns) {\n\t\tif (pattern.test(path)) return true;\n\t}\n\treturn false;\n}\n\nfunction wrapSubscribeHook<T>(inner: Node<T>, before: (sink: NodeSink) => void): Node<T> {\n\t// node() passthrough instead of derived([inner], ([v]) => v) — derived uses\n\t// .at(-1) and would drop intermediate values from multi-DATA batches (D1 gap).\n\tconst wrapper = node<T>(\n\t\t[inner as Node],\n\t\t(data, a) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0) a.emit(v as T);\n\t\t},\n\t\t{ describeKind: \"derived\", initial: inner.cache as T },\n\t);\n\tconst origSubscribe = wrapper.subscribe.bind(wrapper);\n\t(wrapper as { subscribe: typeof wrapper.subscribe }).subscribe = (sink, actor) => {\n\t\tbefore(sink);\n\t\treturn origSubscribe(sink, actor);\n\t};\n\treturn wrapper;\n}\n\n/**\n * Builds a timer-driven source: one-shot (first tick then `COMPLETE`) or periodic (`0`, `1`, `2`, …).\n *\n * @param ms - Milliseconds before the first emission.\n * @param opts - Producer options plus optional `period` for repeating ticks and optional `signal` (`AbortSignal`) to cancel with `ERROR`.\n * @returns `Node<number>` — tick counter from `0`; teardown clears timers.\n *\n * @example\n * ```ts\n * import { fromTimer } from \"@graphrefly/graphrefly-ts\";\n *\n * fromTimer(250, { period: 1_000 });\n * ```\n *\n * @category extra\n */\nexport function fromTimer(ms: number, opts?: AsyncSourceOpts & { period?: number }): Node<number> {\n\tconst { signal, period, ...rest } = opts ?? {};\n\treturn producer<number>((a) => {\n\t\tlet done = false;\n\t\tlet count = 0;\n\t\tlet t: ReturnType<typeof setTimeout> | undefined;\n\t\tlet iv: ReturnType<typeof setInterval> | undefined;\n\t\tconst cleanup = () => {\n\t\t\tdone = true;\n\t\t\tif (t !== undefined) clearTimeout(t);\n\t\t\tif (iv !== undefined) clearInterval(iv);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t};\n\t\tconst finish = () => {\n\t\t\tif (done) return;\n\t\t\tif (period != null) {\n\t\t\t\ta.emit(count++);\n\t\t\t\tiv = setInterval(() => {\n\t\t\t\t\tif (done) return;\n\t\t\t\t\ta.emit(count++);\n\t\t\t\t}, period);\n\t\t\t} else {\n\t\t\t\t// One-shot: mark done, emit, complete synchronously.\n\t\t\t\t// a.emit() delivers DATA to downstream synchronously before\n\t\t\t\t// COMPLETE arrives — no queueMicrotask needed.\n\t\t\t\tdone = true;\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\ta.emit(count++);\n\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t}\n\t\t};\n\t\tconst onAbort = () => {\n\t\t\tif (done) return;\n\t\t\tcleanup();\n\t\t\ta.down([[ERROR, signal!.reason]]);\n\t\t};\n\t\tif (signal?.aborted) {\n\t\t\tonAbort();\n\t\t\treturn;\n\t\t}\n\t\tt = setTimeout(finish, ms);\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\treturn cleanup;\n\t}, sourceOpts(rest));\n}\n\n/**\n * Animation-frame-driven source. Emits on every `requestAnimationFrame` tick,\n * yielding the frame timestamp (DOMHighResTimeStamp, ms since navigation).\n *\n * Use instead of `fromTimer({ period: 16 })` when animation smoothness matters.\n * In a real browser, `requestAnimationFrame` synchronizes with the display\n * refresh. The source keeps ticking even when the tab is hidden — it\n * transparently switches to `setTimeout` while the tab is backgrounded (so\n * downstream state updates continue) and returns to `requestAnimationFrame`\n * when the tab regains focus.\n *\n * When `requestAnimationFrame` is unavailable (Node test environments, SSR),\n * this falls back to `setTimeout(~16ms)` unconditionally. Abortable via\n * `signal` (emits `ERROR`).\n *\n * @example\n * ```ts\n * import { fromRaf, derived } from \"@graphrefly/graphrefly-ts\";\n *\n * const frame = fromRaf();\n * const bouncingX = derived([frame], ([t]) => 50 + 40 * Math.sin((t as number) * 0.001));\n * ```\n *\n * @category extra\n */\nexport function fromRaf(opts?: AsyncSourceOpts): Node<number> {\n\tconst { signal, ...rest } = opts ?? {};\n\treturn producer<number>((a) => {\n\t\tlet done = false;\n\t\tlet rafId: number | undefined;\n\t\tlet fallbackTimer: ReturnType<typeof setTimeout> | undefined;\n\t\tlet abortListenerAdded = false;\n\t\tlet visibilityListenerAdded = false;\n\n\t\tconst raf: typeof requestAnimationFrame | undefined =\n\t\t\ttypeof requestAnimationFrame === \"function\" ? requestAnimationFrame : undefined;\n\t\tconst caf: typeof cancelAnimationFrame | undefined =\n\t\t\ttypeof cancelAnimationFrame === \"function\" ? cancelAnimationFrame : undefined;\n\t\tconst doc: Document | undefined = typeof document !== \"undefined\" ? document : undefined;\n\n\t\tconst clearPending = () => {\n\t\t\tif (rafId !== undefined && caf) caf(rafId);\n\t\t\tif (fallbackTimer !== undefined) clearTimeout(fallbackTimer);\n\t\t\trafId = undefined;\n\t\t\tfallbackTimer = undefined;\n\t\t};\n\t\tconst cleanup = () => {\n\t\t\tdone = true;\n\t\t\tclearPending();\n\t\t\tif (abortListenerAdded) {\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tabortListenerAdded = false;\n\t\t\t}\n\t\t\tif (visibilityListenerAdded && doc) {\n\t\t\t\tdoc.removeEventListener(\"visibilitychange\", onVisibilityChange);\n\t\t\t\tvisibilityListenerAdded = false;\n\t\t\t}\n\t\t};\n\t\tconst onAbort = () => {\n\t\t\tif (done) return;\n\t\t\tcleanup();\n\t\t\ta.down([[ERROR, signal!.reason]]);\n\t\t};\n\t\tconst tick = (now: number) => {\n\t\t\tif (done) return;\n\t\t\ta.emit(now);\n\t\t\tscheduleNext();\n\t\t};\n\t\tconst scheduleNext = () => {\n\t\t\tif (done) return;\n\t\t\t// Prefer rAF for display-synced ticks when the tab is visible; when\n\t\t\t// hidden, rAF is throttled to ~0 by the browser, so fall back to\n\t\t\t// setTimeout so downstream state continues updating.\n\t\t\tif (raf && (!doc || doc.visibilityState !== \"hidden\")) {\n\t\t\t\trafId = raf(tick);\n\t\t\t} else {\n\t\t\t\tfallbackTimer = setTimeout(() => tick(performance.now()), 16);\n\t\t\t}\n\t\t};\n\t\tconst onVisibilityChange = () => {\n\t\t\tif (done) return;\n\t\t\t// Cancel any pending schedule and re-schedule via the path now\n\t\t\t// appropriate for the current visibility state.\n\t\t\tclearPending();\n\t\t\tscheduleNext();\n\t\t};\n\n\t\tif (signal?.aborted) {\n\t\t\tonAbort();\n\t\t\treturn cleanup;\n\t\t}\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\tabortListenerAdded = signal !== undefined;\n\t\tif (doc && raf) {\n\t\t\tdoc.addEventListener(\"visibilitychange\", onVisibilityChange);\n\t\t\tvisibilityListenerAdded = true;\n\t\t}\n\t\tscheduleNext();\n\t\treturn cleanup;\n\t}, sourceOpts(rest));\n}\n\n/**\n * Polls on an interval; when the current minute matches a 5-field cron expression, emits once (see {@link parseCron}).\n *\n * @param expr - Cron string (`min hour dom month dow`).\n * @param opts - Producer options plus `tickMs` (default `60_000`) and `output` (`timestamp_ns` default, or `date` for `Date` values).\n * @returns `Node<number>` (nanosecond timestamp) or `Node<Date>` when `output: \"date\"`.\n *\n * @example\n * ```ts\n * import { fromCron } from \"@graphrefly/graphrefly-ts\";\n *\n * fromCron(\"0 9 * * 1\");\n * ```\n *\n * @category extra\n */\nexport function fromCron(expr: string, opts?: FromCronOptions & { output: \"date\" }): Node<Date>;\nexport function fromCron(expr: string, opts?: FromCronOptions): Node<number>;\nexport function fromCron(expr: string, opts?: FromCronOptions): Node<number | Date> {\n\tconst schedule: CronSchedule = parseCron(expr);\n\tconst { tickMs: tickOpt, output, ...rest } = opts ?? {};\n\tconst tickMs = tickOpt ?? 60_000;\n\tconst emitDate = output === \"date\";\n\treturn producer<number | Date>(\n\t\t(a) => {\n\t\t\tlet lastFiredKey = -1;\n\t\t\tconst check = () => {\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst key =\n\t\t\t\t\tnow.getFullYear() * 100_000_000 +\n\t\t\t\t\t(now.getMonth() + 1) * 1_000_000 +\n\t\t\t\t\tnow.getDate() * 10_000 +\n\t\t\t\t\tnow.getHours() * 100 +\n\t\t\t\t\tnow.getMinutes();\n\t\t\t\tif (key !== lastFiredKey && matchesCron(schedule, now)) {\n\t\t\t\t\tlastFiredKey = key;\n\t\t\t\t\ta.emit(emitDate ? now : wallClockNs());\n\t\t\t\t}\n\t\t\t};\n\t\t\tcheck();\n\t\t\tconst id = setInterval(check, tickMs);\n\t\t\treturn () => clearInterval(id);\n\t\t},\n\t\t{ ...sourceOpts(rest), name: rest.name ?? `cron:${expr}` },\n\t);\n}\n\n/**\n * Wraps a DOM-style `addEventListener` target; each event becomes a `DATA` emission.\n *\n * @param target - Object with `addEventListener` / `removeEventListener`.\n * @param type - Event name (e.g. `\"click\"`).\n * @param opts - Producer options plus listener options (`capture`, `passive`, `once`).\n * @returns `Node<T>` — event payloads; teardown removes the listener.\n *\n * @example\n * ```ts\n * import { fromEvent } from \"@graphrefly/graphrefly-ts\";\n *\n * fromEvent(document.body, \"click\");\n * ```\n *\n * @category extra\n */\nexport function fromEvent<T = unknown>(\n\ttarget: EventTargetLike,\n\ttype: string,\n\topts?: ExtraOpts & { capture?: boolean; passive?: boolean; once?: boolean },\n): Node<T> {\n\tconst { capture, passive, once, ...rest } = opts ?? {};\n\treturn producer<T>((a) => {\n\t\tconst handler = (e: unknown) => {\n\t\t\ta.emit(e as T);\n\t\t};\n\t\tconst options = { capture, passive, once };\n\t\ttarget.addEventListener(type, handler, options);\n\t\treturn () => target.removeEventListener(type, handler, options);\n\t}, sourceOpts(rest));\n}\n\n/**\n * Drains a synchronous iterable; each item is `DATA`, then `COMPLETE`, or `ERROR` if iteration throws.\n *\n * @param iterable - Values to emit in order.\n * @param opts - Optional producer options.\n * @returns `Node<T>` — one emission per element.\n *\n * @example\n * ```ts\n * import { fromIter } from \"@graphrefly/graphrefly-ts\";\n *\n * fromIter([1, 2, 3]);\n * ```\n *\n * @category extra\n */\nexport function fromIter<T>(iterable: Iterable<T>, opts?: ExtraOpts): Node<T> {\n\treturn producer<T>((a) => {\n\t\tlet cancelled = false;\n\t\ttry {\n\t\t\tfor (const x of iterable) {\n\t\t\t\tif (cancelled) return;\n\t\t\t\ta.emit(x);\n\t\t\t}\n\t\t\tif (!cancelled) a.down([[COMPLETE]]);\n\t\t} catch (e) {\n\t\t\tif (!cancelled) a.down([[ERROR, e]]);\n\t\t}\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, sourceOpts(opts));\n}\n\nfunction isThenable(x: unknown): x is PromiseLike<unknown> {\n\treturn x != null && typeof (x as PromiseLike<unknown>).then === \"function\";\n}\n\n/**\n * Lifts a Promise (or thenable) to a single-value stream: one `DATA` then `COMPLETE`, or `ERROR` on rejection.\n *\n * @param p - Promise to await.\n * @param opts - Producer options plus optional `signal` for abort → `ERROR` with reason.\n * @returns `Node<T>` — settles once.\n *\n * @example\n * ```ts\n * import { fromPromise } from \"@graphrefly/graphrefly-ts\";\n *\n * fromPromise(Promise.resolve(42));\n * ```\n *\n * @category extra\n */\nexport function fromPromise<T>(p: Promise<T> | PromiseLike<T>, opts?: AsyncSourceOpts): Node<T> {\n\tconst { signal, ...rest } = opts ?? {};\n\treturn producer<T>((a) => {\n\t\tlet settled = false;\n\t\tconst onAbort = () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\ta.down([[ERROR, signal!.reason]]);\n\t\t};\n\t\tif (signal?.aborted) {\n\t\t\tonAbort();\n\t\t\treturn;\n\t\t}\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\tvoid Promise.resolve(p).then(\n\t\t\t(v) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\ta.emit(v as T);\n\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t},\n\t\t\t(e) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\ta.down([[ERROR, e]]);\n\t\t\t},\n\t\t);\n\t\treturn () => {\n\t\t\tsettled = true;\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t};\n\t}, sourceOpts(rest));\n}\n\n/**\n * Reads an async iterable; each `next()` value becomes `DATA`; `COMPLETE` when done; `ERROR` on failure.\n *\n * @param iterable - Async source (`for await` shape).\n * @param opts - Producer options plus optional `signal` to abort the pump.\n * @returns `Node<T>` — async pull stream.\n *\n * @example\n * ```ts\n * import { fromAsyncIter } from \"@graphrefly/graphrefly-ts\";\n *\n * async function* gen() {\n * yield 1;\n * }\n * fromAsyncIter(gen());\n * ```\n *\n * @category extra\n */\nexport function fromAsyncIter<T>(iterable: AsyncIterable<T>, opts?: AsyncSourceOpts): Node<T> {\n\tconst { signal: outerSignal, ...rest } = opts ?? {};\n\treturn producer<T>((a) => {\n\t\tconst ac = new AbortController();\n\t\tconst onOuterAbort = () => ac.abort(outerSignal?.reason);\n\t\tif (outerSignal?.aborted) {\n\t\t\tac.abort(outerSignal.reason);\n\t\t} else {\n\t\t\touterSignal?.addEventListener(\"abort\", onOuterAbort, { once: true });\n\t\t}\n\t\tconst signal = outerSignal ?? ac.signal;\n\t\tlet cancelled = false;\n\t\tconst it = iterable[Symbol.asyncIterator]();\n\t\t// Each pump() call chains directly into the next via Promise.then —\n\t\t// no queueMicrotask needed; Promise resolution already yields to the\n\t\t// microtask queue. COMPLETE is delivered synchronously after the last\n\t\t// value, same as fromIter semantics.\n\t\tconst pump = (): void => {\n\t\t\tif (cancelled || signal.aborted) return;\n\t\t\tvoid Promise.resolve(it.next()).then(\n\t\t\t\t(step) => {\n\t\t\t\t\tif (cancelled || signal.aborted) return;\n\t\t\t\t\tif (step.done) {\n\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\ta.emit(step.value as T);\n\t\t\t\t\tpump();\n\t\t\t\t},\n\t\t\t\t(e) => {\n\t\t\t\t\tif (!cancelled && !signal.aborted) a.down([[ERROR, e]]);\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\t\tpump();\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\touterSignal?.removeEventListener(\"abort\", onOuterAbort);\n\t\t\tac.abort();\n\t\t\tvoid Promise.resolve(it.return?.()).catch(() => undefined);\n\t\t};\n\t}, sourceOpts(rest));\n}\n\nfunction isNode(x: unknown): x is Node {\n\treturn (\n\t\tx != null &&\n\t\ttypeof x === \"object\" &&\n\t\t\"cache\" in x &&\n\t\ttypeof (x as Node).subscribe === \"function\"\n\t);\n}\n\n/**\n * Coerces a value to a `Node` by shape: existing `Node` passthrough, thenable → {@link fromPromise},\n * async iterable → {@link fromAsyncIter}, sync iterable → {@link fromIter}, else scalar → {@link of}.\n *\n * @param input - Any value to wrap.\n * @param opts - Passed through when a Promise/async path is chosen.\n * @returns `Node` of the inferred element type.\n *\n * @example\n * ```ts\n * import { fromAny, state } from \"@graphrefly/graphrefly-ts\";\n *\n * fromAny(state(1));\n * fromAny(Promise.resolve(2));\n * ```\n *\n * @category extra\n */\nexport function fromAny<T>(input: NodeInput<T>, opts?: AsyncSourceOpts): Node<T> {\n\tif (isNode(input)) {\n\t\treturn input as Node<T>;\n\t}\n\tif (isThenable(input)) {\n\t\treturn fromPromise(input as PromiseLike<T>, opts);\n\t}\n\tif (input !== null && input !== undefined) {\n\t\tconst candidate = input as { [Symbol.asyncIterator]?: unknown; [Symbol.iterator]?: unknown };\n\t\tif (typeof candidate[Symbol.asyncIterator] === \"function\") {\n\t\t\treturn fromAsyncIter(input as AsyncIterable<T>, opts);\n\t\t}\n\t\tif (typeof candidate[Symbol.iterator] === \"function\") {\n\t\t\treturn fromIter(input as Iterable<T>, opts);\n\t\t}\n\t}\n\t// scalar fallback\n\treturn of(input as T);\n}\n\n/**\n * Emits each argument as `DATA` in order, then `COMPLETE` (implemented via {@link fromIter}).\n *\n * @param values - Values to emit.\n * @returns `Node<T>` — finite sequence.\n *\n * @example\n * ```ts\n * import { of } from \"@graphrefly/graphrefly-ts\";\n *\n * of(1, 2, 3);\n * ```\n *\n * @category extra\n */\nexport function of<T>(...values: T[]): Node<T> {\n\treturn fromIter(values, undefined);\n}\n\n/**\n * Completes immediately with no `DATA` (cold `EMPTY` analogue).\n *\n * @param opts - Optional producer options.\n * @returns `Node<T>` — terminal `COMPLETE` only.\n *\n * @example\n * ```ts\n * import { empty } from \"@graphrefly/graphrefly-ts\";\n *\n * empty();\n * ```\n *\n * @category extra\n */\nexport function empty<T = never>(opts?: ExtraOpts): Node<T> {\n\treturn producer<T>((a) => {\n\t\ta.down([[COMPLETE]]);\n\t\treturn undefined;\n\t}, sourceOpts(opts));\n}\n\n/**\n * Never emits and never completes until teardown (cold `NEVER` analogue).\n *\n * @param opts - Optional producer options.\n * @returns `Node<T>` — silent until unsubscribed.\n *\n * @example\n * ```ts\n * import { never } from \"@graphrefly/graphrefly-ts\";\n *\n * never();\n * ```\n *\n * @category extra\n */\nexport function never<T = never>(opts?: ExtraOpts): Node<T> {\n\treturn producer<T>(() => undefined, sourceOpts(opts));\n}\n\n/**\n * Emits `ERROR` as soon as the producer starts (cold error source).\n *\n * @param err - Error payload forwarded as `ERROR` data.\n * @param opts - Optional producer options.\n * @returns `Node<never>` — terminates with `ERROR`.\n *\n * @example\n * ```ts\n * import { throwError } from \"@graphrefly/graphrefly-ts\";\n *\n * throwError(new Error(\"fail\"));\n * ```\n *\n * @category extra\n */\nexport function throwError(err: unknown, opts?: ExtraOpts): Node<never> {\n\treturn producer<never>((a) => {\n\t\ta.down([[ERROR, err]]);\n\t\treturn undefined;\n\t}, sourceOpts(opts));\n}\n\n/**\n * Subscribes immediately and runs `fn` for each upstream `DATA`; returns unsubscribe.\n *\n * @param source - Upstream node.\n * @param fn - Side effect per value.\n * @param opts - Effect node options.\n * @returns Unsubscribe function (idempotent).\n *\n * @example\n * ```ts\n * import { forEach, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const u = forEach(state(1), (v) => console.log(v));\n * u();\n * ```\n *\n * @category extra\n */\nexport function forEach<T>(source: Node<T>, fn: (value: T) => void, opts?: ExtraOpts): () => void {\n\tconst inner = node(\n\t\t[source as Node],\n\t\t(data, _actions) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 != null && batch0.length > 0) {\n\t\t\t\tfor (const v of batch0) fn(v as T);\n\t\t\t}\n\t\t},\n\t\t{ describeKind: \"effect\", ...opts } as NodeOptions,\n\t);\n\treturn inner.subscribe(() => {});\n}\n\n/**\n * Buffers every `DATA`; on upstream `COMPLETE` emits one `DATA` with the full array then `COMPLETE`.\n *\n * @param source - Upstream node.\n * @param opts - Optional node options (derived describe kind).\n * @returns `Node<T[]>` — single array emission before completion.\n *\n * @example\n * ```ts\n * import { of, toArray } from \"@graphrefly/graphrefly-ts\";\n *\n * toArray(of(1, 2, 3));\n * ```\n *\n * @category extra\n */\nexport function toArray<T>(source: Node<T>, opts?: ExtraOpts): Node<T[]> {\n\treturn node<T[]>(\n\t\t[source as Node],\n\t\t(data, actions, ctx) => {\n\t\t\tif (!ctx.store.buf) ctx.store.buf = [];\n\t\t\tconst buf = ctx.store.buf as T[];\n\t\t\t// Accumulate DATA first — must happen before the COMPLETE check so\n\t\t\t// that a same-wave DATA+COMPLETE batch (e.g. fromTimer one-shot,\n\t\t\t// fromIter last item) is included in the emitted array.\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 != null && batch0.length > 0) {\n\t\t\t\tfor (const v of batch0) buf.push(v as T);\n\t\t\t}\n\t\t\t// COMPLETE: emit accumulated array then complete.\n\t\t\t// ERROR: autoError propagates; do NOT emit the partial buffer.\n\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\tactions.emit([...buf]);\n\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// RESOLVED wave: propagate RESOLVED. Covers first-wave case; after first\n\t\t\t// call the pre-fn skip handles this automatically.\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t\t...opts,\n\t\t} as NodeOptions<T[]>,\n\t);\n}\n\n/**\n * Multicasts upstream: one subscription to `source` while this wrapper has subscribers (via {@link producer}).\n *\n * @param source - Upstream node to share.\n * @param opts - Producer options; `initial` seeds from `source.cache` when set by factory.\n * @returns `Node<T>` — hot ref-counted bridge.\n *\n * @example\n * ```ts\n * import { share, state } from \"@graphrefly/graphrefly-ts\";\n *\n * share(state(0));\n * ```\n *\n * @category extra\n */\nexport function share<T>(source: Node<T>, opts?: ExtraOpts): Node<T> {\n\treturn producer<T>(\n\t\t(a) =>\n\t\t\tsource.subscribe((msgs) => {\n\t\t\t\ta.down(msgs);\n\t\t\t}),\n\t\t{ ...sourceOpts<T>(opts), initial: source.cache },\n\t);\n}\n\n/**\n * Like {@link share} with a bounded replay buffer: new subscribers receive the last `bufferSize`\n * `DATA` payloads (as separate batches) before live updates.\n *\n * @param source - Upstream node.\n * @param bufferSize - Maximum past values to replay (≥ 1).\n * @param opts - Producer options.\n * @returns `Node<T>` — multicast with replay on subscribe.\n *\n * @example\n * ```ts\n * import { replay, state } from \"@graphrefly/graphrefly-ts\";\n *\n * replay(state(0), 3);\n * ```\n *\n * @category extra\n */\nexport function replay<T>(source: Node<T>, bufferSize: number, opts?: ExtraOpts): Node<T> {\n\tif (bufferSize < 1) throw new RangeError(\"replay expects bufferSize >= 1\");\n\tconst buf: T[] = [];\n\tconst inner = producer<T>(\n\t\t(a) =>\n\t\t\tsource.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\tbuf.push(m[1] as T);\n\t\t\t\t\t\tif (buf.length > bufferSize) buf.shift();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ta.down(msgs);\n\t\t\t}),\n\t\t{ ...sourceOpts<T>(opts), initial: source.cache },\n\t);\n\treturn wrapSubscribeHook(inner, (sink) => {\n\t\tfor (const v of buf) {\n\t\t\tsink([[DATA, v]]);\n\t\t}\n\t});\n}\n\n/**\n * {@link replay} with `bufferSize === 1` — replays the latest `DATA` to new subscribers.\n *\n * @param source - Upstream node.\n * @param opts - Producer options.\n * @returns `Node<T>` — share + last-value replay.\n *\n * @example\n * ```ts\n * import { cached, state } from \"@graphrefly/graphrefly-ts\";\n *\n * cached(state(0));\n * ```\n *\n * @category extra\n */\nexport function cached<T>(source: Node<T>, opts?: ExtraOpts): Node<T> {\n\treturn replay(source, 1, opts);\n}\n\n/**\n * Converts the first `DATA` on `source` into a Promise; rejects on `ERROR` or `COMPLETE` without data.\n *\n * **Important:** This subscribes and waits for a **future** emission. Data that\n * has already flowed is gone and will not be seen. Call this *before* the upstream\n * emits, or use `source.cache` / `source.status` for already-cached state.\n * See COMPOSITION-GUIDE §2 (subscription ordering).\n *\n * @param source - Node to read once.\n * @returns Promise of the first value.\n *\n * @example\n * ```ts\n * import { firstValueFrom, of } from \"@graphrefly/graphrefly-ts\";\n *\n * await firstValueFrom(of(42));\n * ```\n *\n * @category extra\n */\nexport function firstValueFrom<T>(source: Node<T>): Promise<T> {\n\treturn new Promise<T>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tlet shouldUnsub = false;\n\t\tlet unsub: (() => void) | undefined;\n\t\tunsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (settled) return;\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tresolve(m[1] as T);\n\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (m[0] === ERROR) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(m[1]);\n\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(new Error(\"completed without DATA\"));\n\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif (shouldUnsub) {\n\t\t\tunsub?.();\n\t\t\tunsub = undefined;\n\t\t}\n\t});\n}\n\n/**\n * Wait for the first DATA value from `source` that satisfies `predicate`.\n *\n * Subscribes directly and resolves on the first DATA value where\n * `predicate` returns true. Reactive, no polling. Use in tests and\n * bridging code where you need a single matching value as a Promise.\n *\n * **Important:** This only captures **future** emissions — data that has\n * already flowed through the node is gone. Call this *before* the upstream\n * emits. For already-cached values, use `source.cache` / `source.status`.\n * See COMPOSITION-GUIDE §2 (subscription ordering).\n *\n * ```ts\n * const val = await firstWhere(strategy.node, snap => snap.size > 0);\n * ```\n *\n * @category extra\n */\nexport function firstWhere<T>(source: Node<T>, predicate: (value: T) => boolean): Promise<T> {\n\treturn new Promise<T>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tlet shouldUnsub = false;\n\t\tlet unsub: (() => void) | undefined;\n\t\tunsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (settled) return;\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tconst v = m[1] as T;\n\t\t\t\t\tif (predicate(v)) {\n\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\tresolve(v);\n\t\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\t\tunsub();\n\t\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (m[0] === ERROR) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(m[1]);\n\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(new Error(\"completed without matching value\"));\n\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif (shouldUnsub) {\n\t\t\tunsub?.();\n\t\t\tunsub = undefined;\n\t\t}\n\t});\n}\n\n// ——————————————————————————————————————————————————————————————\n// RxJS-compatible aliases\n// ——————————————————————————————————————————————————————————————\n\n/**\n * RxJS-named alias for {@link replay} — multicast with a replay buffer of size `bufferSize`.\n *\n * @param source - Upstream node.\n * @param bufferSize - Replay depth (≥ 1).\n * @param opts - Producer options.\n * @returns Same behavior as `replay`.\n *\n * @example\n * ```ts\n * import { shareReplay, state } from \"@graphrefly/graphrefly-ts\";\n *\n * shareReplay(state(0), 5);\n * ```\n *\n * @category extra\n */\nexport const shareReplay = replay;\n\n// ---------------------------------------------------------------------------\n// keepalive\n// ---------------------------------------------------------------------------\n\n/**\n * Activate a compute node's upstream wiring without a real sink.\n *\n * Derived/effect nodes are lazy — they don't compute until at least one\n * subscriber exists (COMPOSITION-GUIDE §5). `keepalive` subscribes with an\n * empty sink so the node stays wired for `.cache` and upstream propagation.\n *\n * Returns the unsubscribe handle. Common usage:\n * `graph.addDisposer(keepalive(node))`.\n *\n * @category extra\n */\nexport function keepalive(n: Node<unknown>): () => void {\n\treturn n.subscribe(() => {});\n}\n\n// ---------------------------------------------------------------------------\n// reactiveCounter\n// ---------------------------------------------------------------------------\n\n/** Bundle returned by {@link reactiveCounter}. */\nexport type ReactiveCounterBundle = {\n\t/** Reactive node holding the current count. */\n\treadonly node: Node<number>;\n\t/** Increment by 1. Returns `false` if cap would be exceeded. */\n\tincrement(): boolean;\n\t/** Current count (synchronous read). */\n\tget(): number;\n\t/** Whether the counter has reached its cap. */\n\tatCap(): boolean;\n};\n\n/**\n * Reactive counter with a cap — the building block for circuit breakers.\n *\n * Wraps a `state(0)` node with `increment()` that respects a maximum.\n * The `node` is subscribable and composable like any reactive node. When\n * the cap is reached, `increment()` returns `false`.\n *\n * ```ts\n * const retries = reactiveCounter(10);\n * retries.increment(); // true — count is now 1\n * retries.node.subscribe(...); // reactive updates\n * retries.atCap(); // false\n * ```\n *\n * @param cap - Maximum value (inclusive). 0 = no increments allowed.\n * @category extra\n */\nexport function reactiveCounter(cap: number): ReactiveCounterBundle {\n\tconst counter = state(0);\n\treturn {\n\t\tnode: counter,\n\t\tincrement() {\n\t\t\tconst current = counter.cache ?? 0;\n\t\t\tif (current >= cap) return false;\n\t\t\tcounter.down([[DIRTY], [DATA, current + 1]]);\n\t\t\treturn true;\n\t\t},\n\t\tget() {\n\t\t\treturn counter.cache ?? 0;\n\t\t},\n\t\tatCap() {\n\t\t\treturn (counter.cache ?? 0) >= cap;\n\t\t},\n\t};\n}\n","/**\n * Tier 1 sync operators (roadmap §2.1) and Tier 2 async/dynamic operators (roadmap §2.2) —\n * each returns a {@link Node} built with {@link node} (or {@link producer} for cold sources).\n *\n * v5 foundation redesign: all operators use `actions.emit()` for value emission,\n * `ctx.store` for persistent state, `ctx.terminalDeps` for terminal handling,\n * and `data[i]` batch shape for DATA vs RESOLVED discrimination. `onMessage`\n * and `onResubscribe` are removed.\n */\n\nimport { monotonicNs } from \"../core/clock.js\";\nimport type { NodeActions } from \"../core/config.js\";\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\ttype Message,\n\ttype Messages,\n\tRESOLVED,\n\tSTART,\n} from \"../core/messages.js\";\nimport { type Node, type NodeOptions, node } from \"../core/node.js\";\nimport { derived, producer } from \"../core/sugar.js\";\nimport { NS_PER_MS } from \"./backoff.js\";\nimport { fromAny, type NodeInput } from \"./sources.js\";\n\ntype ExtraOpts = Omit<NodeOptions<unknown>, \"describeKind\">;\n\nfunction operatorOpts<T = unknown>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"derived\", ...opts } as NodeOptions<T>;\n}\n\n/**\n * Maps each settled value from `source` through `project`.\n *\n * @param source - Upstream node.\n * @param project - Transform for each value.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<R>` - Derived node emitting mapped values.\n *\n * @example\n * ```ts\n * import { map, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = map(state(2), (x) => x * 3);\n * ```\n *\n * @category extra\n */\nexport function map<T, R>(source: Node<T>, project: (value: T) => R, opts?: ExtraOpts): Node<R> {\n\treturn node<R>(\n\t\t[source as Node],\n\t\t(data, a) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0) {\n\t\t\t\ta.emit(project(v as T));\n\t\t\t}\n\t\t},\n\t\toperatorOpts<R>(opts),\n\t);\n}\n\n/**\n * Forwards values that satisfy `predicate`; otherwise emits `RESOLVED` with no `DATA` (two-phase semantics).\n *\n * @param source - Upstream node.\n * @param predicate - Inclusion test.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Filtered node.\n *\n * @example\n * ```ts\n * import { filter, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = filter(state(1), (x) => x > 0);\n * ```\n *\n * @category extra\n */\nexport function filter<T>(\n\tsource: Node<T>,\n\tpredicate: (value: T) => boolean,\n\topts?: ExtraOpts,\n): Node<T> {\n\treturn node<T>(\n\t\t[source as Node],\n\t\t(data, a) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet emitted = false;\n\t\t\tfor (const v of batch0) {\n\t\t\t\tif (predicate(v as T)) {\n\t\t\t\t\ta.emit(v as T);\n\t\t\t\t\temitted = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!emitted) a.down([[RESOLVED]]);\n\t\t},\n\t\toperatorOpts(opts),\n\t);\n}\n\n/**\n * Folds each upstream value into an accumulator; emits the new accumulator every time.\n *\n * Unlike RxJS, `seed` is always required — there is no seedless mode where the first\n * value silently becomes the accumulator.\n *\n * @param source - Upstream node.\n * @param reducer - `(acc, value) => nextAcc`.\n * @param seed - Initial accumulator (required).\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<R>` - Scan node.\n *\n * @example\n * ```ts\n * import { scan, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = scan(state(1), (a, x) => a + x, 0);\n * ```\n *\n * @category extra\n */\nexport function scan<T, R>(\n\tsource: Node<T>,\n\treducer: (acc: R, value: T) => R,\n\tseed: R,\n\topts?: ExtraOpts,\n): Node<R> {\n\treturn node<R>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tif (!(\"acc\" in ctx.store)) ctx.store.acc = seed;\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0) {\n\t\t\t\tctx.store.acc = reducer(ctx.store.acc as R, v as T);\n\t\t\t\ta.emit(ctx.store.acc as R);\n\t\t\t}\n\t\t},\n\t\t{ ...operatorOpts(opts), initial: seed, resetOnTeardown: true },\n\t);\n}\n\n/**\n * Reduces to one value emitted when `source` completes; if no `DATA` arrived, emits `seed`.\n *\n * Unlike RxJS, `seed` is always required. If the source completes without emitting\n * DATA, the seed value is emitted (RxJS would throw without a seed).\n *\n * @param source - Upstream node.\n * @param reducer - `(acc, value) => nextAcc`.\n * @param seed - Empty-completion default and initial accumulator (required).\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<R>` - Node that emits once on completion.\n *\n * @example\n * ```ts\n * import { reduce, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = reduce(state(1), (a, x) => a + x, 0);\n * ```\n *\n * @category extra\n */\nexport function reduce<T, R>(\n\tsource: Node<T>,\n\treducer: (acc: R, value: T) => R,\n\tseed: R,\n\topts?: ExtraOpts,\n): Node<R> {\n\treturn node<R>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tif (!(\"acc\" in ctx.store)) ctx.store.acc = seed;\n\t\t\t// COMPLETE: emit accumulated value then COMPLETE.\n\t\t\t// ERROR: autoError propagates automatically; nothing to emit.\n\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\ta.emit(ctx.store.acc as R);\n\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst batch0 = data[0];\n\t\t\t// RESOLVED wave (empty batch): propagate RESOLVED. After fn has run once\n\t\t\t// the pre-fn skip handles this; this guard covers the first-wave case.\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// DATA: accumulate silently — emit nothing until COMPLETE.\n\t\t\tfor (const v of batch0) {\n\t\t\t\tctx.store.acc = reducer(ctx.store.acc as R, v as T);\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(opts),\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t},\n\t);\n}\n\n/**\n * Emits at most `count` **`DATA`** values, then **`COMPLETE`**. `RESOLVED` does not advance the counter.\n *\n * @param source - Upstream node.\n * @param count - Maximum `DATA` emissions (≤0 completes immediately).\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Limited stream.\n *\n * @example\n * ```ts\n * import { take, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = take(state(0), 3);\n * ```\n *\n * @category extra\n */\nexport function take<T>(source: Node<T>, count: number, opts?: ExtraOpts): Node<T> {\n\tif (count <= 0) {\n\t\treturn node<T>(\n\t\t\t[source as Node],\n\t\t\t(_d, a, ctx) => {\n\t\t\t\tif (ctx.store.completed) return;\n\t\t\t\tctx.store.completed = true;\n\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t},\n\t\t\t{\n\t\t\t\t...operatorOpts(opts),\n\t\t\t\tcompleteWhenDepsComplete: false,\n\t\t\t},\n\t\t);\n\t}\n\treturn node<T>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tif (!(\"taken\" in ctx.store)) ctx.store.taken = 0;\n\t\t\tif (ctx.store.done) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Upstream COMPLETE before count reached → forward COMPLETE.\n\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\tctx.store.done = true;\n\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// DATA wave: iterate full batch, stop at count\n\t\t\tfor (const v of batch0) {\n\t\t\t\t(ctx.store.taken as number)++;\n\t\t\t\ta.emit(v as T);\n\t\t\t\tif ((ctx.store.taken as number) >= count) {\n\t\t\t\t\tctx.store.done = true;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(opts),\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t},\n\t);\n}\n\n/**\n * Skips the first `count` **`DATA`** emissions. `RESOLVED` does not advance the counter.\n *\n * @param source - Upstream node.\n * @param count - Number of `DATA` values to drop.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Skipped stream.\n *\n * @example\n * ```ts\n * import { skip, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = skip(state(0), 2);\n * ```\n *\n * @category extra\n */\nexport function skip<T>(source: Node<T>, count: number, opts?: ExtraOpts): Node<T> {\n\treturn node<T>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tif (!(\"skipped\" in ctx.store)) ctx.store.skipped = 0;\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\t// RESOLVED wave — pass through\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet emitted = false;\n\t\t\tfor (const v of batch0) {\n\t\t\t\t(ctx.store.skipped as number)++;\n\t\t\t\tif ((ctx.store.skipped as number) <= count) {\n\t\t\t\t\t// Still in skip window\n\t\t\t\t} else {\n\t\t\t\t\ta.emit(v as T);\n\t\t\t\t\temitted = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!emitted) a.down([[RESOLVED]]);\n\t\t},\n\t\toperatorOpts(opts),\n\t);\n}\n\n/**\n * Emits while `predicate` holds; on first false, sends **`COMPLETE`**.\n *\n * @param source - Upstream node.\n * @param predicate - Continuation test.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Truncated stream.\n *\n * @example\n * ```ts\n * import { takeWhile, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = takeWhile(state(1), (x) => x < 10);\n * ```\n *\n * @category extra\n */\nexport function takeWhile<T>(\n\tsource: Node<T>,\n\tpredicate: (value: T) => boolean,\n\topts?: ExtraOpts,\n): Node<T> {\n\treturn node<T>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tif (ctx.store.done) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0) {\n\t\t\t\tif (!predicate(v as T)) {\n\t\t\t\t\tctx.store.done = true;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ta.emit(v as T);\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(opts),\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t},\n\t);\n}\n\n/**\n * Forwards `source` until `notifier` matches `predicate` (default: notifier **`DATA`**), then **`COMPLETE`**.\n *\n * @param source - Main upstream.\n * @param notifier - Triggers completion when `predicate(msg)` is true.\n * @param opts - Optional {@link NodeOptions}, plus `predicate` for custom notifier matching.\n * @returns `Node<T>` - Truncated stream.\n *\n * @example\n * ```ts\n * import { producer, takeUntil, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const src = state(1);\n * const stop = producer((_d, a) => a.emit(undefined));\n * const n = takeUntil(src, stop);\n * ```\n *\n * @category extra\n */\nexport function takeUntil<T>(\n\tsource: Node<T>,\n\tnotifier: Node,\n\topts?: ExtraOpts & { predicate?: (msg: Message) => boolean },\n): Node<T> {\n\tconst pred = opts?.predicate ?? ((m: Message) => m[0] === DATA);\n\tconst { predicate: _, ...restOpts } = opts ?? {};\n\t// Use producer pattern — subscribe to both manually for message-level control.\n\treturn producer<T>(\n\t\t(a) => {\n\t\t\tlet stopped = false;\n\t\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\t\tif (stopped) return;\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (stopped) return;\n\t\t\t\t\tif (m[0] === DATA) a.emit(m[1] as T);\n\t\t\t\t\telse if (m[0] === COMPLETE || m[0] === ERROR) {\n\t\t\t\t\t\tstopped = true;\n\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst notUnsub = notifier.subscribe((msgs) => {\n\t\t\t\tif (stopped) return;\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (stopped) return;\n\t\t\t\t\tif (pred(m)) {\n\t\t\t\t\t\tstopped = true;\n\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tsrcUnsub();\n\t\t\t\tnotUnsub();\n\t\t\t};\n\t\t},\n\t\toperatorOpts(restOpts as ExtraOpts),\n\t);\n}\n\n/**\n * Emits the first **`DATA`** then **`COMPLETE`** (same as `take(source, 1)`).\n *\n * @param source - Upstream node.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Single-value stream.\n *\n * @example\n * ```ts\n * import { first, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = first(state(42));\n * ```\n *\n * @category extra\n */\nexport function first<T>(source: Node<T>, opts?: ExtraOpts): Node<T> {\n\treturn take(source, 1, opts);\n}\n\n/**\n * Buffers values and emits the last **`DATA`** on **`COMPLETE`**; optional `defaultValue` if none arrived.\n *\n * @param source - Upstream node.\n * @param options - Optional {@link NodeOptions} and `defaultValue` when empty.\n * @returns `Node<T>` - Last-or-default node.\n *\n * @example\n * ```ts\n * import { last, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = last(state(1), { defaultValue: 0 });\n * ```\n *\n * @category extra\n */\nexport function last<T>(source: Node<T>, options?: ExtraOpts & { defaultValue?: T }): Node<T> {\n\tconst { defaultValue, ...rest } = options ?? {};\n\tconst useDefault = options != null && Object.hasOwn(options, \"defaultValue\");\n\treturn node<T>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\t// COMPLETE (terminal === true): emit latest or default, then COMPLETE.\n\t\t\t// ERROR: autoError propagates automatically.\n\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\tif (ctx.store.has) {\n\t\t\t\t\ta.emit(ctx.store.latest as T);\n\t\t\t\t} else if (useDefault) {\n\t\t\t\t\ta.emit(defaultValue as T);\n\t\t\t\t}\n\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst batch0 = data[0];\n\t\t\t// RESOLVED wave: propagate RESOLVED. Covers first-wave case; after first\n\t\t\t// call the pre-fn skip handles this automatically.\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// DATA: accumulate latest — emit nothing until COMPLETE.\n\t\t\tctx.store.latest = batch0.at(-1) as T;\n\t\t\tctx.store.has = true;\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(rest),\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t},\n\t);\n}\n\n/**\n * Emits the first value matching `predicate`, then **`COMPLETE`**.\n *\n * @param source - Upstream node.\n * @param predicate - Match test.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - First-match stream.\n *\n * @example\n * ```ts\n * import { find, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = find(state(1), (x) => x > 0);\n * ```\n *\n * @category extra\n */\nexport function find<T>(\n\tsource: Node<T>,\n\tpredicate: (value: T) => boolean,\n\topts?: ExtraOpts,\n): Node<T> {\n\treturn take(filter(source, predicate, opts), 1, opts);\n}\n\n/**\n * Emits the `index`th **`DATA`** (zero-based), then **`COMPLETE`**.\n *\n * @param source - Upstream node.\n * @param index - Zero-based emission index.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Single indexed value.\n *\n * @example\n * ```ts\n * import { elementAt, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = elementAt(state(0), 2);\n * ```\n *\n * @category extra\n */\nexport function elementAt<T>(source: Node<T>, index: number, opts?: ExtraOpts): Node<T> {\n\treturn take(skip(source, index, opts), 1, opts);\n}\n\n/**\n * Observer shape for {@link tap} — side effects for data, error, and/or complete.\n */\nexport type TapObserver<T> = {\n\tdata?: (value: T) => void;\n\terror?: (err: unknown) => void;\n\tcomplete?: () => void;\n};\n\n/**\n * Invokes side effects; values pass through unchanged.\n *\n * Accepts either a function (called on each DATA) or an observer object\n * `{ data?, error?, complete? }` for lifecycle-aware side effects.\n *\n * @param source - Upstream node.\n * @param fnOrObserver - Side effect function or observer object.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Passthrough node.\n *\n * @example\n * ```ts\n * import { tap, state } from \"@graphrefly/graphrefly-ts\";\n *\n * // Function form (DATA only)\n * tap(state(1), (x) => console.log(x));\n *\n * // Observer form (DATA + ERROR + COMPLETE)\n * tap(state(1), { data: console.log, error: console.error, complete: () => console.log(\"done\") });\n * ```\n *\n * @category extra\n */\nexport function tap<T>(\n\tsource: Node<T>,\n\tfnOrObserver: ((value: T) => void) | TapObserver<T>,\n\topts?: ExtraOpts,\n): Node<T> {\n\tif (typeof fnOrObserver === \"function\") {\n\t\treturn node<T>(\n\t\t\t[source as Node],\n\t\t\t(data, a) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const v of batch0) {\n\t\t\t\t\tfnOrObserver(v as T);\n\t\t\t\t\ta.emit(v as T);\n\t\t\t\t}\n\t\t\t},\n\t\t\toperatorOpts(opts),\n\t\t);\n\t}\n\tconst obs = fnOrObserver;\n\treturn node<T>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\t// Check for terminal events\n\t\t\tif (ctx.terminalDeps[0] !== undefined) {\n\t\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\t\tobs.complete?.();\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else {\n\t\t\t\t\tobs.error?.(ctx.terminalDeps[0]);\n\t\t\t\t\ta.down([[ERROR, ctx.terminalDeps[0]]]);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0) {\n\t\t\t\tobs.data?.(v as T);\n\t\t\t\ta.emit(v as T);\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(opts),\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t},\n\t);\n}\n\n/**\n * Suppresses adjacent duplicates using `equals` (default `Object.is`).\n *\n * @param source - Upstream node.\n * @param equals - Optional equality for consecutive values.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Deduped stream.\n *\n * @example\n * ```ts\n * import { distinctUntilChanged, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = distinctUntilChanged(state(1));\n * ```\n *\n * @category extra\n */\nexport function distinctUntilChanged<T>(\n\tsource: Node<T>,\n\tequals: (a: T, b: T) => boolean = Object.is,\n\topts?: ExtraOpts,\n): Node<T> {\n\treturn node<T>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet emitted = false;\n\t\t\tfor (const val of batch0 as T[]) {\n\t\t\t\tif (ctx.store.hasPrev && equals(ctx.store.prev as T, val)) {\n\t\t\t\t\t// Suppressed — same as previous\n\t\t\t\t} else {\n\t\t\t\t\tctx.store.prev = val;\n\t\t\t\t\tctx.store.hasPrev = true;\n\t\t\t\t\ta.emit(val);\n\t\t\t\t\temitted = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!emitted) a.down([[RESOLVED]]);\n\t\t},\n\t\toperatorOpts(opts),\n\t);\n}\n\n/**\n * Emits `[previous, current]` pairs starting after the second value (first pair uses `RESOLVED` only).\n *\n * @param source - Upstream node.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<readonly [T, T]>` - Pair stream.\n *\n * @example\n * ```ts\n * import { pairwise, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = pairwise(state(0));\n * ```\n *\n * @category extra\n */\nexport function pairwise<T>(source: Node<T>, opts?: ExtraOpts): Node<readonly [T, T]> {\n\treturn node<readonly [T, T]>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet emitted = false;\n\t\t\tfor (const x of batch0 as T[]) {\n\t\t\t\tif (!ctx.store.hasPrev) {\n\t\t\t\t\tctx.store.prev = x;\n\t\t\t\t\tctx.store.hasPrev = true;\n\t\t\t\t\t// First value — no pair yet\n\t\t\t\t} else {\n\t\t\t\t\tconst pair = [ctx.store.prev as T, x] as const;\n\t\t\t\t\tctx.store.prev = x;\n\t\t\t\t\ta.emit(pair);\n\t\t\t\t\temitted = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!emitted) a.down([[RESOLVED]]);\n\t\t},\n\t\toperatorOpts(opts),\n\t);\n}\n\n/**\n * Combines the latest value from each dependency whenever any dep settles (combineLatest).\n *\n * @param sources - Nodes to combine (variadic).\n * @returns `Node<T>` - Tuple of latest values.\n *\n * @example\n * ```ts\n * import { combine, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = combine(state(1), state(\"a\"));\n * ```\n *\n * @remarks\n * Unlike RxJS `combineLatest`, this is named `combine`. Use the {@link combineLatest} alias\n * if you prefer the RxJS name. Seed is always required for `scan`/`reduce` (no seedless mode).\n *\n * @category extra\n */\nexport function combine<const T extends readonly unknown[]>(\n\t...sources: { [K in keyof T]: Node<T[K]> }\n): Node<T> {\n\tconst deps = [...sources] as unknown as Node[];\n\treturn derived(deps, (vals) => vals as unknown as T, {\n\t\t...operatorOpts<T>(),\n\t\tequals: (a, b) => {\n\t\t\tif (a.length !== b.length) return false;\n\t\t\tfor (let i = 0; i < a.length; i++) {\n\t\t\t\tif (!Object.is(a[i], b[i])) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t});\n}\n\n/**\n * When `primary` settles, emits `[primary, latestSecondary]`. `secondary` alone updates cache only.\n *\n * @param primary - Main stream.\n * @param secondary - Latest value is paired on each primary emission.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<readonly [A, B]>` - Paired stream.\n *\n * @example\n * ```ts\n * import { state, withLatestFrom } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = withLatestFrom(state(1), state(\"x\"));\n * ```\n *\n * @category extra\n */\nexport function withLatestFrom<A, B>(\n\tprimary: Node<A>,\n\tsecondary: Node<B>,\n\topts?: ExtraOpts,\n): Node<readonly [A, B]> {\n\t// Known semantic (documented): on initial activation when BOTH deps are\n\t// `state()` nodes with cached values, the paired emission is dropped.\n\t// `_activate` (src/core/node.ts:1002) subscribes deps sequentially in\n\t// declaration order; primary's push-on-subscribe fires before secondary\n\t// has subscribed, so the first-run gate (§2.7) forces RESOLVED. Secondary\n\t// then fires in a separate wave with primary silent, and the fn's\n\t// \"emit only when primary fired this wave\" rule takes the else branch.\n\t// Use the factory-time seed pattern for initial-value pairing (see\n\t// stratify, budgetGate, distill for examples; COMPOSITION-GUIDE §21).\n\t// A naïve `[secondary, primary]` flip breaks topology-sensitive diamond\n\t// callers like `harness/loop.ts` — the fix needs a deeper design pass.\n\treturn node<readonly [A, B]>(\n\t\t[primary as Node, secondary as Node],\n\t\t(data, a, ctx) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tconst batch1 = data[1];\n\t\t\t// Current secondary value: this wave's last DATA if secondary fired,\n\t\t\t// otherwise last known value from ctx.prevData (previous wave).\n\t\t\tconst secondaryVal = (\n\t\t\t\tbatch1 != null && batch1.length > 0 ? batch1.at(-1) : ctx.prevData[1]\n\t\t\t) as B | undefined;\n\n\t\t\t// Only emit when primary (dep 0) sent DATA this wave.\n\t\t\tif (batch0 != null && batch0.length > 0) {\n\t\t\t\t// secondary has never produced DATA — undefined is the protocol\n\t\t\t\t// sentinel for \"never sent DATA\"; null is a valid DATA value.\n\t\t\t\tif (!(batch1 != null && batch1.length > 0) && ctx.prevData[1] === undefined) {\n\t\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const v of batch0 as A[]) {\n\t\t\t\t\ta.emit([v, secondaryVal]);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Secondary update only (or both RESOLVED) — no downstream DATA.\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t}\n\t\t},\n\t\toperatorOpts(opts),\n\t);\n}\n\n/**\n * Merges **`DATA`** from any source with correct two-phase dirty tracking. **`COMPLETE`** after **all** sources complete (spec §1.3.5).\n *\n * @param sources - Nodes to merge (variadic; empty completes immediately).\n * @returns `Node<T>` - Merged stream.\n *\n * @remarks\n * **Ordering:** DIRTY/RESOLVED rules follow multi-source semantics in `~/src/graphrefly/GRAPHREFLY-SPEC.md`.\n *\n * @example\n * ```ts\n * import { merge, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = merge(state(1), state(2));\n * ```\n *\n * @category extra\n */\nexport function merge<T>(...sources: readonly Node<T>[]): Node<T> {\n\tif (sources.length === 0) {\n\t\treturn producer<T>((a) => {\n\t\t\ta.down([[COMPLETE]]);\n\t\t}, operatorOpts());\n\t}\n\t// producer pattern: node() cannot be used here because the sentinel gate\n\t// would block the fn until ALL sources have sent their first DATA, which\n\t// defeats the purpose of merge (forward whichever source fires first).\n\treturn producer<T>((a) => {\n\t\tconst n = sources.length;\n\t\tlet completed = 0;\n\t\tconst unsubs: (() => void)[] = [];\n\t\tfor (const src of sources) {\n\t\t\tconst u = src.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\t\tcompleted += 1;\n\t\t\t\t\t\tif (completed >= n) {\n\t\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t}\n\t\t\t\t\t// DIRTY, RESOLVED, START silently absorbed\n\t\t\t\t}\n\t\t\t});\n\t\t\tunsubs.push(u);\n\t\t}\n\t\treturn () => {\n\t\t\tfor (const u of unsubs) u();\n\t\t};\n\t}, operatorOpts());\n}\n\n/**\n * Zips one **`DATA`** from each source per cycle into a tuple. Only **`DATA`** enqueues (spec §1.3.3).\n *\n * @param sources - Nodes to zip (variadic).\n * @returns `Node<T>` - Zipped tuples.\n *\n * @example\n * ```ts\n * import { state, zip } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = zip(state(1), state(2));\n * ```\n *\n * @category extra\n */\nexport function zip<const T extends readonly unknown[]>(\n\t...sources: { [K in keyof T]: Node<T[K]> }\n): Node<T> {\n\tconst n = sources.length;\n\tif (n === 0) {\n\t\treturn producer<T>((a) => {\n\t\t\ta.emit([] as unknown as T);\n\t\t\ta.down([[COMPLETE]]);\n\t\t}, operatorOpts());\n\t}\n\t// Producer pattern: manage queues internally.\n\treturn producer<T>((a) => {\n\t\tconst queues: unknown[][] = Array.from({ length: n }, () => []);\n\t\tlet active = n;\n\n\t\tfunction tryEmit(): void {\n\t\t\twhile (queues.every((q) => q.length > 0)) {\n\t\t\t\tconst tuple = queues.map((q) => q.shift()!) as unknown as T;\n\t\t\t\ta.emit(tuple);\n\t\t\t}\n\t\t}\n\n\t\tconst unsubs: (() => void)[] = [];\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tconst idx = i;\n\t\t\tconst u = (sources[i] as Node).subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\tqueues[idx].push(m[1]);\n\t\t\t\t\t\ttryEmit();\n\t\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\t\tactive -= 1;\n\t\t\t\t\t\tif (active === 0 || queues[idx].length === 0) {\n\t\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tunsubs.push(u);\n\t\t}\n\t\treturn () => {\n\t\t\tfor (const u of unsubs) u();\n\t\t};\n\t}, operatorOpts());\n}\n\n/**\n * Plays all of `firstSrc`, then all of `secondSrc`. **`DATA`** from `secondSrc` during phase one is buffered until handoff.\n *\n * @param firstSrc - First segment.\n * @param secondSrc - Second segment.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Concatenated stream.\n *\n * @example\n * ```ts\n * import { concat, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = concat(state(1), state(2));\n * ```\n *\n * @category extra\n */\nexport function concat<T>(firstSrc: Node<T>, secondSrc: Node<T>, opts?: ExtraOpts): Node<T> {\n\t// producer pattern: node() cannot be used here because the sentinel gate\n\t// would block the fn until ALL sources have sent their first DATA, which\n\t// defeats the purpose of concat (start forwarding firstSrc immediately,\n\t// regardless of secondSrc state).\n\treturn producer<T>((a) => {\n\t\tlet phase: 0 | 1 = 0;\n\t\tconst pending: unknown[] = [];\n\t\tlet firstUnsub: (() => void) | undefined;\n\t\tlet secondUnsub: (() => void) | undefined;\n\n\t\tsecondUnsub = secondSrc.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (phase === 0) {\n\t\t\t\t\tif (m[0] === DATA) pending.push(m[1]);\n\t\t\t\t\telse if (m[0] === ERROR) a.down([m]);\n\t\t\t\t} else {\n\t\t\t\t\t// phase 1 — forward everything from second\n\t\t\t\t\tif (m[0] === DATA) a.emit(m[1] as T);\n\t\t\t\t\telse if (m[0] === COMPLETE || m[0] === ERROR) a.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tfirstUnsub = firstSrc.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (phase === 0) {\n\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\t\tphase = 1;\n\t\t\t\t\t\t// Flush buffered second-source DATA\n\t\t\t\t\t\tfor (const v of pending) {\n\t\t\t\t\t\t\ta.emit(v as T);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpending.length = 0;\n\t\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// phase 1: ignore further first-source messages\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tfirstUnsub?.();\n\t\t\tsecondUnsub?.();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * First source to emit **`DATA`** wins; later traffic follows only the winner (Rx-style `race`).\n *\n * @param sources - Contestants (variadic; empty completes immediately; one node is identity).\n * @returns `Node<T>` - Winning stream.\n *\n * @example\n * ```ts\n * import { race, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = race(state(1), state(2));\n * ```\n *\n * @category extra\n */\nexport function race<T>(...sources: readonly Node<T>[]): Node<T> {\n\tif (sources.length === 0) {\n\t\treturn producer<T>((a) => {\n\t\t\ta.down([[COMPLETE]]);\n\t\t}, operatorOpts());\n\t}\n\tif (sources.length === 1) {\n\t\t// Identity passthrough — full batch iteration, not derived's .at(-1).\n\t\treturn node<T>(\n\t\t\t[sources[0] as Node],\n\t\t\t(data, a) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const v of batch0) a.emit(v as T);\n\t\t\t},\n\t\t\toperatorOpts<T>(),\n\t\t);\n\t}\n\t// Producer pattern: first DATA wins.\n\treturn producer<T>((a) => {\n\t\tlet winner: number | null = null;\n\t\tconst unsubs: (() => void)[] = [];\n\t\tfor (let i = 0; i < sources.length; i++) {\n\t\t\tconst idx = i;\n\t\t\tconst u = (sources[i] as Node).subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (winner !== null && idx !== winner) return;\n\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\tif (winner === null) winner = idx;\n\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t} else if (m[0] === COMPLETE || m[0] === ERROR) {\n\t\t\t\t\t\tif (winner === null || idx === winner) {\n\t\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tunsubs.push(u);\n\t\t}\n\t\treturn () => {\n\t\t\tfor (const u of unsubs) u();\n\t\t};\n\t}, operatorOpts());\n}\n\n// --- Tier 2: async / dynamic (roadmap §2.2), all on `node` / `producer` ---\n\nfunction forwardInner<R>(inner: Node<R>, a: NodeActions, onInnerComplete: () => void): () => void {\n\tlet unsub: (() => void) | undefined;\n\tlet finished = false;\n\tconst finish = (): void => {\n\t\tif (finished) return;\n\t\tfinished = true;\n\t\tonInnerComplete();\n\t};\n\tunsub = inner.subscribe((msgs) => {\n\t\tlet sawComplete = false;\n\t\tlet sawError = false;\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] === START) continue;\n\t\t\tif (m[0] === DATA) {\n\t\t\t\ta.emit(m[1] as R);\n\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\tsawComplete = true;\n\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\tsawError = true;\n\t\t\t\ta.down([m]);\n\t\t\t} else if (m[0] === DIRTY || m[0] === RESOLVED) {\n\t\t\t\t// Reactive wave signals forwarded to outer output.\n\t\t\t\ta.down([m]);\n\t\t\t}\n\t\t\t// INVALIDATE, PAUSE, RESUME, TEARDOWN from inner are intentionally\n\t\t\t// dropped. Inner lifecycle and flow-control signals are internal to\n\t\t\t// the *Map operator. INVALIDATE is dropped because the inner will\n\t\t\t// follow up with DIRTY+DATA when it recomputes — forwarding\n\t\t\t// INVALIDATE to the outer output's sinks is redundant and wrong for\n\t\t\t// mergeMap (one inner's cache state must not invalidate the whole\n\t\t\t// merged output). PAUSE/RESUME/TEARDOWN: RxJS/callbag precedent —\n\t\t\t// no backpressure forwarding in merge-style operators.\n\t\t}\n\t\tif (sawError) {\n\t\t\tunsub?.();\n\t\t\tunsub = undefined;\n\t\t\tfinish();\n\t\t} else if (sawComplete) {\n\t\t\tfinish();\n\t\t}\n\t});\n\t// P4 START handshake guarantees: subscribe delivers [[START], [DATA, cache]]\n\t// synchronously for settled nodes. Any relevant state is already handled by\n\t// the callback above — no post-subscribe .status/.cache reads needed.\n\treturn () => {\n\t\tunsub?.();\n\t\tunsub = undefined;\n\t};\n}\n\n/**\n * Maps each settled value to an inner node; unsubscribes the previous inner (Rx-style `switchMap`).\n *\n * @param source - Upstream node.\n * @param project - Maps each outer value to an inner source shape (`Node`, scalar, `PromiseLike`, `Iterable`, or `AsyncIterable`) coerced via {@link fromAny}.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<R>` - Emissions from the active inner subscription.\n * @example\n * ```ts\n * import { switchMap, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const src = state(0);\n * switchMap(src, (n) => state((n as number) * 2));\n * ```\n *\n * @category extra\n */\nexport function switchMap<T, R>(\n\tsource: Node<T>,\n\tproject: (value: T) => NodeInput<R>,\n\topts?: ExtraOpts,\n): Node<R> {\n\tlet innerUnsub: (() => void) | undefined;\n\tlet sourceDone = false;\n\n\tfunction clearInner(): void {\n\t\tinnerUnsub?.();\n\t\tinnerUnsub = undefined;\n\t}\n\n\treturn node<R>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\t// Source ERROR: cleanup inner, autoError forwards\n\t\t\tif (ctx.terminalDeps[0] != null && ctx.terminalDeps[0] !== true) {\n\t\t\t\tclearInner();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Source COMPLETE\n\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\tsourceDone = true;\n\t\t\t\tif (!innerUnsub) a.down([[COMPLETE]]);\n\t\t\t\t// inner active: onInnerComplete will fire COMPLETE later\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) return;\n\n\t\t\t// Switch: only the latest value matters; skip to the last in the\n\t\t\t// batch to avoid creating and immediately discarding N-1 inners.\n\t\t\t// clearInner() runs once to cancel any prior-wave inner.\n\t\t\tclearInner();\n\t\t\tinnerUnsub = forwardInner(fromAny(project(batch0[batch0.length - 1] as T)), a, () => {\n\t\t\t\tclearInner();\n\t\t\t\tif (sourceDone) a.down([[COMPLETE]]);\n\t\t\t});\n\n\t\t\t// Deactivation-only cleanup: must NOT fire before fn reruns\n\t\t\t// because the terminal wave needs to see innerUnsub intact.\n\t\t\treturn {\n\t\t\t\tdeactivation: () => {\n\t\t\t\t\tclearInner();\n\t\t\t\t\tsourceDone = false;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{ ...operatorOpts(opts), completeWhenDepsComplete: false },\n\t);\n}\n\n/**\n * Like {@link switchMap}, but ignores outer `DATA` while an inner subscription is active (`exhaustMap`).\n *\n * @param source - Upstream node.\n * @param project - Maps each outer value to an inner source shape (`Node`, scalar, `PromiseLike`, `Iterable`, or `AsyncIterable`) coerced via {@link fromAny}.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<R>` - Emissions from the active inner while it runs.\n * @example\n * ```ts\n * import { exhaustMap, state } from \"@graphrefly/graphrefly-ts\";\n *\n * exhaustMap(state(0), () => state(1));\n * ```\n *\n * @category extra\n */\nexport function exhaustMap<T, R>(\n\tsource: Node<T>,\n\tproject: (value: T) => NodeInput<R>,\n\topts?: ExtraOpts,\n): Node<R> {\n\tlet innerUnsub: (() => void) | undefined;\n\tlet sourceDone = false;\n\n\tfunction clearInner(): void {\n\t\tinnerUnsub?.();\n\t\tinnerUnsub = undefined;\n\t}\n\n\treturn node<R>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tif (ctx.terminalDeps[0] != null && ctx.terminalDeps[0] !== true) {\n\t\t\t\tclearInner();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\tsourceDone = true;\n\t\t\t\tif (!innerUnsub) a.down([[COMPLETE]]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) return;\n\n\t\t\tif (innerUnsub === undefined) {\n\t\t\t\t// First value in batch wins (FIFO exhaustMap gate)\n\t\t\t\tinnerUnsub = forwardInner(fromAny(project(batch0[0] as T)), a, () => {\n\t\t\t\t\tclearInner();\n\t\t\t\t\tif (sourceDone) a.down([[COMPLETE]]);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Inner active — drop, settle the dep-wave\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tdeactivation: () => {\n\t\t\t\t\tclearInner();\n\t\t\t\t\tsourceDone = false;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{ ...operatorOpts(opts), completeWhenDepsComplete: false },\n\t);\n}\n\n/**\n * Enqueues each outer value and subscribes to inners one at a time (`concatMap`).\n *\n * @param source - Upstream node.\n * @param project - Maps each outer value to an inner source shape (`Node`, scalar, `PromiseLike`, `Iterable`, or `AsyncIterable`) coerced via {@link fromAny}.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<R>` - Sequential concatenation of inner streams.\n * @example\n * ```ts\n * import { concatMap, state } from \"@graphrefly/graphrefly-ts\";\n *\n * concatMap(state(0), (n) => state((n as number) + 1));\n * ```\n *\n * @category extra\n */\nexport function concatMap<T, R>(\n\tsource: Node<T>,\n\tproject: (value: T) => NodeInput<R>,\n\topts?: ExtraOpts & { maxBuffer?: number },\n): Node<R> {\n\tconst { maxBuffer: maxBuf, ...concatNodeOpts } = opts ?? {};\n\tconst queue: T[] = [];\n\tlet innerUnsub: (() => void) | undefined;\n\tlet sourceDone = false;\n\tlet actions: NodeActions | undefined;\n\n\tfunction clearInner(): void {\n\t\tinnerUnsub?.();\n\t\tinnerUnsub = undefined;\n\t}\n\n\tfunction tryPump(): void {\n\t\tif (!actions || innerUnsub !== undefined) return;\n\t\tif (queue.length === 0) {\n\t\t\tif (sourceDone) actions.down([[COMPLETE]]);\n\t\t\treturn;\n\t\t}\n\t\tconst v = queue.shift()!;\n\t\tinnerUnsub = forwardInner(fromAny(project(v)), actions, () => {\n\t\t\tclearInner();\n\t\t\ttryPump();\n\t\t});\n\t}\n\n\tfunction enqueue(v: T): void {\n\t\tif (maxBuf && maxBuf > 0 && queue.length >= maxBuf) queue.shift();\n\t\tqueue.push(v);\n\t\ttryPump();\n\t}\n\n\treturn node<R>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tactions = a;\n\n\t\t\tif (ctx.terminalDeps[0] != null && ctx.terminalDeps[0] !== true) {\n\t\t\t\tclearInner();\n\t\t\t\tqueue.length = 0;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\tsourceDone = true;\n\t\t\t\ttryPump();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) return;\n\n\t\t\tfor (const v of batch0 as T[]) {\n\t\t\t\tenqueue(v as T);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tdeactivation: () => {\n\t\t\t\t\tclearInner();\n\t\t\t\t\tqueue.length = 0;\n\t\t\t\t\tsourceDone = false;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{ ...operatorOpts(concatNodeOpts), completeWhenDepsComplete: false },\n\t);\n}\n\n/** Options for {@link mergeMap}. */\nexport type MergeMapOptions = ExtraOpts & {\n\t/** Maximum number of concurrent inner subscriptions. Default: `Infinity` (unbounded). */\n\tconcurrent?: number;\n};\n\n/**\n * Subscribes to inner nodes in parallel (up to `concurrent`) and merges outputs (`mergeMap` / `flatMap`).\n *\n * @param source - Upstream node.\n * @param project - Maps each outer value to an inner source shape (`Node`, scalar, `PromiseLike`, `Iterable`, or `AsyncIterable`) coerced via {@link fromAny}.\n * @param opts - Optional options including `concurrent` limit.\n * @returns `Node<R>` - Merged output of all active inners; completes when the outer and every inner complete.\n *\n * @remarks\n * **ERROR handling:** An `ERROR` from the outer source cancels all active inner\n * subscriptions and propagates the error downstream. An `ERROR` from an inner\n * subscription propagates downstream immediately but does **not** cancel sibling\n * inner subscriptions — other active inners continue until they complete or the\n * outer errors/completes. This is intentional: for parallel work, isolating\n * failures per-inner is more useful than Rx-style \"first error cancels all.\"\n *\n * @example\n * ```ts\n * import { mergeMap, state } from \"@graphrefly/graphrefly-ts\";\n *\n * // Unbounded (default)\n * mergeMap(state(0), (n) => state((n as number) + 1));\n *\n * // Limited concurrency\n * mergeMap(state(0), (n) => state((n as number) + 1), { concurrent: 3 });\n * ```\n *\n * @category extra\n */\nexport function mergeMap<T, R>(\n\tsource: Node<T>,\n\tproject: (value: T) => NodeInput<R>,\n\topts?: MergeMapOptions,\n): Node<R> {\n\tconst { concurrent: concurrentOpt, ...mergeNodeOpts } = opts ?? {};\n\tconst maxConcurrent =\n\t\tconcurrentOpt != null && concurrentOpt > 0 ? concurrentOpt : Number.POSITIVE_INFINITY;\n\n\tlet active = 0;\n\tlet sourceDone = false;\n\tconst innerStops = new Set<() => void>();\n\tconst buffer: T[] = [];\n\tlet actions: NodeActions | undefined;\n\n\tfunction tryComplete(): void {\n\t\tif (sourceDone && active === 0 && buffer.length === 0 && actions) {\n\t\t\tactions.down([[COMPLETE]]);\n\t\t}\n\t}\n\n\tfunction spawn(v: T): void {\n\t\tif (!actions) return;\n\t\tactive++;\n\t\t// Use `let` (not `const`) so the closure can reference `stop` safely even\n\t\t// if onInnerComplete fires synchronously (e.g. already-completed inner node).\n\t\tlet stop: (() => void) | undefined;\n\t\tstop = forwardInner(fromAny(project(v)), actions, () => {\n\t\t\tif (stop) innerStops.delete(stop);\n\t\t\tactive--;\n\t\t\tdrainBuffer();\n\t\t\ttryComplete();\n\t\t});\n\t\tinnerStops.add(stop);\n\t}\n\n\tfunction drainBuffer(): void {\n\t\twhile (buffer.length > 0 && active < maxConcurrent) {\n\t\t\tspawn(buffer.shift()!);\n\t\t}\n\t}\n\n\tfunction enqueue(v: T): void {\n\t\tif (active < maxConcurrent) spawn(v);\n\t\telse buffer.push(v);\n\t}\n\n\tfunction clearAll(): void {\n\t\tfor (const u of innerStops) u();\n\t\tinnerStops.clear();\n\t\tactive = 0;\n\t\tbuffer.length = 0;\n\t}\n\n\treturn node<R>(\n\t\t[source as Node],\n\t\t(data, a, ctx) => {\n\t\t\tactions = a;\n\n\t\t\tif (ctx.terminalDeps[0] != null && ctx.terminalDeps[0] !== true) {\n\t\t\t\tclearAll();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (ctx.terminalDeps[0] === true) {\n\t\t\t\tsourceDone = true;\n\t\t\t\ttryComplete();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) return;\n\n\t\t\tfor (const v of batch0 as T[]) {\n\t\t\t\tenqueue(v as T);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tdeactivation: () => {\n\t\t\t\t\tclearAll();\n\t\t\t\t\tsourceDone = false;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{ ...operatorOpts(mergeNodeOpts), completeWhenDepsComplete: false },\n\t);\n}\n\n/**\n * RxJS-named alias for {@link mergeMap} — projects each `DATA` to an inner node and merges outputs.\n *\n * @param source - Upstream node.\n * @param project - Returns an inner `Node<R>` per value.\n * @param opts - Optional concurrency cap and node options (excluding `describeKind`).\n * @returns Merged projection; behavior matches `mergeMap`.\n *\n * @example\n * ```ts\n * import { flatMap, state } from \"@graphrefly/graphrefly-ts\";\n *\n * flatMap(state(0), (n) => state(n));\n * ```\n *\n * @category extra\n */\nexport const flatMap = mergeMap;\n\n/**\n * Delays phase-2 emissions by `ms` (timers). `DIRTY` still forwards immediately.\n *\n * @param source - Upstream node.\n * @param ms - Delay in milliseconds.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Same values, shifted in time.\n * @example\n * ```ts\n * import { delay, state } from \"@graphrefly/graphrefly-ts\";\n *\n * delay(state(1), 100);\n * ```\n *\n * @category extra\n */\nexport function delay<T>(source: Node<T>, ms: number, opts?: ExtraOpts): Node<T> {\n\treturn producer<T>((a) => {\n\t\tconst timers = new Set<ReturnType<typeof setTimeout>>();\n\t\tfunction clearAll(): void {\n\t\t\tfor (const id of timers) clearTimeout(id);\n\t\t\ttimers.clear();\n\t\t}\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tconst id = setTimeout(() => {\n\t\t\t\t\t\ttimers.delete(id);\n\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t}, ms);\n\t\t\t\t\ttimers.add(id);\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\t// Wait for all pending timers, then complete\n\t\t\t\t\tconst id = setTimeout(() => {\n\t\t\t\t\t\ttimers.delete(id);\n\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t}, ms);\n\t\t\t\t\ttimers.add(id);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\tclearAll();\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t\t// DIRTY from source is NOT forwarded — delay transforms the\n\t\t\t\t// timeline. a.emit(v) in the timer callback handles full\n\t\t\t\t// DIRTY+DATA framing atomically at the delayed time.\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tclearAll();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Emits the latest value only after `ms` quiet time since the last trigger (`debounce`).\n *\n * @param source - Upstream node.\n * @param ms - Quiet window in milliseconds.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Debounced stream.\n * @example\n * ```ts\n * import { debounce, state } from \"@graphrefly/graphrefly-ts\";\n *\n * debounce(state(0), 50);\n * ```\n *\n * @category extra\n */\nexport function debounce<T>(source: Node<T>, ms: number, opts?: ExtraOpts): Node<T> {\n\treturn producer<T>((a) => {\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tlet pending: T | undefined;\n\n\t\tfunction clearTimer(): void {\n\t\t\tif (timer !== undefined) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\ttimer = undefined;\n\t\t\t}\n\t\t}\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tclearTimer();\n\t\t\t\t\tpending = m[1] as T;\n\t\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\t\ttimer = undefined;\n\t\t\t\t\t\ta.emit(pending as T);\n\t\t\t\t\t}, ms);\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\tif (timer !== undefined) {\n\t\t\t\t\t\tclearTimer();\n\t\t\t\t\t\ta.emit(pending as T);\n\t\t\t\t\t}\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\tclearTimer();\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tclearTimer();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\nexport type ThrottleOptions = { leading?: boolean; trailing?: boolean };\n\n/**\n * Rate-limits emissions to at most once per `ms` window (`throttleTime`).\n *\n * @param source - Upstream node.\n * @param ms - Minimum spacing in milliseconds.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`) plus `leading` / `trailing`.\n * @returns `Node<T>` - Throttled stream.\n * @example\n * ```ts\n * import { throttle, state } from \"@graphrefly/graphrefly-ts\";\n *\n * throttle(state(0), 1_000, { trailing: false });\n * ```\n *\n * @category extra\n */\nexport function throttle<T>(\n\tsource: Node<T>,\n\tms: number,\n\topts?: ExtraOpts & ThrottleOptions,\n): Node<T> {\n\tconst { leading: leadingOpt, trailing: trailingOpt, ...throttleNodeOpts } = opts ?? {};\n\tconst leading = leadingOpt !== false;\n\tconst trailing = trailingOpt === true;\n\tconst windowNs = ms * NS_PER_MS;\n\n\treturn producer<T>((a) => {\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tlet lastEmitNs = -Infinity;\n\t\tlet pending: T | undefined;\n\t\tlet hasPending = false;\n\n\t\tfunction clearTimer(): void {\n\t\t\tif (timer !== undefined) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\ttimer = undefined;\n\t\t\t}\n\t\t}\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tconst v = m[1] as T;\n\t\t\t\t\tconst nowNs = monotonicNs();\n\t\t\t\t\tif (leading && nowNs - lastEmitNs >= windowNs) {\n\t\t\t\t\t\tlastEmitNs = nowNs;\n\t\t\t\t\t\ta.emit(v);\n\t\t\t\t\t\tclearTimer();\n\t\t\t\t\t\tif (trailing) {\n\t\t\t\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\t\t\t\ttimer = undefined;\n\t\t\t\t\t\t\t\tif (hasPending) {\n\t\t\t\t\t\t\t\t\tlastEmitNs = monotonicNs();\n\t\t\t\t\t\t\t\t\ta.emit(pending as T);\n\t\t\t\t\t\t\t\t\thasPending = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, ms);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (trailing) {\n\t\t\t\t\t\tpending = v;\n\t\t\t\t\t\thasPending = true;\n\t\t\t\t\t\tif (timer === undefined) {\n\t\t\t\t\t\t\tconst elapsedMs = (nowNs - lastEmitNs) / NS_PER_MS;\n\t\t\t\t\t\t\ttimer = setTimeout(\n\t\t\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\t\t\ttimer = undefined;\n\t\t\t\t\t\t\t\t\tif (hasPending) {\n\t\t\t\t\t\t\t\t\t\tlastEmitNs = monotonicNs();\n\t\t\t\t\t\t\t\t\t\ta.emit(pending as T);\n\t\t\t\t\t\t\t\t\t\thasPending = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tMath.max(0, ms - elapsedMs),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (m[0] === COMPLETE || m[0] === ERROR) {\n\t\t\t\t\tclearTimer();\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tclearTimer();\n\t\t};\n\t}, operatorOpts(throttleNodeOpts));\n}\n\n/**\n * Emits the most recent source value whenever `notifier` emits `DATA` (`sample`).\n *\n * Source `COMPLETE` stops sampling (clears held value); notifier `COMPLETE` terminates the\n * operator. `ERROR` from either dep terminates immediately. At most one terminal message is\n * emitted downstream (latch). Supports `resubscribable` — `ctx.store` resets automatically.\n *\n * @param source - Node whose latest value is sampled.\n * @param notifier - When this node emits `DATA`, a sample is taken.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Sampled snapshots of `source`.\n * @example\n * ```ts\n * import { sample, state } from \"@graphrefly/graphrefly-ts\";\n *\n * sample(state(1), state(0));\n * ```\n *\n * @category extra\n */\nexport function sample<T>(source: Node<T>, notifier: Node<unknown>, opts?: ExtraOpts): Node<T> {\n\treturn producer<T>((a) => {\n\t\tlet lastSourceValue: { v: T } | undefined;\n\t\tlet terminated = false;\n\t\tlet sourceCompleted = false;\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tif (terminated) return;\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (terminated) return;\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tlastSourceValue = { v: m[1] as T };\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\tterminated = true;\n\t\t\t\t\ta.down([m]);\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\tsourceCompleted = true;\n\t\t\t\t\tlastSourceValue = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tconst notUnsub = notifier.subscribe((msgs) => {\n\t\t\tif (terminated) return;\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (terminated) return;\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tif (lastSourceValue !== undefined && !sourceCompleted) {\n\t\t\t\t\t\ta.emit(lastSourceValue.v);\n\t\t\t\t\t}\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\tterminated = true;\n\t\t\t\t\ta.down([m]);\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\tterminated = true;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tnotUnsub();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * After each source `DATA`, waits `ms` then emits the latest value if another `DATA` has not arrived (`auditTime` / trailing window).\n *\n * @param source - Upstream node.\n * @param ms - Window in milliseconds after each `DATA`.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Trailing-edge sampled stream.\n * @example\n * ```ts\n * import { audit, state } from \"@graphrefly/graphrefly-ts\";\n *\n * audit(state(0), 100);\n * ```\n *\n * @category extra\n */\nexport function audit<T>(source: Node<T>, ms: number, opts?: ExtraOpts): Node<T> {\n\treturn producer<T>((a) => {\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tlet latest: T | undefined;\n\t\tlet has = false;\n\n\t\tfunction clearTimer(): void {\n\t\t\tif (timer !== undefined) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\ttimer = undefined;\n\t\t\t}\n\t\t}\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tlatest = m[1] as T;\n\t\t\t\t\thas = true;\n\t\t\t\t\tclearTimer();\n\t\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\t\ttimer = undefined;\n\t\t\t\t\t\tif (has) {\n\t\t\t\t\t\t\thas = false;\n\t\t\t\t\t\t\ta.emit(latest as T);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, ms);\n\t\t\t\t} else if (m[0] === COMPLETE || m[0] === ERROR) {\n\t\t\t\t\tclearTimer();\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tclearTimer();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Errors if no `DATA` arrives within `ms` after subscribe or after the previous `DATA`.\n *\n * @param source - Upstream node.\n * @param ms - Idle budget in milliseconds.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`) and `with` for a custom error payload.\n * @returns `Node<T>` - Pass-through with idle watchdog.\n * @example\n * ```ts\n * import { timeout, state } from \"@graphrefly/graphrefly-ts\";\n *\n * timeout(state(0), 5_000);\n * ```\n *\n * @category extra\n */\nexport function timeout<T>(\n\tsource: Node<T>,\n\tms: number,\n\topts?: ExtraOpts & { with?: unknown },\n): Node<T> {\n\tconst { with: withPayload, ...timeoutNodeOpts } = opts ?? {};\n\tconst err = withPayload ?? new Error(\"timeout\");\n\n\treturn producer<T>((a) => {\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\n\t\tfunction arm(): void {\n\t\t\tclearTimeout(timer);\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\ttimer = undefined;\n\t\t\t\ta.down([[ERROR, err]]);\n\t\t\t}, ms);\n\t\t}\n\n\t\t// Arm immediately on subscribe\n\t\tarm();\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tarm();\n\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t} else if (m[0] === COMPLETE || m[0] === ERROR) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tclearTimeout(timer);\n\t\t};\n\t}, operatorOpts(timeoutNodeOpts));\n}\n\n/**\n * Buffers source `DATA` values; flushes an array when `notifier` settles (`buffer`).\n *\n * @param source - Upstream node.\n * @param notifier - Flush trigger on each settlement.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T[]>` - Emits buffered arrays (may be empty-handled via `RESOLVED` when nothing buffered).\n * @example\n * ```ts\n * import { buffer, state } from \"@graphrefly/graphrefly-ts\";\n *\n * buffer(state(0), state(0));\n * ```\n *\n * @category extra\n */\nexport function buffer<T>(source: Node<T>, notifier: Node<unknown>, opts?: ExtraOpts): Node<T[]> {\n\treturn producer<T[]>((a) => {\n\t\tconst buf: T[] = [];\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tbuf.push(m[1] as T);\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\tif (buf.length > 0) a.emit([...buf]);\n\t\t\t\t\tbuf.length = 0;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tconst notUnsub = notifier.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tif (buf.length > 0) {\n\t\t\t\t\t\ta.emit([...buf]);\n\t\t\t\t\t\tbuf.length = 0;\n\t\t\t\t\t}\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\t// Notifier complete — forward\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tnotUnsub();\n\t\t\tbuf.length = 0;\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Batches consecutive `DATA` values into arrays of length `count` (`bufferCount` / `windowCount`).\n *\n * @param source - Upstream node.\n * @param count - Buffer size before emit; must be > 0.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T[]>` - Emits fixed-size arrays; remainder flushes on `COMPLETE`.\n * @example\n * ```ts\n * import { bufferCount, state } from \"@graphrefly/graphrefly-ts\";\n *\n * bufferCount(state(0), 3);\n * ```\n *\n * @category extra\n */\nexport function bufferCount<T>(source: Node<T>, count: number, opts?: ExtraOpts): Node<T[]> {\n\tif (count <= 0) throw new RangeError(\"bufferCount expects count > 0\");\n\treturn producer<T[]>((a) => {\n\t\tconst buf: T[] = [];\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tbuf.push(m[1] as T);\n\t\t\t\t\tif (buf.length >= count) {\n\t\t\t\t\t\ta.emit(buf.splice(0, buf.length));\n\t\t\t\t\t}\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\tif (buf.length > 0) a.emit([...buf]);\n\t\t\t\t\tbuf.length = 0;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tbuf.length = 0;\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Splits source `DATA` into sub-nodes of `count` values each. Each sub-node completes after `count` items or when source completes.\n *\n * @param source - Upstream node.\n * @param count - Items per window.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<Node<T>>` - Each emission is a sub-node carrying that window's values.\n *\n * @example\n * ```ts\n * import { windowCount, state } from \"@graphrefly/graphrefly-ts\";\n *\n * windowCount(state(0), 3);\n * ```\n *\n * @category extra\n */\nexport function windowCount<T>(source: Node<T>, count: number, opts?: ExtraOpts): Node<Node<T>> {\n\tif (count <= 0) throw new RangeError(\"windowCount expects count > 0\");\n\n\treturn producer<Node<T>>((a) => {\n\t\tlet winDown: ((msgs: Messages) => void) | undefined;\n\t\tlet n = 0;\n\n\t\tfunction openWindow(): void {\n\t\t\tconst s = producer<T>((actions) => {\n\t\t\t\twinDown = actions.down.bind(actions);\n\t\t\t\treturn () => {\n\t\t\t\t\twinDown = undefined;\n\t\t\t\t};\n\t\t\t}, operatorOpts());\n\t\t\tn = 0;\n\t\t\ta.emit(s);\n\t\t}\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tif (!winDown) openWindow();\n\t\t\t\t\twinDown?.([[DATA, m[1]]]);\n\t\t\t\t\tn += 1;\n\t\t\t\t\tif (n >= count) {\n\t\t\t\t\t\twinDown?.([[COMPLETE]]);\n\t\t\t\t\t\twinDown = undefined;\n\t\t\t\t\t}\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\twinDown?.([[COMPLETE]]);\n\t\t\t\t\twinDown = undefined;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\twinDown?.([m]);\n\t\t\t\t\twinDown = undefined;\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\twinDown?.([[COMPLETE]]);\n\t\t\twinDown = undefined;\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Flushes buffered `DATA` values every `ms` (`bufferTime` / `windowTime`).\n *\n * @param source - Upstream node.\n * @param ms - Flush interval in milliseconds.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T[]>` - Time-windowed batches.\n * @example\n * ```ts\n * import { bufferTime, state } from \"@graphrefly/graphrefly-ts\";\n *\n * bufferTime(state(0), 250);\n * ```\n *\n * @category extra\n */\nexport function bufferTime<T>(source: Node<T>, ms: number, opts?: ExtraOpts): Node<T[]> {\n\treturn producer<T[]>((a) => {\n\t\tconst buf: T[] = [];\n\n\t\tconst iv = setInterval(() => {\n\t\t\tif (buf.length > 0) {\n\t\t\t\ta.emit([...buf]);\n\t\t\t\tbuf.length = 0;\n\t\t\t}\n\t\t}, ms);\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tbuf.push(m[1] as T);\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\tclearInterval(iv);\n\t\t\t\t\tif (buf.length > 0) a.emit([...buf]);\n\t\t\t\t\tbuf.length = 0;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\tclearInterval(iv);\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t\t// DIRTY from source is NOT forwarded — bufferTime\n\t\t\t\t// transforms the timeline. a.emit(buf) handles full\n\t\t\t\t// DIRTY+DATA framing when the interval fires.\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tclearInterval(iv);\n\t\t\tbuf.length = 0;\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Splits source `DATA` into time-windowed sub-nodes; each window lasts `ms`.\n *\n * @param source - Upstream node.\n * @param ms - Window duration in milliseconds.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<Node<T>>` - Each emission is a sub-node carrying that window's values.\n *\n * @example\n * ```ts\n * import { windowTime, state } from \"@graphrefly/graphrefly-ts\";\n *\n * windowTime(state(0), 500);\n * ```\n *\n * @category extra\n */\nexport function windowTime<T>(source: Node<T>, ms: number, opts?: ExtraOpts): Node<Node<T>> {\n\treturn producer<Node<T>>((a) => {\n\t\tlet winDown: ((msgs: Messages) => void) | undefined;\n\n\t\tfunction closeWindow(): void {\n\t\t\twinDown?.([[COMPLETE]]);\n\t\t\twinDown = undefined;\n\t\t}\n\n\t\tfunction openWindow(): void {\n\t\t\tconst s = producer<T>((actions) => {\n\t\t\t\twinDown = actions.down.bind(actions);\n\t\t\t\treturn () => {\n\t\t\t\t\twinDown = undefined;\n\t\t\t\t};\n\t\t\t}, operatorOpts());\n\t\t\ta.emit(s);\n\t\t}\n\n\t\topenWindow();\n\t\tconst iv = setInterval(() => {\n\t\t\tcloseWindow();\n\t\t\topenWindow();\n\t\t}, ms);\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\twinDown?.([[DATA, m[1]]]);\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\tclearInterval(iv);\n\t\t\t\t\tcloseWindow();\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\tclearInterval(iv);\n\t\t\t\t\twinDown?.([m]);\n\t\t\t\t\tcloseWindow();\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tclearInterval(iv);\n\t\t\tcloseWindow();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Splits source `DATA` into sub-nodes, opening a new window each time `notifier` emits `DATA`.\n *\n * @param source - Upstream node.\n * @param notifier - Each `DATA` from `notifier` closes the current window and opens a new one.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<Node<T>>` - Each emission is a sub-node carrying that window's values.\n *\n * @example\n * ```ts\n * import { state, window } from \"@graphrefly/graphrefly-ts\";\n *\n * window(state(0), state(0));\n * ```\n *\n * @category extra\n */\nexport function window<T>(\n\tsource: Node<T>,\n\tnotifier: Node<unknown>,\n\topts?: ExtraOpts,\n): Node<Node<T>> {\n\treturn producer<Node<T>>((a) => {\n\t\tlet winDown: ((msgs: Messages) => void) | undefined;\n\n\t\tfunction closeWindow(): void {\n\t\t\twinDown?.([[COMPLETE]]);\n\t\t\twinDown = undefined;\n\t\t}\n\n\t\tfunction openWindow(): void {\n\t\t\tconst s = producer<T>((actions) => {\n\t\t\t\twinDown = actions.down.bind(actions);\n\t\t\t\treturn () => {\n\t\t\t\t\twinDown = undefined;\n\t\t\t\t};\n\t\t\t}, operatorOpts());\n\t\t\ta.emit(s);\n\t\t}\n\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tif (!winDown) openWindow();\n\t\t\t\t\twinDown?.([[DATA, m[1]]]);\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\tcloseWindow();\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\twinDown?.([m]);\n\t\t\t\t\twinDown = undefined;\n\t\t\t\t\ta.down([m]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tconst notUnsub = notifier.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tcloseWindow();\n\t\t\t\t\topenWindow();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t\tnotUnsub();\n\t\t\tcloseWindow();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Increments on each tick (`interval`); uses `setInterval` via {@link producer}.\n *\n * @param periodMs - Time between ticks.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<number>` - Emits `0`, `1`, `2`, … while subscribed.\n * @example\n * ```ts\n * import { interval } from \"@graphrefly/graphrefly-ts\";\n *\n * interval(1_000);\n * ```\n *\n * @category extra\n */\nexport function interval(periodMs: number, opts?: ExtraOpts): Node<number> {\n\treturn producer<number>((a, ctx) => {\n\t\tif (!(\"n\" in ctx.store)) ctx.store.n = 0;\n\t\tconst id = setInterval(() => {\n\t\t\ta.emit(ctx.store.n as number);\n\t\t\tctx.store.n = (ctx.store.n as number) + 1;\n\t\t}, periodMs);\n\t\treturn () => clearInterval(id);\n\t}, operatorOpts(opts));\n}\n\n/**\n * Subscribes to `source` repeatedly (`count` times, sequentially). Best with a fresh or `resubscribable` source.\n *\n * @param source - Upstream node to replay.\n * @param count - Number of subscription rounds.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Forwards each round then completes after the last inner `COMPLETE`.\n * @example\n * ```ts\n * import { repeat, state } from \"@graphrefly/graphrefly-ts\";\n *\n * repeat(state(1, { resubscribable: true }), 2);\n * ```\n *\n * @category extra\n */\nexport function repeat<T>(source: Node<T>, count: number, opts?: ExtraOpts): Node<T> {\n\tif (count <= 0) throw new RangeError(\"repeat expects count > 0\");\n\treturn producer<T>((a) => {\n\t\tlet remaining = count;\n\t\tlet innerU: (() => void) | undefined;\n\n\t\tconst start = (): void => {\n\t\t\tinnerU?.();\n\t\t\tinnerU = source.subscribe((msgs) => {\n\t\t\t\tlet completed = false;\n\t\t\t\tconst fwd: Message[] = [];\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === COMPLETE) completed = true;\n\t\t\t\t\telse fwd.push(m);\n\t\t\t\t}\n\t\t\t\tif (fwd.length > 0) a.down(fwd as unknown as Messages);\n\t\t\t\tif (completed) {\n\t\t\t\t\tinnerU?.();\n\t\t\t\t\tinnerU = undefined;\n\t\t\t\t\tremaining -= 1;\n\t\t\t\t\tif (remaining > 0) start();\n\t\t\t\t\telse a.down([[COMPLETE]]);\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\tstart();\n\t\treturn () => {\n\t\t\tinnerU?.();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Identity passthrough — `pausable()` has been promoted to default node behavior in v5 (§4).\n *\n * @deprecated Default node behavior now handles PAUSE/RESUME. This operator is a no-op\n * identity passthrough kept only for migration compatibility.\n *\n * @param source - Upstream node.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Pass-through (identity).\n * @example\n * ```ts\n * import { pausable, state } from \"@graphrefly/graphrefly-ts\";\n *\n * // No longer needed — default nodes handle PAUSE/RESUME.\n * const s = state(0);\n * pausable(s); // identity passthrough\n * ```\n *\n * @category extra\n */\nexport function pausable<T>(source: Node<T>, opts?: ExtraOpts): Node<T> {\n\treturn node<T>(\n\t\t[source as Node],\n\t\t(data, a) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0) a.emit(v as T);\n\t\t},\n\t\toperatorOpts<T>(opts),\n\t);\n}\n\n/**\n * Replaces an upstream `ERROR` with a recovered value (`catchError`-style).\n *\n * @param source - Upstream node.\n * @param recover - Maps the error payload to a replacement value; if it throws, `ERROR` is forwarded.\n * @param opts - Optional {@link NodeOptions} (excluding `describeKind`).\n * @returns `Node<T>` - Recovered stream.\n * @example\n * ```ts\n * import { rescue, state } from \"@graphrefly/graphrefly-ts\";\n *\n * rescue(state(0), () => 0);\n * ```\n *\n * @category extra\n */\nexport function rescue<T>(\n\tsource: Node<T>,\n\trecover: (err: unknown) => T,\n\topts?: ExtraOpts,\n): Node<T> {\n\treturn producer<T>((a) => {\n\t\tconst srcUnsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\ta.emit(recover(m[1]));\n\t\t\t\t\t} catch (recoverErr) {\n\t\t\t\t\t\ta.down([[ERROR, recoverErr]]);\n\t\t\t\t\t}\n\t\t\t\t} else if (m[0] === COMPLETE) {\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn () => {\n\t\t\tsrcUnsub();\n\t\t};\n\t}, operatorOpts(opts));\n}\n\n/**\n * Forwards upstream `DATA` only while `control.get()` is truthy; when closed, emits `RESOLVED`\n * instead of repeating the last value (value-level valve). For protocol pause/resume, use default\n * node PAUSE/RESUME behavior.\n *\n * @param source - Upstream value node.\n * @param control - Boolean node; when falsy, output stays \"closed\" for that tick.\n * @param opts - Optional node options (excluding `describeKind`).\n * @returns `Node<T>` gated by `control`.\n *\n * @example\n * ```ts\n * import { valve, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const data = state(1);\n * const open = state(true);\n * valve(data, open);\n * ```\n *\n * @category extra\n */\nexport function valve<T>(source: Node<T>, control: Node<boolean>, opts?: ExtraOpts): Node<T> {\n\treturn node<T>(\n\t\t[source as Node, control as Node],\n\t\t(data, a, ctx) => {\n\t\t\tconst batch1 = data[1];\n\t\t\t// undefined = control never sent DATA (gate closed); falsy = explicitly closed.\n\t\t\tconst controlValue = batch1 != null && batch1.length > 0 ? batch1.at(-1) : ctx.prevData[1];\n\t\t\tif (!controlValue) {\n\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst batch0 = data[0];\n\t\t\tif (batch0 != null && batch0.length > 0) {\n\t\t\t\t// Source data this wave: forward it.\n\t\t\t\tfor (const v of batch0) a.emit(v as T);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Control just opened this wave but source didn't fire this wave.\n\t\t\t// Re-emit the last known source value so downstream sees the current\n\t\t\t// value when the gate opens (only when source has a prior value).\n\t\t\tif (batch1 != null && batch1.length > 0 && ctx.prevData[0] !== undefined) {\n\t\t\t\ta.emit(ctx.prevData[0] as T);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ta.down([[RESOLVED]]);\n\t\t},\n\t\toperatorOpts(opts),\n\t);\n}\n\n// ——————————————————————————————————————————————————————————————\n// RxJS-compatible aliases — improve AI code-generation accuracy\n// ——————————————————————————————————————————————————————————————\n\n/**\n * RxJS-named alias for {@link combine} — emits when any dep updates with latest tuple of values.\n *\n * @param sources - Upstream nodes as separate arguments (same calling shape as `combine`).\n * @returns Combined node; signature matches `combine`.\n *\n * @example\n * ```ts\n * import { combineLatest, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const n = combineLatest(state(1), state(\"a\"));\n * ```\n *\n * @category extra\n */\nexport const combineLatest = combine;\n\n/**\n * RxJS-named alias for {@link debounce} — drops rapid `DATA` until `ms` of quiet.\n *\n * @param source - Upstream node.\n * @param ms - Quiet period in milliseconds.\n * @param opts - Optional node options (excluding `describeKind`).\n * @returns Debounced node; behavior matches `debounce`.\n *\n * @example\n * ```ts\n * import { debounceTime, state } from \"@graphrefly/graphrefly-ts\";\n *\n * debounceTime(state(0), 100);\n * ```\n *\n * @category extra\n */\nexport const debounceTime = debounce;\n\n/**\n * RxJS-named alias for {@link throttle} — emits on leading/trailing edges within `ms`.\n *\n * @param source - Upstream node.\n * @param ms - Minimum spacing in milliseconds.\n * @param opts - Optional throttle shape (`leading` / `trailing`) and node options.\n * @returns Throttled node; behavior matches `throttle`.\n *\n * @example\n * ```ts\n * import { throttleTime, state } from \"@graphrefly/graphrefly-ts\";\n *\n * throttleTime(state(0), 100);\n * ```\n *\n * @category extra\n */\nexport const throttleTime = throttle;\n\n/**\n * RxJS-named alias for {@link rescue} — replaces upstream `ERROR` with a recovered value.\n *\n * @param source - Upstream node.\n * @param recover - Maps error payload to replacement value.\n * @param opts - Optional node options (excluding `describeKind`).\n * @returns Recovered stream; behavior matches `rescue`.\n *\n * @example\n * ```ts\n * import { catchError, state } from \"@graphrefly/graphrefly-ts\";\n *\n * catchError(state(0), () => 0);\n * ```\n *\n * @category extra\n */\nexport const catchError = rescue;\n","/**\n * Reactive key–value map (roadmap §3.2) — emits `ReadonlyMap` snapshots directly.\n *\n * Internal version counter drives efficient equality without leaking `Versioned`\n * into the public API (spec §5.12).\n *\n * **Wave 4 refactor (2026-04-15):** Introduces the `MapBackend<K, V>` pluggable-backend\n * interface. The default `NativeMapBackend` owns LRU ordering, TTL expiry, and a\n * monotonic `version` counter. Reads that discover expired entries prune them and\n * emit (fixes the former `size`-getter stale-snapshot gap).\n */\nimport { batch } from \"../core/batch.js\";\nimport { monotonicNs } from \"../core/clock.js\";\nimport { DATA, DIRTY } from \"../core/messages.js\";\nimport type { Node, NodeOptions } from \"../core/node.js\";\nimport { state } from \"../core/sugar.js\";\nimport type { VersioningLevel } from \"../core/versioning.js\";\n\nexport type ReactiveMapOptions<K, V> = {\n\t/** Optional registry name for `describe()` / debugging. */\n\tname?: string;\n\t/**\n\t * LRU cap. When set, evicts least-recently-used keys after inserts that exceed this size.\n\t * Forwarded to the default `NativeMapBackend`. Ignored if a custom `backend` is provided.\n\t */\n\tmaxSize?: number;\n\t/**\n\t * Default TTL in seconds. Used when `set`/`setMany` omits per-call `ttl`.\n\t * Forwarded to the default `NativeMapBackend`. Ignored if a custom `backend` is provided.\n\t */\n\tdefaultTtl?: number;\n\t/**\n\t * Storage backend. Defaults to `NativeMapBackend`. Users can plug in persistent\n\t * (HAMT / Immutable.js) or shared-state backends via the {@link MapBackend} interface.\n\t */\n\tbackend?: MapBackend<K, V>;\n\t/**\n\t * Optional versioning level for the underlying `entries` state node. Set at\n\t * construction time; cannot be changed later. Pass `0` for V0 identity +\n\t * monotonic version counter, or `1` for V1 + content-addressed cid.\n\t */\n\tversioning?: VersioningLevel;\n} & Omit<NodeOptions, \"initial\" | \"describeKind\" | \"equals\" | \"versioning\">;\n\nexport type ReactiveMapBundle<K, V> = {\n\t/** Emits `ReadonlyMap<K, V>` on each structural change (two-phase). */\n\tentries: Node<ReadonlyMap<K, V>>;\n\t/**\n\t * Checks existence. O(1) for live keys. If the key is expired, prunes it AND\n\t * emits a snapshot so the reactive surface stays consistent with the return\n\t * value. Reads on expired keys are therefore **observable side effects**.\n\t *\n\t * **LRU touch (F4):** When `maxSize` is configured, a live-key `has` also\n\t * marks the entry as most-recently-used — which rearranges internal insertion\n\t * order without bumping `version` or emitting. If you care about iteration\n\t * order in a downstream subscriber, rely on the `entries` snapshot (a fresh\n\t * `ReadonlyMap` per mutation) rather than iterating the backend directly.\n\t */\n\thas: (key: K) => boolean;\n\t/**\n\t * Gets value. O(1) for live keys. If the key is expired, prunes it AND emits\n\t * a snapshot. Reads on expired keys are therefore **observable side effects**.\n\t *\n\t * **LRU touch (F4):** When `maxSize` is configured, a live-key `get` also\n\t * marks the entry as most-recently-used (no version bump, no emission). See\n\t * `has` for the full note on iteration order.\n\t */\n\tget: (key: K) => V | undefined;\n\t/**\n\t * Sets value with optional TTL (seconds). Throws on `ttl <= 0`. Applies LRU eviction\n\t * if `maxSize` is set. Always emits.\n\t */\n\tset: (key: K, value: V, opts?: { ttl?: number }) => void;\n\t/**\n\t * Bulk set — emits one snapshot for the whole batch. Applies `opts.ttl` (falls back\n\t * to `defaultTtl`) to every entry. No-op if `entries` is empty.\n\t *\n\t * **Iterable consumption:** Consumes `entries` once (single-pass). Pass an array\n\t * or `Set` for multi-shot consumers. If the iterator throws mid-iteration,\n\t * entries already applied remain committed and a snapshot IS emitted (via the\n\t * wrapper's finally-block).\n\t */\n\tsetMany: (entries: Iterable<readonly [K, V]>, opts?: { ttl?: number }) => void;\n\tdelete: (key: K) => void;\n\t/**\n\t * Bulk delete — emits one snapshot. No-op if no keys were present.\n\t *\n\t * **Iterable consumption:** Consumes `keys` once (single-pass).\n\t */\n\tdeleteMany: (keys: Iterable<K>) => void;\n\tclear: () => void;\n\t/**\n\t * Current entry count — O(1), **pure read** (no emission). May include\n\t * expired entries on TTL maps until a mutation or explicit\n\t * `pruneExpired()` / `has(key)` / `get(key)` prunes them. Call\n\t * `pruneExpired()` first if you need a live count.\n\t */\n\treadonly size: number;\n\t/** Explicitly prunes all expired entries. Emits if any were removed. */\n\tpruneExpired: () => void;\n\t/**\n\t * Releases any internal keepalive subscriptions so the bundle can be\n\t * GC'd. `reactiveMap` currently holds none (the `entries` node lives only\n\t * as long as external subscribers keep it alive), so `dispose()` is a\n\t * no-op today — exposed for API parity with `reactiveIndex.dispose` /\n\t * `reactiveList.dispose` / `reactiveLog.dispose`. Idempotent. D6(a).\n\t */\n\tdispose: () => void;\n};\n\n// ── Backend interface ─────────────────────────────────────────────────────\n\n/**\n * Storage contract for {@link reactiveMap}. Implementations own the mutable state,\n * including optional TTL and LRU semantics, and expose a monotonic `version` counter\n * that increments on every change to visible state.\n *\n * The reactive layer reads `version` before and after each backend call; when it\n * advances, a snapshot is emitted. Reads (`has`, `get`) may internally prune the\n * target key if expired and advance `version` — in which case the layer emits so\n * subscribers see state consistent with the read's return value.\n *\n * @remarks Post-1.0 op-log changesets will extend this interface with a\n * `changesSince(version: number): Iterable<Change>` method. Current consumers\n * should treat all methods here as stable.\n *\n * @category extra\n */\nexport interface MapBackend<K, V> {\n\t/** Monotonic mutation counter; increments on every visible state change. */\n\treadonly version: number;\n\t/** Raw entry count (may include expired entries until a read / prune removes them). */\n\treadonly size: number;\n\t/** Checks existence. May prune target key if expired; advances `version` if pruned. */\n\thas(key: K): boolean;\n\t/** Gets value. May prune target key if expired; advances `version` if pruned. */\n\tget(key: K): V | undefined;\n\t/**\n\t * Sets a value with optional TTL (seconds). Throws `RangeError` if `ttl <= 0`.\n\t * Applies LRU eviction if `maxSize` is configured. Advances `version`.\n\t *\n\t * **Atomicity contract:** Either fully succeeds or throws before any state\n\t * change; `version` advances only on success.\n\t */\n\tset(key: K, value: V, ttl?: number): void;\n\t/**\n\t * Atomic bulk set. Pre-validates TTL once, then applies all entries. Advances\n\t * `version` at most once (even for N entries). No-op if iterable is empty.\n\t *\n\t * **Consumes `entries` once** — pass an array if you want repeatability.\n\t *\n\t * **Atomicity contract:** TTL validation throws before any mutation. If the\n\t * iterable itself throws mid-iteration, entries committed before the throw\n\t * remain persisted AND `version` is bumped once (surfaced via finally) so\n\t * the reactive wrapper emits a snapshot reflecting the partial state. \"At\n\t * most once\" invariant is preserved.\n\t */\n\tsetMany(entries: Iterable<readonly [K, V]>, ttl?: number): void;\n\t/** Removes a key. Returns `true` if the key existed. Advances `version` only if true. */\n\tdelete(key: K): boolean;\n\t/**\n\t * Atomic bulk delete. Returns count removed. Advances `version` at most once\n\t * (even for N keys). No-op if no keys were present. Consumes `keys` once.\n\t */\n\tdeleteMany(keys: Iterable<K>): number;\n\t/** Removes all entries. Returns count removed. Advances `version` only if non-zero. */\n\tclear(): number;\n\t/** Removes all expired entries. Returns count removed. Advances `version` only if non-zero. */\n\tpruneExpired(): number;\n\t/** Fresh snapshot of non-expired entries (does NOT mutate state). */\n\ttoMap(): ReadonlyMap<K, V>;\n}\n\nexport type NativeMapBackendOptions = {\n\tmaxSize?: number;\n\t/** Default TTL in seconds. */\n\tdefaultTtl?: number;\n};\n\ntype MapEntry<V> = { value: V; expiresAt?: number };\n\n/**\n * Default `Map<K, {value, expiresAt}>` backend with optional per-key TTL and LRU cap.\n *\n * **Complexity:**\n * - `has`, `get`, `delete`, `size`: O(1)\n * - `set`: O(1) amortized (LRU touch + eviction)\n * - `pruneExpired`, `toMap`: O(n)\n *\n * LRU order uses native `Map` insertion order. `get` / `has` on a live key \"touches\"\n * it by delete-then-reinsert (moving it to the end). This touch does NOT advance\n * `version` — it's an internal optimization; the externally visible snapshot\n * preserves iteration order as of the last mutation. **Note:** because touch\n * reorders the internal `_store` without emitting, an in-process consumer iterating\n * `_store` directly (custom subclasses) could observe changing order; external\n * subscribers only see `toMap()` snapshots which are defensively copied and stable.\n *\n * @category extra\n */\nexport class NativeMapBackend<K, V> implements MapBackend<K, V> {\n\tprivate _version = 0;\n\tprivate readonly _store = new Map<K, MapEntry<V>>();\n\tprivate readonly _maxSize?: number;\n\tprivate readonly _defaultTtl?: number;\n\n\tconstructor(options: NativeMapBackendOptions = {}) {\n\t\tconst { maxSize, defaultTtl } = options;\n\t\tif (maxSize !== undefined && maxSize < 1) {\n\t\t\tthrow new RangeError(\"maxSize must be >= 1\");\n\t\t}\n\t\tif (defaultTtl !== undefined && defaultTtl <= 0) {\n\t\t\tthrow new RangeError(\"defaultTtl must be positive\");\n\t\t}\n\t\tthis._maxSize = maxSize;\n\t\tthis._defaultTtl = defaultTtl;\n\t}\n\n\tget version(): number {\n\t\treturn this._version;\n\t}\n\n\tget size(): number {\n\t\treturn this._store.size;\n\t}\n\n\thas(key: K): boolean {\n\t\tconst e = this._store.get(key);\n\t\tif (e === undefined) return false;\n\t\tif (this._isExpired(e)) {\n\t\t\tthis._store.delete(key);\n\t\t\tthis._version += 1;\n\t\t\treturn false;\n\t\t}\n\t\tthis._touchLru(key, e);\n\t\treturn true;\n\t}\n\n\tget(key: K): V | undefined {\n\t\tconst e = this._store.get(key);\n\t\tif (e === undefined) return undefined;\n\t\tif (this._isExpired(e)) {\n\t\t\tthis._store.delete(key);\n\t\t\tthis._version += 1;\n\t\t\treturn undefined;\n\t\t}\n\t\tthis._touchLru(key, e);\n\t\treturn e.value;\n\t}\n\n\tset(key: K, value: V, ttl?: number): void {\n\t\tconst expiresAt = this._resolveExpiresAt(ttl);\n\t\t// Delete-then-insert to place key at LRU end.\n\t\tif (this._store.has(key)) this._store.delete(key);\n\t\tthis._store.set(key, { value, expiresAt });\n\t\tthis._evictLruWhileOver();\n\t\tthis._version += 1;\n\t}\n\n\tsetMany(entries: Iterable<readonly [K, V]>, ttl?: number): void {\n\t\t// Pre-validate TTL once (throws before any mutation).\n\t\tconst expiresAt = this._resolveExpiresAt(ttl);\n\t\tlet count = 0;\n\t\ttry {\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tif (this._store.has(key)) this._store.delete(key);\n\t\t\t\tthis._store.set(key, { value, expiresAt });\n\t\t\t\tcount += 1;\n\t\t\t}\n\t\t} finally {\n\t\t\t// D3: if the iterable threw mid-iteration, entries committed before\n\t\t\t// the throw must still advance `version` so subscribers see the\n\t\t\t// partial state consistently. \"At most once\" is preserved.\n\t\t\tif (count > 0) {\n\t\t\t\tthis._evictLruWhileOver();\n\t\t\t\tthis._version += 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tdelete(key: K): boolean {\n\t\tconst had = this._store.delete(key);\n\t\tif (had) this._version += 1;\n\t\treturn had;\n\t}\n\n\tdeleteMany(keys: Iterable<K>): number {\n\t\tlet removed = 0;\n\t\ttry {\n\t\t\tfor (const k of keys) {\n\t\t\t\tif (this._store.delete(k)) removed += 1;\n\t\t\t}\n\t\t} finally {\n\t\t\tif (removed > 0) this._version += 1;\n\t\t}\n\t\treturn removed;\n\t}\n\n\tclear(): number {\n\t\tconst n = this._store.size;\n\t\tif (n === 0) return 0;\n\t\tthis._store.clear();\n\t\tthis._version += 1;\n\t\treturn n;\n\t}\n\n\tpruneExpired(): number {\n\t\tconst now = monotonicNs();\n\t\tlet removed = 0;\n\t\tfor (const [k, e] of this._store) {\n\t\t\tif (this._isExpired(e, now)) {\n\t\t\t\tthis._store.delete(k);\n\t\t\t\tremoved += 1;\n\t\t\t}\n\t\t}\n\t\tif (removed > 0) this._version += 1;\n\t\treturn removed;\n\t}\n\n\ttoMap(): ReadonlyMap<K, V> {\n\t\tconst now = monotonicNs();\n\t\tconst out = new Map<K, V>();\n\t\tfor (const [k, e] of this._store) {\n\t\t\tif (!this._isExpired(e, now)) out.set(k, e.value);\n\t\t}\n\t\treturn out;\n\t}\n\n\tprivate _resolveExpiresAt(ttl?: number): number | undefined {\n\t\tconst effectiveTtl = ttl ?? this._defaultTtl;\n\t\tif (effectiveTtl === undefined) return undefined;\n\t\tif (!Number.isFinite(effectiveTtl) || effectiveTtl <= 0) {\n\t\t\tthrow new RangeError(\n\t\t\t\t`MapBackend: ttl must be a positive finite number (got ${effectiveTtl})`,\n\t\t\t);\n\t\t}\n\t\treturn monotonicNs() + effectiveTtl * 1_000_000_000;\n\t}\n\n\tprivate _isExpired(e: MapEntry<V>, now?: number): boolean {\n\t\tif (e.expiresAt === undefined) return false;\n\t\treturn (now ?? monotonicNs()) >= e.expiresAt;\n\t}\n\n\tprivate _touchLru(key: K, entry: MapEntry<V>): void {\n\t\t// Move to LRU end. Does NOT advance `version` — internal optimization.\n\t\tthis._store.delete(key);\n\t\tthis._store.set(key, entry);\n\t}\n\n\tprivate _evictLruWhileOver(): void {\n\t\tif (this._maxSize === undefined) return;\n\t\twhile (this._store.size > this._maxSize) {\n\t\t\tconst first = this._store.keys().next().value as K | undefined;\n\t\t\tif (first === undefined) break;\n\t\t\tthis._store.delete(first);\n\t\t}\n\t}\n}\n\n// ── Reactive wrapper ──────────────────────────────────────────────────────\n\n/**\n * Creates a reactive `Map` with optional per-key TTL and optional LRU max size.\n *\n * @param options - `name`, `maxSize`, `defaultTtl` (seconds), or custom `backend`.\n * @returns `ReactiveMapBundle` — imperative methods (`has`/`get`/`set`/`setMany`/`delete`/\n * `deleteMany`/`clear`/`pruneExpired`), reactive `entries` node, and O(1)-ish `size`.\n *\n * @remarks\n * **TTL:** Expiry is checked on `get`, `has`, `size`, `pruneExpired`, and before each\n * snapshot emission (expired keys are pruned first). Reads that discover expired keys\n * emit a snapshot so subscribers see state consistent with the read's return value.\n * There is no background timer; monotonic-clock expiry is immune to wall-clock changes.\n *\n * **LRU:** Uses native `Map` insertion order — `get` / `has` refreshes position via\n * delete-then-reinsert; under `maxSize` pressure the first key in iteration order is\n * evicted. LRU touching does NOT trigger emission (internal optimization).\n *\n * **Backend:** The default {@link NativeMapBackend} owns LRU/TTL. For persistent /\n * HAMT / shared-state semantics plug in a custom {@link MapBackend}. `maxSize` and\n * `defaultTtl` on the options object are only applied to the default backend — if\n * you supply `backend`, configure those on your backend directly.\n *\n * @example\n * ```ts\n * import { reactiveMap } from \"@graphrefly/graphrefly-ts\";\n *\n * const m = reactiveMap<string, number>({ name: \"cache\", maxSize: 100, defaultTtl: 60 });\n * m.set(\"x\", 1);\n * m.setMany([[\"y\", 2], [\"z\", 3]]);\n * m.entries.subscribe((msgs) => { console.log(msgs); });\n * ```\n *\n * @category extra\n */\nexport function reactiveMap<K, V>(options: ReactiveMapOptions<K, V> = {}): ReactiveMapBundle<K, V> {\n\tconst { name, maxSize, defaultTtl, versioning, backend: userBackend } = options;\n\tconst backend: MapBackend<K, V> =\n\t\tuserBackend ?? new NativeMapBackend<K, V>({ maxSize, defaultTtl });\n\n\tconst n = state<ReadonlyMap<K, V>>(backend.toMap(), {\n\t\tname,\n\t\tdescribeKind: \"state\",\n\t\tequals: (a, b) => a === b,\n\t\t...(versioning != null ? { versioning } : {}),\n\t});\n\n\tfunction pushSnapshot(): void {\n\t\tconst map = backend.toMap();\n\t\tbatch(() => {\n\t\t\tn.down([[DIRTY]]);\n\t\t\tn.down([[DATA, map]]);\n\t\t});\n\t}\n\n\t/**\n\t * Defense-in-depth emission guard: compares `version` before/after `op` and\n\t * emits a snapshot if advanced. Uses `try/finally` so partial-mutation state\n\t * from a custom non-atomic backend is still surfaced to subscribers if the\n\t * op throws mid-way (native backends are atomic by contract and won't trip\n\t * this path).\n\t */\n\tfunction wrapMutation<T>(op: () => T): T {\n\t\tconst prev = backend.version;\n\t\ttry {\n\t\t\treturn op();\n\t\t} finally {\n\t\t\tif (backend.version !== prev) pushSnapshot();\n\t\t}\n\t}\n\n\treturn {\n\t\tentries: n,\n\n\t\thas(key: K): boolean {\n\t\t\treturn wrapMutation(() => backend.has(key));\n\t\t},\n\n\t\tget(key: K): V | undefined {\n\t\t\treturn wrapMutation(() => backend.get(key));\n\t\t},\n\n\t\tset(key: K, value: V, opts?: { ttl?: number }): void {\n\t\t\twrapMutation(() => backend.set(key, value, opts?.ttl));\n\t\t},\n\n\t\tsetMany(entries: Iterable<readonly [K, V]>, opts?: { ttl?: number }): void {\n\t\t\twrapMutation(() => backend.setMany(entries, opts?.ttl));\n\t\t},\n\n\t\tdelete(key: K): void {\n\t\t\twrapMutation(() => backend.delete(key));\n\t\t},\n\n\t\tdeleteMany(keys: Iterable<K>): void {\n\t\t\twrapMutation(() => backend.deleteMany(keys));\n\t\t},\n\n\t\tclear(): void {\n\t\t\twrapMutation(() => backend.clear());\n\t\t},\n\n\t\tpruneExpired(): void {\n\t\t\twrapMutation(() => backend.pruneExpired());\n\t\t},\n\n\t\t/**\n\t\t * Current raw entry count — O(1), **pure read**. May include\n\t\t * not-yet-pruned expired entries on TTL maps until the next mutation\n\t\t * or an explicit `pruneExpired()` / `has` / `get` triggers a prune.\n\t\t *\n\t\t * Previously this getter ran `pruneExpired()` inline and emitted a\n\t\t * snapshot as a side effect — that violated spec §5.8 \"no\n\t\t * side-effectful reads\" and created a re-entrancy hazard when a\n\t\t * subscriber to `entries` read `.size` from its own callback. D2(a).\n\t\t *\n\t\t * For a live count that excludes expired entries, call\n\t\t * `bundle.pruneExpired()` first.\n\t\t */\n\t\tget size(): number {\n\t\t\treturn backend.size;\n\t\t},\n\n\t\tdispose(): void {\n\t\t\t// D6(a): no internal keepalives yet — no-op for API parity with\n\t\t\t// reactive-index / reactive-list / reactive-log. If a future\n\t\t\t// refactor adds a keepalive (e.g. on `entries`), wire its\n\t\t\t// disposer here.\n\t\t},\n\t};\n}\n","/**\n * Composite data patterns (roadmap §3.2b).\n *\n * These helpers compose existing primitives (`node`, `switchMap`, `reactiveMap`,\n * `dynamicNode`, `fromAny`) without introducing new protocol semantics.\n */\n\nimport { batch } from \"../core/batch.js\";\nimport { DATA } from \"../core/messages.js\";\nimport type { Node, NodeOptions } from \"../core/node.js\";\nimport { derived, state } from \"../core/sugar.js\";\nimport { merge, switchMap } from \"./operators.js\";\nimport { type ReactiveMapBundle, type ReactiveMapOptions, reactiveMap } from \"./reactive-map.js\";\nimport { forEach, fromAny, type NodeInput } from \"./sources.js\";\n\nfunction isNodeLike<T>(value: unknown): value is Node<T> {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"cache\" in (value as Node<T>) &&\n\t\ttypeof (value as Node<T>).subscribe === \"function\"\n\t);\n}\n\n/**\n * Verification payload shape is intentionally user-defined.\n */\nexport type VerifyValue = unknown;\n\nexport type VerifiableOptions<TVerify = VerifyValue> = Omit<\n\tNodeOptions,\n\t\"describeKind\" | \"initial\"\n> & {\n\t/** Reactive re-verification trigger. */\n\ttrigger?: NodeInput<unknown>;\n\t/** Re-run verification whenever `source` settles. */\n\tautoVerify?: boolean;\n\t/** Initial verification companion value. */\n\tinitialVerified?: TVerify | null;\n};\n\nexport type VerifiableBundle<T, TVerify = VerifyValue> = {\n\t/** Coerced source node. */\n\tnode: Node<T>;\n\t/** Latest verification result (`null` before first verification). */\n\tverified: Node<TVerify | null>;\n\t/** Effective trigger node used for verification, if any. */\n\ttrigger: Node<unknown> | null;\n};\n\n/**\n * Composes a value node with a reactive verification companion.\n *\n * Uses `switchMap` so newer triggers cancel stale in-flight verification work.\n */\nexport function verifiable<T, TVerify = VerifyValue>(\n\tsource: NodeInput<T>,\n\tverifyFn: (value: T) => NodeInput<TVerify>,\n\topts?: VerifiableOptions<TVerify>,\n): VerifiableBundle<T, TVerify> {\n\tconst sourceNode = fromAny(source);\n\tconst hasSourceVersioning = sourceNode.v != null;\n\tconst verified = state<TVerify | null>(opts?.initialVerified ?? null, {\n\t\t...(hasSourceVersioning ? { meta: { sourceVersion: null } } : {}),\n\t});\n\tconst hasTrigger = opts?.trigger !== undefined && opts.trigger !== null;\n\n\tlet triggerNode: Node<unknown> | null = null;\n\tif (hasTrigger && opts?.autoVerify) {\n\t\ttriggerNode = merge(fromAny(opts.trigger) as Node<unknown>, sourceNode as Node<unknown>);\n\t} else if (hasTrigger) {\n\t\ttriggerNode = fromAny(opts.trigger);\n\t} else if (opts?.autoVerify) {\n\t\ttriggerNode = sourceNode as Node<unknown>;\n\t}\n\n\tif (triggerNode !== null) {\n\t\t// Closes P3 audit #2. Two patterns used depending on trigger shape:\n\t\t// - autoVerify-only (triggerNode === sourceNode): the projected\n\t\t// switchMap value IS the source DATA, pass it directly.\n\t\t// - explicit trigger: capture the source value into a closure\n\t\t// (`latestSource`) seeded from `sourceNode.cache` at wiring time\n\t\t// (§3.6 boundary read) and kept current via a subscribe handler.\n\t\t// The switchMap fn reads the closure, never `sourceNode.cache`\n\t\t// from a reactive context.\n\t\tlet verifyStream: Node<TVerify>;\n\t\tif (triggerNode === (sourceNode as Node<unknown>)) {\n\t\t\tverifyStream = switchMap(sourceNode, (src) => verifyFn(src as T));\n\t\t} else {\n\t\t\tlet latestSource: T | undefined = sourceNode.cache as T | undefined;\n\t\t\tsourceNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === DATA) latestSource = m[1] as T;\n\t\t\t\t}\n\t\t\t});\n\t\t\tverifyStream = switchMap(triggerNode, () => verifyFn(latestSource as T));\n\t\t}\n\t\tforEach(verifyStream, (value) => {\n\t\t\tbatch(() => {\n\t\t\t\tverified.down([[DATA, value]]);\n\t\t\t\t// V0 backfill: stamp which source version was verified (§6.0b).\n\t\t\t\tif (hasSourceVersioning) {\n\t\t\t\t\tconst sv = sourceNode.v;\n\t\t\t\t\tif (sv != null) {\n\t\t\t\t\t\tverified.meta.sourceVersion.down([[DATA, { id: sv.id, version: sv.version }]]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\treturn { node: sourceNode, verified, trigger: triggerNode };\n}\n\nexport type Extraction<TMem> = {\n\tupsert: Array<{ key: string; value: TMem }>;\n\tremove?: string[];\n};\n\nexport type DistillOptions<TMem> = {\n\tscore: (mem: TMem, context: unknown) => number;\n\tcost: (mem: TMem) => number;\n\tbudget?: number;\n\tevict?: (key: string, mem: TMem) => boolean | Node<boolean>;\n\tconsolidate?: (entries: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>;\n\tconsolidateTrigger?: NodeInput<unknown>;\n\tcontext?: NodeInput<unknown>;\n\tmapOptions?: ReactiveMapOptions<string, TMem>;\n};\n\nexport type DistillBundle<TMem> = {\n\tstore: ReactiveMapBundle<string, TMem>;\n\tcompact: Node<Array<{ key: string; value: TMem; score: number }>>;\n\tsize: Node<number>;\n};\n\nfunction keepalive(node: Node): void {\n\tnode.subscribe(() => undefined);\n}\n\nfunction mapFromSnapshot<TMem>(snapshot: unknown): ReadonlyMap<string, TMem> {\n\tif (snapshot instanceof Map) return snapshot as ReadonlyMap<string, TMem>;\n\treturn new Map<string, TMem>();\n}\n\nfunction applyExtraction<TMem>(\n\tstore: ReactiveMapBundle<string, TMem>,\n\textraction: Extraction<TMem>,\n): void {\n\tif (!Array.isArray(extraction.upsert)) {\n\t\tthrow new TypeError(\"distill extraction requires upsert: Array<{ key, value }>\");\n\t}\n\tbatch(() => {\n\t\tfor (const { key, value } of extraction.upsert) {\n\t\t\tstore.set(key, value);\n\t\t}\n\t\tfor (const key of extraction.remove ?? []) {\n\t\t\tstore.delete(key);\n\t\t}\n\t});\n}\n\n/**\n * Budget-constrained reactive memory composition.\n */\nexport function distill<TRaw, TMem>(\n\tsource: NodeInput<TRaw>,\n\textractFn: (raw: TRaw, existing: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>,\n\topts: DistillOptions<TMem>,\n): DistillBundle<TMem> {\n\tconst sourceNode = fromAny(source);\n\tconst store = reactiveMap<string, TMem>(opts.mapOptions ?? {});\n\tconst budget = opts.budget ?? 2000;\n\tconst hasContext = opts.context !== undefined && opts.context !== null;\n\tconst contextNode = hasContext ? fromAny(opts.context) : state<unknown>(null);\n\n\t// Closes P3 audit #7. `latestStore` is seeded at wiring time (§3.6\n\t// boundary read) and kept current via a subscribe handler. `extractFn`\n\t// and `consolidate` read the closure, never `store.entries.cache` from\n\t// inside a reactive callback. `withLatestFrom` would swallow the initial\n\t// source emission because primary's push-on-subscribe fires before\n\t// secondary subscribes — same reason stratify/budgetGate use this pattern.\n\tlet latestStore: ReadonlyMap<string, TMem> = mapFromSnapshot<TMem>(store.entries.cache);\n\tstore.entries.subscribe((msgs) => {\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] === DATA) latestStore = mapFromSnapshot<TMem>(m[1]);\n\t\t}\n\t});\n\n\tconst extractionStream = switchMap(sourceNode, (raw) => extractFn(raw as TRaw, latestStore));\n\tforEach(extractionStream, (extraction) => {\n\t\tapplyExtraction(store, extraction);\n\t});\n\n\tif (opts.evict) {\n\t\t// Track active verdict-node subscriptions so we can react to Node<boolean> changes.\n\t\tconst verdictUnsubs = new Map<string, () => void>();\n\n\t\tconst evictionKeys = derived([store.entries], ([snapshot]) => {\n\t\t\tconst out: string[] = [];\n\t\t\tconst entries = mapFromSnapshot<TMem>(snapshot);\n\t\t\t// Clean up verdict subscriptions for removed keys.\n\t\t\tfor (const key of verdictUnsubs.keys()) {\n\t\t\t\tif (!entries.has(key)) {\n\t\t\t\t\tverdictUnsubs.get(key)!();\n\t\t\t\t\tverdictUnsubs.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const [key, mem] of entries) {\n\t\t\t\tconst verdict = opts.evict!(key, mem);\n\t\t\t\tif (isNodeLike<boolean>(verdict)) {\n\t\t\t\t\t// Subscribe if not already — push-on-subscribe fires with\n\t\t\t\t\t// the verdict's current value on first subscribe, so an\n\t\t\t\t\t// already-true verdict deletes via the callback without\n\t\t\t\t\t// needing a `verdict.cache` read (closes P3 audit #3).\n\t\t\t\t\t// Future transitions to `true` flow through the same path.\n\t\t\t\t\tif (!verdictUnsubs.has(key)) {\n\t\t\t\t\t\tconst unsub = forEach(verdict, (val) => {\n\t\t\t\t\t\t\tif (val === true && store.has(key)) {\n\t\t\t\t\t\t\t\tstore.delete(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\tverdictUnsubs.set(key, unsub);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (typeof verdict === \"boolean\") {\n\t\t\t\t\tif (verdict) out.push(key);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new TypeError(\"distill evict() must return boolean or Node<boolean>\");\n\t\t\t}\n\t\t\treturn out;\n\t\t});\n\t\tforEach(evictionKeys, (keys) => {\n\t\t\tfor (const key of keys) store.delete(key);\n\t\t});\n\t}\n\n\tconst hasConsolidateTrigger =\n\t\topts.consolidateTrigger !== undefined && opts.consolidateTrigger !== null;\n\tif (opts.consolidate && hasConsolidateTrigger) {\n\t\tconst consolidateTriggerNode = fromAny(opts.consolidateTrigger);\n\t\tconst consolidationStream = switchMap(consolidateTriggerNode, () =>\n\t\t\topts.consolidate!(latestStore),\n\t\t);\n\t\tforEach(consolidationStream, (extraction) => {\n\t\t\tapplyExtraction(store, extraction);\n\t\t});\n\t}\n\n\tconst compact = derived([store.entries, contextNode], ([snapshot, context]) => {\n\t\tconst entries = [...mapFromSnapshot<TMem>(snapshot).entries()].map(([key, value]) => ({\n\t\t\tkey,\n\t\t\tvalue,\n\t\t\tscore: opts.score(value, context),\n\t\t\tcost: opts.cost(value),\n\t\t}));\n\t\tentries.sort((a, b) => b.score - a.score);\n\n\t\tconst packed: Array<{ key: string; value: TMem; score: number }> = [];\n\t\tlet remaining = budget;\n\t\tfor (const item of entries) {\n\t\t\tif (item.cost <= remaining) {\n\t\t\t\tpacked.push({ key: item.key, value: item.value, score: item.score });\n\t\t\t\tremaining -= item.cost;\n\t\t\t}\n\t\t}\n\t\treturn packed;\n\t});\n\n\tconst size = derived([store.entries], ([snapshot]) => mapFromSnapshot<TMem>(snapshot).size);\n\tkeepalive(compact);\n\tkeepalive(size);\n\n\treturn { store, compact, size };\n}\n","/**\n * Reactive append-only log (roadmap §3.2) — emits `readonly T[]` snapshots directly.\n *\n * Internal version counter drives efficient equality without leaking `Versioned`\n * into the public API (spec §5.12).\n *\n * **Wave 4 refactor (2026-04-15):** Introduces the `LogBackend<T>` pluggable-backend\n * interface. The default `NativeLogBackend` uses a ring buffer when `maxSize` is set\n * (O(1) append + trim) and a flat array otherwise. `tail(n)` and `slice(start, stop)`\n * are memoized — repeat calls with identical arguments return the same derived node,\n * bounding the keepalive-subscription footprint. The standalone `logSlice` factory\n * has been removed; use `log.slice(start, stop)` instead.\n */\nimport { batch } from \"../core/batch.js\";\nimport { DATA, DIRTY } from \"../core/messages.js\";\nimport type { Node } from \"../core/node.js\";\nimport { derived, state } from \"../core/sugar.js\";\nimport type { VersioningLevel } from \"../core/versioning.js\";\n\nexport type ReactiveLogOptions<T> = {\n\tname?: string;\n\tmaxSize?: number;\n\t/**\n\t * Optional versioning level for the underlying `entries` state node. Set\n\t * at construction time; cannot be changed later. Pass `0` for V0 identity\n\t * + monotonic version counter, or `1` for V1 + content-addressed cid.\n\t */\n\tversioning?: VersioningLevel;\n\t/**\n\t * Storage backend. Defaults to `NativeLogBackend` (ring buffer if `maxSize` is set,\n\t * flat array otherwise). Users can plug in persistent / RRB-tree backends via\n\t * the {@link LogBackend} interface.\n\t */\n\tbackend?: LogBackend<T>;\n};\n\nexport type ReactiveLogBundle<T> = {\n\t/** Emits `readonly T[]` on each append/clear/trim (two-phase). */\n\treadonly entries: Node<readonly T[]>;\n\t/** Current entry count (O(1)). */\n\treadonly size: number;\n\t/** Positional access (O(1)); returns `undefined` on out-of-range. Supports negative indices (Python-style). */\n\tat: (index: number) => T | undefined;\n\tappend: (value: T) => void;\n\t/**\n\t * Push all values, emit one snapshot. No-op if `values` is empty.\n\t * **Iterable consumption:** `values` is a `readonly T[]` — safe to pass arrays.\n\t */\n\tappendMany: (values: readonly T[]) => void;\n\tclear: () => void;\n\t/** Remove the first `n` entries (clamped to `size`). Throws on non-integer or negative `n`. */\n\ttrimHead: (n: number) => void;\n\t/**\n\t * Last `n` entries (or fewer) as a derived reactive view. Memoized with\n\t * an LRU cache (default cap 64) — repeat calls with the same `n` return\n\t * the same node. Throws on non-integer or negative `n`.\n\t *\n\t * **LRU eviction contract (D3(b)):** when a 65th distinct `n` is passed,\n\t * the least-recently-used cached view is evicted and its keepalive is\n\t * disposed. External holders of the evicted node will NOT receive further\n\t * updates — re-call `tail(n)` for a fresh node, or dispose proactively\n\t * via {@link disposeTail} / {@link disposeAllViews}. To avoid surprise:\n\t * resolve `tail(n)` at the point of use rather than caching the returned\n\t * node across many distinct `n`s.\n\t */\n\ttail: (n: number) => Node<readonly T[]>;\n\t/**\n\t * Reactive view of `entries.slice(start, stop)` — non-negative integer\n\t * `start`, non-negative integer `stop` (exclusive) or `undefined` (to end).\n\t * Memoized with an LRU cache (default cap 64) — repeat calls with the\n\t * same `(start, stop)` return the same node.\n\t *\n\t * Throws on non-integer `start`, negative `start`, non-integer `stop`, or\n\t * negative `stop` (P4 — the backend cannot cheaply honor JS-style\n\t * negative `stop` without scanning length; disallowed for a consistent\n\t * contract between backend, derived recomputation, and cached initial).\n\t *\n\t * **LRU eviction contract (D3(b)):** same as {@link tail} — past 64\n\t * distinct `(start, stop)` pairs, the oldest cached view is evicted and\n\t * its keepalive disposed. External holders stop receiving updates.\n\t */\n\tslice: (start: number, stop?: number) => Node<readonly T[]>;\n\t/**\n\t * Releases the cached `tail(n)` view if present (disposes its keepalive\n\t * subscription). Subsequent `tail(n)` calls create a fresh node. No-op if\n\t * `n` was not cached. Returns `true` if a view was disposed.\n\t */\n\tdisposeTail: (n: number) => boolean;\n\t/**\n\t * Releases the cached `slice(start, stop?)` view if present. No-op if not cached.\n\t */\n\tdisposeSlice: (start: number, stop?: number) => boolean;\n\t/** Releases all cached tail/slice views and their keepalive subscriptions. */\n\tdisposeAllViews: () => void;\n\t/**\n\t * Releases all internal keepalive subscriptions so the bundle can be\n\t * GC'd — currently equivalent to {@link disposeAllViews}, but exposed as\n\t * a uniform API across all reactive data structures for lifecycle\n\t * symmetry (mirrors `reactiveMap.dispose` / `reactiveList.dispose` /\n\t * `reactiveIndex.dispose`). Idempotent. D6(a).\n\t */\n\tdispose: () => void;\n};\n\n// ── Backend interface ─────────────────────────────────────────────────────\n\n/**\n * Storage contract for {@link reactiveLog}. Implementations own the mutable state and\n * expose a monotonic `version` counter that increments on every structural change.\n *\n * The reactive layer reads `version` to decide when to emit; it does not inspect\n * internal representation. Users can plug in persistent / ring-buffer / skip-list\n * backends without touching the reactive emission logic.\n *\n * @remarks Post-1.0 op-log changesets will extend this interface with a\n * `changesSince(version: number): Iterable<Change>` method. Current consumers\n * should treat all methods here as stable.\n *\n * @category extra\n */\nexport interface LogBackend<T> {\n\t/** Monotonic mutation counter; increments on every append/trim/clear that changes state. */\n\treadonly version: number;\n\t/** Number of entries currently stored. */\n\treadonly size: number;\n\t/** O(1) positional access; returns `undefined` on out-of-range. */\n\tat(index: number): T | undefined;\n\t/** Append a value. Applies `maxSize` head-drop if configured. Advances `version`. */\n\tappend(value: T): void;\n\t/** Append a batch; advances `version` once. No-op if `values.length === 0`. */\n\tappendMany(values: readonly T[]): void;\n\t/** Remove all entries. Returns count removed. Advances `version` only if non-zero. */\n\tclear(): number;\n\t/** Remove the first `n` entries (clamped). Returns count removed. Throws on negative `n`. */\n\ttrimHead(n: number): number;\n\t/** Fresh snapshot array for `[start, stop)`. Throws on negative `start`. */\n\tslice(start: number, stop?: number): readonly T[];\n\t/** Last `n` entries as a fresh array. Throws on negative `n`. */\n\ttail(n: number): readonly T[];\n\t/** Full snapshot as a fresh array. */\n\ttoArray(): readonly T[];\n}\n\n/**\n * Default append-only log backend.\n *\n * - When `maxSize` is set: uses a **ring buffer** with `_head` index and circular\n * modular arithmetic. Append and trim become O(1); snapshot is O(size) unrolling.\n * - When `maxSize` is unset: uses a flat array with standard push/splice.\n *\n * `appendMany` pre-trims oversize input: if `values.length > maxSize`, only the\n * tail of `values` is pushed (the rest would be immediately evicted).\n *\n * @category extra\n */\nexport class NativeLogBackend<T> implements LogBackend<T> {\n\tprivate _version = 0;\n\tprivate readonly _maxSize?: number;\n\tprivate readonly _buf: T[];\n\tprivate _head = 0;\n\tprivate _size = 0;\n\n\tconstructor(initial?: readonly T[], maxSize?: number) {\n\t\tif (maxSize !== undefined && maxSize < 1) {\n\t\t\tthrow new RangeError(\"maxSize must be >= 1\");\n\t\t}\n\t\tthis._maxSize = maxSize;\n\t\tif (maxSize !== undefined) {\n\t\t\t// Ring buffer mode — pre-allocate fixed size\n\t\t\tthis._buf = new Array(maxSize);\n\t\t\tif (initial && initial.length > 0) {\n\t\t\t\tconst take = Math.min(initial.length, maxSize);\n\t\t\t\tconst start = initial.length - take;\n\t\t\t\tfor (let i = 0; i < take; i++) {\n\t\t\t\t\tthis._buf[i] = initial[start + i]!;\n\t\t\t\t}\n\t\t\t\tthis._size = take;\n\t\t\t}\n\t\t} else {\n\t\t\t// Unbounded mode — dynamic array\n\t\t\tthis._buf = initial ? [...initial] : [];\n\t\t\tthis._size = this._buf.length;\n\t\t}\n\t}\n\n\tget version(): number {\n\t\treturn this._version;\n\t}\n\n\tget size(): number {\n\t\treturn this._size;\n\t}\n\n\tat(index: number): T | undefined {\n\t\tif (!Number.isInteger(index)) return undefined;\n\t\t// P5: Python-style negative index — `-1` returns the last entry.\n\t\tconst i = index >= 0 ? index : this._size + index;\n\t\tif (i < 0 || i >= this._size) return undefined;\n\t\tif (this._maxSize !== undefined) {\n\t\t\treturn this._buf[(this._head + i) % this._maxSize];\n\t\t}\n\t\treturn this._buf[i];\n\t}\n\n\tappend(value: T): void {\n\t\tthis._rawAppend(value);\n\t\tthis._version += 1;\n\t}\n\n\tappendMany(values: readonly T[]): void {\n\t\tif (values.length === 0) return;\n\t\t// Pre-trim oversize input in ring mode — skip values that would be\n\t\t// immediately evicted. Iterate with a start index instead of\n\t\t// allocating an intermediate slice. F2.\n\t\tconst start =\n\t\t\tthis._maxSize !== undefined && values.length > this._maxSize\n\t\t\t\t? values.length - this._maxSize\n\t\t\t\t: 0;\n\t\tfor (let i = start; i < values.length; i++) {\n\t\t\tthis._rawAppend(values[i] as T);\n\t\t}\n\t\tthis._version += 1;\n\t}\n\n\tclear(): number {\n\t\tif (this._size === 0) return 0;\n\t\tconst n = this._size;\n\t\tif (this._maxSize === undefined) {\n\t\t\tthis._buf.length = 0;\n\t\t} else {\n\t\t\t// Ring buffer: only null the currently-live window so the GC can\n\t\t\t// reclaim ref-typed `T`. Iterating the full capacity would be O(cap)\n\t\t\t// even when only a few slots are in use (P6). Non-live slots are\n\t\t\t// already `undefined` (pre-allocation state) or whatever a prior\n\t\t\t// trim/clear left — they hold no live refs.\n\t\t\tfor (let i = 0; i < n; i++) {\n\t\t\t\tthis._buf[(this._head + i) % this._maxSize] = undefined as unknown as T;\n\t\t\t}\n\t\t}\n\t\tthis._head = 0;\n\t\tthis._size = 0;\n\t\tthis._version += 1;\n\t\treturn n;\n\t}\n\n\ttrimHead(n: number): number {\n\t\tif (!Number.isInteger(n) || n < 0) {\n\t\t\tthrow new RangeError(`trimHead: n must be a non-negative integer (got ${n})`);\n\t\t}\n\t\tif (n === 0 || this._size === 0) return 0;\n\t\tconst removed = Math.min(n, this._size);\n\t\tif (this._maxSize === undefined) {\n\t\t\tthis._buf.splice(0, removed);\n\t\t} else {\n\t\t\t// Null trimmed slots so the GC can reclaim ref-typed T (P4 extension).\n\t\t\tfor (let i = 0; i < removed; i++) {\n\t\t\t\tthis._buf[(this._head + i) % this._maxSize] = undefined as unknown as T;\n\t\t\t}\n\t\t\tthis._head = (this._head + removed) % this._maxSize;\n\t\t}\n\t\tthis._size -= removed;\n\t\tthis._version += 1;\n\t\treturn removed;\n\t}\n\n\tslice(start: number, stop?: number): readonly T[] {\n\t\tif (!Number.isInteger(start) || start < 0) {\n\t\t\tthrow new RangeError(`slice: start must be a non-negative integer (got ${start})`);\n\t\t}\n\t\t// P4: reject negative `stop` explicitly so the bundle / backend / derived\n\t\t// contract stays consistent. Previously stop was silently clamped to 0,\n\t\t// producing `[]` in the backend but a different value under JS semantics\n\t\t// in the derived recomputation — a latent bug for negative inputs.\n\t\tif (stop !== undefined && (!Number.isInteger(stop) || stop < 0)) {\n\t\t\tthrow new RangeError(`slice: stop must be a non-negative integer or undefined (got ${stop})`);\n\t\t}\n\t\tconst end = stop === undefined ? this._size : Math.min(Math.max(stop, 0), this._size);\n\t\tconst s = Math.min(start, this._size);\n\t\tif (s >= end) return [];\n\t\tconst len = end - s;\n\t\tif (this._maxSize === undefined) {\n\t\t\treturn this._buf.slice(s, end);\n\t\t}\n\t\tconst out: T[] = new Array(len);\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tout[i] = this._buf[(this._head + s + i) % this._maxSize]!;\n\t\t}\n\t\treturn out;\n\t}\n\n\ttail(n: number): readonly T[] {\n\t\tif (!Number.isInteger(n) || n < 0) {\n\t\t\tthrow new RangeError(`tail: n must be a non-negative integer (got ${n})`);\n\t\t}\n\t\tif (n === 0 || this._size === 0) return [];\n\t\tconst take = Math.min(n, this._size);\n\t\treturn this.slice(this._size - take, this._size);\n\t}\n\n\ttoArray(): readonly T[] {\n\t\tif (this._maxSize === undefined) {\n\t\t\treturn [...this._buf];\n\t\t}\n\t\tconst out: T[] = new Array(this._size);\n\t\tfor (let i = 0; i < this._size; i++) {\n\t\t\tout[i] = this._buf[(this._head + i) % this._maxSize]!;\n\t\t}\n\t\treturn out;\n\t}\n\n\t/** Internal append without version bump — used by `appendMany`. */\n\tprivate _rawAppend(value: T): void {\n\t\tif (this._maxSize === undefined) {\n\t\t\tthis._buf.push(value);\n\t\t\tthis._size = this._buf.length;\n\t\t\treturn;\n\t\t}\n\t\tif (this._size < this._maxSize) {\n\t\t\tthis._buf[(this._head + this._size) % this._maxSize] = value;\n\t\t\tthis._size += 1;\n\t\t} else {\n\t\t\t// Overwrite slot at head, advance head.\n\t\t\tthis._buf[this._head] = value;\n\t\t\tthis._head = (this._head + 1) % this._maxSize;\n\t\t}\n\t}\n}\n\n// ── Reactive wrapper ──────────────────────────────────────────────────────\n\n/** Installs a keepalive subscription; returns the disposer so callers can release it. */\nfunction keepaliveDerived(n: Node<unknown>): () => void {\n\treturn n.subscribe(() => {});\n}\n\n/** Default cap on the LRU view cache for `tail(n)` / `slice(start, stop?)`. D2(c). */\nconst DEFAULT_VIEW_CACHE_MAX = 64;\n\n/**\n * Creates an append-only reactive log with immutable array snapshots.\n *\n * @param initial - Optional seed entries (copied; pre-trimmed to `maxSize` if set).\n * @param options - `name`, `maxSize`, and optional pluggable `backend`.\n * @returns Bundle with `entries` (state node), `append`/`appendMany`/`clear`/`trimHead`,\n * `size` / `at`, and memoized derived views `tail(n)` / `slice(start, stop?)`.\n *\n * @remarks\n * **Backend:** The default {@link NativeLogBackend} uses a ring buffer when `maxSize`\n * is set (O(1) append + trim) and a flat array otherwise. For persistent/structural-\n * sharing semantics plug in a custom {@link LogBackend}.\n *\n * **`initial` + custom `backend` (F5):** When you supply `options.backend`, the\n * `initial` argument is IGNORED — seed the backend yourself before passing it in.\n * The `initial` seed only applies to the default `NativeLogBackend`.\n *\n * **Memoized views:** {@link ReactiveLogBundle.tail} and {@link ReactiveLogBundle.slice}\n * cache derived nodes per-argument. Repeat calls with the same `n` / `(start, stop)`\n * return the same node, bounding keepalive-subscription count to one per unique argument.\n *\n * @example\n * ```ts\n * import { reactiveLog } from \"@graphrefly/graphrefly-ts\";\n *\n * const lg = reactiveLog<number>([1, 2], { name: \"audit\", maxSize: 100 });\n * lg.append(3);\n * lg.entries.subscribe((msgs) => console.log(msgs));\n * const last5 = lg.tail(5); // derived node\n * const window = lg.slice(10, 20); // derived node\n * ```\n *\n * @category extra\n */\nexport function reactiveLog<T>(\n\tinitial?: readonly T[],\n\toptions: ReactiveLogOptions<T> = {},\n): ReactiveLogBundle<T> {\n\tconst { name, maxSize, versioning, backend: userBackend } = options;\n\tconst backend: LogBackend<T> = userBackend ?? new NativeLogBackend<T>(initial, maxSize);\n\n\tconst entries = state<readonly T[]>(backend.toArray(), {\n\t\tname,\n\t\tdescribeKind: \"state\",\n\t\tequals: (a, b) => a === b,\n\t\t...(versioning != null ? { versioning } : {}),\n\t});\n\n\tfunction pushSnapshot(): void {\n\t\tconst snapshot = backend.toArray();\n\t\tbatch(() => {\n\t\t\tentries.down([[DIRTY]]);\n\t\t\tentries.down([[DATA, snapshot]]);\n\t\t});\n\t}\n\n\t// Memoization caches for derived views (D2(c)). Each cache is an LRU keyed by\n\t// the unique view argument, bounded by `DEFAULT_VIEW_CACHE_MAX`. On cache miss\n\t// past the cap, the least-recently-used entry is evicted and its keepalive\n\t// disposer is called so the underlying derived node can be GC'd. Callers can\n\t// also release views proactively via `disposeTail` / `disposeSlice` /\n\t// `disposeAllViews`. Iteration order of `Map` is insertion order, so moving\n\t// an entry to the end on hit is the LRU \"touch\".\n\ttype ViewEntry = { node: Node<readonly T[]>; dispose: () => void };\n\tconst tailCache = new Map<number, ViewEntry>();\n\tconst sliceCache = new Map<string, ViewEntry>();\n\n\tfunction sliceKey(start: number, stop?: number): string {\n\t\treturn `${start}:${stop === undefined ? \"END\" : stop}`;\n\t}\n\n\tfunction evictOldestIfFull<K>(cache: Map<K, ViewEntry>): void {\n\t\tif (cache.size < DEFAULT_VIEW_CACHE_MAX) return;\n\t\tconst first = cache.keys().next();\n\t\tif (first.done) return;\n\t\tconst oldest = cache.get(first.value);\n\t\tif (oldest !== undefined) oldest.dispose();\n\t\tcache.delete(first.value);\n\t}\n\n\t/**\n\t * D4(a): try/finally defense-in-depth — if a custom backend op throws\n\t * mid-mutation, surface the partial state via pushSnapshot so subscribers\n\t * don't see a stale cache. Matches the pattern in reactive-map and\n\t * reactive-index. Native ops are atomic by contract; this only matters\n\t * for user-supplied backends.\n\t */\n\tfunction wrapMutation<R>(op: () => R): R {\n\t\tconst prev = backend.version;\n\t\ttry {\n\t\t\treturn op();\n\t\t} finally {\n\t\t\tif (backend.version !== prev) pushSnapshot();\n\t\t}\n\t}\n\n\treturn {\n\t\tentries,\n\n\t\tget size(): number {\n\t\t\treturn backend.size;\n\t\t},\n\n\t\tat(index: number): T | undefined {\n\t\t\treturn backend.at(index);\n\t\t},\n\n\t\tappend(value: T): void {\n\t\t\twrapMutation(() => backend.append(value));\n\t\t},\n\n\t\tappendMany(values: readonly T[]): void {\n\t\t\tif (values.length === 0) return;\n\t\t\twrapMutation(() => backend.appendMany(values));\n\t\t},\n\n\t\tclear(): void {\n\t\t\twrapMutation(() => backend.clear());\n\t\t\t// NOTE: cached tail/slice derived views are intentionally NOT\n\t\t\t// disposed here. Disposing would kill the keepalive on any node\n\t\t\t// a caller already holds externally, silently stopping their\n\t\t\t// updates. The derived nodes recompute from the new empty\n\t\t\t// snapshot when `entries` emits post-clear, so `.cache` on an\n\t\t\t// outstanding view settles to `[]` without any manual\n\t\t\t// reset. (Initial snapshots, if inspected before the next wave,\n\t\t\t// may be stale — callers who care can `disposeTail` / `slice`\n\t\t\t// explicitly.)\n\t\t},\n\n\t\ttrimHead(n: number): void {\n\t\t\twrapMutation(() => backend.trimHead(n));\n\t\t},\n\n\t\ttail(n: number): Node<readonly T[]> {\n\t\t\tif (!Number.isInteger(n) || n < 0) {\n\t\t\t\tthrow new RangeError(`tail: n must be a non-negative integer (got ${n})`);\n\t\t\t}\n\t\t\tconst hit = tailCache.get(n);\n\t\t\tif (hit !== undefined) {\n\t\t\t\t// LRU touch: move to end of insertion order.\n\t\t\t\ttailCache.delete(n);\n\t\t\t\ttailCache.set(n, hit);\n\t\t\t\treturn hit.node;\n\t\t\t}\n\t\t\tevictOldestIfFull(tailCache);\n\t\t\tconst node_ = derived(\n\t\t\t\t[entries],\n\t\t\t\t([s]) => {\n\t\t\t\t\tconst list = s as readonly T[];\n\t\t\t\t\tif (n === 0 || list.length === 0) return [];\n\t\t\t\t\treturn list.slice(Math.max(0, list.length - n));\n\t\t\t\t},\n\t\t\t\t{ initial: backend.tail(n), describeKind: \"derived\" },\n\t\t\t);\n\t\t\tconst dispose = keepaliveDerived(node_);\n\t\t\ttailCache.set(n, { node: node_, dispose });\n\t\t\treturn node_;\n\t\t},\n\n\t\tslice(start: number, stop?: number): Node<readonly T[]> {\n\t\t\tif (!Number.isInteger(start) || start < 0) {\n\t\t\t\tthrow new RangeError(`slice: start must be a non-negative integer (got ${start})`);\n\t\t\t}\n\t\t\t// P4: reject negative stop explicitly to keep bundle / backend / derived\n\t\t\t// consistent (JS `Array.prototype.slice` supports negative stop, but the\n\t\t\t// backend can't cheaply honor it without scanning length, so we disallow).\n\t\t\tif (stop !== undefined && (!Number.isInteger(stop) || stop < 0)) {\n\t\t\t\tthrow new RangeError(\n\t\t\t\t\t`slice: stop must be a non-negative integer or undefined (got ${stop})`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst key = sliceKey(start, stop);\n\t\t\tconst hit = sliceCache.get(key);\n\t\t\tif (hit !== undefined) {\n\t\t\t\tsliceCache.delete(key);\n\t\t\t\tsliceCache.set(key, hit);\n\t\t\t\treturn hit.node;\n\t\t\t}\n\t\t\tevictOldestIfFull(sliceCache);\n\t\t\tconst node_ = derived(\n\t\t\t\t[entries],\n\t\t\t\t([s]) => {\n\t\t\t\t\tconst list = s as readonly T[];\n\t\t\t\t\treturn stop === undefined ? list.slice(start) : list.slice(start, stop);\n\t\t\t\t},\n\t\t\t\t{ initial: backend.slice(start, stop), describeKind: \"derived\" },\n\t\t\t);\n\t\t\tconst dispose = keepaliveDerived(node_);\n\t\t\tsliceCache.set(key, { node: node_, dispose });\n\t\t\treturn node_;\n\t\t},\n\n\t\tdisposeTail(n: number): boolean {\n\t\t\tconst hit = tailCache.get(n);\n\t\t\tif (hit === undefined) return false;\n\t\t\thit.dispose();\n\t\t\ttailCache.delete(n);\n\t\t\treturn true;\n\t\t},\n\n\t\tdisposeSlice(start: number, stop?: number): boolean {\n\t\t\tconst key = sliceKey(start, stop);\n\t\t\tconst hit = sliceCache.get(key);\n\t\t\tif (hit === undefined) return false;\n\t\t\thit.dispose();\n\t\t\tsliceCache.delete(key);\n\t\t\treturn true;\n\t\t},\n\n\t\tdisposeAllViews(): void {\n\t\t\tfor (const entry of tailCache.values()) entry.dispose();\n\t\t\ttailCache.clear();\n\t\t\tfor (const entry of sliceCache.values()) entry.dispose();\n\t\t\tsliceCache.clear();\n\t\t},\n\n\t\tdispose(): void {\n\t\t\t// D6(a): currently identical to disposeAllViews. Exposed as a\n\t\t\t// uniform lifecycle API across all 4 reactive data structures.\n\t\t\tfor (const entry of tailCache.values()) entry.dispose();\n\t\t\ttailCache.clear();\n\t\t\tfor (const entry of sliceCache.values()) entry.dispose();\n\t\t\tsliceCache.clear();\n\t\t},\n\t};\n}\n","/**\n * Creates a resettable deadline timer for internal timeout, retry, and rate-limiting use.\n *\n * @remarks **Centralised primitive:** wraps `setTimeout`/`clearTimeout` with a generation guard\n * so that stale callbacks never fire after `cancel()` or a new `start()`.\n *\n * @remarks **Spec §5.10 exception:** resilience operators (`timeout`, `retry`, `rateLimiter`)\n * need raw timers — `fromTimer` creates a new Node per reset, which is too heavy here.\n * Lives in `src/extra/` (not `src/core/`) because it is a documented escape hatch from\n * the protocol-pure core layer.\n *\n * @example\n * ```ts\n * import { ResettableTimer } from \"@graphrefly/graphrefly-ts\";\n *\n * const timer = new ResettableTimer();\n * timer.start(1000, () => console.log(\"fired\"));\n * timer.cancel(); // cancels before firing\n * timer.start(500, () => console.log(\"new deadline\"));\n * console.log(timer.pending); // true\n * ```\n *\n * @category extra\n */\nexport class ResettableTimer {\n\tprivate _timer: ReturnType<typeof setTimeout> | undefined;\n\tprivate _gen = 0;\n\n\t/** Schedule callback after delayMs. Cancels any pending timer. */\n\tstart(delayMs: number, callback: () => void): void {\n\t\tthis.cancel();\n\t\tthis._gen += 1;\n\t\tconst gen = this._gen;\n\t\tthis._timer = setTimeout(() => {\n\t\t\tthis._timer = undefined;\n\t\t\tif (gen !== this._gen) return;\n\t\t\tcallback();\n\t\t}, delayMs);\n\t}\n\n\t/** Cancel the pending timer (if any). */\n\tcancel(): void {\n\t\tif (this._timer !== undefined) {\n\t\t\tclearTimeout(this._timer);\n\t\t\tthis._timer = undefined;\n\t\t}\n\t}\n\n\t/** Whether a timer is currently pending. */\n\tget pending(): boolean {\n\t\treturn this._timer !== undefined;\n\t}\n}\n","import type { Actor } from \"./actor.js\";\nimport { accessHintForGuard } from \"./guard.js\";\nimport { type Node, type NodeDescribeKind, NodeImpl } from \"./node.js\";\n\n/**\n * JSON-shaped slice of a node for `Graph.describe()`\n * (GRAPHREFLY-SPEC §3.6, Appendix B).\n */\nexport type DescribeNodeOutput = {\n\ttype: NodeDescribeKind;\n\tstatus?: Node[\"status\"];\n\tdeps: string[];\n\tmeta?: Record<string, unknown>;\n\tname?: string;\n\tvalue?: unknown;\n\t/** True when the node is in `\"sentinel\"` state (no value ever). */\n\tsentinel?: boolean;\n\tv?: { id: string; version: number; cid?: string; prev?: string | null };\n\tguard?: string;\n\tlastMutation?: Readonly<{ actor: Actor; timestamp_ns: number }>;\n\t/**\n\t * Latest reason annotation attached via `graph.trace(path, reason)`,\n\t * when present. Populated by `Graph.describe` only — `describeNode`\n\t * has no graph context.\n\t */\n\treason?: string;\n};\n\n/** Detail level for progressive disclosure (Phase 3.3b). */\nexport type DescribeDetail = \"minimal\" | \"standard\" | \"full\";\n\n/** Valid field names for `describe({ fields: [...] })`. */\nexport type DescribeField =\n\t| \"type\"\n\t| \"status\"\n\t| \"value\"\n\t| \"deps\"\n\t| \"meta\"\n\t| \"v\"\n\t| \"guard\"\n\t| \"lastMutation\"\n\t| `meta.${string}`;\n\n/** Resolve which fields to include based on detail level or explicit field list. */\nexport function resolveDescribeFields(\n\tdetail?: DescribeDetail,\n\tfields?: readonly DescribeField[],\n): Set<string> | null {\n\tif (fields != null && fields.length > 0) return new Set(fields);\n\tswitch (detail) {\n\t\tcase \"standard\":\n\t\t\treturn new Set([\"type\", \"status\", \"value\", \"deps\", \"meta\", \"v\"]);\n\t\tcase \"full\":\n\t\t\treturn null;\n\t\tdefault:\n\t\t\treturn new Set([\"type\", \"deps\"]);\n\t}\n}\n\nfunction inferDescribeType(n: NodeImpl): NodeDescribeKind {\n\tif (n._describeKind != null) return n._describeKind;\n\tconst hasDeps = n._deps.length > 0;\n\tif (!hasDeps) return n._fn != null ? \"producer\" : \"state\";\n\t// With deps: derived (passthrough falls under derived, no fn → derived shape).\n\treturn \"derived\";\n}\n\n/**\n * Reads the current cached value of every companion meta field on a node,\n * suitable for merging into `describe()`-style JSON.\n *\n * Values come from {@link Node.cache}, which returns the last settled cache.\n * If a meta field is in `\"dirty\"` status (DIRTY received, DATA pending), the\n * snapshot contains the *previous* value — check `node.meta[key].status`\n * when freshness matters.\n */\nexport function metaSnapshot(node: Node): Record<string, unknown> {\n\tconst out: Record<string, unknown> = {};\n\tfor (const [key, child] of Object.entries(node.meta)) {\n\t\ttry {\n\t\t\tout[key] = child.cache;\n\t\t} catch {\n\t\t\t/* omit key — describe tooling still gets other fields */\n\t\t}\n\t}\n\treturn out;\n}\n\n/**\n * Builds a single-node slice of `Graph.describe()` JSON (structure + `meta`\n * snapshot). Parity with `graphrefly-py` `describe_node`.\n */\nexport function describeNode(node: Node, includeFields?: Set<string> | null): DescribeNodeOutput {\n\tconst all = includeFields == null;\n\tconst metaKeys: string[] | null =\n\t\t!all && includeFields != null\n\t\t\t? [...includeFields].filter((f) => f.startsWith(\"meta.\")).map((f) => f.slice(5))\n\t\t\t: null;\n\tconst wantsMeta = all || includeFields!.has(\"meta\") || (metaKeys != null && metaKeys.length > 0);\n\n\tlet type: NodeDescribeKind = \"state\";\n\tlet deps: string[] = [];\n\n\tif (node instanceof NodeImpl) {\n\t\ttype = inferDescribeType(node);\n\t\tdeps = node._deps.map((d) => d.node.name ?? \"\");\n\t}\n\n\tconst out: DescribeNodeOutput = { type, deps };\n\n\tif (all || includeFields!.has(\"status\")) {\n\t\tout.status = node.status;\n\t}\n\n\tconst guard = node instanceof NodeImpl ? node._guard : undefined;\n\n\tif (wantsMeta) {\n\t\tconst rawMeta: Record<string, unknown> = { ...metaSnapshot(node) };\n\t\tif (guard != null && rawMeta.access === undefined) {\n\t\t\trawMeta.access = accessHintForGuard(guard);\n\t\t}\n\t\tif (metaKeys != null && metaKeys.length > 0 && !includeFields!.has(\"meta\")) {\n\t\t\tconst filtered: Record<string, unknown> = {};\n\t\t\tfor (const k of metaKeys) {\n\t\t\t\tif (k in rawMeta) filtered[k] = rawMeta[k];\n\t\t\t}\n\t\t\tout.meta = filtered;\n\t\t} else {\n\t\t\tout.meta = rawMeta;\n\t\t}\n\t}\n\n\tif (node.name != null) {\n\t\tout.name = node.name;\n\t}\n\n\tif (all || includeFields!.has(\"value\")) {\n\t\tif (node.status === \"sentinel\") out.sentinel = true;\n\t\ttry {\n\t\t\tout.value = node.cache;\n\t\t} catch {\n\t\t\t/* omit value */\n\t\t}\n\t}\n\n\tif ((all || includeFields!.has(\"v\")) && node.v != null) {\n\t\tconst vInfo: NonNullable<DescribeNodeOutput[\"v\"]> = {\n\t\t\tid: node.v.id,\n\t\t\tversion: node.v.version,\n\t\t};\n\t\tif (\"cid\" in node.v) {\n\t\t\tvInfo.cid = (node.v as { cid: string }).cid;\n\t\t\tvInfo.prev = (node.v as { prev: string | null }).prev;\n\t\t}\n\t\tout.v = vInfo;\n\t}\n\n\tif (all || includeFields!.has(\"guard\")) {\n\t\tif (guard != null) out.guard = accessHintForGuard(guard);\n\t}\n\n\tif (all || includeFields!.has(\"lastMutation\")) {\n\t\tif (node.lastMutation != null) out.lastMutation = node.lastMutation;\n\t}\n\n\treturn out;\n}\n","/**\n * Fixed-capacity ring buffer — O(1) push and drop-oldest eviction.\n *\n * Used by `Graph._traceRing` (reasoning trace), `reactiveLog` (append-only\n * log backend), and `reactiveSink` (drop-oldest backpressure buffer). One\n * implementation, three use sites.\n *\n * @module\n * @internal\n */\n\n/**\n * Fixed-capacity ring buffer. Once `capacity` entries are stored, subsequent\n * `push` calls evict the oldest entry (drop-oldest / FIFO eviction).\n *\n * Operations:\n * - `push(item)` — O(1).\n * - `shift()` — O(1) remove oldest (returns `undefined` when empty).\n * - `at(i)` — O(1) index lookup, with Python-style negative indexing.\n * - `toArray()` — O(n) materialize in insertion order.\n * - `clear()` — O(1) reset to empty.\n *\n * Not thread-safe; JS semantics assumed (single-threaded within a sync call).\n */\nexport class RingBuffer<T> {\n\tprivate buf: (T | undefined)[];\n\tprivate head = 0;\n\tprivate _size = 0;\n\n\tconstructor(private capacity: number) {\n\t\tif (!Number.isInteger(capacity) || capacity <= 0) {\n\t\t\tthrow new Error(`RingBuffer capacity must be a positive integer (got ${capacity})`);\n\t\t}\n\t\tthis.buf = new Array(capacity);\n\t}\n\n\t/** Current number of stored entries. */\n\tget size(): number {\n\t\treturn this._size;\n\t}\n\n\t/** Configured maximum before drop-oldest eviction fires. */\n\tget maxSize(): number {\n\t\treturn this.capacity;\n\t}\n\n\t/**\n\t * Append an item. If size equals capacity, drops the oldest entry and\n\t * advances the head pointer.\n\t */\n\tpush(item: T): void {\n\t\tconst idx = (this.head + this._size) % this.capacity;\n\t\tthis.buf[idx] = item;\n\t\tif (this._size < this.capacity) this._size++;\n\t\telse this.head = (this.head + 1) % this.capacity;\n\t}\n\n\t/** Remove and return the oldest entry; `undefined` when empty. */\n\tshift(): T | undefined {\n\t\tif (this._size === 0) return undefined;\n\t\tconst item = this.buf[this.head];\n\t\tthis.buf[this.head] = undefined;\n\t\tthis.head = (this.head + 1) % this.capacity;\n\t\tthis._size--;\n\t\treturn item;\n\t}\n\n\t/**\n\t * O(1) index lookup. Negative indices count from the tail (Python-style).\n\t * Returns `undefined` for out-of-range.\n\t */\n\tat(i: number): T | undefined {\n\t\tif (this._size === 0) return undefined;\n\t\tconst n = i < 0 ? this._size + i : i;\n\t\tif (n < 0 || n >= this._size) return undefined;\n\t\treturn this.buf[(this.head + n) % this.capacity];\n\t}\n\n\t/**\n\t * Materialize the contents in insertion order (oldest → newest).\n\t * Returns a new array each call.\n\t */\n\ttoArray(): T[] {\n\t\tconst result: T[] = new Array(this._size);\n\t\tfor (let i = 0; i < this._size; i++) {\n\t\t\tresult[i] = this.buf[(this.head + i) % this.capacity]!;\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Reset to empty. Storage slots are released so held refs can GC. */\n\tclear(): void {\n\t\tfor (let i = 0; i < this._size; i++) {\n\t\t\tthis.buf[(this.head + i) % this.capacity] = undefined;\n\t\t}\n\t\tthis.head = 0;\n\t\tthis._size = 0;\n\t}\n}\n","/**\n * Causal walkback over a {@link Graph.describe} snapshot (roadmap §9.2).\n *\n * `explainPath` finds the shortest dep-chain from `from` to `to` and returns a\n * step-by-step {@link CausalChain} enriched with each node's current value,\n * status, last-mutation actor, and any `graph.trace()` reasoning annotation.\n *\n * Pure function over the snapshot — peer to {@link reachable}. The\n * {@link Graph.explain} instance method auto-passes `describe({detail:\"standard\"})`\n * plus runtime annotations and `lastMutation` so callers get rich output by\n * default.\n *\n * @module\n */\nimport type { Actor } from \"../core/actor.js\";\nimport type { DescribeNodeOutput } from \"../core/meta.js\";\nimport type { GraphDescribeOutput } from \"./graph.js\";\n\n/** One node along the causal chain returned by {@link explainPath}. */\nexport interface CausalStep {\n\t/** Qualified node path. */\n\tpath: string;\n\t/** Node kind (`state` / `derived` / `producer` / etc.). */\n\ttype: DescribeNodeOutput[\"type\"];\n\t/** Status as of the source snapshot. */\n\tstatus?: DescribeNodeOutput[\"status\"];\n\t/** Cached value at snapshot time (omitted when describe didn't include it). */\n\tvalue?: unknown;\n\t/** Hop distance from `from` (0 = `from`, N = `to`). */\n\thop: number;\n\t/** Reason annotation set via `graph.trace(path, reason)`, when present. */\n\treason?: string;\n\t/** Most recent guarded mutation, when known. */\n\tlastMutation?: Readonly<{ actor: Actor; timestamp_ns: number }>;\n\t/** V0/V1 versioning info, when present. */\n\tv?: DescribeNodeOutput[\"v\"];\n\t/** Index of this step in the next step's `deps` (i.e. which dep slot fed forward). */\n\tdep_index?: number;\n\t/**\n\t * All dep slots when the same dep appears multiple times in the next\n\t * step's `deps`. Present only for multi-edge connections; `dep_index`\n\t * always equals `dep_indices[0]` when set.\n\t */\n\tdep_indices?: number[];\n}\n\n/** Outcome of an {@link explainPath} call. */\nexport interface CausalChain {\n\tfrom: string;\n\tto: string;\n\t/** True when a path was found. */\n\tfound: boolean;\n\t/** Why the chain may be empty/incomplete. `\"ok\"` when `found` is true. */\n\treason: \"ok\" | \"no-such-from\" | \"no-such-to\" | \"no-path\" | \"max-depth-exceeded\";\n\t/** Ordered steps — first element is `from`, last is `to`. Empty when `!found`. */\n\tsteps: readonly CausalStep[];\n\t/** Pretty multi-line rendering. Always present, even on failure (one-line message). */\n\ttext: string;\n\t/** JSON-serializable form (drops `text` to keep payloads compact). */\n\ttoJSON(): {\n\t\tfrom: string;\n\t\tto: string;\n\t\tfound: boolean;\n\t\treason: CausalChain[\"reason\"];\n\t\tsteps: readonly CausalStep[];\n\t};\n}\n\n/** Options for {@link explainPath}. */\nexport interface ExplainPathOptions {\n\t/** Maximum hop distance to search. Omit for unbounded. */\n\tmaxDepth?: number;\n\t/** Per-path reasoning annotations (typically `graph.trace()` output map). */\n\tannotations?: ReadonlyMap<string, string>;\n\t/** Per-path `lastMutation` map (overrides describe-derived values). */\n\tlastMutations?: ReadonlyMap<string, Readonly<{ actor: Actor; timestamp_ns: number }>>;\n\t/**\n\t * When `true` and `from === to`, search for a non-trivial cycle (path\n\t * back to `from` through ≥1 other node) instead of returning the trivial\n\t * single-step. Use when debugging feedback loops (COMPOSITION-GUIDE §7).\n\t * If no real cycle exists, falls back to the trivial single-step. Default\n\t * `false` — backward-compatible.\n\t */\n\tfindCycle?: boolean;\n}\n\n/**\n * Walks backward from `to` through `deps` to find the shortest path to `from`,\n * then assembles an ordered, enriched {@link CausalChain}.\n *\n * @param described - `graph.describe()` output (any detail level; richer detail → richer steps).\n * @param from - Path of the upstream node (the cause).\n * @param to - Path of the downstream node (the effect).\n * @param opts - Optional `maxDepth` and per-path annotation overlays.\n * @returns A {@link CausalChain} — `found:false` with a `reason` when no path exists.\n *\n * @example\n * ```ts\n * import { explainPath } from \"@graphrefly/graphrefly-ts\";\n * const chain = explainPath(graph.describe({ detail: \"standard\" }), \"input\", \"result\");\n * console.log(chain.text);\n * ```\n */\nexport function explainPath(\n\tdescribed: GraphDescribeOutput,\n\tfrom: string,\n\tto: string,\n\topts: ExplainPathOptions = {},\n): CausalChain {\n\tconst fromExists = from in described.nodes;\n\tconst toExists = to in described.nodes;\n\tif (!fromExists) return makeFailure(from, to, \"no-such-from\");\n\tif (!toExists) return makeFailure(from, to, \"no-such-to\");\n\n\tconst maxDepth = opts.maxDepth;\n\tif (maxDepth != null && (!Number.isInteger(maxDepth) || maxDepth < 0)) {\n\t\tthrow new Error(`explainPath: maxDepth must be an integer >= 0`);\n\t}\n\n\tif (from === to) {\n\t\t// findCycle: search for shortest non-trivial cycle (a path of ≥2 hops\n\t\t// back to `from` through other nodes). Falls back to trivial single\n\t\t// step if no real cycle exists.\n\t\tif (opts.findCycle === true) {\n\t\t\tconst cycle = findShortestCycle(described, from, opts);\n\t\t\tif (cycle != null) return cycle;\n\t\t}\n\t\tconst step = buildStep(from, described.nodes[from]!, 0, opts);\n\t\treturn makeSuccess(from, to, [step]);\n\t}\n\n\tif (maxDepth === 0) return makeFailure(from, to, \"no-path\");\n\n\tconst result = bfsShortestPath(described, from, to, maxDepth);\n\tif (!result.found) {\n\t\treturn makeFailure(from, to, result.truncated ? \"max-depth-exceeded\" : \"no-path\");\n\t}\n\treturn makeSuccess(from, to, materializeSteps(described, result.pathOrder, opts));\n}\n\n// ── BFS helpers ──────────────────────────────────────────────────────────\n\ntype StepPlan = { path: string; depIndices?: number[] };\n\ninterface BfsResult {\n\tfound: boolean;\n\tpathOrder: StepPlan[];\n\ttruncated: boolean;\n}\n\n/**\n * Backward BFS from `to` to `from`. Returns the ordered chain `from → … → to`\n * with `depIndices` annotating each non-final step (which slot(s) in the next\n * step's `deps` list connect us — typically a single index, but multi-edges\n * preserve every matching slot).\n */\nfunction bfsShortestPath(\n\tdescribed: GraphDescribeOutput,\n\tfrom: string,\n\tto: string,\n\tmaxDepth: number | undefined,\n): BfsResult {\n\ttype Pred = { from: string; depIndices: number[] };\n\tconst pred = new Map<string, Pred>();\n\tconst queue: Array<{ path: string; depth: number }> = [{ path: to, depth: 0 }];\n\tconst visited = new Set<string>([to]);\n\tlet head = 0;\n\tlet truncated = false;\n\n\twhile (head < queue.length) {\n\t\tconst cur = queue[head++]!;\n\t\tif (cur.path === from) break;\n\t\tif (maxDepth != null && cur.depth >= maxDepth) {\n\t\t\tconst node = described.nodes[cur.path];\n\t\t\tif (node?.deps && node.deps.length > 0) truncated = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconst node = described.nodes[cur.path];\n\t\tif (node == null) continue;\n\t\tconst deps = node.deps ?? [];\n\t\t// Aggregate all dep-slot indices for each unique dep — preserves\n\t\t// multi-edge information when the same dep appears twice.\n\t\tconst slots = new Map<string, number[]>();\n\t\tfor (let i = 0; i < deps.length; i++) {\n\t\t\tconst dep = deps[i]!;\n\t\t\tif (!dep) continue;\n\t\t\tlet arr = slots.get(dep);\n\t\t\tif (arr == null) {\n\t\t\t\tarr = [];\n\t\t\t\tslots.set(dep, arr);\n\t\t\t}\n\t\t\tarr.push(i);\n\t\t}\n\t\tfor (const [dep, indices] of slots) {\n\t\t\tif (visited.has(dep)) continue;\n\t\t\tvisited.add(dep);\n\t\t\tpred.set(dep, { from: cur.path, depIndices: indices });\n\t\t\tqueue.push({ path: dep, depth: cur.depth + 1 });\n\t\t}\n\t}\n\n\tif (!pred.has(from)) {\n\t\treturn { found: false, pathOrder: [], truncated };\n\t}\n\n\t// Reconstruct: walk pred from `from` forward to `to`.\n\tconst pathOrder: StepPlan[] = [{ path: from }];\n\tlet cursor = from;\n\twhile (cursor !== to) {\n\t\tconst p = pred.get(cursor);\n\t\tif (p == null) return { found: false, pathOrder: [], truncated: false };\n\t\t// Attach depIndices to the step we just came from (cursor) — dep_index\n\t\t// names \"which slot in the NEXT step's deps am I\".\n\t\tpathOrder[pathOrder.length - 1]!.depIndices = p.depIndices;\n\t\tpathOrder.push({ path: p.from });\n\t\tcursor = p.from;\n\t}\n\treturn { found: true, pathOrder, truncated: false };\n}\n\n/**\n * Find the shortest cycle starting and ending at `start`, excluding the\n * trivial 0-hop \"self-step\" case. Returns a {@link CausalChain} success when\n * a cycle of length ≥2 exists, otherwise `null`. Handles direct self-loops\n * (`start ∈ deps(start)`) and multi-hop cycles uniformly.\n */\nfunction findShortestCycle(\n\tdescribed: GraphDescribeOutput,\n\tstart: string,\n\topts: ExplainPathOptions,\n): CausalChain | null {\n\tconst startNode = described.nodes[start];\n\tif (startNode == null) return null;\n\tconst startDeps = startNode.deps ?? [];\n\n\t// Direct self-loop: start ∈ deps(start). Return [start, start] with\n\t// dep_index pointing at the matching slot(s).\n\tconst selfSlots: number[] = [];\n\tfor (let i = 0; i < startDeps.length; i++) if (startDeps[i] === start) selfSlots.push(i);\n\tif (selfSlots.length > 0) {\n\t\tconst step0 = buildStep(start, startNode, 0, opts);\n\t\tstep0.dep_index = selfSlots[0]!;\n\t\tconst step1 = buildStep(start, startNode, 1, opts);\n\t\treturn makeSuccess(start, start, [step0, step1]);\n\t}\n\n\t// Multi-hop cycle: BFS from each direct dep of start back to start.\n\tlet best: BfsResult | null = null;\n\tfor (let i = 0; i < startDeps.length; i++) {\n\t\tconst dep = startDeps[i]!;\n\t\tif (!dep || dep === start) continue;\n\t\tconst sub = bfsShortestPath(described, dep, start, opts.maxDepth);\n\t\tif (!sub.found) continue;\n\t\tif (best == null || sub.pathOrder.length < best.pathOrder.length) {\n\t\t\tbest = sub;\n\t\t\t// Prepend `start` so the cycle reads: start → dep → … → start.\n\t\t\t// The slot index from start to its first dep needs preserving.\n\t\t\tbest = {\n\t\t\t\tfound: true,\n\t\t\t\tpathOrder: [{ path: start, depIndices: [i] }, ...sub.pathOrder],\n\t\t\t\ttruncated: false,\n\t\t\t};\n\t\t}\n\t}\n\tif (best == null) return null;\n\treturn makeSuccess(start, start, materializeSteps(described, best.pathOrder, opts));\n}\n\nfunction materializeSteps(\n\tdescribed: GraphDescribeOutput,\n\tpathOrder: readonly StepPlan[],\n\topts: ExplainPathOptions,\n): CausalStep[] {\n\treturn pathOrder.map((entry, i) => {\n\t\tconst node = described.nodes[entry.path]!;\n\t\tconst step = buildStep(entry.path, node, i, opts);\n\t\tif (entry.depIndices != null && entry.depIndices.length > 0) {\n\t\t\tstep.dep_index = entry.depIndices[0]!;\n\t\t\tif (entry.depIndices.length > 1) step.dep_indices = [...entry.depIndices];\n\t\t}\n\t\treturn step;\n\t});\n}\n\nfunction buildStep(\n\tpath: string,\n\tnode: DescribeNodeOutput,\n\thop: number,\n\topts: ExplainPathOptions,\n): CausalStep {\n\tconst step: CausalStep = {\n\t\tpath,\n\t\ttype: node.type,\n\t\thop,\n\t};\n\tif (node.status !== undefined) step.status = node.status;\n\tif (\"value\" in node) step.value = node.value;\n\tif (node.v != null) step.v = node.v;\n\tconst annotation = opts.annotations?.get(path) ?? node.reason;\n\tif (annotation != null) step.reason = annotation;\n\tconst lastMutation = opts.lastMutations?.get(path) ?? node.lastMutation;\n\tif (lastMutation != null) step.lastMutation = lastMutation;\n\treturn step;\n}\n\nfunction makeSuccess(from: string, to: string, steps: readonly CausalStep[]): CausalChain {\n\treturn finalize(from, to, true, \"ok\", steps);\n}\n\nfunction makeFailure(from: string, to: string, reason: CausalChain[\"reason\"]): CausalChain {\n\treturn finalize(from, to, false, reason, []);\n}\n\nfunction finalize(\n\tfrom: string,\n\tto: string,\n\tfound: boolean,\n\treason: CausalChain[\"reason\"],\n\tsteps: readonly CausalStep[],\n): CausalChain {\n\tconst text = renderChain(from, to, found, reason, steps);\n\treturn {\n\t\tfrom,\n\t\tto,\n\t\tfound,\n\t\treason,\n\t\tsteps,\n\t\ttext,\n\t\ttoJSON() {\n\t\t\treturn { from, to, found, reason, steps };\n\t\t},\n\t};\n}\n\nfunction renderChain(\n\tfrom: string,\n\tto: string,\n\tfound: boolean,\n\treason: CausalChain[\"reason\"],\n\tsteps: readonly CausalStep[],\n): string {\n\tif (!found) {\n\t\tswitch (reason) {\n\t\t\tcase \"no-such-from\":\n\t\t\t\treturn `explainPath: no node named \"${from}\"`;\n\t\t\tcase \"no-such-to\":\n\t\t\t\treturn `explainPath: no node named \"${to}\"`;\n\t\t\tcase \"max-depth-exceeded\":\n\t\t\t\treturn `explainPath: no path from \"${from}\" to \"${to}\" within maxDepth`;\n\t\t\tdefault:\n\t\t\t\treturn `explainPath: no path from \"${from}\" to \"${to}\"`;\n\t\t}\n\t}\n\tconst lines: string[] = [`Causal path: ${from} → ${to} (${steps.length} step(s))`];\n\tfor (const step of steps) {\n\t\tconst arrow = step.hop === 0 ? \"·\" : \"↓\";\n\t\tconst head = ` ${arrow} ${step.path} (${step.type}${step.status ? `/${step.status}` : \"\"})`;\n\t\tlines.push(head);\n\t\tif (\"value\" in step) {\n\t\t\tlines.push(` value: ${formatValue(step.value)}`);\n\t\t}\n\t\tif (step.reason != null) {\n\t\t\tlines.push(` reason: ${step.reason}`);\n\t\t}\n\t\tif (step.lastMutation != null) {\n\t\t\tconst a = step.lastMutation.actor;\n\t\t\tlines.push(` actor: ${a.type}${a.id ? `:${a.id}` : \"\"}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction formatValue(v: unknown): string {\n\tif (v === undefined) return \"<sentinel>\";\n\tif (v === null) return \"null\";\n\tif (typeof v === \"string\") return JSON.stringify(v);\n\tif (typeof v === \"number\" || typeof v === \"boolean\" || typeof v === \"bigint\") return String(v);\n\ttry {\n\t\tconst s = JSON.stringify(v);\n\t\treturn s.length > 80 ? `${s.slice(0, 77)}...` : s;\n\t} catch {\n\t\treturn String(v);\n\t}\n}\n","/**\n * Approximate in-memory size estimation for arbitrary JS values.\n *\n * Iterative walk with cycle detection via `WeakSet`. V8-tuned overhead\n * heuristics. Not exact — approximate enough for profiling and hotspot\n * detection.\n *\n * Use cases: `graphProfile` (per-node value size), reactive data structure\n * memory audits, heuristic cache admission.\n *\n * @module\n */\n\n/** Approximate per-type overhead in bytes (V8 heuristics). */\nexport const OVERHEAD = {\n\tobject: 56,\n\tarray: 64,\n\tstring: 40, // header; content added separately\n\tnumber: 8,\n\tboolean: 4,\n\tnull: 0,\n\tundefined: 0,\n\tsymbol: 40,\n\tbigint: 16, // base; scales with digit count (see `_bigintSize`)\n\tfunction: 120,\n\tmap: 72,\n\tset: 72,\n\tmapEntry: 40,\n\tsetEntry: 24,\n\tdate: 24,\n\tregexp: 48,\n\terror: 64,\n\turl: 80,\n\tpromise: 48,\n\tweakmap: 40,\n\tweakset: 40,\n} as const;\n\n/**\n * Optional user hook. Declare a `sizeof` symbol key on any object to return\n * a precomputed size (in bytes); the walker will honor it and skip recursion.\n *\n * @example\n * ```ts\n * const SIZEOF = Symbol.for(\"sizeof\");\n * class MyCache { [SIZEOF]() { return this.bytes; } }\n * ```\n */\nexport const SIZEOF_SYMBOL = Symbol.for(\"sizeof\");\n\n/**\n * Estimate the approximate retained memory (in bytes) of a JS value.\n *\n * Handles primitives, plain objects, arrays, Maps, Sets, ArrayBuffers +\n * TypedArrays (shared-buffer dedup), Date, RegExp, Error, URL, Promise,\n * WeakMap, WeakSet, nested combinations. Cyclic refs are counted once.\n *\n * @param value - The value to measure.\n * @returns Approximate size in bytes.\n */\nexport function sizeof(value: unknown): number {\n\tconst seen = new WeakSet<object>();\n\tconst seenBuffers = new WeakSet<ArrayBufferLike>();\n\t// Iterative walk via explicit stack — avoids blowing the call stack on\n\t// deeply nested values (linked lists, AST nodes, deep JSON).\n\tconst stack: unknown[] = [value];\n\tlet total = 0;\n\twhile (stack.length > 0) {\n\t\tconst v = stack.pop();\n\t\ttotal += _shallowSize(v, seen, seenBuffers, stack);\n\t}\n\treturn total;\n}\n\n/** Shallow size of `v`; pushes children onto `stack` for iterative traversal. */\nfunction _shallowSize(\n\tvalue: unknown,\n\tseen: WeakSet<object>,\n\tseenBuffers: WeakSet<ArrayBufferLike>,\n\tstack: unknown[],\n): number {\n\tif (value === null || value === undefined) return 0;\n\n\tconst t = typeof value;\n\tswitch (t) {\n\t\tcase \"number\":\n\t\t\treturn OVERHEAD.number;\n\t\tcase \"boolean\":\n\t\t\treturn OVERHEAD.boolean;\n\t\tcase \"string\":\n\t\t\treturn OVERHEAD.string + (value as string).length * 2;\n\t\tcase \"bigint\":\n\t\t\treturn OVERHEAD.bigint + _bigintSize(value as bigint);\n\t\tcase \"symbol\":\n\t\t\treturn OVERHEAD.symbol;\n\t\tcase \"function\":\n\t\t\tif (seen.has(value as object)) return 0;\n\t\t\tseen.add(value as object);\n\t\t\treturn OVERHEAD.function;\n\t\tcase \"undefined\":\n\t\t\treturn 0;\n\t}\n\n\tconst obj = value as object;\n\tif (seen.has(obj)) return 0;\n\tseen.add(obj);\n\n\t// User-supplied size hook wins — `Symbol.for(\"sizeof\")` method on the\n\t// object returns an exact byte count and we skip recursion.\n\tconst hook = (obj as Record<symbol, unknown>)[SIZEOF_SYMBOL];\n\tif (typeof hook === \"function\") {\n\t\ttry {\n\t\t\tconst reported = (hook as () => unknown).call(obj);\n\t\t\tif (typeof reported === \"number\" && Number.isFinite(reported)) return reported;\n\t\t} catch {\n\t\t\t/* ignore — fall through to default estimator */\n\t\t}\n\t}\n\n\tif (obj instanceof Date) return OVERHEAD.date;\n\tif (obj instanceof RegExp) return OVERHEAD.regexp + obj.source.length * 2;\n\tif (obj instanceof Error) {\n\t\tconst m = obj.message ? obj.message.length * 2 : 0;\n\t\tconst s = obj.stack ? obj.stack.length * 2 : 0;\n\t\treturn OVERHEAD.error + m + s;\n\t}\n\tif (typeof URL !== \"undefined\" && obj instanceof URL) {\n\t\treturn OVERHEAD.url + obj.href.length * 2;\n\t}\n\tif (typeof Promise !== \"undefined\" && obj instanceof Promise) {\n\t\treturn OVERHEAD.promise;\n\t}\n\tif (obj instanceof WeakMap) return OVERHEAD.weakmap;\n\tif (obj instanceof WeakSet) return OVERHEAD.weakset;\n\n\tif (obj instanceof Map) {\n\t\tlet size = OVERHEAD.map;\n\t\tfor (const [k, v] of obj) {\n\t\t\tsize += OVERHEAD.mapEntry;\n\t\t\tstack.push(k);\n\t\t\tstack.push(v);\n\t\t}\n\t\treturn size;\n\t}\n\n\tif (obj instanceof Set) {\n\t\tlet size = OVERHEAD.set;\n\t\tfor (const v of obj) {\n\t\t\tsize += OVERHEAD.setEntry;\n\t\t\tstack.push(v);\n\t\t}\n\t\treturn size;\n\t}\n\n\tif (Array.isArray(obj)) {\n\t\tconst size = OVERHEAD.array + obj.length * 8;\n\t\tfor (const item of obj) stack.push(item);\n\t\treturn size;\n\t}\n\n\t// ArrayBuffer — count once per buffer (multi-view dedup via `seenBuffers`).\n\tif (obj instanceof ArrayBuffer) {\n\t\tif (seenBuffers.has(obj)) return 0;\n\t\tseenBuffers.add(obj);\n\t\treturn obj.byteLength;\n\t}\n\tif (ArrayBuffer.isView(obj)) {\n\t\tconst view = obj as { byteLength: number; buffer: ArrayBufferLike };\n\t\tif (seenBuffers.has(view.buffer)) return 48; // view header only\n\t\tseenBuffers.add(view.buffer);\n\t\t// Charge the full underlying buffer — a small view over a large\n\t\t// buffer still retains all of it. Add the view header on top.\n\t\treturn view.buffer.byteLength + 48;\n\t}\n\n\t// Plain object — sum key overhead + recurse into values.\n\tlet size = OVERHEAD.object;\n\tconst keys = Object.keys(obj);\n\tfor (const key of keys) {\n\t\tsize += OVERHEAD.string + key.length * 2;\n\t\ttry {\n\t\t\tstack.push((obj as Record<string, unknown>)[key]);\n\t\t} catch {\n\t\t\t/* getter throw — skip this key */\n\t\t}\n\t}\n\treturn size;\n}\n\n/** BigInt digit-count-based sizing: each ~32-bit limb ≈ 8 bytes. */\nfunction _bigintSize(n: bigint): number {\n\tconst abs = n < 0n ? -n : n;\n\tif (abs === 0n) return 0;\n\tconst bits = abs.toString(2).length;\n\treturn Math.ceil(bits / 32) * 8;\n}\n","/**\n * Graph profiling and inspection utilities.\n *\n * Provides per-node memory estimation, connectivity stats, and hotspot\n * detection. Non-invasive — reads from `describe()` and node internals\n * without modifying state.\n *\n * @module\n */\n\nimport { type Node, NodeImpl } from \"../core/node.js\";\nimport { sizeof } from \"../extra/utils/sizeof.js\";\nimport type { Graph, GraphDescribeOutput } from \"./graph.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Per-node profile entry. */\nexport interface NodeProfile {\n\t/** Qualified path within the graph. */\n\tpath: string;\n\t/** Node type (state, derived, producer, effect). */\n\ttype: string;\n\t/** Node status (disconnected, dirty, settled, errored, completed). */\n\tstatus: string;\n\t/** Approximate retained bytes for the node's cached value. */\n\tvalueSizeBytes: number;\n\t/** Number of downstream subscribers (sinks). */\n\tsubscriberCount: number;\n\t/** Number of upstream dependencies. */\n\tdepCount: number;\n\t/**\n\t * True if this is an effect node with no external subscribers — a classic\n\t * leak pattern. See {@link GraphProfileResult.orphans} for the broader\n\t * orphan-node detection across `derived` / `producer` / `effect`.\n\t */\n\tisOrphanEffect: boolean;\n\t/**\n\t * Orphan category (batch 8 Unit 13 D). `null` when the node is healthy.\n\t * - `\"orphan-effect\"` — effect with zero subscribers (pre-existing class).\n\t * - `\"idle-derived\"` — derived with zero subscribers (wasted compute path\n\t * if it ever activates; may indicate a factory forgot keepalive).\n\t * - `\"idle-producer\"` — producer with zero subscribers (no external\n\t * consumer; may be an over-eager factory or forgotten cleanup).\n\t */\n\torphanKind: \"orphan-effect\" | \"idle-derived\" | \"idle-producer\" | null;\n}\n\n/** Aggregate graph profile. */\nexport interface GraphProfileResult {\n\t/** Total node count. */\n\tnodeCount: number;\n\t/** Total edge count. */\n\tedgeCount: number;\n\t/** Subgraph count. */\n\tsubgraphCount: number;\n\t/** All node profiles. */\n\tnodes: NodeProfile[];\n\t/** Total approximate value memory across all nodes. */\n\ttotalValueSizeBytes: number;\n\t/**\n\t * Top-N hotspots by dimension. Each list is sorted descending. See\n\t * {@link GraphProfileOptions.topN} for the cap (default 10).\n\t */\n\thotspots: {\n\t\tbyValueSize: NodeProfile[];\n\t\tbySubscriberCount: NodeProfile[];\n\t\tbyDepCount: NodeProfile[];\n\t};\n\t/**\n\t * Every orphan across types — `effect`, `derived`, `producer` with zero\n\t * subscribers. See {@link NodeProfile.orphanKind} for category.\n\t */\n\torphans: NodeProfile[];\n\t/** Effect nodes with no external subscribers (legacy; subset of `orphans`). */\n\torphanEffects: NodeProfile[];\n}\n\n/** Options for {@link graphProfile}. */\nexport interface GraphProfileOptions {\n\t/** Limit hotspot list (default 10). */\n\ttopN?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Profile a graph's memory and connectivity characteristics.\n *\n * Uses `describe({ detail: \"standard\" })` for node metadata and direct\n * `NodeImpl` access for subscriber counts and cached values.\n *\n * @param graph - The graph to profile.\n * @param opts - Optional configuration.\n * @returns Aggregate profile with per-node details, hotspots (multi-dim), and orphans.\n */\nexport function graphProfile(graph: Graph, opts?: GraphProfileOptions): GraphProfileResult {\n\tconst topN = opts?.topN ?? 10;\n\n\tconst desc: GraphDescribeOutput = graph.describe({ detail: \"standard\" });\n\n\t// Build path→Node lookup via _collectObserveTargets (same as describe uses).\n\t// Runtime guard: if the internal method is missing (refactored), degrade\n\t// gracefully — profiles will show 0 for valueSizeBytes and subscriberCount.\n\tconst targets: [string, Node][] = [];\n\tconst collector = (\n\t\tgraph as unknown as { _collectObserveTargets?: (prefix: string, out: [string, Node][]) => void }\n\t)._collectObserveTargets;\n\tif (typeof collector === \"function\") {\n\t\tcollector.call(graph, \"\", targets);\n\t}\n\tconst pathToNode = new Map<string, Node>();\n\tfor (const [p, n] of targets) pathToNode.set(p, n);\n\n\tconst profiles: NodeProfile[] = [];\n\n\tfor (const [path, nodeDesc] of Object.entries(desc.nodes)) {\n\t\tconst nd = pathToNode.get(path);\n\t\tconst impl = nd instanceof NodeImpl ? nd : null;\n\n\t\tconst valueSizeBytes = impl ? sizeof(impl.cache) : 0;\n\t\tconst subscriberCount = impl ? impl._sinkCount : 0;\n\t\tconst depCount = nodeDesc.deps?.length ?? 0;\n\n\t\tconst isOrphanEffect = nodeDesc.type === \"effect\" && subscriberCount === 0;\n\t\tconst orphanKind: NodeProfile[\"orphanKind\"] =\n\t\t\tsubscriberCount === 0\n\t\t\t\t? nodeDesc.type === \"effect\"\n\t\t\t\t\t? \"orphan-effect\"\n\t\t\t\t\t: nodeDesc.type === \"derived\"\n\t\t\t\t\t\t? \"idle-derived\"\n\t\t\t\t\t\t: nodeDesc.type === \"producer\"\n\t\t\t\t\t\t\t? \"idle-producer\"\n\t\t\t\t\t\t\t: null\n\t\t\t\t: null;\n\n\t\tprofiles.push({\n\t\t\tpath,\n\t\t\ttype: nodeDesc.type,\n\t\t\tstatus: nodeDesc.status ?? \"unknown\",\n\t\t\tvalueSizeBytes,\n\t\t\tsubscriberCount,\n\t\t\tdepCount,\n\t\t\tisOrphanEffect,\n\t\t\torphanKind,\n\t\t});\n\t}\n\n\tconst totalValueSizeBytes = profiles.reduce((sum, p) => sum + p.valueSizeBytes, 0);\n\n\tconst topBy = <K extends keyof NodeProfile>(\n\t\tkey: K,\n\t\tcmp?: (a: NodeProfile, b: NodeProfile) => number,\n\t): NodeProfile[] =>\n\t\t[...profiles].sort(cmp ?? ((a, b) => (b[key] as number) - (a[key] as number))).slice(0, topN);\n\n\tconst orphans = profiles.filter((p) => p.orphanKind != null);\n\tconst orphanEffects = profiles.filter((p) => p.isOrphanEffect);\n\n\treturn {\n\t\tnodeCount: profiles.length,\n\t\tedgeCount: desc.edges.length,\n\t\tsubgraphCount: desc.subgraphs.length,\n\t\tnodes: profiles,\n\t\ttotalValueSizeBytes,\n\t\thotspots: {\n\t\t\tbyValueSize: topBy(\"valueSizeBytes\"),\n\t\t\tbySubscriberCount: topBy(\"subscriberCount\"),\n\t\t\tbyDepCount: topBy(\"depCount\"),\n\t\t},\n\t\torphans,\n\t\torphanEffects,\n\t};\n}\n","import type { Actor } from \"../core/actor.js\";\nimport { batch, isBatching } from \"../core/batch.js\";\nimport { monotonicNs, wallClockNs } from \"../core/clock.js\";\nimport type { GraphReFlyConfig } from \"../core/config.js\";\nimport { GuardDenied } from \"../core/guard.js\";\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tINVALIDATE,\n\ttype Messages,\n\tPAUSE,\n\tRESOLVED,\n\tRESUME,\n\tTEARDOWN,\n} from \"../core/messages.js\";\nimport {\n\ttype DescribeDetail,\n\ttype DescribeField,\n\ttype DescribeNodeOutput,\n\tdescribeNode,\n\tresolveDescribeFields,\n} from \"../core/meta.js\";\nimport {\n\tdefaultConfig,\n\ttype Node,\n\tNodeImpl,\n\ttype NodeSink,\n\ttype NodeTransportOptions,\n} from \"../core/node.js\";\nimport { producer, state as stateNode } from \"../core/sugar.js\";\nimport type { VersioningLevel } from \"../core/versioning.js\";\nimport type { StorageHandle, StorageTier } from \"../extra/storage.js\";\nimport { ResettableTimer } from \"../extra/timer.js\";\nimport { RingBuffer } from \"../extra/utils/ring-buffer.js\";\nimport { decodeEnvelope, encodeEnvelope, type GraphCodec } from \"./codec.js\";\nimport { type CausalChain, explainPath } from \"./explain.js\";\nimport { type GraphProfileOptions, type GraphProfileResult, graphProfile } from \"./profile.js\";\n\n/** The separator used for qualified paths in {@link Graph.resolve} et al. */\nconst PATH_SEP = \"::\";\n\n/**\n * Reserved segment for meta companion paths: `nodeName::__meta__::metaKey` (GRAPHREFLY-SPEC §3.6).\n * Forbidden as a local node or mount name.\n */\nexport const GRAPH_META_SEGMENT = \"__meta__\";\n\n/**\n * Options for {@link Graph}. Named fields documented below; the open index\n * signature is preserved so callers can stash extension data on the graph\n * without losing type discipline on the reserved names.\n *\n * - `config` — bind this graph to a specific {@link GraphReFlyConfig} for\n * tier/metaPassthrough/inspector lookups. Defaults to the singleton\n * `defaultConfig` exported from `core/node.ts`.\n * - `versioning` — convenience for `graph.setVersioning(level)` at\n * construction time. Monotonic bulk-apply; see {@link Graph.setVersioning}.\n * - `factories` — reserved for future per-graph factory registration;\n * currently factories flow through `Graph.fromSnapshot(data, {factories})`.\n */\nexport interface GraphOptions {\n\tconfig?: GraphReFlyConfig;\n\tversioning?: VersioningLevel;\n\tfactories?: Record<string, GraphNodeFactory>;\n\t/**\n\t * Capacity of the reasoning-trace ring buffer. Default: `1000`. Set lower\n\t * to reduce memory; higher for audit-heavy workloads. Set at construction\n\t * time — not mutable afterward (ring buffers can't resize cleanly).\n\t */\n\ttraceCapacity?: number;\n\t[key: string]: unknown;\n}\n\n/** Filter for {@link Graph.describe} — object-style partial match or predicate. */\nexport type DescribeFilter =\n\t| Partial<Pick<DescribeNodeOutput, \"type\" | \"status\">>\n\t| {\n\t\t\ttype?: DescribeNodeOutput[\"type\"];\n\t\t\tstatus?: DescribeNodeOutput[\"status\"];\n\t\t\t/** Keep nodes whose `deps` includes this qualified path. */\n\t\t\tdepsIncludes?: string;\n\t\t\t/** Snake-case alias for `depsIncludes` (Python parity). */\n\t\t\tdeps_includes?: string;\n\t\t\t/** Keep nodes whose `meta` contains this key. */\n\t\t\tmetaHas?: string;\n\t\t\t/** Snake-case alias for `metaHas` (Python parity). */\n\t\t\tmeta_has?: string;\n\t }\n\t| ((node: DescribeNodeOutput) => boolean)\n\t| ((nodePath: string, node: DescribeNodeOutput) => boolean);\n\n/** Options for {@link Graph.signal} and {@link Graph.set} (actor context, internal lifecycle). */\nexport type GraphActorOptions = {\n\tactor?: Actor;\n\t/**\n\t * When `true`, skips node guards (graph lifecycle TEARDOWN, unmount teardown, etc.).\n\t */\n\tinternal?: boolean;\n};\n\n/** Options for {@link Graph.describe} (Phase 3.3b progressive disclosure). */\nexport type GraphDescribeOptions = {\n\tactor?: Actor;\n\t/**\n\t * Node filter. Filters operate on whatever fields the chosen `detail` level\n\t * provides. For `metaHas` and `status` filters, use `detail: \"standard\"` or\n\t * higher — at `\"minimal\"` those fields are absent and the filter silently\n\t * excludes all nodes.\n\t */\n\tfilter?: DescribeFilter;\n\t/**\n\t * Detail level (Phase 3.3b). Default: `\"minimal\"`.\n\t * - `\"minimal\"` — type + deps only\n\t * - `\"standard\"` — type, status, value, deps, meta, versioning (`v`)\n\t * - `\"full\"` — standard + guard, lastMutation\n\t */\n\tdetail?: DescribeDetail;\n\t/**\n\t * Explicit field selection (GraphQL-style). Overrides `detail` when provided.\n\t * Dotted paths like `\"meta.label\"` select specific meta keys.\n\t */\n\tfields?: DescribeField[];\n\t/**\n\t * Output format.\n\t * - `undefined` / omitted — return the full {@link GraphDescribeOutput} object.\n\t * - `\"spec\"` — GraphSpec input format (object; no status/value, deps as edges).\n\t * - `\"json\"` — stable JSON **text** with sorted keys.\n\t * - `\"pretty\"` — human-readable plaintext (optionally colorized; see\n\t * `colorize` / `indent` / `logger` / `includeEdges` / `includeSubgraphs`).\n\t * - `\"mermaid\"` — Mermaid flowchart text.\n\t * - `\"d2\"` — D2 diagram text.\n\t */\n\tformat?: \"spec\" | \"json\" | \"pretty\" | \"mermaid\" | \"d2\";\n\t/** Pretty/diagram render: direction for diagram formats (default `LR`). */\n\tdirection?: GraphDiagramDirection;\n\t/** Pretty/JSON render: indent (default 2 for JSON, ignored for pretty). */\n\tindent?: number;\n\t/** Pretty render: optional logger hook; fires with the rendered text before return. */\n\tlogger?: (text: string) => void;\n\t/** Pretty render: include an Edges section (default `true`). */\n\tincludeEdges?: boolean;\n\t/** Pretty render: include a Subgraphs section (default `true`). */\n\tincludeSubgraphs?: boolean;\n};\n\n/** JSON snapshot from {@link Graph.describe} (GRAPHREFLY-SPEC §3.6, Appendix B). */\nexport type GraphDescribeOutput = {\n\tname: string;\n\tnodes: Record<string, DescribeNodeOutput>;\n\tedges: ReadonlyArray<{ from: string; to: string }>;\n\tsubgraphs: string[];\n\t/**\n\t * Re-read the live graph with higher detail (Phase 3.3b).\n\t * Returns a new `GraphDescribeOutput`; the original remains a snapshot.\n\t * Present on live describe results; absent on deserialized snapshots.\n\t */\n\texpand?: (detailOrFields: DescribeDetail | DescribeField[]) => GraphDescribeOutput;\n};\n\n/**\n * Persisted graph snapshot: {@link GraphDescribeOutput} plus optional format version\n * ({@link Graph.snapshot}, {@link Graph.restore}, {@link Graph.fromSnapshot}, {@link Graph.toObject},\n * {@link Graph.toJSONString} — §3.8).\n */\nexport type GraphPersistSnapshot = GraphDescribeOutput & {\n\tversion?: number;\n};\n\nexport type GraphFactoryContext = {\n\tpath: string;\n\ttype: DescribeNodeOutput[\"type\"];\n\tvalue: unknown;\n\tmeta: Record<string, unknown>;\n\tdeps: readonly string[];\n\tresolvedDeps: readonly Node[];\n};\n\nexport type GraphNodeFactory = (name: string, context: GraphFactoryContext) => Node;\n\n/**\n * Checkpoint record shape passed to `StorageTier.save`. Written by\n * {@link Graph.attachStorage} per-tier according to each tier's\n * `compactEvery` cadence.\n *\n * `mode: \"full\"` → full snapshot. Baseline anchor emitted on the first save\n * and every `compactEvery`-th save thereafter. Sufficient to recover state\n * on its own without WAL replay.\n * `mode: \"diff\"` → delta payload only, relative to this tier's most recent\n * `\"full\"` baseline. Between compacts. Wire-efficient; requires WAL replay\n * over the preceding `\"full\"` record to reconstruct state.\n *\n * Every record includes `seq` (per-tier monotonic counter), `timestamp_ns`\n * (wall-clock at flush time), and `format_version` (envelope version for\n * cross-version WAL replay).\n */\nexport type GraphCheckpointRecord = {\n\tseq: number;\n\ttimestamp_ns: number;\n\tformat_version: number;\n} & ({ mode: \"full\"; snapshot: GraphPersistSnapshot } | { mode: \"diff\"; diff: GraphWALDiff });\n\n/** Options for {@link Graph.attachStorage}. */\nexport type GraphAttachStorageOptions = {\n\t/**\n\t * Before the first save, attempt to restore from the first tier whose\n\t * `load(graph.name)` hits. Runs asynchronously in the background for\n\t * async tiers; errors surface via `onError`. Default `false`.\n\t */\n\tautoRestore?: boolean;\n\t/**\n\t * Limit the subscription surface (scoped observe). By default\n\t * `attachStorage` observes every node in the graph tree; on large graphs\n\t * that's thousands of subscriptions just for tier-gating. Pass a path\n\t * list (or a single glob) to observe only those nodes.\n\t */\n\tpaths?: readonly string[] | string;\n\t/** Pre-save path-level filter — skip records triggered by paths that fail this predicate. */\n\tfilter?: (name: string, described: DescribeNodeOutput) => boolean;\n\t/** Surfaced on tier save errors and autoRestore failures. */\n\tonError?: (error: unknown, tier: StorageTier) => void;\n};\n\n/**\n * Event emitted by {@link Graph.topology} on every structural change to the\n * graph's own registry. Does NOT include value mutations (use `observe()` for\n * those) or transitively nested subgraph events (subscribe to each mounted\n * child's `topology` for that).\n *\n * - `\"added\"` — `name` is the local key registered via {@link Graph.add}\n * (`nodeKind: \"node\"`) or {@link Graph.mount} (`nodeKind: \"mount\"`).\n * - `\"removed\"` — emitted AFTER {@link Graph.remove} completes teardown.\n * `audit` is the full {@link GraphRemoveAudit} returned to the caller.\n */\nexport type TopologyEvent =\n\t| { kind: \"added\"; name: string; nodeKind: \"node\" | \"mount\" }\n\t| {\n\t\t\tkind: \"removed\";\n\t\t\tname: string;\n\t\t\tnodeKind: \"node\" | \"mount\";\n\t\t\taudit: GraphRemoveAudit;\n\t };\n\n/** Direction options for diagram export helpers. */\nexport type GraphDiagramDirection = \"TD\" | \"LR\" | \"BT\" | \"RL\";\n\n/** Options for {@link Graph.toMermaid} / {@link Graph.toD2}. */\nexport type GraphDiagramOptions = {\n\t/**\n\t * Diagram flow direction.\n\t * - `TD`: top-down\n\t * - `LR`: left-right (default)\n\t * - `BT`: bottom-top\n\t * - `RL`: right-left\n\t */\n\tdirection?: GraphDiagramDirection;\n};\n\n/**\n * Snapshot format version (§3.8). Exported so the surface layer's\n * `saveSnapshot` writes the same `format_version` as\n * `Graph.attachStorage` — one source of truth prevents silent wire\n * drift between auto-checkpoint and one-shot persistence paths.\n */\nexport const SNAPSHOT_VERSION = 1;\n\n/**\n * Drain a disposer set iteratively — pop, remove, run. Disposers registered\n * mid-drain are picked up by the next iteration. Capped to guard against a\n * disposer that re-registers itself in an infinite loop. Exceptions are\n * surfaced via `console.error` rather than silently swallowed so leaks in\n * cleanup code remain visible.\n */\nfunction drainDisposers(set: Set<() => void>, graphName: string): void {\n\tconst cap = Math.max(16, set.size * 4);\n\tlet iterations = 0;\n\twhile (set.size > 0) {\n\t\tif (iterations++ >= cap) {\n\t\t\tconsole.error(\n\t\t\t\t`[Graph \"${graphName}\".destroy] disposer drain exceeded cap (${cap}); ${set.size} disposer(s) discarded`,\n\t\t\t);\n\t\t\tset.clear();\n\t\t\treturn;\n\t\t}\n\t\tconst it = set.values().next();\n\t\tif (it.done) return;\n\t\tconst dispose = it.value;\n\t\tset.delete(dispose);\n\t\ttry {\n\t\t\tdispose();\n\t\t} catch (err) {\n\t\t\tconsole.error(`[Graph \"${graphName}\".destroy] disposer threw:`, err);\n\t\t}\n\t}\n}\n\n/**\n * Cheap graph-level V0 version fingerprint: concatenate `v.id@v.version` for\n * every node that carries V0 info. Used by {@link Graph.attachStorage} to\n * short-circuit per-tier flushes when nothing versioned has changed since\n * the tier's last save. Non-versioned graphs produce an empty string so the\n * shortcut is a no-op for them (every scheduled flush writes).\n */\nfunction computeVersionFingerprint(nodes: Record<string, DescribeNodeOutput>): string {\n\tconst parts: string[] = [];\n\tfor (const path of Object.keys(nodes).sort()) {\n\t\tconst v = nodes[path]!.v;\n\t\tif (v != null) parts.push(`${path}\\t${v.id}\\t${v.version}`);\n\t}\n\treturn parts.join(\"\\n\");\n}\n\n/**\n * Validate the snapshot envelope: version, required keys, types. Aligned with\n * Python `_parse_snapshot_envelope`. Throws on invalid data.\n */\nfunction parseSnapshotEnvelope(data: GraphPersistSnapshot): void {\n\tif (data.version !== SNAPSHOT_VERSION) {\n\t\tthrow new Error(\n\t\t\t`unsupported snapshot version ${String(data.version)} (expected ${SNAPSHOT_VERSION})`,\n\t\t);\n\t}\n\tfor (const key of [\"name\", \"nodes\", \"edges\", \"subgraphs\"] as const) {\n\t\tif (!(key in data)) {\n\t\t\tthrow new Error(`snapshot missing required key \"${key}\"`);\n\t\t}\n\t}\n\tif (typeof data.name !== \"string\") {\n\t\tthrow new TypeError(`snapshot 'name' must be a string`);\n\t}\n\tif (typeof data.nodes !== \"object\" || data.nodes === null || Array.isArray(data.nodes)) {\n\t\tthrow new TypeError(`snapshot 'nodes' must be an object`);\n\t}\n\tif (!Array.isArray(data.edges)) {\n\t\tthrow new TypeError(`snapshot 'edges' must be an array`);\n\t}\n\tif (!Array.isArray(data.subgraphs)) {\n\t\tthrow new TypeError(`snapshot 'subgraphs' must be an array`);\n\t}\n}\n\n/**\n * Structural deep equality — handles cycles, BigInt, Map, Set, Date, RegExp,\n * TypedArray, and nested objects/arrays. Used by `Graph.diff` to compare\n * node values without the cycle/BigInt/Map/Set footguns of `JSON.stringify`.\n *\n * Semantics: `Object.is` on primitives (so `NaN === NaN`, `-0 !== 0`), same\n * constructor required for object types, key-order-insensitive for plain\n * objects, order-sensitive for arrays + TypedArrays, unordered for Set,\n * key-equality for Map.\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n\tconst seen = new WeakMap<object, WeakSet<object>>();\n\tconst walk = (x: unknown, y: unknown): boolean => {\n\t\tif (Object.is(x, y)) return true;\n\t\tif (x == null || y == null || typeof x !== \"object\" || typeof y !== \"object\") return false;\n\t\t// Cycle handling: assume equal on re-encounter (cycles match iff they\n\t\t// correspond structurally — standard \"optimistic\" deep-equal rule).\n\t\tlet seenRhs = seen.get(x as object);\n\t\tif (seenRhs == null) {\n\t\t\tseenRhs = new WeakSet();\n\t\t\tseen.set(x as object, seenRhs);\n\t\t}\n\t\tif (seenRhs.has(y as object)) return true;\n\t\tseenRhs.add(y as object);\n\n\t\tconst ctorA = (x as object).constructor;\n\t\tconst ctorB = (y as object).constructor;\n\t\tif (ctorA !== ctorB) return false;\n\n\t\tif (x instanceof Date) return (x as Date).getTime() === (y as Date).getTime();\n\t\tif (x instanceof RegExp)\n\t\t\treturn (\n\t\t\t\t(x as RegExp).source === (y as RegExp).source && (x as RegExp).flags === (y as RegExp).flags\n\t\t\t);\n\t\tif (Array.isArray(x)) {\n\t\t\tconst arrB = y as unknown[];\n\t\t\tif ((x as unknown[]).length !== arrB.length) return false;\n\t\t\tfor (let i = 0; i < (x as unknown[]).length; i++) {\n\t\t\t\tif (!walk((x as unknown[])[i], arrB[i])) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (x instanceof Map) {\n\t\t\tconst mB = y as Map<unknown, unknown>;\n\t\t\tif ((x as Map<unknown, unknown>).size !== mB.size) return false;\n\t\t\tfor (const [k, v] of x as Map<unknown, unknown>) {\n\t\t\t\tif (!mB.has(k) || !walk(v, mB.get(k))) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (x instanceof Set) {\n\t\t\tconst sB = y as Set<unknown>;\n\t\t\tif ((x as Set<unknown>).size !== sB.size) return false;\n\t\t\t// O(n²) fallback — Sets have no ordering, and walking each pair\n\t\t\t// is the only way to support structural equality on non-primitive\n\t\t\t// members. Acceptable: diff scale is describe-output-sized.\n\t\t\tfor (const v of x as Set<unknown>) {\n\t\t\t\tlet found = false;\n\t\t\t\tfor (const w of sB) {\n\t\t\t\t\tif (walk(v, w)) {\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!found) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (ArrayBuffer.isView(x)) {\n\t\t\tconst taA = x as unknown as { length: number; [i: number]: number };\n\t\t\tconst taB = y as unknown as { length: number; [i: number]: number };\n\t\t\tif (taA.length !== taB.length) return false;\n\t\t\tfor (let i = 0; i < taA.length; i++) if (taA[i] !== taB[i]) return false;\n\t\t\treturn true;\n\t\t}\n\t\t// Plain object: same key-set, same values (key order irrelevant).\n\t\tconst keysA = Object.keys(x as Record<string, unknown>);\n\t\tconst keysB = Object.keys(y as Record<string, unknown>);\n\t\tif (keysA.length !== keysB.length) return false;\n\t\tconst setB = new Set(keysB);\n\t\tfor (const k of keysA) {\n\t\t\tif (!setB.has(k)) return false;\n\t\t\tif (!walk((x as Record<string, unknown>)[k], (y as Record<string, unknown>)[k])) return false;\n\t\t}\n\t\treturn true;\n\t};\n\treturn walk(a, b);\n}\n\n/** Recursively sort object keys for deterministic JSON (git-diffable). */\nfunction sortJsonValue(value: unknown): unknown {\n\tif (value === null || typeof value !== \"object\") {\n\t\treturn value;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map(sortJsonValue);\n\t}\n\tconst obj = value as Record<string, unknown>;\n\tconst keys = Object.keys(obj).sort();\n\tconst out: Record<string, unknown> = {};\n\tfor (const k of keys) {\n\t\tout[k] = sortJsonValue(obj[k]);\n\t}\n\treturn out;\n}\n\nfunction escapeMermaidLabel(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"');\n}\n\nfunction escapeD2Label(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"');\n}\n\nfunction d2DirectionFromGraphDirection(direction: GraphDiagramDirection): string {\n\tif (direction === \"TD\") return \"down\";\n\tif (direction === \"BT\") return \"up\";\n\tif (direction === \"RL\") return \"left\";\n\treturn \"right\";\n}\n\n/** Collect deduplicated (from, to) arrows from deps + edges. */\nfunction collectDiagramArrows(described: GraphDescribeOutput): [string, string][] {\n\tconst seen = new Set<string>();\n\tconst arrows: [string, string][] = [];\n\tfunction add(from: string, to: string): void {\n\t\tconst key = `${from}\\0${to}`;\n\t\tif (seen.has(key)) return;\n\t\tseen.add(key);\n\t\tarrows.push([from, to]);\n\t}\n\tfor (const [path, info] of Object.entries(described.nodes)) {\n\t\tconst deps: string[] | undefined = (info as Record<string, unknown>).deps as\n\t\t\t| string[]\n\t\t\t| undefined;\n\t\tif (deps) {\n\t\t\tfor (const dep of deps) add(dep, path);\n\t\t}\n\t}\n\tfor (const edge of described.edges) add(edge.from, edge.to);\n\treturn arrows;\n}\n\nfunction normalizeDiagramDirection(direction: unknown): GraphDiagramDirection {\n\tif (direction === undefined) return \"LR\";\n\tif (direction === \"TD\" || direction === \"LR\" || direction === \"BT\" || direction === \"RL\") {\n\t\treturn direction;\n\t}\n\tthrow new Error(\n\t\t`invalid diagram direction ${String(direction)}; expected one of: TD, LR, BT, RL`,\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// describe({format}) renderers — consolidated from the ex-dumpGraph /\n// ex-toMermaid / ex-toD2 methods (Unit 12 + Unit 20).\n// ---------------------------------------------------------------------------\n\nfunction renderDescribeAsJson(d: GraphDescribeOutput, options: GraphDescribeOptions): string {\n\tconst includeEdges = options.includeEdges ?? true;\n\tconst includeSubgraphs = options.includeSubgraphs ?? true;\n\tconst { expand: _expand, ...rest } = d;\n\tconst payload: GraphDescribeOutput = {\n\t\t...rest,\n\t\tedges: includeEdges ? d.edges : [],\n\t\tsubgraphs: includeSubgraphs ? d.subgraphs : [],\n\t};\n\tconst text = JSON.stringify(sortJsonValue(payload), null, options.indent ?? 2);\n\toptions.logger?.(text);\n\treturn text;\n}\n\nfunction renderDescribeAsPretty(d: GraphDescribeOutput, options: GraphDescribeOptions): string {\n\tconst includeEdges = options.includeEdges ?? true;\n\tconst includeSubgraphs = options.includeSubgraphs ?? true;\n\tconst lines: string[] = [];\n\tlines.push(`Graph ${d.name}`);\n\tlines.push(\"Nodes:\");\n\tfor (const path of Object.keys(d.nodes).sort()) {\n\t\tconst n = d.nodes[path]!;\n\t\tlines.push(`- ${path} (${n.type}/${n.status}): ${describeData(n.value)}`);\n\t}\n\tif (includeEdges) {\n\t\tlines.push(\"Edges:\");\n\t\tfor (const edge of d.edges) {\n\t\t\tlines.push(`- ${edge.from} -> ${edge.to}`);\n\t\t}\n\t}\n\tif (includeSubgraphs) {\n\t\tlines.push(\"Subgraphs:\");\n\t\tfor (const sg of d.subgraphs) {\n\t\t\tlines.push(`- ${sg}`);\n\t\t}\n\t}\n\tconst text = lines.join(\"\\n\");\n\toptions.logger?.(text);\n\treturn text;\n}\n\nfunction renderDescribeAsMermaid(d: GraphDescribeOutput, options: GraphDescribeOptions): string {\n\tconst direction = normalizeDiagramDirection(options.direction);\n\tconst paths = Object.keys(d.nodes).sort();\n\tconst ids = new Map<string, string>();\n\tfor (let i = 0; i < paths.length; i += 1) ids.set(paths[i]!, `n${i}`);\n\tconst lines: string[] = [`flowchart ${direction}`];\n\tfor (const path of paths) {\n\t\tconst id = ids.get(path)!;\n\t\tlines.push(` ${id}[\"${escapeMermaidLabel(path)}\"]`);\n\t}\n\tfor (const [from, to] of collectDiagramArrows(d)) {\n\t\tconst fromId = ids.get(from);\n\t\tconst toId = ids.get(to);\n\t\tif (!fromId || !toId) continue;\n\t\tlines.push(` ${fromId} --> ${toId}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction renderDescribeAsD2(d: GraphDescribeOutput, options: GraphDescribeOptions): string {\n\tconst direction = normalizeDiagramDirection(options.direction);\n\tconst paths = Object.keys(d.nodes).sort();\n\tconst ids = new Map<string, string>();\n\tfor (let i = 0; i < paths.length; i += 1) ids.set(paths[i]!, `n${i}`);\n\tconst lines: string[] = [`direction: ${d2DirectionFromGraphDirection(direction)}`];\n\tfor (const path of paths) {\n\t\tconst id = ids.get(path)!;\n\t\tlines.push(`${id}: \"${escapeD2Label(path)}\"`);\n\t}\n\tfor (const [from, to] of collectDiagramArrows(d)) {\n\t\tconst fromId = ids.get(from);\n\t\tconst toId = ids.get(to);\n\t\tif (!fromId || !toId) continue;\n\t\tlines.push(`${fromId} -> ${toId}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction escapeRegexLiteral(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction globToRegex(pattern: string): RegExp {\n\tlet re = \"^\";\n\tfor (let i = 0; i < pattern.length; i += 1) {\n\t\tconst ch = pattern[i]!;\n\t\tif (ch === \"*\") {\n\t\t\tre += \".*\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === \"?\") {\n\t\t\tre += \".\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === \"[\") {\n\t\t\tconst end = pattern.indexOf(\"]\", i + 1);\n\t\t\tif (end <= i + 1) {\n\t\t\t\tre += \"\\\\[\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet cls = pattern.slice(i + 1, end);\n\t\t\tif (cls.startsWith(\"!\")) cls = `^${cls.slice(1)}`;\n\t\t\tcls = cls.replace(/\\\\/g, \"\\\\\\\\\");\n\t\t\tre += `[${cls}]`;\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\t\tre += escapeRegexLiteral(ch);\n\t}\n\tre += \"$\";\n\treturn new RegExp(re);\n}\n\nconst OBSERVE_ANSI_THEME: Required<ObserveTheme> = {\n\tdata: \"\\u001b[32m\",\n\tdirty: \"\\u001b[33m\",\n\tresolved: \"\\u001b[36m\",\n\tinvalidate: \"\\u001b[93m\",\n\tpause: \"\\u001b[90m\",\n\tresume: \"\\u001b[96m\",\n\tcomplete: \"\\u001b[34m\",\n\terror: \"\\u001b[31m\",\n\tteardown: \"\\u001b[91m\",\n\tderived: \"\\u001b[35m\",\n\tpath: \"\\u001b[90m\",\n\treset: \"\\u001b[0m\",\n};\n\nconst OBSERVE_NO_COLOR_THEME: Required<ObserveTheme> = {\n\tdata: \"\",\n\tdirty: \"\",\n\tresolved: \"\",\n\tinvalidate: \"\",\n\tpause: \"\",\n\tresume: \"\",\n\tcomplete: \"\",\n\terror: \"\",\n\tteardown: \"\",\n\tderived: \"\",\n\tpath: \"\",\n\treset: \"\",\n};\n\nfunction describeData(value: unknown): string {\n\tif (typeof value === \"string\") return JSON.stringify(value);\n\tif (typeof value === \"number\" || typeof value === \"boolean\" || value == null)\n\t\treturn String(value);\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\n\nfunction resolveObserveTheme(theme: ObserveOptions[\"theme\"]): Required<ObserveTheme> {\n\tif (theme === \"none\") return OBSERVE_NO_COLOR_THEME;\n\tif (theme === \"ansi\" || theme == null) return OBSERVE_ANSI_THEME;\n\treturn {\n\t\tdata: theme.data ?? \"\",\n\t\tdirty: theme.dirty ?? \"\",\n\t\tresolved: theme.resolved ?? \"\",\n\t\tinvalidate: theme.invalidate ?? \"\",\n\t\tpause: theme.pause ?? \"\",\n\t\tresume: theme.resume ?? \"\",\n\t\tcomplete: theme.complete ?? \"\",\n\t\terror: theme.error ?? \"\",\n\t\tteardown: theme.teardown ?? \"\",\n\t\tderived: theme.derived ?? \"\",\n\t\tpath: theme.path ?? \"\",\n\t\treset: theme.reset ?? \"\",\n\t};\n}\n\n/** Resolve observe `detail` level into effective boolean flags. */\nfunction resolveObserveDetail(opts?: ObserveOptions): ObserveOptions {\n\tif (opts == null) return {};\n\tconst detail = opts.detail;\n\tif (detail === \"full\") {\n\t\treturn {\n\t\t\t...opts,\n\t\t\tstructured: opts.structured ?? true,\n\t\t\ttimeline: opts.timeline ?? true,\n\t\t\tcausal: opts.causal ?? true,\n\t\t\tderived: opts.derived ?? true,\n\t\t};\n\t}\n\tif (detail === \"minimal\") {\n\t\treturn { ...opts, structured: opts.structured ?? true };\n\t}\n\treturn opts;\n}\n\n/**\n * Option shapes that trigger structured-mode dispatch in {@link Graph.observe}.\n * Presence of any of these fields (truthy) → returns {@link ObserveResult};\n * otherwise `observe()` returns the raw-stream variants.\n */\nexport type StructuredTriggers = {\n\tstructured?: true;\n\ttimeline?: true;\n\tcausal?: true;\n\tderived?: true;\n\tformat?: \"pretty\" | \"json\";\n\tdetail?: \"minimal\" | \"full\";\n};\n\n/** {@link Graph.observe} on a single node or meta path — sink receives plain message batches. */\nexport type GraphObserveOne = {\n\tsubscribe(sink: NodeSink): () => void;\n\t/** Send messages upstream toward the observed node's sources (e.g. PAUSE/RESUME). */\n\tup(messages: Messages): void;\n};\n\n/**\n * {@link Graph.observe} on the whole graph — sink receives each batch with the qualified source path.\n * Subscription order follows code-point sort on paths (mounts-first walk, then sorted locals/meta).\n */\nexport type GraphObserveAll = {\n\tsubscribe(sink: (nodePath: string, messages: Messages) => void): () => void;\n\t/** Send messages upstream toward a specific observed node's sources (e.g. PAUSE/RESUME). */\n\tup(path: string, messages: Messages): void;\n};\n\n/**\n * Detail level for `observe()` progressive disclosure (Phase 3.3b).\n * - `\"minimal\"` — DATA events only, no timestamps, no causal info.\n * - `\"standard\"` — all message types (DATA, DIRTY, RESOLVED, INVALIDATE,\n * PAUSE, RESUME, COMPLETE, ERROR, TEARDOWN).\n * - `\"full\"` — standard + timeline + causal + derived.\n */\nexport type ObserveDetail = \"minimal\" | \"standard\" | \"full\";\n\n/** Options for structured observation modes on {@link Graph.observe}. */\nexport type ObserveOptions = {\n\tactor?: Actor;\n\t/** Return an {@link ObserveResult} accumulator instead of a raw stream. */\n\tstructured?: boolean;\n\t/** Include causal trace info (which dep triggered each recomputation). */\n\tcausal?: boolean;\n\t/** Include timestamps and batch context on each event. */\n\ttimeline?: boolean;\n\t/** Include per-evaluation dep snapshots for compute/derived nodes. */\n\tderived?: boolean;\n\t/**\n\t * Detail level (Phase 3.3b). Individual flags (`causal`, `timeline`, `derived`)\n\t * override. `\"full\"` implies all three plus structured.\n\t * `\"minimal\"` filters to DATA-only events.\n\t */\n\tdetail?: ObserveDetail;\n\n\t// ——— Format / logging (merged from spy) ———\n\n\t/**\n\t * When set, auto-enables structured mode and attaches a logger.\n\t * `\"pretty\"` renders colored one-line output; `\"json\"` emits one JSON object per event.\n\t */\n\tformat?: \"pretty\" | \"json\";\n\t/** Sink for rendered lines (`console.log` by default). Only used when `format` is set. */\n\tlogger?: (line: string, event: ObserveEvent) => void;\n\t/** Keep only these event types in formatted output. Only used when `format` is set. */\n\tincludeTypes?: ObserveEvent[\"type\"][];\n\t/** Exclude these event types from formatted output. Only used when `format` is set. */\n\texcludeTypes?: ObserveEvent[\"type\"][];\n\t/** Built-in color preset (`ansi` default) or explicit color tokens. Only used when `format` is set. */\n\ttheme?: ObserveThemeName | ObserveTheme;\n\t/**\n\t * Cap the `events` buffer. When set, the result uses a {@link RingBuffer}\n\t * under the hood: oldest events are dropped on overflow. Unbounded when\n\t * omitted (default).\n\t */\n\tmaxEvents?: number;\n};\n\n/** Accumulated observation result (structured mode). */\nexport type ObserveResult<T = unknown> = AsyncIterable<ObserveEvent> & {\n\t/** Latest DATA value by observed path. */\n\treadonly values: Record<string, T>;\n\t/** Number of DIRTY messages received. */\n\treadonly dirtyCount: number;\n\t/** Number of RESOLVED messages received. */\n\treadonly resolvedCount: number;\n\t/** Number of INVALIDATE messages received (tier 1 cache-clear). */\n\treadonly invalidateCount: number;\n\t/** Number of PAUSE messages received (tier 2 backpressure). */\n\treadonly pauseCount: number;\n\t/** Number of RESUME messages received (tier 2 backpressure). */\n\treadonly resumeCount: number;\n\t/** Number of TEARDOWN messages received (tier 5 permanent cleanup). */\n\treadonly teardownCount: number;\n\t/**\n\t * All events in order — ring-buffered when `options.maxEvents` is set,\n\t * unbounded otherwise. Always materialized as an `ObserveEvent[]`\n\t * snapshot on read.\n\t */\n\treadonly events: ObserveEvent[];\n\t/** True if any observed node sent COMPLETE without prior ERROR on that node. */\n\treadonly anyCompletedCleanly: boolean;\n\t/** True if any observed node sent ERROR. */\n\treadonly anyErrored: boolean;\n\t/** True if at least one COMPLETE received and no ERROR from any observed node. */\n\treadonly completedWithoutErrors: boolean;\n\t/**\n\t * Attach a live listener that fires for each event as it arrives.\n\t * Returns an unsubscribe fn. Independent of the `events` buffer.\n\t */\n\tonEvent(listener: (event: ObserveEvent) => void): () => void;\n\t/** Stop observing. */\n\tdispose(): void;\n\t/**\n\t * Resubscribe with higher detail (Phase 3.3b).\n\t * Disposes current observation, returns new `ObserveResult` with merged options.\n\t */\n\texpand(\n\t\textra: Partial<Pick<ObserveOptions, \"causal\" | \"timeline\" | \"derived\">> | ObserveDetail,\n\t): ObserveResult<T>;\n};\n\n/** Fields common to every {@link ObserveEvent} variant. */\nexport interface ObserveEventBase {\n\tpath?: string;\n\t/** Optional `timeline` context — wall-clock when `options.timeline === true`. */\n\ttimestamp_ns?: number;\n\tin_batch?: boolean;\n\t/** Monotonically increasing counter per subscribe-callback invocation. All events in one delivery share the same id. */\n\tbatch_id?: number;\n}\n\n/** Optional `causal` context present on `data`/`resolved`/`derived` events. */\nexport interface ObserveCausalContext {\n\ttrigger_dep_index?: number;\n\ttrigger_dep_name?: string;\n\t/**\n\t * V0 version of the triggering dep at observation time (§6.0b).\n\t * This is the dep's post-emission version (after its own `advanceVersion`),\n\t * not the pre-emission version that caused this node's recomputation.\n\t */\n\ttrigger_version?: { id: string; version: number };\n\t/**\n\t * One scalar per dep: the last value that arrived in the current wave,\n\t * or the pre-wave cached value for deps that didn't fire. Convenient\n\t * for single-value-wave tooling (the common case).\n\t */\n\tdep_values?: unknown[];\n\t/**\n\t * Full per-dep batches for the wave that fired the fn — `dep_batches[i]`\n\t * is the array of values dep `i` delivered this wave (`undefined` for\n\t * deps that didn't fire). Use this to distinguish a single-value wave\n\t * from a multi-value wave; `dep_values` compresses each batch to its\n\t * last element and hides that difference.\n\t */\n\tdep_batches?: ReadonlyArray<ReadonlyArray<unknown> | undefined>;\n}\n\n/** A single event in the structured observation log (discriminated on `type`). */\nexport type ObserveEvent =\n\t| (ObserveEventBase & ObserveCausalContext & { type: \"data\"; data: unknown })\n\t| (ObserveEventBase & { type: \"dirty\" })\n\t| (ObserveEventBase & ObserveCausalContext & { type: \"resolved\" })\n\t| (ObserveEventBase & { type: \"invalidate\" })\n\t| (ObserveEventBase & { type: \"pause\"; lockId: unknown })\n\t| (ObserveEventBase & { type: \"resume\"; lockId: unknown })\n\t| (ObserveEventBase & { type: \"complete\" })\n\t| (ObserveEventBase & { type: \"error\"; data: unknown })\n\t| (ObserveEventBase & { type: \"teardown\" })\n\t| (ObserveEventBase & ObserveCausalContext & { type: \"derived\"; dep_values: unknown[] });\n\n/** Built-in color preset names for observe `format` rendering. */\nexport type ObserveThemeName = \"none\" | \"ansi\";\n\n/** ANSI/style overrides for observe `format` event rendering. */\nexport type ObserveTheme = Partial<Record<ObserveEvent[\"type\"] | \"path\" | \"reset\", string>>;\n\n/**\n * Reject characters that would collide with internal serialization or path\n * grammar. Control chars (0x00–0x1F, 0x7F) break `describe()` key stability,\n * diagram rendering, and any tab-delimited log/trace format. Keep the test\n * tight so the error message points at the first offending code point.\n */\nfunction assertNoControlChars(name: string, graphName: string, label: string): void {\n\tfor (let i = 0; i < name.length; i++) {\n\t\tconst c = name.charCodeAt(i);\n\t\tif (c < 0x20 || c === 0x7f) {\n\t\t\tthrow new Error(\n\t\t\t\t`Graph \"${graphName}\": ${label} \"${name}\" must not contain control character (U+${c.toString(16).padStart(4, \"0\").toUpperCase()} at index ${i})`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validate a registerable local name (`add`, `mount`, `remove` inputs):\n * non-empty, no `::` separator, not the reserved `__meta__` segment, and no\n * control characters.\n */\nfunction assertRegisterableName(name: string, graphName: string, label: string): void {\n\tif (name === \"\") {\n\t\tthrow new Error(`Graph \"${graphName}\": ${label} name must be non-empty`);\n\t}\n\tif (name.includes(PATH_SEP)) {\n\t\tthrow new Error(\n\t\t\t`Graph \"${graphName}\": ${label} \"${name}\" must not contain '${PATH_SEP}' (path separator)`,\n\t\t);\n\t}\n\tif (name === GRAPH_META_SEGMENT) {\n\t\tthrow new Error(\n\t\t\t`Graph \"${graphName}\": ${label} name \"${GRAPH_META_SEGMENT}\" is reserved for meta companion paths`,\n\t\t);\n\t}\n\tassertNoControlChars(name, graphName, label);\n}\n\nfunction splitPath(path: string, graphName: string): string[] {\n\tif (path === \"\") {\n\t\tthrow new Error(`Graph \"${graphName}\": resolve path must be non-empty`);\n\t}\n\tconst segments = path.split(PATH_SEP);\n\tfor (const s of segments) {\n\t\tif (s === \"\") {\n\t\t\tthrow new Error(`Graph \"${graphName}\": resolve path has empty segment`);\n\t\t}\n\t}\n\treturn segments;\n}\n\n/**\n * Strip messages that are not marked `metaPassthrough` on the given config\n * (spec §2.3 Companion lifecycle). Built-ins: `INVALIDATE`, `COMPLETE`,\n * `ERROR`, `TEARDOWN` are registered `metaPassthrough: false` in\n * `registerBuiltins`. Custom types default to `true` (meta receives them).\n *\n * To target a meta node directly without the filter, call `meta.down(...)`.\n *\n * Returns empty array when nothing remains.\n */\nfunction filterMetaMessages(messages: Messages, config: GraphReFlyConfig): Messages {\n\t// Fast path: if every message is metaPassthrough, reuse the input array.\n\tlet anyFiltered = false;\n\tfor (const m of messages) {\n\t\tif (!config.isMetaPassthrough(m[0])) {\n\t\t\tanyFiltered = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!anyFiltered) return messages;\n\tconst kept = messages.filter((m) => config.isMetaPassthrough(m[0]));\n\treturn kept as unknown as Messages;\n}\n\n/**\n * TEARDOWN every node in a mounted graph tree (depth-first into mounts).\n * Errors from individual node teardowns are swallowed — a single bad handler\n * must not abort cleanup of the rest of the subtree.\n */\nfunction teardownMountedGraph(root: Graph): void {\n\tfor (const child of root._mounts.values()) {\n\t\tteardownMountedGraph(child);\n\t}\n\tfor (const n of root._nodes.values()) {\n\t\ttry {\n\t\t\tn.down([[TEARDOWN]] satisfies Messages, { internal: true });\n\t\t} catch {\n\t\t\t/* resilience: keep tearing down siblings */\n\t\t}\n\t}\n}\n\n/**\n * Named container for nodes and explicit edges (GRAPHREFLY-SPEC §3.1–§3.7).\n *\n * Qualified paths use `::` as the segment separator (for example `parent::child::node`).\n *\n * Edges are pure wires: `connect` only validates wiring — the target must already list the source in\n * its dependency array; no transforms run on the edge.\n *\n * @example\n * ```ts\n * import { Graph, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const g = new Graph(\"app\");\n * g.add(\"counter\", state(0));\n * ```\n *\n * @category graph\n */\nexport class Graph {\n\treadonly name: string;\n\treadonly opts: Readonly<GraphOptions>;\n\t/** Protocol config bound to this graph (defaults to `defaultConfig`). */\n\treadonly config: GraphReFlyConfig;\n\t/** @internal — exposed for {@link teardownMountedGraph} and cross-graph helpers. */\n\treadonly _nodes = new Map<string, Node>();\n\t/**\n\t * @internal Reverse lookup for duplicate-instance detection in\n\t * {@link Graph.add} — O(1) replacement for an O(n) scan of `_nodes`.\n\t * Weak so nodes can be GC'd after `remove()` even if a caller keeps the\n\t * map alive via some unusual pattern.\n\t */\n\tprivate readonly _nodeToName = new WeakMap<Node, string>();\n\t/** @internal — exposed for {@link teardownMountedGraph}. */\n\treadonly _mounts = new Map<string, Graph>();\n\t/**\n\t * @internal Parent graph if this instance is mounted. `undefined` when\n\t * this is the root or when the graph has been unmounted. Used for\n\t * reparenting rejection + O(depth) ancestor walks.\n\t */\n\t_parent: Graph | undefined = undefined;\n\tprivate readonly _storageDisposers = new Set<() => void>();\n\tprivate readonly _disposers = new Set<() => void>();\n\t/**\n\t * @internal Lazy `TopologyEvent` producer. Created on first `.topology`\n\t * access. Zero cost until something subscribes — producer fn only runs when\n\t * the first sink attaches, registering one handler into\n\t * {@link Graph._topologyEmitters}.\n\t */\n\tprivate _topology: Node<TopologyEvent> | undefined;\n\t/**\n\t * @internal Active emit handlers for the topology producer. Each entry is\n\t * the closure registered by the producer fn on activation; cleared on\n\t * deactivation. `_emitTopology` broadcasts through every entry (there is at\n\t * most one per activation cycle of the producer).\n\t */\n\tprivate readonly _topologyEmitters = new Set<(event: TopologyEvent) => void>();\n\n\t/**\n\t * @param name - Non-empty graph id (must not contain `::` and must not\n\t * equal the reserved meta segment `__meta__`).\n\t * @param opts - See {@link GraphOptions}. Stored frozen on the instance.\n\t */\n\tconstructor(name: string, opts?: GraphOptions) {\n\t\tif (name === \"\") {\n\t\t\tthrow new Error(\"Graph name must be non-empty\");\n\t\t}\n\t\tif (name.includes(PATH_SEP)) {\n\t\t\tthrow new Error(`Graph name must not contain '${PATH_SEP}' (got \"${name}\")`);\n\t\t}\n\t\tif (name === GRAPH_META_SEGMENT) {\n\t\t\tthrow new Error(`Graph name \"${GRAPH_META_SEGMENT}\" is reserved for meta companion paths`);\n\t\t}\n\t\tthis.name = name;\n\t\tthis.opts = Object.freeze({ ...(opts ?? {}) });\n\t\tthis.config = opts?.config ?? defaultConfig;\n\t\tthis._traceRing = new RingBuffer<TraceEntry>(opts?.traceCapacity ?? 1000);\n\t\tif (opts?.versioning != null) {\n\t\t\t// No nodes yet, but keep the API consistent — apply at construction\n\t\t\t// so opts.versioning is honored as a startup default via this helper.\n\t\t\tthis.setVersioning(opts.versioning);\n\t\t}\n\t}\n\n\t/**\n\t * Walk ancestors up through `_parent`. Returns the chain starting at this\n\t * instance, ending at the root (a graph with no parent). O(depth).\n\t *\n\t * @param includeSelf - Include `this` in the chain (default `true`).\n\t */\n\tancestors(includeSelf = true): Graph[] {\n\t\tconst out: Graph[] = [];\n\t\tlet p: Graph | undefined = includeSelf ? this : this._parent;\n\t\twhile (p != null) {\n\t\t\tout.push(p);\n\t\t\tp = p._parent;\n\t\t}\n\t\treturn out;\n\t}\n\n\t// ——————————————————————————————————————————————————————————————\n\t// Topology companion (structural-change event stream)\n\t// ——————————————————————————————————————————————————————————————\n\n\t/**\n\t * Reactive stream of structural changes to this graph's own registry\n\t * (add / mount / remove). Value mutations live on `observe()`; this\n\t * companion only fires when the topology shape changes.\n\t *\n\t * Lazy: the underlying node is created on first access and activates when\n\t * something subscribes. No emission replay — late subscribers do not\n\t * receive historical events and should snapshot via {@link Graph.describe}\n\t * before listening for incremental changes. Events that fire while the\n\t * producer has zero subscribers are dropped (no retention).\n\t *\n\t * Own-graph only: a parent's `topology` does NOT emit for structural\n\t * changes inside a mounted child. Transitive consumers subscribe to each\n\t * child's topology separately (recurse through `topology`'s own \"added\"\n\t * events with `nodeKind: \"mount\"` to discover new children).\n\t *\n\t * See {@link TopologyEvent} for payload shape.\n\t *\n\t * @category observability\n\t */\n\tget topology(): Node<TopologyEvent> {\n\t\tif (this._topology == null) {\n\t\t\tthis._topology = producer<TopologyEvent>(\n\t\t\t\t(actions) => {\n\t\t\t\t\tconst handler = (event: TopologyEvent): void => {\n\t\t\t\t\t\tactions.emit(event);\n\t\t\t\t\t};\n\t\t\t\t\tthis._topologyEmitters.add(handler);\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tthis._topologyEmitters.delete(handler);\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t{ name: `${this.name}_topology` },\n\t\t\t);\n\t\t}\n\t\treturn this._topology;\n\t}\n\n\t/**\n\t * @internal Fire a {@link TopologyEvent} to every active subscriber of\n\t * `this.topology`. No-op when the topology node has never been accessed or\n\t * currently has no sinks — zero cost for graphs nobody observes.\n\t */\n\tprivate _emitTopology(event: TopologyEvent): void {\n\t\tif (this._topology == null || this._topologyEmitters.size === 0) return;\n\t\tfor (const h of this._topologyEmitters) h(event);\n\t}\n\n\t// ——————————————————————————————————————————————————————————————\n\t// Node registry\n\t// ——————————————————————————————————————————————————————————————\n\n\t/**\n\t * Registers a node under a local name. Fails if the name is already used,\n\t * reserved by a mount, the same node instance is already registered, or\n\t * the node is torn down.\n\t *\n\t * Returns the registered node so callers can chain:\n\t * `const counter = g.add(\"counter\", state(0))`.\n\t *\n\t * @param name - Local key (no `::`).\n\t * @param node - Node instance to own.\n\t */\n\tadd<T extends Node>(name: string, node: T): T {\n\t\tassertRegisterableName(name, this.name, \"add\");\n\t\tif (this._mounts.has(name)) {\n\t\t\tthrow new Error(`Graph \"${this.name}\": name \"${name}\" is already a mount point`);\n\t\t}\n\t\tif (this._nodes.has(name)) {\n\t\t\tthrow new Error(`Graph \"${this.name}\": node \"${name}\" already exists`);\n\t\t}\n\t\tconst existingName = this._nodeToName.get(node);\n\t\tif (existingName !== undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`Graph \"${this.name}\": node instance already registered as \"${existingName}\"`,\n\t\t\t);\n\t\t}\n\t\tthis._nodes.set(name, node);\n\t\tthis._nodeToName.set(node, name);\n\t\t// Edges are derived on demand from node `_deps` (see `edges()`) — no\n\t\t// stored registry to keep in sync. See Unit 7 of the graph review.\n\t\tthis._emitTopology({ kind: \"added\", name, nodeKind: \"node\" });\n\t\treturn node;\n\t}\n\n\t/**\n\t * Bulk-apply a minimum versioning level to every currently-registered node\n\t * in this graph (roadmap §6.0). `_applyVersioning` is monotonic — nodes\n\t * already at a higher level are untouched. The method refuses to run\n\t * mid-wave; invoke at setup time before any external subscribers attach.\n\t *\n\t * **Not** a default-for-future-adds mechanism — that's what\n\t * `config.defaultVersioning` is for. Nodes added after this call do NOT\n\t * automatically inherit `level`; register new nodes with their own\n\t * `opts.versioning` or set `config.defaultVersioning` before construction.\n\t *\n\t * **Scope:** local only. Does not propagate to mounted subgraphs.\n\t *\n\t * @param level - `0` for V0, `1` for V1, or `undefined` to no-op.\n\t */\n\tsetVersioning(level: VersioningLevel | undefined): void {\n\t\tif (level == null) return;\n\t\tfor (const node of this._nodes.values()) {\n\t\t\tif (node instanceof NodeImpl) {\n\t\t\t\tnode._applyVersioning(level);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Unregisters a node or unmounts a subgraph and sends `[[TEARDOWN]]` to the\n\t * removed node or recursively through the mounted subtree (§3.2).\n\t *\n\t * @param name - Local mount or node name.\n\t * @returns Audit record of what was removed: `{kind, nodes, mounts}`.\n\t * `kind: \"node\"` → `nodes: [name]`, `mounts: []`. `kind: \"mount\"` →\n\t * `nodes` lists every primary node torn down across the subtree (sorted\n\t * qualified paths relative to the unmounted subgraph) and `mounts` lists\n\t * the mounted subgraphs in depth-first order including `name` itself.\n\t */\n\tremove(name: string): GraphRemoveAudit {\n\t\tassertRegisterableName(name, this.name, \"remove\");\n\n\t\t// Case 1: unmount a subgraph\n\t\tconst child = this._mounts.get(name);\n\t\tif (child) {\n\t\t\tconst audit: GraphRemoveAudit = { kind: \"mount\", nodes: [], mounts: [] };\n\t\t\tconst targets: [string, Node][] = [];\n\t\t\tchild._collectObserveTargets(\"\", targets);\n\t\t\tfor (const [p, n] of targets) {\n\t\t\t\t// Only primary nodes (not meta companions) — meta cascades via\n\t\t\t\t// the primary's TEARDOWN.\n\t\t\t\tif (!p.includes(`${PATH_SEP}${GRAPH_META_SEGMENT}${PATH_SEP}`)) {\n\t\t\t\t\taudit.nodes.push(p);\n\t\t\t\t}\n\t\t\t\tvoid n;\n\t\t\t}\n\t\t\taudit.nodes.sort();\n\t\t\taudit.mounts.push(name);\n\t\t\taudit.mounts.push(...child._collectSubgraphs(`${name}${PATH_SEP}`));\n\t\t\tthis._mounts.delete(name);\n\t\t\tchild._parent = undefined;\n\t\t\tteardownMountedGraph(child);\n\t\t\tthis._emitTopology({ kind: \"removed\", name, nodeKind: \"mount\", audit });\n\t\t\treturn audit;\n\t\t}\n\n\t\t// Case 2: remove a local node\n\t\tconst node = this._nodes.get(name);\n\t\tif (!node) {\n\t\t\tthrow new Error(`Graph \"${this.name}\": unknown node or mount \"${name}\"`);\n\t\t}\n\t\tthis._nodes.delete(name);\n\t\tthis._nodeToName.delete(node);\n\t\tnode.down([[TEARDOWN]] satisfies Messages, { internal: true });\n\t\tconst audit: GraphRemoveAudit = { kind: \"node\", nodes: [name], mounts: [] };\n\t\tthis._emitTopology({ kind: \"removed\", name, nodeKind: \"node\", audit });\n\t\treturn audit;\n\t}\n\n\t/**\n\t * Bulk remove — invokes {@link Graph.remove} for every local name matching\n\t * `filter`. Audit records merge into a single result. Mounted subgraphs\n\t * are included via `filter` receiving the mount name; internal subtree\n\t * entries are not walked directly (use describe + scan for tree-level\n\t * queries).\n\t *\n\t * @param filter - Predicate or glob. Glob strings support `*` within a\n\t * segment and `**` across segments (same grammar as `restore({only})`).\n\t * @returns Combined audit of all nodes + mounts removed.\n\t */\n\tremoveAll(filter: ((name: string) => boolean) | string): GraphRemoveAudit {\n\t\tconst match =\n\t\t\ttypeof filter === \"function\"\n\t\t\t\t? filter\n\t\t\t\t: (() => {\n\t\t\t\t\t\tconst re = globToRegex(filter);\n\t\t\t\t\t\treturn (n: string) => re.test(n);\n\t\t\t\t\t})();\n\t\tconst audit: GraphRemoveAudit = { kind: \"mount\", nodes: [], mounts: [] };\n\t\t// Snapshot names first — remove mutates the maps.\n\t\tconst localNames = [...this._nodes.keys(), ...this._mounts.keys()].filter((n) => match(n));\n\t\tfor (const name of localNames) {\n\t\t\tconst sub = this.remove(name);\n\t\t\taudit.nodes.push(...sub.nodes);\n\t\t\taudit.mounts.push(...sub.mounts);\n\t\t}\n\t\taudit.nodes.sort();\n\t\taudit.mounts.sort();\n\t\treturn audit;\n\t}\n\n\t/**\n\t * Iterable over locally-registered `[localName, Node]` pairs (sorted).\n\t * Does not recurse into mounts.\n\t */\n\t[Symbol.iterator](): IterableIterator<[string, Node]> {\n\t\tconst sorted = [...this._nodes.keys()].sort();\n\t\tconst nodes = this._nodes;\n\t\tlet i = 0;\n\t\treturn {\n\t\t\t[Symbol.iterator]() {\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tnext(): IteratorResult<[string, Node]> {\n\t\t\t\tif (i >= sorted.length) return { value: undefined, done: true };\n\t\t\t\tconst name = sorted[i++];\n\t\t\t\treturn { value: [name, nodes.get(name)!], done: false };\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Returns a node by local name or `::` qualified path.\n\t * Local names are looked up directly; paths with `::` delegate to {@link resolve}.\n\t *\n\t * @param name - Local name or qualified path.\n\t */\n\tnode(name: string): Node {\n\t\tif (name === \"\") {\n\t\t\tthrow new Error(`Graph \"${this.name}\": node name must be non-empty`);\n\t\t}\n\t\tif (name.includes(PATH_SEP)) {\n\t\t\treturn this.resolve(name);\n\t\t}\n\t\tconst n = this._nodes.get(name);\n\t\tif (!n) {\n\t\t\tthrow new Error(`Graph \"${this.name}\": unknown node \"${name}\"`);\n\t\t}\n\t\treturn n;\n\t}\n\n\t/**\n\t * Reads `graph.node(name).get()` — accepts `::` qualified paths (§3.2).\n\t *\n\t * @param name - Local name or qualified path.\n\t * @returns Cached value or `undefined`.\n\t */\n\tget(name: string): unknown {\n\t\treturn this.node(name).cache;\n\t}\n\n\t/**\n\t * Shorthand for `graph.node(name).down([[DATA, value]], { actor })` — accepts `::` qualified paths (§3.2).\n\t *\n\t * @param name - Local name or qualified path.\n\t * @param value - Next `DATA` payload.\n\t * @param options - Optional `actor` and `internal` guard bypass.\n\t */\n\tset(name: string, value: unknown, options?: GraphActorOptions): void {\n\t\tconst internal = options?.internal === true;\n\t\tthis.node(name).down([[DATA, value]] satisfies Messages, {\n\t\t\tactor: options?.actor,\n\t\t\tinternal,\n\t\t\tdelivery: \"write\",\n\t\t});\n\t}\n\n\t/**\n\t * Atomic multi-node DATA write. Wraps every {@link Graph.set} call in a\n\t * single `batch(...)` so downstream dependents see one coalesced wave\n\t * instead of N cascading ones.\n\t *\n\t * @param entries - `{name → value}` map or `[name, value]` pairs.\n\t * @param options - Passed to each underlying `set` call (same `actor` + `internal` semantics).\n\t */\n\tsetAll(\n\t\tentries: Record<string, unknown> | Iterable<readonly [string, unknown]>,\n\t\toptions?: GraphActorOptions,\n\t): void {\n\t\tconst iter: Iterable<readonly [string, unknown]> =\n\t\t\tSymbol.iterator in entries\n\t\t\t\t? (entries as Iterable<readonly [string, unknown]>)\n\t\t\t\t: Object.entries(entries as Record<string, unknown>);\n\t\tbatch(() => {\n\t\t\tfor (const [name, value] of iter) this.set(name, value, options);\n\t\t});\n\t}\n\n\t/**\n\t * Emit a single `[[INVALIDATE]]` (tier 1) on a node. Thin wrapper over\n\t * `node.down([[INVALIDATE]], …)` matching the {@link Graph.set} ergonomics.\n\t */\n\tinvalidate(name: string, options?: GraphActorOptions): void {\n\t\tconst internal = options?.internal === true;\n\t\tthis.node(name).down([[INVALIDATE]] satisfies Messages, {\n\t\t\tactor: options?.actor,\n\t\t\tinternal,\n\t\t\tdelivery: \"write\",\n\t\t});\n\t}\n\n\t/**\n\t * Emit a single `[[ERROR, err]]` (tier 4) on a node.\n\t */\n\terror(name: string, err: unknown, options?: GraphActorOptions): void {\n\t\tconst internal = options?.internal === true;\n\t\tthis.node(name).down([[ERROR, err]] satisfies Messages, {\n\t\t\tactor: options?.actor,\n\t\t\tinternal,\n\t\t\tdelivery: \"write\",\n\t\t});\n\t}\n\n\t/**\n\t * Emit a single `[[COMPLETE]]` (tier 4) on a node, declaring the stream\n\t * cleanly finished. Distinct from {@link Graph.remove} (which emits\n\t * TEARDOWN and unregisters the node).\n\t */\n\tcomplete(name: string, options?: GraphActorOptions): void {\n\t\tconst internal = options?.internal === true;\n\t\tthis.node(name).down([[COMPLETE]] satisfies Messages, {\n\t\t\tactor: options?.actor,\n\t\t\tinternal,\n\t\t\tdelivery: \"write\",\n\t\t});\n\t}\n\n\t// ——————————————————————————————————————————————————————————————\n\t// Edges (derived on-demand from node `_deps`)\n\t// ——————————————————————————————————————————————————————————————\n\n\t/**\n\t * Returns the full edge list for this graph tree, derived on demand from\n\t * each registered node's `_deps` (no stored registry). Local-only\n\t * (non-recursive) by default to match the historical `edges()` surface;\n\t * pass `{recursive: true}` to include mounted subgraphs with qualified\n\t * paths relative to this graph.\n\t *\n\t * Use {@link Graph.describe} for full-tree snapshots with edges already\n\t * qualified and paired with node metadata.\n\t */\n\tedges(opts?: { recursive?: boolean }): ReadonlyArray<[string, string]> {\n\t\tconst recursive = opts?.recursive === true;\n\t\tconst nodeToLocal = new Map<Node, string>();\n\t\tif (!recursive) {\n\t\t\tfor (const [localName, n] of this._nodes) nodeToLocal.set(n, localName);\n\t\t\tconst result: [string, string][] = [];\n\t\t\tfor (const [localName, n] of this._nodes) {\n\t\t\t\tif (!(n instanceof NodeImpl)) continue;\n\t\t\t\tfor (const dep of n._deps) {\n\t\t\t\t\tconst from = nodeToLocal.get(dep.node);\n\t\t\t\t\tif (from != null) result.push([from, localName]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tresult.sort((a, b) =>\n\t\t\t\ta[0] < b[0] ? -1 : a[0] > b[0] ? 1 : a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0,\n\t\t\t);\n\t\t\treturn result;\n\t\t}\n\t\tconst targets: [string, Node][] = [];\n\t\tthis._collectObserveTargets(\"\", targets);\n\t\tconst nodeToPath = new Map<Node, string>();\n\t\tfor (const [p, n] of targets) nodeToPath.set(n, p);\n\t\tconst result: [string, string][] = [];\n\t\tfor (const [path, n] of targets) {\n\t\t\tif (!(n instanceof NodeImpl)) continue;\n\t\t\tfor (const dep of n._deps) {\n\t\t\t\tconst from = nodeToPath.get(dep.node);\n\t\t\t\tif (from != null) result.push([from, path]);\n\t\t\t}\n\t\t}\n\t\tresult.sort((a, b) =>\n\t\t\ta[0] < b[0] ? -1 : a[0] > b[0] ? 1 : a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0,\n\t\t);\n\t\treturn result;\n\t}\n\n\t// ——————————————————————————————————————————————————————————————\n\t// Composition\n\t// ——————————————————————————————————————————————————————————————\n\n\t/**\n\t * Embed a child graph at a local mount name (§3.4). Child nodes are reachable via\n\t * {@link Graph.resolve} using `::` delimited paths (§3.5). Lifecycle\n\t * {@link Graph.signal} visits mounted subgraphs recursively.\n\t *\n\t * Rejects: same name as existing node or mount, self-mount, mount cycles,\n\t * and the same child graph instance mounted twice on one parent.\n\t *\n\t * @param name - Local mount point.\n\t * @param child - Nested `Graph` instance.\n\t * @returns The mounted `child`, for chaining.\n\t */\n\tmount<G extends Graph>(name: string, child: G): G {\n\t\tassertRegisterableName(name, this.name, \"mount\");\n\t\tif (this._nodes.has(name)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Graph \"${this.name}\": cannot mount at \"${name}\" — node with that name exists`,\n\t\t\t);\n\t\t}\n\t\tif (this._mounts.has(name)) {\n\t\t\tthrow new Error(`Graph \"${this.name}\": mount \"${name}\" already exists`);\n\t\t}\n\t\tif ((child as Graph) === this) {\n\t\t\tthrow new Error(`Graph \"${this.name}\": cannot mount a graph into itself`);\n\t\t}\n\t\t// Reject reparenting (Unit 6 B): same child instance may only be\n\t\t// mounted once across the entire tree. Cheap O(1) check via the\n\t\t// back-pointer (replaces both the \"mounted twice on this parent\"\n\t\t// loop AND the O(G) cycle DFS).\n\t\tif (child._parent != null) {\n\t\t\tthrow new Error(\n\t\t\t\t`Graph \"${this.name}\": this child graph is already mounted on \"${child._parent.name}\"`,\n\t\t\t);\n\t\t}\n\t\t// Cycle rejection — walk UP from `this` to detect if we are already in\n\t\t// `child`'s descendant tree. O(depth), independent of tree size.\n\t\tfor (let p: Graph | undefined = this; p != null; p = p._parent) {\n\t\t\tif (p === (child as Graph)) {\n\t\t\t\tthrow new Error(`Graph \"${this.name}\": mount(\"${name}\", …) would create a mount cycle`);\n\t\t\t}\n\t\t}\n\t\tthis._mounts.set(name, child);\n\t\tchild._parent = this;\n\t\tthis._emitTopology({ kind: \"added\", name, nodeKind: \"mount\" });\n\t\treturn child;\n\t}\n\n\t/**\n\t * Look up a node by qualified path (§3.5). Segments are separated by `::`.\n\t *\n\t * If the first segment equals this graph's {@link Graph.name}, it is stripped\n\t * (so `root.resolve(\"app::a\")` works when `root.name === \"app\"`). The strip\n\t * is applied **recursively** when descending into mounted children, so\n\t * `child.resolve(\"child::x\")` also works when `child.name === \"child\"`.\n\t *\n\t * @param path - Qualified `::` path or local name.\n\t * @returns The resolved `Node`.\n\t */\n\tresolve(path: string): Node {\n\t\tconst segments = splitPath(path, this.name);\n\t\treturn this._resolveFromSegments(segments);\n\t}\n\n\t/**\n\t * Non-throwing {@link Graph.resolve}. Returns `undefined` instead of\n\t * throwing when the path does not resolve to a node.\n\t */\n\ttryResolve(path: string): Node | undefined {\n\t\ttry {\n\t\t\treturn this.resolve(path);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate _resolveFromSegments(segments: readonly string[]): Node {\n\t\t// Recursive self-name strip: if the first segment equals this graph's\n\t\t// own name, peel it off. Applied at every recursion level so nested\n\t\t// resolution of `child::x` inside `child` works uniformly.\n\t\tlet seg = segments;\n\t\tif (seg[0] === this.name) {\n\t\t\tseg = seg.slice(1);\n\t\t\tif (seg.length === 0) {\n\t\t\t\tthrow new Error(`Graph \"${this.name}\": resolve path ends at graph name only`);\n\t\t\t}\n\t\t}\n\t\tconst head = seg[0] as string;\n\t\tconst rest = seg.slice(1);\n\n\t\tif (rest.length === 0) {\n\t\t\tconst n = this._nodes.get(head);\n\t\t\tif (n) return n;\n\t\t\tif (this._mounts.has(head)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Graph \"${this.name}\": path ends at subgraph \"${head}\" — not a node (GRAPHREFLY-SPEC §3.5)`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new Error(`Graph \"${this.name}\": unknown name \"${head}\"`);\n\t\t}\n\n\t\tconst localN = this._nodes.get(head);\n\t\tif (localN && rest.length > 0 && rest[0] === GRAPH_META_SEGMENT) {\n\t\t\treturn this._resolveMetaChainFromNode(localN, rest, seg.join(PATH_SEP));\n\t\t}\n\n\t\tconst child = this._mounts.get(head);\n\t\tif (!child) {\n\t\t\tif (this._nodes.has(head)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Graph \"${this.name}\": \"${head}\" is a node; trailing path \"${rest.join(PATH_SEP)}\" is invalid`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new Error(`Graph \"${this.name}\": unknown mount or node \"${head}\"`);\n\t\t}\n\n\t\treturn child.resolve(rest.join(PATH_SEP));\n\t}\n\n\t/**\n\t * Resolve `::__meta__::key` segments from a registered primary node (possibly chained).\n\t */\n\tprivate _resolveMetaChainFromNode(n: Node, parts: readonly string[], fullPath: string): Node {\n\t\tlet current = n;\n\t\tlet i = 0;\n\t\tconst p = [...parts];\n\t\twhile (i < p.length) {\n\t\t\tif (p[i] !== GRAPH_META_SEGMENT) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Graph \"${this.name}\": expected ${GRAPH_META_SEGMENT} segment in meta path \"${fullPath}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (i + 1 >= p.length) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Graph \"${this.name}\": meta path requires a key after ${GRAPH_META_SEGMENT} in \"${fullPath}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst key = p[i + 1] as string;\n\t\t\tconst next = current.meta[key];\n\t\t\tif (!next) {\n\t\t\t\tthrow new Error(`Graph \"${this.name}\": unknown meta \"${key}\" in path \"${fullPath}\"`);\n\t\t\t}\n\t\t\tcurrent = next;\n\t\t\ti += 2;\n\t\t}\n\t\treturn current;\n\t}\n\n\t/**\n\t * Deliver a message batch to every registered node in this graph and, recursively,\n\t * in mounted child graphs (§3.7). Recurses into mounts first, then delivers to\n\t * local nodes (sorted by name). Each {@link Node} receives at most one delivery\n\t * per call (deduped by reference).\n\t *\n\t * **Primary-vs-meta filter asymmetry (intentional):** primary nodes receive the\n\t * unfiltered `messages` batch — that's the canonical data-plane flow. Companion\n\t * `meta` nodes receive a filtered subset keyed by the per-type `metaPassthrough`\n\t * flag on {@link GraphReFlyConfig}. Built-in defaults: PAUSE / RESUME / DATA /\n\t * RESOLVED pass through to meta; INVALIDATE / COMPLETE / ERROR / TEARDOWN do\n\t * not.\n\t *\n\t * **Where lifecycle terminals reach meta:**\n\t * - **TEARDOWN** — primary's `_emit` cascades to meta children directly (see\n\t * `core/node.ts` \"Meta TEARDOWN fan-out\" block) so meta is torn down with\n\t * its primary regardless of the signal-level filter.\n\t * - **COMPLETE / ERROR / INVALIDATE** — scoped to primaries on the broadcast\n\t * path. Meta companions are an attribution side-channel, not a lifecycle\n\t * participant; address meta directly via `meta.down(...)` if you need to\n\t * forward these. Audit confirmed 2026-04-17: no current meta consumer\n\t * relies on broadcast COMPLETE/ERROR/INVALIDATE delivery.\n\t *\n\t * @param messages - Batch to deliver to every registered node (and mounts, recursively).\n\t * @param options - Optional `actor` / `internal` for transport.\n\t */\n\tsignal(messages: Messages, options?: GraphActorOptions): void {\n\t\t// Reject tier ≥ 3 (DATA / RESOLVED / COMPLETE / ERROR / TEARDOWN when\n\t\t// called externally — destroy() routes through signal with\n\t\t// `{internal: true}` which bypasses this check). Broadcasting per-flow\n\t\t// values to every node in the tree is almost always a mistake.\n\t\tif (options?.internal !== true) {\n\t\t\tfor (const m of messages) {\n\t\t\t\tconst tier = this.config.messageTier(m[0]);\n\t\t\t\t// Tier 3 (DATA / RESOLVED) is per-flow state — broadcasting it\n\t\t\t\t// to every node overwrites unrelated caches. Tier 4/5 stays\n\t\t\t\t// allowed: ERROR/COMPLETE/TEARDOWN have legitimate broadcast\n\t\t\t\t// use (graceful shutdown, error cascade).\n\t\t\t\tif (tier === 3) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Graph \"${this.name}\": Graph.signal() rejects tier-3 messages (DATA / RESOLVED). ` +\n\t\t\t\t\t\t\t`Broadcast is for control-plane tiers (START / DIRTY / INVALIDATE / PAUSE / RESUME / COMPLETE / ERROR / TEARDOWN). ` +\n\t\t\t\t\t\t\t`For per-node value writes, use Graph.set or graph.node(name).down(...).`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst errors: unknown[] = [];\n\t\tthis._signalDeliver(messages, options ?? {}, new Set(), errors);\n\t\t// Surface the first collected error so callers see failures without\n\t\t// aborting the rest of the broadcast. Guard denials are re-thrown\n\t\t// immediately in _signalDeliver (deliberate access-control rejections).\n\t\tif (errors.length > 0) throw errors[0];\n\t}\n\n\tprivate _signalDeliver(\n\t\tmessages: Messages,\n\t\topts: GraphActorOptions,\n\t\tvis: Set<Node>,\n\t\terrors: unknown[],\n\t): void {\n\t\tfor (const sub of this._mounts.values()) {\n\t\t\tsub._signalDeliver(messages, opts, vis, errors);\n\t\t}\n\t\tconst internal = opts.internal === true;\n\t\tconst downOpts: NodeTransportOptions = internal\n\t\t\t? { internal: true }\n\t\t\t: { actor: opts.actor, delivery: \"signal\" };\n\t\tconst metaMessages = filterMetaMessages(messages, this.config);\n\t\tfor (const localName of [...this._nodes.keys()].sort()) {\n\t\t\tconst n = this._nodes.get(localName)!;\n\t\t\tif (vis.has(n)) continue;\n\t\t\tvis.add(n);\n\t\t\ttry {\n\t\t\t\tn.down(messages, downOpts);\n\t\t\t} catch (err) {\n\t\t\t\t// Guard denials bubble — they're deliberate rejections, not\n\t\t\t\t// resilience failures. Other errors collect so one bad handler\n\t\t\t\t// doesn't abort the rest of the broadcast.\n\t\t\t\tif (err instanceof GuardDenied) throw err;\n\t\t\t\terrors.push(err);\n\t\t\t}\n\t\t\tif (metaMessages.length === 0) continue;\n\t\t\tthis._signalMetaSubtree(n, metaMessages, vis, downOpts, errors);\n\t\t}\n\t}\n\n\tprivate _signalMetaSubtree(\n\t\troot: Node,\n\t\tmessages: Messages,\n\t\tvis: Set<Node>,\n\t\tdownOpts: NodeTransportOptions,\n\t\terrors: unknown[],\n\t): void {\n\t\tfor (const mk of Object.keys(root.meta).sort()) {\n\t\t\tconst mnode = root.meta[mk];\n\t\t\tif (vis.has(mnode)) continue;\n\t\t\tvis.add(mnode);\n\t\t\ttry {\n\t\t\t\tmnode.down(messages, downOpts);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof GuardDenied) throw err;\n\t\t\t\terrors.push(err);\n\t\t\t}\n\t\t\tthis._signalMetaSubtree(mnode, messages, vis, downOpts, errors);\n\t\t}\n\t}\n\n\t/**\n\t * Static structure snapshot: qualified node keys, edges, mount names (GRAPHREFLY-SPEC §3.6, Appendix B).\n\t *\n\t * `format` controls the return type:\n\t * - omitted or `\"spec\"` → {@link GraphDescribeOutput} object.\n\t * - `\"json\"` / `\"pretty\"` / `\"mermaid\"` / `\"d2\"` → rendered string.\n\t *\n\t * @param options - Optional `actor` for guard-scoped visibility, `filter` for\n\t * selective output, or `format` to render.\n\t *\n\t * @example\n\t * ```ts\n\t * graph.describe() // full snapshot object\n\t * graph.describe({ filter: { status: \"errored\" } }) // filtered object\n\t * graph.describe({ format: \"pretty\" }) // human-readable text\n\t * graph.describe({ format: \"mermaid\" }) // Mermaid flowchart\n\t * graph.describe({ format: \"d2\", direction: \"TD\" }) // D2 top-down\n\t * ```\n\t */\n\tdescribe(\n\t\toptions: GraphDescribeOptions & { format: \"json\" | \"pretty\" | \"mermaid\" | \"d2\" },\n\t): string;\n\tdescribe(options?: GraphDescribeOptions): GraphDescribeOutput;\n\tdescribe(options?: GraphDescribeOptions): GraphDescribeOutput | string {\n\t\tconst actor = options?.actor;\n\t\tconst filter = options?.filter;\n\t\tconst includeFields = resolveDescribeFields(options?.detail, options?.fields);\n\t\tconst isSpec = options?.format === \"spec\";\n\t\t// For spec format, force minimal fields (type + deps only, no status/value)\n\t\tconst effectiveFields = isSpec ? resolveDescribeFields(\"minimal\") : includeFields;\n\n\t\tconst targets: [string, Node][] = [];\n\t\tthis._collectObserveTargets(\"\", targets);\n\t\tconst nodeToPath = new Map<Node, string>();\n\t\tfor (const [p, n] of targets) {\n\t\t\tnodeToPath.set(n, p);\n\t\t}\n\t\tconst nodes: Record<string, DescribeNodeOutput> = {};\n\t\tfor (const [p, n] of targets) {\n\t\t\tif (actor != null && !n.allowsObserve(actor)) continue;\n\t\t\tconst raw = describeNode(n, effectiveFields);\n\t\t\tconst deps =\n\t\t\t\tn instanceof NodeImpl\n\t\t\t\t\t? n._deps.map((d) => nodeToPath.get(d.node) ?? d.node.name ?? \"\")\n\t\t\t\t\t: [];\n\t\t\tconst { name: _name, ...rest } = raw;\n\t\t\tconst entry: DescribeNodeOutput = { ...rest, deps };\n\t\t\t// Unit 14 A: attach reason annotation from `trace(path, reason)`\n\t\t\t// when one exists. Skipped for the `\"spec\"` format (input-schema\n\t\t\t// use case — annotations don't round-trip through GraphSpec).\n\t\t\tif (!isSpec) {\n\t\t\t\tconst reason = this._annotations.get(p);\n\t\t\t\tif (reason != null) entry.reason = reason;\n\t\t\t}\n\t\t\tif (filter != null) {\n\t\t\t\tif (typeof filter === \"function\") {\n\t\t\t\t\tconst fn = filter as\n\t\t\t\t\t\t| ((nodePath: string, node: DescribeNodeOutput) => boolean)\n\t\t\t\t\t\t| ((node: DescribeNodeOutput) => boolean);\n\t\t\t\t\tconst pass =\n\t\t\t\t\t\tfn.length >= 2\n\t\t\t\t\t\t\t? (fn as (nodePath: string, node: DescribeNodeOutput) => boolean)(p, entry)\n\t\t\t\t\t\t\t: (fn as (node: DescribeNodeOutput) => boolean)(entry);\n\t\t\t\t\tif (!pass) continue;\n\t\t\t\t} else {\n\t\t\t\t\tlet match = true;\n\t\t\t\t\tfor (const [fk, fv] of Object.entries(filter)) {\n\t\t\t\t\t\tconst normalizedKey =\n\t\t\t\t\t\t\tfk === \"deps_includes\" ? \"depsIncludes\" : fk === \"meta_has\" ? \"metaHas\" : fk;\n\t\t\t\t\t\tif (normalizedKey === \"depsIncludes\") {\n\t\t\t\t\t\t\tif (!entry.deps.includes(String(fv))) {\n\t\t\t\t\t\t\t\tmatch = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (normalizedKey === \"metaHas\") {\n\t\t\t\t\t\t\tif (!Object.hasOwn(entry.meta ?? {}, String(fv))) {\n\t\t\t\t\t\t\t\tmatch = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((entry as Record<string, unknown>)[normalizedKey] !== fv) {\n\t\t\t\t\t\t\tmatch = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!match) continue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnodes[p] = entry;\n\t\t}\n\t\tconst nodeKeys = new Set(Object.keys(nodes));\n\t\t// Edges are derived from node `_deps` via `edges({recursive: true})`\n\t\t// (sorted, fully qualified relative to this graph).\n\t\tlet edges: { from: string; to: string }[] = this.edges({ recursive: true }).map(\n\t\t\t([from, to]) => ({ from, to }),\n\t\t);\n\t\tif (actor != null || filter != null) {\n\t\t\tedges = edges.filter((e) => nodeKeys.has(e.from) && nodeKeys.has(e.to));\n\t\t}\n\t\tconst allSubgraphs = this._collectSubgraphs(\"\");\n\t\tconst subgraphs =\n\t\t\tactor != null || filter != null\n\t\t\t\t? allSubgraphs.filter((sg) => {\n\t\t\t\t\t\tconst prefix = `${sg}${PATH_SEP}`;\n\t\t\t\t\t\treturn [...nodeKeys].some((k) => k === sg || k.startsWith(prefix));\n\t\t\t\t\t})\n\t\t\t\t: allSubgraphs;\n\n\t\t// Capture graph ref and base options for expand()\n\t\tconst graph = this;\n\t\tconst baseOpts = options;\n\n\t\tconst struct: GraphDescribeOutput = {\n\t\t\tname: this.name,\n\t\t\tnodes,\n\t\t\tedges,\n\t\t\tsubgraphs,\n\t\t\texpand(detailOrFields: DescribeDetail | DescribeField[]): GraphDescribeOutput {\n\t\t\t\tconst merged: GraphDescribeOptions = { ...baseOpts, format: undefined };\n\t\t\t\tif (Array.isArray(detailOrFields)) {\n\t\t\t\t\tmerged.fields = detailOrFields;\n\t\t\t\t\tmerged.detail = undefined;\n\t\t\t\t} else {\n\t\t\t\t\tmerged.detail = detailOrFields;\n\t\t\t\t\tmerged.fields = undefined;\n\t\t\t\t}\n\t\t\t\treturn graph.describe(merged);\n\t\t\t},\n\t\t};\n\n\t\t// Text-format dispatch. `\"spec\"` and undefined return the struct as-is.\n\t\tconst opts = options ?? {};\n\t\tconst fmt = opts.format;\n\t\tif (fmt === \"json\") return renderDescribeAsJson(struct, opts);\n\t\tif (fmt === \"pretty\") return renderDescribeAsPretty(struct, opts);\n\t\tif (fmt === \"mermaid\") return renderDescribeAsMermaid(struct, opts);\n\t\tif (fmt === \"d2\") return renderDescribeAsD2(struct, opts);\n\t\treturn struct;\n\t}\n\n\tprivate _collectSubgraphs(prefix: string): string[] {\n\t\tconst out: string[] = [];\n\t\tfor (const m of [...this._mounts.keys()].sort()) {\n\t\t\tconst q = prefix === \"\" ? m : `${prefix}${m}`;\n\t\t\tout.push(q);\n\t\t\tout.push(...this._mounts.get(m)!._collectSubgraphs(`${q}${PATH_SEP}`));\n\t\t}\n\t\treturn out;\n\t}\n\n\t/**\n\t * Snapshot-based resource profile: per-node stats, orphan effect detection,\n\t * memory hotspots. Zero runtime overhead — walks nodes on demand.\n\t *\n\t * @param opts - Optional `topN` for hotspot limit (default 10).\n\t * @returns Aggregate profile with per-node details, hotspots, and orphan effects.\n\t */\n\tresourceProfile(opts?: GraphProfileOptions): GraphProfileResult {\n\t\treturn graphProfile(this, opts);\n\t}\n\n\t/**\n\t * Reachability query rooted at `from`. Instance convenience — wraps\n\t * `reachable(this.describe(), from, direction, opts)`. See\n\t * {@link reachable} for semantics.\n\t */\n\treachable(\n\t\tfrom: string,\n\t\tdirection: ReachableDirection,\n\t\topts: ReachableOptions & { withDetail: true },\n\t): ReachableResult;\n\treachable(from: string, direction: ReachableDirection, opts?: ReachableOptions): string[];\n\treachable(\n\t\tfrom: string,\n\t\tdirection: ReachableDirection,\n\t\topts: ReachableOptions = {},\n\t): string[] | ReachableResult {\n\t\tif (opts.withDetail === true) {\n\t\t\treturn reachable(this.describe(), from, direction, {\n\t\t\t\t...opts,\n\t\t\t\twithDetail: true,\n\t\t\t});\n\t\t}\n\t\treturn reachable(this.describe(), from, direction, opts);\n\t}\n\n\t/**\n\t * Causal walkback: shortest dep-chain from `from` to `to`, enriched with\n\t * each node's value, status, last-mutation actor, and reasoning annotation\n\t * from {@link Graph.trace}. Wraps {@link explainPath} (roadmap §9.2).\n\t *\n\t * @param from - Upstream node (the cause).\n\t * @param to - Downstream node (the effect).\n\t * @param opts - Optional `maxDepth` and `findCycle`. When `findCycle:true`\n\t * and `from === to`, returns the shortest cycle through other nodes\n\t * (useful for diagnosing feedback loops, COMPOSITION-GUIDE §7).\n\t * Annotations and lastMutations are collected automatically from the\n\t * live graph.\n\t */\n\texplain(\n\t\tfrom: string,\n\t\tto: string,\n\t\topts?: { maxDepth?: number; findCycle?: boolean },\n\t): CausalChain {\n\t\t// `detail: \"full\"` includes `value`, `status`, `lastMutation`, `v`, etc.\n\t\t// — everything `explainPath` enriches each step with.\n\t\tconst described = this.describe({ detail: \"full\" });\n\t\tconst annotations = new Map<string, string>(this._annotations);\n\t\tconst lastMutations = new Map<string, Readonly<{ actor: Actor; timestamp_ns: number }>>();\n\t\tfor (const [path, n] of Object.entries(described.nodes)) {\n\t\t\tif (n.lastMutation != null) lastMutations.set(path, n.lastMutation);\n\t\t}\n\t\treturn explainPath(described, from, to, {\n\t\t\t...(opts?.maxDepth != null ? { maxDepth: opts.maxDepth } : {}),\n\t\t\t...(opts?.findCycle === true ? { findCycle: true as const } : {}),\n\t\t\tannotations,\n\t\t\tlastMutations,\n\t\t});\n\t}\n\n\t/**\n\t * @internal Collect all qualified paths in this graph tree matching a\n\t * glob pattern. Used by scoped autoCheckpoint subscription.\n\t */\n\tprivate _pathsMatching(glob: string): string[] {\n\t\tconst re = globToRegex(glob);\n\t\tconst targets: [string, Node][] = [];\n\t\tthis._collectObserveTargets(\"\", targets);\n\t\treturn targets.map(([p]) => p).filter((p) => re.test(p));\n\t}\n\n\tprivate _collectObserveTargets(prefix: string, out: [string, Node][]): void {\n\t\tfor (const m of [...this._mounts.keys()].sort()) {\n\t\t\tconst p2 = prefix === \"\" ? m : `${prefix}${PATH_SEP}${m}`;\n\t\t\tthis._mounts.get(m)!._collectObserveTargets(p2, out);\n\t\t}\n\t\tfor (const loc of [...this._nodes.keys()].sort()) {\n\t\t\tconst n = this._nodes.get(loc)!;\n\t\t\tconst p = prefix === \"\" ? loc : `${prefix}${PATH_SEP}${loc}`;\n\t\t\tout.push([p, n]);\n\t\t\tthis._appendMetaObserveTargets(p, n, out);\n\t\t}\n\t}\n\n\tprivate _appendMetaObserveTargets(basePath: string, n: Node, out: [string, Node][]): void {\n\t\tfor (const mk of Object.keys(n.meta).sort()) {\n\t\t\tconst m = n.meta[mk];\n\t\t\tconst mp = `${basePath}${PATH_SEP}${GRAPH_META_SEGMENT}${PATH_SEP}${mk}`;\n\t\t\tout.push([mp, m]);\n\t\t\tthis._appendMetaObserveTargets(mp, m, out);\n\t\t}\n\t}\n\n\t/**\n\t * Live message stream from one node (or meta path), or from the whole graph (§3.6).\n\t *\n\t * Two modes dispatched on first argument:\n\t * - `observe(path, options?)` — one node. Returns {@link GraphObserveOne}\n\t * (raw stream), or {@link ObserveResult} when `options` requests structured\n\t * accumulation (`structured`, `timeline`, `causal`, `derived`, `format`,\n\t * `detail: \"minimal\"|\"full\"`).\n\t * - `observe(options?)` — all nodes. Returns {@link GraphObserveAll} (raw),\n\t * or {@link ObserveResult} under the same structured trigger conditions.\n\t *\n\t * Structured mode subscribes in sorted path order (code-point). Inspector\n\t * extras (`causal`/`derived`) require `graph.config.inspectorEnabled`;\n\t * when disabled, those fields silently drop and the rest still works.\n\t *\n\t * `ObserveResult` is also an `AsyncIterable<ObserveEvent>` — use\n\t * `for await (const ev of result)` for pull-based consumption.\n\t */\n\tobserve(path: string, options?: ObserveOptions & StructuredTriggers): ObserveResult;\n\tobserve(path: string, options?: ObserveOptions): GraphObserveOne;\n\tobserve(options: ObserveOptions & StructuredTriggers): ObserveResult;\n\tobserve(options?: ObserveOptions): GraphObserveAll;\n\tobserve(\n\t\tpathOrOpts?: string | ObserveOptions,\n\t\toptions?: ObserveOptions,\n\t): GraphObserveOne | GraphObserveAll | ObserveResult {\n\t\tconst isPath = typeof pathOrOpts === \"string\";\n\t\tconst rawOpts = isPath ? options : (pathOrOpts as ObserveOptions | undefined);\n\t\tconst resolved = resolveObserveDetail(rawOpts);\n\t\tconst wantsStructured =\n\t\t\tresolved.structured === true ||\n\t\t\tresolved.timeline === true ||\n\t\t\tresolved.causal === true ||\n\t\t\tresolved.derived === true ||\n\t\t\tresolved.detail === \"minimal\" ||\n\t\t\tresolved.detail === \"full\" ||\n\t\t\tresolved.format != null;\n\t\tconst actor = resolved.actor;\n\n\t\tif (isPath) {\n\t\t\tconst path = pathOrOpts as string;\n\t\t\tconst target = this.resolve(path);\n\t\t\tif (actor != null && !target.allowsObserve(actor)) {\n\t\t\t\tthrow new GuardDenied({ actor, action: \"observe\", nodeName: path });\n\t\t\t}\n\t\t\tif (wantsStructured) return this._buildStructuredObserver([[path, target]], resolved, \"one\");\n\t\t\treturn {\n\t\t\t\tsubscribe(sink: NodeSink) {\n\t\t\t\t\treturn target.subscribe(sink);\n\t\t\t\t},\n\t\t\t\tup(messages: Messages) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttarget.up?.(messages);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tif (err instanceof GuardDenied) return;\n\t\t\t\t\t\tthrow err;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst collected: [string, Node][] = [];\n\t\tthis._collectObserveTargets(\"\", collected);\n\t\tcollected.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n\t\tconst picked =\n\t\t\tactor == null ? collected : collected.filter(([, nd]) => nd.allowsObserve(actor));\n\t\tif (wantsStructured) return this._buildStructuredObserver(picked, resolved, \"all\");\n\t\treturn {\n\t\t\tsubscribe: (sink: (nodePath: string, messages: Messages) => void) => {\n\t\t\t\tconst unsubs = picked.map(([p, nd]) =>\n\t\t\t\t\tnd.subscribe((msgs) => {\n\t\t\t\t\t\tsink(p, msgs);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn () => {\n\t\t\t\t\tfor (const u of unsubs) u();\n\t\t\t\t};\n\t\t\t},\n\t\t\tup: (upPath: string, messages: Messages) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst nd = this.resolve(upPath);\n\t\t\t\t\tnd.up?.(messages);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof GuardDenied) return;\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\t/** Dispatch helper — builds a unified observer + its expand closure. */\n\tprivate _buildStructuredObserver<T>(\n\t\ttargets: ReadonlyArray<[string, Node]>,\n\t\toptions: ObserveOptions,\n\t\tmode: \"one\" | \"all\",\n\t): ObserveResult<T> {\n\t\tconst firstPath = mode === \"one\" ? targets[0]?.[0] : undefined;\n\t\tconst expand = (merged: ObserveOptions): ObserveResult<T> => {\n\t\t\tif (mode === \"one\" && firstPath != null) {\n\t\t\t\tconst target = this.resolve(firstPath);\n\t\t\t\treturn this._buildStructuredObserver([[firstPath, target]], merged, \"one\");\n\t\t\t}\n\t\t\tconst collected: [string, Node][] = [];\n\t\t\tthis._collectObserveTargets(\"\", collected);\n\t\t\tcollected.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n\t\t\tconst actor = merged.actor;\n\t\t\tconst picked =\n\t\t\t\tactor == null ? collected : collected.filter(([, nd]) => nd.allowsObserve(actor));\n\t\t\treturn this._buildStructuredObserver(picked, merged, \"all\");\n\t\t};\n\t\treturn this._createObserveResult<T>(targets, options, expand);\n\t}\n\n\t/**\n\t * Unified observer builder — replaces the four ex-creators\n\t * (`_createObserveResult` / `...ForAll` / `_createFallback…`). Accepts a\n\t * list of `[path, node]` targets (single-element for one-node observe,\n\t * N-element for all-nodes). Inspector hooks attach per-target when\n\t * `causal`/`derived` requested AND `config.inspectorEnabled`; otherwise\n\t * those fields gracefully drop.\n\t *\n\t * Events flow through a `recordEvent()` helper so the format logger,\n\t * ring-buffer, and async-iterable hooks all share one push path.\n\t */\n\tprivate _createObserveResult<T>(\n\t\ttargets: ReadonlyArray<[string, Node]>,\n\t\toptions: ObserveOptions,\n\t\texpand: (merged: ObserveOptions) => ObserveResult<T>,\n\t): ObserveResult<T> {\n\t\tconst timeline = options.timeline === true;\n\t\tconst causal = options.causal === true;\n\t\tconst derived = options.derived === true;\n\t\tconst minimal = options.detail === \"minimal\";\n\t\tconst inspectorOn = this.config.inspectorEnabled;\n\t\tconst wantInspector = (causal || derived) && inspectorOn;\n\n\t\t// Event buffer: unbounded array, or RingBuffer when maxEvents capped.\n\t\tconst maxEvents = options.maxEvents;\n\t\tconst ring =\n\t\t\tmaxEvents != null && maxEvents > 0 ? new RingBuffer<ObserveEvent>(maxEvents) : null;\n\t\tconst events: ObserveEvent[] = [];\n\n\t\t// Listener set — format logger, async iterable, and user `onEvent` hooks.\n\t\tconst listeners = new Set<(event: ObserveEvent) => void>();\n\n\t\tconst values: Record<string, T> = {};\n\t\tconst nodeErrored = new Set<string>();\n\t\tlet dirtyCount = 0;\n\t\tlet resolvedCount = 0;\n\t\tlet invalidateCount = 0;\n\t\tlet pauseCount = 0;\n\t\tlet resumeCount = 0;\n\t\tlet teardownCount = 0;\n\t\tlet anyCompletedCleanly = false;\n\t\tlet anyErrored = false;\n\t\tlet batchSeq = 0;\n\n\t\t// Per-target causal context (keyed by target index).\n\t\tconst lastTriggerDepIndex = new Map<Node, number>();\n\t\tconst lastRunDepValues = new Map<Node, readonly unknown[]>();\n\t\tconst lastRunDepBatches = new Map<Node, ReadonlyArray<ReadonlyArray<unknown> | undefined>>();\n\n\t\tconst recordEvent = (event: ObserveEvent): void => {\n\t\t\tif (ring) ring.push(event);\n\t\t\telse events.push(event);\n\t\t\tfor (const listener of listeners) listener(event);\n\t\t};\n\n\t\tconst baseMeta = (): Partial<ObserveEventBase> =>\n\t\t\ttimeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching(), batch_id: batchSeq } : {};\n\n\t\tconst attachInspector = (target: Node, path: string): (() => void) | undefined => {\n\t\t\tif (!wantInspector || !(target instanceof NodeImpl)) return undefined;\n\t\t\treturn target._setInspectorHook((ev) => {\n\t\t\t\tif (ev.kind === \"dep_message\") {\n\t\t\t\t\tlastTriggerDepIndex.set(target, ev.depIndex);\n\t\t\t\t} else if (ev.kind === \"run\") {\n\t\t\t\t\tconst effective = ev.batchData.map((b, i) =>\n\t\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ev.prevData[i],\n\t\t\t\t\t);\n\t\t\t\t\tlastRunDepValues.set(target, effective);\n\t\t\t\t\t// Snapshot the full per-dep batches so multi-value waves stay\n\t\t\t\t\t// visible to observers. `ev.batchData` references run-local\n\t\t\t\t\t// arrays, so clone the outer array (inner arrays are\n\t\t\t\t\t// effectively immutable from the observer's POV).\n\t\t\t\t\tconst batches: ReadonlyArray<ReadonlyArray<unknown> | undefined> = ev.batchData.map(\n\t\t\t\t\t\t(b) => (b != null ? [...b] : undefined),\n\t\t\t\t\t);\n\t\t\t\t\tlastRunDepBatches.set(target, batches);\n\t\t\t\t\tif (derived) {\n\t\t\t\t\t\trecordEvent({\n\t\t\t\t\t\t\ttype: \"derived\",\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\tdep_values: effective,\n\t\t\t\t\t\t\tdep_batches: batches,\n\t\t\t\t\t\t\t...baseMeta(),\n\t\t\t\t\t\t} as ObserveEvent);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\tconst buildCausal = (target: Node): ObserveCausalContext => {\n\t\t\tconst idx = lastTriggerDepIndex.get(target);\n\t\t\tconst depValues = lastRunDepValues.get(target);\n\t\t\tif (!causal || depValues == null) return {};\n\t\t\tconst triggerDep =\n\t\t\t\tidx != null && idx >= 0 && target instanceof NodeImpl ? target._deps[idx] : undefined;\n\t\t\tconst triggerNode = triggerDep?.node;\n\t\t\tconst tv = triggerNode?.v;\n\t\t\tconst depBatches = lastRunDepBatches.get(target);\n\t\t\treturn {\n\t\t\t\ttrigger_dep_index: idx,\n\t\t\t\ttrigger_dep_name: triggerNode?.name,\n\t\t\t\t...(tv != null ? { trigger_version: { id: tv.id, version: tv.version } } : {}),\n\t\t\t\tdep_values: [...depValues],\n\t\t\t\t...(depBatches != null ? { dep_batches: depBatches } : {}),\n\t\t\t};\n\t\t};\n\n\t\tconst inspectorDetaches: Array<() => void> = [];\n\t\tconst unsubs: Array<() => void> = [];\n\t\tfor (const [path, target] of targets) {\n\t\t\tconst detach = attachInspector(target, path);\n\t\t\tif (detach) inspectorDetaches.push(detach);\n\t\t\tunsubs.push(\n\t\t\t\ttarget.subscribe((msgs) => {\n\t\t\t\t\tbatchSeq++;\n\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\tconst t = m[0];\n\t\t\t\t\t\tconst base = baseMeta();\n\t\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\t\tvalues[path] = m[1] as T;\n\t\t\t\t\t\t\trecordEvent({\n\t\t\t\t\t\t\t\ttype: \"data\",\n\t\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\t\tdata: m[1],\n\t\t\t\t\t\t\t\t...base,\n\t\t\t\t\t\t\t\t...buildCausal(target),\n\t\t\t\t\t\t\t} as ObserveEvent);\n\t\t\t\t\t\t} else if (minimal) {\n\t\t\t\t\t\t\tif (t === DIRTY) dirtyCount++;\n\t\t\t\t\t\t\telse if (t === RESOLVED) resolvedCount++;\n\t\t\t\t\t\t\telse if (t === INVALIDATE) invalidateCount++;\n\t\t\t\t\t\t\telse if (t === PAUSE) pauseCount++;\n\t\t\t\t\t\t\telse if (t === RESUME) resumeCount++;\n\t\t\t\t\t\t\telse if (t === TEARDOWN) teardownCount++;\n\t\t\t\t\t\t\telse if (t === COMPLETE && !nodeErrored.has(path)) anyCompletedCleanly = true;\n\t\t\t\t\t\t\telse if (t === ERROR) {\n\t\t\t\t\t\t\t\tanyErrored = true;\n\t\t\t\t\t\t\t\tnodeErrored.add(path);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (t === DIRTY) {\n\t\t\t\t\t\t\tdirtyCount++;\n\t\t\t\t\t\t\trecordEvent({ type: \"dirty\", path, ...base } as ObserveEvent);\n\t\t\t\t\t\t} else if (t === RESOLVED) {\n\t\t\t\t\t\t\tresolvedCount++;\n\t\t\t\t\t\t\trecordEvent({\n\t\t\t\t\t\t\t\ttype: \"resolved\",\n\t\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\t\t...base,\n\t\t\t\t\t\t\t\t...buildCausal(target),\n\t\t\t\t\t\t\t} as ObserveEvent);\n\t\t\t\t\t\t} else if (t === INVALIDATE) {\n\t\t\t\t\t\t\tinvalidateCount++;\n\t\t\t\t\t\t\trecordEvent({ type: \"invalidate\", path, ...base } as ObserveEvent);\n\t\t\t\t\t\t} else if (t === PAUSE) {\n\t\t\t\t\t\t\tpauseCount++;\n\t\t\t\t\t\t\trecordEvent({ type: \"pause\", path, lockId: m[1], ...base } as ObserveEvent);\n\t\t\t\t\t\t} else if (t === RESUME) {\n\t\t\t\t\t\t\tresumeCount++;\n\t\t\t\t\t\t\trecordEvent({ type: \"resume\", path, lockId: m[1], ...base } as ObserveEvent);\n\t\t\t\t\t\t} else if (t === COMPLETE) {\n\t\t\t\t\t\t\tif (!nodeErrored.has(path)) anyCompletedCleanly = true;\n\t\t\t\t\t\t\trecordEvent({ type: \"complete\", path, ...base } as ObserveEvent);\n\t\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\t\tanyErrored = true;\n\t\t\t\t\t\t\tnodeErrored.add(path);\n\t\t\t\t\t\t\trecordEvent({\n\t\t\t\t\t\t\t\ttype: \"error\",\n\t\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\t\tdata: m[1],\n\t\t\t\t\t\t\t\t...base,\n\t\t\t\t\t\t\t} as ObserveEvent);\n\t\t\t\t\t\t} else if (t === TEARDOWN) {\n\t\t\t\t\t\t\tteardownCount++;\n\t\t\t\t\t\t\trecordEvent({ type: \"teardown\", path, ...base } as ObserveEvent);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tlet disposed = false;\n\t\tconst dispose = (): void => {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\t\t\tfor (const u of unsubs) u();\n\t\t\tfor (const d of inspectorDetaches) d();\n\t\t\tfor (const resolve of asyncResolvers) resolve({ value: undefined, done: true });\n\t\t\tasyncResolvers.length = 0;\n\t\t};\n\n\t\t// AsyncIterator plumbing: queue events until a pull arrives, or wake\n\t\t// a pending pull when a new event lands.\n\t\tconst asyncQueue: ObserveEvent[] = [];\n\t\tconst asyncResolvers: Array<(r: IteratorResult<ObserveEvent>) => void> = [];\n\t\tlisteners.add((ev) => {\n\t\t\tconst resolve = asyncResolvers.shift();\n\t\t\tif (resolve) resolve({ value: ev, done: false });\n\t\t\telse asyncQueue.push(ev);\n\t\t});\n\n\t\tconst result: ObserveResult<T> = {\n\t\t\tget values() {\n\t\t\t\treturn values;\n\t\t\t},\n\t\t\tget dirtyCount() {\n\t\t\t\treturn dirtyCount;\n\t\t\t},\n\t\t\tget resolvedCount() {\n\t\t\t\treturn resolvedCount;\n\t\t\t},\n\t\t\tget invalidateCount() {\n\t\t\t\treturn invalidateCount;\n\t\t\t},\n\t\t\tget pauseCount() {\n\t\t\t\treturn pauseCount;\n\t\t\t},\n\t\t\tget resumeCount() {\n\t\t\t\treturn resumeCount;\n\t\t\t},\n\t\t\tget teardownCount() {\n\t\t\t\treturn teardownCount;\n\t\t\t},\n\t\t\tget events() {\n\t\t\t\treturn ring ? ring.toArray() : [...events];\n\t\t\t},\n\t\t\tget anyCompletedCleanly() {\n\t\t\t\treturn anyCompletedCleanly;\n\t\t\t},\n\t\t\tget anyErrored() {\n\t\t\t\treturn anyErrored;\n\t\t\t},\n\t\t\tget completedWithoutErrors() {\n\t\t\t\treturn anyCompletedCleanly && !anyErrored;\n\t\t\t},\n\t\t\tonEvent(listener) {\n\t\t\t\tlisteners.add(listener);\n\t\t\t\treturn () => listeners.delete(listener);\n\t\t\t},\n\t\t\tdispose,\n\t\t\texpand(extra) {\n\t\t\t\tdispose();\n\t\t\t\tconst merged: ObserveOptions = { ...options };\n\t\t\t\tif (typeof extra === \"string\") {\n\t\t\t\t\tmerged.detail = extra;\n\t\t\t\t} else {\n\t\t\t\t\tObject.assign(merged, extra);\n\t\t\t\t}\n\t\t\t\treturn expand(resolveObserveDetail(merged));\n\t\t\t},\n\t\t\t[Symbol.asyncIterator](): AsyncIterator<ObserveEvent> {\n\t\t\t\treturn {\n\t\t\t\t\tnext(): Promise<IteratorResult<ObserveEvent>> {\n\t\t\t\t\t\tif (asyncQueue.length > 0) {\n\t\t\t\t\t\t\treturn Promise.resolve({ value: asyncQueue.shift()!, done: false });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (disposed) return Promise.resolve({ value: undefined, done: true });\n\t\t\t\t\t\treturn new Promise((resolve) => asyncResolvers.push(resolve));\n\t\t\t\t\t},\n\t\t\t\t\treturn(): Promise<IteratorResult<ObserveEvent>> {\n\t\t\t\t\t\tdispose();\n\t\t\t\t\t\treturn Promise.resolve({ value: undefined, done: true });\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t};\n\n\t\t// Format logger: subscribes to event stream, renders via theme/format.\n\t\tif (options.format != null) this._attachFormatLogger(result, options);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Attach format-rendering logger to an ObserveResult by subscribing to its\n\t * event stream (no monkey-patching). Renders each event per `format` and\n\t * `theme`, filtered by `includeTypes` / `excludeTypes`.\n\t */\n\tprivate _attachFormatLogger(result: ObserveResult, options: ObserveOptions): void {\n\t\tconst format = options.format;\n\t\tif (format == null) return;\n\t\tconst logger = options.logger ?? ((line: string) => console.log(line));\n\t\t// Compile include/exclude predicates once.\n\t\tconst include = options.includeTypes ? new Set(options.includeTypes) : null;\n\t\tconst exclude = options.excludeTypes ? new Set(options.excludeTypes) : null;\n\t\tconst shouldLog =\n\t\t\tinclude == null && exclude == null\n\t\t\t\t? () => true\n\t\t\t\t: (type: ObserveEvent[\"type\"]): boolean =>\n\t\t\t\t\t\t(include == null || include.has(type)) && (exclude == null || !exclude.has(type));\n\t\tconst theme = resolveObserveTheme(options.theme);\n\n\t\tconst renderEvent = (event: ObserveEvent): string => {\n\t\t\tif (format === \"json\") {\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.stringify(event);\n\t\t\t\t} catch {\n\t\t\t\t\treturn JSON.stringify({\n\t\t\t\t\t\ttype: event.type,\n\t\t\t\t\t\tpath: event.path,\n\t\t\t\t\t\tdata: \"[unserializable]\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst color = theme[event.type] ?? \"\";\n\t\t\tconst pathPart = event.path ? `${theme.path}${event.path}${theme.reset} ` : \"\";\n\t\t\tconst isDataBearing = event.type === \"data\" || event.type === \"error\";\n\t\t\tconst isLockBearing = event.type === \"pause\" || event.type === \"resume\";\n\t\t\tconst dataPart = isDataBearing\n\t\t\t\t? ` ${describeData((event as { data: unknown }).data)}`\n\t\t\t\t: isLockBearing\n\t\t\t\t\t? ` ${describeData((event as { lockId: unknown }).lockId)}`\n\t\t\t\t\t: \"\";\n\t\t\tconst causal =\n\t\t\t\tevent.type === \"data\" || event.type === \"resolved\" || event.type === \"derived\"\n\t\t\t\t\t? (event as ObserveCausalContext)\n\t\t\t\t\t: undefined;\n\t\t\tconst triggerPart =\n\t\t\t\tcausal?.trigger_dep_name != null\n\t\t\t\t\t? ` <- ${causal.trigger_dep_name}`\n\t\t\t\t\t: causal?.trigger_dep_index != null\n\t\t\t\t\t\t? ` <- #${causal.trigger_dep_index}`\n\t\t\t\t\t\t: \"\";\n\t\t\tconst batchPart = event.in_batch ? \" [batch]\" : \"\";\n\t\t\treturn `${pathPart}${color}${event.type.toUpperCase()}${theme.reset}${dataPart}${triggerPart}${batchPart}`;\n\t\t};\n\n\t\tresult.onEvent((event) => {\n\t\t\tif (shouldLog(event.type)) logger(renderEvent(event), event);\n\t\t});\n\t}\n\n\t// `dumpGraph` is folded into `describe({format: \"pretty\" | \"json\"})` (Unit 12).\n\t// `toMermaid` / `toD2` are folded into `describe({format: \"mermaid\" | \"d2\"})` (Unit 20).\n\n\t// ——————————————————————————————————————————————————————————————\n\t// Lifecycle & persistence (§3.7–§3.8)\n\t// ——————————————————————————————————————————————————————————————\n\n\t/**\n\t * Register a cleanup function to be called on {@link Graph.destroy}.\n\t *\n\t * Factories use this to attach teardown logic for internal nodes, keepalive\n\t * subscriptions, or other resources that are not registered on the graph and\n\t * would otherwise leak on repeated create/destroy cycles.\n\t *\n\t * Returns a removal function — call it to unregister the disposer early.\n\t */\n\taddDisposer(fn: () => void): () => void {\n\t\tthis._disposers.add(fn);\n\t\treturn () => {\n\t\t\tthis._disposers.delete(fn);\n\t\t};\n\t}\n\n\t/**\n\t * Drains disposers (registered via {@link addDisposer}), then sends `[[TEARDOWN]]` to all\n\t * nodes and clears registries on this graph and every mounted subgraph (§3.7).\n\t * The instance is left empty and may be reused with {@link Graph.add}.\n\t */\n\tdestroy(): void {\n\t\t// Drain disposers (keepalive unsubs etc.) BEFORE TEARDOWN so that\n\t\t// internal effect nodes are disconnected before the cascade fires.\n\t\t// Drain iteratively so disposers registered mid-drain also run; cap\n\t\t// iterations to guard against a disposer that re-registers itself.\n\t\tdrainDisposers(this._disposers, this.name);\n\t\t// TEARDOWN is tier 5 — below `attachStorage`'s `tier < 5` gate, so no\n\t\t// final checkpoint fires; storage disposers unsubscribe after TEARDOWN\n\t\t// has propagated through the subscription pipeline.\n\t\tthis.signal([[TEARDOWN]] satisfies Messages, { internal: true });\n\t\tdrainDisposers(this._storageDisposers, this.name);\n\t\tfor (const child of [...this._mounts.values()]) {\n\t\t\tchild._parent = undefined;\n\t\t\tchild._destroyClearOnly();\n\t\t}\n\t\tthis._mounts.clear();\n\t\tthis._nodes.clear();\n\t\tthis._parent = undefined;\n\t}\n\n\t/** Clear structure after parent already signaled TEARDOWN through this subtree. */\n\tprivate _destroyClearOnly(): void {\n\t\tfor (const child of [...this._mounts.values()]) {\n\t\t\tchild._parent = undefined;\n\t\t\tchild._destroyClearOnly();\n\t\t}\n\t\tthis._mounts.clear();\n\t\tthis._nodes.clear();\n\t\tthis._parent = undefined;\n\t}\n\n\t/**\n\t * Serializes structure and current values to JSON-shaped data (§3.8). Same\n\t * information as {@link Graph.describe} plus a `version` field for format\n\t * evolution.\n\t *\n\t * The overload path supports three outputs:\n\t * - no arg → `GraphPersistSnapshot` (plain JS object).\n\t * - `{format: \"json-string\"}` → deterministic JSON `string`\n\t * (key-sorted; safe for hashing or file write).\n\t * - `{format: \"bytes\", codec: name}` → `Uint8Array` wrapped in the v1\n\t * envelope from {@link encodeEnvelope}. The codec must be registered\n\t * on this graph's {@link GraphReFlyConfig} via `config.registerCodec`.\n\t * Paired with {@link Graph.decode} for auto-dispatch on the read side.\n\t */\n\tsnapshot(): GraphPersistSnapshot;\n\tsnapshot(opts: { format: \"json-string\" }): string;\n\tsnapshot(opts: { format: \"bytes\"; codec: string }): Uint8Array;\n\tsnapshot(opts?: {\n\t\tformat?: \"json-string\" | \"bytes\";\n\t\tcodec?: string;\n\t}): GraphPersistSnapshot | string | Uint8Array {\n\t\tconst { expand: _, ...d } = this.describe({ detail: \"full\" });\n\t\t// Explicit key sorting for deterministic output — don't rely on\n\t\t// describe() iteration order (audit batch-3, §3.8).\n\t\t// Strip non-restorable fields (runtime attribution) so snapshot → restore → snapshot\n\t\t// is idempotent. Use describe({ detail: \"full\" }) for audit snapshots instead.\n\t\tconst sortedNodes: Record<string, DescribeNodeOutput> = {};\n\t\tfor (const key of Object.keys(d.nodes).sort()) {\n\t\t\tconst { lastMutation: _lm, guard: _g, ...node } = d.nodes[key]!;\n\t\t\tsortedNodes[key] = node;\n\t\t}\n\t\tconst sortedSubgraphs = [...d.subgraphs].sort();\n\t\tconst snap: GraphPersistSnapshot = {\n\t\t\t...d,\n\t\t\tversion: 1,\n\t\t\tnodes: sortedNodes,\n\t\t\tsubgraphs: sortedSubgraphs,\n\t\t};\n\t\tif (opts?.format == null) return snap;\n\t\tif (opts.format === \"json-string\") return JSON.stringify(snap);\n\t\tif (opts.format === \"bytes\") {\n\t\t\tif (opts.codec == null) {\n\t\t\t\tthrow new Error(\"snapshot({format: 'bytes'}) requires a `codec` name\");\n\t\t\t}\n\t\t\tconst codec = this.config.lookupCodec<GraphCodec>(opts.codec);\n\t\t\tif (codec == null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`snapshot: codec \"${opts.codec}\" is not registered on this graph's config. ` +\n\t\t\t\t\t\t`Call config.registerCodec(...) before creating nodes.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn encodeEnvelope(codec, codec.encode(snap));\n\t\t}\n\t\tthrow new Error(`snapshot: unknown format \"${String(opts.format)}\"`);\n\t}\n\n\t/**\n\t * Auto-dispatch a byte buffer produced by {@link Graph.snapshot} with\n\t * `{format: \"bytes\", codec: name}`. Reads the v1 envelope, resolves the\n\t * named codec on `config` (defaults to `defaultConfig`), and returns the\n\t * decoded snapshot. Combine with {@link Graph.fromSnapshot} to rehydrate\n\t * a full graph topology from bytes.\n\t *\n\t * @throws If the envelope is malformed or the named codec isn't\n\t * registered on the target config.\n\t */\n\tstatic decode(bytes: Uint8Array, opts?: { config?: GraphReFlyConfig }): GraphPersistSnapshot {\n\t\tconst cfg = opts?.config ?? defaultConfig;\n\t\tconst { codec, codecVersion, payload } = decodeEnvelope(bytes, cfg);\n\t\treturn codec.decode(payload, codecVersion);\n\t}\n\n\t/**\n\t * Apply persisted values onto an existing graph whose topology matches the snapshot\n\t * (§3.8). Only {@link DescribeNodeOutput.type} `state` entries with a `value` field\n\t * are written by default; `derived` / `operator` / `effect` are always skipped so\n\t * deps drive recomputation. `producer` entries are skipped unless `includeProducers`\n\t * is set (producers recompute on activation, so restoring is usually a no-op\n\t * overwritten on the next wave — opt in for audit / forensic round-trip use cases).\n\t * Unknown paths are ignored.\n\t *\n\t * @param data - Snapshot envelope with matching `name` and node slices.\n\t * @throws If `data.name` does not equal {@link Graph.name}.\n\t */\n\trestore(\n\t\tdata: GraphPersistSnapshot,\n\t\toptions?: {\n\t\t\tonly?: string | readonly string[];\n\t\t\t/**\n\t\t\t * Fires per failing write. Default behavior (omitted) is silent —\n\t\t\t * missing paths and guard denials are swallowed to match the\n\t\t\t * historical semantics. Provide a callback to surface failures\n\t\t\t * without aborting the remaining restores.\n\t\t\t */\n\t\t\tonError?: (path: string, err: unknown) => void;\n\t\t\t/**\n\t\t\t * Restore `producer` node values alongside `state`. Default `false`:\n\t\t\t * producers are reactive sources whose value recomputes on\n\t\t\t * activation, so restoring from a snapshot is usually a no-op\n\t\t\t * overwritten on the next wave. Audit / forensic round-trip use\n\t\t\t * cases that need the stored value to survive restoration can\n\t\t\t * opt in. Does not change `derived` / `effect` handling — those\n\t\t\t * are always skipped.\n\t\t\t */\n\t\t\tincludeProducers?: boolean;\n\t\t},\n\t): void {\n\t\tparseSnapshotEnvelope(data);\n\t\tif (data.name !== this.name) {\n\t\t\tthrow new Error(\n\t\t\t\t`Graph \"${this.name}\": restore snapshot name \"${data.name}\" does not match this graph`,\n\t\t\t);\n\t\t}\n\t\tconst onlyPatterns =\n\t\t\toptions?.only == null\n\t\t\t\t? null\n\t\t\t\t: (Array.isArray(options.only) ? options.only : [options.only]).map((p) => globToRegex(p));\n\t\tconst includeProducers = options?.includeProducers === true;\n\t\tfor (const path of Object.keys(data.nodes).sort()) {\n\t\t\tif (onlyPatterns !== null && !onlyPatterns.some((re) => re.test(path))) continue;\n\t\t\tconst slice = data.nodes[path];\n\t\t\tif (slice === undefined) continue;\n\t\t\tif (!(\"value\" in slice) || slice.value === undefined) {\n\t\t\t\t// Value absent (valid slice with no snapshotted value) or\n\t\t\t\t// value === undefined (malformed — undefined is the global\n\t\t\t\t// SENTINEL per spec §2.5, not valid DATA). Surface the\n\t\t\t\t// malformed case so torn snapshots don't round-trip silently.\n\t\t\t\tif (\"value\" in slice && slice.value === undefined) {\n\t\t\t\t\toptions?.onError?.(\n\t\t\t\t\t\tpath,\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`restore: slice.value is undefined for \"${path}\" (undefined is the global SENTINEL; not valid DATA)`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (slice.type === \"derived\" || slice.type === \"effect\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (slice.type === \"producer\" && !includeProducers) {\n\t\t\t\t// Reactive producers recompute on activation — restoring would\n\t\t\t\t// be overwritten on the first wave. Opt in via\n\t\t\t\t// `{includeProducers: true}` for audit use cases.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// V0 shortcut: if the snapshot slice and the live node both carry\n\t\t\t// matching versioning info (`v.id` + `v.version`), skip the\n\t\t\t// `set()` — the state is already what the snapshot represents.\n\t\t\t// Avoids redundant DATA waves on idempotent restores.\n\t\t\tif (slice.v != null) {\n\t\t\t\tconst live = this.tryResolve(path);\n\t\t\t\tconst lv = live?.v;\n\t\t\t\tif (lv != null && lv.id === slice.v.id && lv.version === slice.v.version) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tthis.set(path, slice.value);\n\t\t\t} catch (err) {\n\t\t\t\toptions?.onError?.(path, err);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Creates a graph named from the snapshot, optionally runs `build` to register nodes\n\t * and mounts, then {@link Graph.restore} values (§3.8).\n\t *\n\t * @param data - Snapshot envelope (`version` checked).\n\t * @param opts - Either a legacy `build(g)` callback, or an options object:\n\t * - `build?` — topology constructor; skips auto-hydration when present.\n\t * - `factories?` — map from glob pattern to {@link GraphNodeFactory},\n\t * used by auto-hydration to reconstruct non-state nodes. Per-call (no\n\t * process-global registry). First matching pattern wins.\n\t * @returns Hydrated `Graph` instance.\n\t */\n\tstatic fromSnapshot(\n\t\tdata: GraphPersistSnapshot,\n\t\topts?:\n\t\t\t| ((g: Graph) => void)\n\t\t\t| { build?: (g: Graph) => void; factories?: Record<string, GraphNodeFactory> },\n\t): Graph {\n\t\tparseSnapshotEnvelope(data);\n\t\tconst build = typeof opts === \"function\" ? opts : opts?.build;\n\t\tconst factoryMap = typeof opts === \"function\" ? undefined : opts?.factories;\n\t\tconst g = new Graph(data.name);\n\t\tif (build) {\n\t\t\tbuild(g);\n\t\t\tg.restore(data);\n\t\t\treturn g;\n\t\t}\n\t\t// Auto-create mount hierarchy from subgraphs.\n\t\tfor (const mount of [...data.subgraphs].sort((a, b) => {\n\t\t\tconst da = a.split(PATH_SEP).length;\n\t\t\tconst db = b.split(PATH_SEP).length;\n\t\t\tif (da !== db) return da - db;\n\t\t\tif (a < b) return -1;\n\t\t\tif (a > b) return 1;\n\t\t\treturn 0;\n\t\t})) {\n\t\t\tconst parts = mount.split(PATH_SEP);\n\t\t\tlet target: Graph = g;\n\t\t\tfor (const seg of parts) {\n\t\t\t\tif (!target._mounts.has(seg)) {\n\t\t\t\t\ttarget.mount(seg, new Graph(seg));\n\t\t\t\t}\n\t\t\t\ttarget = target._mounts.get(seg)!;\n\t\t\t}\n\t\t}\n\n\t\t// Compile factory glob patterns once. First match in insertion order wins.\n\t\tconst factories = factoryMap\n\t\t\t? Object.entries(factoryMap).map(([pattern, factory]) => ({\n\t\t\t\t\tre: globToRegex(pattern),\n\t\t\t\t\tfactory,\n\t\t\t\t}))\n\t\t\t: [];\n\t\tconst factoryForPath = (path: string): GraphNodeFactory | undefined => {\n\t\t\tfor (const entry of factories) {\n\t\t\t\tif (entry.re.test(path)) return entry.factory;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t};\n\n\t\t// Resolve the owning graph + local name for a qualified snapshot path.\n\t\tconst ownerForPath = (path: string): [Graph, string] => {\n\t\t\tconst segments = path.split(PATH_SEP);\n\t\t\tconst local = segments.pop();\n\t\t\tif (local == null || local.length === 0) {\n\t\t\t\tthrow new Error(`invalid snapshot path \"${path}\"`);\n\t\t\t}\n\t\t\tlet owner: Graph = g;\n\t\t\tfor (const seg of segments) {\n\t\t\t\tconst next = owner._mounts.get(seg);\n\t\t\t\tif (!next) throw new Error(`unknown mount \"${seg}\" in path \"${path}\"`);\n\t\t\t\towner = next;\n\t\t\t}\n\t\t\treturn [owner, local];\n\t\t};\n\n\t\tconst primaryEntries = Object.entries(data.nodes)\n\t\t\t.filter(([path]) => !path.includes(`${PATH_SEP}${GRAPH_META_SEGMENT}${PATH_SEP}`))\n\t\t\t.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n\t\tconst pending = new Map(primaryEntries);\n\t\tconst created = new Map<string, Node>();\n\n\t\tlet progressed = true;\n\t\twhile (pending.size > 0 && progressed) {\n\t\t\tprogressed = false;\n\t\t\tfor (const [path, slice] of [...pending.entries()]) {\n\t\t\t\tconst deps = slice?.deps ?? [];\n\t\t\t\tif (!deps.every((dep) => created.has(dep))) continue;\n\t\t\t\tconst [owner, localName] = ownerForPath(path);\n\t\t\t\tconst meta: Record<string, unknown> = { ...(slice?.meta ?? {}) };\n\t\t\t\tconst factory = factoryForPath(path);\n\t\t\t\tlet node: Node;\n\t\t\t\tif (slice?.type === \"state\") {\n\t\t\t\t\tnode = stateNode(slice.value, { meta });\n\t\t\t\t} else {\n\t\t\t\t\tif (factory == null) continue;\n\t\t\t\t\tnode = factory(localName, {\n\t\t\t\t\t\tpath,\n\t\t\t\t\t\ttype: slice.type,\n\t\t\t\t\t\tvalue: slice.value,\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\tdeps,\n\t\t\t\t\t\tresolvedDeps: deps.map((dep) => created.get(dep)!),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\towner.add(localName, node);\n\t\t\t\tcreated.set(path, node);\n\t\t\t\tpending.delete(path);\n\t\t\t\tprogressed = true;\n\t\t\t}\n\t\t}\n\t\tif (pending.size > 0) {\n\t\t\tconst unresolved = [...pending.keys()].sort().join(\", \");\n\t\t\tthrow new Error(\n\t\t\t\t`Graph.fromSnapshot could not reconstruct nodes without build callback: ${unresolved}. ` +\n\t\t\t\t\t`Pass matching factories via fromSnapshot(data, { factories: { pattern: factoryFn } }).`,\n\t\t\t);\n\t\t}\n\t\t// Edges are derived from node `_deps` reconstructed during node\n\t\t// creation above — no explicit edge replay needed (Unit 7).\n\t\tg.restore(data);\n\t\treturn g;\n\t}\n\n\t/**\n\t * ECMAScript `JSON.stringify` hook — returns the same object as\n\t * {@link Graph.snapshot}. Makes `JSON.stringify(graph)` \"just work\"\n\t * without double-encoding.\n\t */\n\ttoJSON(): GraphPersistSnapshot {\n\t\treturn this.snapshot();\n\t}\n\n\t/**\n\t * Unified persistence surface (§3.8). Cascades snapshot records through\n\t * one or more {@link StorageTier}s, each with its own `debounceMs` /\n\t * `compactEvery` cadence and independent diff baseline.\n\t *\n\t * Subscription gates on {@link messageTier} ≥ 3 (DATA/RESOLVED/terminal),\n\t * never on tier-0/1/2 control waves (START/DIRTY/INVALIDATE/PAUSE/RESUME)\n\t * or tier-5 TEARDOWN (graceful shutdown is the caller's responsibility).\n\t *\n\t * Per-tier cadence lets the hot tier stay sync while cold tiers absorb\n\t * async writes without blocking the hot path. Each tier holds its own\n\t * `{lastSnapshot, lastVersionFingerprint}` so cold-tier diff baselines\n\t * aren't polluted by hot-tier flushes. Tiers with `debounceMs === 0`\n\t * share a single snapshot computation per observe event; debounced tiers\n\t * compute their own snapshot when their timer fires.\n\t */\n\tattachStorage(\n\t\ttiers: readonly StorageTier[],\n\t\toptions: GraphAttachStorageOptions = {},\n\t): StorageHandle {\n\t\ttype TierState = {\n\t\t\ttier: StorageTier;\n\t\t\tdebounceMs: number;\n\t\t\tcompactEvery: number;\n\t\t\ttimer: ResettableTimer | undefined;\n\t\t\tseq: number;\n\t\t\tlastSnapshot: GraphPersistSnapshot | undefined;\n\t\t\tlastFingerprint: string;\n\t\t\tdisposed: boolean;\n\t\t\t// Chain of pending async saves for this tier. Each flush awaits the\n\t\t\t// previous one so baseline advances only after persistence confirms;\n\t\t\t// on rejection the chain resets (next flush starts from the last\n\t\t\t// successfully-persisted baseline). Sync tiers never populate this.\n\t\t\tsavePending: Promise<void> | undefined;\n\t\t};\n\t\tconst states: TierState[] = tiers.map((tier) => ({\n\t\t\ttier,\n\t\t\tdebounceMs: Math.max(0, tier.debounceMs ?? 0),\n\t\t\tcompactEvery: Math.max(1, tier.compactEvery ?? 10),\n\t\t\ttimer: undefined,\n\t\t\tseq: 0,\n\t\t\tlastSnapshot: undefined,\n\t\t\tlastFingerprint: \"\",\n\t\t\tdisposed: false,\n\t\t\tsavePending: undefined,\n\t\t}));\n\n\t\tif (options.autoRestore === true) {\n\t\t\t// Fire-and-forget cascade restore; errors surface via onError with\n\t\t\t// the specific tier that failed.\n\t\t\tvoid this._cascadeRestore(tiers, options.onError);\n\t\t}\n\n\t\tconst runFlush = (s: TierState, snapshot: GraphPersistSnapshot): void => {\n\t\t\tif (s.disposed) return;\n\t\t\tconst fingerprint = computeVersionFingerprint(snapshot.nodes);\n\t\t\tif (s.lastSnapshot != null && fingerprint !== \"\" && fingerprint === s.lastFingerprint) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextSeq = s.seq + 1;\n\t\t\t// Persisted records carry wall-clock attribution (CLAUDE.md time-util\n\t\t\t// rule). Internal event-order timestamps use monotonicNs — this is the\n\t\t\t// output-to-durable-store boundary, so wall clock is correct and\n\t\t\t// cross-source comparable with surface.saveSnapshot records.\n\t\t\tconst timestamp_ns = wallClockNs();\n\t\t\tconst isFirst = s.lastSnapshot == null;\n\t\t\tconst shouldCompact = isFirst || nextSeq % s.compactEvery === 0;\n\t\t\tconst record: GraphCheckpointRecord = shouldCompact\n\t\t\t\t? {\n\t\t\t\t\t\tmode: \"full\",\n\t\t\t\t\t\tsnapshot,\n\t\t\t\t\t\tseq: nextSeq,\n\t\t\t\t\t\ttimestamp_ns,\n\t\t\t\t\t\tformat_version: SNAPSHOT_VERSION,\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tmode: \"diff\",\n\t\t\t\t\t\tdiff: diffForWAL(s.lastSnapshot!, snapshot),\n\t\t\t\t\t\tseq: nextSeq,\n\t\t\t\t\t\ttimestamp_ns,\n\t\t\t\t\t\tformat_version: SNAPSHOT_VERSION,\n\t\t\t\t\t};\n\t\t\tif (s.tier.filter && !s.tier.filter(this.name, record)) {\n\t\t\t\t// Filter rejected — don't advance seq or baseline.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet result: void | Promise<void>;\n\t\t\ttry {\n\t\t\t\tresult = s.tier.save(this.name, record);\n\t\t\t} catch (error) {\n\t\t\t\t// Synchronous throw — baseline untouched; surface and bail.\n\t\t\t\toptions.onError?.(error, s.tier);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (result && typeof (result as Promise<void>).then === \"function\") {\n\t\t\t\t// Async tier: defer baseline + seq advance until the promise\n\t\t\t\t// settles. Chain saves per-tier so they land in order without\n\t\t\t\t// overlapping baselines. On rejection, baseline is left intact\n\t\t\t\t// so the next flush diffs against the last successfully\n\t\t\t\t// persisted snapshot.\n\t\t\t\tconst prev = s.savePending ?? Promise.resolve();\n\t\t\t\tconst chained = prev.then(\n\t\t\t\t\t() => result as Promise<void>,\n\t\t\t\t\t// Previous rejection already surfaced; don't block this save.\n\t\t\t\t\t() => result as Promise<void>,\n\t\t\t\t);\n\t\t\t\tconst final = chained.then(\n\t\t\t\t\t() => {\n\t\t\t\t\t\tif (s.disposed) return;\n\t\t\t\t\t\ts.seq = nextSeq;\n\t\t\t\t\t\ts.lastSnapshot = snapshot;\n\t\t\t\t\t\ts.lastFingerprint = fingerprint;\n\t\t\t\t\t},\n\t\t\t\t\t(err) => {\n\t\t\t\t\t\toptions.onError?.(err, s.tier);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\ts.savePending = final.finally(() => {\n\t\t\t\t\tif (s.savePending === final) s.savePending = undefined;\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\ts.seq = nextSeq;\n\t\t\t\ts.lastSnapshot = snapshot;\n\t\t\t\ts.lastFingerprint = fingerprint;\n\t\t\t}\n\t\t};\n\n\t\tconst flushTier = (s: TierState, snapshot: GraphPersistSnapshot): void => {\n\t\t\ttry {\n\t\t\t\trunFlush(s, snapshot);\n\t\t\t} catch (error) {\n\t\t\t\toptions.onError?.(error, s.tier);\n\t\t\t}\n\t\t};\n\n\t\tconst onEvent = (path: string, messages: Messages): void => {\n\t\t\tconst triggeredByTier = messages.some((m) => {\n\t\t\t\tconst tier = this.config.messageTier(m[0]);\n\t\t\t\treturn tier >= 3 && tier < 5;\n\t\t\t});\n\t\t\tif (!triggeredByTier) return;\n\t\t\tif (options.filter) {\n\t\t\t\tconst nd = this.tryResolve(path);\n\t\t\t\tif (nd == null) return;\n\t\t\t\tconst described = describeNode(nd, resolveDescribeFields(\"standard\"));\n\t\t\t\tif (!options.filter(path, described)) return;\n\t\t\t}\n\t\t\t// Shared snapshot for all sync (debounceMs=0) tiers firing on this event.\n\t\t\tlet sharedSnapshot: GraphPersistSnapshot | undefined;\n\t\t\tconst getSnapshot = (): GraphPersistSnapshot => {\n\t\t\t\tif (sharedSnapshot == null) sharedSnapshot = this.snapshot();\n\t\t\t\treturn sharedSnapshot;\n\t\t\t};\n\t\t\tfor (const s of states) {\n\t\t\t\tif (s.disposed) continue;\n\t\t\t\tif (s.debounceMs === 0) {\n\t\t\t\t\tflushTier(s, getSnapshot());\n\t\t\t\t} else {\n\t\t\t\t\tif (s.timer == null) s.timer = new ResettableTimer();\n\t\t\t\t\ts.timer.start(s.debounceMs, () => {\n\t\t\t\t\t\tif (s.disposed) return;\n\t\t\t\t\t\tflushTier(s, this.snapshot());\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tlet off: () => void;\n\t\tif (options.paths != null) {\n\t\t\tconst paths =\n\t\t\t\ttypeof options.paths === \"string\"\n\t\t\t\t\t? this._pathsMatching(options.paths)\n\t\t\t\t\t: (options.paths as readonly string[]);\n\t\t\tconst unsubs = paths.map((p) => {\n\t\t\t\tconst nd = this.tryResolve(p);\n\t\t\t\tif (nd == null) return () => {};\n\t\t\t\treturn nd.subscribe((msgs) => onEvent(p, msgs));\n\t\t\t});\n\t\t\toff = () => {\n\t\t\t\tfor (const u of unsubs) u();\n\t\t\t};\n\t\t} else {\n\t\t\toff = this.observe().subscribe((path, messages) => onEvent(path, messages));\n\t\t}\n\n\t\tconst dispose = () => {\n\t\t\toff();\n\t\t\tfor (const s of states) {\n\t\t\t\ts.disposed = true;\n\t\t\t\ts.timer?.cancel();\n\t\t\t}\n\t\t\tthis._storageDisposers.delete(dispose);\n\t\t};\n\t\tthis._storageDisposers.add(dispose);\n\t\treturn { dispose };\n\t}\n\n\t/**\n\t * Try tiers in order (hottest first); apply the first record that hits\n\t * via {@link Graph.restore}. Returns `true` if any tier produced a\n\t * restorable snapshot, `false` if all missed.\n\t *\n\t * Resilience: a tier that returns data which cannot be restored (load\n\t * throws, shape unrecognized, or `restore()` itself throws) does not abort\n\t * the cascade — the error is routed through `onError` (if supplied) and\n\t * the next colder tier is tried. This mirrors how a multi-tier cache\n\t * falls through on a corrupt hot entry.\n\t *\n\t * Note: `restore()` mutates state incrementally. If a restore throws\n\t * partway through, the graph may hold a mixed state (some slices from\n\t * the bad tier, some pre-existing). A subsequent successful tier's\n\t * `restore()` overwrites the overlapping slices.\n\t *\n\t * Internal helper shared by {@link Graph.attachStorage}'s `autoRestore`\n\t * option and the static {@link Graph.fromStorage} factory.\n\t */\n\tprivate async _cascadeRestore(\n\t\ttiers: readonly StorageTier[],\n\t\tonError?: (err: unknown, tier: StorageTier) => void,\n\t): Promise<boolean> {\n\t\tfor (const tier of tiers) {\n\t\t\tlet raw: unknown;\n\t\t\ttry {\n\t\t\t\traw = await tier.load(this.name);\n\t\t\t} catch (err) {\n\t\t\t\tonError?.(err, tier);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (raw == null) continue;\n\t\t\tif (typeof raw !== \"object\" || Array.isArray(raw)) continue;\n\t\t\tconst record = raw as Record<string, unknown>;\n\t\t\ttry {\n\t\t\t\t// Accept both a `GraphCheckpointRecord` envelope\n\t\t\t\t// (`mode === \"full\"`) and a bare `GraphPersistSnapshot` (the\n\t\t\t\t// shape written by `saveGraphCheckpoint`). Bare snapshots\n\t\t\t\t// carry `version: 1`.\n\t\t\t\tif (record.mode === \"full\" && record.snapshot != null) {\n\t\t\t\t\tthis.restore(record.snapshot as GraphPersistSnapshot);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (record.version === SNAPSHOT_VERSION && record.nodes != null) {\n\t\t\t\t\tthis.restore(record as GraphPersistSnapshot);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tonError?.(err, tier);\n\t\t\t\t// Fall through to the next tier.\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Construct a fresh {@link Graph} pre-hydrated from the first tier that\n\t * hits. Delegates topology reconstruction to {@link Graph.fromSnapshot}\n\t * on `\"full\"` records and direct {@link Graph.restore} on bare snapshots.\n\t *\n\t * Always asynchronous — awaits `tier.load()` for async tier support even\n\t * when all tiers are sync. Callers that know they only pass sync tiers\n\t * can safely `await` immediately.\n\t *\n\t * @throws If no tier holds a restorable record matching `name` *and* no\n\t * `factories` override is provided for dynamic nodes.\n\t */\n\tstatic async fromStorage(\n\t\tname: string,\n\t\ttiers: readonly StorageTier[],\n\t\topts?: GraphOptions & {\n\t\t\tfactories?: Record<string, GraphNodeFactory>;\n\t\t\t/**\n\t\t\t * Called when a tier throws during `load()` or when\n\t\t\t * {@link Graph.fromSnapshot} rejects a tier's record. The cascade\n\t\t\t * falls through to the next colder tier regardless.\n\t\t\t */\n\t\t\tonError?: (err: unknown, tier: StorageTier) => void;\n\t\t},\n\t): Promise<Graph> {\n\t\tfor (const tier of tiers) {\n\t\t\tlet raw: unknown;\n\t\t\ttry {\n\t\t\t\traw = await tier.load(name);\n\t\t\t} catch (err) {\n\t\t\t\topts?.onError?.(err, tier);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (raw == null) continue;\n\t\t\tif (typeof raw !== \"object\" || Array.isArray(raw)) continue;\n\t\t\tconst record = raw as Record<string, unknown>;\n\t\t\tconst snapshot: GraphPersistSnapshot | undefined =\n\t\t\t\trecord.mode === \"full\" && record.snapshot != null\n\t\t\t\t\t? (record.snapshot as GraphPersistSnapshot)\n\t\t\t\t\t: record.version === SNAPSHOT_VERSION && record.nodes != null\n\t\t\t\t\t\t? (record as GraphPersistSnapshot)\n\t\t\t\t\t\t: undefined;\n\t\t\tif (snapshot == null) continue;\n\t\t\ttry {\n\t\t\t\treturn Graph.fromSnapshot(snapshot, opts);\n\t\t\t} catch (err) {\n\t\t\t\topts?.onError?.(err, tier);\n\t\t\t\t// Fall through to colder tier.\n\t\t\t}\n\t\t}\n\t\tthrow new Error(\n\t\t\t`Graph.fromStorage: no tier held a restorable record for \"${name}\" across ${tiers.length} tier(s)`,\n\t\t);\n\t}\n\n\t// ——————————————————————————————————————————————————————————————\n\t// Inspector (roadmap 3.3) — reasoning trace, overhead gating\n\t// ——————————————————————————————————————————————————————————————\n\n\t// Inspector gating lives on `this.config.inspectorEnabled` (see\n\t// `core/config.ts`). Default: `true` outside `NODE_ENV === \"production\"`.\n\n\tprivate _annotations = new Map<string, string>();\n\tprivate readonly _traceRing: RingBuffer<TraceEntry>;\n\n\t/**\n\t * Unified reasoning trace: write annotations or read the ring buffer.\n\t *\n\t * Write: `graph.trace(\"path\", \"reason\")` — attaches a reasoning annotation\n\t * to a node, capturing *why* an AI agent set a value. Unknown paths are\n\t * silently dropped (matching `observe` resilience). No-op when\n\t * `config.inspectorEnabled` is `false`.\n\t *\n\t * Read: `graph.trace()` — returns a chronological log of all annotations.\n\t * Returns `[]` when `config.inspectorEnabled` is `false`.\n\t */\n\ttrace(path: string, reason: string, opts?: { actor?: Actor }): void;\n\ttrace(): readonly TraceEntry[];\n\ttrace(\n\t\tpath?: string,\n\t\treason?: string,\n\t\topts?: { actor?: Actor },\n\t): undefined | readonly TraceEntry[] {\n\t\tif (path != null && reason != null) {\n\t\t\tif (!this.config.inspectorEnabled) return;\n\t\t\t// Silent-drop unknown paths — matches `observe` resilience. Callers\n\t\t\t// with robust path-hygiene needs can pre-check via `tryResolve`.\n\t\t\tif (this.tryResolve(path) == null) return;\n\t\t\tthis._annotations.set(path, reason);\n\t\t\tconst entry: TraceEntry = {\n\t\t\t\tpath,\n\t\t\t\treason,\n\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t...(opts?.actor != null ? { actor: opts.actor } : {}),\n\t\t\t};\n\t\t\tthis._traceRing.push(entry);\n\t\t\treturn;\n\t\t}\n\t\tif (!this.config.inspectorEnabled) return [];\n\t\treturn this._traceRing.toArray();\n\t}\n\n\t/**\n\t * Latest reason annotation attached to `path` via {@link Graph.trace},\n\t * or `undefined` if none. `describe()` surfaces this via the `reason`\n\t * field on each node entry (when present).\n\t */\n\tannotation(path: string): string | undefined {\n\t\treturn this._annotations.get(path);\n\t}\n\n\t/**\n\t * Clear all reasoning-trace state (both the per-path annotations map and\n\t * the ring buffer). Useful for long-running processes that want periodic\n\t * resets, or tests that need a clean slate.\n\t */\n\tclearTrace(): void {\n\t\tthis._annotations.clear();\n\t\tthis._traceRing.clear();\n\t}\n\n\t/**\n\t * Remove trace entries matching `predicate`. Returns the number of\n\t * entries removed. Does not touch the per-path annotations map — call\n\t * {@link Graph.clearTrace} for a full reset.\n\t */\n\tpruneTrace(predicate: (entry: TraceEntry) => boolean): number {\n\t\tconst kept = this._traceRing.toArray().filter((e) => !predicate(e));\n\t\tconst removed = this._traceRing.size - kept.length;\n\t\tthis._traceRing.clear();\n\t\tfor (const e of kept) this._traceRing.push(e);\n\t\treturn removed;\n\t}\n\n\t/**\n\t * Computes structural + value diff between two {@link Graph.describe} snapshots.\n\t *\n\t * @param a - Earlier describe output.\n\t * @param b - Later describe output.\n\t * @returns Added/removed nodes, changed fields, and edge deltas.\n\t */\n\tstatic diff(a: GraphDescribeOutput, b: GraphDescribeOutput): GraphDiffResult {\n\t\tconst aKeys = new Set(Object.keys(a.nodes));\n\t\tconst bKeys = new Set(Object.keys(b.nodes));\n\n\t\tconst nodesAdded = [...bKeys].filter((k) => !aKeys.has(k)).sort();\n\t\tconst nodesRemoved = [...aKeys].filter((k) => !bKeys.has(k)).sort();\n\t\tconst nodesChanged: GraphDiffChange[] = [];\n\t\tconst versionChanges: GraphVersionChange[] = [];\n\n\t\tfor (const key of aKeys) {\n\t\t\tif (!bKeys.has(key)) continue;\n\t\t\tconst na = a.nodes[key];\n\t\t\tconst nb = b.nodes[key];\n\t\t\tconst av = na.v;\n\t\t\tconst bv = nb.v;\n\t\t\t// Surface version bumps (even if value is identical, the bump itself\n\t\t\t// is meaningful for audit / wire-efficient sync).\n\t\t\tif (av != null && bv != null && av.id === bv.id && av.version !== bv.version) {\n\t\t\t\tversionChanges.push({\n\t\t\t\t\tpath: key,\n\t\t\t\t\tid: av.id,\n\t\t\t\t\tfrom: av.version,\n\t\t\t\t\tto: bv.version,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst versionMatches =\n\t\t\t\tav != null && bv != null && av.id === bv.id && av.version === bv.version;\n\t\t\t// V0 fast path: when versions match, skip value / meta compare —\n\t\t\t// upstream is guaranteed unchanged by protocol. Only type/status\n\t\t\t// (cheap string compare) + sentinel flip are possible.\n\t\t\tfor (const field of [\"type\", \"status\", \"sentinel\"] as const) {\n\t\t\t\tconst va = (na as Record<string, unknown>)[field];\n\t\t\t\tconst vb = (nb as Record<string, unknown>)[field];\n\t\t\t\tif (va !== vb) {\n\t\t\t\t\tnodesChanged.push({ path: key, field, from: va, to: vb });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (versionMatches) continue;\n\t\t\t// Full slow-path: deep-equal on value + meta.\n\t\t\tfor (const field of [\"value\", \"meta\"] as const) {\n\t\t\t\tconst va = (na as Record<string, unknown>)[field];\n\t\t\t\tconst vb = (nb as Record<string, unknown>)[field];\n\t\t\t\tif (!deepEqual(va, vb)) {\n\t\t\t\t\tnodesChanged.push({ path: key, field, from: va, to: vb });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst edgeKey = (e: { from: string; to: string }) => `${e.from}\\t${e.to}`;\n\t\tconst aEdges = new Set(a.edges.map(edgeKey));\n\t\tconst bEdges = new Set(b.edges.map(edgeKey));\n\n\t\tconst edgesAdded = b.edges.filter((e) => !aEdges.has(edgeKey(e)));\n\t\tconst edgesRemoved = a.edges.filter((e) => !bEdges.has(edgeKey(e)));\n\t\tconst aSubgraphs = new Set(a.subgraphs);\n\t\tconst bSubgraphs = new Set(b.subgraphs);\n\t\tconst subgraphsAdded = [...bSubgraphs].filter((s) => !aSubgraphs.has(s)).sort();\n\t\tconst subgraphsRemoved = [...aSubgraphs].filter((s) => !bSubgraphs.has(s)).sort();\n\n\t\treturn {\n\t\t\tnodesAdded,\n\t\t\tnodesRemoved,\n\t\t\tnodesChanged,\n\t\t\tversionChanges,\n\t\t\tedgesAdded,\n\t\t\tedgesRemoved,\n\t\t\tsubgraphsAdded,\n\t\t\tsubgraphsRemoved,\n\t\t};\n\t}\n}\n\n/** Entry in the reasoning trace ring buffer (roadmap 3.3). */\nexport type TraceEntry = {\n\tpath: string;\n\treason: string;\n\ttimestamp_ns: number;\n\t/**\n\t * Actor that produced the annotation (optional). Enables multi-agent\n\t * attribution: distinguish \"LLM set this rootCause\" from \"human approved\n\t * this intervention\" in the trace log.\n\t */\n\tactor?: Actor;\n};\n\n/** Result of {@link Graph.diff}. */\nexport type GraphDiffResult = {\n\tnodesAdded: string[];\n\tnodesRemoved: string[];\n\tnodesChanged: GraphDiffChange[];\n\t/**\n\t * V0 version bumps (same `v.id`, different `v.version`). Surfaced even\n\t * when values are identical — the bump itself is audit-meaningful.\n\t */\n\tversionChanges: GraphVersionChange[];\n\tedgesAdded: Array<{ from: string; to: string }>;\n\tedgesRemoved: Array<{ from: string; to: string }>;\n\tsubgraphsAdded: string[];\n\tsubgraphsRemoved: string[];\n};\n\n/**\n * WAL-oriented diff — extends {@link GraphDiffResult} with the full node\n * slice for each added path so {@link replayWAL} can reconstruct nodes added\n * between full anchors (topology mutations inside a `compactEvery` window).\n *\n * `Graph.diff()` returns the audit shape (no payload); `attachStorage` writes\n * this WAL shape. The two shapes stay structurally compatible — `GraphWALDiff`\n * is a superset.\n */\nexport type GraphWALDiff = GraphDiffResult & {\n\t/**\n\t * Full node slices for every path in `nodesAdded`, keyed by path. Applied\n\t * verbatim to `snapshot.nodes[path]` during replay.\n\t */\n\tnodesAddedFull: Record<string, DescribeNodeOutput>;\n};\n\n/**\n * Build a WAL-ready diff between two snapshots: the structural diff from\n * {@link Graph.diff} plus the full node slice for each added path (pulled\n * from `b.nodes`). Callers that only need the audit shape should use\n * `Graph.diff` directly.\n */\nexport function diffForWAL(a: GraphDescribeOutput, b: GraphDescribeOutput): GraphWALDiff {\n\tconst base = Graph.diff(a, b);\n\tconst nodesAddedFull: Record<string, DescribeNodeOutput> = {};\n\tfor (const path of base.nodesAdded) {\n\t\tconst slice = b.nodes[path];\n\t\tif (slice != null) nodesAddedFull[path] = slice;\n\t}\n\treturn { ...base, nodesAddedFull };\n}\n\n/** A single field change within a diff. */\nexport type GraphDiffChange = {\n\tpath: string;\n\tfield: string;\n\tfrom: unknown;\n\tto: unknown;\n};\n\n/** A single V0 version bump within a diff. */\nexport type GraphVersionChange = {\n\tpath: string;\n\tid: string;\n\tfrom: number;\n\tto: number;\n};\n\n/** Audit record returned by {@link Graph.remove}. */\nexport type GraphRemoveAudit = {\n\t/** Whether the removed entry was a local node or a mount. */\n\tkind: \"node\" | \"mount\";\n\t/**\n\t * Primary nodes torn down by this `remove()`. For `kind: \"node\"` contains\n\t * just the removed name; for `kind: \"mount\"` lists every primary node in\n\t * the unmounted subtree (qualified paths relative to the mount point,\n\t * sorted).\n\t */\n\tnodes: string[];\n\t/**\n\t * Mounted subgraphs that were unmounted. For `kind: \"node\"` this is empty;\n\t * for `kind: \"mount\"` starts with the top-level mount name and lists its\n\t * descendants in depth-first order.\n\t */\n\tmounts: string[];\n};\n\n/** Direction for {@link reachable} graph traversal. */\nexport type ReachableDirection = \"upstream\" | \"downstream\";\n\n/** Options for {@link reachable}. */\nexport type ReachableOptions = {\n\t/** Maximum hop depth from `from` (0 returns `[]`). Omit for unbounded traversal. */\n\tmaxDepth?: number;\n\t/**\n\t * Traverse both directions in one pass (union of upstream + downstream).\n\t * Ignores the `direction` arg when set.\n\t */\n\tboth?: boolean;\n\t/**\n\t * Return the richer {@link ReachableResult} shape (paths + per-path\n\t * hop depth + truncation flag) instead of the flat sorted string array.\n\t */\n\twithDetail?: boolean;\n};\n\n/** Rich reachable result (opt-in via `{withDetail: true}`). */\nexport type ReachableResult = {\n\t/** Reachable paths, sorted lexicographically. */\n\tpaths: string[];\n\t/** Hop depth from `from` to each reachable path. */\n\tdepths: Map<string, number>;\n\t/** True when traversal hit `maxDepth` and some neighbors were not explored. */\n\ttruncated: boolean;\n};\n\n/**\n * Reachability query over a {@link Graph.describe} snapshot.\n *\n * Traversal follows `deps` (upstream) and reverse-`deps` (downstream). Edges\n * are derived from deps post Unit 7, so `edges[]` in the snapshot is\n * redundant with deps — it's walked defensively in case a caller supplied a\n * pre-Unit-7 snapshot.\n *\n * @param described - `graph.describe()` output to traverse.\n * @param from - Start path (qualified node path).\n * @param direction - Traversal direction (ignored when `opts.both` is `true`).\n * @param options - Optional `maxDepth`, `both`, `withDetail`.\n * @returns Sorted paths (flat) — or {@link ReachableResult} when `withDetail: true`.\n */\nexport function reachable(\n\tdescribed: GraphDescribeOutput,\n\tfrom: string,\n\tdirection: ReachableDirection,\n\toptions?: ReachableOptions & { withDetail: true },\n): ReachableResult;\nexport function reachable(\n\tdescribed: GraphDescribeOutput,\n\tfrom: string,\n\tdirection: ReachableDirection,\n\toptions?: ReachableOptions,\n): string[];\nexport function reachable(\n\tdescribed: GraphDescribeOutput,\n\tfrom: string,\n\tdirection: ReachableDirection,\n\toptions: ReachableOptions = {},\n): string[] | ReachableResult {\n\tconst empty: ReachableResult = { paths: [], depths: new Map(), truncated: false };\n\tif (!from) return options.withDetail ? empty : [];\n\tif (!options.both && direction !== \"upstream\" && direction !== \"downstream\") {\n\t\tthrow new Error(`reachable: direction must be \"upstream\" or \"downstream\"`);\n\t}\n\tconst maxDepth = options.maxDepth;\n\tif (maxDepth != null && (!Number.isInteger(maxDepth) || maxDepth < 0)) {\n\t\tthrow new Error(`reachable: maxDepth must be an integer >= 0`);\n\t}\n\tif (maxDepth === 0) return options.withDetail ? empty : [];\n\n\tconst depsByPath = new Map<string, readonly string[]>();\n\tconst reverseDeps = new Map<string, Set<string>>();\n\tconst incomingEdges = new Map<string, Set<string>>();\n\tconst outgoingEdges = new Map<string, Set<string>>();\n\tconst universe = new Set<string>();\n\n\tfor (const [path, node] of Object.entries(described.nodes)) {\n\t\tif (!path) continue;\n\t\tuniverse.add(path);\n\t\tconst deps = node.deps ?? [];\n\t\tdepsByPath.set(path, deps);\n\t\tfor (const dep of deps) {\n\t\t\tif (!dep) continue;\n\t\t\tuniverse.add(dep);\n\t\t\tif (!reverseDeps.has(dep)) reverseDeps.set(dep, new Set());\n\t\t\treverseDeps.get(dep)!.add(path);\n\t\t}\n\t}\n\t// Edges are normally derived from deps post Unit 7, but synthetic snapshots\n\t// (e.g. test fixtures) may declare edges independently — walk both for\n\t// compatibility. Minimal null/string checks for malformed JSON.\n\tfor (const edge of described.edges) {\n\t\tif (edge == null || typeof edge !== \"object\") continue;\n\t\tconst from = typeof edge.from === \"string\" ? edge.from : \"\";\n\t\tconst to = typeof edge.to === \"string\" ? edge.to : \"\";\n\t\tif (!from || !to) continue;\n\t\tuniverse.add(from);\n\t\tuniverse.add(to);\n\t\tif (!outgoingEdges.has(from)) outgoingEdges.set(from, new Set());\n\t\toutgoingEdges.get(from)!.add(to);\n\t\tif (!incomingEdges.has(to)) incomingEdges.set(to, new Set());\n\t\tincomingEdges.get(to)!.add(from);\n\t}\n\n\tif (!universe.has(from)) return options.withDetail ? empty : [];\n\n\tconst doBoth = options.both === true;\n\tconst visit = (path: string): readonly string[] => {\n\t\tif (doBoth) {\n\t\t\tconst up = depsByPath.get(path) ?? [];\n\t\t\tconst upEdges = incomingEdges.get(path);\n\t\t\tconst down = reverseDeps.get(path);\n\t\t\tconst downEdges = outgoingEdges.get(path);\n\t\t\tconst acc: string[] = [...up];\n\t\t\tif (upEdges) acc.push(...upEdges);\n\t\t\tif (down) acc.push(...down);\n\t\t\tif (downEdges) acc.push(...downEdges);\n\t\t\treturn acc;\n\t\t}\n\t\tif (direction === \"upstream\") {\n\t\t\tconst up = depsByPath.get(path) ?? [];\n\t\t\tconst upEdges = incomingEdges.get(path);\n\t\t\tif (!upEdges) return up;\n\t\t\treturn [...up, ...upEdges];\n\t\t}\n\t\tconst down = reverseDeps.get(path);\n\t\tconst downEdges = outgoingEdges.get(path);\n\t\tconst acc: string[] = down ? [...down] : [];\n\t\tif (downEdges) acc.push(...downEdges);\n\t\treturn acc;\n\t};\n\n\t// Head-index BFS — avoids O(n²) from `Array.prototype.shift`.\n\tconst visited = new Set<string>([from]);\n\tconst depths = new Map<string, number>();\n\tconst queue: Array<{ path: string; depth: number }> = [{ path: from, depth: 0 }];\n\tlet head = 0;\n\tlet truncated = false;\n\twhile (head < queue.length) {\n\t\tconst next = queue[head++]!;\n\t\tif (maxDepth != null && next.depth >= maxDepth) {\n\t\t\t// Flag truncation only if this node actually has unexplored neighbors.\n\t\t\tif (visit(next.path).length > 0) truncated = true;\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const nb of visit(next.path)) {\n\t\t\tif (!nb || visited.has(nb)) continue;\n\t\t\tvisited.add(nb);\n\t\t\tdepths.set(nb, next.depth + 1);\n\t\t\tqueue.push({ path: nb, depth: next.depth + 1 });\n\t\t}\n\t}\n\n\tconst paths = [...depths.keys()].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n\tif (options.withDetail) return { paths, depths, truncated };\n\treturn paths;\n}\n","/**\n * Memory patterns (roadmap §4.3).\n *\n * Domain-layer helpers composed from GraphRefly primitives. `vectorIndex` uses\n * an exact-search backend by default; an HNSW adapter can be injected as an\n * optional dependency.\n */\n\nimport { monotonicNs } from \"../core/clock.js\";\nimport { DATA } from \"../core/messages.js\";\nimport type { Node } from \"../core/node.js\";\nimport { derived, state } from \"../core/sugar.js\";\nimport { Graph } from \"../graph/graph.js\";\n\nexport type CollectionPolicy = \"fifo\" | \"lru\";\nexport type VectorBackend = \"flat\" | \"hnsw\";\n\nexport type LightCollectionEntry<T> = {\n\treadonly id: string;\n\treadonly value: T;\n\treadonly createdAtNs: number;\n\treadonly lastAccessNs: number;\n};\n\nexport type LightCollectionOptions = {\n\tname?: string;\n\tmaxSize?: number;\n\tpolicy?: CollectionPolicy;\n};\n\nexport type LightCollectionBundle<T> = {\n\treadonly entries: Node<ReadonlyMap<string, LightCollectionEntry<T>>>;\n\tupsert: (id: string, value: T) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\tget: (id: string) => T | undefined;\n\thas: (id: string) => boolean;\n};\n\nexport type CollectionEntry<T> = LightCollectionEntry<T> & {\n\treadonly baseScore: number;\n};\n\nexport type RankedCollectionEntry<T> = CollectionEntry<T> & {\n\treadonly score: number;\n};\n\nexport type CollectionOptions<T> = {\n\tmaxSize?: number;\n\tpolicy?: CollectionPolicy;\n\t/**\n\t * Produces a base score at insert/update time.\n\t */\n\tscore?: (value: T) => number;\n\t/**\n\t * Exponential decay rate per second. 0 disables decay.\n\t */\n\tdecayRate?: number;\n\t/**\n\t * Minimum score floor after decay.\n\t */\n\tminScore?: number;\n};\n\nexport type CollectionGraph<T> = Graph & {\n\tupsert: (id: string, value: T, opts?: { score?: number }) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\tgetItem: (id: string) => CollectionEntry<T> | undefined;\n};\n\nexport type VectorRecord<TMeta> = {\n\treadonly id: string;\n\treadonly vector: readonly number[];\n\treadonly meta?: TMeta;\n};\n\nexport type VectorSearchResult<TMeta> = {\n\treadonly id: string;\n\treadonly score: number;\n\treadonly meta?: TMeta;\n};\n\nexport type HnswAdapter<TMeta> = {\n\tupsert: (id: string, vector: readonly number[], meta?: TMeta) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\tsearch: (query: readonly number[], k: number) => ReadonlyArray<VectorSearchResult<TMeta>>;\n};\n\nexport type VectorIndexOptions<TMeta> = {\n\tbackend?: VectorBackend;\n\tdimension?: number;\n\t/**\n\t * Optional dependency seam for HNSW.\n\t */\n\thnswFactory?: () => HnswAdapter<TMeta>;\n};\n\nexport type VectorIndexBundle<TMeta> = {\n\treadonly backend: VectorBackend;\n\treadonly entries: Node<ReadonlyMap<string, VectorRecord<TMeta>>>;\n\tupsert: (id: string, vector: readonly number[], meta?: TMeta) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\tsearch: (query: readonly number[], k?: number) => ReadonlyArray<VectorSearchResult<TMeta>>;\n};\n\nexport type KnowledgeEdge<TRelation extends string = string> = {\n\treadonly from: string;\n\treadonly to: string;\n\treadonly relation: TRelation;\n\treadonly weight: number;\n};\n\nexport type KnowledgeGraphGraph<TEntity, TRelation extends string = string> = Graph & {\n\tupsertEntity: (id: string, value: TEntity) => void;\n\tremoveEntity: (id: string) => void;\n\tlink: (from: string, to: string, relation: TRelation, weight?: number) => void;\n\tunlink: (from: string, to: string, relation?: TRelation) => void;\n\trelated: (id: string, relation?: TRelation) => ReadonlyArray<KnowledgeEdge<TRelation>>;\n};\n\nexport function decay(\n\tbaseScore: number,\n\tageSeconds: number,\n\tratePerSecond: number,\n\tminScore = 0,\n): number {\n\tif (!Number.isFinite(baseScore)) return minScore;\n\tif (!Number.isFinite(ageSeconds) || ageSeconds <= 0) return Math.max(minScore, baseScore);\n\tif (!Number.isFinite(ratePerSecond) || ratePerSecond <= 0) return Math.max(minScore, baseScore);\n\tconst decayed = baseScore * Math.exp(-ratePerSecond * ageSeconds);\n\treturn Math.max(minScore, decayed);\n}\n\nfunction assertMaxSize(maxSize: number | undefined): void {\n\tif (maxSize !== undefined && maxSize < 1) {\n\t\tthrow new RangeError(\"maxSize must be >= 1\");\n\t}\n}\n\nfunction copyMap<K, V>(m: ReadonlyMap<K, V>): Map<K, V> {\n\treturn new Map(m);\n}\n\nfunction readMap<K, V>(node: Node<ReadonlyMap<K, V>>): ReadonlyMap<K, V> {\n\treturn node.cache ?? new Map<K, V>();\n}\n\nfunction readArray<T>(node: Node<ReadonlyArray<T>>): ReadonlyArray<T> {\n\treturn node.cache ?? [];\n}\n\nfunction cosineSimilarity(a: readonly number[], b: readonly number[]): number {\n\tconst n = Math.max(a.length, b.length);\n\tlet dot = 0;\n\tlet na = 0;\n\tlet nb = 0;\n\tfor (let i = 0; i < n; i += 1) {\n\t\tconst av = a[i] ?? 0;\n\t\tconst bv = b[i] ?? 0;\n\t\tdot += av * bv;\n\t\tna += av * av;\n\t\tnb += bv * bv;\n\t}\n\tif (na === 0 || nb === 0) return 0;\n\treturn dot / Math.sqrt(na * nb);\n}\n\nexport function lightCollection<T>(opts: LightCollectionOptions = {}): LightCollectionBundle<T> {\n\tconst maxSize = opts.maxSize;\n\tconst policy = opts.policy ?? \"fifo\";\n\tassertMaxSize(maxSize);\n\n\tconst entries = state<ReadonlyMap<string, LightCollectionEntry<T>>>(new Map(), {\n\t\tname: opts.name,\n\t\tdescribeKind: \"state\",\n\t});\n\n\tfunction evictIfNeeded(next: Map<string, LightCollectionEntry<T>>): void {\n\t\tif (maxSize === undefined) return;\n\t\twhile (next.size > maxSize) {\n\t\t\tlet victim: LightCollectionEntry<T> | undefined;\n\t\t\tfor (const entry of next.values()) {\n\t\t\t\tif (!victim) {\n\t\t\t\t\tvictim = entry;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst lhs = policy === \"lru\" ? entry.lastAccessNs : entry.createdAtNs;\n\t\t\t\tconst rhs = policy === \"lru\" ? victim.lastAccessNs : victim.createdAtNs;\n\t\t\t\tif (lhs < rhs) victim = entry;\n\t\t\t}\n\t\t\tif (!victim) break;\n\t\t\tnext.delete(victim.id);\n\t\t}\n\t}\n\n\tfunction commit(next: Map<string, LightCollectionEntry<T>>): void {\n\t\tentries.down([[DATA, next]]);\n\t}\n\n\treturn {\n\t\tentries,\n\t\tupsert(id, value) {\n\t\t\tconst now = monotonicNs();\n\t\t\tconst current = readMap(entries);\n\t\t\tconst prev = current.get(id);\n\t\t\tconst next = copyMap(current);\n\t\t\tnext.set(id, {\n\t\t\t\tid,\n\t\t\t\tvalue,\n\t\t\t\tcreatedAtNs: prev?.createdAtNs ?? now,\n\t\t\t\tlastAccessNs: now,\n\t\t\t});\n\t\t\tevictIfNeeded(next);\n\t\t\tcommit(next);\n\t\t},\n\t\tremove(id) {\n\t\t\tconst next = copyMap(readMap(entries));\n\t\t\tif (!next.delete(id)) return;\n\t\t\tcommit(next);\n\t\t},\n\t\tclear() {\n\t\t\tif (readMap(entries).size === 0) return;\n\t\t\tcommit(new Map());\n\t\t},\n\t\tget(id) {\n\t\t\tconst current = readMap(entries);\n\t\t\tconst found = current.get(id);\n\t\t\tif (!found) return undefined;\n\t\t\tif (policy === \"lru\") {\n\t\t\t\tconst now = monotonicNs();\n\t\t\t\tconst next = copyMap(current);\n\t\t\t\tnext.set(id, { ...found, lastAccessNs: now });\n\t\t\t\tcommit(next);\n\t\t\t}\n\t\t\treturn found.value;\n\t\t},\n\t\thas(id) {\n\t\t\treturn readMap(entries).has(id);\n\t\t},\n\t};\n}\n\nexport function collection<T>(name: string, opts: CollectionOptions<T> = {}): CollectionGraph<T> {\n\tconst maxSize = opts.maxSize;\n\tconst policy = opts.policy ?? \"lru\";\n\tconst decayRate = opts.decayRate ?? 0;\n\tconst minScore = opts.minScore ?? 0;\n\tconst scoreFn = opts.score ?? (() => 1);\n\tassertMaxSize(maxSize);\n\n\tconst graph = new Graph(name);\n\tconst items = state<ReadonlyMap<string, CollectionEntry<T>>>(new Map(), {\n\t\tname: \"items\",\n\t\tdescribeKind: \"state\",\n\t});\n\tconst ranked = derived(\n\t\t[items],\n\t\t([snapshot]) => {\n\t\t\tconst typed = (snapshot ?? new Map()) as ReadonlyMap<string, CollectionEntry<T>>;\n\t\t\tconst now = monotonicNs();\n\t\t\tconst out = [...typed.values()].map((entry) => {\n\t\t\t\tconst ageSeconds = (now - entry.lastAccessNs) / 1_000_000_000;\n\t\t\t\treturn {\n\t\t\t\t\t...entry,\n\t\t\t\t\tscore: decay(entry.baseScore, ageSeconds, decayRate, minScore),\n\t\t\t\t};\n\t\t\t});\n\t\t\tout.sort((a, b) => b.score - a.score || b.lastAccessNs - a.lastAccessNs);\n\t\t\treturn out;\n\t\t},\n\t\t{ name: \"ranked\", describeKind: \"derived\" },\n\t);\n\tconst size = derived(\n\t\t[items],\n\t\t([snapshot]) => ((snapshot ?? new Map()) as ReadonlyMap<string, CollectionEntry<T>>).size,\n\t\t{\n\t\t\tname: \"size\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: 0,\n\t\t},\n\t);\n\tvoid ranked.subscribe(() => undefined);\n\tvoid size.subscribe(() => undefined);\n\n\tgraph.add(\"items\", items);\n\tgraph.add(\"ranked\", ranked);\n\tgraph.add(\"size\", size);\n\n\tfunction effective(entry: CollectionEntry<T>, now: number): number {\n\t\tconst ageSeconds = (now - entry.lastAccessNs) / 1_000_000_000;\n\t\treturn decay(entry.baseScore, ageSeconds, decayRate, minScore);\n\t}\n\n\tfunction evictIfNeeded(next: Map<string, CollectionEntry<T>>): void {\n\t\tif (maxSize === undefined) return;\n\t\twhile (next.size > maxSize) {\n\t\t\tconst now = monotonicNs();\n\t\t\tlet victim: CollectionEntry<T> | undefined;\n\t\t\tlet victimScore = Number.POSITIVE_INFINITY;\n\t\t\tfor (const entry of next.values()) {\n\t\t\t\tconst score = effective(entry, now);\n\t\t\t\tif (score < victimScore) {\n\t\t\t\t\tvictim = entry;\n\t\t\t\t\tvictimScore = score;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (score === victimScore && victim) {\n\t\t\t\t\tconst lhs = policy === \"lru\" ? entry.lastAccessNs : entry.createdAtNs;\n\t\t\t\t\tconst rhs = policy === \"lru\" ? victim.lastAccessNs : victim.createdAtNs;\n\t\t\t\t\tif (lhs < rhs) victim = entry;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!victim) break;\n\t\t\tnext.delete(victim.id);\n\t\t}\n\t}\n\n\tfunction commit(next: Map<string, CollectionEntry<T>>): void {\n\t\titems.down([[DATA, next]]);\n\t}\n\n\tconst out = Object.assign(graph, {\n\t\tupsert(id: string, value: T, upsertOpts?: { score?: number }) {\n\t\t\tconst now = monotonicNs();\n\t\t\tconst current = readMap(items);\n\t\t\tconst prev = current.get(id);\n\t\t\tconst baseScore = upsertOpts?.score ?? scoreFn(value);\n\t\t\tconst next = copyMap(current);\n\t\t\tnext.set(id, {\n\t\t\t\tid,\n\t\t\t\tvalue,\n\t\t\t\tbaseScore,\n\t\t\t\tcreatedAtNs: prev?.createdAtNs ?? now,\n\t\t\t\tlastAccessNs: now,\n\t\t\t});\n\t\t\tevictIfNeeded(next);\n\t\t\tcommit(next);\n\t\t},\n\t\tremove(id: string) {\n\t\t\tconst next = copyMap(readMap(items));\n\t\t\tif (!next.delete(id)) return;\n\t\t\tcommit(next);\n\t\t},\n\t\tclear() {\n\t\t\tif (readMap(items).size === 0) return;\n\t\t\tcommit(new Map());\n\t\t},\n\t\tgetItem(id: string): CollectionEntry<T> | undefined {\n\t\t\tconst current = readMap(items);\n\t\t\tconst found = current.get(id);\n\t\t\tif (!found) return undefined;\n\t\t\tif (policy === \"lru\") {\n\t\t\t\tconst next = copyMap(current);\n\t\t\t\tnext.set(id, { ...found, lastAccessNs: monotonicNs() });\n\t\t\t\tcommit(next);\n\t\t\t}\n\t\t\treturn found;\n\t\t},\n\t}) as CollectionGraph<T>;\n\treturn out;\n}\n\nexport function vectorIndex<TMeta>(opts: VectorIndexOptions<TMeta> = {}): VectorIndexBundle<TMeta> {\n\tconst backend = opts.backend ?? \"flat\";\n\tconst dimension = opts.dimension;\n\tlet hnsw: HnswAdapter<TMeta> | undefined;\n\tif (backend === \"hnsw\") {\n\t\thnsw = opts.hnswFactory?.();\n\t\tif (!hnsw) {\n\t\t\tthrow new Error(\n\t\t\t\t'vectorIndex backend \"hnsw\" requires an optional dependency adapter; install your HNSW package and provide `hnswFactory`.',\n\t\t\t);\n\t\t}\n\t}\n\n\tconst entries = state<ReadonlyMap<string, VectorRecord<TMeta>>>(new Map(), {\n\t\tdescribeKind: \"state\",\n\t\tname: \"vector-index\",\n\t});\n\n\tfunction assertDimension(vector: readonly number[]): void {\n\t\tif (dimension !== undefined && vector.length !== dimension) {\n\t\t\tthrow new RangeError(\n\t\t\t\t`vector dimension mismatch: expected ${dimension}, got ${vector.length}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tfunction commit(next: Map<string, VectorRecord<TMeta>>): void {\n\t\tentries.down([[DATA, next]]);\n\t}\n\n\treturn {\n\t\tbackend,\n\t\tentries,\n\t\tupsert(id, vector, meta) {\n\t\t\tassertDimension(vector);\n\t\t\tconst next = copyMap(readMap(entries));\n\t\t\tnext.set(id, { id, vector: [...vector], meta });\n\t\t\tif (backend === \"hnsw\") hnsw!.upsert(id, vector, meta);\n\t\t\tcommit(next);\n\t\t},\n\t\tremove(id) {\n\t\t\tconst next = copyMap(readMap(entries));\n\t\t\tif (!next.delete(id)) return;\n\t\t\tif (backend === \"hnsw\") hnsw!.remove(id);\n\t\t\tcommit(next);\n\t\t},\n\t\tclear() {\n\t\t\tif (readMap(entries).size === 0) return;\n\t\t\tif (backend === \"hnsw\") hnsw!.clear();\n\t\t\tcommit(new Map());\n\t\t},\n\t\tsearch(query, k = 5) {\n\t\t\tassertDimension(query);\n\t\t\tif (k <= 0) return [];\n\t\t\tif (backend === \"hnsw\") return hnsw!.search(query, k);\n\t\t\tconst ranked = [...readMap(entries).values()]\n\t\t\t\t.map((row) => ({\n\t\t\t\t\tid: row.id,\n\t\t\t\t\tscore: cosineSimilarity(query, row.vector),\n\t\t\t\t\tmeta: row.meta,\n\t\t\t\t}))\n\t\t\t\t.sort((a, b) => b.score - a.score)\n\t\t\t\t.slice(0, k);\n\t\t\treturn ranked;\n\t\t},\n\t};\n}\n\nexport function knowledgeGraph<TEntity, TRelation extends string = string>(\n\tname: string,\n): KnowledgeGraphGraph<TEntity, TRelation> {\n\tconst graph = new Graph(name);\n\tconst entities = state<ReadonlyMap<string, TEntity>>(new Map(), {\n\t\tname: \"entities\",\n\t\tdescribeKind: \"state\",\n\t});\n\tconst edges = state<ReadonlyArray<KnowledgeEdge<TRelation>>>([], {\n\t\tname: \"edges\",\n\t\tdescribeKind: \"state\",\n\t});\n\tconst adjacency = derived(\n\t\t[edges],\n\t\t([rows]) => {\n\t\t\tconst typed = (rows ?? []) as ReadonlyArray<KnowledgeEdge<TRelation>>;\n\t\t\tconst out = new Map<string, ReadonlyArray<KnowledgeEdge<TRelation>>>();\n\t\t\tfor (const edge of typed) {\n\t\t\t\tconst prev = out.get(edge.from) ?? [];\n\t\t\t\tout.set(edge.from, Object.freeze([...prev, edge]));\n\t\t\t}\n\t\t\treturn out;\n\t\t},\n\t\t{ name: \"adjacency\", describeKind: \"derived\", initial: new Map() },\n\t);\n\tvoid adjacency.subscribe(() => undefined);\n\n\tgraph.add(\"entities\", entities);\n\tgraph.add(\"edges\", edges);\n\tgraph.add(\"adjacency\", adjacency);\n\n\tfunction commitEntities(next: Map<string, TEntity>): void {\n\t\tentities.down([[DATA, next]]);\n\t}\n\n\tfunction commitEdges(next: ReadonlyArray<KnowledgeEdge<TRelation>>): void {\n\t\tedges.down([[DATA, next]]);\n\t}\n\n\tconst out = Object.assign(graph, {\n\t\tupsertEntity(id: string, value: TEntity) {\n\t\t\tconst next = copyMap(readMap(entities));\n\t\t\tnext.set(id, value);\n\t\t\tcommitEntities(next);\n\t\t},\n\t\tremoveEntity(id: string) {\n\t\t\tconst nextEntities = copyMap(readMap(entities));\n\t\t\tconst existed = nextEntities.delete(id);\n\t\t\tconst currentEdges = readArray(edges);\n\t\t\tconst nextEdges = currentEdges.filter((edge) => edge.from !== id && edge.to !== id);\n\t\t\tif (!existed && nextEdges.length === currentEdges.length) return;\n\t\t\tcommitEntities(nextEntities);\n\t\t\tcommitEdges(nextEdges);\n\t\t},\n\t\tlink(from: string, to: string, relation: TRelation, weight = 1) {\n\t\t\tconst key = `${from}\\u0000${to}\\u0000${relation}`;\n\t\t\tconst currentEdges = readArray(edges);\n\t\t\tconst existing = new Set(\n\t\t\t\tcurrentEdges.map((edge) => `${edge.from}\\u0000${edge.to}\\u0000${edge.relation}`),\n\t\t\t);\n\t\t\tconst next = [...currentEdges];\n\t\t\tif (existing.has(key)) {\n\t\t\t\tfor (let i = 0; i < next.length; i += 1) {\n\t\t\t\t\tconst edge = next[i]!;\n\t\t\t\t\tif (edge.from === from && edge.to === to && edge.relation === relation) {\n\t\t\t\t\t\tnext[i] = { ...edge, weight };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnext.push({ from, to, relation, weight });\n\t\t\t}\n\t\t\tcommitEdges(next);\n\t\t},\n\t\tunlink(from: string, to: string, relation?: TRelation) {\n\t\t\tconst currentEdges = readArray(edges);\n\t\t\tconst next = currentEdges.filter((edge) =>\n\t\t\t\trelation === undefined\n\t\t\t\t\t? !(edge.from === from && edge.to === to)\n\t\t\t\t\t: !(edge.from === from && edge.to === to && edge.relation === relation),\n\t\t\t);\n\t\t\tif (next.length === currentEdges.length) return;\n\t\t\tcommitEdges(next);\n\t\t},\n\t\trelated(id: string, relation?: TRelation): ReadonlyArray<KnowledgeEdge<TRelation>> {\n\t\t\treturn readArray(edges).filter(\n\t\t\t\t(edge) =>\n\t\t\t\t\t(edge.from === id || edge.to === id) &&\n\t\t\t\t\t(relation === undefined || edge.relation === relation),\n\t\t\t);\n\t\t},\n\t}) as KnowledgeGraphGraph<TEntity, TRelation>;\n\treturn out;\n}\n","/**\n * Shared internal utilities for the patterns layer.\n *\n * These are private helpers used across multiple pattern modules. They are NOT\n * part of the public API — import from `./patterns/index.js` for public exports.\n *\n * General-purpose reactive utilities (`keepalive`, `reactiveCounter`) live in\n * `extra/sources.ts` and are re-exported here for convenience.\n *\n * @internal\n * @module\n */\n\nimport { downWithBatch } from \"../core/batch.js\";\nimport { DATA, DIRTY } from \"../core/messages.js\";\nimport type { Node } from \"../core/node.js\";\nimport { defaultConfig } from \"../core/node.js\";\n\n// Re-export general-purpose utilities from extra (canonical home).\nexport { keepalive, reactiveCounter } from \"../extra/sources.js\";\n\n// ---------------------------------------------------------------------------\n// emitToMeta\n// ---------------------------------------------------------------------------\n\n/**\n * Forward a single `[DATA, value]` to a meta companion node via tier-3\n * deferral, tolerating absent companions. Used by patterns that publish\n * per-wave statistics alongside their main output (cache-hit-rate,\n * segment-count, layout-time-ns, etc.) — subscribers see the parent's\n * DATA first because phase-2 completes before phase-3 during drain.\n *\n * // Expands to: `if (meta) downWithBatch(meta, [[Type, value]])` with null-guard.\n *\n * @internal\n */\nexport function emitToMeta<T>(metaNode: Node<T> | undefined, value: T): void {\n\tif (metaNode == null) return;\n\tdownWithBatch((msgs) => metaNode.down(msgs), [[DATA, value]], defaultConfig.tierOf);\n}\n\n// ---------------------------------------------------------------------------\n// tryIncrementBounded\n// ---------------------------------------------------------------------------\n\n/**\n * Bounded increment for a self-owned counter state node.\n *\n * Reads `counter.cache`, bumps by 1 if under `cap`, writes back. Returns\n * `false` when the cap is reached. Documented P3 exception: the counter is\n * not a declared dep of the caller — it's a private budget read+written from\n * a single call site. This helper keeps the `.cache` access in one named\n * place.\n *\n * **Safety today:**\n * 1. Single-threaded JS runner never invokes the caller concurrently.\n * 2. `counter.down` writes the cache synchronously before returning, so\n * synchronous re-entry through a downstream publish reads the\n * freshly-incremented value — no double-count.\n *\n * **Future risk:** under a free-threaded runner (PY no-GIL or hypothetical\n * concurrent TS runner), two concurrent firings could still race. Revisit\n * when that surfaces.\n *\n * @internal\n */\nexport function tryIncrementBounded(counter: Node<number>, cap: number): boolean {\n\tconst cur = (counter.cache as number | undefined) ?? 0;\n\tif (cur >= cap) return false;\n\tcounter.down([[DIRTY], [DATA, cur + 1]]);\n\treturn true;\n}\n\n// ---------------------------------------------------------------------------\n// domainMeta\n// ---------------------------------------------------------------------------\n\n/**\n * Build a domain metadata object for pattern-layer nodes.\n *\n * Each domain (orchestration, messaging, reduction, ai, cqrs, domain_template)\n * follows the same shape: `{ [domain]: true, [domain]_type: kind, ...extra }`.\n *\n * @param domain - The domain tag (e.g. `\"orchestration\"`, `\"ai\"`, `\"cqrs\"`).\n * @param kind - The specific type within the domain (e.g. `\"gate\"`, `\"prompt\"`).\n * @param extra - Additional metadata to merge.\n * @returns Metadata object.\n *\n * @internal\n */\nexport function domainMeta(\n\tdomain: string,\n\tkind: string,\n\textra?: Record<string, unknown>,\n): Record<string, unknown> {\n\treturn {\n\t\t[domain]: true,\n\t\t[`${domain}_type`]: kind,\n\t\t...(extra ?? {}),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// trackingKey\n// ---------------------------------------------------------------------------\n\n/**\n * Stable tracking key for an item with retry/reingestion decoration.\n *\n * Uses `relatedTo[0]` if present (carries the original key forward through\n * retries and reingestions). Falls back to `summary` for first-time items.\n *\n * This avoids deriving keys from mutated summary strings — retries decorate\n * the summary with `[RETRY N/M]` and failure context, so regex-stripping\n * would be fragile and any new decoration pattern would risk infinite loops\n * by generating novel keys.\n *\n * @internal\n */\nexport function trackingKey(item: { summary: string; relatedTo?: string[] }): string {\n\treturn item.relatedTo?.[0] ?? item.summary;\n}\n","/**\n * Messaging patterns (roadmap §4.2).\n *\n * Pulsar-inspired messaging features modeled as graph factories:\n * - `topic()` for append-only topic streams\n * - `subscription()` for cursor-based consumers\n * - `jobQueue()` for queue claim/ack flow\n */\n\nimport { batch, COMPLETE, DATA, derived, type Node, node, state } from \"../core/index.js\";\nimport { reactiveList } from \"../extra/reactive-list.js\";\nimport { reactiveLog } from \"../extra/reactive-log.js\";\nimport { reactiveMap } from \"../extra/reactive-map.js\";\nimport { Graph, type GraphOptions } from \"../graph/index.js\";\n\nconst DEFAULT_MAX_PER_PUMP = 2_147_483_647;\n\nfunction requireNonNegativeInt(value: number, label: string): number {\n\tif (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {\n\t\tthrow new Error(`${label} must be a non-negative integer`);\n\t}\n\treturn value;\n}\n\nimport { domainMeta, keepalive } from \"./_internal.js\";\n\nfunction messagingMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"messaging\", kind, extra);\n}\n\nexport type TopicOptions = {\n\tgraph?: GraphOptions;\n\tretainedLimit?: number;\n};\n\nexport class TopicGraph<T> extends Graph {\n\tprivate readonly _log;\n\treadonly events: Node<readonly T[]>;\n\t/**\n\t * Most recently published value, or `null` when the topic has no entries\n\t * yet. Spec §5.12 reserves `undefined` as the protocol-internal \"never\n\t * sent DATA\" sentinel — `null` is the idiomatic \"empty / no value\" signal\n\t * for domain nodes. F7.\n\t *\n\t * **Caveat when `T` itself includes `null`** (e.g., `topic<number | null>`):\n\t * `latest === null` is ambiguous — it could mean \"no publish yet\" OR \"a\n\t * `null` value was published\". Use {@link hasLatest} to disambiguate, or\n\t * observe {@link events} directly and track length yourself.\n\t */\n\treadonly latest: Node<T | null>;\n\t/**\n\t * Reactive `true` once the topic has at least one published entry.\n\t * Disambiguates \"`null` never published\" from \"`null` was published\" when\n\t * `T` includes `null`.\n\t */\n\treadonly hasLatest: Node<boolean>;\n\n\tconstructor(name: string, opts: TopicOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\tthis._log = reactiveLog<T>([], { name: \"events\", maxSize: opts.retainedLimit });\n\t\tthis.events = this._log.entries;\n\t\tthis.add(\"events\", this.events);\n\t\tthis.latest = derived<T | null>(\n\t\t\t[this.events],\n\t\t\t([snapshot]) => {\n\t\t\t\tconst entries = snapshot as readonly T[];\n\t\t\t\treturn entries.length === 0 ? null : (entries[entries.length - 1] as T);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"latest\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: messagingMeta(\"topic_latest\"),\n\t\t\t},\n\t\t);\n\t\tthis.add(\"latest\", this.latest);\n\t\tthis.addDisposer(keepalive(this.latest));\n\n\t\tthis.hasLatest = derived<boolean>(\n\t\t\t[this.events],\n\t\t\t([snapshot]) => (snapshot as readonly T[]).length > 0,\n\t\t\t{\n\t\t\t\tname: \"hasLatest\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: messagingMeta(\"topic_has_latest\"),\n\t\t\t},\n\t\t);\n\t\tthis.add(\"hasLatest\", this.hasLatest);\n\t\tthis.addDisposer(keepalive(this.hasLatest));\n\n\t\t// D1(a): on teardown, propagate COMPLETE on `events` so downstream\n\t\t// derived chains (including any externally-held SubscriptionGraph\n\t\t// sources) see the termination via their `terminalDeps` and can stop\n\t\t// serving stale caches. Tier-3 terminal per spec §2.2.\n\t\tthis.addDisposer(() => {\n\t\t\tthis.events.down([[COMPLETE]]);\n\t\t});\n\t\t// P9: release any memoized tail/slice view keepalives held by the log.\n\t\t// TopicGraph itself doesn't call log.tail/slice, but plugins may have\n\t\t// attached views via `_log` — defensive.\n\t\tthis.addDisposer(() => this._log.disposeAllViews());\n\t}\n\n\tpublish(value: T): void {\n\t\tthis._log.append(value);\n\t}\n\n\tretained(): readonly T[] {\n\t\treturn this.events.cache as readonly T[];\n\t}\n}\n\nexport type SubscriptionOptions = {\n\tgraph?: GraphOptions;\n\tcursor?: number;\n};\n\nexport class SubscriptionGraph<T> extends Graph {\n\treadonly source: Node<readonly T[]>;\n\treadonly cursor: Node<number>;\n\treadonly available: Node<readonly T[]>;\n\t/**\n\t * Reference to the upstream topic graph. Intentionally NOT mounted\n\t * under this subscription: a subscription is a VIEW over an\n\t * externally-owned topic. Double-mounting (e.g. hub-owned topic +\n\t * sub-mount here) would make either-side teardown leave the other\n\t * holding a dead reference. Node-level `derived([topicEvents], …)`\n\t * still wires the data dependency across graph boundaries. D1(e).\n\t */\n\treadonly topic: TopicGraph<T>;\n\n\tconstructor(name: string, topicGraph: TopicGraph<T>, opts: SubscriptionOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\tconst initialCursor = requireNonNegativeInt(opts.cursor ?? 0, \"subscription cursor\");\n\t\tthis.topic = topicGraph;\n\t\tconst topicEvents = topicGraph.events;\n\t\tthis.source = derived([topicEvents], ([snapshot]) => snapshot as readonly T[], {\n\t\t\tname: \"source\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: messagingMeta(\"subscription_source\"),\n\t\t\tinitial: topicEvents.cache as readonly T[],\n\t\t});\n\t\tthis.add(\"source\", this.source);\n\t\tthis.cursor = state(initialCursor, {\n\t\t\tname: \"cursor\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: messagingMeta(\"subscription_cursor\"),\n\t\t});\n\t\tthis.add(\"cursor\", this.cursor);\n\t\tthis.available = derived(\n\t\t\t[this.source, this.cursor],\n\t\t\t([sourceSnapshot, cursor]) => {\n\t\t\t\tconst entries = sourceSnapshot as readonly T[];\n\t\t\t\tconst start = Math.max(0, Math.trunc((cursor as number) ?? 0));\n\t\t\t\treturn entries.slice(start);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"available\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: messagingMeta(\"subscription_available\"),\n\t\t\t\tinitial: [],\n\t\t\t},\n\t\t);\n\t\tthis.add(\"available\", this.available);\n\t\t// No `connect(\"topic::events\", \"source\")` — topic is not mounted here.\n\t\t// The node-level dep `derived([topicEvents], …)` above is the live wire.\n\t\tthis.addDisposer(keepalive(this.source));\n\t\tthis.addDisposer(keepalive(this.available));\n\t}\n\n\tack(count?: number): number {\n\t\tconst available = this.available.cache as readonly T[];\n\t\tconst requested =\n\t\t\tcount === undefined\n\t\t\t\t? available.length\n\t\t\t\t: requireNonNegativeInt(count, \"subscription ack count\");\n\t\tconst step = Math.min(requested, available.length);\n\t\tif (step <= 0) return this.cursor.cache as number;\n\t\tconst next = (this.cursor.cache as number) + step;\n\t\t// F8: use emit() so the pipeline auto-prefixes DIRTY, runs equals\n\t\t// substitution, and produces a proper two-phase wave (the raw\n\t\t// `down([[DATA, next]])` path bypassed those contracts).\n\t\tthis.cursor.emit(next);\n\t\treturn next;\n\t}\n\n\tpull(limit?: number, opts: { ack?: boolean } = {}): readonly T[] {\n\t\tconst available = this.available.cache as readonly T[];\n\t\tconst max =\n\t\t\tlimit === undefined\n\t\t\t\t? available.length\n\t\t\t\t: requireNonNegativeInt(limit, \"subscription pull limit\");\n\t\tconst out = available.slice(0, max);\n\t\tif (opts.ack && out.length > 0) this.ack(out.length);\n\t\treturn out;\n\t}\n}\n\nexport type JobState = \"queued\" | \"inflight\";\n\nexport type JobEnvelope<T> = {\n\tid: string;\n\tpayload: T;\n\tattempts: number;\n\tmetadata: Readonly<Record<string, unknown>>;\n\tstate: JobState;\n};\n\nexport type JobQueueOptions = {\n\tgraph?: GraphOptions;\n};\n\nexport class JobQueueGraph<T> extends Graph {\n\tprivate readonly _pending;\n\tprivate readonly _jobs;\n\tprivate _seq = 0;\n\treadonly pending: Node<readonly string[]>;\n\treadonly jobs: Node<ReadonlyMap<string, JobEnvelope<T>>>;\n\treadonly depth: Node<number>;\n\n\tconstructor(name: string, opts: JobQueueOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\tthis._pending = reactiveList<string>([], { name: \"pending\" });\n\t\tthis._jobs = reactiveMap<string, JobEnvelope<T>>({ name: \"jobs\" });\n\t\tthis.pending = this._pending.items;\n\t\tthis.jobs = this._jobs.entries;\n\t\tthis.add(\"pending\", this.pending);\n\t\tthis.add(\"jobs\", this.jobs);\n\t\tthis.depth = derived([this.pending], ([snapshot]) => (snapshot as readonly string[]).length, {\n\t\t\tname: \"depth\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: messagingMeta(\"queue_depth\"),\n\t\t\tinitial: 0,\n\t\t});\n\t\tthis.add(\"depth\", this.depth);\n\t\tthis.addDisposer(keepalive(this.depth));\n\t}\n\n\tenqueue(payload: T, opts: { id?: string; metadata?: Record<string, unknown> } = {}): string {\n\t\tconst id = opts.id ?? `${this.name}-${++this._seq}`;\n\t\tif (this._jobs.get(id) !== undefined) {\n\t\t\tthrow new Error(`jobQueue(\"${this.name}\"): duplicate job id \"${id}\"`);\n\t\t}\n\t\tconst job: JobEnvelope<T> = {\n\t\t\tid,\n\t\t\tpayload,\n\t\t\tattempts: 0,\n\t\t\tmetadata: Object.freeze({ ...(opts.metadata ?? {}) }),\n\t\t\tstate: \"queued\",\n\t\t};\n\t\tthis._jobs.set(id, job);\n\t\tthis._pending.append(id);\n\t\treturn id;\n\t}\n\n\tclaim(limit = 1): readonly JobEnvelope<T>[] {\n\t\tconst max = requireNonNegativeInt(limit, \"job queue claim limit\");\n\t\tif (max === 0) return [];\n\t\tconst out: JobEnvelope<T>[] = [];\n\t\twhile (out.length < max) {\n\t\t\tconst ids = this.pending.cache as readonly string[];\n\t\t\tif (ids.length === 0) break;\n\t\t\tconst id = this._pending.pop(0);\n\t\t\tconst job = this._jobs.get(id);\n\t\t\tif (!job || job.state !== \"queued\") continue;\n\t\t\tconst inflight: JobEnvelope<T> = {\n\t\t\t\t...job,\n\t\t\t\tstate: \"inflight\",\n\t\t\t\tattempts: job.attempts + 1,\n\t\t\t};\n\t\t\tthis._jobs.set(id, inflight);\n\t\t\tout.push(inflight);\n\t\t}\n\t\treturn out;\n\t}\n\n\tack(id: string): boolean {\n\t\tconst job = this._jobs.get(id);\n\t\tif (!job || job.state !== \"inflight\") return false;\n\t\tthis._jobs.delete(id);\n\t\treturn true;\n\t}\n\n\tnack(id: string, opts: { requeue?: boolean } = {}): boolean {\n\t\tconst job = this._jobs.get(id);\n\t\tif (!job || job.state !== \"inflight\") return false;\n\t\tif (opts.requeue ?? true) {\n\t\t\tthis._jobs.set(id, { ...job, state: \"queued\" });\n\t\t\tthis._pending.append(id);\n\t\t\treturn true;\n\t\t}\n\t\tthis._jobs.delete(id);\n\t\treturn true;\n\t}\n}\n\nexport type JobFlowOptions = {\n\tgraph?: GraphOptions;\n\tstages?: readonly string[];\n\tmaxPerPump?: number;\n};\n\nexport class JobFlowGraph<T> extends Graph {\n\tprivate readonly _stageNames: readonly string[];\n\tprivate readonly _queues = new Map<string, JobQueueGraph<T>>();\n\tprivate readonly _completed;\n\treadonly completed: Node<readonly JobEnvelope<T>[]>;\n\treadonly completedCount: Node<number>;\n\n\tconstructor(name: string, opts: JobFlowOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\tconst stages = (opts.stages ?? [\"incoming\", \"processing\", \"done\"]).map((v) => v.trim());\n\t\tif (stages.length < 2) {\n\t\t\tthrow new Error(`jobFlow(\"${name}\"): requires at least 2 stages`);\n\t\t}\n\t\tconst unique = new Set(stages);\n\t\tif (unique.size !== stages.length) {\n\t\t\tthrow new Error(`jobFlow(\"${name}\"): stage names must be unique`);\n\t\t}\n\t\tthis._stageNames = Object.freeze([...stages]);\n\t\tfor (const stage of this._stageNames) {\n\t\t\tconst q = jobQueue<T>(`${name}-${stage}`);\n\t\t\tthis._queues.set(stage, q);\n\t\t\tthis.mount(stage, q);\n\t\t}\n\t\tthis._completed = reactiveLog<JobEnvelope<T>>([], { name: \"completed\" });\n\t\tthis.completed = this._completed.entries;\n\t\tthis.add(\"completed\", this.completed);\n\t\tthis.completedCount = derived(\n\t\t\t[this.completed],\n\t\t\t([snapshot]) => (snapshot as readonly JobEnvelope<T>[]).length,\n\t\t\t{\n\t\t\t\tname: \"completedCount\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: messagingMeta(\"job_flow_completed_count\"),\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t);\n\t\tthis.add(\"completedCount\", this.completedCount);\n\t\tthis.addDisposer(keepalive(this.completedCount));\n\n\t\tconst maxPerPump = Math.max(\n\t\t\t1,\n\t\t\trequireNonNegativeInt(opts.maxPerPump ?? DEFAULT_MAX_PER_PUMP, \"job flow maxPerPump\"),\n\t\t);\n\t\tfor (let i = 0; i < this._stageNames.length; i += 1) {\n\t\t\tconst stage = this._stageNames[i] as string;\n\t\t\tconst current = this.queue(stage);\n\t\t\tconst next =\n\t\t\t\ti + 1 < this._stageNames.length ? this.queue(this._stageNames[i + 1] as string) : null;\n\t\t\tconst pump = node<unknown>(\n\t\t\t\t[current.pending],\n\t\t\t\t() => {\n\t\t\t\t\tlet moved = 0;\n\t\t\t\t\twhile (moved < maxPerPump) {\n\t\t\t\t\t\tconst claim = current.claim(1);\n\t\t\t\t\t\tif (claim.length === 0) break;\n\t\t\t\t\t\tconst job = claim[0] as JobEnvelope<T>;\n\t\t\t\t\t\tif (!job) break;\n\t\t\t\t\t\tif (next) {\n\t\t\t\t\t\t\tnext.enqueue(job.payload, {\n\t\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t\t...job.metadata,\n\t\t\t\t\t\t\t\t\tjob_flow_from: stage,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis._completed.append(job);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcurrent.ack(job.id);\n\t\t\t\t\t\tmoved += 1;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: `pump_${stage}`,\n\t\t\t\t\tdescribeKind: \"effect\",\n\t\t\t\t\tmeta: messagingMeta(\"job_flow_pump\"),\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.add(`pump_${stage}`, pump);\n\t\t\tthis.addDisposer(keepalive(pump));\n\t\t}\n\t}\n\n\tstages(): readonly string[] {\n\t\treturn this._stageNames;\n\t}\n\n\tqueue(stage: string): JobQueueGraph<T> {\n\t\tconst q = this._queues.get(stage);\n\t\tif (!q) throw new Error(`jobFlow(\"${this.name}\"): unknown stage \"${stage}\"`);\n\t\treturn q;\n\t}\n\n\tenqueue(payload: T, opts: { id?: string; metadata?: Record<string, unknown> } = {}): string {\n\t\treturn this.queue(this._stageNames[0] as string).enqueue(payload, opts);\n\t}\n\n\tretainedCompleted(): readonly JobEnvelope<T>[] {\n\t\treturn this.completed.cache as readonly JobEnvelope<T>[];\n\t}\n}\n\nexport type TopicBridgeOptions<TIn, TOut> = {\n\tgraph?: GraphOptions;\n\tcursor?: number;\n\tmaxPerPump?: number;\n\tmap?: (value: TIn) => TOut | undefined;\n};\n\nexport class TopicBridgeGraph<TIn, TOut = TIn> extends Graph {\n\tprivate readonly _sourceSub;\n\tprivate readonly _target;\n\treadonly bridgedCount: Node<number>;\n\n\tconstructor(\n\t\tname: string,\n\t\tsourceTopic: TopicGraph<TIn>,\n\t\ttargetTopic: TopicGraph<TOut>,\n\t\topts: TopicBridgeOptions<TIn, TOut> = {},\n\t) {\n\t\tsuper(name, opts.graph);\n\t\tthis._sourceSub = subscription<TIn>(`${name}-subscription`, sourceTopic, {\n\t\t\tcursor: opts.cursor,\n\t\t});\n\t\tthis._target = targetTopic;\n\t\tthis.mount(\"subscription\", this._sourceSub);\n\t\tthis.bridgedCount = state(0, {\n\t\t\tname: \"bridgedCount\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: messagingMeta(\"topic_bridge_count\"),\n\t\t});\n\t\tthis.add(\"bridgedCount\", this.bridgedCount);\n\n\t\tconst maxPerPump = Math.max(\n\t\t\t1,\n\t\t\trequireNonNegativeInt(opts.maxPerPump ?? DEFAULT_MAX_PER_PUMP, \"topic bridge maxPerPump\"),\n\t\t);\n\t\tconst mapValue = opts.map ?? ((value: TIn) => value as unknown as TOut);\n\t\tconst pump = node<unknown>(\n\t\t\t[this._sourceSub.available],\n\t\t\t() => {\n\t\t\t\tconst available = this._sourceSub.pull(maxPerPump, { ack: true });\n\t\t\t\tif (available.length === 0) return;\n\t\t\t\tlet bridged = 0;\n\t\t\t\tfor (const value of available) {\n\t\t\t\t\tconst mapped = mapValue(value as TIn);\n\t\t\t\t\tif (mapped === undefined) continue;\n\t\t\t\t\tthis._target.publish(mapped);\n\t\t\t\t\tbridged += 1;\n\t\t\t\t}\n\t\t\t\tif (bridged > 0) {\n\t\t\t\t\tconst current = this.bridgedCount.cache as number;\n\t\t\t\t\tthis.bridgedCount.down([[DATA, current + bridged]]);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"pump\",\n\t\t\t\tdescribeKind: \"effect\",\n\t\t\t\tmeta: messagingMeta(\"topic_bridge_pump\"),\n\t\t\t},\n\t\t);\n\t\tthis.add(\"pump\", pump);\n\t\tthis.addDisposer(keepalive(pump));\n\t}\n}\n\n// ── MessagingHubGraph ─────────────────────────────────────────────────────\n\nexport type MessagingHubOptions = {\n\tgraph?: GraphOptions;\n\t/**\n\t * Default `TopicOptions` applied to every topic created via `topic(name)`\n\t * without explicit options. Per-call opts override. Default: `{}`\n\t * (unbounded retention per topic unless `retainedLimit` is set per call).\n\t */\n\tdefaultTopicOptions?: TopicOptions;\n};\n\n/**\n * Lazy Pulsar-inspired topic registry. Manages a named set of {@link TopicGraph}\n * instances with retention + cursor semantics. Topics are created on first\n * access; `removeTopic(name)` unmounts and tears down via {@link Graph.remove}.\n *\n * **Relationship to `pubsub()` in `src/extra/pubsub.ts`:** `pubsub` is a\n * lightweight last-value state hub (no retention, no cursors). `MessagingHubGraph`\n * is the full messaging hub — retained message logs, cursor-based subscriptions,\n * and pattern-layer lifecycle management.\n *\n * @category patterns\n */\nexport class MessagingHubGraph extends Graph {\n\tprivate readonly _topics = new Map<string, TopicGraph<unknown>>();\n\tprivate _version = 0;\n\tprivate readonly _defaultTopicOptions: TopicOptions;\n\n\tconstructor(name: string, opts: MessagingHubOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\t// P8: shallow-copy caller-provided defaults so post-construction\n\t\t// mutations by the caller don't leak into every future `topic()` call.\n\t\tthis._defaultTopicOptions = { ...(opts.defaultTopicOptions ?? {}) };\n\t}\n\n\t/** Monotonic counter advancing on topic create/remove. */\n\tget version(): number {\n\t\treturn this._version;\n\t}\n\n\t/** Number of topics currently in the hub. */\n\tget size(): number {\n\t\treturn this._topics.size;\n\t}\n\n\t/** Checks topic existence without creating. */\n\thas(name: string): boolean {\n\t\treturn this._topics.has(name);\n\t}\n\n\t/** Iterator over topic names. */\n\ttopicNames(): IterableIterator<string> {\n\t\treturn this._topics.keys();\n\t}\n\n\t/**\n\t * Returns the {@link TopicGraph} for `name`, creating lazily on first call.\n\t * Subsequent calls with the same name return the same instance (options on\n\t * repeat calls are ignored — the topic is already configured).\n\t */\n\ttopic<T = unknown>(name: string, opts?: TopicOptions): TopicGraph<T> {\n\t\tlet t = this._topics.get(name) as TopicGraph<T> | undefined;\n\t\tif (t === undefined) {\n\t\t\tconst effective: TopicOptions = { ...this._defaultTopicOptions, ...(opts ?? {}) };\n\t\t\tt = new TopicGraph<T>(name, effective);\n\t\t\tthis._topics.set(name, t as TopicGraph<unknown>);\n\t\t\tthis.mount(name, t);\n\t\t\tthis._version += 1;\n\t\t}\n\t\treturn t;\n\t}\n\n\t/**\n\t * Publishes a value to the topic, lazily creating it on first publish.\n\t *\n\t * **Late-subscriber caveat:** the topic is created lazily, so subscribers\n\t * that attach AFTER a publish only see the retained window (governed by\n\t * `retainedLimit` on `TopicOptions` / `defaultTopicOptions`). If\n\t * `retainedLimit === 0` is set explicitly, early publishes are\n\t * effectively dropped — prefer an unset `retainedLimit` (unbounded\n\t * retention) or subscribe before publishing when late-subscribers matter.\n\t */\n\tpublish<T = unknown>(name: string, value: T): void {\n\t\tthis.topic<T>(name).publish(value);\n\t}\n\n\t/**\n\t * Bulk publish — issues all publishes inside one outer batch. New topics\n\t * are created on demand. No-op if `entries` yields nothing.\n\t *\n\t * **Iterable consumption (F6):** `entries` is consumed once (single-pass)\n\t * INSIDE the batch frame. If the iterator throws mid-way, the batch is\n\t * discarded and NO publishes are visible to subscribers (all-or-nothing).\n\t * Pass an array or `Set` for multi-shot callers.\n\t */\n\tpublishMany(entries: Iterable<[string, unknown]>): void {\n\t\t// P2: iterate inside batch — no `[...entries]` materialization so large\n\t\t// / infinite iterables don't OOM, and iterator throws are contained.\n\t\tbatch(() => {\n\t\t\tfor (const [name, value] of entries) {\n\t\t\t\tthis.topic(name).publish(value);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Creates a {@link SubscriptionGraph} over a named topic. The topic is\n\t * lazily created if missing. Subscription lifecycle is owned by the caller —\n\t * the hub does NOT mount the subscription.\n\t *\n\t * @param subName - Local name for the subscription graph.\n\t * @param topicName - Hub topic to subscribe to.\n\t * @param opts - `SubscriptionOptions` (initial cursor, etc.).\n\t */\n\tsubscribe<T = unknown>(\n\t\tsubName: string,\n\t\ttopicName: string,\n\t\topts?: SubscriptionOptions,\n\t): SubscriptionGraph<T> {\n\t\tconst t = this.topic<T>(topicName);\n\t\treturn new SubscriptionGraph<T>(subName, t, opts);\n\t}\n\n\t/**\n\t * Unmounts and tears down the topic's graph. Returns `true` if the topic\n\t * existed. Subscribers receive `TEARDOWN` via {@link Graph.remove}.\n\t */\n\tremoveTopic(name: string): boolean {\n\t\tif (!this._topics.has(name)) return false;\n\t\t// P1 / P3: Graph.remove first — if it throws, `_topics` must NOT still\n\t\t// hold the broken half-disposed topic (otherwise the next\n\t\t// `hub.topic(name)` returns the corrupted reference). Wrap in\n\t\t// try/finally so `_topics` / `_version` converge to a consistent state\n\t\t// regardless of whether `remove` throws. Mount-orphan safety is\n\t\t// preserved by removing before deleting.\n\t\ttry {\n\t\t\tthis.remove(name); // unmounts, drops edges, tears down\n\t\t} finally {\n\t\t\tthis._topics.delete(name);\n\t\t\tthis._version += 1;\n\t\t}\n\t\treturn true;\n\t}\n}\n\n/**\n * Creates a Pulsar-inspired topic graph (append-only retained stream + latest value).\n */\nexport function topic<T>(name: string, opts?: TopicOptions): TopicGraph<T> {\n\treturn new TopicGraph<T>(name, opts);\n}\n\n/**\n * Creates a lazy Pulsar-inspired messaging hub. Topics are created on first access\n * via `hub.topic(name)`; `hub.publish(name, value)` shortcuts through the registry.\n *\n * @example\n * ```ts\n * import { messagingHub } from \"@graphrefly/graphrefly-ts\";\n *\n * const hub = messagingHub(\"main\", { defaultTopicOptions: { retainedLimit: 256 } });\n * hub.publish(\"orders\", { id: 1 });\n * hub.publishMany([[\"shipments\", { id: 1 }], [\"orders\", { id: 2 }]]);\n * const sub = hub.subscribe(\"orders-worker\", \"orders\", { cursor: 0 });\n * ```\n */\nexport function messagingHub(name: string, opts?: MessagingHubOptions): MessagingHubGraph {\n\treturn new MessagingHubGraph(name, opts);\n}\n\n/**\n * Creates a cursor-based subscription graph over a topic.\n */\nexport function subscription<T>(\n\tname: string,\n\ttopicGraph: TopicGraph<T>,\n\topts?: SubscriptionOptions,\n): SubscriptionGraph<T> {\n\treturn new SubscriptionGraph<T>(name, topicGraph, opts);\n}\n\n/**\n * Creates a Pulsar-inspired job queue graph with claim/ack/nack workflow.\n */\nexport function jobQueue<T>(name: string, opts?: JobQueueOptions): JobQueueGraph<T> {\n\treturn new JobQueueGraph<T>(name, opts);\n}\n\n/**\n * Creates an autonomous multi-stage queue chain graph.\n */\nexport function jobFlow<T>(name: string, opts?: JobFlowOptions): JobFlowGraph<T> {\n\treturn new JobFlowGraph<T>(name, opts);\n}\n\n/**\n * Creates an autonomous cursor-based topic relay graph.\n */\nexport function topicBridge<TIn, TOut = TIn>(\n\tname: string,\n\tsourceTopic: TopicGraph<TIn>,\n\ttargetTopic: TopicGraph<TOut>,\n\topts?: TopicBridgeOptions<TIn, TOut>,\n): TopicBridgeGraph<TIn, TOut> {\n\treturn new TopicBridgeGraph<TIn, TOut>(name, sourceTopic, targetTopic, opts);\n}\n","/**\n * Orchestration patterns (roadmap §4.1).\n *\n * Domain-layer helpers that build workflow shapes on top of core + extra primitives.\n * Exported under the `patterns.orchestration` namespace to avoid collisions with\n * Phase 2 operator names (for example `gate`, `forEach`).\n */\n\nimport { batch } from \"../core/batch.js\";\nimport type { NodeActions } from \"../core/config.js\";\nimport { COMPLETE, DATA, ERROR, type Messages, RESOLVED } from \"../core/messages.js\";\nimport { type Node, type NodeFn, type NodeOptions, node } from \"../core/node.js\";\nimport { type DerivedFn, derived, state } from \"../core/sugar.js\";\nimport { GRAPH_META_SEGMENT, Graph, type GraphOptions } from \"../graph/graph.js\";\n\nexport type StepRef = string | Node<unknown>;\n\ntype OrchestrationMeta = {\n\torchestration?: true;\n\torchestration_type?: string;\n};\n\nexport type OrchestrationStepOptions = Omit<\n\tNodeOptions<unknown>,\n\t\"describeKind\" | \"name\" | \"meta\"\n> & {\n\tdeps?: ReadonlyArray<StepRef>;\n\tmeta?: Record<string, unknown> & OrchestrationMeta;\n};\n\nexport type BranchResult<T> = {\n\tbranch: \"then\" | \"else\";\n\tvalue: T;\n};\n\nexport type SensorControls<T> = {\n\tnode: Node<T>;\n\tpush(value: T): void;\n\terror(err: unknown): void;\n\tcomplete(): void;\n};\n\nexport type LoopOptions = Omit<OrchestrationStepOptions, \"deps\"> & {\n\titerations?: number | StepRef;\n};\n\nexport type WaitOptions = Omit<OrchestrationStepOptions, \"deps\">;\n\nexport type SubPipelineBuilder = (sub: Graph) => void;\n\nfunction resolveDep(graph: Graph, dep: StepRef): { node: Node<unknown>; path?: string } {\n\tif (typeof dep === \"string\") {\n\t\treturn { node: graph.resolve(dep), path: dep };\n\t}\n\tconst path = findRegisteredNodePath(graph, dep);\n\tif (!path) {\n\t\tthrow new Error(\n\t\t\t\"orchestration dep node must already be registered in the graph so explicit edges can be recorded; pass a string path or register the node first\",\n\t\t);\n\t}\n\treturn { node: dep, path };\n}\n\nfunction findRegisteredNodePath(graph: Graph, target: Node<unknown>): string | undefined {\n\tconst described = graph.describe();\n\tconst metaSegment = `::${GRAPH_META_SEGMENT}::`;\n\tfor (const path of Object.keys(described.nodes).sort()) {\n\t\tif (path.includes(metaSegment)) continue;\n\t\ttry {\n\t\t\tif (graph.resolve(path) === target) return path;\n\t\t} catch {\n\t\t\t/* ignore stale path while scanning */\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction registerStep(\n\tgraph: Graph,\n\tname: string,\n\tstep: Node<unknown>,\n\tdepPaths: ReadonlyArray<string>,\n): void {\n\tgraph.add(name, step);\n\t// depPaths used to drive graph.connect() edge-registry calls; after\n\t// Unit 7 edges are derived from node _deps and this wiring is a no-op.\n\tvoid depPaths;\n}\n\nimport { domainMeta } from \"./_internal.js\";\n\nfunction baseMeta(kind: string, meta?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"orchestration\", kind, meta);\n}\n\nfunction coerceLoopIterations(raw: unknown): number {\n\tconst parseString = (value: string): number => {\n\t\tconst trimmed = value.trim();\n\t\tif (trimmed.length === 0) return 0;\n\t\treturn Number(trimmed);\n\t};\n\tlet parsed: number;\n\tif (typeof raw === \"string\") {\n\t\tparsed = parseString(raw);\n\t} else if (raw === null) {\n\t\tparsed = 0;\n\t} else {\n\t\tparsed = Number(raw);\n\t}\n\tif (!Number.isFinite(parsed)) return 1;\n\treturn Math.max(0, Math.trunc(parsed));\n}\n\n/**\n * Creates an orchestration graph container.\n */\nexport function pipeline(name: string, opts?: GraphOptions): Graph {\n\treturn new Graph(name, opts);\n}\n\n/**\n * Registers a workflow task node.\n */\nexport function task<T>(\n\tgraph: Graph,\n\tname: string,\n\trun: DerivedFn<T>,\n\topts?: OrchestrationStepOptions,\n): Node<T> {\n\tconst depRefs = opts?.deps ?? [];\n\tconst deps = depRefs.map((dep) => resolveDep(graph, dep));\n\tconst { deps: _deps, ...nodeOpts } = opts ?? {};\n\tconst wrapped: NodeFn = (batchData, actions, ctx) => {\n\t\tconst data = batchData.map((batch, i) =>\n\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t);\n\t\tactions.emit(run(data, ctx));\n\t\treturn undefined;\n\t};\n\tconst step = node<T>(\n\t\tdeps.map((d) => d.node),\n\t\twrapped,\n\t\t{\n\t\t\t...nodeOpts,\n\t\t\tname,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"task\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\tregisterStep(\n\t\tgraph,\n\t\tname,\n\t\tstep as unknown as Node<unknown>,\n\t\tdeps.flatMap((d) => (d.path ? [d.path] : [])),\n\t);\n\treturn step;\n}\n\n/**\n * Emits tagged branch outcomes (`then` / `else`) for each source value.\n */\nexport function branch<T>(\n\tgraph: Graph,\n\tname: string,\n\tsource: StepRef,\n\tpredicate: (value: T) => boolean,\n\topts?: Omit<OrchestrationStepOptions, \"deps\">,\n): Node<BranchResult<T>> {\n\tconst src = resolveDep(graph, source);\n\tconst step = derived<BranchResult<T>>(\n\t\t[src.node],\n\t\t([value]) => ({\n\t\t\tbranch: predicate(value as T) ? \"then\" : \"else\",\n\t\t\tvalue: value as T,\n\t\t}),\n\t\t{\n\t\t\t...opts,\n\t\t\tname,\n\t\t\tmeta: baseMeta(\"branch\", opts?.meta),\n\t\t} as NodeOptions<BranchResult<T>>,\n\t);\n\tregisterStep(graph, name, step as unknown as Node<unknown>, src.path ? [src.path] : []);\n\treturn step;\n}\n\n/**\n * Forwards source values only while `control` is truthy.\n */\nexport function valve<T>(\n\tgraph: Graph,\n\tname: string,\n\tsource: StepRef,\n\tcontrol: StepRef,\n\topts?: Omit<OrchestrationStepOptions, \"deps\">,\n): Node<T> {\n\tconst src = resolveDep(graph, source);\n\tconst ctrl = resolveDep(graph, control);\n\t// Raw node so we can emit RESOLVED (hold) instead of DATA(undefined) when closed.\n\tconst step = node<T>(\n\t\t[src.node, ctrl.node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst batch0 = batchData[0];\n\t\t\tconst batch1 = batchData[1];\n\t\t\t// undefined = control never sent DATA (closed); falsy = explicitly closed.\n\t\t\tconst ctrlVal = batch1 != null && batch1.length > 0 ? batch1.at(-1) : ctx.prevData[1];\n\t\t\t// Control just opened and no new source data this wave: re-emit last source value.\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\tif (batch1 != null && batch1.length > 0 && ctrlVal && ctx.prevData[0] !== undefined) {\n\t\t\t\t\tactions.emit(ctx.prevData[0] as T);\n\t\t\t\t} else {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!ctrlVal) {\n\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0 as T[]) actions.emit(v);\n\t\t},\n\t\t{\n\t\t\t...opts,\n\t\t\tname,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"valve\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\tregisterStep(\n\t\tgraph,\n\t\tname,\n\t\tstep as unknown as Node<unknown>,\n\t\t[src.path, ctrl.path].filter((v): v is string => typeof v === \"string\"),\n\t);\n\treturn step;\n}\n\nexport type ApprovalOptions = Omit<OrchestrationStepOptions, \"deps\"> & {\n\tisApproved?: (value: unknown) => boolean;\n};\n\n/**\n * Human/LLM approval gate over a source value.\n */\nexport function approval<T>(\n\tgraph: Graph,\n\tname: string,\n\tsource: StepRef,\n\tapprover: StepRef,\n\topts?: ApprovalOptions,\n): Node<T> {\n\tconst src = resolveDep(graph, source);\n\tconst ctrl = resolveDep(graph, approver);\n\tconst isApproved = opts?.isApproved ?? ((value: unknown) => Boolean(value));\n\t// Raw node so we can emit RESOLVED (hold) instead of DATA(undefined) when not approved.\n\tconst step = node<T>(\n\t\t[src.node, ctrl.node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst batch0 = batchData[0];\n\t\t\tconst batch1 = batchData[1];\n\t\t\t// undefined = approver never sent DATA (not yet approved).\n\t\t\tconst ctrlVal = batch1 != null && batch1.length > 0 ? batch1.at(-1) : ctx.prevData[1];\n\t\t\tif (ctrlVal === undefined || !isApproved(ctrlVal)) {\n\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\t// Approval just granted and no new source data: re-emit last source value.\n\t\t\t\tif (batch1 != null && batch1.length > 0 && ctx.prevData[0] !== undefined) {\n\t\t\t\t\tactions.emit(ctx.prevData[0] as T);\n\t\t\t\t} else {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0 as T[]) actions.emit(v);\n\t\t},\n\t\t{\n\t\t\t...opts,\n\t\t\tname,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"approval\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\tregisterStep(\n\t\tgraph,\n\t\tname,\n\t\tstep as unknown as Node<unknown>,\n\t\t[src.path, ctrl.path].filter((v): v is string => typeof v === \"string\"),\n\t);\n\treturn step;\n}\n\n// ---------------------------------------------------------------------------\n// gate — human-in-the-loop approval with pending queue\n// ---------------------------------------------------------------------------\n\nexport interface GateOptions {\n\t/** Maximum queue size. Oldest values are FIFO-dropped when exceeded. Default: Infinity. */\n\tmaxPending?: number;\n\t/** Start in open mode (auto-approve). Default: false. */\n\tstartOpen?: boolean;\n\tmeta?: Record<string, unknown>;\n}\n\n/** Control surface returned by {@link gate}. */\nexport interface GateController<T> {\n\t/** The output node registered in the graph (subscribe to receive approved values). */\n\tnode: Node<T>;\n\t/** Reactive queue of values waiting for approval. */\n\tpending: Node<T[]>;\n\t/** Derived count of pending items. */\n\tcount: Node<number>;\n\t/** Whether the gate is currently open (auto-approving). */\n\tisOpen: Node<boolean>;\n\t/** Approve and forward the next `count` pending values (default: 1). */\n\tapprove(count?: number): void;\n\t/** Reject (discard) the next `count` pending values (default: 1). */\n\treject(count?: number): void;\n\t/**\n\t * Transform and forward `count` pending values (default: 1).\n\t * `fn` receives `(value, index, pending)` — Array.map-style.\n\t */\n\tmodify(fn: (value: T, index: number, pending: readonly T[]) => T, count?: number): void;\n\t/** Flush all pending values and auto-approve future values. */\n\topen(): void;\n\t/** Re-enable manual gating (stop auto-approving). */\n\tclose(): void;\n}\n\n/**\n * Human-in-the-loop gate: queues incoming values from `source` and lets an external\n * controller {@link GateController.approve approve}, {@link GateController.reject reject},\n * or {@link GateController.modify modify} them before forwarding downstream.\n *\n * Observable surfaces (`pending`, `count`, `isOpen`) are reactive nodes registered in\n * the graph. The gate output node is also registered.\n */\nexport function gate<T>(\n\tgraph: Graph,\n\tname: string,\n\tsource: StepRef,\n\topts?: GateOptions,\n): GateController<T> {\n\tconst maxPending = opts?.maxPending ?? Infinity;\n\tif (maxPending < 1 && maxPending !== Infinity) {\n\t\tthrow new RangeError(\"gate: maxPending must be >= 1\");\n\t}\n\tconst startOpen = opts?.startOpen ?? false;\n\n\tconst src = resolveDep(graph, source);\n\n\t// Internal reactive state\n\tconst pendingNode = state<T[]>([], { name: \"pending\", equals: () => false });\n\tconst isOpenNode = state<boolean>(startOpen, { name: \"isOpen\" });\n\tconst countNode = derived<number>([pendingNode], ([arr]) => (arr as T[]).length, {\n\t\tname: \"count\",\n\t});\n\n\tlet queue: T[] = [];\n\tlet torn = false;\n\t// Capture `isOpenNode` DATA into a closure variable fed by its own subscribe\n\t// handler. The output producer consults `latestIsOpen` instead of reading\n\t// `isOpenNode.cache` from inside its callback — keeps the gate decision on\n\t// the protocol delivery path (P3 audit #11). Seeded with `startOpen` at\n\t// wiring time so the first item arriving before any open()/close() uses\n\t// the same value the state node was constructed with. Same template as\n\t// the `stratify` rule-capture pattern.\n\tlet latestIsOpen = startOpen;\n\tconst isOpenUnsub = isOpenNode.subscribe((msgs) => {\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] === DATA) latestIsOpen = m[1] as boolean;\n\t\t}\n\t});\n\n\tfunction syncPending(): void {\n\t\tpendingNode.down([[DATA, [...queue]]]);\n\t}\n\n\tfunction enqueue(value: T): void {\n\t\tqueue.push(value);\n\t\tif (queue.length > maxPending) queue.shift();\n\t\tsyncPending();\n\t}\n\n\tfunction dequeue(n: number): T[] {\n\t\tconst items = queue.splice(0, n);\n\t\tsyncPending();\n\t\treturn items;\n\t}\n\n\tfunction guardTorn(method: string): void {\n\t\tif (torn) throw new Error(`gate: ${method}() called after gate was torn down`);\n\t}\n\n\tconst output = node<T>(\n\t\t[src.node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst terminal = ctx.terminalDeps[0];\n\t\t\tif (terminal !== undefined) {\n\t\t\t\ttorn = true;\n\t\t\t\tqueue = [];\n\t\t\t\tsyncPending();\n\t\t\t\tactions.down(terminal === true ? [[COMPLETE]] : [[ERROR, terminal]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst batch0 = batchData[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0 as T[]) {\n\t\t\t\tif (latestIsOpen) {\n\t\t\t\t\tactions.emit(v);\n\t\t\t\t} else {\n\t\t\t\t\tenqueue(v);\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tname,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"gate\", opts?.meta),\n\t\t},\n\t);\n\n\tconst controller: GateController<T> = {\n\t\tnode: output,\n\t\tpending: pendingNode,\n\t\tcount: countNode,\n\t\tisOpen: isOpenNode,\n\t\tapprove(count = 1) {\n\t\t\tguardTorn(\"approve\");\n\t\t\tconst items = dequeue(count);\n\t\t\tfor (const item of items) {\n\t\t\t\tif (torn) break;\n\t\t\t\toutput.down([[DATA, item]]);\n\t\t\t}\n\t\t},\n\t\treject(count = 1) {\n\t\t\tguardTorn(\"reject\");\n\t\t\tdequeue(count);\n\t\t},\n\t\tmodify(fn, count = 1) {\n\t\t\tguardTorn(\"modify\");\n\t\t\tconst snapshot = [...queue] as readonly T[];\n\t\t\tconst items = dequeue(count);\n\t\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\t\tif (torn) break;\n\t\t\t\toutput.down([[DATA, fn(items[i], i, snapshot)]]);\n\t\t\t}\n\t\t},\n\t\topen() {\n\t\t\tguardTorn(\"open\");\n\t\t\t// Wrap the isOpen transition + queued flush in one batch so every\n\t\t\t// `output.down` is tier-3-deferred until after the `isOpenNode` dep\n\t\t\t// wave settles. Without this, queued DATAs could interleave with\n\t\t\t// the in-flight isOpen settlement wave under async runners — item\n\t\t\t// order relative to the open signal would be non-deterministic.\n\t\t\tbatch(() => {\n\t\t\t\tisOpenNode.down([[DATA, true]]);\n\t\t\t\tconst items = dequeue(queue.length);\n\t\t\t\tfor (const item of items) {\n\t\t\t\t\tif (torn) break;\n\t\t\t\t\toutput.down([[DATA, item]]);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tclose() {\n\t\t\tguardTorn(\"close\");\n\t\t\tisOpenNode.down([[DATA, false]]);\n\t\t},\n\t};\n\n\t// Activate count so it stays reactive\n\tgraph.addDisposer(countNode.subscribe(() => undefined));\n\t// Tear down the isOpen capture when the owning graph disposes.\n\tgraph.addDisposer(isOpenUnsub);\n\n\t// Register output + internal state as a mounted subgraph (aligned with PY)\n\tregisterStep(graph, name, output as unknown as Node<unknown>, src.path ? [src.path] : []);\n\tconst internal = new Graph(`${name}_state`);\n\tinternal.add(\"pending\", pendingNode);\n\tinternal.add(\"isOpen\", isOpenNode);\n\tinternal.add(\"count\", countNode);\n\tgraph.mount(`${name}_state`, internal);\n\n\treturn controller;\n}\n\n/**\n * Registers a workflow side-effect step that runs `run` for each upstream\n * DATA value.\n *\n * `run` receives the full `NodeActions` and is the **sole emission point** —\n * call `actions.emit(v)` or `actions.down(msgs)` inside `run` to produce\n * downstream output. If `run` does not emit, this step acts as a pure\n * side-effect sink (graph-observable but no output). Throwing inside `run`\n * terminates the step with ERROR.\n */\nexport function forEach<T>(\n\tgraph: Graph,\n\tname: string,\n\tsource: StepRef,\n\trun: (value: T, actions: NodeActions) => void,\n\topts?: Omit<OrchestrationStepOptions, \"deps\">,\n): Node<T> {\n\tconst src = resolveDep(graph, source);\n\tlet terminated = false;\n\tconst step = node<T>(\n\t\t[src.node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (terminated) {\n\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Terminal from dep\n\t\t\tconst terminal = ctx.terminalDeps[0];\n\t\t\tif (terminal !== undefined) {\n\t\t\t\tterminated = true;\n\t\t\t\tactions.down(terminal === true ? [[COMPLETE]] : [[ERROR, terminal]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst batch0 = batchData[0];\n\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const v of batch0 as T[]) {\n\t\t\t\ttry {\n\t\t\t\t\trun(v, actions);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tterminated = true;\n\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t...opts,\n\t\t\tname,\n\t\t\tdescribeKind: \"effect\",\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t\tmeta: baseMeta(\"forEach\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\t// registerStep registers the edge for graph visibility. g.connect's dedup\n\t// check skips _addDep since src.node is already a constructor dep.\n\tregisterStep(graph, name, step as unknown as Node<unknown>, src.path ? [src.path] : []);\n\treturn step;\n}\n\n/**\n * Registers a join step that emits a tuple of latest dependency values.\n */\nexport function join<T extends readonly unknown[]>(\n\tgraph: Graph,\n\tname: string,\n\tdeps: { [K in keyof T]: StepRef },\n\topts?: Omit<OrchestrationStepOptions, \"deps\">,\n): Node<T> {\n\tconst resolved = deps.map((dep) => resolveDep(graph, dep));\n\tconst step = derived<T>(\n\t\tresolved.map((d) => d.node),\n\t\t(values) => values as T,\n\t\t{\n\t\t\t...opts,\n\t\t\tname,\n\t\t\tmeta: baseMeta(\"join\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\tregisterStep(\n\t\tgraph,\n\t\tname,\n\t\tstep as unknown as Node<unknown>,\n\t\tresolved.flatMap((d) => (d.path ? [d.path] : [])),\n\t);\n\treturn step;\n}\n\n/**\n * Registers a loop step that applies `iterate` to each source value N times.\n */\nexport function loop<T>(\n\tgraph: Graph,\n\tname: string,\n\tsource: StepRef,\n\titerate: (value: T, iteration: number, actions: NodeActions) => T,\n\topts?: LoopOptions,\n): Node<T> {\n\tconst src = resolveDep(graph, source);\n\tconst iterRef = opts?.iterations;\n\tconst iterDep =\n\t\ttypeof iterRef === \"number\" || iterRef === undefined ? undefined : resolveDep(graph, iterRef);\n\tconst staticIterations = typeof iterRef === \"number\" ? iterRef : undefined;\n\tconst step = node<T>(\n\t\titerDep ? [src.node, iterDep.node] : [src.node],\n\t\t(depValues, actions, ctx) => {\n\t\t\tconst batch0 = depValues[0];\n\t\t\tlet current = (batch0 != null && batch0.length > 0 ? batch0.at(-1) : ctx.prevData[0]) as T;\n\t\t\tconst batch1 = iterDep ? depValues[1] : undefined;\n\t\t\tconst rawCount =\n\t\t\t\tstaticIterations ??\n\t\t\t\t(iterDep ? (batch1 != null && batch1.length > 0 ? batch1.at(-1) : ctx.prevData[1]) : 1);\n\t\t\tconst count = coerceLoopIterations(rawCount);\n\t\t\tfor (let i = 0; i < count; i += 1) {\n\t\t\t\tcurrent = iterate(current, i, actions);\n\t\t\t}\n\t\t\tactions.emit(current);\n\t\t},\n\t\t{\n\t\t\t...opts,\n\t\t\tname,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"loop\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\tregisterStep(\n\t\tgraph,\n\t\tname,\n\t\tstep as unknown as Node<unknown>,\n\t\t[src.path, iterDep?.path].filter((v): v is string => typeof v === \"string\"),\n\t);\n\treturn step;\n}\n\n/**\n * Mounts and returns a child workflow graph.\n */\nexport function subPipeline(\n\tgraph: Graph,\n\tname: string,\n\tchildOrBuild?: Graph | SubPipelineBuilder,\n\topts?: GraphOptions,\n): Graph {\n\tconst child = childOrBuild instanceof Graph ? childOrBuild : pipeline(name, opts);\n\tif (typeof childOrBuild === \"function\") {\n\t\tchildOrBuild(child);\n\t}\n\tgraph.mount(name, child);\n\treturn child;\n}\n\n/**\n * Registers a producer-style sensor source and returns imperative controls.\n */\nexport function sensor<T>(\n\tgraph: Graph,\n\tname: string,\n\tinitial?: T,\n\topts?: Omit<NodeOptions<unknown>, \"name\" | \"describeKind\" | \"meta\"> & {\n\t\tmeta?: Record<string, unknown>;\n\t},\n): SensorControls<T> {\n\tconst source = node<T>([], () => undefined, {\n\t\t...opts,\n\t\tname,\n\t\tinitial,\n\t\tdescribeKind: \"producer\",\n\t\tmeta: baseMeta(\"sensor\", opts?.meta),\n\t});\n\tregisterStep(graph, name, source as unknown as Node<unknown>, []);\n\treturn {\n\t\tnode: source,\n\t\tpush(value: T) {\n\t\t\tsource.down([[DATA, value]] satisfies Messages);\n\t\t},\n\t\terror(err: unknown) {\n\t\t\tsource.down([[ERROR, err]] satisfies Messages);\n\t\t},\n\t\tcomplete() {\n\t\t\tsource.down([[COMPLETE]] satisfies Messages);\n\t\t},\n\t};\n}\n\n/**\n * Registers a delayed-forwarding step (value-level wait).\n */\nexport function wait<T>(\n\tgraph: Graph,\n\tname: string,\n\tsource: StepRef,\n\tms: number,\n\topts?: WaitOptions,\n): Node<T> {\n\tconst src = resolveDep(graph, source);\n\tconst timers = new Set<ReturnType<typeof setTimeout>>();\n\tlet terminated = false;\n\tlet completed = false;\n\n\tfunction clearAllTimers(): void {\n\t\tfor (const id of timers) clearTimeout(id);\n\t\ttimers.clear();\n\t}\n\n\t// Producer pattern: 0 deps, manual subscribe to source.\n\t// Under Model B (push-on-subscribe) the fn runs eagerly via _startProducer,\n\t// ensuring the cleanup is registered and timers are cleared on teardown.\n\t// Only set initial if source has a real cached value (not SENTINEL/undefined).\n\tconst srcVal = src.node.cache;\n\tconst initialOpt = srcVal !== undefined ? { initial: srcVal as T } : {};\n\n\tconst step = node<T>(\n\t\t[],\n\t\t(_deps, actions) => {\n\t\t\tclearAllTimers();\n\t\t\tterminated = false;\n\t\t\tcompleted = false;\n\t\t\tconst unsub = src.node.subscribe((msgs) => {\n\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\tif (terminated) return;\n\t\t\t\t\tif (msg[0] === DATA) {\n\t\t\t\t\t\tconst id = setTimeout(() => {\n\t\t\t\t\t\t\ttimers.delete(id);\n\t\t\t\t\t\t\tactions.down([msg] satisfies Messages);\n\t\t\t\t\t\t\tif (completed && timers.size === 0) {\n\t\t\t\t\t\t\t\tactions.down([[COMPLETE]] satisfies Messages);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, ms);\n\t\t\t\t\t\ttimers.add(id);\n\t\t\t\t\t} else if (msg[0] === COMPLETE) {\n\t\t\t\t\t\tterminated = true;\n\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\tif (timers.size === 0) {\n\t\t\t\t\t\t\tactions.down([[COMPLETE]] satisfies Messages);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (msg[0] === ERROR) {\n\t\t\t\t\t\tterminated = true;\n\t\t\t\t\t\tclearAllTimers();\n\t\t\t\t\t\tactions.down([msg] satisfies Messages);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tactions.down([msg] satisfies Messages);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tunsub();\n\t\t\t\tclearAllTimers();\n\t\t\t\tterminated = true;\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t...opts,\n\t\t\tname,\n\t\t\t...initialOpt,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t\tmeta: baseMeta(\"wait\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\t// Producer pattern: register in graph without dep edges (manual subscription).\n\t// Post edge-registry deletion (Unit 7), edges are derived from node `_deps`\n\t// exclusively; this producer's logical dep on `src` is not reflected in\n\t// `describe()` — by design, since there is no real constructor-time\n\t// dependency to show.\n\tgraph.add(name, step as unknown as Node<unknown>);\n\treturn step;\n}\n\n/**\n * Registers an error-recovery step for a source.\n */\nexport function onFailure<T>(\n\tgraph: Graph,\n\tname: string,\n\tsource: StepRef,\n\trecover: (err: unknown, actions: NodeActions) => T,\n\topts?: Omit<OrchestrationStepOptions, \"deps\">,\n): Node<T> {\n\tconst src = resolveDep(graph, source);\n\tlet terminated = false;\n\t// Producer pattern: manually subscribe to source for per-message interception\n\t// (onMessage removed in v5 — use producer+subscribe instead)\n\tconst step = node<T>(\n\t\t[],\n\t\t(_data, actions) => {\n\t\t\tconst unsub = src.node.subscribe((msgs) => {\n\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\tif (terminated) return;\n\t\t\t\t\tif (msg[0] === ERROR) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tactions.emit(recover(msg[1], actions));\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tterminated = true;\n\t\t\t\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tactions.down([msg] satisfies Messages);\n\t\t\t\t\t\tif (msg[0] === COMPLETE) terminated = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn () => unsub();\n\t\t},\n\t\t{\n\t\t\t...opts,\n\t\t\tname,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t\t// onFailure handles errors via manual subscription (recover callback).\n\t\t\t// Disable auto-propagation so dep-channel ERROR doesn't terminate this\n\t\t\t// node before the recover callback has a chance to emit a replacement value.\n\t\t\terrorWhenDepsError: false,\n\t\t\tmeta: baseMeta(\"onFailure\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\tregisterStep(graph, name, step as unknown as Node<unknown>, src.path ? [src.path] : []);\n\treturn step;\n}\n"],"mappings":"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","names":["node","batch","batch","keepalive","node","node","node","size","node","audit","result","derived","baseMeta","from","down","downEdges","acc","node","out","isNodeLike","node"]}