@graphrefly/graphrefly 0.47.1 → 0.48.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 (303) hide show
  1. package/dist/base/composition/index.cjs +28 -19
  2. package/dist/base/composition/index.cjs.map +1 -1
  3. package/dist/base/composition/index.d.cts +14 -5
  4. package/dist/base/composition/index.d.ts +14 -5
  5. package/dist/base/composition/index.js +9 -9
  6. package/dist/base/index.cjs +294 -164
  7. package/dist/base/index.cjs.map +1 -1
  8. package/dist/base/index.d.cts +2 -2
  9. package/dist/base/index.d.ts +2 -2
  10. package/dist/base/index.js +77 -72
  11. package/dist/base/io/index.cjs +145 -85
  12. package/dist/base/io/index.cjs.map +1 -1
  13. package/dist/base/io/index.d.cts +32 -5
  14. package/dist/base/io/index.d.ts +32 -5
  15. package/dist/base/io/index.js +5 -5
  16. package/dist/base/mutation/index.cjs +21 -0
  17. package/dist/base/mutation/index.cjs.map +1 -1
  18. package/dist/base/mutation/index.d.cts +23 -1
  19. package/dist/base/mutation/index.d.ts +23 -1
  20. package/dist/base/mutation/index.js +3 -1
  21. package/dist/base/sources/browser/index.cjs +18 -12
  22. package/dist/base/sources/browser/index.cjs.map +1 -1
  23. package/dist/base/sources/browser/index.d.cts +20 -2
  24. package/dist/base/sources/browser/index.d.ts +20 -2
  25. package/dist/base/sources/browser/index.js +18 -12
  26. package/dist/base/sources/browser/index.js.map +1 -1
  27. package/dist/base/sources/event/index.cjs +29 -1
  28. package/dist/base/sources/event/index.cjs.map +1 -1
  29. package/dist/base/sources/event/index.d.cts +67 -3
  30. package/dist/base/sources/event/index.d.ts +67 -3
  31. package/dist/base/sources/event/index.js +5 -2
  32. package/dist/base/sources/index.cjs +96 -50
  33. package/dist/base/sources/index.cjs.map +1 -1
  34. package/dist/base/sources/index.d.cts +1 -1
  35. package/dist/base/sources/index.d.ts +1 -1
  36. package/dist/base/sources/index.js +7 -4
  37. package/dist/base/sources/node/index.cjs +43 -37
  38. package/dist/base/sources/node/index.cjs.map +1 -1
  39. package/dist/base/sources/node/index.js +43 -37
  40. package/dist/base/sources/node/index.js.map +1 -1
  41. package/dist/{chunk-J5WFUEO4.js → chunk-23MAWVOJ.js} +3 -3
  42. package/dist/{chunk-YXCPV26R.js → chunk-3REMCHSS.js} +39 -27
  43. package/dist/chunk-3REMCHSS.js.map +1 -0
  44. package/dist/{chunk-CEVNQ74M.js → chunk-3YGXPUHW.js} +2 -2
  45. package/dist/{chunk-CEVNQ74M.js.map → chunk-3YGXPUHW.js.map} +1 -1
  46. package/dist/{chunk-EVYY4X5A.js → chunk-46X2EFQH.js} +16 -5
  47. package/dist/chunk-46X2EFQH.js.map +1 -0
  48. package/dist/{chunk-NY2PYHNC.js → chunk-5UY3PNFY.js} +12 -5
  49. package/dist/chunk-5UY3PNFY.js.map +1 -0
  50. package/dist/{chunk-RGMTUZCL.js → chunk-65OM4XLQ.js} +50 -4
  51. package/dist/chunk-65OM4XLQ.js.map +1 -0
  52. package/dist/{chunk-3PSLNJDU.js → chunk-6DQYBIHW.js} +314 -49
  53. package/dist/chunk-6DQYBIHW.js.map +1 -0
  54. package/dist/{chunk-LDCSZ72P.js → chunk-6YBER5UP.js} +3 -3
  55. package/dist/{chunk-LDCSZ72P.js.map → chunk-6YBER5UP.js.map} +1 -1
  56. package/dist/{chunk-7EGRP2VX.js → chunk-7BULJTL6.js} +2 -2
  57. package/dist/{chunk-7EGRP2VX.js.map → chunk-7BULJTL6.js.map} +1 -1
  58. package/dist/{chunk-VLAGJZSL.js → chunk-7T7WLEPM.js} +25 -4
  59. package/dist/chunk-7T7WLEPM.js.map +1 -0
  60. package/dist/{chunk-PKPO3JTZ.js → chunk-AQAKDE7F.js} +29 -11
  61. package/dist/chunk-AQAKDE7F.js.map +1 -0
  62. package/dist/{chunk-2OB3CEJS.js → chunk-B5Y5GPD5.js} +2 -2
  63. package/dist/{chunk-BXGZFGZ4.js → chunk-C5QD5DQX.js} +22 -1
  64. package/dist/chunk-C5QD5DQX.js.map +1 -0
  65. package/dist/{chunk-4XCHZRUJ.js → chunk-D5YGR4TP.js} +58 -7
  66. package/dist/chunk-D5YGR4TP.js.map +1 -0
  67. package/dist/{chunk-NPRP3MCV.js → chunk-DHDCOOJU.js} +2 -2
  68. package/dist/chunk-DHDCOOJU.js.map +1 -0
  69. package/dist/{chunk-MTTRCEJT.js → chunk-DVTDF5OI.js} +2 -2
  70. package/dist/{chunk-SOOKUYVM.js → chunk-F7EKHR32.js} +13 -9
  71. package/dist/chunk-F7EKHR32.js.map +1 -0
  72. package/dist/{chunk-A7KV5UK4.js → chunk-G7H6PN7P.js} +2 -2
  73. package/dist/{chunk-OCUDSN63.js → chunk-GGKHHG5Y.js} +110 -64
  74. package/dist/chunk-GGKHHG5Y.js.map +1 -0
  75. package/dist/{chunk-RAGGHLCV.js → chunk-GUNIRPEJ.js} +8 -6
  76. package/dist/{chunk-RAGGHLCV.js.map → chunk-GUNIRPEJ.js.map} +1 -1
  77. package/dist/{chunk-YJ4U2D2C.js → chunk-J5TBZFBD.js} +9 -7
  78. package/dist/chunk-J5TBZFBD.js.map +1 -0
  79. package/dist/{chunk-Y52CS6YA.js → chunk-JA67ZQG2.js} +2 -2
  80. package/dist/{chunk-Y52CS6YA.js.map → chunk-JA67ZQG2.js.map} +1 -1
  81. package/dist/{chunk-U225SKB4.js → chunk-K4ZYJ4EM.js} +569 -424
  82. package/dist/chunk-K4ZYJ4EM.js.map +1 -0
  83. package/dist/{chunk-Z4YXAUDN.js → chunk-KUFXLAEY.js} +11 -7
  84. package/dist/{chunk-Z4YXAUDN.js.map → chunk-KUFXLAEY.js.map} +1 -1
  85. package/dist/{chunk-IHTWQEDR.js → chunk-LTSI7ULC.js} +3 -3
  86. package/dist/{chunk-IHTWQEDR.js.map → chunk-LTSI7ULC.js.map} +1 -1
  87. package/dist/{chunk-DKNHAICT.js → chunk-MMHGYX44.js} +25 -9
  88. package/dist/chunk-MMHGYX44.js.map +1 -0
  89. package/dist/{chunk-K7PDZYQE.js → chunk-MQMTRKY3.js} +129 -50
  90. package/dist/chunk-MQMTRKY3.js.map +1 -0
  91. package/dist/{chunk-42FQ27MQ.js → chunk-MTODGQBR.js} +44 -179
  92. package/dist/chunk-MTODGQBR.js.map +1 -0
  93. package/dist/{chunk-O3MT7DYI.js → chunk-N6MNJNHB.js} +2 -2
  94. package/dist/{chunk-FVINAAKA.js → chunk-NBK6QQMG.js} +14 -13
  95. package/dist/{chunk-FVINAAKA.js.map → chunk-NBK6QQMG.js.map} +1 -1
  96. package/dist/{chunk-DM4OMPWK.js → chunk-NSA5K5G2.js} +2 -2
  97. package/dist/{chunk-MLTPJMH6.js → chunk-QQYULEZL.js} +2 -2
  98. package/dist/chunk-QSW4DFKE.js +31 -0
  99. package/dist/chunk-QSW4DFKE.js.map +1 -0
  100. package/dist/{chunk-PZWISPIQ.js → chunk-S7HN5FHL.js} +17 -11
  101. package/dist/chunk-S7HN5FHL.js.map +1 -0
  102. package/dist/{chunk-4S53H2KR.js → chunk-SUNCHMML.js} +2 -2
  103. package/dist/{chunk-4GYMCUDZ.js → chunk-T2U6N3FV.js} +7 -7
  104. package/dist/{chunk-RJOG4IJU.js → chunk-T5URUIIY.js} +50 -35
  105. package/dist/chunk-T5URUIIY.js.map +1 -0
  106. package/dist/{chunk-B4AKFXGE.js → chunk-TPTZZV25.js} +6 -6
  107. package/dist/chunk-TPTZZV25.js.map +1 -0
  108. package/dist/{chunk-BU3SEFA5.js → chunk-V46JWFGV.js} +7 -6
  109. package/dist/chunk-V46JWFGV.js.map +1 -0
  110. package/dist/{chunk-IJRR6YAI.js → chunk-VLDRAMP7.js} +18 -12
  111. package/dist/chunk-VLDRAMP7.js.map +1 -0
  112. package/dist/{chunk-6XZYT4SW.js → chunk-X6ESZDR6.js} +8 -9
  113. package/dist/chunk-X6ESZDR6.js.map +1 -0
  114. package/dist/{chunk-E5OZPDIW.js → chunk-X7BA5PWG.js} +7 -5
  115. package/dist/chunk-X7BA5PWG.js.map +1 -0
  116. package/dist/{chunk-CXANAIZU.js → chunk-XEWV254I.js} +3 -3
  117. package/dist/{chunk-CXANAIZU.js.map → chunk-XEWV254I.js.map} +1 -1
  118. package/dist/{chunk-V4Y3TM7U.js → chunk-YBJVKMTM.js} +38 -16
  119. package/dist/chunk-YBJVKMTM.js.map +1 -0
  120. package/dist/{chunk-7ADWWI2T.js → chunk-ZW32BPXV.js} +17 -6
  121. package/dist/chunk-ZW32BPXV.js.map +1 -0
  122. package/dist/compat/index.cjs +52 -5
  123. package/dist/compat/index.cjs.map +1 -1
  124. package/dist/compat/index.d.cts +1 -1
  125. package/dist/compat/index.d.ts +1 -1
  126. package/dist/compat/index.js +7 -7
  127. package/dist/compat/nestjs/index.cjs +52 -5
  128. package/dist/compat/nestjs/index.cjs.map +1 -1
  129. package/dist/compat/nestjs/index.d.cts +1 -1
  130. package/dist/compat/nestjs/index.d.ts +1 -1
  131. package/dist/compat/nestjs/index.js +4 -4
  132. package/dist/{fallback-Bx46zqky.d.cts → fallback-BROR6ZhO.d.cts} +1 -1
  133. package/dist/{fallback-pIWW8A2d.d.ts → fallback-DO80aM_3.d.ts} +1 -1
  134. package/dist/{index-B_p8tnvf.d.cts → index-D1z3XcF9.d.cts} +1 -0
  135. package/dist/{index-_HDSmPyp.d.ts → index-DZ6yua0Q.d.ts} +1 -0
  136. package/dist/index.cjs +2387 -1707
  137. package/dist/index.cjs.map +1 -1
  138. package/dist/index.d.cts +10 -10
  139. package/dist/index.d.ts +10 -10
  140. package/dist/index.js +173 -150
  141. package/dist/index.js.map +1 -1
  142. package/dist/presets/ai/index.cjs +88 -26
  143. package/dist/presets/ai/index.cjs.map +1 -1
  144. package/dist/presets/ai/index.js +14 -14
  145. package/dist/presets/harness/index.cjs +183 -51
  146. package/dist/presets/harness/index.cjs.map +1 -1
  147. package/dist/presets/harness/index.d.cts +15 -5
  148. package/dist/presets/harness/index.d.ts +15 -5
  149. package/dist/presets/harness/index.js +26 -26
  150. package/dist/presets/index.cjs +298 -101
  151. package/dist/presets/index.cjs.map +1 -1
  152. package/dist/presets/index.d.cts +2 -2
  153. package/dist/presets/index.d.ts +2 -2
  154. package/dist/presets/index.js +49 -49
  155. package/dist/presets/inspect/index.cjs +63 -14
  156. package/dist/presets/inspect/index.cjs.map +1 -1
  157. package/dist/presets/inspect/index.d.cts +1 -1
  158. package/dist/presets/inspect/index.d.ts +1 -1
  159. package/dist/presets/inspect/index.js +6 -6
  160. package/dist/presets/resilience/index.cjs +64 -44
  161. package/dist/presets/resilience/index.cjs.map +1 -1
  162. package/dist/presets/resilience/index.d.cts +12 -8
  163. package/dist/presets/resilience/index.d.ts +12 -8
  164. package/dist/presets/resilience/index.js +6 -6
  165. package/dist/{rate-limiter-DpVbSYdH.d.cts → rate-limiter-DC26FM8J.d.cts} +10 -1
  166. package/dist/{rate-limiter-CEALq4N1.d.ts → rate-limiter-DyWpwpQP.d.ts} +10 -1
  167. package/dist/{reactive-layout-fswlBUvX.d.ts → reactive-layout-BBBWH0V_.d.cts} +85 -4
  168. package/dist/{reactive-layout-fswlBUvX.d.cts → reactive-layout-BBBWH0V_.d.ts} +85 -4
  169. package/dist/solutions/index.cjs +239 -92
  170. package/dist/solutions/index.cjs.map +1 -1
  171. package/dist/solutions/index.d.cts +2 -2
  172. package/dist/solutions/index.d.ts +2 -2
  173. package/dist/solutions/index.js +32 -32
  174. package/dist/{spawnable-5mDY501F.d.cts → spawnable-B2IlW60f.d.cts} +23 -2
  175. package/dist/{spawnable-D3lR0oQu.d.ts → spawnable-tttFz2Nh.d.ts} +23 -2
  176. package/dist/testing/index.cjs +94 -0
  177. package/dist/testing/index.cjs.map +1 -0
  178. package/dist/testing/index.d.cts +59 -0
  179. package/dist/testing/index.d.ts +59 -0
  180. package/dist/testing/index.js +73 -0
  181. package/dist/testing/index.js.map +1 -0
  182. package/dist/{timeout-U5O4ESK3.js → timeout-BEABACRP.js} +2 -2
  183. package/dist/utils/ai/browser.cjs.map +1 -1
  184. package/dist/utils/ai/browser.d.cts +2 -2
  185. package/dist/utils/ai/browser.d.ts +2 -2
  186. package/dist/utils/ai/browser.js +10 -10
  187. package/dist/utils/ai/browser.js.map +1 -1
  188. package/dist/utils/ai/index.cjs +291 -191
  189. package/dist/utils/ai/index.cjs.map +1 -1
  190. package/dist/utils/ai/index.d.cts +108 -12
  191. package/dist/utils/ai/index.d.ts +108 -12
  192. package/dist/utils/ai/index.js +23 -21
  193. package/dist/utils/ai/node.cjs.map +1 -1
  194. package/dist/utils/ai/node.d.cts +5 -5
  195. package/dist/utils/ai/node.d.ts +5 -5
  196. package/dist/utils/ai/node.js +3 -3
  197. package/dist/utils/ai/node.js.map +1 -1
  198. package/dist/utils/cqrs/index.cjs +29 -3
  199. package/dist/utils/cqrs/index.cjs.map +1 -1
  200. package/dist/utils/cqrs/index.d.cts +12 -7
  201. package/dist/utils/cqrs/index.d.ts +12 -7
  202. package/dist/utils/cqrs/index.js +2 -2
  203. package/dist/utils/demo-shell/index.cjs +45 -19
  204. package/dist/utils/demo-shell/index.cjs.map +1 -1
  205. package/dist/utils/demo-shell/index.d.cts +1 -1
  206. package/dist/utils/demo-shell/index.d.ts +1 -1
  207. package/dist/utils/demo-shell/index.js +2 -2
  208. package/dist/utils/domain-templates/index.cjs +1 -1
  209. package/dist/utils/domain-templates/index.cjs.map +1 -1
  210. package/dist/utils/domain-templates/index.js +3 -3
  211. package/dist/utils/graphspec/index.cjs +1 -1
  212. package/dist/utils/graphspec/index.cjs.map +1 -1
  213. package/dist/utils/graphspec/index.js +3 -3
  214. package/dist/utils/harness/index.cjs +16 -10
  215. package/dist/utils/harness/index.cjs.map +1 -1
  216. package/dist/utils/harness/index.js +1 -1
  217. package/dist/utils/index.cjs +1692 -1192
  218. package/dist/utils/index.cjs.map +1 -1
  219. package/dist/utils/index.d.cts +7 -7
  220. package/dist/utils/index.d.ts +7 -7
  221. package/dist/utils/index.js +77 -59
  222. package/dist/utils/inspect/index.cjs +52 -4
  223. package/dist/utils/inspect/index.cjs.map +1 -1
  224. package/dist/utils/inspect/index.d.cts +32 -3
  225. package/dist/utils/inspect/index.d.ts +32 -3
  226. package/dist/utils/inspect/index.js +4 -4
  227. package/dist/utils/job-queue/index.cjs +46 -9
  228. package/dist/utils/job-queue/index.cjs.map +1 -1
  229. package/dist/utils/job-queue/index.d.cts +33 -3
  230. package/dist/utils/job-queue/index.d.ts +33 -3
  231. package/dist/utils/job-queue/index.js +2 -2
  232. package/dist/utils/memory/index.cjs +570 -425
  233. package/dist/utils/memory/index.cjs.map +1 -1
  234. package/dist/utils/memory/index.d.cts +261 -33
  235. package/dist/utils/memory/index.d.ts +261 -33
  236. package/dist/utils/memory/index.js +10 -2
  237. package/dist/utils/messaging/index.cjs.map +1 -1
  238. package/dist/utils/messaging/index.d.cts +4 -3
  239. package/dist/utils/messaging/index.d.ts +4 -3
  240. package/dist/utils/messaging/index.js +2 -2
  241. package/dist/utils/orchestration/index.cjs +14 -3
  242. package/dist/utils/orchestration/index.cjs.map +1 -1
  243. package/dist/utils/orchestration/index.js +3 -3
  244. package/dist/utils/process/index.cjs +32 -2
  245. package/dist/utils/process/index.cjs.map +1 -1
  246. package/dist/utils/process/index.d.cts +4 -3
  247. package/dist/utils/process/index.d.ts +4 -3
  248. package/dist/utils/process/index.js +3 -3
  249. package/dist/utils/reactive-layout/index.cjs +184 -55
  250. package/dist/utils/reactive-layout/index.cjs.map +1 -1
  251. package/dist/utils/reactive-layout/index.d.cts +128 -3
  252. package/dist/utils/reactive-layout/index.d.ts +128 -3
  253. package/dist/utils/reactive-layout/index.js +16 -8
  254. package/dist/utils/reduction/index.cjs +1 -1
  255. package/dist/utils/reduction/index.cjs.map +1 -1
  256. package/dist/utils/reduction/index.js +2 -2
  257. package/dist/utils/resilience/index.cjs +64 -43
  258. package/dist/utils/resilience/index.cjs.map +1 -1
  259. package/dist/utils/resilience/index.d.cts +1 -1
  260. package/dist/utils/resilience/index.d.ts +1 -1
  261. package/dist/utils/resilience/index.js +5 -5
  262. package/dist/utils/surface/index.cjs +1 -1
  263. package/dist/utils/surface/index.cjs.map +1 -1
  264. package/dist/utils/surface/index.js +4 -4
  265. package/package.json +15 -3
  266. package/dist/chunk-3PSLNJDU.js.map +0 -1
  267. package/dist/chunk-42FQ27MQ.js.map +0 -1
  268. package/dist/chunk-4XCHZRUJ.js.map +0 -1
  269. package/dist/chunk-6XZYT4SW.js.map +0 -1
  270. package/dist/chunk-7ADWWI2T.js.map +0 -1
  271. package/dist/chunk-B4AKFXGE.js.map +0 -1
  272. package/dist/chunk-BU3SEFA5.js.map +0 -1
  273. package/dist/chunk-BXGZFGZ4.js.map +0 -1
  274. package/dist/chunk-DKNHAICT.js.map +0 -1
  275. package/dist/chunk-E5OZPDIW.js.map +0 -1
  276. package/dist/chunk-EVYY4X5A.js.map +0 -1
  277. package/dist/chunk-IJRR6YAI.js.map +0 -1
  278. package/dist/chunk-K7PDZYQE.js.map +0 -1
  279. package/dist/chunk-NPRP3MCV.js.map +0 -1
  280. package/dist/chunk-NY2PYHNC.js.map +0 -1
  281. package/dist/chunk-OCUDSN63.js.map +0 -1
  282. package/dist/chunk-PKPO3JTZ.js.map +0 -1
  283. package/dist/chunk-PZWISPIQ.js.map +0 -1
  284. package/dist/chunk-RGMTUZCL.js.map +0 -1
  285. package/dist/chunk-RJOG4IJU.js.map +0 -1
  286. package/dist/chunk-SOOKUYVM.js.map +0 -1
  287. package/dist/chunk-U225SKB4.js.map +0 -1
  288. package/dist/chunk-V4Y3TM7U.js.map +0 -1
  289. package/dist/chunk-VLAGJZSL.js.map +0 -1
  290. package/dist/chunk-W2BOPXTI.js +0 -1
  291. package/dist/chunk-YJ4U2D2C.js.map +0 -1
  292. package/dist/chunk-YXCPV26R.js.map +0 -1
  293. package/dist/timeout-U5O4ESK3.js.map +0 -1
  294. /package/dist/{chunk-J5WFUEO4.js.map → chunk-23MAWVOJ.js.map} +0 -0
  295. /package/dist/{chunk-2OB3CEJS.js.map → chunk-B5Y5GPD5.js.map} +0 -0
  296. /package/dist/{chunk-MTTRCEJT.js.map → chunk-DVTDF5OI.js.map} +0 -0
  297. /package/dist/{chunk-A7KV5UK4.js.map → chunk-G7H6PN7P.js.map} +0 -0
  298. /package/dist/{chunk-O3MT7DYI.js.map → chunk-N6MNJNHB.js.map} +0 -0
  299. /package/dist/{chunk-DM4OMPWK.js.map → chunk-NSA5K5G2.js.map} +0 -0
  300. /package/dist/{chunk-MLTPJMH6.js.map → chunk-QQYULEZL.js.map} +0 -0
  301. /package/dist/{chunk-4S53H2KR.js.map → chunk-SUNCHMML.js.map} +0 -0
  302. /package/dist/{chunk-4GYMCUDZ.js.map → chunk-T2U6N3FV.js.map} +0 -0
  303. /package/dist/{chunk-W2BOPXTI.js.map → timeout-BEABACRP.js.map} +0 -0
@@ -341,11 +341,13 @@ function withTimeout(source, opts, extraOpts) {
341
341
  if (latestOpts != null) {
342
342
  attachSource();
343
343
  }
344
- return () => {
345
- stopped = true;
346
- timer.cancel();
347
- if (srcUnsub) srcUnsub();
348
- if (optsUnsub) optsUnsub();
344
+ return {
345
+ onDeactivation: () => {
346
+ stopped = true;
347
+ timer.cancel();
348
+ if (srcUnsub) srcUnsub();
349
+ if (optsUnsub) optsUnsub();
350
+ }
349
351
  };
350
352
  },
351
353
  {
@@ -475,9 +477,11 @@ function _oneShotLlmCall(adapter, messages, config) {
475
477
  invokeResult = adapter.invoke(messages, { ...config.invokeOpts, signal: ac.signal });
476
478
  } catch (err) {
477
479
  emitOnce(config.onFailure("throw", err));
478
- return () => {
479
- unlinkParent();
480
- ac.abort();
480
+ return {
481
+ onDeactivation: () => {
482
+ unlinkParent();
483
+ ac.abort();
484
+ }
481
485
  };
482
486
  }
483
487
  const callNode = (0, import_extra.fromAny)(invokeResult, { signal: ac.signal });
@@ -506,11 +510,13 @@ function _oneShotLlmCall(adapter, messages, config) {
506
510
  unsub();
507
511
  unsub = null;
508
512
  }
509
- return () => {
510
- unlinkParent();
511
- ac.abort();
512
- unsub?.();
513
- unsub = null;
513
+ return {
514
+ onDeactivation: () => {
515
+ unlinkParent();
516
+ ac.abort();
517
+ unsub?.();
518
+ unsub = null;
519
+ }
514
520
  };
515
521
  },
516
522
  { describeKind: "producer" }
@@ -553,6 +559,26 @@ function createAuditLog(opts) {
553
559
  }
554
560
  return log;
555
561
  }
562
+ function readonlyAuditLog(log) {
563
+ return Object.freeze({
564
+ get entries() {
565
+ return log.entries;
566
+ },
567
+ get size() {
568
+ return log.size;
569
+ },
570
+ get lastValue() {
571
+ return log.lastValue;
572
+ },
573
+ get mutationLog() {
574
+ return log.mutationLog;
575
+ },
576
+ at: log.at.bind(log),
577
+ withLatest: log.withLatest.bind(log),
578
+ view: log.view.bind(log),
579
+ scan: log.scan.bind(log)
580
+ });
581
+ }
556
582
  function deepFreeze(value) {
557
583
  if (value === null || typeof value !== "object" || Object.isFrozen(value)) return value;
558
584
  for (const k of Object.keys(value)) {
@@ -1586,9 +1612,11 @@ function _retrySource(source, opts, emitState) {
1586
1612
  const merged = makeMergedOptsMirror(opts);
1587
1613
  const getCfg = () => resolveRetryConfig(merged.current());
1588
1614
  const inner = _runRetryStateMachine(getCfg, () => source, a, emitState);
1589
- return () => {
1590
- inner();
1591
- merged.unsub();
1615
+ return {
1616
+ onDeactivation: () => {
1617
+ inner();
1618
+ merged.unsub();
1619
+ }
1592
1620
  };
1593
1621
  },
1594
1622
  {
@@ -1612,9 +1640,11 @@ function _retryFactory(factory, opts, emitState) {
1612
1640
  const merged = makeMergedOptsMirror(opts);
1613
1641
  const getCfg = () => resolveRetryConfig(merged.current());
1614
1642
  const inner = _runRetryStateMachine(getCfg, factory, a, emitState);
1615
- return () => {
1616
- inner();
1617
- merged.unsub();
1643
+ return {
1644
+ onDeactivation: () => {
1645
+ inner();
1646
+ merged.unsub();
1647
+ }
1618
1648
  };
1619
1649
  },
1620
1650
  {
@@ -1768,16 +1798,20 @@ var ToolRegistryGraph = class extends import_graph4.Graph {
1768
1798
  inner = handlerResultToNode(raw, ac.signal);
1769
1799
  } catch (err) {
1770
1800
  actions.down([[import_core10.ERROR, err]]);
1771
- return () => {
1772
- ac.abort();
1801
+ return {
1802
+ onDeactivation: () => {
1803
+ ac.abort();
1804
+ }
1773
1805
  };
1774
1806
  }
1775
1807
  const unsub = inner.subscribe((batch15) => {
1776
1808
  actions.down(batch15);
1777
1809
  });
1778
- return () => {
1779
- ac.abort();
1780
- unsub();
1810
+ return {
1811
+ onDeactivation: () => {
1812
+ ac.abort();
1813
+ unsub();
1814
+ }
1781
1815
  };
1782
1816
  },
1783
1817
  {
@@ -2013,6 +2047,11 @@ var AgentLoopGraph = class extends import_graph5.Graph {
2013
2047
  chat.append("assistant", response.content, {
2014
2048
  toolCalls: response.toolCalls
2015
2049
  });
2050
+ if (capReached && hasToolCalls) {
2051
+ for (const tc of response.toolCalls) {
2052
+ chat.appendToolResult(tc.id, "[tool call denied: maxTurns reached]");
2053
+ }
2054
+ }
2016
2055
  });
2017
2056
  },
2018
2057
  { describeKind: "effect" }
@@ -2034,6 +2073,45 @@ var AgentLoopGraph = class extends import_graph5.Graph {
2034
2073
  },
2035
2074
  { describeKind: "effect" }
2036
2075
  );
2076
+ const effFullDeny = gatedToolCallsNode !== toolCallsRaw ? (0, import_core11.node)(
2077
+ [toolCallsRaw, gatedToolCallsNode],
2078
+ (batchData) => {
2079
+ if (latestAborted) return;
2080
+ const rawBatch = batchData[0];
2081
+ const gatedBatch = batchData[1];
2082
+ const rawCalls = rawBatch != null && rawBatch.length > 0 ? rawBatch.at(-1) : null;
2083
+ if (rawCalls == null || rawCalls.length === 0) return;
2084
+ const gatedCalls = gatedBatch != null && gatedBatch.length > 0 ? gatedBatch.at(-1) : null;
2085
+ const allowedIds = gatedCalls === null ? null : new Set(gatedCalls.map((c) => c.id));
2086
+ const denied = allowedIds === null ? rawCalls : rawCalls.filter((c) => !allowedIds.has(c.id));
2087
+ if (denied.length === 0) return;
2088
+ const isFullDeny = gatedCalls === null;
2089
+ (0, import_core11.batch)(() => {
2090
+ if (isFullDeny) {
2091
+ statusNode.emit(latestTurn >= maxTurns ? "done" : "thinking");
2092
+ }
2093
+ for (const c of denied)
2094
+ chat.appendToolResult(c.id, "[tool call denied by interceptor]");
2095
+ });
2096
+ },
2097
+ {
2098
+ name: "fullDenyRecovery",
2099
+ describeKind: "effect",
2100
+ meta: aiMeta("agent_full_deny_recovery"),
2101
+ // MUST be explicit: the core `node()` default is
2102
+ // `partial: false` (node.ts `opts.partial ?? false`),
2103
+ // and `gatedToolCallsNode` only ever emits RESOLVED on the
2104
+ // full-deny path (never DATA/terminal). Spec R2.7.0
2105
+ // (DS-2.7.A, 2026-05-19) holds the `partial: false`
2106
+ // first-run gate until every dep has contributed real
2107
+ // DATA, so a `partial: false` effFullDeny would hold the
2108
+ // fn FOREVER. Spec R2.7.2 = `partial: true` disables the
2109
+ // gate; the fn body's `denied`-subtraction guard above
2110
+ // covers the SENTINEL slot per the R2.7.2 author
2111
+ // contract.
2112
+ partial: true
2113
+ }
2114
+ ) : null;
2037
2115
  let latestStatus = statusNode.cache ?? "idle";
2038
2116
  const statusSub = statusNode.subscribe((msgs) => {
2039
2117
  for (const m of msgs) if (m[0] === import_core11.DATA) latestStatus = m[1];
@@ -2053,6 +2131,7 @@ var AgentLoopGraph = class extends import_graph5.Graph {
2053
2131
  );
2054
2132
  const kaResponse = (0, import_extra7.keepalive)(effResponse);
2055
2133
  const kaResults = (0, import_extra7.keepalive)(effResults);
2134
+ const kaFullDeny = effFullDeny ? (0, import_extra7.keepalive)(effFullDeny) : null;
2056
2135
  const kaAbort = (0, import_extra7.keepalive)(effAbort);
2057
2136
  this._terminalResult = (0, import_core11.node)(
2058
2137
  [statusNode, lastResponseState],
@@ -2105,6 +2184,7 @@ var AgentLoopGraph = class extends import_graph5.Graph {
2105
2184
  this.addDisposer(statusSub);
2106
2185
  this.addDisposer(kaResponse);
2107
2186
  this.addDisposer(kaResults);
2187
+ if (kaFullDeny) this.addDisposer(kaFullDeny);
2108
2188
  this.addDisposer(kaAbort);
2109
2189
  this._disposeRunWiring = () => {
2110
2190
  };
@@ -3979,8 +4059,10 @@ function promptNode(adapter, deps, prompt, opts) {
3979
4059
  } catch (err) {
3980
4060
  done = true;
3981
4061
  actions.down([[import_core17.ERROR, err]]);
3982
- return () => {
3983
- abortDispose?.();
4062
+ return {
4063
+ onDeactivation: () => {
4064
+ abortDispose?.();
4065
+ }
3984
4066
  };
3985
4067
  }
3986
4068
  const callNode = (0, import_extra14.fromAny)(invokeResult);
@@ -4038,11 +4120,13 @@ function promptNode(adapter, deps, prompt, opts) {
4038
4120
  }
4039
4121
  }
4040
4122
  });
4041
- return () => {
4042
- cancelled = true;
4043
- sub();
4044
- abortDispose?.();
4045
- abortDispose = void 0;
4123
+ return {
4124
+ onDeactivation: () => {
4125
+ cancelled = true;
4126
+ sub();
4127
+ abortDispose?.();
4128
+ abortDispose = void 0;
4129
+ }
4046
4130
  };
4047
4131
  },
4048
4132
  {
@@ -4609,9 +4693,11 @@ function heterogeneousDebate(parent, opts) {
4609
4693
  if (!cancelled) actions.down([[import_core21.ERROR, err]]);
4610
4694
  }
4611
4695
  })();
4612
- return () => {
4613
- cancelled = true;
4614
- ac.abort();
4696
+ return {
4697
+ onDeactivation: () => {
4698
+ cancelled = true;
4699
+ ac.abort();
4700
+ }
4615
4701
  };
4616
4702
  },
4617
4703
  { describeKind: "producer", name: `${name}.round-work` }
@@ -4748,7 +4834,7 @@ function actorPool(parent, opts = {}) {
4748
4834
  const name = opts.name ?? `actorPool-${++_actorPoolSeq}`;
4749
4835
  const graph = new import_graph12.Graph(name);
4750
4836
  parent.mount(name, graph);
4751
- const depthCap = opts.depthCap ?? Number.POSITIVE_INFINITY;
4837
+ const depthCap = opts.depthCap ?? 8;
4752
4838
  let autoActor = 0;
4753
4839
  const liveHandles = /* @__PURE__ */ new Set();
4754
4840
  const contextPool = taggedContextPool(graph, {
@@ -4852,6 +4938,16 @@ var import_core23 = require("@graphrefly/pure-ts/core");
4852
4938
  var import_extra20 = require("@graphrefly/pure-ts/extra");
4853
4939
  var import_graph13 = require("@graphrefly/pure-ts/graph");
4854
4940
  var RefineLoopGraph = class extends import_graph13.Graph {
4941
+ /**
4942
+ * Best candidate so far. **SENTINEL until the first iteration settles** —
4943
+ * `loop.best.cache` is `undefined` (not `null`) before any iteration
4944
+ * produces a best, and a degenerate empty-candidate iteration leaves the
4945
+ * prior best in place rather than wiping it. Consumers guard with
4946
+ * `=== undefined` (spec §3 SENTINEL), not `== null`. (Anti-pattern sweep
4947
+ * 2026-05-18: dropped the `initial: null` eager-placeholder; `null` is
4948
+ * reserved for the per-iteration {@link Iteration.best} data field where an
4949
+ * empty batch is a valid domain value.)
4950
+ */
4855
4951
  best;
4856
4952
  /**
4857
4953
  * Best score so far. Pseudo-private (`_score`) to avoid colliding with any
@@ -4902,8 +4998,7 @@ var RefineLoopGraph = class extends import_graph13.Graph {
4902
4998
  });
4903
4999
  this.add(strategyNode, { name: "strategy" });
4904
5000
  const lastFeedbackState = (0, import_core23.node)([], {
4905
- name: "lastFeedback",
4906
- initial: null
5001
+ name: "lastFeedback"
4907
5002
  });
4908
5003
  this.add(lastFeedbackState, { name: "lastFeedback" });
4909
5004
  const prevCandidatesState = (0, import_core23.node)([], {
@@ -4922,7 +5017,7 @@ var RefineLoopGraph = class extends import_graph13.Graph {
4922
5017
  // append-style; reactive consumers want every push
4923
5018
  });
4924
5019
  this.add(historyState, { name: "history" });
4925
- const bestState = (0, import_core23.node)([], { name: "best", initial: null });
5020
+ const bestState = (0, import_core23.node)([], { name: "best" });
4926
5021
  this.add(bestState, { name: "best" });
4927
5022
  const scoreState = (0, import_core23.node)([], { name: "score", initial: Number.NEGATIVE_INFINITY });
4928
5023
  this.add(scoreState, { name: "score" });
@@ -4946,7 +5041,7 @@ var RefineLoopGraph = class extends import_graph13.Graph {
4946
5041
  this.decide = hubDecideTopic;
4947
5042
  this._pauseState = pauseState;
4948
5043
  let latestStrategy = initialStrategy;
4949
- let latestFeedback = null;
5044
+ let latestFeedback;
4950
5045
  let latestPrevCandidates = [];
4951
5046
  this.addDisposer(
4952
5047
  strategyNode.subscribe((msgs) => {
@@ -4967,7 +5062,7 @@ var RefineLoopGraph = class extends import_graph13.Graph {
4967
5062
  iterationTrigger,
4968
5063
  (iter) => {
4969
5064
  const strat = latestStrategy;
4970
- const isSeed = iter === 0 || latestFeedback == null;
5065
+ const isSeed = iter === 0 || latestFeedback === void 0;
4971
5066
  return (0, import_core23.node)(
4972
5067
  [],
4973
5068
  (_data, actions) => {
@@ -4983,8 +5078,10 @@ var RefineLoopGraph = class extends import_graph13.Graph {
4983
5078
  if (!cancelled) actions.down([[import_core23.ERROR, err]]);
4984
5079
  }
4985
5080
  );
4986
- return () => {
4987
- cancelled = true;
5081
+ return {
5082
+ onDeactivation: () => {
5083
+ cancelled = true;
5084
+ }
4988
5085
  };
4989
5086
  }
4990
5087
  actions.emit({ iter, items: result });
@@ -5357,7 +5454,7 @@ var RefineLoopGraph = class extends import_graph13.Graph {
5357
5454
  decision = "paused";
5358
5455
  }
5359
5456
  (0, import_core23.batch)(() => {
5360
- bestState.emit(best);
5457
+ if (best !== null) bestState.emit(best);
5361
5458
  scoreState.emit(fb.score);
5362
5459
  historyState.emit(nextHistory);
5363
5460
  budgetState.emit(nextBudget);
@@ -5597,7 +5694,7 @@ function errorCritique(opts) {
5597
5694
  function defaultToOutput(result) {
5598
5695
  const { best, score, status } = result;
5599
5696
  const scoreStr = Number.isFinite(score) ? score.toFixed(3) : String(score);
5600
- const artifact = best ?? void 0;
5697
+ const artifact = best;
5601
5698
  if (status === "converged") {
5602
5699
  return {
5603
5700
  outcome: "success",
@@ -5850,7 +5947,7 @@ function withStatus(src, options) {
5850
5947
  } else a.down([m]);
5851
5948
  }
5852
5949
  });
5853
- return unsub;
5950
+ return { onDeactivation: unsub };
5854
5951
  },
5855
5952
  {
5856
5953
  ...operatorOpts(),
@@ -6075,7 +6172,7 @@ function withBreaker(breaker, options) {
6075
6172
  }
6076
6173
  });
6077
6174
  syncState();
6078
- return unsub;
6175
+ return { onDeactivation: unsub };
6079
6176
  },
6080
6177
  {
6081
6178
  ...operatorOpts(),
@@ -6217,8 +6314,10 @@ function budgetGate(source, constraints, opts) {
6217
6314
  })
6218
6315
  );
6219
6316
  }
6220
- return () => {
6221
- for (const u of unsubs) u();
6317
+ return {
6318
+ onDeactivation: () => {
6319
+ for (const u of unsubs) u();
6320
+ }
6222
6321
  };
6223
6322
  },
6224
6323
  {
@@ -6348,9 +6447,11 @@ function fallback(source, fb, options) {
6348
6447
  } else a.down([m]);
6349
6448
  }
6350
6449
  });
6351
- return () => {
6352
- sourceUnsub?.();
6353
- fallbackUnsub?.();
6450
+ return {
6451
+ onDeactivation: () => {
6452
+ sourceUnsub?.();
6453
+ fallbackUnsub?.();
6454
+ }
6354
6455
  };
6355
6456
  },
6356
6457
  {
@@ -6415,31 +6516,40 @@ var RATE_LIMITER_INITIAL_STATE = Object.freeze({
6415
6516
  pendingCount: 0,
6416
6517
  paused: false
6417
6518
  });
6519
+ function validateRateLimiterOpts(o) {
6520
+ if (o.maxEvents <= 0) throw new RangeError("maxEvents must be > 0");
6521
+ if (o.windowNs <= 0) throw new RangeError("windowNs must be > 0");
6522
+ if (o.maxBuffer === void 0) {
6523
+ throw new RangeError(
6524
+ "rateLimiter requires explicit maxBuffer (use Infinity to opt in to unbounded)"
6525
+ );
6526
+ }
6527
+ const isUnbounded = o.maxBuffer === Infinity;
6528
+ if (!isUnbounded && (!Number.isInteger(o.maxBuffer) || o.maxBuffer < 1)) {
6529
+ throw new RangeError("maxBuffer must be a positive integer (or Infinity for unbounded)");
6530
+ }
6531
+ }
6532
+ function resolveInitialReactiveOpts(optsNode) {
6533
+ const cached = optsNode.cache;
6534
+ if (cached === void 0) {
6535
+ throw new RangeError(
6536
+ "rateLimiter: reactive (Node-form) opts must carry a cached value at construction \u2014 seed the opts Node with `initial`. Mode (bounded vs unbounded) and the initial cap are LOCKED from `.cache` at construction and the swap handler rejects mode toggles; an un-seeded Node would silently lock bounded `maxBuffer: 1` (D4)."
6537
+ );
6538
+ }
6539
+ return cached;
6540
+ }
6418
6541
  function rateLimiter(source, opts) {
6419
6542
  const isReactive = isNode(opts);
6420
- if (!isReactive) {
6421
- const o = opts;
6422
- if (o.maxEvents <= 0) throw new RangeError("maxEvents must be > 0");
6423
- if (o.windowNs <= 0) throw new RangeError("windowNs must be > 0");
6424
- if (o.maxBuffer === void 0) {
6425
- throw new RangeError(
6426
- "rateLimiter requires explicit maxBuffer (use Infinity to opt in to unbounded)"
6427
- );
6428
- }
6429
- const isUnbounded0 = o.maxBuffer === Infinity;
6430
- if (!isUnbounded0 && (!Number.isInteger(o.maxBuffer) || o.maxBuffer < 1)) {
6431
- throw new RangeError("maxBuffer must be a positive integer (or Infinity for unbounded)");
6432
- }
6433
- }
6434
- const initialOpts = isReactive ? opts.cache : opts;
6435
- const initialMaxBuffer = initialOpts?.maxBuffer;
6543
+ const initialOpts = isReactive ? resolveInitialReactiveOpts(opts) : opts;
6544
+ validateRateLimiterOpts(initialOpts);
6545
+ const initialMaxBuffer = initialOpts.maxBuffer;
6436
6546
  const isUnbounded = initialMaxBuffer === Infinity;
6437
6547
  const out = (0, import_core30.node)(
6438
6548
  (_data, a) => {
6439
- let maxEvents = initialOpts?.maxEvents ?? 1;
6440
- let windowNs = initialOpts?.windowNs ?? NS_PER_SEC;
6441
- let maxBuffer = initialMaxBuffer ?? 1;
6442
- let onOverflow = initialOpts?.onOverflow ?? "drop-newest";
6549
+ let maxEvents = initialOpts.maxEvents;
6550
+ let windowNs = initialOpts.windowNs;
6551
+ let maxBuffer = initialMaxBuffer;
6552
+ let onOverflow = initialOpts.onOverflow ?? "drop-newest";
6443
6553
  let refillPerSec = maxEvents * NS_PER_SEC / windowNs;
6444
6554
  let tokenTimeNs = NS_PER_SEC / refillPerSec;
6445
6555
  let bucket = tokenBucket(maxEvents, refillPerSec);
@@ -6562,11 +6672,13 @@ function rateLimiter(source, opts) {
6562
6672
  } else a.down([m]);
6563
6673
  }
6564
6674
  });
6565
- return () => {
6566
- terminated = true;
6567
- timer.cancel();
6568
- unsub();
6569
- optMirror.unsub();
6675
+ return {
6676
+ onDeactivation: () => {
6677
+ terminated = true;
6678
+ timer.cancel();
6679
+ unsub();
6680
+ optMirror.unsub();
6681
+ }
6570
6682
  };
6571
6683
  },
6572
6684
  {
@@ -6808,6 +6920,10 @@ var PipelineGraph = class extends import_graph15.Graph {
6808
6920
  {
6809
6921
  name,
6810
6922
  describeKind: "derived",
6923
+ // Spec §2.7 R2.7.1 (DS-2.7.A). fn must fire on
6924
+ // upstream-COMPLETE/ERROR-only-without-DATA so the
6925
+ // teardown-decision record + downstream terminal forward run.
6926
+ terminalAsRealInput: true,
6811
6927
  meta: meta("approval_gate", opts.meta)
6812
6928
  }
6813
6929
  );
@@ -7025,6 +7141,11 @@ var PipelineGraph = class extends import_graph15.Graph {
7025
7141
  describeKind: "derived",
7026
7142
  completeWhenDepsComplete: opts.completeWhenDepsComplete ?? !(mode === "completed" || mode === "terminal"),
7027
7143
  errorWhenDepsError: !(mode === "errored" || mode === "terminal"),
7144
+ // Spec §2.7 R2.7.1 (DS-2.7.A). `catch` exists to fire on a
7145
+ // source terminal — its whole job is `recover(cause, …)` on a
7146
+ // terminal-only wave. Without this opt-in the gate holds and
7147
+ // the recover branch never runs.
7148
+ terminalAsRealInput: true,
7028
7149
  meta: meta("catch", opts.meta)
7029
7150
  }
7030
7151
  );
@@ -7227,7 +7348,10 @@ var JobQueueGraph = class extends import_graph17.Graph {
7227
7348
  depth;
7228
7349
  /** Audit log of every queue mutation (Audit 2). */
7229
7350
  events;
7230
- /** Alias for {@link JobQueueGraph.events} — Audit 2 `.audit` duplication. */
7351
+ /**
7352
+ * Read-only view of {@link JobQueueGraph.events} — Audit 2 `.audit`
7353
+ * duplication; M7 (cannot mutate the canonical log via the alias).
7354
+ */
7231
7355
  audit;
7232
7356
  // Tier 8 / COMPOSITION-GUIDE §35: mutate wrappers for the four
7233
7357
  // single-record mutation methods. Assigned in the constructor (NOT via
@@ -7268,7 +7392,7 @@ var JobQueueGraph = class extends import_graph17.Graph {
7268
7392
  retainedLimit: 1024,
7269
7393
  graph: this
7270
7394
  });
7271
- this.audit = this.events;
7395
+ this.audit = readonlyAuditLog(this.events);
7272
7396
  this._seqCursor = registerCursor(this, "seq", 0);
7273
7397
  this._enqueueImpl = mutate(
7274
7398
  (payload, enqueueOpts) => {
@@ -7321,7 +7445,7 @@ var JobQueueGraph = class extends import_graph17.Graph {
7321
7445
  }
7322
7446
  );
7323
7447
  this._nackImpl = mutate(
7324
- (id, job, requeue) => {
7448
+ (id, job, requeue, _error) => {
7325
7449
  if (requeue) {
7326
7450
  this._jobs.set(id, { ...job, state: "queued" });
7327
7451
  this._pending.append(id);
@@ -7334,12 +7458,16 @@ var JobQueueGraph = class extends import_graph17.Graph {
7334
7458
  log: this.events,
7335
7459
  seq: this._seqCursor,
7336
7460
  freeze: false,
7337
- onSuccessRecord: ([id, job], _r, { t_ns, seq }) => ({
7461
+ onSuccessRecord: ([id, job, requeue, error], _r, { t_ns, seq }) => ({
7338
7462
  action: "nack",
7339
7463
  id,
7340
7464
  attempts: job.attempts,
7341
7465
  t_ns,
7342
- seq: seq ?? 0
7466
+ seq: seq ?? 0,
7467
+ // F-CATCH D-3: surface the failure cause on the no-requeue
7468
+ // (terminal-failure) nack only. A requeue nack is a retry,
7469
+ // not a failure, so it carries no error.
7470
+ ...!requeue && error !== void 0 ? { error } : {}
7343
7471
  })
7344
7472
  }
7345
7473
  );
@@ -7411,10 +7539,20 @@ var JobQueueGraph = class extends import_graph17.Graph {
7411
7539
  this._ackImpl(id, job);
7412
7540
  return true;
7413
7541
  }
7542
+ /**
7543
+ * Negatively-acknowledge an inflight job.
7544
+ *
7545
+ * @param opts.requeue - `true` (default) returns the job to the queue for
7546
+ * retry; `false` drops it permanently (terminal failure).
7547
+ * @param opts.error - Optional failure cause for a `requeue: false` nack.
7548
+ * Recorded on the emitted `"nack"` {@link JobEvent} as `error` so the
7549
+ * reason a job failed is recoverable from the event stream (F-CATCH
7550
+ * D-3). Ignored when `requeue` is `true` (a retry is not a failure).
7551
+ */
7414
7552
  nack(id, opts = {}) {
7415
7553
  const job = this._jobs.get(id);
7416
7554
  if (!job || job.state !== "inflight") return false;
7417
- this._nackImpl(id, job, opts.requeue ?? true);
7555
+ this._nackImpl(id, job, opts.requeue ?? true, opts.error);
7418
7556
  return true;
7419
7557
  }
7420
7558
  /**
@@ -7580,10 +7718,10 @@ var JobFlowGraph = class extends import_graph17.Graph {
7580
7718
  let result;
7581
7719
  try {
7582
7720
  result = workFn(job, { signal: ac.signal });
7583
- } catch {
7721
+ } catch (err) {
7584
7722
  inflight.delete(entry);
7585
7723
  inflightCounter?.emit(inflight.size);
7586
- current.nack(job.id, { requeue: false });
7724
+ current.nack(job.id, { requeue: false, error: err });
7587
7725
  processed += 1;
7588
7726
  continue;
7589
7727
  }
@@ -7634,7 +7772,7 @@ var JobFlowGraph = class extends import_graph17.Graph {
7634
7772
  } else if (m[0] === import_core33.ERROR) {
7635
7773
  settled = true;
7636
7774
  cleanupSub();
7637
- current.nack(job.id, { requeue: false });
7775
+ current.nack(job.id, { requeue: false, error: m[1] });
7638
7776
  return;
7639
7777
  }
7640
7778
  }
@@ -7890,7 +8028,18 @@ var HarnessGraph = class extends import_graph18.Graph {
7890
8028
  * (use {@link unrouted}), and the internal `triage-output` fan-in.
7891
8029
  */
7892
8030
  queueTopics;
7893
- /** Strategy model — `auditedSuccessTracker` keyed by `StrategyKey`. */
8031
+ /**
8032
+ * Strategy model — `auditedSuccessTracker` keyed by `StrategyKey`.
8033
+ *
8034
+ * **Ownership (EC10/EC15).** Owned by the harness: it is mounted as a
8035
+ * child subgraph (`harness.mount("strategy", strategy)`), so its disposal
8036
+ * cascades from `harness.destroy()` via the mount lifecycle. Do **not**
8037
+ * call `strategy.destroy()` independently — the harness's `triage-input`
8038
+ * node and (when `opts.priority` is set) `buildPriorityScores` hold
8039
+ * cross-graph deps on `strategy.entries`; destroying the strategy out of
8040
+ * band staleness those nodes while the rest of the loop keeps running.
8041
+ * Read/subscribe freely; let the harness own the lifecycle.
8042
+ */
7894
8043
  strategy;
7895
8044
  /** Global retry count across all items (circuit breaker). Reactive — subscribable. */
7896
8045
  totalRetries;
@@ -9190,7 +9339,11 @@ function healthReportEqual(a, b) {
9190
9339
  }
9191
9340
  return true;
9192
9341
  }
9193
- function graphLens(target) {
9342
+ function graphLens(target, opts = {}) {
9343
+ const mutLogOpt = opts.mutations;
9344
+ const mutationsEnabled = mutLogOpt != null;
9345
+ const pendingFlowChanges = [];
9346
+ let disposed = false;
9194
9347
  const topologyHandle = target.describe({
9195
9348
  reactive: true,
9196
9349
  detail: "standard",
@@ -9233,17 +9386,26 @@ function graphLens(target) {
9233
9386
  const path = event.path;
9234
9387
  if (path == null || path === "") continue;
9235
9388
  const prior = flowMap.get(path);
9389
+ const count = (prior?.count ?? 0) + 1;
9236
9390
  flowMap.set(path, {
9237
9391
  path,
9238
- count: (prior?.count ?? 0) + 1,
9392
+ count,
9239
9393
  lastUpdate_ns: c.flushedAt_ns
9240
9394
  });
9395
+ if (mutationsEnabled && !disposed) {
9396
+ pendingFlowChanges.push({ kind: "tick", path, count });
9397
+ }
9241
9398
  }
9242
9399
  }
9243
9400
  if (desc != null && flowMap.size > 0) {
9244
9401
  const valid = new Set(Object.keys(desc.nodes));
9245
9402
  for (const k of [...flowMap.keys()]) {
9246
- if (!valid.has(k)) flowMap.delete(k);
9403
+ if (!valid.has(k)) {
9404
+ flowMap.delete(k);
9405
+ if (mutationsEnabled && !disposed) {
9406
+ pendingFlowChanges.push({ kind: "evict", path: k });
9407
+ }
9408
+ }
9247
9409
  }
9248
9410
  }
9249
9411
  actions.emit(new Map(flowMap));
@@ -9254,15 +9416,50 @@ function graphLens(target) {
9254
9416
  meta: domainMeta("lens", "flow")
9255
9417
  }
9256
9418
  );
9419
+ let flowMutations;
9420
+ let stopFlowMutKeep;
9421
+ if (mutLogOpt != null) {
9422
+ const log = (0, import_extra30.reactiveLog)(void 0, {
9423
+ name: mutLogOpt === true ? "graphLens.flowMutations" : mutLogOpt.name ?? "graphLens.flowMutations",
9424
+ maxSize: mutLogOpt === true ? void 0 : mutLogOpt.maxSize
9425
+ });
9426
+ flowMutations = log;
9427
+ let mutVersion = 0;
9428
+ const flowMutationsDrain = (0, import_core39.node)(
9429
+ [flow],
9430
+ (_batchData, _actions, _ctx) => {
9431
+ if (pendingFlowChanges.length === 0) return;
9432
+ const drained = pendingFlowChanges.splice(0);
9433
+ for (const change of drained) {
9434
+ log.append({
9435
+ structure: "lensFlow",
9436
+ version: ++mutVersion,
9437
+ t_ns: (0, import_core39.wallClockNs)(),
9438
+ lifecycle: "data",
9439
+ change
9440
+ });
9441
+ }
9442
+ },
9443
+ {
9444
+ name: "graphLens.flowMutationsDrain",
9445
+ describeKind: "effect",
9446
+ meta: domainMeta("lens", "flowMutations")
9447
+ }
9448
+ );
9449
+ stopFlowMutKeep = (0, import_extra30.keepalive)(flowMutationsDrain);
9450
+ }
9257
9451
  const stopFlowKeep = (0, import_extra30.keepalive)(flow);
9258
- let disposed = false;
9259
9452
  return {
9260
9453
  topology,
9261
9454
  health,
9262
9455
  flow,
9456
+ ...flowMutations ? { flowMutations } : {},
9263
9457
  dispose() {
9264
9458
  if (disposed) return;
9265
9459
  disposed = true;
9460
+ stopFlowMutKeep?.();
9461
+ flowMutations?.dispose();
9462
+ pendingFlowChanges.length = 0;
9266
9463
  stopFlowKeep();
9267
9464
  stopHealthKeep();
9268
9465
  topologyHandle.dispose();
@@ -9481,11 +9678,12 @@ var GuardedExecutionGraph = class extends import_graph26.Graph {
9481
9678
  this.addDisposer((0, import_extra31.keepalive)(this.scope));
9482
9679
  const scopedHandle = target.describe({
9483
9680
  reactive: true,
9484
- // F8 (Tier 5.2): `_actorNode` is `Node<Actor | null>`. The cast is
9485
- // safe at runtime per the `resolveActorOption` null-tolerance
9486
- // contract `null` / `undefined` cache is treated as "no scoping"
9487
- // (full visibility). See `scopedDescribeNode` for the matching
9488
- // per-call site and graph.ts § "Cache-undefined semantics".
9681
+ // F8 (resolved 2026-05-18): `GraphDescribeOptions.actor` is now
9682
+ // `Actor | Node<Actor | null>`, so `_actorNode` (a
9683
+ // `Node<Actor | null>`) passes without a cast. A `null`/`undefined`
9684
+ // cache resolves to "no scoping" (full visibility) per
9685
+ // `resolveActorOption`. See graph.ts § "Cache-undefined/null
9686
+ // semantics".
9489
9687
  actor: this._actorNode,
9490
9688
  reactiveName: "scopedDescribe"
9491
9689
  });
@@ -9531,11 +9729,11 @@ var GuardedExecutionGraph = class extends import_graph26.Graph {
9531
9729
  const actorNode = actorOverride == null ? this._actorNode : isNode4(actorOverride) ? actorOverride : (0, import_core41.node)([], { name: "actor_override", initial: actorOverride });
9532
9730
  const handle = this._target.describe({
9533
9731
  reactive: true,
9534
- // `_actorNode` is `Node<Actor | null>`. The `as Node<Actor>` cast is
9535
- // safe at runtime: `_describeReactive` resolves the actor via
9536
- // `resolveActorOption`, which treats `null`/`undefined` cache as
9537
- // "no scoping" (full visibility). Documented in graph.ts §
9538
- // "Cache-undefined semantics."
9732
+ // F8 (resolved 2026-05-18): `actor` accepts `Node<Actor | null>`
9733
+ // directly. `actorNode` is `_actorNode` (`Node<Actor | null>`) or
9734
+ // an override (`Node<Actor>`/`Node<Actor | null>`); both assign
9735
+ // without a cast. `_describeReactive` resolves via
9736
+ // `resolveActorOption` (null/undefined cache → no scoping).
9539
9737
  actor: actorNode,
9540
9738
  ...opts ?? {}
9541
9739
  });
@@ -9636,7 +9834,6 @@ var ResilientPipelineGraph = class extends import_graph27.Graph {
9636
9834
  } else {
9637
9835
  const rateOpts = {
9638
9836
  ...opts.rateLimit,
9639
- maxBuffer: opts.rateLimit.maxBuffer ?? Infinity,
9640
9837
  meta: domainMeta("resilient", "rate-limit")
9641
9838
  };
9642
9839
  const bundle = rateLimiter(current, rateOpts);