@graphrefly/graphrefly 0.45.0 → 0.47.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.
- package/README.md +1 -2
- package/dist/_internal-B23BagFd.d.cts +33 -0
- package/dist/_internal-B23BagFd.d.ts +33 -0
- package/dist/adaptive-rate-limiter-Dch_xYIi.d.cts +111 -0
- package/dist/adaptive-rate-limiter-Dch_xYIi.d.ts +111 -0
- package/dist/agents-C0Ji9ldU.d.cts +629 -0
- package/dist/agents-C9zexT7I.d.ts +629 -0
- package/dist/audit-BAXb3VOg.d.ts +246 -0
- package/dist/audit-C_bPfkqS.d.cts +246 -0
- package/dist/backoff-7KIK3WQW.js +24 -0
- package/dist/backoff-7KIK3WQW.js.map +1 -0
- package/dist/backoff-Bnb9OoPh.d.cts +6 -0
- package/dist/backoff-Bnb9OoPh.d.ts +6 -0
- package/dist/base/composition/index.cjs +865 -0
- package/dist/base/composition/index.cjs.map +1 -0
- package/dist/base/composition/index.d.cts +468 -0
- package/dist/base/composition/index.d.ts +468 -0
- package/dist/base/composition/index.js +40 -0
- package/dist/base/composition/index.js.map +1 -0
- package/dist/base/index.cjs +6390 -0
- package/dist/base/index.cjs.map +1 -0
- package/dist/base/index.d.cts +21 -0
- package/dist/base/index.d.ts +21 -0
- package/dist/base/index.js +259 -0
- package/dist/base/index.js.map +1 -0
- package/dist/base/io/index.cjs +3270 -0
- package/dist/base/io/index.cjs.map +1 -0
- package/dist/base/io/index.d.cts +2245 -0
- package/dist/base/io/index.d.ts +2245 -0
- package/dist/base/io/index.js +117 -0
- package/dist/base/io/index.js.map +1 -0
- package/dist/base/meta/index.cjs +43 -0
- package/dist/base/meta/index.cjs.map +1 -0
- package/dist/base/meta/index.d.cts +45 -0
- package/dist/base/meta/index.d.ts +45 -0
- package/dist/base/meta/index.js +13 -0
- package/dist/base/meta/index.js.map +1 -0
- package/dist/base/mutation/index.cjs +200 -0
- package/dist/base/mutation/index.cjs.map +1 -0
- package/dist/base/mutation/index.d.cts +177 -0
- package/dist/base/mutation/index.d.ts +177 -0
- package/dist/base/mutation/index.js +22 -0
- package/dist/base/mutation/index.js.map +1 -0
- package/dist/base/render/index.cjs +1120 -0
- package/dist/base/render/index.cjs.map +1 -0
- package/dist/base/render/index.d.cts +227 -0
- package/dist/base/render/index.d.ts +227 -0
- package/dist/base/render/index.js +24 -0
- package/dist/base/render/index.js.map +1 -0
- package/dist/base/sources/browser/index.cjs +172 -0
- package/dist/base/sources/browser/index.cjs.map +1 -0
- package/dist/base/sources/browser/index.d.cts +84 -0
- package/dist/base/sources/browser/index.d.ts +84 -0
- package/dist/base/sources/browser/index.js +151 -0
- package/dist/base/sources/browser/index.js.map +1 -0
- package/dist/base/sources/event/index.cjs +98 -0
- package/dist/base/sources/event/index.cjs.map +1 -0
- package/dist/base/sources/event/index.d.cts +91 -0
- package/dist/base/sources/event/index.d.ts +91 -0
- package/dist/base/sources/event/index.js +13 -0
- package/dist/base/sources/event/index.js.map +1 -0
- package/dist/base/sources/index.cjs +755 -0
- package/dist/base/sources/index.cjs.map +1 -0
- package/dist/base/sources/index.d.cts +357 -0
- package/dist/base/sources/index.d.ts +357 -0
- package/dist/base/sources/index.js +42 -0
- package/dist/base/sources/index.js.map +1 -0
- package/dist/base/sources/node/index.cjs +320 -0
- package/dist/base/sources/node/index.cjs.map +1 -0
- package/dist/base/sources/node/index.d.cts +185 -0
- package/dist/base/sources/node/index.d.ts +185 -0
- package/dist/base/sources/node/index.js +306 -0
- package/dist/base/sources/node/index.js.map +1 -0
- package/dist/base/utils/index.cjs +37 -0
- package/dist/base/utils/index.cjs.map +1 -0
- package/dist/base/utils/index.d.cts +37 -0
- package/dist/base/utils/index.d.ts +37 -0
- package/dist/base/utils/index.js +11 -0
- package/dist/base/utils/index.js.map +1 -0
- package/dist/base/worker/index.cjs +548 -0
- package/dist/base/worker/index.cjs.map +1 -0
- package/dist/base/worker/index.d.cts +207 -0
- package/dist/base/worker/index.d.ts +207 -0
- package/dist/base/worker/index.js +20 -0
- package/dist/base/worker/index.js.map +1 -0
- package/dist/breaker-C9skL3d8.d.ts +175 -0
- package/dist/breaker-ugSdq54q.d.cts +175 -0
- package/dist/cascading-CSSbKGrJ.d.ts +199 -0
- package/dist/cascading-baGkiihI.d.cts +199 -0
- package/dist/chunk-22SG74BD.js +207 -0
- package/dist/chunk-22SG74BD.js.map +1 -0
- package/dist/chunk-255UCBG4.js +58 -0
- package/dist/chunk-255UCBG4.js.map +1 -0
- package/dist/chunk-2LO3EL4W.js +1 -0
- package/dist/chunk-2LO3EL4W.js.map +1 -0
- package/dist/chunk-2OB3CEJS.js +1065 -0
- package/dist/chunk-2OB3CEJS.js.map +1 -0
- package/dist/chunk-36NMM65U.js +144 -0
- package/dist/chunk-36NMM65U.js.map +1 -0
- package/dist/chunk-3CEXCBN6.js +1 -0
- package/dist/chunk-3CEXCBN6.js.map +1 -0
- package/dist/chunk-3MUSLI6E.js +105 -0
- package/dist/chunk-3MUSLI6E.js.map +1 -0
- package/dist/chunk-3PSLNJDU.js +884 -0
- package/dist/chunk-3PSLNJDU.js.map +1 -0
- package/dist/chunk-42FQ27MQ.js +594 -0
- package/dist/chunk-42FQ27MQ.js.map +1 -0
- package/dist/chunk-4GYMCUDZ.js +1085 -0
- package/dist/chunk-4GYMCUDZ.js.map +1 -0
- package/dist/chunk-4S53H2KR.js +382 -0
- package/dist/chunk-4S53H2KR.js.map +1 -0
- package/dist/chunk-4XCHZRUJ.js +128 -0
- package/dist/chunk-4XCHZRUJ.js.map +1 -0
- package/dist/chunk-5IMMNARC.js +1153 -0
- package/dist/chunk-5IMMNARC.js.map +1 -0
- package/dist/chunk-6XZYT4SW.js +256 -0
- package/dist/chunk-6XZYT4SW.js.map +1 -0
- package/dist/chunk-7EGRP2VX.js +76 -0
- package/dist/chunk-7EGRP2VX.js.map +1 -0
- package/dist/chunk-A7KV5UK4.js +150 -0
- package/dist/chunk-A7KV5UK4.js.map +1 -0
- package/dist/chunk-APY2SS5X.js +156 -0
- package/dist/chunk-APY2SS5X.js.map +1 -0
- package/dist/chunk-AZDQPQ3V.js +66 -0
- package/dist/chunk-AZDQPQ3V.js.map +1 -0
- package/dist/chunk-BU3SEFA5.js +90 -0
- package/dist/chunk-BU3SEFA5.js.map +1 -0
- package/dist/chunk-BXGZFGZ4.js +189 -0
- package/dist/chunk-BXGZFGZ4.js.map +1 -0
- package/dist/chunk-CGHORL6G.js +579 -0
- package/dist/chunk-CGHORL6G.js.map +1 -0
- package/dist/chunk-CXANAIZU.js +530 -0
- package/dist/chunk-CXANAIZU.js.map +1 -0
- package/dist/chunk-CZQHCKKG.js +1 -0
- package/dist/chunk-CZQHCKKG.js.map +1 -0
- package/dist/chunk-DKNHAICT.js +133 -0
- package/dist/chunk-DKNHAICT.js.map +1 -0
- package/dist/chunk-DM4OMPWK.js +584 -0
- package/dist/chunk-DM4OMPWK.js.map +1 -0
- package/dist/chunk-DMSNO6ZB.js +452 -0
- package/dist/chunk-DMSNO6ZB.js.map +1 -0
- package/dist/chunk-E5OZPDIW.js +229 -0
- package/dist/chunk-E5OZPDIW.js.map +1 -0
- package/dist/chunk-EHRRQ4IC.js +211 -0
- package/dist/chunk-EHRRQ4IC.js.map +1 -0
- package/dist/chunk-EVYY4X5A.js +509 -0
- package/dist/chunk-EVYY4X5A.js.map +1 -0
- package/dist/chunk-FDFD67UO.js +1 -0
- package/dist/chunk-FDFD67UO.js.map +1 -0
- package/dist/chunk-FMPF42Q4.js +13 -0
- package/dist/chunk-FMPF42Q4.js.map +1 -0
- package/dist/chunk-FW23JYNQ.js +454 -0
- package/dist/chunk-FW23JYNQ.js.map +1 -0
- package/dist/chunk-GWRNLJNW.js +2508 -0
- package/dist/chunk-GWRNLJNW.js.map +1 -0
- package/dist/chunk-HL7HUJIX.js +1 -0
- package/dist/chunk-HL7HUJIX.js.map +1 -0
- package/dist/chunk-IHTWQEDR.js +169 -0
- package/dist/chunk-IHTWQEDR.js.map +1 -0
- package/dist/chunk-IJRR6YAI.js +128 -0
- package/dist/chunk-IJRR6YAI.js.map +1 -0
- package/dist/chunk-JGFRAFDL.js +221 -0
- package/dist/chunk-JGFRAFDL.js.map +1 -0
- package/dist/chunk-JKTC747G.js +725 -0
- package/dist/chunk-JKTC747G.js.map +1 -0
- package/dist/chunk-KN3H5CNT.js +11 -0
- package/dist/chunk-KN3H5CNT.js.map +1 -0
- package/dist/chunk-KPG3DGLA.js +1 -0
- package/dist/chunk-KPG3DGLA.js.map +1 -0
- package/dist/chunk-KRNQ6RGQ.js +1 -0
- package/dist/chunk-KRNQ6RGQ.js.map +1 -0
- package/dist/chunk-MLTPJMH6.js +417 -0
- package/dist/chunk-MLTPJMH6.js.map +1 -0
- package/dist/chunk-N3SZ7BMH.js +95 -0
- package/dist/chunk-N3SZ7BMH.js.map +1 -0
- package/dist/chunk-NDUD3IMO.js +540 -0
- package/dist/chunk-NDUD3IMO.js.map +1 -0
- package/dist/chunk-NY2PYHNC.js +873 -0
- package/dist/chunk-NY2PYHNC.js.map +1 -0
- package/dist/chunk-O3MT7DYI.js +225 -0
- package/dist/chunk-O3MT7DYI.js.map +1 -0
- package/dist/chunk-OCUDSN63.js +2386 -0
- package/dist/chunk-OCUDSN63.js.map +1 -0
- package/dist/chunk-OIWU3NYV.js +199 -0
- package/dist/chunk-OIWU3NYV.js.map +1 -0
- package/dist/chunk-OQUIJT7A.js +1 -0
- package/dist/chunk-OQUIJT7A.js.map +1 -0
- package/dist/chunk-P5LBT622.js +105 -0
- package/dist/chunk-P5LBT622.js.map +1 -0
- package/dist/chunk-PKGQG5QQ.js +519 -0
- package/dist/chunk-PKGQG5QQ.js.map +1 -0
- package/dist/chunk-PKPO3JTZ.js +561 -0
- package/dist/chunk-PKPO3JTZ.js.map +1 -0
- package/dist/chunk-PL5UDIQ5.js +118 -0
- package/dist/chunk-PL5UDIQ5.js.map +1 -0
- package/dist/chunk-PZWISPIQ.js +432 -0
- package/dist/chunk-PZWISPIQ.js.map +1 -0
- package/dist/chunk-Q3EYOCZB.js +510 -0
- package/dist/chunk-Q3EYOCZB.js.map +1 -0
- package/dist/chunk-QMBYUVRL.js +15 -0
- package/dist/chunk-QMBYUVRL.js.map +1 -0
- package/dist/chunk-RAGGHLCV.js +200 -0
- package/dist/chunk-RAGGHLCV.js.map +1 -0
- package/dist/chunk-RJOG4IJU.js +1039 -0
- package/dist/chunk-RJOG4IJU.js.map +1 -0
- package/dist/chunk-SOOKUYVM.js +403 -0
- package/dist/chunk-SOOKUYVM.js.map +1 -0
- package/dist/chunk-T5BN5KG7.js +1 -0
- package/dist/chunk-T5BN5KG7.js.map +1 -0
- package/dist/chunk-TNX5ZGDJ.js +574 -0
- package/dist/chunk-TNX5ZGDJ.js.map +1 -0
- package/dist/chunk-TP7244Y6.js +207 -0
- package/dist/chunk-TP7244Y6.js.map +1 -0
- package/dist/chunk-TSBFTJKM.js +57 -0
- package/dist/chunk-TSBFTJKM.js.map +1 -0
- package/dist/chunk-URQ2CBBF.js +143 -0
- package/dist/chunk-URQ2CBBF.js.map +1 -0
- package/dist/chunk-VLAGJZSL.js +1079 -0
- package/dist/chunk-VLAGJZSL.js.map +1 -0
- package/dist/chunk-W2BOPXTI.js +1 -0
- package/dist/chunk-W2BOPXTI.js.map +1 -0
- package/dist/chunk-Y52CS6YA.js +88 -0
- package/dist/chunk-Y52CS6YA.js.map +1 -0
- package/dist/chunk-YCBUWK77.js +92 -0
- package/dist/chunk-YCBUWK77.js.map +1 -0
- package/dist/chunk-YJ4U2D2C.js +314 -0
- package/dist/chunk-YJ4U2D2C.js.map +1 -0
- package/dist/chunk-Z4YXAUDN.js +239 -0
- package/dist/chunk-Z4YXAUDN.js.map +1 -0
- package/dist/chunk-Z65DVDEQ.js +146 -0
- package/dist/chunk-Z65DVDEQ.js.map +1 -0
- package/dist/chunk-Z6EGP5D7.js +92 -0
- package/dist/chunk-Z6EGP5D7.js.map +1 -0
- package/dist/chunk-ZT4WMQW4.js +1575 -0
- package/dist/chunk-ZT4WMQW4.js.map +1 -0
- package/dist/chunk-ZVXXDWIB.js +1282 -0
- package/dist/chunk-ZVXXDWIB.js.map +1 -0
- package/dist/compat/index.cjs +3150 -6
- package/dist/compat/index.cjs.map +1 -1
- package/dist/compat/index.d.cts +116 -1
- package/dist/compat/index.d.ts +116 -1
- package/dist/compat/index.js +175 -2
- package/dist/compat/index.js.map +1 -1
- package/dist/compat/jotai/index.cjs +130 -2
- package/dist/compat/jotai/index.cjs.map +1 -1
- package/dist/compat/jotai/index.d.cts +2 -1
- package/dist/compat/jotai/index.d.ts +2 -1
- package/dist/compat/jotai/index.js +7 -2
- package/dist/compat/jotai/index.js.map +1 -1
- package/dist/compat/nanostores/index.cjs +186 -2
- package/dist/compat/nanostores/index.cjs.map +1 -1
- package/dist/compat/nanostores/index.d.cts +2 -1
- package/dist/compat/nanostores/index.d.ts +2 -1
- package/dist/compat/nanostores/index.js +21 -2
- package/dist/compat/nanostores/index.js.map +1 -1
- package/dist/compat/nestjs/index.cjs +2291 -6
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +10 -1
- package/dist/compat/nestjs/index.d.ts +10 -1
- package/dist/compat/nestjs/index.js +76 -2
- package/dist/compat/nestjs/index.js.map +1 -1
- package/dist/compat/react/index.cjs +95 -2
- package/dist/compat/react/index.cjs.map +1 -1
- package/dist/compat/react/index.d.cts +2 -1
- package/dist/compat/react/index.d.ts +2 -1
- package/dist/compat/react/index.js +11 -2
- package/dist/compat/react/index.js.map +1 -1
- package/dist/compat/solid/index.cjs +82 -2
- package/dist/compat/solid/index.cjs.map +1 -1
- package/dist/compat/solid/index.d.cts +2 -1
- package/dist/compat/solid/index.d.ts +2 -1
- package/dist/compat/solid/index.js +11 -2
- package/dist/compat/solid/index.js.map +1 -1
- package/dist/compat/svelte/index.cjs +85 -2
- package/dist/compat/svelte/index.cjs.map +1 -1
- package/dist/compat/svelte/index.d.cts +2 -1
- package/dist/compat/svelte/index.d.ts +2 -1
- package/dist/compat/svelte/index.js +11 -2
- package/dist/compat/svelte/index.js.map +1 -1
- package/dist/compat/vue/index.cjs +100 -2
- package/dist/compat/vue/index.cjs.map +1 -1
- package/dist/compat/vue/index.d.cts +3 -1
- package/dist/compat/vue/index.d.ts +3 -1
- package/dist/compat/vue/index.js +11 -2
- package/dist/compat/vue/index.js.map +1 -1
- package/dist/compat/zustand/index.cjs +50 -2
- package/dist/compat/zustand/index.cjs.map +1 -1
- package/dist/compat/zustand/index.d.cts +2 -1
- package/dist/compat/zustand/index.d.ts +2 -1
- package/dist/compat/zustand/index.js +7 -2
- package/dist/compat/zustand/index.js.map +1 -1
- package/dist/distill-De6Rnn15.d.cts +48 -0
- package/dist/distill-De6Rnn15.d.ts +48 -0
- package/dist/external-register-CWyroXb_.d.cts +138 -0
- package/dist/external-register-CWyroXb_.d.ts +138 -0
- package/dist/fallback-Bx46zqky.d.cts +243 -0
- package/dist/fallback-pIWW8A2d.d.ts +243 -0
- package/dist/guarded-execution-BcdtxeBk.d.ts +207 -0
- package/dist/guarded-execution-C-3hnP6A.d.cts +207 -0
- package/dist/index-B6pxYJzO.d.cts +36 -0
- package/dist/index-B6pxYJzO.d.ts +36 -0
- package/dist/index-BFsng6v1.d.cts +44 -0
- package/dist/index-BFsng6v1.d.ts +44 -0
- package/dist/index-B_p8tnvf.d.cts +770 -0
- package/dist/index-Bg-LwEt-.d.cts +45 -0
- package/dist/index-Bg-LwEt-.d.ts +45 -0
- package/dist/index-Brp888t0.d.cts +127 -0
- package/dist/index-Brp888t0.d.ts +127 -0
- package/dist/index-CDfk6jHN.d.cts +37 -0
- package/dist/index-CDfk6jHN.d.ts +37 -0
- package/dist/index-DLAxYaN5.d.cts +169 -0
- package/dist/index-DLAxYaN5.d.ts +169 -0
- package/dist/index-DeWbQzMe.d.cts +34 -0
- package/dist/index-DeWbQzMe.d.ts +34 -0
- package/dist/index-_HDSmPyp.d.ts +770 -0
- package/dist/index-dX9IzPqj.d.cts +86 -0
- package/dist/index-dX9IzPqj.d.ts +86 -0
- package/dist/index.cjs +26009 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -42
- package/dist/index.d.ts +55 -42
- package/dist/index.js +849 -0
- package/dist/index.js.map +1 -1
- package/dist/layout-types-B5aiHYgk.d.cts +72 -0
- package/dist/layout-types-B5aiHYgk.d.ts +72 -0
- package/dist/memory-composers-BryDrRBX.d.cts +529 -0
- package/dist/memory-composers-CVQqPYEV.d.ts +529 -0
- package/dist/observable-B25XqCbZ.d.cts +59 -0
- package/dist/observable-B25XqCbZ.d.ts +59 -0
- package/dist/pipeline-graph-Ce47CB6Y.d.cts +145 -0
- package/dist/pipeline-graph-DXCwY9vG.d.ts +145 -0
- package/dist/presets/ai/index.cjs +4377 -0
- package/dist/presets/ai/index.cjs.map +1 -0
- package/dist/presets/ai/index.d.cts +98 -0
- package/dist/presets/ai/index.d.ts +98 -0
- package/dist/presets/ai/index.js +54 -0
- package/dist/presets/ai/index.js.map +1 -0
- package/dist/presets/harness/index.cjs +5929 -0
- package/dist/presets/harness/index.cjs.map +1 -0
- package/dist/presets/harness/index.d.cts +566 -0
- package/dist/presets/harness/index.d.ts +566 -0
- package/dist/presets/harness/index.js +71 -0
- package/dist/presets/harness/index.js.map +1 -0
- package/dist/presets/index.cjs +9782 -0
- package/dist/presets/index.cjs.map +1 -0
- package/dist/presets/index.d.cts +28 -0
- package/dist/presets/index.d.ts +28 -0
- package/dist/presets/index.js +129 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/inspect/index.cjs +1087 -0
- package/dist/presets/inspect/index.cjs.map +1 -0
- package/dist/presets/inspect/index.d.cts +172 -0
- package/dist/presets/inspect/index.d.ts +172 -0
- package/dist/presets/inspect/index.js +21 -0
- package/dist/presets/inspect/index.js.map +1 -0
- package/dist/presets/resilience/index.cjs +1593 -0
- package/dist/presets/resilience/index.cjs.map +1 -0
- package/dist/presets/resilience/index.d.cts +205 -0
- package/dist/presets/resilience/index.d.ts +205 -0
- package/dist/presets/resilience/index.js +18 -0
- package/dist/presets/resilience/index.js.map +1 -0
- package/dist/rate-limiter-CEALq4N1.d.ts +559 -0
- package/dist/rate-limiter-DpVbSYdH.d.cts +559 -0
- package/dist/reactive-layout-fswlBUvX.d.cts +195 -0
- package/dist/reactive-layout-fswlBUvX.d.ts +195 -0
- package/dist/retry-BDbRZ_gx.d.ts +125 -0
- package/dist/retry-DWuhjvsA.d.cts +125 -0
- package/dist/solutions/index.cjs +8200 -0
- package/dist/solutions/index.cjs.map +1 -0
- package/dist/solutions/index.d.cts +23 -0
- package/dist/solutions/index.d.ts +23 -0
- package/dist/solutions/index.js +55 -0
- package/dist/solutions/index.js.map +1 -0
- package/dist/spawnable-5mDY501F.d.cts +746 -0
- package/dist/spawnable-D3lR0oQu.d.ts +746 -0
- package/dist/status-U-rUI79b.d.cts +84 -0
- package/dist/status-U-rUI79b.d.ts +84 -0
- package/dist/timeout-U5O4ESK3.js +12 -0
- package/dist/timeout-U5O4ESK3.js.map +1 -0
- package/dist/types-BB5Lw-pB.d.cts +442 -0
- package/dist/types-BB5Lw-pB.d.ts +442 -0
- package/dist/types-CJWIMJiZ.d.ts +548 -0
- package/dist/types-vCq7ShIm.d.cts +548 -0
- package/dist/utils/ai/browser.cjs +2169 -0
- package/dist/utils/ai/browser.cjs.map +1 -0
- package/dist/utils/ai/browser.d.cts +129 -0
- package/dist/utils/ai/browser.d.ts +129 -0
- package/dist/utils/ai/browser.js +255 -0
- package/dist/utils/ai/browser.js.map +1 -0
- package/dist/utils/ai/index.cjs +8468 -0
- package/dist/utils/ai/index.cjs.map +1 -0
- package/dist/utils/ai/index.d.cts +1777 -0
- package/dist/utils/ai/index.d.ts +1777 -0
- package/dist/utils/ai/index.js +173 -0
- package/dist/utils/ai/index.js.map +1 -0
- package/dist/utils/ai/node.cjs +648 -0
- package/dist/utils/ai/node.cjs.map +1 -0
- package/dist/utils/ai/node.d.cts +57 -0
- package/dist/utils/ai/node.d.ts +57 -0
- package/dist/utils/ai/node.js +84 -0
- package/dist/utils/ai/node.js.map +1 -0
- package/dist/utils/cqrs/index.cjs +1036 -0
- package/dist/utils/cqrs/index.cjs.map +1 -0
- package/dist/utils/cqrs/index.d.cts +438 -0
- package/dist/utils/cqrs/index.d.ts +438 -0
- package/dist/utils/cqrs/index.js +18 -0
- package/dist/utils/cqrs/index.js.map +1 -0
- package/dist/utils/demo-shell/index.cjs +865 -0
- package/dist/utils/demo-shell/index.cjs.map +1 -0
- package/dist/utils/demo-shell/index.d.cts +90 -0
- package/dist/utils/demo-shell/index.d.ts +90 -0
- package/dist/utils/demo-shell/index.js +13 -0
- package/dist/utils/demo-shell/index.js.map +1 -0
- package/dist/utils/domain-templates/index.cjs +732 -0
- package/dist/utils/domain-templates/index.cjs.map +1 -0
- package/dist/utils/domain-templates/index.d.cts +214 -0
- package/dist/utils/domain-templates/index.d.ts +214 -0
- package/dist/utils/domain-templates/index.js +17 -0
- package/dist/utils/domain-templates/index.js.map +1 -0
- package/dist/utils/graphspec/index.cjs +1174 -0
- package/dist/utils/graphspec/index.cjs.map +1 -0
- package/dist/utils/graphspec/index.d.cts +449 -0
- package/dist/utils/graphspec/index.d.ts +449 -0
- package/dist/utils/graphspec/index.js +35 -0
- package/dist/utils/graphspec/index.js.map +1 -0
- package/dist/utils/harness/index.cjs +656 -0
- package/dist/utils/harness/index.cjs.map +1 -0
- package/dist/utils/harness/index.d.cts +542 -0
- package/dist/utils/harness/index.d.ts +542 -0
- package/dist/utils/harness/index.js +56 -0
- package/dist/utils/harness/index.js.map +1 -0
- package/dist/utils/index.cjs +17614 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +96 -0
- package/dist/utils/index.d.ts +96 -0
- package/dist/utils/index.js +514 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/inspect/index.cjs +807 -0
- package/dist/utils/inspect/index.cjs.map +1 -0
- package/dist/utils/inspect/index.d.cts +123 -0
- package/dist/utils/inspect/index.d.ts +123 -0
- package/dist/utils/inspect/index.js +30 -0
- package/dist/utils/inspect/index.js.map +1 -0
- package/dist/utils/job-queue/index.cjs +717 -0
- package/dist/utils/job-queue/index.cjs.map +1 -0
- package/dist/utils/job-queue/index.d.cts +200 -0
- package/dist/utils/job-queue/index.d.ts +200 -0
- package/dist/utils/job-queue/index.js +18 -0
- package/dist/utils/job-queue/index.js.map +1 -0
- package/dist/utils/memory/index.cjs +1456 -0
- package/dist/utils/memory/index.cjs.map +1 -0
- package/dist/utils/memory/index.d.cts +660 -0
- package/dist/utils/memory/index.d.ts +660 -0
- package/dist/utils/memory/index.js +19 -0
- package/dist/utils/memory/index.js.map +1 -0
- package/dist/utils/messaging/index.cjs +666 -0
- package/dist/utils/messaging/index.cjs.map +1 -0
- package/dist/utils/messaging/index.d.cts +562 -0
- package/dist/utils/messaging/index.d.ts +562 -0
- package/dist/utils/messaging/index.js +50 -0
- package/dist/utils/messaging/index.js.map +1 -0
- package/dist/utils/orchestration/index.cjs +876 -0
- package/dist/utils/orchestration/index.cjs.map +1 -0
- package/dist/utils/orchestration/index.d.cts +233 -0
- package/dist/utils/orchestration/index.d.ts +233 -0
- package/dist/utils/orchestration/index.js +19 -0
- package/dist/utils/orchestration/index.js.map +1 -0
- package/dist/utils/process/index.cjs +743 -0
- package/dist/utils/process/index.cjs.map +1 -0
- package/dist/utils/process/index.d.cts +411 -0
- package/dist/utils/process/index.d.ts +411 -0
- package/dist/utils/process/index.js +14 -0
- package/dist/utils/process/index.js.map +1 -0
- package/dist/utils/reactive-layout/index.cjs +1607 -0
- package/dist/utils/reactive-layout/index.cjs.map +1 -0
- package/dist/utils/reactive-layout/index.d.cts +492 -0
- package/dist/utils/reactive-layout/index.d.ts +492 -0
- package/dist/utils/reactive-layout/index.js +52 -0
- package/dist/utils/reactive-layout/index.js.map +1 -0
- package/dist/utils/reduction/index.cjs +203 -0
- package/dist/utils/reduction/index.cjs.map +1 -0
- package/dist/utils/reduction/index.d.cts +102 -0
- package/dist/utils/reduction/index.d.ts +102 -0
- package/dist/utils/reduction/index.js +14 -0
- package/dist/utils/reduction/index.js.map +1 -0
- package/dist/utils/resilience/index.cjs +1617 -0
- package/dist/utils/resilience/index.cjs.map +1 -0
- package/dist/utils/resilience/index.d.cts +9 -0
- package/dist/utils/resilience/index.d.ts +9 -0
- package/dist/utils/resilience/index.js +44 -0
- package/dist/utils/resilience/index.js.map +1 -0
- package/dist/utils/surface/index.cjs +1070 -0
- package/dist/utils/surface/index.cjs.map +1 -0
- package/dist/utils/surface/index.d.cts +240 -0
- package/dist/utils/surface/index.d.ts +240 -0
- package/dist/utils/surface/index.js +30 -0
- package/dist/utils/surface/index.js.map +1 -0
- package/dist/utils/topology-view/index.cjs +620 -0
- package/dist/utils/topology-view/index.cjs.map +1 -0
- package/dist/utils/topology-view/index.d.cts +68 -0
- package/dist/utils/topology-view/index.d.ts +68 -0
- package/dist/utils/topology-view/index.js +11 -0
- package/dist/utils/topology-view/index.js.map +1 -0
- package/package.json +293 -241
- package/dist/core/index.cjs +0 -21
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +0 -3
- package/dist/core/index.js.map +0 -1
- package/dist/extra/browser.cjs +0 -21
- package/dist/extra/browser.cjs.map +0 -1
- package/dist/extra/browser.d.cts +0 -1
- package/dist/extra/browser.d.ts +0 -1
- package/dist/extra/browser.js +0 -3
- package/dist/extra/browser.js.map +0 -1
- package/dist/extra/index.cjs +0 -21
- package/dist/extra/index.cjs.map +0 -1
- package/dist/extra/index.d.cts +0 -1
- package/dist/extra/index.d.ts +0 -1
- package/dist/extra/index.js +0 -3
- package/dist/extra/index.js.map +0 -1
- package/dist/extra/node.cjs +0 -21
- package/dist/extra/node.cjs.map +0 -1
- package/dist/extra/node.d.cts +0 -1
- package/dist/extra/node.d.ts +0 -1
- package/dist/extra/node.js +0 -3
- package/dist/extra/node.js.map +0 -1
- package/dist/extra/operators.cjs +0 -21
- package/dist/extra/operators.cjs.map +0 -1
- package/dist/extra/operators.d.cts +0 -1
- package/dist/extra/operators.d.ts +0 -1
- package/dist/extra/operators.js +0 -3
- package/dist/extra/operators.js.map +0 -1
- package/dist/extra/reactive.cjs +0 -21
- package/dist/extra/reactive.cjs.map +0 -1
- package/dist/extra/reactive.d.cts +0 -1
- package/dist/extra/reactive.d.ts +0 -1
- package/dist/extra/reactive.js +0 -3
- package/dist/extra/reactive.js.map +0 -1
- package/dist/extra/render/index.cjs +0 -21
- package/dist/extra/render/index.cjs.map +0 -1
- package/dist/extra/render/index.d.cts +0 -1
- package/dist/extra/render/index.d.ts +0 -1
- package/dist/extra/render/index.js +0 -3
- package/dist/extra/render/index.js.map +0 -1
- package/dist/extra/sources.cjs +0 -21
- package/dist/extra/sources.cjs.map +0 -1
- package/dist/extra/sources.d.cts +0 -1
- package/dist/extra/sources.d.ts +0 -1
- package/dist/extra/sources.js +0 -3
- package/dist/extra/sources.js.map +0 -1
- package/dist/extra/storage-browser.cjs +0 -21
- package/dist/extra/storage-browser.cjs.map +0 -1
- package/dist/extra/storage-browser.d.cts +0 -1
- package/dist/extra/storage-browser.d.ts +0 -1
- package/dist/extra/storage-browser.js +0 -3
- package/dist/extra/storage-browser.js.map +0 -1
- package/dist/extra/storage-core.cjs +0 -21
- package/dist/extra/storage-core.cjs.map +0 -1
- package/dist/extra/storage-core.d.cts +0 -1
- package/dist/extra/storage-core.d.ts +0 -1
- package/dist/extra/storage-core.js +0 -3
- package/dist/extra/storage-core.js.map +0 -1
- package/dist/extra/storage-node.cjs +0 -21
- package/dist/extra/storage-node.cjs.map +0 -1
- package/dist/extra/storage-node.d.cts +0 -1
- package/dist/extra/storage-node.d.ts +0 -1
- package/dist/extra/storage-node.js +0 -3
- package/dist/extra/storage-node.js.map +0 -1
- package/dist/extra/storage-tiers-browser.cjs +0 -21
- package/dist/extra/storage-tiers-browser.cjs.map +0 -1
- package/dist/extra/storage-tiers-browser.d.cts +0 -1
- package/dist/extra/storage-tiers-browser.d.ts +0 -1
- package/dist/extra/storage-tiers-browser.js +0 -3
- package/dist/extra/storage-tiers-browser.js.map +0 -1
- package/dist/extra/storage-tiers-node.cjs +0 -21
- package/dist/extra/storage-tiers-node.cjs.map +0 -1
- package/dist/extra/storage-tiers-node.d.cts +0 -1
- package/dist/extra/storage-tiers-node.d.ts +0 -1
- package/dist/extra/storage-tiers-node.js +0 -3
- package/dist/extra/storage-tiers-node.js.map +0 -1
- package/dist/extra/storage-tiers.cjs +0 -21
- package/dist/extra/storage-tiers.cjs.map +0 -1
- package/dist/extra/storage-tiers.d.cts +0 -1
- package/dist/extra/storage-tiers.d.ts +0 -1
- package/dist/extra/storage-tiers.js +0 -3
- package/dist/extra/storage-tiers.js.map +0 -1
- package/dist/extra/storage-wal.cjs +0 -21
- package/dist/extra/storage-wal.cjs.map +0 -1
- package/dist/extra/storage-wal.d.cts +0 -1
- package/dist/extra/storage-wal.d.ts +0 -1
- package/dist/extra/storage-wal.js +0 -3
- package/dist/extra/storage-wal.js.map +0 -1
- package/dist/graph/index.cjs +0 -21
- package/dist/graph/index.cjs.map +0 -1
- package/dist/graph/index.d.cts +0 -1
- package/dist/graph/index.d.ts +0 -1
- package/dist/graph/index.js +0 -3
- package/dist/graph/index.js.map +0 -1
- package/dist/patterns/ai/browser.cjs +0 -21
- package/dist/patterns/ai/browser.cjs.map +0 -1
- package/dist/patterns/ai/browser.d.cts +0 -1
- package/dist/patterns/ai/browser.d.ts +0 -1
- package/dist/patterns/ai/browser.js +0 -3
- package/dist/patterns/ai/browser.js.map +0 -1
- package/dist/patterns/ai/index.cjs +0 -21
- package/dist/patterns/ai/index.cjs.map +0 -1
- package/dist/patterns/ai/index.d.cts +0 -1
- package/dist/patterns/ai/index.d.ts +0 -1
- package/dist/patterns/ai/index.js +0 -3
- package/dist/patterns/ai/index.js.map +0 -1
- package/dist/patterns/ai/node.cjs +0 -21
- package/dist/patterns/ai/node.cjs.map +0 -1
- package/dist/patterns/ai/node.d.cts +0 -1
- package/dist/patterns/ai/node.d.ts +0 -1
- package/dist/patterns/ai/node.js +0 -3
- package/dist/patterns/ai/node.js.map +0 -1
- package/dist/patterns/cqrs/index.cjs +0 -21
- package/dist/patterns/cqrs/index.cjs.map +0 -1
- package/dist/patterns/cqrs/index.d.cts +0 -1
- package/dist/patterns/cqrs/index.d.ts +0 -1
- package/dist/patterns/cqrs/index.js +0 -3
- package/dist/patterns/cqrs/index.js.map +0 -1
- package/dist/patterns/demo-shell/index.cjs +0 -21
- package/dist/patterns/demo-shell/index.cjs.map +0 -1
- package/dist/patterns/demo-shell/index.d.cts +0 -1
- package/dist/patterns/demo-shell/index.d.ts +0 -1
- package/dist/patterns/demo-shell/index.js +0 -3
- package/dist/patterns/demo-shell/index.js.map +0 -1
- package/dist/patterns/domain-templates/index.cjs +0 -21
- package/dist/patterns/domain-templates/index.cjs.map +0 -1
- package/dist/patterns/domain-templates/index.d.cts +0 -1
- package/dist/patterns/domain-templates/index.d.ts +0 -1
- package/dist/patterns/domain-templates/index.js +0 -3
- package/dist/patterns/domain-templates/index.js.map +0 -1
- package/dist/patterns/graphspec/index.cjs +0 -21
- package/dist/patterns/graphspec/index.cjs.map +0 -1
- package/dist/patterns/graphspec/index.d.cts +0 -1
- package/dist/patterns/graphspec/index.d.ts +0 -1
- package/dist/patterns/graphspec/index.js +0 -3
- package/dist/patterns/graphspec/index.js.map +0 -1
- package/dist/patterns/harness/index.cjs +0 -21
- package/dist/patterns/harness/index.cjs.map +0 -1
- package/dist/patterns/harness/index.d.cts +0 -1
- package/dist/patterns/harness/index.d.ts +0 -1
- package/dist/patterns/harness/index.js +0 -3
- package/dist/patterns/harness/index.js.map +0 -1
- package/dist/patterns/inspect/index.cjs +0 -21
- package/dist/patterns/inspect/index.cjs.map +0 -1
- package/dist/patterns/inspect/index.d.cts +0 -1
- package/dist/patterns/inspect/index.d.ts +0 -1
- package/dist/patterns/inspect/index.js +0 -3
- package/dist/patterns/inspect/index.js.map +0 -1
- package/dist/patterns/job-queue/index.cjs +0 -21
- package/dist/patterns/job-queue/index.cjs.map +0 -1
- package/dist/patterns/job-queue/index.d.cts +0 -1
- package/dist/patterns/job-queue/index.d.ts +0 -1
- package/dist/patterns/job-queue/index.js +0 -3
- package/dist/patterns/job-queue/index.js.map +0 -1
- package/dist/patterns/memory/index.cjs +0 -21
- package/dist/patterns/memory/index.cjs.map +0 -1
- package/dist/patterns/memory/index.d.cts +0 -1
- package/dist/patterns/memory/index.d.ts +0 -1
- package/dist/patterns/memory/index.js +0 -3
- package/dist/patterns/memory/index.js.map +0 -1
- package/dist/patterns/messaging/index.cjs +0 -21
- package/dist/patterns/messaging/index.cjs.map +0 -1
- package/dist/patterns/messaging/index.d.cts +0 -1
- package/dist/patterns/messaging/index.d.ts +0 -1
- package/dist/patterns/messaging/index.js +0 -3
- package/dist/patterns/messaging/index.js.map +0 -1
- package/dist/patterns/orchestration/index.cjs +0 -21
- package/dist/patterns/orchestration/index.cjs.map +0 -1
- package/dist/patterns/orchestration/index.d.cts +0 -1
- package/dist/patterns/orchestration/index.d.ts +0 -1
- package/dist/patterns/orchestration/index.js +0 -3
- package/dist/patterns/orchestration/index.js.map +0 -1
- package/dist/patterns/process/index.cjs +0 -21
- package/dist/patterns/process/index.cjs.map +0 -1
- package/dist/patterns/process/index.d.cts +0 -1
- package/dist/patterns/process/index.d.ts +0 -1
- package/dist/patterns/process/index.js +0 -3
- package/dist/patterns/process/index.js.map +0 -1
- package/dist/patterns/reactive-layout/index.cjs +0 -21
- package/dist/patterns/reactive-layout/index.cjs.map +0 -1
- package/dist/patterns/reactive-layout/index.d.cts +0 -1
- package/dist/patterns/reactive-layout/index.d.ts +0 -1
- package/dist/patterns/reactive-layout/index.js +0 -3
- package/dist/patterns/reactive-layout/index.js.map +0 -1
- package/dist/patterns/reduction/index.cjs +0 -21
- package/dist/patterns/reduction/index.cjs.map +0 -1
- package/dist/patterns/reduction/index.d.cts +0 -1
- package/dist/patterns/reduction/index.d.ts +0 -1
- package/dist/patterns/reduction/index.js +0 -3
- package/dist/patterns/reduction/index.js.map +0 -1
- package/dist/patterns/surface/index.cjs +0 -21
- package/dist/patterns/surface/index.cjs.map +0 -1
- package/dist/patterns/surface/index.d.cts +0 -1
- package/dist/patterns/surface/index.d.ts +0 -1
- package/dist/patterns/surface/index.js +0 -3
- package/dist/patterns/surface/index.js.map +0 -1
- package/dist/patterns/topology-view/index.cjs +0 -21
- package/dist/patterns/topology-view/index.cjs.map +0 -1
- package/dist/patterns/topology-view/index.d.cts +0 -1
- package/dist/patterns/topology-view/index.d.ts +0 -1
- package/dist/patterns/topology-view/index.js +0 -3
- package/dist/patterns/topology-view/index.js.map +0 -1
- package/dist/testing/index.cjs +0 -21
- package/dist/testing/index.cjs.map +0 -1
- package/dist/testing/index.d.cts +0 -1
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +0 -3
- package/dist/testing/index.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/base/resilience/_internal.ts","../../src/base/resilience/backoff.ts","../../src/base/resilience/timeout.ts","../../src/utils/index.ts","../../src/utils/_errors/index.ts","../../src/utils/ai/adapters/core/capabilities.ts","../../src/utils/ai/adapters/providers/anthropic.ts","../../src/base/io/http-error.ts","../../src/base/io/sse.ts","../../src/utils/ai/adapters/providers/dry-run.ts","../../src/utils/ai/adapters/providers/fallback.ts","../../src/utils/ai/adapters/middleware/replay-cache.ts","../../src/base/composition/single-from-any.ts","../../src/base/sources/settled.ts","../../src/utils/ai/adapters/_internal/content-addressed-cache.ts","../../src/utils/ai/adapters/_internal/wrappers.ts","../../src/utils/ai/adapters/providers/google.ts","../../src/utils/ai/adapters/providers/openai-compat.ts","../../src/utils/ai/adapters/core/factory.ts","../../src/utils/ai/adapters/core/observable.ts","../../src/utils/ai/adapters/core/types.ts","../../src/utils/ai/adapters/core/pricing.ts","../../src/utils/ai/adapters/middleware/breaker.ts","../../src/base/resilience/retry.ts","../../src/base/resilience/status.ts","../../src/utils/resilience/index.ts","../../src/utils/resilience/breaker.ts","../../src/utils/resilience/budget-gate.ts","../../src/base/meta/domain-meta.ts","../../src/utils/resilience/fallback.ts","../../src/utils/resilience/rate-limiter.ts","../../src/utils/resilience/adaptive-rate-limiter.ts","../../src/utils/ai/adapters/middleware/budget-gate.ts","../../src/utils/ai/adapters/middleware/dry-run.ts","../../src/utils/ai/adapters/middleware/http429-parser.ts","../../src/utils/ai/adapters/middleware/rate-limiter.ts","../../src/utils/ai/adapters/routing/cascading.ts","../../src/utils/ai/adapters/middleware/retry.ts","../../src/utils/ai/adapters/middleware/timeout.ts","../../src/utils/ai/adapters/middleware/resilient-adapter.ts","../../src/utils/ai/prompts/frozen-context.ts","../../src/utils/ai/_internal.ts","../../src/utils/ai/prompts/prompt-call.ts","../../src/utils/ai/prompts/prompt-node.ts","../../src/utils/ai/prompts/streaming.ts","../../src/utils/messaging/audit-records.ts","../../src/utils/messaging/message.ts","../../src/utils/messaging/index.ts","../../src/base/mutation/index.ts","../../src/utils/orchestration/human-input.ts","../../src/utils/orchestration/pipeline-graph.ts","../../src/utils/orchestration/tracker.ts","../../src/utils/ai/prompts/system-prompt.ts","../../src/utils/ai/extractors/cost-meter.ts","../../src/utils/ai/extractors/keyword-flag.ts","../../src/utils/ai/extractors/stream-extractor.ts","../../src/utils/ai/extractors/tool-call.ts","../../src/utils/ai/safety/content-gate.ts","../../src/utils/ai/safety/redactor.ts","../../src/utils/ai/agents/chat-stream.ts","../../src/utils/ai/agents/handoff.ts","../../src/utils/ai/agents/tool-execution.ts","../../src/utils/ai/agents/tool-registry.ts","../../src/utils/ai/agents/tool-selector.ts","../../src/utils/ai/memory/admission.ts","../../src/utils/ai/memory/memory-composers.ts","../../src/base/composition/distill.ts","../../src/base/sources/async.ts","../../src/base/utils/decay.ts","../../src/utils/memory/index.ts","../../src/utils/memory/fact-store.ts","../../src/utils/ai/graph-integration/gauges-as-context.ts","../../src/utils/ai/graph-integration/graph-from-spec.ts","../../src/utils/graphspec/index.ts","../../src/utils/reduction/index.ts","../../src/utils/ai/graph-integration/knobs-as-tools.ts","../../src/utils/ai/graph-integration/suggest-strategy.ts","../../src/utils/ai/graph-integration/validate-graph-def.ts","../../src/utils/cqrs/index.ts","../../src/utils/demo-shell/index.ts","../../src/base/render/_ascii-width.ts","../../src/base/render/_layout-sugiyama.ts","../../src/base/render/_internal.ts","../../src/base/render/graph-spec-to-mermaid.ts","../../src/utils/reactive-layout/reactive-layout.ts","../../src/base/meta/emit-to-meta.ts","../../src/utils/domain-templates/index.ts","../../src/utils/harness/actuator-executor.ts","../../src/utils/harness/auto-solidify.ts","../../src/utils/harness/bridge.ts","../../src/utils/harness/defaults.ts","../../src/utils/harness/strategy.ts","../../src/utils/orchestration/audited-success-tracker.ts","../../src/utils/harness/types.ts","../../src/utils/inspect/audit.ts","../../src/utils/inspect/lens.ts","../../src/utils/job-queue/index.ts","../../src/utils/process/index.ts","../../src/utils/reactive-layout/measurement-adapters.ts","../../src/utils/reactive-layout/reactive-block-layout.ts","../../src/utils/reactive-layout/reactive-flow-layout.ts","../../src/utils/surface/errors.ts","../../src/utils/surface/create.ts","../../src/utils/surface/reduce.ts","../../src/utils/surface/snapshot.ts","../../src/utils/topology-view/index.ts","../../src/utils/topology-view/_internal.ts"],"sourcesContent":["/**\n * Internal helpers shared by resilience sub-files.\n *\n * Not part of the public surface. The base-layer resilience operators\n * co-located here (`retry.ts`, `status.ts`, `timeout.ts`) import what they\n * need from this file directly; the utils-layer resilience primitives that\n * stayed in `utils/resilience/` (`breaker.ts`, `rate-limiter.ts`,\n * `fallback.ts`) import it top-down via `../../base/resilience/_internal.js`.\n *\n * `NodeOrValue<T>` is the only export re-surfaced publicly — there is no\n * `base/resilience/index.ts`; it ships through `utils/resilience/index.ts`\n * (and `utils/memory/index.ts`). Every resilience primitive that accepts\n * reactive options uses it as the option-arg shape.\n */\n\nimport type { Node, NodeOptions } from \"@graphrefly/pure-ts/core\";\nimport { DATA, type Message } from \"@graphrefly/pure-ts/core\";\n\nexport type ExtraOpts = Omit<NodeOptions, \"describeKind\">;\n\nexport function operatorOpts<T>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"derived\", ...opts } as NodeOptions<T>;\n}\n\nexport function clampNonNegative(value: number): number {\n\treturn value < 0 ? 0 : value;\n}\n\nexport function msgVal(m: Message): unknown {\n\treturn m[1];\n}\n\nexport function coerceDelayNs(raw: number): number {\n\tif (typeof raw !== \"number\" || !Number.isFinite(raw)) {\n\t\tthrow new TypeError(\"backoff strategy must return a finite number\");\n\t}\n\treturn raw < 0 ? 0 : raw;\n}\n\nexport function 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 * Either a literal value or a reactive Node carrying it. Mirrors\n * {@link FallbackInput}'s precedent for \"options that may be reactive.\"\n *\n * Used by {@link timeout} / {@link retry} / {@link rateLimiter} /\n * {@link circuitBreaker} / {@link budgetGate} to accept reactive option\n * configurations (Tier 6.5 3.2, 2026-04-29). Each primitive subscribes\n * to the option Node via {@link resolveReactiveOption} and rebinds\n * internal state per its locked swap-semantic rule (see each primitive's\n * JSDoc for the rule).\n *\n * @category extra\n */\nexport type NodeOrValue<T> = T | Node<T>;\n\n/**\n * Closure-mirror helper for `NodeOrValue<T>` options\n * (COMPOSITION-GUIDE §28). Returns:\n * - `current()` — read the latest value (cached at construction; updated\n * on each Node DATA emission).\n * - `unsub()` — release the subscription. Static-form arg never\n * subscribes; `unsub` is a no-op there.\n *\n * `onChange` fires on each DATA after the initial value (skips the\n * cache-seed read). Use to rebind primitive-internal state per the\n * primitive's locked swap-semantic rule.\n *\n * @internal\n */\nexport function resolveReactiveOption<T>(\n\targ: NodeOrValue<T>,\n\tonChange?: (next: T) => void,\n): { current: () => T; unsub: () => void } {\n\tif (!isNode(arg)) {\n\t\treturn { current: () => arg, unsub: () => undefined };\n\t}\n\tconst node = arg as Node<T>;\n\tlet latest: T = node.cache as T;\n\tconst unsub = node.subscribe((msgs) => {\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] === DATA) {\n\t\t\t\tlatest = m[1] as T;\n\t\t\t\tif (onChange) onChange(latest);\n\t\t\t}\n\t\t}\n\t});\n\treturn {\n\t\tcurrent: () => latest,\n\t\tunsub,\n\t};\n}\n\nexport function isThenable(x: unknown): x is PromiseLike<unknown> {\n\treturn x != null && typeof (x as PromiseLike<unknown>).then === \"function\";\n}\n\nexport function isAsyncIterable(x: unknown): x is AsyncIterable<unknown> {\n\treturn (\n\t\tx != null &&\n\t\ttypeof x === \"object\" &&\n\t\ttypeof (x as AsyncIterable<unknown>)[Symbol.asyncIterator] === \"function\"\n\t);\n}\n","/**\n * Backoff strategies for {@link retry} (roadmap §3.1). Delays are in **nanoseconds**.\n *\n * Convention: all graphrefly-ts timestamps and durations use nanoseconds (`_ns` suffix).\n * 1 second = 1_000_000_000 ns, 1 ms = 1_000_000 ns.\n */\n\nexport const NS_PER_MS = 1_000_000;\nexport const NS_PER_SEC = 1_000_000_000;\n\nexport type JitterMode = \"none\" | \"full\" | \"equal\";\n\nexport type BackoffPreset =\n\t| \"constant\"\n\t| \"linear\"\n\t| \"exponential\"\n\t| \"fibonacci\"\n\t| \"decorrelatedJitter\";\n\n/** `(attempt, error?, previousDelayNs?) => delayNs | null` — `null` means zero delay. */\nexport type BackoffStrategy = (\n\tattempt: number,\n\terror?: unknown,\n\tprevDelayNs?: number | null,\n) => number | null;\n\nfunction clampNonNegative(value: number): number {\n\treturn value < 0 ? 0 : value;\n}\n\nfunction applyJitter(delay: number, jitter: JitterMode): number {\n\tif (jitter === \"none\") return delay;\n\tif (jitter === \"full\") return Math.random() * delay;\n\treturn delay / 2 + Math.random() * (delay / 2);\n}\n\nfunction randomBetween(min: number, max: number): number {\n\treturn min + Math.random() * (max - min);\n}\n\n/**\n * Builds a strategy that always returns the same delay in nanoseconds.\n *\n * @param delayNs - Non-negative delay in nanoseconds; values below zero are clamped to zero.\n * @returns `BackoffStrategy` for use with {@link retry} or custom timers.\n *\n * @example\n * ```ts\n * import { constant, retry, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * const out = retry(source, { count: 3, backoff: constant(0.25 * NS_PER_SEC) });\n * ```\n *\n * @category extra\n */\nexport function constant(delayNs: number): BackoffStrategy {\n\tconst safe = clampNonNegative(delayNs);\n\treturn () => safe;\n}\n\n/**\n * Builds linear backoff: `baseNs + stepNs * attempt` (`stepNs` defaults to `baseNs`).\n *\n * @param baseNs - Base delay in nanoseconds (clamped non-negative).\n * @param stepNs - Added per retry attempt in nanoseconds (clamped non-negative).\n * @returns `BackoffStrategy` for {@link retry}.\n *\n * @example\n * ```ts\n * import { linear, retry, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * // Attempt 0 → 1 s, attempt 1 → 2 s, attempt 2 → 3 s …\n * const out = retry(source, { count: 4, backoff: linear(NS_PER_SEC) });\n * ```\n *\n * @category extra\n */\nexport function linear(baseNs: number, stepNs?: number): BackoffStrategy {\n\tconst safeBase = clampNonNegative(baseNs);\n\tconst safeStep = stepNs === undefined ? safeBase : clampNonNegative(stepNs);\n\treturn (attempt: number) => safeBase + safeStep * Math.max(0, attempt);\n}\n\nexport type ExponentialBackoffOptions = {\n\tbaseNs?: number;\n\tfactor?: number;\n\tmaxDelayNs?: number;\n\tjitter?: JitterMode;\n};\n\n/**\n * Builds exponential backoff in nanoseconds, capped by `maxDelayNs`, with optional jitter.\n *\n * @param options - Base, factor, cap, and jitter mode.\n * @returns `BackoffStrategy` for {@link retry}.\n *\n * @remarks\n * **Jitter:** `\"full\"` spreads delay across `[0, delay]`; `\"equal\"` uses `[delay/2, delay]`.\n *\n * @example\n * ```ts\n * import { exponential, retry, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * // 100 ms → 200 ms → 400 ms … capped at 30 s, with full jitter\n * const out = retry(source, {\n * count: 5,\n * backoff: exponential({ baseNs: 100 * NS_PER_SEC / 1000, jitter: \"full\" }),\n * });\n * ```\n *\n * @category extra\n */\nexport function exponential(options?: ExponentialBackoffOptions): BackoffStrategy {\n\tconst baseNs = clampNonNegative(options?.baseNs ?? 100 * NS_PER_MS);\n\tconst factor = options?.factor !== undefined && options.factor < 1 ? 1 : (options?.factor ?? 2);\n\tconst maxDelayNs = clampNonNegative(options?.maxDelayNs ?? 30 * NS_PER_SEC);\n\tconst jitter = options?.jitter ?? \"none\";\n\n\treturn (attempt: number) => {\n\t\tlet delay: number;\n\t\tif (baseNs === 0) {\n\t\t\tdelay = 0;\n\t\t} else if (factor === 1) {\n\t\t\tdelay = baseNs;\n\t\t} else {\n\t\t\tconst capRatio = maxDelayNs / baseNs;\n\t\t\tlet growth = 1;\n\t\t\tfor (let i = 0; i < Math.max(0, attempt); i++) {\n\t\t\t\tif (growth >= capRatio) {\n\t\t\t\t\tgrowth = capRatio;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tgrowth *= factor;\n\t\t\t}\n\t\t\tdelay = baseNs * growth;\n\t\t\tif (delay > maxDelayNs) delay = maxDelayNs;\n\t\t}\n\t\treturn applyJitter(delay, jitter);\n\t};\n}\n\n/**\n * Builds Fibonacci-scaled delays: `1, 2, 3, 5, … × baseNs`, capped at `maxDelayNs`.\n *\n * @param baseNs - Multiplier applied to the Fibonacci unit (default `100ms` in nanoseconds).\n * @param maxDelayNs - Upper bound in nanoseconds (default `30s`).\n * @returns `BackoffStrategy` for {@link retry}.\n *\n * @example\n * ```ts\n * import { fibonacci, retry, NS_PER_MS } from \"@graphrefly/graphrefly-ts\";\n *\n * // Delays: 100 ms, 200 ms, 300 ms, 500 ms, 800 ms … (× 100 ms base)\n * const out = retry(source, { count: 5, backoff: fibonacci(100 * NS_PER_MS) });\n * ```\n *\n * @category extra\n */\nexport function fibonacci(baseNs = 100 * NS_PER_MS, maxDelayNs = 30 * NS_PER_SEC): BackoffStrategy {\n\tconst safeBase = clampNonNegative(baseNs);\n\tconst safeMax = clampNonNegative(maxDelayNs);\n\n\tfunction fibUnit(attempt: number): number {\n\t\tif (attempt <= 0) return 1;\n\t\tlet prev = 1;\n\t\tlet cur = 2;\n\t\tfor (let i = 1; i < attempt; i++) {\n\t\t\tconst next = prev + cur;\n\t\t\tprev = cur;\n\t\t\tcur = next;\n\t\t}\n\t\treturn cur;\n\t}\n\n\treturn (attempt: number) => {\n\t\tconst raw = fibUnit(attempt) * safeBase;\n\t\treturn raw <= safeMax ? raw : safeMax;\n\t};\n}\n\n/**\n * Decorrelated jitter (AWS-recommended): `random(baseNs, min(maxNs, lastDelay * 3))`.\n *\n * Stateless — uses `prevDelayNs` (passed by the consumer) instead of closure state.\n * Safe to share across concurrent retry sequences.\n *\n * @param baseNs - Floor of the random range (default `100ms` in nanoseconds).\n * @param maxNs - Ceiling cap (default `30s` in nanoseconds).\n * @returns `BackoffStrategy` for {@link retry}.\n *\n * @example\n * ```ts\n * import { decorrelatedJitter, retry, NS_PER_MS, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * const out = retry(source, {\n * count: 6,\n * backoff: decorrelatedJitter(100 * NS_PER_MS, 10 * NS_PER_SEC),\n * });\n * ```\n *\n * @category extra\n */\nexport function decorrelatedJitter(\n\tbaseNs = 100 * NS_PER_MS,\n\tmaxNs = 30 * NS_PER_SEC,\n): BackoffStrategy {\n\treturn (_attempt, _error, prevDelayNs) => {\n\t\tconst last = prevDelayNs ?? baseNs;\n\t\tconst ceiling = Math.min(maxNs, last * 3);\n\t\treturn randomBetween(baseNs, ceiling);\n\t};\n}\n\n/**\n * Decorator that caps any strategy at `maxAttempts`. Returns `null` (stop retrying) after the cap.\n *\n * @param strategy - Inner strategy to wrap.\n * @param maxAttempts - Maximum number of attempts (inclusive).\n * @returns Wrapped `BackoffStrategy`.\n *\n * @example\n * ```ts\n * import { withMaxAttempts, exponential } from \"@graphrefly/graphrefly-ts\";\n *\n * const capped = withMaxAttempts(exponential(), 3);\n * capped(3); // null — no more retries beyond attempt 3\n * ```\n *\n * @category extra\n */\nexport function withMaxAttempts(strategy: BackoffStrategy, maxAttempts: number): BackoffStrategy {\n\treturn (attempt, error, prevDelayNs) => {\n\t\tif (attempt >= maxAttempts) return null;\n\t\treturn strategy(attempt, error, prevDelayNs);\n\t};\n}\n\n/**\n * Maps a preset name to a concrete {@link BackoffStrategy} with library-default parameters.\n *\n * @param name - One of `constant`, `linear`, `exponential`, `fibonacci`, or `decorrelatedJitter`.\n * @returns Configured strategy with default parameters.\n * @throws Error when `name` is not a known preset.\n *\n * @example\n * ```ts\n * import { resolveBackoffPreset, retry } from \"@graphrefly/graphrefly-ts\";\n *\n * const out = retry(source, { count: 3, backoff: resolveBackoffPreset(\"exponential\") });\n * // Equivalent to retry(source, { count: 3, backoff: exponential() })\n * ```\n *\n * @category extra\n */\nexport function resolveBackoffPreset(name: BackoffPreset): BackoffStrategy {\n\tif (name === \"constant\") return constant(1 * NS_PER_SEC);\n\tif (name === \"linear\") return linear(1 * NS_PER_SEC);\n\tif (name === \"exponential\") return exponential();\n\tif (name === \"fibonacci\") return fibonacci();\n\tif (name === \"decorrelatedJitter\") return decorrelatedJitter();\n\tthrow new Error(\n\t\t`Unknown backoff preset: \"${String(name)}\". Use one of: constant, linear, exponential, fibonacci, decorrelatedJitter`,\n\t);\n}\n","/**\n * Timeout — emits `ERROR` with `TimeoutError` if no `DATA` arrives within the deadline.\n *\n * §3.1c — caching, fallback & composition sugar. Uses\n * `core/clock.js`-style nanoseconds and a `ResettableTimer` so the deadline\n * resets on each DATA. Distinct from the `operators/control.ts` timeout\n * (which forwards a caller-supplied error/value) — this one is the\n * resilience family's \"deadline → ERROR\" primitive.\n *\n * **DS-13.5.B (locked 2026-05-01).** Pre-1.0 break: returns\n * {@link TimeoutBundle} with `node` + `timeoutState` companion. Opts\n * accept `Partial<TimeoutOptions>` or `Node<Partial<TimeoutOptions>>`\n * (object-shape, replacing the old `NodeOrValue<number>` flat shape).\n * State preservation across rebind: `ns` change does NOT reset the\n * in-flight deadline — new `ns` applies to next attempt only.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tfactoryTag,\n\tmonotonicNs,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n\tResettableTimer,\n\tTEARDOWN,\n} from \"@graphrefly/pure-ts/core\";\nimport { isNode, operatorOpts } from \"./_internal.js\";\nimport { NS_PER_MS } from \"./backoff.js\";\n\n/**\n * Thrown by {@link withTimeout} when no `DATA` arrives within the deadline.\n *\n * @category extra\n */\nexport class TimeoutError extends Error {\n\toverride name = \"TimeoutError\";\n\tconstructor(ns: number) {\n\t\tsuper(`Timed out after ${ns / NS_PER_MS}ms`);\n\t}\n}\n\n/**\n * Options accepted by {@link withTimeout}.\n *\n * - `ns` — deadline in nanoseconds (must be `> 0`). Required at the\n * first opts settle; missing / non-positive values throw at\n * construction.\n * - `meta` — optional metadata merged onto the result node's `meta`\n * for describe()/explain() introspection. Reactive `meta` updates\n * are picked up on the next attempt's emission.\n *\n * @category extra/resilience\n */\nexport interface TimeoutOptions {\n\tns: number;\n\tmeta?: Record<string, unknown>;\n}\n\n/**\n * Lifecycle-shaped state companion emitted by {@link withTimeout}.\n *\n * Default `equals` dedups on the `status` field — subscribers don't\n * re-fire on identical-shape transitions, but DO fire on every state\n * transition AND on payload changes within the same status (e.g. when\n * `running.startedAt_ns` advances on a fresh attempt).\n *\n * @category extra/resilience\n */\nexport type TimeoutState =\n\t| { status: \"pending\" }\n\t| { status: \"running\"; startedAt_ns: number; deadline_ns: number }\n\t| { status: \"completed\"; settledAt_ns: number }\n\t| { status: \"errored\"; firedAt_ns: number; deadline_ns: number };\n\n/**\n * Bundle returned by {@link withTimeout}: the timeout-wrapped output node and\n * its lifecycle-shaped state companion.\n *\n * **Single-subscriber / pipeline-only contract (DS-13.5.B QA, N1, 2026-05-03).**\n * The `timeoutState` companion is allocated once at factory time and shared\n * across all subscribers to `node`. With one subscriber (the typical use\n * case — wire `node` into your downstream chain, optionally observe\n * `timeoutState` separately) the companion reflects a coherent timeline.\n * With **two or more subscribers** to `node`, each subscriber re-runs the\n * producer body and writes into the same `timeoutState`, which can flip\n * between states from different in-flight machines. Don't fan out\n * `node` to multiple subscribers and rely on `timeoutState` accuracy\n * unless you use {@link keepalive} / {@link share}-style consolidation.\n *\n * @category extra/resilience\n */\nexport interface TimeoutBundle<T> {\n\tnode: Node<T>;\n\ttimeoutState: Node<TimeoutState>;\n}\n\ninterface TimeoutExtraOpts {\n\tmeta?: Record<string, unknown>;\n}\n\n/**\n * Wrap `source` with a deadline. If no `DATA` arrives within `opts.ns`\n * nanoseconds, the result node emits `[[ERROR, TimeoutError]]` and\n * transitions `timeoutState` to `\"errored\"`.\n *\n * The timer starts on subscription and resets on each `DATA`. `DIRTY`\n * does NOT reset the timer. Terminal messages (`COMPLETE` / `ERROR`)\n * cancel the timer.\n *\n * **Reactive opts (DS-13.5.B, locked 2026-05-01).**\n *\n * - Static-form callers pass `Partial<TimeoutOptions>` (today's path).\n * `ns` is validated at construction; missing / non-positive throws\n * `RangeError`.\n * - Reactive-form callers pass `Node<Partial<TimeoutOptions>>` — each\n * emission shallow-merges over the prior opts. Empty `{}` emissions\n * are no-ops (no rebind, no companion fire). Mid-flight opts swap\n * does NOT reset the in-flight deadline; new `ns` applies to the\n * next `startTimer()` call.\n * - When the opts Node has `cache === undefined` (SENTINEL: no opts\n * emitted yet), the source is paused until the first valid opts\n * settle. The first valid settle must carry `ns > 0` or the timer\n * layer emits an ERROR (downstream observable) — distinct from the\n * construction-time `RangeError` thrown for static / cache-defined\n * invalid values.\n *\n * @param source - Upstream node.\n * @param opts - `Partial<TimeoutOptions>` (static) or\n * `Node<Partial<TimeoutOptions>>` (reactive).\n * @param extraOpts - Forwarded factory metadata (meta field merged\n * onto the result node).\n * @returns {@link TimeoutBundle} with `node` and `timeoutState`.\n *\n * @throws {RangeError} when the first opts settle is missing or has\n * non-positive `ns`.\n *\n * @category extra\n */\nexport function withTimeout<T>(\n\tsource: Node<T>,\n\topts: Partial<TimeoutOptions> | Node<Partial<TimeoutOptions>>,\n\textraOpts?: TimeoutExtraOpts,\n): TimeoutBundle<T> {\n\tconst isReactive = isNode(opts);\n\n\t// Construction-time validation:\n\t// - Static form: validate the supplied object eagerly.\n\t// - Node form with defined cache: validate the cache value eagerly.\n\t// - Node form with `cache === undefined`: defer validation to first\n\t// DATA emission; source is paused in the meantime.\n\tlet latestOpts: TimeoutOptions | null = null;\n\tif (!isReactive) {\n\t\tconst staticOpts = opts as Partial<TimeoutOptions>;\n\t\tif (\n\t\t\tstaticOpts.ns === undefined ||\n\t\t\ttypeof staticOpts.ns !== \"number\" ||\n\t\t\t!Number.isFinite(staticOpts.ns) ||\n\t\t\tstaticOpts.ns <= 0\n\t\t) {\n\t\t\tthrow new RangeError(\"withTimeout: opts.ns must be a positive finite number\");\n\t\t}\n\t\tlatestOpts = {\n\t\t\tns: staticOpts.ns,\n\t\t\t...(staticOpts.meta != null ? { meta: staticOpts.meta } : {}),\n\t\t};\n\t} else {\n\t\tconst cached = (opts as Node<Partial<TimeoutOptions>>).cache as\n\t\t\t| Partial<TimeoutOptions>\n\t\t\t| undefined;\n\t\tif (cached !== undefined) {\n\t\t\tif (\n\t\t\t\tcached.ns === undefined ||\n\t\t\t\ttypeof cached.ns !== \"number\" ||\n\t\t\t\t!Number.isFinite(cached.ns) ||\n\t\t\t\tcached.ns <= 0\n\t\t\t) {\n\t\t\t\tthrow new RangeError(\n\t\t\t\t\t\"withTimeout: opts.ns must be a positive finite number on first settle\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tlatestOpts = {\n\t\t\t\tns: cached.ns,\n\t\t\t\t...(cached.meta != null ? { meta: cached.meta } : {}),\n\t\t\t};\n\t\t}\n\t}\n\n\tconst callerMeta = extraOpts?.meta;\n\tconst factoryArgs: Record<string, unknown> = isReactive\n\t\t? { ns: \"Node<Partial<TimeoutOptions>>\" }\n\t\t: { ns: latestOpts!.ns };\n\n\t// Companion state node — lifecycle-shaped. Default Object.is-on-status\n\t// dedup so identical-shape transitions don't re-fire downstream.\n\tconst timeoutState = node<TimeoutState>([], {\n\t\tname: \"timeoutState\",\n\t\tdescribeKind: \"state\",\n\t\tinitial: { status: \"pending\" },\n\t\tequals: (a, b) =>\n\t\t\ta === b ||\n\t\t\t(a != null &&\n\t\t\t\tb != null &&\n\t\t\t\ttypeof a === \"object\" &&\n\t\t\t\ttypeof b === \"object\" &&\n\t\t\t\t(a as { status: string }).status === (b as { status: string }).status &&\n\t\t\t\tJSON.stringify(a) === JSON.stringify(b)),\n\t});\n\n\tconst out = node<T>(\n\t\t(_data, a) => {\n\t\t\tlet stopped = false;\n\t\t\tlet lastDeadlineNs = 0;\n\t\t\tconst timer = new ResettableTimer();\n\t\t\tlet optsUnsub: (() => void) | null = null;\n\t\t\tlet srcUnsub: (() => void) | null = null;\n\n\t\t\tfunction emitState(next: TimeoutState): void {\n\t\t\t\ttimeoutState.down([[DIRTY], [DATA, next]]);\n\t\t\t}\n\n\t\t\tfunction startTimer(): void {\n\t\t\t\tif (stopped) return;\n\t\t\t\t// QA A4 (2026-05-03): defensive guard — `latestOpts.ns`\n\t\t\t\t// reaching `undefined` / `NaN` / non-finite is a Class-of-\n\t\t\t\t// bugs source: an explicit `{ ns: undefined }` emit would\n\t\t\t\t// pass the per-key validation (which only checks\n\t\t\t\t// `next.ns !== undefined`) and shallow-merge over a valid\n\t\t\t\t// prior `ns`. Without this guard, `delayMs = NaN`, which\n\t\t\t\t// `setTimeout` treats as `0` → spurious immediate timeout.\n\t\t\t\tif (\n\t\t\t\t\tlatestOpts == null ||\n\t\t\t\t\ttypeof latestOpts.ns !== \"number\" ||\n\t\t\t\t\t!Number.isFinite(latestOpts.ns) ||\n\t\t\t\t\tlatestOpts.ns <= 0\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst ns = latestOpts.ns;\n\t\t\t\tlastDeadlineNs = ns;\n\t\t\t\tconst startedAt = monotonicNs();\n\t\t\t\tconst delayMs = ns / NS_PER_MS;\n\t\t\t\temitState({\n\t\t\t\t\tstatus: \"running\",\n\t\t\t\t\tstartedAt_ns: startedAt,\n\t\t\t\t\tdeadline_ns: ns,\n\t\t\t\t});\n\t\t\t\ttimer.start(delayMs, () => {\n\t\t\t\t\tif (stopped) return;\n\t\t\t\t\tstopped = true;\n\t\t\t\t\tsrcUnsub?.();\n\t\t\t\t\temitState({\n\t\t\t\t\t\tstatus: \"errored\",\n\t\t\t\t\t\tfiredAt_ns: monotonicNs(),\n\t\t\t\t\t\tdeadline_ns: ns,\n\t\t\t\t\t});\n\t\t\t\t\ta.down([[ERROR, new TimeoutError(ns)]]);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfunction attachSource(): void {\n\t\t\t\tif (srcUnsub != null || stopped) return;\n\t\t\t\tsrcUnsub = source.subscribe((msgs) => {\n\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\tif (stopped) return;\n\t\t\t\t\t\tconst t = m[0];\n\t\t\t\t\t\tif (t === DIRTY) a.down([[DIRTY]]);\n\t\t\t\t\t\telse if (t === DATA) {\n\t\t\t\t\t\t\tstartTimer();\n\t\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t\t} else if (t === RESOLVED) a.down([[RESOLVED]]);\n\t\t\t\t\t\telse if (t === COMPLETE) {\n\t\t\t\t\t\t\ttimer.cancel();\n\t\t\t\t\t\t\tstopped = true;\n\t\t\t\t\t\t\temitState({\n\t\t\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\t\t\tsettledAt_ns: monotonicNs(),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\t\ttimer.cancel();\n\t\t\t\t\t\t\tstopped = true;\n\t\t\t\t\t\t\temitState({\n\t\t\t\t\t\t\t\tstatus: \"errored\",\n\t\t\t\t\t\t\t\tfiredAt_ns: monotonicNs(),\n\t\t\t\t\t\t\t\tdeadline_ns: lastDeadlineNs,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} else if (t === TEARDOWN) {\n\t\t\t\t\t\t\ttimer.cancel();\n\t\t\t\t\t\t\tstopped = true;\n\t\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} else a.down([m]);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// Kick the initial timer if we already have valid opts.\n\t\t\t\tif (latestOpts != null && latestOpts.ns > 0) {\n\t\t\t\t\tstartTimer();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isReactive) {\n\t\t\t\tconst optsNode = opts as Node<Partial<TimeoutOptions>>;\n\t\t\t\toptsUnsub = optsNode.subscribe((msgs) => {\n\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\t\t\tconst next = m[1] as Partial<TimeoutOptions>;\n\t\t\t\t\t\tif (next == null || typeof next !== \"object\") continue;\n\t\t\t\t\t\t// Empty `{}` emit is a no-op (lock spec).\n\t\t\t\t\t\tconst keys = Object.keys(next);\n\t\t\t\t\t\tif (keys.length === 0) continue;\n\t\t\t\t\t\t// QA A4 (2026-05-03): validate ns whenever it APPEARS\n\t\t\t\t\t\t// in the emit's keys — including `{ ns: undefined }`,\n\t\t\t\t\t\t// which would otherwise skip validation and shallow-\n\t\t\t\t\t\t// merge over a valid prior `ns` with `undefined`,\n\t\t\t\t\t\t// producing `delayMs = NaN` ≈ 0 ms in startTimer().\n\t\t\t\t\t\t// `'ns' in next` covers both \"explicitly undefined\"\n\t\t\t\t\t\t// and \"explicitly invalid\" forms.\n\t\t\t\t\t\tif (\"ns\" in next) {\n\t\t\t\t\t\t\tif (typeof next.ns !== \"number\" || !Number.isFinite(next.ns) || next.ns <= 0) {\n\t\t\t\t\t\t\t\tif (latestOpts == null) {\n\t\t\t\t\t\t\t\t\t// First settle invalid — emit ERROR rather\n\t\t\t\t\t\t\t\t\t// than throw (mid-subscribe; sync throw\n\t\t\t\t\t\t\t\t\t// would corrupt the host scheduler).\n\t\t\t\t\t\t\t\t\tstopped = true;\n\t\t\t\t\t\t\t\t\ta.down([\n\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\tERROR,\n\t\t\t\t\t\t\t\t\t\t\tnew RangeError(\n\t\t\t\t\t\t\t\t\t\t\t\t\"withTimeout: opts.ns must be a positive finite number on first settle\",\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Ignore invalid mid-flight ns updates; keep\n\t\t\t\t\t\t\t\t// prior latestOpts.\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst wasNull = latestOpts == null;\n\t\t\t\t\t\tlatestOpts = {\n\t\t\t\t\t\t\t...(latestOpts ?? { ns: 0 }),\n\t\t\t\t\t\t\t...next,\n\t\t\t\t\t\t} as TimeoutOptions;\n\t\t\t\t\t\t// First valid settle activates the source attach.\n\t\t\t\t\t\tif (wasNull && latestOpts.ns > 0) {\n\t\t\t\t\t\t\tattachSource();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Static form: attach immediately. Reactive form with defined\n\t\t\t// cache also attaches immediately (latestOpts pre-populated).\n\t\t\tif (latestOpts != null) {\n\t\t\t\tattachSource();\n\t\t\t}\n\n\t\t\treturn () => {\n\t\t\t\tstopped = true;\n\t\t\t\ttimer.cancel();\n\t\t\t\tif (srcUnsub) srcUnsub();\n\t\t\t\tif (optsUnsub) optsUnsub();\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(),\n\t\t\tinitial: source.cache,\n\t\t\tmeta: { ...(callerMeta ?? {}), ...factoryTag(\"withTimeout\", factoryArgs) },\n\t\t},\n\t);\n\n\treturn { node: out, timeoutState };\n}\n","/**\n * Utils layer — domain building blocks.\n *\n * Single-purpose factories returning Node or Graph, organized by domain.\n *\n * @module\n */\n\nexport * from \"./_errors/index.js\";\nexport * from \"./ai/index.js\";\nexport * from \"./cqrs/index.js\";\nexport * from \"./demo-shell/index.js\";\nexport * from \"./domain-templates/index.js\";\nexport * from \"./graphspec/index.js\";\nexport * from \"./harness/index.js\";\nexport * from \"./inspect/index.js\";\nexport * from \"./job-queue/index.js\";\nexport * from \"./memory/index.js\";\nexport * from \"./messaging/index.js\";\nexport * from \"./orchestration/index.js\";\nexport * from \"./process/index.js\";\nexport * from \"./reactive-layout/index.js\";\nexport * from \"./reduction/index.js\";\nexport * from \"./resilience/index.js\";\nexport * from \"./surface/index.js\";\nexport * from \"./topology-view/index.js\";\n","/**\n * Shared pattern-layer error hierarchy (Audit 2 — locked 2026-04-24).\n *\n * Cross-primitive `instanceof` checks: gate, queue, cqrs.dispatch, saga,\n * projection, subscription, etc. all use these classes so consumer error\n * handlers can branch by kind rather than by message string.\n *\n * @internal — exposed via patterns/index for primitive impls; consumers\n * should import the relevant class from the primitive's barrel.\n */\n\n/** Root error class. All pattern-layer errors extend this. */\nexport class GraphReFlyError extends Error {\n\tconstructor(message: string, options?: ErrorOptions) {\n\t\tsuper(message, options);\n\t\tthis.name = this.constructor.name;\n\t}\n}\n\n/** Re-registering a name that's already taken (command, gate, queue, saga, projection). */\nexport class DuplicateRegistrationError extends GraphReFlyError {\n\tconstructor(\n\t\treadonly kind: string,\n\t\treadonly registrationName: string,\n\t) {\n\t\tsuper(`Duplicate ${kind} registration: \"${registrationName}\"`);\n\t}\n}\n\n/** CQRS handler emitted an event type not in its declared `emits` set. */\nexport class UndeclaredEmitError extends GraphReFlyError {\n\tconstructor(\n\t\treadonly commandName: string,\n\t\treadonly eventName: string,\n\t\treadonly declaredEmits: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`Command \"${commandName}\" emitted undeclared event \"${eventName}\". Declared emits: [${declaredEmits.join(\", \")}]`,\n\t\t);\n\t}\n}\n\n/** Aggregate version expected vs observed mismatch on dispatch. */\nexport class OptimisticConcurrencyError extends GraphReFlyError {\n\tconstructor(\n\t\treadonly aggregateId: string,\n\t\treadonly expected: number,\n\t\treadonly actual: number,\n\t) {\n\t\tsuper(\n\t\t\t`Optimistic concurrency conflict on aggregate \"${aggregateId}\": expected version ${expected}, got ${actual}`,\n\t\t);\n\t}\n}\n\n/** `dispatch(name, ...)` for a name that wasn't registered via `command()`. */\nexport class UnknownCommandError extends GraphReFlyError {\n\tconstructor(readonly commandName: string) {\n\t\tsuper(`Unknown command: \"${commandName}\". Register with command() first.`);\n\t}\n}\n\n/** Wrap any error thrown from inside a command handler. Original on `cause`. */\nexport class CommandHandlerError extends GraphReFlyError {\n\tconstructor(\n\t\treadonly commandName: string,\n\t\tcause: unknown,\n\t) {\n\t\tsuper(\n\t\t\t`Command handler \"${commandName}\" threw: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t{ cause },\n\t\t);\n\t}\n}\n\n/** Mutation method called after the primitive was torn down. */\nexport class TeardownError extends GraphReFlyError {\n\tconstructor(\n\t\treadonly kind: string,\n\t\treadonly method: string,\n\t) {\n\t\tsuper(`${kind}: ${method}() called after teardown`);\n\t}\n}\n\n/** Projection rebuild failure — adapter / decode / reducer error. */\nexport class RebuildError extends GraphReFlyError {\n\tconstructor(\n\t\treadonly projectionName: string,\n\t\tcause: unknown,\n\t) {\n\t\tsuper(\n\t\t\t`Projection \"${projectionName}\" rebuild failed: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t{ cause },\n\t\t);\n\t}\n}\n","/**\n * Pluggable model capabilities (roadmap §9.3d).\n *\n * The library defines the **shape** of what's knowable about a model\n * (context window, rate limits, features, pricing reference) and provides\n * a registry factory. Capability **data** is user-supplied — no baked-in\n * tables, no drift-prone catalog.\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport { node } from \"@graphrefly/pure-ts/core\";\n\nimport { reactiveMap } from \"@graphrefly/pure-ts/extra\";\nimport type { ModelPricing } from \"./pricing.js\";\n\n// ---------------------------------------------------------------------------\n// Limits\n// ---------------------------------------------------------------------------\n\n/**\n * Rate and size limits for a single model at the user's service tier.\n *\n * Where providers expose distinct standard / batch / flex limits, register\n * each as a separate model id with its own `ModelLimits`.\n */\nexport interface ModelLimits {\n\t/** Total tokens the model can process per request (input + output). */\n\tcontextWindow?: number;\n\t/** Max input tokens if distinct from contextWindow. */\n\tmaxInputTokens?: number;\n\t/** Max generated output tokens (excludes reasoning unless provider folds them). */\n\tmaxOutputTokens?: number;\n\t/** Max reasoning/thinking tokens budget. */\n\tmaxReasoningTokens?: number;\n\t/** Minimum prompt size for prompt caching to activate. */\n\tminCacheTokens?: number;\n\t/** Requests-per-minute rate limit. */\n\trpm?: number;\n\t/** Requests-per-day rate limit. */\n\trpd?: number;\n\t/** Tokens-per-minute rate limit (input + output, per provider convention). */\n\ttpm?: number;\n\t/** Tokens-per-day rate limit. */\n\ttpd?: number;\n\t/** Max concurrent in-flight requests. */\n\tconcurrentRequests?: number;\n\t/** Provider-specific limits not covered above. */\n\textensions?: Record<string, number>;\n}\n\n// ---------------------------------------------------------------------------\n// Features\n// ---------------------------------------------------------------------------\n\nexport interface ModelFeatures {\n\ttoolUse?: boolean;\n\tvision?: boolean;\n\taudioInput?: boolean;\n\taudioOutput?: boolean;\n\treasoning?: boolean;\n\tstreaming?: boolean;\n\tpromptCache?: boolean;\n\tbatchApi?: boolean;\n\t/** Provider-specific feature flags. */\n\textensions?: Record<string, boolean>;\n}\n\n// ---------------------------------------------------------------------------\n// ModelCapabilities\n// ---------------------------------------------------------------------------\n\n/** Static facts about a model. Pricing is optional; keep a separate registry if preferred. */\nexport interface ModelCapabilities {\n\tid: string;\n\tprovider: string;\n\tpricing?: ModelPricing;\n\tlimits?: ModelLimits;\n\tfeatures?: ModelFeatures;\n\t/** Free-form metadata (release date, deprecation flag, provider notes). */\n\tmetadata?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// CapabilitiesRegistry\n// ---------------------------------------------------------------------------\n\nexport interface CapabilitiesRegistry {\n\tlookup(provider: string, model: string): ModelCapabilities | undefined;\n\tregister(cap: ModelCapabilities): void;\n\tremove(provider: string, model: string): boolean;\n\tentries(): IterableIterator<ModelCapabilities>;\n\t// Reactive views (Unit 10 Q4) ---------------------------------------------\n\t/**\n\t * Reactive view of `(provider, model)` → `ModelCapabilities`. Re-emits\n\t * whenever any `register()` / `remove()` touches the underlying store, so\n\t * UIs and gated middleware (capability-aware retry, feature flags) can\n\t * subscribe instead of polling. Prefix fallback mirrors the imperative\n\t * `lookup()`: exact match first, then longest-prefix within provider.\n\t */\n\tlookupNode(provider: string, model: string): Node<ModelCapabilities | undefined>;\n\t/** Reactive view of every registered entry. */\n\treadonly entriesNode: Node<readonly ModelCapabilities[]>;\n\t/** Reactive slice of entries for a single provider. */\n\tbyProvider(provider: string): Node<readonly ModelCapabilities[]>;\n}\n\nfunction capKey(provider: string, model: string): string {\n\treturn `${provider}::${model}`;\n}\n\n/** Create a fresh `CapabilitiesRegistry`. Optionally seed with entries. */\nexport function createCapabilitiesRegistry(\n\tinitial?: readonly ModelCapabilities[],\n): CapabilitiesRegistry {\n\t// Reactive storage (Unit 10 Q4). We keep the imperative `lookup` fast path\n\t// (O(1) exact match + prefix fallback) by reading the bundle's snapshot via\n\t// `.cache`. Reactive views (`lookupNode`, `entriesNode`, `byProvider`) are\n\t// `derived` nodes over the bundle's `entries` node.\n\tconst bundle = reactiveMap<string, ModelCapabilities>({\n\t\tname: \"capabilitiesRegistry\",\n\t});\n\n\tconst register = (cap: ModelCapabilities): void => {\n\t\tbundle.set(capKey(cap.provider, cap.id), cap);\n\t};\n\n\tif (initial) for (const cap of initial) register(cap);\n\n\tconst lookupSync = (provider: string, model: string): ModelCapabilities | undefined => {\n\t\tconst exact = bundle.get(capKey(provider, model));\n\t\tif (exact) return exact;\n\t\t// Prefix fallback within provider via snapshot iteration. The fast\n\t\t// path (`maxSize` unset → all entries live) keeps this O(|models|).\n\t\tconst snapshot = bundle.entries.cache;\n\t\tif (!snapshot) return undefined;\n\t\tlet best: ModelCapabilities | undefined;\n\t\tfor (const [, cap] of snapshot) {\n\t\t\tif (cap.provider !== provider) continue;\n\t\t\tconst candidate = cap.id;\n\t\t\tif (model.startsWith(candidate)) {\n\t\t\t\tif (!best || candidate.length > best.id.length) {\n\t\t\t\t\tbest = cap;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn best;\n\t};\n\n\t// Reactive views — derived over the bundle's entries snapshot. Caches\n\t// per-(provider, model) pair so re-invoking `lookupNode(\"anthropic\", \"X\")`\n\t// returns the same node (keepalive stays attached, no churn).\n\t//\n\t// LRU cap protects callers that mint `lookupNode(provider, userSupplied)`\n\t// from unbounded growth. Native `Map` insertion-order iteration gives us\n\t// O(1) eviction: the oldest insertion is the first key. 128 is large\n\t// enough to cover realistic provider × model combos (every shipped\n\t// Anthropic / OpenAI / Google model fits well under this).\n\tconst LOOKUP_CACHE_MAX = 128;\n\tconst lookupCache = new Map<string, Node<ModelCapabilities | undefined>>();\n\tconst byProviderCache = new Map<string, Node<readonly ModelCapabilities[]>>();\n\tconst lruTouch = <V>(cache: Map<string, V>, key: string, value: V, max: number): void => {\n\t\t// Delete-then-reinsert moves the key to the LRU end; evict the oldest\n\t\t// (first-inserted) entry when we overflow.\n\t\tif (cache.has(key)) cache.delete(key);\n\t\tcache.set(key, value);\n\t\twhile (cache.size > max) {\n\t\t\tconst oldest = cache.keys().next().value as string | undefined;\n\t\t\tif (oldest === undefined) break;\n\t\t\tcache.delete(oldest);\n\t\t}\n\t};\n\n\tconst entriesNode = node<readonly ModelCapabilities[]>(\n\t\t[bundle.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst snapshot = data[0];\n\t\t\t// Defensive coercion: `ReactiveMapBundle.entries` always emits a\n\t\t\t// real `Map` on the live emit path, but a snapshot-restore round\n\t\t\t// trip can deliver a plain `{}` (the default codec serializes\n\t\t\t// `Map` to a non-Map shape). Without the `instanceof` guard,\n\t\t\t// `.values()` would be `undefined`. Same defense pattern as\n\t\t\t// `mapFromSnapshot` in `extra/composite.ts`.\n\t\t\tactions.emit(\n\t\t\t\tsnapshot instanceof Map\n\t\t\t\t\t? Array.from((snapshot as ReadonlyMap<string, ModelCapabilities>).values())\n\t\t\t\t\t: [],\n\t\t\t);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tname: \"capabilitiesRegistry/entries\",\n\t\t\tinitial: [] as ModelCapabilities[],\n\t\t},\n\t);\n\n\treturn {\n\t\tregister,\n\t\tlookup: lookupSync,\n\t\tremove(provider, model) {\n\t\t\tconst existed = bundle.has(capKey(provider, model));\n\t\t\tif (existed) bundle.delete(capKey(provider, model));\n\t\t\treturn existed;\n\t\t},\n\t\tentries() {\n\t\t\t// Snapshot via bundle — matches legacy behavior.\n\t\t\tconst snapshot = bundle.entries.cache;\n\t\t\treturn (function* () {\n\t\t\t\tif (!snapshot) return;\n\t\t\t\tfor (const cap of snapshot.values()) yield cap;\n\t\t\t})();\n\t\t},\n\t\tlookupNode(provider, model) {\n\t\t\tconst cacheKey = capKey(provider, model);\n\t\t\tconst cached = lookupCache.get(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\t// LRU touch: move to end so it survives eviction.\n\t\t\t\tlookupCache.delete(cacheKey);\n\t\t\t\tlookupCache.set(cacheKey, cached);\n\t\t\t\treturn cached;\n\t\t\t}\n\t\t\tconst lookupNode = node<ModelCapabilities | undefined>(\n\t\t\t\t[bundle.entries],\n\t\t\t\t(_batchData, actions) => {\n\t\t\t\t\tactions.emit(lookupSync(provider, model));\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\tname: `capabilitiesRegistry/lookup/${provider}::${model}`,\n\t\t\t\t\tinitial: undefined,\n\t\t\t\t},\n\t\t\t);\n\t\t\tlruTouch(lookupCache, cacheKey, lookupNode, LOOKUP_CACHE_MAX);\n\t\t\treturn lookupNode;\n\t\t},\n\t\tentriesNode,\n\t\tbyProvider(provider) {\n\t\t\tconst cached = byProviderCache.get(provider);\n\t\t\tif (cached) {\n\t\t\t\tbyProviderCache.delete(provider);\n\t\t\t\tbyProviderCache.set(provider, cached);\n\t\t\t\treturn cached;\n\t\t\t}\n\t\t\tconst providerNode = node<readonly ModelCapabilities[]>(\n\t\t\t\t[entriesNode],\n\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t\t);\n\t\t\t\t\tconst entries = data[0] as readonly ModelCapabilities[];\n\t\t\t\t\tactions.emit(entries.filter((c) => c.provider === provider));\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\tname: `capabilitiesRegistry/byProvider/${provider}`,\n\t\t\t\t\tinitial: [],\n\t\t\t\t},\n\t\t\t);\n\t\t\tlruTouch(byProviderCache, provider, providerNode, LOOKUP_CACHE_MAX);\n\t\t\treturn providerNode;\n\t\t},\n\t};\n}\n","/**\n * AnthropicAdapter — default fetch-backed, optional SDK-backed.\n *\n * - `anthropicAdapter({ apiKey })` uses native `fetch` + SSE parsing.\n * - `anthropicAdapter({ sdk })` delegates to a user-provided `@anthropic-ai/sdk` instance.\n *\n * Token usage mapping:\n * - `input_tokens` → `input.regular`\n * - `cache_read_input_tokens` → `input.cacheRead`\n * - `cache_creation.ephemeral_5m_input_tokens` → `input.cacheWrite5m`\n * - `cache_creation.ephemeral_1h_input_tokens` → `input.cacheWrite1h`\n * - `cache_creation_input_tokens` (legacy) → `input.cacheWrite5m` (default TTL)\n * - `output_tokens` → `output.regular`\n * - `server_tool_use.web_search_requests` → `auxiliary.webSearchRequests`\n */\n\nimport { monotonicNs } from \"@graphrefly/pure-ts/core\";\nimport { makeHttpError } from \"../../../../base/io/http-error.js\";\nimport { parseSSEStream } from \"../../../../base/io/sse.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n\tToolDefinition,\n} from \"../core/types.js\";\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface AnthropicAdapterOptions {\n\t/** API key. Falls back to `process.env.ANTHROPIC_API_KEY` on Node. */\n\tapiKey?: string;\n\t/** Default model (overridable per-call via `LLMInvokeOptions.model`). */\n\tmodel?: string;\n\t/** Override the base URL. Default `https://api.anthropic.com`. */\n\tbaseURL?: string;\n\t/** API version header. Default `\"2023-06-01\"`. */\n\tanthropicVersion?: string;\n\t/** Additional headers to send on every request (overridden by per-call). */\n\theaders?: Record<string, string>;\n\t/**\n\t * User-provided SDK instance. When present, the adapter delegates to it\n\t * (uses `.messages.create`) instead of native fetch.\n\t * Shape matches `@anthropic-ai/sdk` `.messages` API; any object with a\n\t * compatible `create`/`stream` contract works.\n\t */\n\tsdk?: AnthropicSdkLike;\n\t/** Custom fetch (useful for tests). Default `globalThis.fetch`. */\n\tfetchImpl?: typeof fetch;\n}\n\n/** Minimal SDK shape we interoperate with. */\nexport interface AnthropicSdkLike {\n\tmessages: {\n\t\tcreate(\n\t\t\tparams: Record<string, unknown>,\n\t\t\topts?: { signal?: AbortSignal },\n\t\t): Promise<AnthropicMessageResponse>;\n\t\tstream?(\n\t\t\tparams: Record<string, unknown>,\n\t\t\topts?: { signal?: AbortSignal },\n\t\t): AsyncIterable<AnthropicStreamEvent>;\n\t};\n}\n\ninterface AnthropicMessageResponse {\n\tid: string;\n\tcontent: ReadonlyArray<\n\t\t| { type: \"text\"; text: string }\n\t\t| { type: \"tool_use\"; id: string; name: string; input: Record<string, unknown> }\n\t\t| { type: \"thinking\"; thinking: string }\n\t\t| { type: string; [key: string]: unknown }\n\t>;\n\tstop_reason?: string;\n\tusage: AnthropicUsage;\n\tmodel?: string;\n}\n\ninterface AnthropicUsage {\n\tinput_tokens?: number;\n\toutput_tokens?: number;\n\tcache_read_input_tokens?: number;\n\tcache_creation_input_tokens?: number;\n\tcache_creation?: {\n\t\tephemeral_5m_input_tokens?: number;\n\t\tephemeral_1h_input_tokens?: number;\n\t};\n\tserver_tool_use?: {\n\t\tweb_search_requests?: number;\n\t};\n}\n\ntype AnthropicStreamEvent =\n\t| { type: \"message_start\"; message: { usage: AnthropicUsage } }\n\t| { type: \"content_block_start\"; index: number; content_block: Record<string, unknown> }\n\t| { type: \"content_block_delta\"; index: number; delta: Record<string, unknown> }\n\t| { type: \"content_block_stop\"; index: number }\n\t| { type: \"message_delta\"; delta: { stop_reason?: string; usage?: AnthropicUsage } }\n\t| { type: \"message_stop\" }\n\t| { type: string; [key: string]: unknown };\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function anthropicAdapter(opts: AnthropicAdapterOptions = {}): LLMAdapter {\n\tif (opts.sdk) return sdkBackedAnthropic(opts);\n\treturn fetchBackedAnthropic(opts);\n}\n\n// ---------------------------------------------------------------------------\n// Request/response mapping\n// ---------------------------------------------------------------------------\n\nfunction toAnthropicRequest(\n\tmessages: readonly ChatMessage[],\n\tinvokeOpts: LLMInvokeOptions | undefined,\n\tdefaultModel: string | undefined,\n\tstream: boolean,\n): Record<string, unknown> {\n\tconst model = invokeOpts?.model ?? defaultModel;\n\tif (!model)\n\t\tthrow new Error(\"anthropicAdapter: model must be set via options.model or invokeOpts.model\");\n\n\tconst { system, chat } = partitionSystem(messages, invokeOpts?.systemPrompt);\n\n\tconst body: Record<string, unknown> = {\n\t\tmodel,\n\t\tmessages: chat.map(toAnthropicMessage),\n\t\tmax_tokens: invokeOpts?.maxTokens ?? 4096,\n\t};\n\tif (system) body.system = system;\n\tif (invokeOpts?.temperature != null) body.temperature = invokeOpts.temperature;\n\tif (invokeOpts?.tools && invokeOpts.tools.length > 0)\n\t\tbody.tools = invokeOpts.tools.map(toAnthropicTool);\n\tif (invokeOpts?.maxReasoningTokens != null) {\n\t\tbody.thinking = { type: \"enabled\", budget_tokens: invokeOpts.maxReasoningTokens };\n\t}\n\tif (invokeOpts?.cacheHint) {\n\t\t// Cache-control injected per-message by the user (Anthropic cache is\n\t\t// block-level). We surface the hint via metadata, but the canonical\n\t\t// cacheHint API is informational — power users pass cache_control\n\t\t// directly on messages via providerExtras.\n\t}\n\tif (stream) body.stream = true;\n\tif (invokeOpts?.providerExtras) Object.assign(body, invokeOpts.providerExtras);\n\treturn body;\n}\n\nfunction partitionSystem(\n\tmessages: readonly ChatMessage[],\n\tsystemPrompt: string | undefined,\n): { system: string | undefined; chat: readonly ChatMessage[] } {\n\tconst systemParts: string[] = [];\n\tif (systemPrompt) systemParts.push(systemPrompt);\n\tconst chat: ChatMessage[] = [];\n\tfor (const m of messages) {\n\t\tif (m.role === \"system\") systemParts.push(m.content);\n\t\telse chat.push(m);\n\t}\n\treturn { system: systemParts.length > 0 ? systemParts.join(\"\\n\\n\") : undefined, chat };\n}\n\nfunction toAnthropicMessage(m: ChatMessage): Record<string, unknown> {\n\tif (m.role === \"tool\") {\n\t\treturn {\n\t\t\trole: \"user\",\n\t\t\tcontent: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"tool_result\",\n\t\t\t\t\ttool_use_id: m.toolCallId,\n\t\t\t\t\tcontent: m.content,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\tif (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n\t\tconst blocks: unknown[] = [];\n\t\tif (m.content) blocks.push({ type: \"text\", text: m.content });\n\t\tfor (const tc of m.toolCalls) {\n\t\t\tblocks.push({ type: \"tool_use\", id: tc.id, name: tc.name, input: tc.arguments });\n\t\t}\n\t\treturn { role: \"assistant\", content: blocks };\n\t}\n\treturn { role: m.role, content: m.content };\n}\n\nfunction toAnthropicTool(t: ToolDefinition): Record<string, unknown> {\n\treturn {\n\t\tname: t.name,\n\t\tdescription: t.description,\n\t\tinput_schema: t.parameters,\n\t};\n}\n\n/**\n * Merge an incoming Anthropic usage update into the running snapshot. Unlike\n * a shallow spread, this preserves nested `cache_creation` fields when the\n * update omits them (or sends an empty object). Applied to both SSE and SDK\n * streaming paths.\n */\nfunction mergeAnthropicUsage(\n\tprev: AnthropicUsage | undefined,\n\tnext: AnthropicUsage,\n): AnthropicUsage {\n\tif (!prev) return { ...next };\n\tconst merged: AnthropicUsage = { ...prev };\n\t// Scalar fields: overwrite when present in `next`.\n\tif (next.input_tokens != null) merged.input_tokens = next.input_tokens;\n\tif (next.output_tokens != null) merged.output_tokens = next.output_tokens;\n\tif (next.cache_read_input_tokens != null)\n\t\tmerged.cache_read_input_tokens = next.cache_read_input_tokens;\n\tif (next.cache_creation_input_tokens != null)\n\t\tmerged.cache_creation_input_tokens = next.cache_creation_input_tokens;\n\t// Nested `cache_creation`: shallow-merge its own fields so a non-empty\n\t// update doesn't wipe a prior ephemeral_5m/1h value.\n\tif (next.cache_creation) {\n\t\tmerged.cache_creation = {\n\t\t\t...(prev.cache_creation ?? {}),\n\t\t\t...next.cache_creation,\n\t\t};\n\t}\n\tif (next.server_tool_use) {\n\t\tmerged.server_tool_use = {\n\t\t\t...(prev.server_tool_use ?? {}),\n\t\t\t...next.server_tool_use,\n\t\t};\n\t}\n\treturn merged;\n}\n\nfunction mapUsage(u: AnthropicUsage | undefined): TokenUsage {\n\tconst usage: TokenUsage = {\n\t\tinput: { regular: u?.input_tokens ?? 0 },\n\t\toutput: { regular: u?.output_tokens ?? 0 },\n\t\traw: u,\n\t};\n\tif (u?.cache_read_input_tokens) usage.input.cacheRead = u.cache_read_input_tokens;\n\tif (u?.cache_creation) {\n\t\tif (u.cache_creation.ephemeral_5m_input_tokens)\n\t\t\tusage.input.cacheWrite5m = u.cache_creation.ephemeral_5m_input_tokens;\n\t\tif (u.cache_creation.ephemeral_1h_input_tokens)\n\t\t\tusage.input.cacheWrite1h = u.cache_creation.ephemeral_1h_input_tokens;\n\t} else if (u?.cache_creation_input_tokens) {\n\t\t// Legacy flat field — default to 5m TTL.\n\t\tusage.input.cacheWrite5m = u.cache_creation_input_tokens;\n\t}\n\tif (u?.server_tool_use?.web_search_requests) {\n\t\tusage.auxiliary = { webSearchRequests: u.server_tool_use.web_search_requests };\n\t}\n\treturn usage;\n}\n\nfunction toLLMResponse(msg: AnthropicMessageResponse, latencyMs: number): LLMResponse {\n\tconst textParts: string[] = [];\n\tconst toolCalls: { id: string; name: string; arguments: Record<string, unknown> }[] = [];\n\tfor (const block of msg.content) {\n\t\tif (block.type === \"text\" && typeof (block as { text?: unknown }).text === \"string\") {\n\t\t\ttextParts.push((block as { text: string }).text);\n\t\t} else if (block.type === \"tool_use\") {\n\t\t\tconst tb = block as { id: string; name: string; input: Record<string, unknown> };\n\t\t\ttoolCalls.push({ id: tb.id, name: tb.name, arguments: tb.input ?? {} });\n\t\t}\n\t}\n\treturn {\n\t\tcontent: textParts.join(\"\"),\n\t\ttoolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n\t\tusage: mapUsage(msg.usage),\n\t\tfinishReason: msg.stop_reason,\n\t\tlatencyMs,\n\t\tmodel: msg.model,\n\t\tprovider: \"anthropic\",\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Fetch-backed impl\n// ---------------------------------------------------------------------------\n\nfunction fetchBackedAnthropic(opts: AnthropicAdapterOptions): LLMAdapter {\n\tconst apiKey =\n\t\topts.apiKey ??\n\t\t(globalThis as { process?: { env?: Record<string, string> } }).process?.env?.ANTHROPIC_API_KEY;\n\tif (!apiKey) {\n\t\t// Don't throw at construction — allow test harnesses / dry-run setups\n\t\t// that never call invoke. Throw at first use instead.\n\t}\n\tconst baseURL = opts.baseURL ?? \"https://api.anthropic.com\";\n\tconst anthropicVersion = opts.anthropicVersion ?? \"2023-06-01\";\n\tconst fetchImpl = opts.fetchImpl ?? fetch;\n\n\tconst commonHeaders = (): Record<string, string> => {\n\t\tif (!apiKey)\n\t\t\tthrow new Error(\"anthropicAdapter: apiKey required for invoke/stream (or provide opts.sdk)\");\n\t\treturn {\n\t\t\t\"x-api-key\": apiKey,\n\t\t\t\"anthropic-version\": anthropicVersion,\n\t\t\t\"content-type\": \"application/json\",\n\t\t\t...(opts.headers ?? {}),\n\t\t};\n\t};\n\n\treturn {\n\t\tprovider: \"anthropic\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toAnthropicRequest(messages, invokeOpts, opts.model, false);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await fetchImpl(`${baseURL}/v1/messages`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: commonHeaders(),\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, \"Anthropic\");\n\t\t\tconst json = (await resp.json()) as AnthropicMessageResponse;\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(json, latencyMs);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst body = toAnthropicRequest(messages, invokeOpts, opts.model, true);\n\t\t\tconst resp = await fetchImpl(`${baseURL}/v1/messages`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { ...commonHeaders(), accept: \"text/event-stream\" },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, \"Anthropic\");\n\t\t\tif (!resp.body) throw new Error(\"anthropicAdapter: streaming response has no body\");\n\n\t\t\tlet finalUsage: AnthropicUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tconst toolCallsByIndex: Map<number, { id: string; name: string; argBuf: string }> = new Map();\n\n\t\t\tfor await (const event of parseSSEStream(resp.body, { signal: invokeOpts?.signal })) {\n\t\t\t\tconst data = event.data;\n\t\t\t\tif (!data) continue;\n\t\t\t\tlet parsed: AnthropicStreamEvent;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(data) as AnthropicStreamEvent;\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tswitch (parsed.type) {\n\t\t\t\t\tcase \"message_start\": {\n\t\t\t\t\t\tconst ms = parsed as { message: { usage: AnthropicUsage } };\n\t\t\t\t\t\tfinalUsage = mergeAnthropicUsage(finalUsage, ms.message.usage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"content_block_start\": {\n\t\t\t\t\t\tconst cb = parsed as { index: number; content_block: Record<string, unknown> };\n\t\t\t\t\t\tconst b = cb.content_block;\n\t\t\t\t\t\tif (b.type === \"tool_use\") {\n\t\t\t\t\t\t\ttoolCallsByIndex.set(cb.index, {\n\t\t\t\t\t\t\t\tid: String(b.id ?? \"\"),\n\t\t\t\t\t\t\t\tname: String(b.name ?? \"\"),\n\t\t\t\t\t\t\t\targBuf: \"\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\t\tdelta: { id: String(b.id ?? \"\"), name: String(b.name ?? \"\") },\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"content_block_delta\": {\n\t\t\t\t\t\tconst cbd = parsed as { index: number; delta: Record<string, unknown> };\n\t\t\t\t\t\tconst d = cbd.delta;\n\t\t\t\t\t\tif (d.type === \"text_delta\" && typeof d.text === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"token\", delta: d.text };\n\t\t\t\t\t\t} else if (d.type === \"input_json_delta\" && typeof d.partial_json === \"string\") {\n\t\t\t\t\t\t\tconst existing = toolCallsByIndex.get(cbd.index);\n\t\t\t\t\t\t\tif (existing) existing.argBuf += d.partial_json;\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\t\tdelta: { argumentsDelta: d.partial_json },\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (d.type === \"thinking_delta\" && typeof d.thinking === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"thinking\", delta: d.thinking };\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_delta\": {\n\t\t\t\t\t\tconst md = parsed as { delta: { stop_reason?: string; usage?: AnthropicUsage } };\n\t\t\t\t\t\tif (md.delta.stop_reason) finishReason = md.delta.stop_reason;\n\t\t\t\t\t\tif (md.delta.usage) {\n\t\t\t\t\t\t\tfinalUsage = mergeAnthropicUsage(finalUsage, md.delta.usage);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_stop\":\n\t\t\t\t\t\t// Fall through to finalize after the loop.\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// SDK-backed impl\n// ---------------------------------------------------------------------------\n\nfunction sdkBackedAnthropic(opts: AnthropicAdapterOptions): LLMAdapter {\n\tconst sdk = opts.sdk;\n\tif (!sdk) throw new Error(\"sdkBackedAnthropic: sdk instance required\");\n\treturn {\n\t\tprovider: \"anthropic\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toAnthropicRequest(messages, invokeOpts, opts.model, false);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = (await sdk.messages.create(body, {\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t})) as AnthropicMessageResponse;\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(resp, latencyMs);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (!sdk.messages.stream) {\n\t\t\t\tthrow new Error(\"sdkBackedAnthropic: SDK instance does not expose .messages.stream\");\n\t\t\t}\n\t\t\tconst body = toAnthropicRequest(messages, invokeOpts, opts.model, true);\n\t\t\tlet finalUsage: AnthropicUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tfor await (const event of sdk.messages.stream(body, { signal: invokeOpts?.signal })) {\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"message_start\":\n\t\t\t\t\t\tfinalUsage = mergeAnthropicUsage(\n\t\t\t\t\t\t\tfinalUsage,\n\t\t\t\t\t\t\t(event as { message: { usage: AnthropicUsage } }).message.usage,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"content_block_delta\": {\n\t\t\t\t\t\tconst d = (event as { delta: Record<string, unknown> }).delta;\n\t\t\t\t\t\tif (d?.type === \"text_delta\" && typeof d.text === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"token\", delta: d.text };\n\t\t\t\t\t\t} else if (d?.type === \"input_json_delta\" && typeof d.partial_json === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"tool-call-delta\", delta: { argumentsDelta: d.partial_json } };\n\t\t\t\t\t\t} else if (d?.type === \"thinking_delta\" && typeof d.thinking === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"thinking\", delta: d.thinking };\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_delta\": {\n\t\t\t\t\t\tconst md = event as { delta: { stop_reason?: string; usage?: AnthropicUsage } };\n\t\t\t\t\t\tif (md.delta.stop_reason) finishReason = md.delta.stop_reason;\n\t\t\t\t\t\tif (md.delta.usage) finalUsage = mergeAnthropicUsage(finalUsage, md.delta.usage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// SSE parser\n// ---------------------------------------------------------------------------\n","/**\n * HTTP error builder — companion to {@link ./adapters.ts}'s `fromHTTP` /\n * `fromHTTPStream` / `toHTTP`. Pure, zero-dep function that turns a failed\n * `Response` into an `Error` exposing the `{status, headers, message}` shape\n * that `HttpErrorLike` consumers (rate-limit parsers, retry predicates,\n * observability layers) expect.\n *\n * Universal tier — safe for browser and Node. No Node-only imports.\n */\n\n/**\n * Construct an `Error` carrying `status` + `headers` fields from a non-ok\n * `Response`. Reads the body with `resp.text()` for diagnostic context; a\n * body read failure is swallowed (empty string) so the returned error always\n * reflects the original status/statusText at minimum.\n *\n * @param resp - The offending `Response` object.\n * @param provider - Optional prefix (e.g. `\"Anthropic\"`, `\"openai\"`) used in\n * the error message. Defaults to `\"HTTP\"`.\n * @returns An `Error` whose `message` is `\"${provider} API <status>: <statusText>[ — body]\"`,\n * with `status: number` and `headers: Headers` attached.\n *\n * @category extra\n */\nexport async function makeHttpError(resp: Response, provider?: string): Promise<Error> {\n\tlet body: string;\n\ttry {\n\t\tbody = await resp.text();\n\t} catch {\n\t\tbody = \"\";\n\t}\n\tconst prefix = provider ?? \"HTTP\";\n\tconst err = new Error(\n\t\t`${prefix} API ${resp.status}: ${resp.statusText}${body ? ` — ${body}` : \"\"}`,\n\t) as Error & {\n\t\tstatus: number;\n\t\theaders: Headers;\n\t};\n\terr.status = resp.status;\n\terr.headers = resp.headers;\n\treturn err;\n}\n","/**\n * Server-Sent Events IO — `toSSE` / `toSSEBytes` (encode any node into the\n * `text/event-stream` wire format), `toReadableStream` (web-stream sink),\n * `parseSSEStream` (async-iterator parser), `fromSSE` (line-delimited parser\n * source).\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tdefaultConfig,\n\tERROR,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport { type ExtraOpts, sourceOpts } from \"./_internal.js\";\n\n/** Options for {@link toSSE}. */\nexport type ToSSEOptions = {\n\t/** Custom payload serializer for non-string payloads. Default: `JSON.stringify` fallback to `String(value)`. */\n\tserialize?: (value: unknown) => string;\n\t/** Event name for DATA tuples. Default: `\"data\"`. */\n\tdataEvent?: string;\n\t/** Event name for ERROR tuples. Default: `\"error\"`. */\n\terrorEvent?: string;\n\t/** Event name for COMPLETE tuples. Default: `\"complete\"`. */\n\tcompleteEvent?: string;\n\t/** Emit `event: resolved` when RESOLVED arrives. Default: `false`. */\n\tincludeResolved?: boolean;\n\t/** Emit `event: dirty` when DIRTY arrives. Default: `false`. */\n\tincludeDirty?: boolean;\n\t/** Add SSE comment keepalive frames (`: keepalive`) on an interval. Disabled when unset. */\n\tkeepAliveMs?: number;\n\t/** Optional abort signal to terminate the stream early. */\n\tsignal?: AbortSignal;\n\t/** Maps custom message types to SSE event names. */\n\teventNameResolver?: (type: symbol) => string;\n};\n\nfunction messageTypeLabel(t: symbol): string {\n\treturn Symbol.keyFor(t) ?? t.description ?? \"message\";\n}\n\nfunction serializeSseData(value: unknown, serialize: (value: unknown) => string): string {\n\tif (typeof value === \"string\") return value;\n\treturn serialize(value);\n}\n\nfunction sseFrame(event: string, data?: string): string {\n\tlet out = `event: ${event}\\n`;\n\tif (data !== undefined) {\n\t\tconst lines = data.split(/\\r?\\n/);\n\t\tfor (const line of lines) {\n\t\t\tout += `data: ${line}\\n`;\n\t\t}\n\t}\n\treturn `${out}\\n`;\n}\n\n/**\n * Creates a standard Server-Sent Events stream from node messages.\n *\n * @category extra\n */\nexport function toSSE<T>(source: Node<T>, opts?: ToSSEOptions): ReadableStream<Uint8Array> {\n\tconst {\n\t\tserialize = (value: unknown) => {\n\t\t\tif (value instanceof Error) return value.message;\n\t\t\ttry {\n\t\t\t\treturn JSON.stringify(value);\n\t\t\t} catch {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t},\n\t\tdataEvent = \"data\",\n\t\terrorEvent = \"error\",\n\t\tcompleteEvent = \"complete\",\n\t\tincludeResolved = false,\n\t\tincludeDirty = false,\n\t\tkeepAliveMs,\n\t\tsignal,\n\t\teventNameResolver = messageTypeLabel,\n\t} = opts ?? {};\n\tconst encoder = new TextEncoder();\n\tlet stop: (() => void) | undefined;\n\n\treturn new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tlet closed = false;\n\t\t\tlet keepAlive: ReturnType<typeof setInterval> | undefined;\n\t\t\tlet unsub: () => void = () => {};\n\t\t\tconst close = () => {\n\t\t\t\tif (closed) return;\n\t\t\t\tclosed = true;\n\t\t\t\tif (keepAlive !== undefined) clearInterval(keepAlive);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tunsub();\n\t\t\t\tcontroller.close();\n\t\t\t};\n\t\t\tstop = close;\n\t\t\tconst write = (event: string, data?: string) => {\n\t\t\t\tif (closed) return;\n\t\t\t\tcontroller.enqueue(encoder.encode(sseFrame(event, data)));\n\t\t\t};\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (closed) return;\n\t\t\t\tclose();\n\t\t\t};\n\t\t\tunsub = source.subscribe((msgs) => {\n\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\tconst t = msg[0];\n\t\t\t\t\t// Skip graph-local signals (tier < 3: START, DIRTY, INVALIDATE,\n\t\t\t\t\t// PAUSE, RESUME). DIRTY is opt-in for observability.\n\t\t\t\t\tif (defaultConfig.isLocalOnly(t)) {\n\t\t\t\t\t\tif (t === DIRTY && includeDirty) {\n\t\t\t\t\t\t\t/* fall through to write */\n\t\t\t\t\t\t} else continue;\n\t\t\t\t\t}\n\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\twrite(dataEvent, serializeSseData(msg[1], serialize));\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (t === ERROR) {\n\t\t\t\t\t\twrite(errorEvent, serializeSseData(msg[1], serialize));\n\t\t\t\t\t\tclose();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (t === COMPLETE) {\n\t\t\t\t\t\twrite(completeEvent);\n\t\t\t\t\t\tclose();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// RESOLVED (tier 3) is opt-in for observability.\n\t\t\t\t\tif (!includeResolved && t === RESOLVED) continue;\n\t\t\t\t\twrite(\n\t\t\t\t\t\teventNameResolver(t),\n\t\t\t\t\t\tmsg.length > 1 ? serializeSseData(msg[1], serialize) : undefined,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (keepAliveMs !== undefined && keepAliveMs > 0) {\n\t\t\t\tkeepAlive = setInterval(() => {\n\t\t\t\t\tif (closed) return;\n\t\t\t\t\tcontroller.enqueue(encoder.encode(\": keepalive\\n\\n\"));\n\t\t\t\t}, keepAliveMs);\n\t\t\t}\n\t\t\tif (signal?.aborted) onAbort();\n\t\t\telse signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t},\n\t\tcancel() {\n\t\t\tstop?.();\n\t\t},\n\t});\n}\n\n/**\n * Composable variant of {@link toSSE} — emits encoded SSE frames as\n * `Uint8Array` through a reactive `Node`. Use this when you want to pipe SSE\n * bytes through the reactive graph (persist to file, tee to multiple streams,\n * etc.). Wrap with {@link toReadableStream} to expose a `ReadableStream` for\n * `new Response(...)` use cases.\n *\n * @category extra\n */\nexport function toSSEBytes<T>(source: Node<T>, opts?: ToSSEOptions): Node<Uint8Array> {\n\tconst {\n\t\tserialize = (value: unknown) => {\n\t\t\tif (value instanceof Error) return value.message;\n\t\t\ttry {\n\t\t\t\treturn JSON.stringify(value);\n\t\t\t} catch {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t},\n\t\tdataEvent = \"data\",\n\t\terrorEvent = \"error\",\n\t\tcompleteEvent = \"complete\",\n\t\tincludeResolved = false,\n\t\tincludeDirty = false,\n\t\tkeepAliveMs,\n\t\tsignal,\n\t\teventNameResolver = messageTypeLabel,\n\t} = opts ?? {};\n\tconst encoder = new TextEncoder();\n\treturn node<Uint8Array>([], (_data, a) => {\n\t\tlet active = true;\n\t\tlet keepAlive: ReturnType<typeof setInterval> | undefined;\n\t\tconst emitFrame = (event: string, data?: string) => {\n\t\t\tif (!active) return;\n\t\t\ta.emit(encoder.encode(sseFrame(event, data)));\n\t\t};\n\t\tconst onAbort = () => {\n\t\t\tif (!active) return;\n\t\t\tactive = false;\n\t\t\ta.down([[COMPLETE]]);\n\t\t};\n\t\tconst unsub = source.subscribe((msgs) => {\n\t\t\tif (!active) return;\n\t\t\tfor (const msg of msgs) {\n\t\t\t\tconst t = msg[0];\n\t\t\t\tif (defaultConfig.isLocalOnly(t)) {\n\t\t\t\t\tif (t === DIRTY && includeDirty) {\n\t\t\t\t\t\t/* fall through */\n\t\t\t\t\t} else continue;\n\t\t\t\t}\n\t\t\t\tif (t === DATA) {\n\t\t\t\t\temitFrame(dataEvent, serializeSseData(msg[1], serialize));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (t === ERROR) {\n\t\t\t\t\temitFrame(errorEvent, serializeSseData(msg[1], serialize));\n\t\t\t\t\tactive = false;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (t === COMPLETE) {\n\t\t\t\t\temitFrame(completeEvent);\n\t\t\t\t\tactive = false;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!includeResolved && t === RESOLVED) continue;\n\t\t\t\temitFrame(\n\t\t\t\t\teventNameResolver(t),\n\t\t\t\t\tmsg.length > 1 ? serializeSseData(msg[1], serialize) : undefined,\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t\tif (keepAliveMs !== undefined && keepAliveMs > 0) {\n\t\t\tkeepAlive = setInterval(() => {\n\t\t\t\tif (!active) return;\n\t\t\t\ta.emit(encoder.encode(\": keepalive\\n\\n\"));\n\t\t\t}, keepAliveMs);\n\t\t}\n\t\tif (signal?.aborted) onAbort();\n\t\telse signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\treturn () => {\n\t\t\tactive = false;\n\t\t\tif (keepAlive !== undefined) clearInterval(keepAlive);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tunsub();\n\t\t};\n\t});\n}\n\n/**\n * Converts a `Node<Uint8Array>` into a WHATWG `ReadableStream<Uint8Array>`.\n * Useful for composing with `new Response(...)` / `fetch` bodies.\n *\n * @category extra\n */\nexport function toReadableStream(bytes: Node<Uint8Array>): ReadableStream<Uint8Array> {\n\tlet unsub: (() => void) | undefined;\n\tlet closed = false;\n\treturn new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tunsub = bytes.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tconst t = m[0];\n\t\t\t\t\tif (closed) return;\n\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcontroller.enqueue(m[1] as Uint8Array);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* controller closed mid-batch — upstream unsub will follow */\n\t\t\t\t\t\t\tclosed = true;\n\t\t\t\t\t\t\tunsub?.();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\tclosed = true;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcontroller.error(m[1]);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* controller already closed */\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (t === COMPLETE) {\n\t\t\t\t\t\tclosed = true;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* controller already closed */\n\t\t\t\t\t\t}\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},\n\t\tcancel() {\n\t\t\tclosed = true;\n\t\t\tunsub?.();\n\t\t},\n\t});\n}\n\n/** Parsed Server-Sent Event. */\nexport type SSEEvent<T = string> = {\n\tevent: string;\n\tdata: T;\n\tid?: string;\n\tretry?: number;\n};\n\n/** Options for {@link fromSSE}. */\nexport type FromSSEOptions<T = string> = ExtraOpts & {\n\t/** Parse the raw `data:` payload. Default: identity (string). */\n\tparse?: (raw: string) => T;\n};\n\n/** Options for {@link parseSSEStream}. */\nexport type ParseSSEStreamOptions<T = string> = {\n\t/** Parse the raw `data:` payload. Default: identity (string). */\n\tparse?: (raw: string) => T;\n\t/**\n\t * External abort signal. If aborted, the generator returns early after\n\t * cancelling the underlying reader / iterator. Does not emit an error —\n\t * the generator simply ends.\n\t */\n\tsignal?: AbortSignal;\n};\n\n/**\n * Parses a Server-Sent Events byte stream into an async-iterator of structured\n * `{event, data, id, retry}` records. Pure async generator with no reactive\n * dependency — safe to consume anywhere an `AsyncIterable<SSEEvent>` is\n * expected (LLM provider adapters, tests, non-reactive transports).\n *\n * Handles:\n * - Arbitrary chunk boundaries (internal text buffer + `TextDecoder` streaming).\n * - `\\n` and `\\r\\n` line endings.\n * - `event:` / `data:` (multi-line via repeated fields) / `id:` / `retry:`.\n * - Comments (`:` prefix).\n * - Cancels the underlying reader / iterator on external abort or consumer\n * break, so a quiet stream doesn't leak pending `read()` calls.\n *\n * Used internally by {@link fromSSE} (reactive `Node<SSEEvent>`) — exposed as a\n * pure helper so LLM provider adapters (Anthropic, OpenAI, Google) can parse\n * their SSE streams without building a reactive node per call.\n *\n * @param source - SSE byte source (`ReadableStream`, `Response`, or `AsyncIterable<Uint8Array>`).\n * @param opts - `{ parse?, signal? }`.\n * @returns `AsyncGenerator<SSEEvent<T>>` — yields one event per SSE block; returns on stream end / abort.\n *\n * @category extra\n */\nexport async function* parseSSEStream<T = string>(\n\tsource: ReadableStream<Uint8Array> | Response | AsyncIterable<Uint8Array>,\n\topts?: ParseSSEStreamOptions<T>,\n): AsyncGenerator<SSEEvent<T>, void, unknown> {\n\tconst parse = opts?.parse ?? ((raw: string) => raw as unknown as T);\n\tconst externalSignal = opts?.signal;\n\n\tconst decoder = new TextDecoder();\n\tlet buffer = \"\";\n\tlet currentEvent = \"message\";\n\tlet currentData: string[] = [];\n\tlet currentId: string | undefined;\n\tlet currentRetry: number | undefined;\n\tconst queue: SSEEvent<T>[] = [];\n\n\tconst flushEvent = () => {\n\t\tif (currentData.length === 0 && currentEvent === \"message\" && currentId === undefined) {\n\t\t\tcurrentData = [];\n\t\t\treturn;\n\t\t}\n\t\tconst raw = currentData.join(\"\\n\");\n\t\tqueue.push({\n\t\t\tevent: currentEvent,\n\t\t\tdata: parse(raw),\n\t\t\tid: currentId,\n\t\t\tretry: currentRetry,\n\t\t});\n\t\tcurrentEvent = \"message\";\n\t\tcurrentData = [];\n\t\tcurrentId = undefined;\n\t\tcurrentRetry = undefined;\n\t};\n\n\tconst processLine = (line: string) => {\n\t\tif (line === \"\") {\n\t\t\tflushEvent();\n\t\t\treturn;\n\t\t}\n\t\tif (line.startsWith(\":\")) return; // comment\n\t\tconst colon = line.indexOf(\":\");\n\t\tconst field = colon < 0 ? line : line.slice(0, colon);\n\t\tlet value = colon < 0 ? \"\" : line.slice(colon + 1);\n\t\tif (value.startsWith(\" \")) value = value.slice(1);\n\t\tswitch (field) {\n\t\t\tcase \"event\":\n\t\t\t\tcurrentEvent = value;\n\t\t\t\tbreak;\n\t\t\tcase \"data\":\n\t\t\t\tcurrentData.push(value);\n\t\t\t\tbreak;\n\t\t\tcase \"id\":\n\t\t\t\tif (!value.includes(\"\\0\")) currentId = value;\n\t\t\t\tbreak;\n\t\t\tcase \"retry\": {\n\t\t\t\tconst n = Number(value);\n\t\t\t\tif (Number.isFinite(n)) currentRetry = n;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t};\n\n\tconst processChunk = (chunk: Uint8Array, done: boolean) => {\n\t\tbuffer += decoder.decode(chunk, { stream: !done });\n\t\tconst parts = buffer.split(/\\r?\\n/);\n\t\tbuffer = parts.pop() ?? \"\";\n\t\tfor (const line of parts) processLine(line);\n\t};\n\n\t// Resolve the underlying byte source into either a `ReadableStream` or an\n\t// `AsyncIterator<Uint8Array>` — identical dispatch as the legacy fromSSE.\n\tconst resp = source as Response;\n\tconst stream =\n\t\tsource instanceof ReadableStream\n\t\t\t? source\n\t\t\t: resp && typeof resp === \"object\" && resp.body instanceof ReadableStream\n\t\t\t\t? resp.body\n\t\t\t\t: null;\n\n\tlet reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n\tlet iter: AsyncIterator<Uint8Array> | undefined;\n\t// `cleanupDone` flips once we've invoked `reader.cancel()` / `iter.return()`\n\t// — guards against the `onAbort` listener + the `finally` path both\n\t// cancelling the same underlying resource (WHATWG streams allow double-\n\t// cancel but custom `AsyncIterator.return` implementations are not\n\t// required to be idempotent).\n\tlet cleanupDone = false;\n\tconst cleanupReader = (): void => {\n\t\tif (cleanupDone) return;\n\t\tcleanupDone = true;\n\t\tif (reader) {\n\t\t\tvoid reader.cancel().catch(() => undefined);\n\t\t}\n\t\tif (iter && typeof iter.return === \"function\") {\n\t\t\tvoid Promise.resolve(iter.return()).catch(() => undefined);\n\t\t}\n\t};\n\n\t// Wire the external abort signal to cancel the reader / iterator promptly\n\t// instead of waiting for the next chunk.\n\tconst onAbort = (): void => {\n\t\tcleanupReader();\n\t};\n\tif (externalSignal) {\n\t\tif (externalSignal.aborted) return;\n\t\texternalSignal.addEventListener(\"abort\", onAbort, { once: true });\n\t}\n\n\ttry {\n\t\tif (stream) {\n\t\t\treader = stream.getReader();\n\t\t\twhile (!externalSignal?.aborted) {\n\t\t\t\tconst { value, done } = await reader.read();\n\t\t\t\tif (done) break;\n\t\t\t\tprocessChunk(value, false);\n\t\t\t\twhile (queue.length > 0) {\n\t\t\t\t\tconst ev = queue.shift() as SSEEvent<T>;\n\t\t\t\t\tyield ev;\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessChunk(new Uint8Array(), true);\n\t\t} else {\n\t\t\tconst asyncIter = source as AsyncIterable<Uint8Array>;\n\t\t\titer = asyncIter[Symbol.asyncIterator]();\n\t\t\twhile (!externalSignal?.aborted) {\n\t\t\t\tconst step = await iter.next();\n\t\t\t\tif (step.done) break;\n\t\t\t\tprocessChunk(step.value, false);\n\t\t\t\twhile (queue.length > 0) {\n\t\t\t\t\tconst ev = queue.shift() as SSEEvent<T>;\n\t\t\t\t\tyield ev;\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessChunk(new Uint8Array(), true);\n\t\t}\n\t\tif (buffer.trim()) {\n\t\t\tfor (const line of buffer.split(/\\r?\\n/)) processLine(line);\n\t\t\tflushEvent();\n\t\t}\n\t\twhile (queue.length > 0) {\n\t\t\tconst ev = queue.shift() as SSEEvent<T>;\n\t\t\tyield ev;\n\t\t}\n\t} finally {\n\t\tif (externalSignal) {\n\t\t\texternalSignal.removeEventListener(\"abort\", onAbort);\n\t\t}\n\t\t// Idempotent cleanup — if `onAbort` already ran the cancel, this is a\n\t\t// no-op. Covers the normal consumer-break path (generator exits → finally\n\t\t// runs → cancel underlying reader / iterator so a quiet upstream\n\t\t// doesn't leak its `read()` call).\n\t\tcleanupReader();\n\t}\n}\n\n/**\n * Parses a Server-Sent Events stream into structured `{event, data, id}` records.\n *\n * @param source - SSE byte source (`ReadableStream`, `Response`, or `AsyncIterable<Uint8Array>`).\n * @param opts - Parse function and node options.\n * @returns `Node<SSEEvent<T>>` — one `DATA` per SSE event; `COMPLETE` on stream end.\n *\n * @category extra\n */\nexport function fromSSE<T = string>(\n\tsource: ReadableStream<Uint8Array> | Response | AsyncIterable<Uint8Array>,\n\topts?: FromSSEOptions<T>,\n): Node<SSEEvent<T>> {\n\tconst { parse, ...rest } = opts ?? {};\n\treturn node<SSEEvent<T>>(\n\t\t[],\n\t\t(_data, a) => {\n\t\t\tlet active = true;\n\t\t\tconst ctrl = new AbortController();\n\t\t\tconst run = async () => {\n\t\t\t\ttry {\n\t\t\t\t\tfor await (const ev of parseSSEStream<T>(source, { parse, signal: ctrl.signal })) {\n\t\t\t\t\t\tif (!active) return;\n\t\t\t\t\t\ta.emit(ev);\n\t\t\t\t\t}\n\t\t\t\t\tif (active) a.down([[COMPLETE]]);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (active) a.down([[ERROR, err]]);\n\t\t\t\t}\n\t\t\t};\n\t\t\tvoid run();\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t\tctrl.abort();\n\t\t\t};\n\t\t},\n\t\tsourceOpts(rest),\n\t);\n}\n","/**\n * DryRunAdapter — zero-cost mock provider.\n *\n * Returns a deterministic fake response (plus a configurable hook for\n * customization). Useful for: pipeline smoke tests, CI without API keys,\n * local development, and as the leaf of a `cascadingLlmAdapter` when every\n * real tier fails.\n *\n * The library ships a minimal implementation only — richer scenario-\n * scripted mocks (per-stage responses, call recording) belong at the test\n * harness layer, not in the shipped library.\n *\n * Uses `ResettableTimer` for simulated latency (spec §5.10 escape hatch\n * documented on the class), and throws an `AbortError`-named Error on\n * abort so retry/timeout middleware can classify it.\n */\n\nimport { ResettableTimer } from \"@graphrefly/pure-ts/core\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n} from \"../core/types.js\";\n\nexport interface DryRunAdapterOptions {\n\tprovider?: string;\n\tmodel?: string;\n\t/** Generate the fake response. Defaults to echoing the last user message. */\n\trespond?: (messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => string;\n\t/**\n\t * Generate a fake usage object. Defaults to a simple character-count\n\t * heuristic (`input = sum(messages) / 4`, `output = content / 4`).\n\t */\n\tusage?: (messages: readonly ChatMessage[], content: string) => TokenUsage;\n\t/** Simulated latency in milliseconds (applied to both invoke and stream). */\n\tlatencyMs?: number;\n\t/** Stream chunk size in characters. Default 16. */\n\tstreamChunkSize?: number;\n}\n\nfunction makeAbortError(): Error {\n\tconst err = new Error(\"aborted\") as Error & { name: string };\n\terr.name = \"AbortError\";\n\treturn err;\n}\n\n/**\n * Abort-aware sleep using `ResettableTimer`. Spec §5.10 escape hatch.\n * No-op if `ms <= 0`; rejects with `AbortError` if the signal aborts.\n */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\tif (ms <= 0) return Promise.resolve();\n\tif (signal?.aborted) return Promise.reject(makeAbortError());\n\treturn new Promise((resolve, reject) => {\n\t\tconst timer = new ResettableTimer();\n\t\tlet onAbort: (() => void) | undefined;\n\t\tconst cleanup = (): void => {\n\t\t\ttimer.cancel();\n\t\t\tif (signal && onAbort) signal.removeEventListener(\"abort\", onAbort);\n\t\t};\n\t\ttimer.start(ms, () => {\n\t\t\tcleanup();\n\t\t\tresolve();\n\t\t});\n\t\tif (signal) {\n\t\t\tonAbort = (): void => {\n\t\t\t\tcleanup();\n\t\t\t\treject(makeAbortError());\n\t\t\t};\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t});\n}\n\n/**\n * Create a DryRun adapter.\n *\n * @example\n * ```ts\n * const adapter = dryRunAdapter({ respond: (msgs) => \"hello from dry-run\" });\n * const resp = await Promise.resolve(adapter.invoke([{ role: \"user\", content: \"hi\" }]));\n * ```\n */\nexport function dryRunAdapter(opts: DryRunAdapterOptions = {}): LLMAdapter {\n\tconst provider = opts.provider ?? \"dry-run\";\n\tconst model = opts.model ?? \"dry-run-v1\";\n\tconst latencyMs = opts.latencyMs ?? 0;\n\tconst streamChunkSize = Math.max(1, opts.streamChunkSize ?? 16);\n\n\tconst respondFn =\n\t\topts.respond ??\n\t\t((msgs: readonly ChatMessage[]): string => {\n\t\t\tconst lastUser = [...msgs].reverse().find((m) => m.role === \"user\");\n\t\t\treturn lastUser ? `echo: ${lastUser.content}` : \"dry-run: no user message\";\n\t\t});\n\n\tconst usageFn =\n\t\topts.usage ??\n\t\t((msgs: readonly ChatMessage[], content: string): TokenUsage => {\n\t\t\tconst totalInput = msgs.reduce((s, m) => s + m.content.length, 0);\n\t\t\treturn {\n\t\t\t\tinput: { regular: Math.ceil(totalInput / 4) },\n\t\t\t\toutput: { regular: Math.ceil(content.length / 4) },\n\t\t\t};\n\t\t});\n\n\treturn {\n\t\tprovider,\n\t\tmodel,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tawait sleep(latencyMs, invokeOpts?.signal);\n\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\tconst content = respondFn(messages, invokeOpts);\n\t\t\tconst usage = usageFn(messages, content);\n\t\t\treturn {\n\t\t\t\tcontent,\n\t\t\t\tusage,\n\t\t\t\tfinishReason: \"stop\",\n\t\t\t\tmodel: invokeOpts?.model ?? model,\n\t\t\t\tprovider,\n\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\tmetadata: { dryRun: true },\n\t\t\t};\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst content = respondFn(messages, invokeOpts);\n\t\t\tconst usage = usageFn(messages, content);\n\t\t\tconst chunkCount = Math.ceil(content.length / streamChunkSize) || 1;\n\t\t\tconst perChunkMs = latencyMs > 0 ? latencyMs / chunkCount : 0;\n\t\t\tfor (let i = 0; i < content.length; i += streamChunkSize) {\n\t\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\t\tawait sleep(perChunkMs, invokeOpts?.signal);\n\t\t\t\tyield { type: \"token\", delta: content.slice(i, i + streamChunkSize) };\n\t\t\t}\n\t\t\tyield { type: \"usage\", usage };\n\t\t\tyield { type: \"finish\", reason: \"stop\" };\n\t\t},\n\t};\n}\n","/**\n * `fallbackAdapter` — fixture-backed {@link LLMAdapter} for offline demos,\n * deterministic tests, and graceful degradation in production.\n *\n * A peer of `anthropicAdapter` / `openAICompatAdapter` / `googleAdapter` /\n * `ollamaAdapter` / `dryRunAdapter`, but whose role is to serve pre-recorded\n * or canned responses when real providers aren't reachable. Install it as a\n * tier via the existing routing primitives (no new composer needed):\n *\n * ```ts\n * // Graceful offline fallback for a user app:\n * resilientAdapter(anthropicAdapter({ ... }), {\n * fallback: fallbackAdapter({ fixturesDir: \"./fixtures\" }),\n * });\n *\n * // Or the general N-tier shape:\n * cascadingLlmAdapter([\n * { name: \"primary\", adapter: anthropicAdapter({ ... }) },\n * { name: \"fallback\", adapter: fallbackAdapter({ fixturesDir: \"./fixtures\" }) },\n * ]);\n * ```\n *\n * The `provider` field is `\"fallback\"` so its role is self-documenting in\n * logs, stats, cost tables, and audit trails.\n *\n * ## Three fixture sources (mutually exclusive)\n *\n * Pick exactly one of:\n *\n * 1. **`fixtures: FallbackFixture[]`** — inline, hand-authored. Supports\n * both hash-keyed and messages-keyed shapes; the adapter computes the\n * canonical hash for messages-keyed entries at init time. Ideal when you\n * want full control in code (tests, small demos).\n *\n * 2. **`fixturesStorage: KvStorageTier`** — the escape hatch for any backend.\n * Pass a `memoryKv()`, `indexedDbKv(...)`, `sqliteKv(...)`,\n * `cascadingCache(...)`, or a custom tier. You own the layout — no\n * auto-namespacing.\n *\n * **Filesystem directories (Node only):** the core `fallbackAdapter`\n * does NOT import `node:fs` / `node:path` — it's safe to bundle for\n * browsers. For a directory convenience, import `fallbackAdapter` from\n * `@graphrefly/graphrefly/patterns/ai/node` (node subpath);\n * that variant adds `fixturesDir: string` (auto-namespaced to\n * `join(dir, keyPrefix)`, cache-format validated at init).\n *\n * ## Record mode\n *\n * `record: { adapter: real, storage }` proxies every call to `real` AND\n * persists the response through the provided tier. Use the node subpath's\n * `fallbackAdapter` for `record.dir` (auto-namespaced + `record.dir` defaults\n * to `fixturesDir` when both are file-backed).\n *\n * ## Three use cases, one implementation\n *\n * | Use case | Config |\n * |---|---|\n * | **User apps** — degrade when the cloud provider errors or network is down | `fallbackAdapter({ fixturesStorage: ... })` installed as a fallback tier |\n * | **Tests** — deterministic replays, fail loudly on miss | `fallbackAdapter({ fixturesStorage: ..., onMiss: \"throw\" })` |\n * | **Eval offline replay** — zero-spend repeat runs | `fallbackAdapter({ fixturesStorage: ... })` as the only adapter |\n *\n * ## Implementation\n *\n * Thin sugar over {@link withReplayCache}. Key shape comes from its\n * `canonicalJson` — fixtures written by either tool are interchangeable.\n *\n * @module\n */\n\nimport { sha256Hex, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { canonicalJson, type KvStorageTier, memoryKv } from \"@graphrefly/pure-ts/extra\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n} from \"../core/types.js\";\nimport {\n\ttype ReplayCacheKeyContext,\n\tReplayCacheMissError,\n\twithReplayCache,\n} from \"../middleware/replay-cache.js\";\nimport { dryRunAdapter } from \"./dry-run.js\";\n\nexport type FallbackMissPolicy = \"throw\" | \"respond\";\n\n/**\n * Thrown when `fallbackAdapter({ onMiss: \"throw\" })` receives a request that\n * has no matching fixture. Alias of `ReplayCacheMissError` for now — the\n * adapter is a thin sugar over `withReplayCache` and shares its miss-error.\n */\nexport const FallbackMissError = ReplayCacheMissError;\nexport type FallbackMissError = ReplayCacheMissError;\n\n/**\n * One recorded fixture. Two authoring shapes:\n * - **Hash-keyed** — `{ key, response, stream? }`. Key is `sha256(canonicalJson({messages, opts}))`\n * with `fallback:` prefix. This is what `record` mode writes.\n * - **Messages-keyed** — `{ messages, invokeOpts?, response }`. The adapter\n * computes the key at init time. Ergonomic for hand-authored fixtures.\n */\nexport type FallbackFixture =\n\t| {\n\t\t\treadonly key: string;\n\t\t\treadonly response: LLMResponse;\n\t\t\treadonly stream?: {\n\t\t\t\treadonly chunks: readonly StreamDelta[];\n\t\t\t\treadonly delaysMs?: readonly number[];\n\t\t\t};\n\t }\n\t| {\n\t\t\treadonly messages: readonly ChatMessage[];\n\t\t\treadonly invokeOpts?: Omit<LLMInvokeOptions, \"signal\">;\n\t\t\treadonly response: LLMResponse;\n\t };\n\nexport interface FallbackAdapterOptions {\n\t/** Adapter provider label. Default `\"fallback\"`. */\n\treadonly provider?: string;\n\t/** Adapter model label. Default `\"fallback\"`. */\n\treadonly model?: string;\n\t/**\n\t * Inline hand-authored fixtures. Supports both hash-keyed (`{key, response, stream?}`)\n\t * and messages-keyed (`{messages, invokeOpts?, response}`) shapes — the adapter\n\t * computes the canonical hash for messages-keyed entries at init time. Held in\n\t * an internal `memoryKv`. Mutually exclusive with `fixturesDir` and\n\t * `fixturesStorage`.\n\t */\n\treadonly fixtures?: readonly FallbackFixture[];\n\t/**\n\t * Bring-your-own `KvStorageTier` (`memoryKv`, `sqliteKv`,\n\t * `indexedDbKv`, `cascadingCache`, or a custom tier). You own the\n\t * layout — no auto-namespacing. Mutually exclusive with `fixtures`.\n\t *\n\t * For filesystem directories, use the node subpath's `fallbackAdapter`\n\t * with its `fixturesDir` option (auto-namespaced + validated).\n\t */\n\treadonly fixturesStorage?: KvStorageTier;\n\t/**\n\t * Called on fixture miss when `onMiss === \"respond\"`. If not provided and\n\t * `onMiss === \"respond\"`, a canned \"service unavailable\" response is\n\t * returned (marked with `metadata.degraded: true`).\n\t */\n\treadonly respond?: (\n\t\tmessages: readonly ChatMessage[],\n\t\topts?: LLMInvokeOptions,\n\t) => string | LLMResponse;\n\t/** Miss policy. Default `\"respond\"`. */\n\treadonly onMiss?: FallbackMissPolicy;\n\t/**\n\t * Record mode. Proxies every call to `record.adapter` AND persists the\n\t * result through `record.storage`. For filesystem `record.dir` convenience,\n\t * use the node subpath's `fallbackAdapter`.\n\t */\n\treadonly record?: {\n\t\treadonly adapter: LLMAdapter;\n\t\treadonly storage?: KvStorageTier;\n\t};\n\t/** Stream replay speed multiplier. See {@link withReplayCache}. Default `1`. */\n\treadonly replaySpeed?: number;\n\t/** Key prefix. Kept compatible with `withReplayCache` defaults. Default `\"fallback\"`. */\n\treadonly keyPrefix?: string;\n\t/**\n\t * Custom key function — forwarded directly to the underlying\n\t * {@link withReplayCache}. Use to shard fixtures by `invokeOpts.keyContext`\n\t * (tenant, session, feature flag). Accepts either the new\n\t * {@link ReplayCacheKeyContext} object form or the legacy 2-arg\n\t * `(messages, opts?)` form.\n\t */\n\treadonly keyFn?:\n\t\t| ((ctx: ReplayCacheKeyContext) => string)\n\t\t| ((messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => string);\n}\n\n// ---------------------------------------------------------------------------\n// Canned degraded response\n// ---------------------------------------------------------------------------\n\nfunction degradedResponse(provider: string, model: string): LLMResponse {\n\treturn {\n\t\tcontent: \"[fallback: no cached response available for this request]\",\n\t\tusage: { input: { regular: 0 }, output: { regular: 0 } },\n\t\tfinishReason: \"stop\",\n\t\tmodel,\n\t\tprovider,\n\t\tmetadata: { degraded: true, reason: \"no-fixture\" },\n\t};\n}\n\nfunction normalizeRespondResult(\n\traw: string | LLMResponse,\n\tprovider: string,\n\tmodel: string,\n): LLMResponse {\n\tif (typeof raw === \"string\") {\n\t\treturn {\n\t\t\tcontent: raw,\n\t\t\tusage: { input: { regular: 0 }, output: { regular: 0 } },\n\t\t\tfinishReason: \"stop\",\n\t\t\tmodel,\n\t\t\tprovider,\n\t\t\tmetadata: { degraded: true, reason: \"respond\" },\n\t\t};\n\t}\n\treturn raw;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture → storage tier conversion\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the key a `FallbackFixture` would hash to. Messages-keyed fixtures\n * get their key derived on the spot; hash-keyed fixtures pass through. Async\n * because `sha256Hex` uses `globalThis.crypto.subtle` (universal, no\n * `node:crypto` leak) — see {@link sha256Hex}.\n */\nasync function fixtureKey(fixture: FallbackFixture, keyPrefix: string): Promise<string> {\n\tif (\"key\" in fixture) return fixture.key;\n\tconst canonical = canonicalJson({ messages: fixture.messages, opts: fixture.invokeOpts ?? {} });\n\tconst hex = await sha256Hex(canonical);\n\treturn `${keyPrefix}:${hex}`;\n}\n\n/**\n * `withReplayCache` stores values as `CachedEntry = { response, storedAtNs, streamChunks?, streamCadenceMs? }`.\n * Convert a `FallbackFixture` into that shape so inline fixtures can be\n * seeded into a memory tier alongside file-authored ones.\n */\nfunction toCachedEntry(fixture: FallbackFixture): unknown {\n\tconst base: { response: LLMResponse; storedAtNs: number } = {\n\t\tresponse: fixture.response,\n\t\t// Real timestamp so future TTL-aware tiers don't treat inline fixtures\n\t\t// as Epoch-old and evict them on first pass. Matches the wall-clock\n\t\t// write `withReplayCache` uses for disk-written entries.\n\t\tstoredAtNs: wallClockNs(),\n\t};\n\tif (\"key\" in fixture && fixture.stream) {\n\t\tconst tokenChunks = fixture.stream.chunks.filter(\n\t\t\t(c): c is Extract<StreamDelta, { type: \"token\" }> => c.type === \"token\",\n\t\t);\n\t\treturn {\n\t\t\t...base,\n\t\t\tstreamChunks: tokenChunks.map((c) => ({ delta: c.delta })),\n\t\t\tstreamCadenceMs: fixture.stream.delaysMs ?? tokenChunks.map(() => 0),\n\t\t};\n\t}\n\treturn base;\n}\n\n/**\n * Resolve the fixture source to a `KvStorageTier`. Enforces mutual exclusion\n * between `fixtures` and `fixturesStorage`. When `fixtures` is provided, the\n * seeded memory tier is returned synchronously but keys are populated\n * asynchronously via the returned seeding promise (await before first use).\n */\nfunction resolveFixtureStorage(\n\topts: FallbackAdapterOptions,\n\tkeyPrefix: string,\n): { tier: KvStorageTier | undefined; seedReady: Promise<void> } {\n\tconst sources: string[] = [];\n\tif (opts.fixtures != null) sources.push(\"fixtures\");\n\tif (opts.fixturesStorage != null) sources.push(\"fixturesStorage\");\n\tif (sources.length > 1) {\n\t\tthrow new TypeError(\n\t\t\t`fallbackAdapter: \\`fixtures\\` and \\`fixturesStorage\\` are mutually ` +\n\t\t\t\t`exclusive; got both ${sources.join(\" and \")}. Pick one source. ` +\n\t\t\t\t`For filesystem directories use the node subpath's \\`fallbackAdapter\\`.`,\n\t\t);\n\t}\n\tif (opts.fixtures) {\n\t\tconst tier = memoryKv();\n\t\tconst fixtures = opts.fixtures;\n\t\tconst seedReady = (async () => {\n\t\t\tfor (const fixture of fixtures) {\n\t\t\t\tconst key = await fixtureKey(fixture, keyPrefix);\n\t\t\t\tawait tier.save(key, toCachedEntry(fixture));\n\t\t\t}\n\t\t})();\n\t\t// Attach a no-op catch so a failure inside the IIFE (e.g. `sha256Hex`\n\t\t// throws because `globalThis.crypto.subtle` is unavailable) does NOT\n\t\t// become an unhandled rejection when the adapter is constructed but\n\t\t// never invoked. V8 records the handler attachment via this branch\n\t\t// of the promise graph, so the Node `unhandledRejection` hook stays\n\t\t// silent — yet subsequent `await seedReady` inside `invoke`/`stream`\n\t\t// still throws the original error for the caller to see.\n\t\tseedReady.catch(() => {});\n\t\treturn { tier, seedReady };\n\t}\n\tif (opts.fixturesStorage) return { tier: opts.fixturesStorage, seedReady: Promise.resolve() };\n\treturn { tier: undefined, seedReady: Promise.resolve() };\n}\n\n// ---------------------------------------------------------------------------\n// fallbackAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * Build a fixture-backed {@link LLMAdapter}. See module docs for use cases\n * (offline demo, tests, degraded-mode) and recipe snippets.\n */\nexport function fallbackAdapter(opts: FallbackAdapterOptions = {}): LLMAdapter {\n\tconst provider = opts.provider ?? \"fallback\";\n\tconst model = opts.model ?? \"fallback\";\n\tconst onMiss: FallbackMissPolicy = opts.onMiss ?? \"respond\";\n\tconst keyPrefix = opts.keyPrefix ?? \"fallback\";\n\n\t// Pick the inner leaf adapter based on mode.\n\tconst leaf: LLMAdapter = (() => {\n\t\tif (opts.record) return opts.record.adapter;\n\t\tif (onMiss === \"throw\") {\n\t\t\t// `withReplayCache({ mode: \"read-strict\" })` throws on miss before\n\t\t\t// ever calling the inner. Supply a no-op to satisfy the type.\n\t\t\treturn dryRunAdapter({\n\t\t\t\tprovider,\n\t\t\t\tmodel,\n\t\t\t\trespond: () => \"[unreachable: read-strict mode throws on miss]\",\n\t\t\t});\n\t\t}\n\t\t// Custom leaf (not `dryRunAdapter`) so `metadata.degraded` is preserved\n\t\t// — `dryRunAdapter` returns a string and constructs its own response,\n\t\t// discarding our metadata. For the respond-on-miss path we want full\n\t\t// `LLMResponse` control.\n\t\treturn {\n\t\t\tprovider,\n\t\t\tmodel,\n\t\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\t\tconst raw = opts.respond\n\t\t\t\t\t? opts.respond(messages, invokeOpts)\n\t\t\t\t\t: degradedResponse(provider, model);\n\t\t\t\treturn normalizeRespondResult(raw, provider, model);\n\t\t\t},\n\t\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\t\tconst raw = opts.respond\n\t\t\t\t\t? opts.respond(messages, invokeOpts)\n\t\t\t\t\t: degradedResponse(provider, model);\n\t\t\t\tconst r = normalizeRespondResult(raw, provider, model);\n\t\t\t\tyield { type: \"token\", delta: r.content };\n\t\t\t\tif (r.usage) yield { type: \"usage\", usage: r.usage };\n\t\t\t\tyield { type: \"finish\", reason: r.finishReason ?? \"stop\" };\n\t\t\t},\n\t\t} satisfies LLMAdapter;\n\t})();\n\n\t// Resolve the storage tier.\n\t// - `record` mode: require `record.storage`.\n\t// - Replay-only: `fixtures` seeds an in-memory tier (async) OR\n\t// `fixturesStorage` passes through.\n\tlet storage: KvStorageTier;\n\tlet seedReady: Promise<void> = Promise.resolve();\n\tif (opts.record) {\n\t\tif (!opts.record.storage) {\n\t\t\tthrow new TypeError(\n\t\t\t\t\"fallbackAdapter: `record.storage` is required in record mode. For filesystem \" +\n\t\t\t\t\t\"`record.dir` convenience, use the node subpath's `fallbackAdapter`.\",\n\t\t\t);\n\t\t}\n\t\tstorage = opts.record.storage;\n\t} else {\n\t\tconst resolved = resolveFixtureStorage(opts, keyPrefix);\n\t\tstorage = resolved.tier ?? memoryKv();\n\t\tseedReady = resolved.seedReady;\n\t}\n\n\tconst mode = opts.record ? \"read-write\" : onMiss === \"throw\" ? \"read-strict\" : \"read\";\n\n\tconst cached = withReplayCache(leaf, {\n\t\tstorage,\n\t\tmode,\n\t\tkeyPrefix,\n\t\tcacheStreaming: true,\n\t\tcaptureStreamCadence: true,\n\t\treplaySpeed: opts.replaySpeed,\n\t\t...(opts.keyFn ? { keyFn: opts.keyFn } : {}),\n\t});\n\n\t// Wrap invoke/stream so the first call awaits the seed-complete Promise.\n\t// Adapter construction stays synchronous (`fallbackAdapter(...)` returns\n\t// immediately); inline fixture hashing happens lazily on first use.\n\treturn {\n\t\tprovider,\n\t\tmodel,\n\t\tcapabilities: cached.capabilities?.bind(cached),\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tawait seedReady;\n\t\t\t// `cached` came from `withReplayCache`, whose `invoke` always returns\n\t\t\t// `Promise<LLMResponse>`. The `LLMAdapter` interface types it as the\n\t\t\t// broader `NodeInput<LLMResponse>` union; narrow here to the actual\n\t\t\t// shape so the wrapper surface stays `Promise<LLMResponse>`.\n\t\t\treturn cached.invoke(messages, invokeOpts) as Promise<LLMResponse>;\n\t\t},\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tawait seedReady;\n\t\t\tfor await (const delta of cached.stream(messages, invokeOpts)) yield delta;\n\t\t},\n\t};\n}\n","/**\n * `withReplayCache` — content-addressed response cache over `KvStorageTier`.\n *\n * - Key: sha256 of canonicalized (messages + invoke options minus `signal`).\n * - `\"read-write\"` (default): returns cached response if present; on miss,\n * passes through and stores the result.\n * - `\"write-only\"`: never reads; populates the cache for later runs.\n * - `\"read\"`: reads only; on miss, passes through without writing.\n * - `\"read-strict\"`: reads only; on miss, **throws `ReplayCacheMissError`**\n * instead of passing through. Use for fixture-driven tests or offline\n * fallback adapters where any cache miss is a test failure or a signal to\n * degrade.\n *\n * Reuses the library's existing `KvStorageTier` abstraction — any kv tier\n * (memoryKv / fileKv / sqliteKv / indexedDbKv / custom).\n *\n * **Concurrent cache-miss dedup:** uses `singleFromAny` so two concurrent\n * calls with the same key share one upstream request. Second caller sees the\n * same response that the first caller fetched; no duplicate provider spend.\n *\n * **Circular-ref safe:** `canonicalJson` uses a seen-set replacer so\n * user-supplied `ToolDefinition.parameters` with `$ref` cycles don't stack-\n * overflow the key computation.\n *\n * **Stream cadence capture:** when `cacheStreaming: true` AND\n * `captureStreamCadence: true`, per-chunk delays (ms since previous chunk)\n * are recorded alongside the content. Replay honors the recorded cadence\n * unless `replaySpeed` is set, which multiplies the effective per-chunk\n * delay (`replaySpeed: 2` → 2× faster; `replaySpeed: 0` → instant).\n * Without `captureStreamCadence`, replay is instant regardless.\n */\n\nimport { monotonicNs, ResettableTimer, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport type { KvStorageTier } from \"@graphrefly/pure-ts/extra\";\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { singleFromAny } from \"../../../../base/composition/single-from-any.js\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport { contentAddressedCache } from \"../_internal/content-addressed-cache.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n} from \"../core/types.js\";\n\nexport type ReplayCacheMode = \"read\" | \"read-strict\" | \"write-only\" | \"read-write\";\n\nexport class ReplayCacheMissError extends Error {\n\toverride name = \"ReplayCacheMissError\";\n\tconstructor(\n\t\tpublic readonly key: string,\n\t\tpublic readonly method: \"invoke\" | \"stream\",\n\t) {\n\t\tsuper(`withReplayCache: no cached response for ${method} (key=${key}, mode=read-strict)`);\n\t}\n}\n\n/**\n * Context object passed to {@link WithReplayCacheOptions.keyFn}. Extending\n * with additional fields is forward-compatible — current implementations\n * ignoring unknown fields continue to work.\n */\nexport interface ReplayCacheKeyContext {\n\treadonly messages: readonly ChatMessage[];\n\treadonly opts: LLMInvokeOptions | undefined;\n\t/** Shortcut to `opts?.keyContext` — avoids an extra guard in callers. */\n\treadonly context: unknown;\n}\n\nexport interface WithReplayCacheOptions {\n\tstorage: KvStorageTier;\n\tmode?: ReplayCacheMode;\n\t/**\n\t * Custom key function. Receives a {@link ReplayCacheKeyContext} with the\n\t * chat messages, the invoke options, and the caller-supplied\n\t * `opts.keyContext`. Defaults to sha256 of canonical JSON over\n\t * `(messages, opts without signal/keyContext)`.\n\t *\n\t * Legacy 2-arg form `(messages, opts?)` also accepted — the adapter\n\t * detects arity and dispatches. Prefer the object form for new code.\n\t */\n\tkeyFn?:\n\t\t| ((ctx: ReplayCacheKeyContext) => string | Promise<string>)\n\t\t| ((messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => string | Promise<string>);\n\t/** Prefix for cached keys (useful when sharing a tier across domains). */\n\tkeyPrefix?: string;\n\t/**\n\t * Whether to cache streaming responses (by consuming the full stream\n\t * and replaying it as one synthetic token chunk). Default `false`.\n\t */\n\tcacheStreaming?: boolean;\n\t/**\n\t * When `cacheStreaming: true`, also record per-chunk delays (ms since\n\t * previous chunk) so replay can honor the original streaming cadence.\n\t * Default `false` (chunks replay instantly).\n\t */\n\tcaptureStreamCadence?: boolean;\n\t/**\n\t * Stream replay speed multiplier. `1` = original cadence (requires\n\t * `captureStreamCadence`). `2` = 2× faster. `0` = instant. Default `1`.\n\t */\n\treplaySpeed?: number;\n}\n\ninterface CachedEntry {\n\tresponse: LLMResponse;\n\tstoredAtNs: number;\n\t/**\n\t * Per-chunk deltas in milliseconds — populated only when `captureStreamCadence`\n\t * is `true` during the write. Replayed via `ResettableTimer` in stream().\n\t */\n\tstreamCadenceMs?: readonly number[];\n\t/**\n\t * Per-chunk bodies in order (tokens only — `usage`/`finish` are reconstructed\n\t * from `response.usage` / `response.finishReason`). Populated only when\n\t * `captureStreamCadence` is `true`, used for cadence-faithful replay.\n\t */\n\tstreamChunks?: ReadonlyArray<{ delta: string }>;\n}\n\ntype ResolveArgs = {\n\tmessages: readonly ChatMessage[];\n\tinvokeOpts: LLMInvokeOptions | undefined;\n};\ntype ResolveArgsWithKey = ResolveArgs & { _precomputedKey: string };\n\n/** Wrap an adapter with a replay cache. */\nexport function withReplayCache(inner: LLMAdapter, opts: WithReplayCacheOptions): LLMAdapter {\n\tconst mode = opts.mode ?? \"read-write\";\n\tconst cacheStreaming = opts.cacheStreaming ?? false;\n\tconst captureStreamCadence = opts.captureStreamCadence ?? false;\n\tconst replaySpeed = opts.replaySpeed ?? 1;\n\tconst keyPrefix = opts.keyPrefix ?? \"llm-replay\";\n\tconst isReadOnly = mode === \"read\" || mode === \"read-strict\";\n\n\t// Content-addressed substrate — keys via canonicalJson + sha256 over\n\t// (messages, opts minus signal/keyContext) or the caller's custom keyFn.\n\t// Value type is `CachedEntry` so we can persist stream cadence alongside\n\t// the response. Uses the shared substrate in `src/extra/content-addressed-\n\t// storage.ts` via the LLM-specific wrapper in `_internal/`.\n\t//\n\t// Mode translation: `ReplayCacheMode` uses `\"write-only\"` (legacy name);\n\t// the substrate uses `\"write\"`. All other modes map 1:1.\n\tconst cache = contentAddressedCache<CachedEntry>({\n\t\tstorage: opts.storage,\n\t\tmode: mode === \"write-only\" ? \"write\" : mode,\n\t\tkeyFn: opts.keyFn,\n\t\tkeyPrefix,\n\t});\n\n\tconst sleepMs = (ms: number): Promise<void> =>\n\t\tms <= 0\n\t\t\t? Promise.resolve()\n\t\t\t: new Promise<void>((resolve) => {\n\t\t\t\t\tconst t = new ResettableTimer();\n\t\t\t\t\tt.start(ms, () => resolve());\n\t\t\t\t});\n\n\t// Singleflight — concurrent cache-miss requests with the same key share one\n\t// upstream call. `keyFn` must be synchronous (singleflight needs the key\n\t// before dispatching), so we compute the key eagerly in `invoke`/`stream`\n\t// and thread it through as `_precomputedKey`. The passed `keyFn` reads\n\t// that precomputed value instead of re-hashing.\n\tconst upstreamInFlight = singleFromAny<ResolveArgsWithKey, LLMResponse>(\n\t\tasync ({ messages, invokeOpts }) => {\n\t\t\treturn await firstValueFrom(fromAny(inner.invoke(messages, invokeOpts)));\n\t\t},\n\t\t{ keyFn: ({ _precomputedKey }) => _precomputedKey },\n\t);\n\n\tconst wrap = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst key = await cache.keyFor(messages, invokeOpts);\n\t\t\tconst entry = await cache.lookup(messages, invokeOpts);\n\t\t\tif (entry?.response) {\n\t\t\t\tconst cached = entry.response;\n\t\t\t\treturn { ...cached, metadata: { ...(cached.metadata ?? {}), replayCache: \"hit\" } };\n\t\t\t}\n\n\t\t\tif (mode === \"read-strict\") throw new ReplayCacheMissError(key, \"invoke\");\n\t\t\tconst resp = await upstreamInFlight({ messages, invokeOpts, _precomputedKey: key });\n\t\t\tif (!isReadOnly) {\n\t\t\t\tawait cache.store(messages, invokeOpts, { response: resp, storedAtNs: wallClockNs() });\n\t\t\t}\n\t\t\treturn resp;\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (!cacheStreaming) {\n\t\t\t\t// `read-strict` only applies to cache-checked paths. When\n\t\t\t\t// `cacheStreaming: false` the cache isn't consulted for\n\t\t\t\t// streams at all, so passthrough is correct — throwing would\n\t\t\t\t// make the adapter's stream() permanently unusable.\n\t\t\t\tfor await (const delta of inner.stream(messages, invokeOpts)) yield delta;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst key = await cache.keyFor(messages, invokeOpts);\n\t\t\tconst entry = await cache.lookup(messages, invokeOpts);\n\t\t\tif (entry) {\n\t\t\t\tconst cached = entry.response;\n\t\t\t\t// Cadence-faithful replay when both recorded chunks + delays are present.\n\t\t\t\tif (entry.streamChunks && entry.streamCadenceMs) {\n\t\t\t\t\tfor (let i = 0; i < entry.streamChunks.length; i++) {\n\t\t\t\t\t\tconst delay = entry.streamCadenceMs[i] ?? 0;\n\t\t\t\t\t\tconst effective = replaySpeed > 0 ? delay / replaySpeed : 0;\n\t\t\t\t\t\tif (effective > 0) await sleepMs(effective);\n\t\t\t\t\t\tyield { type: \"token\", delta: entry.streamChunks[i]?.delta ?? \"\" };\n\t\t\t\t\t}\n\t\t\t\t} else if (cached.content) {\n\t\t\t\t\tyield { type: \"token\", delta: cached.content };\n\t\t\t\t}\n\t\t\t\tif (cached.usage) yield { type: \"usage\", usage: cached.usage };\n\t\t\t\tyield { type: \"finish\", reason: cached.finishReason ?? \"stop\" };\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (mode === \"read-strict\") throw new ReplayCacheMissError(key, \"stream\");\n\t\t\t// Miss: accumulate, store, re-yield.\n\t\t\tlet content = \"\";\n\t\t\tlet usage: LLMResponse[\"usage\"] | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tconst chunks: { delta: string }[] = [];\n\t\t\tconst delaysMs: number[] = [];\n\t\t\t// Time-to-first-token (TTFT — provider latency / network / queue\n\t\t\t// warmup) is NOT cadence; setting lastNs inside the loop on first\n\t\t\t// chunk means chunk-0's delay is 0 (boundary-clean) and subsequent\n\t\t\t// delays measure only inter-chunk gaps. Use the central clock so\n\t\t\t// the scale matches every other cadence measurement in the library\n\t\t\t// and the module stays browser-safe (spec §5.11).\n\t\t\tlet lastNs: number | undefined;\n\t\t\tfor await (const delta of inner.stream(messages, invokeOpts)) {\n\t\t\t\tif (delta.type === \"token\") {\n\t\t\t\t\tcontent += delta.delta;\n\t\t\t\t\tif (captureStreamCadence) {\n\t\t\t\t\t\tconst now = monotonicNs();\n\t\t\t\t\t\tconst gap = lastNs === undefined ? 0 : (now - lastNs) / 1e6;\n\t\t\t\t\t\tdelaysMs.push(gap);\n\t\t\t\t\t\tlastNs = now;\n\t\t\t\t\t\tchunks.push({ delta: delta.delta });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (delta.type === \"usage\") usage = delta.usage;\n\t\t\t\tif (delta.type === \"finish\") finishReason = delta.reason;\n\t\t\t\tyield delta;\n\t\t\t}\n\t\t\tif ((content || usage) && !isReadOnly) {\n\t\t\t\tconst resp: LLMResponse = {\n\t\t\t\t\tcontent,\n\t\t\t\t\tusage: usage ?? { input: { regular: 0 }, output: { regular: 0 } },\n\t\t\t\t\tfinishReason,\n\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? \"\",\n\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t};\n\t\t\t\tconst entryToStore: CachedEntry = {\n\t\t\t\t\tresponse: resp,\n\t\t\t\t\tstoredAtNs: wallClockNs(),\n\t\t\t\t\t...(captureStreamCadence ? { streamChunks: chunks, streamCadenceMs: delaysMs } : {}),\n\t\t\t\t};\n\t\t\t\tawait cache.store(messages, invokeOpts, entryToStore);\n\t\t\t}\n\t\t},\n\t});\n\twithLayer(wrap, \"withReplayCache\", inner);\n\treturn wrap;\n}\n\n// canonicalJson is no longer re-exported here — consumers import directly from\n// @graphrefly/pure-ts/extra. The presentation-layer re-export caused a\n// duplicate-export conflict at the root barrel level (A3 build gate).\n","/**\n * `singleFromAny` — keyed promise/Node de-duplication (\"singleflight\").\n *\n * Given a `factory: (key) => NodeInput<T>`, returns a callable that dedupes\n * concurrent invocations sharing the same key — all callers with the same\n * key while a request is in-flight receive the same `Promise<T>`. Once the\n * underlying source settles (DATA, ERROR, or COMPLETE), the cache entry is\n * cleared so the next call re-invokes the factory.\n *\n * This is the classic \"singleflight\" pattern from Go, generalised over the\n * library's `NodeInput<T>` bridge so callers can pass Promise-returning\n * factories, Node-returning factories, or plain value factories with\n * identical semantics.\n *\n * Use cases:\n * - `withReplayCache` cache-miss thundering-herd dedup\n * - Shared HTTP fetches keyed by URL\n * - Expensive compute keyed by request fingerprint\n *\n * @example\n * ```ts\n * const fetchUser = singleFromAny<string, User>((id) => fetch(`/users/${id}`).then(r => r.json()));\n * // Two concurrent callers with id=\"42\" → one underlying fetch, two Promises resolving to the same User.\n * const [a, b] = await Promise.all([fetchUser(\"42\"), fetchUser(\"42\")]);\n * ```\n *\n * @category extra\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport { COMPLETE, ERROR } from \"@graphrefly/pure-ts/core\";\n// Import directly from the source sub-files (rather than the `./sources.js`\n// barrel) so the `single-from-any` module is NOT part of any cycle that runs\n// through `extra/sources/index.ts` — eager re-exports through the barrel were\n// observed to leave `firstValueFrom` / `keepalive` unresolved during nested\n// import chains under vite-node.\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../sources/settled.js\";\n\nexport interface SingleFromAnyOptions<K> {\n\t/**\n\t * Convert a typed key into a cache-string. Defaults to `String(key)`, which\n\t * works for primitive keys; callers with object keys should provide a\n\t * stable serializer (e.g., canonical JSON).\n\t */\n\tkeyFn?: (key: K) => string;\n}\n\n/**\n * Dedupe concurrent `factory(key)` invocations. Returns a bound callable.\n *\n * @param factory - Produces a `NodeInput<T>` for each unique key.\n * @param opts - Optional key-stringification.\n * @returns A function `(key: K) => Promise<T>` whose inflight results are shared per key.\n */\nexport function singleFromAny<K, T>(\n\tfactory: (key: K) => NodeInput<T>,\n\topts: SingleFromAnyOptions<K> = {},\n): (key: K) => Promise<T> {\n\tconst keyFn = opts.keyFn ?? ((k: K) => String(k));\n\tconst inFlight = new Map<string, Promise<T>>();\n\n\treturn (key: K): Promise<T> => {\n\t\tconst k = keyFn(key);\n\t\tconst existing = inFlight.get(k);\n\t\tif (existing) return existing;\n\n\t\tconst input = factory(key);\n\n\t\t// Resolve the NodeInput to a Promise<T>. Different input shapes need\n\t\t// different bridges — Promise/Node/AsyncIterable/Iterable/plain value.\n\t\tlet rawPromise: Promise<T>;\n\t\tif (input != null && typeof (input as PromiseLike<T>).then === \"function\") {\n\t\t\trawPromise = Promise.resolve(input as PromiseLike<T>);\n\t\t} else if (\n\t\t\tinput != null &&\n\t\t\ttypeof input === \"object\" &&\n\t\t\t\"subscribe\" in (input as object) &&\n\t\t\t\"cache\" in (input as object)\n\t\t) {\n\t\t\t// Node: bridge via firstValueFrom.\n\t\t\trawPromise = firstValueFrom(input as Node<T>);\n\t\t} else if (\n\t\t\tinput != null &&\n\t\t\ttypeof input === \"object\" &&\n\t\t\tSymbol.asyncIterator in (input as object)\n\t\t) {\n\t\t\t// AsyncIterable — take the first value, then close the iterator so\n\t\t\t// any owned resources (HTTP body, subscription, timer) are released.\n\t\t\trawPromise = (async () => {\n\t\t\t\tconst iter = (input as AsyncIterable<T>)[Symbol.asyncIterator]();\n\t\t\t\ttry {\n\t\t\t\t\tconst { value, done } = await iter.next();\n\t\t\t\t\tif (done) throw new Error(\"singleFromAny: factory returned empty async iterable\");\n\t\t\t\t\treturn value as T;\n\t\t\t\t} finally {\n\t\t\t\t\tawait iter.return?.();\n\t\t\t\t}\n\t\t\t})();\n\t\t} else if (input != null && typeof input === \"object\" && Symbol.iterator in (input as object)) {\n\t\t\t// Iterable — take the first value, close the iterator.\n\t\t\trawPromise = (async () => {\n\t\t\t\tconst iter = (input as Iterable<T>)[Symbol.iterator]();\n\t\t\t\ttry {\n\t\t\t\t\tconst { value, done } = iter.next();\n\t\t\t\t\tif (done) throw new Error(\"singleFromAny: factory returned empty iterable\");\n\t\t\t\t\treturn value as T;\n\t\t\t\t} finally {\n\t\t\t\t\titer.return?.();\n\t\t\t\t}\n\t\t\t})();\n\t\t} else {\n\t\t\t// Plain value.\n\t\t\trawPromise = Promise.resolve(input as T);\n\t\t}\n\n\t\t// Install the cache entry BEFORE attaching `.finally`. Otherwise a\n\t\t// sync-resolved Promise's finally microtask could run before the\n\t\t// `inFlight.set` below, leaving a stale entry installed afterwards.\n\t\t// We wrap in a holder whose reference we capture *before* chaining.\n\t\tlet tracked!: Promise<T>;\n\t\tconst cleanup = (): void => {\n\t\t\tif (inFlight.get(k) === tracked) inFlight.delete(k);\n\t\t};\n\t\ttracked = rawPromise.then(\n\t\t\t(v) => {\n\t\t\t\tcleanup();\n\t\t\t\treturn v;\n\t\t\t},\n\t\t\t(e) => {\n\t\t\t\tcleanup();\n\t\t\t\tthrow e;\n\t\t\t},\n\t\t);\n\t\tinFlight.set(k, tracked);\n\t\treturn tracked;\n\t};\n}\n\n/**\n * Reactive variant: returns a bound callable that hands out `Node<T>` values.\n * All concurrent callers with the same key during an in-flight source share\n * the same Node. When the underlying source **terminally** settles (ERROR\n * or COMPLETE), the Node is removed from the cache so the next call\n * re-invokes `factory`. DATA is NOT terminal — callers subscribing after\n * the first DATA still receive the shared Node (and push-on-subscribe per\n * the spec's cached-DATA contract).\n *\n * Use when downstream wants reactive subscription (not a one-shot Promise).\n *\n * @category extra\n */\nexport function singleNodeFromAny<K, T>(\n\tfactory: (key: K) => NodeInput<T>,\n\topts: SingleFromAnyOptions<K> = {},\n): (key: K) => Node<T> {\n\tconst keyFn = opts.keyFn ?? ((k: K) => String(k));\n\tconst inFlight = new Map<string, Node<T>>();\n\n\treturn (key: K): Node<T> => {\n\t\tconst k = keyFn(key);\n\t\tconst existing = inFlight.get(k);\n\t\tif (existing) return existing;\n\n\t\tconst node = fromAny(factory(key));\n\t\tinFlight.set(k, node);\n\n\t\t// Evict on terminal settle only — ERROR or COMPLETE. DATA is a value\n\t\t// emission, not a lifecycle transition; multi-emitting Nodes should\n\t\t// continue to share across subscribers after the first value.\n\t\tconst unsub = node.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === ERROR || m[0] === COMPLETE) {\n\t\t\t\t\tif (inFlight.get(k) === node) inFlight.delete(k);\n\t\t\t\t\tunsub();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn node;\n\t};\n}\n","/**\n * Settled/signal helpers.\n *\n * Moved from extra/sources/settled.ts during cleave A2.\n * `keepalive` is substrate — it lives at `@graphrefly/pure-ts`\n * (`packages/pure-ts/src/extra/sources/_keepalive.ts`), not here.\n */\n\n/**\n * Settled / signal helpers — boundary primitives for converting reactive\n * sources into Promise/AbortSignal endpoints.\n *\n * - {@link firstValueFrom} / {@link firstWhere} — Promise of the first\n * matching DATA.\n * - {@link awaitSettled} — composition over `firstWhere` + reactive\n * `timeout` from `extra/resilience` (lazy import to avoid a\n * resilience → sources cycle).\n * - {@link nodeSignal} — `Node<boolean>` → `AbortSignal` bridge.\n * - {@link reactiveCounter} — capped counter exposed as a `Node<number>`.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\ttype Messages,\n\ttype Node,\n\tnode,\n} from \"@graphrefly/pure-ts/core\";\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.snapshot, snap => snap.size > 0);\n * ```\n *\n * @param source - Upstream node to observe.\n * @param predicate - Returns `true` for the value to resolve on.\n * @param opts - `{ skipCurrent?: boolean }`. When `skipCurrent: true`, any DATA\n * delivered during the synchronous `subscribe()` call (push-on-subscribe §2.2\n * replay of the cached value) is ignored — the promise resolves only on the\n * next future emission. Useful when the caller wants to await the next\n * settlement event after an imperative action (e.g. `run()` minting a new\n * runVersion, where the currently-cached value belongs to the previous run).\n *\n * @category extra\n */\nexport function firstWhere<T>(\n\tsource: Node<T>,\n\tpredicate: (value: T) => boolean,\n\topts?: { skipCurrent?: boolean; kick?: () => void },\n): Promise<T> {\n\t// Lock 3.A (Phase 13.6.B): subscribe synchronously inside the function\n\t// body — NOT inside the Promise executor. Subscribing inside the\n\t// executor would defer the subscription past any synchronous `kick()`\n\t// the caller fires after the call returns, race-losing the very wave\n\t// the caller wants to observe.\n\t//\n\t// To bridge sync-subscribe with the async Promise contract, we record\n\t// any settlement that fires *before* the Promise constructor runs, and\n\t// the executor immediately resolves/rejects with the recorded value.\n\t// Settlements after the executor runs go straight through resolve/reject.\n\ttype Pending =\n\t\t| { kind: \"data\"; value: T }\n\t\t| { kind: \"error\"; err: unknown }\n\t\t| { kind: \"complete\" };\n\tlet pending: Pending | undefined;\n\tlet resolveFn: ((value: T) => void) | undefined;\n\tlet rejectFn: ((err: unknown) => void) | undefined;\n\tlet settled = false;\n\tlet shouldUnsub = false;\n\tlet unsub: (() => void) | undefined;\n\tlet inInitialSyncPhase = opts?.skipCurrent === true;\n\n\t// QA P1: every settler short-circuits when `settled === true` so a\n\t// later settle attempt (e.g. `kick()` throwing AFTER it synchronously\n\t// fired matching DATA, OR a `[DATA matched, ERROR]` wave during\n\t// push-on-subscribe) cannot overwrite an earlier `pending` outcome.\n\t// Without this gate, a kick that races sink-callback settlement could\n\t// reject a Promise the user already has resolved-DATA for.\n\tconst settleData = (v: T): void => {\n\t\tif (settled) return;\n\t\tsettled = true;\n\t\tif (resolveFn != null) resolveFn(v);\n\t\telse pending = { kind: \"data\", value: v };\n\t};\n\tconst settleError = (err: unknown): void => {\n\t\tif (settled) return;\n\t\tsettled = true;\n\t\tif (rejectFn != null) rejectFn(err);\n\t\telse pending = { kind: \"error\", err };\n\t};\n\tconst settleComplete = (): void => {\n\t\tif (settled) return;\n\t\tsettled = true;\n\t\tconst err = new Error(\"completed without matching value\");\n\t\tif (rejectFn != null) rejectFn(err);\n\t\telse pending = { kind: \"complete\" };\n\t};\n\tconst detach = (): void => {\n\t\tif (unsub) {\n\t\t\tunsub();\n\t\t\tunsub = undefined;\n\t\t} else shouldUnsub = true;\n\t};\n\n\tconst sink: (msgs: Messages) => void = (msgs) => {\n\t\tif (settled) return;\n\t\tfor (const m of msgs) {\n\t\t\tif (settled) return;\n\t\t\t// During the initial sync phase, swallow only cached DATA\n\t\t\t// (push-on-subscribe §2.2). Terminal ERROR / COMPLETE must\n\t\t\t// still reject the promise — otherwise an already-terminated\n\t\t\t// source synchronously delivering `[[ERROR, ...]]` or\n\t\t\t// `[[COMPLETE]]` during `subscribe()` would hang forever\n\t\t\t// under `skipCurrent: true`.\n\t\t\tif (inInitialSyncPhase && m[0] === DATA) continue;\n\t\t\tif (m[0] === DATA) {\n\t\t\t\tconst v = m[1] as T;\n\t\t\t\tif (predicate(v)) {\n\t\t\t\t\tsettleData(v);\n\t\t\t\t\tdetach();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (m[0] === ERROR) {\n\t\t\t\tsettleError(m[1]);\n\t\t\t\tdetach();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\tsettleComplete();\n\t\t\t\tdetach();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t};\n\tunsub = source.subscribe(sink);\n\tinInitialSyncPhase = false;\n\t// Lock 3.A: fire `kick` AFTER subscribe is in place. With sync\n\t// subscribe + sync kick, the resulting wave reaches `sink` before\n\t// control returns — making subscribe-before-kick ordering structurally\n\t// impossible to misuse.\n\tif (opts?.kick != null && !settled) {\n\t\ttry {\n\t\t\topts.kick();\n\t\t} catch (err) {\n\t\t\tsettleError(err);\n\t\t\tdetach();\n\t\t}\n\t}\n\tif (shouldUnsub) {\n\t\tunsub?.();\n\t\tunsub = undefined;\n\t}\n\n\treturn new Promise<T>((resolve, reject) => {\n\t\t// If a settlement landed synchronously before the executor runs,\n\t\t// flush it through immediately.\n\t\tif (pending != null) {\n\t\t\tif (pending.kind === \"data\") resolve(pending.value);\n\t\t\telse if (pending.kind === \"error\") reject(pending.err);\n\t\t\telse reject(new Error(\"completed without matching value\"));\n\t\t\treturn;\n\t\t}\n\t\tresolveFn = resolve;\n\t\trejectFn = reject;\n\t});\n}\n\n/**\n * Await the first non-nullish DATA value from `source`, with optional\n * timeout. Composition sugar over `firstWhere` + reactive timeout.\n *\n * Designed as the CLI/boundary sink for reactive pipelines that end in a\n * nullable node (e.g. `promptNode` — per COMPOSITION-GUIDE §8, it emits\n * `null` before it settles with a real value). Replaces the common pattern\n * `firstValueFrom(filter(source, v => v != null))` with a deadline.\n *\n * - Rejects with `TimeoutError` (from `extra/resilience`) if no matching\n * value arrives within `timeoutMs`. Omit `timeoutMs` for unbounded wait.\n * - `predicate` defaults to `v => v != null`. Pass a custom predicate to\n * gate on a stronger condition (e.g. `v => typeof v === \"string\"`).\n * - Pass `skipCurrent: true` to ignore the currently-cached value delivered\n * synchronously via push-on-subscribe and resolve only on the *next*\n * matching emission. Useful after an imperative action that should produce\n * a fresh settlement (e.g. `run()` minting a new version — the stale\n * cached value from the previous run must not resolve the new caller).\n *\n * ```ts\n * const brief = await awaitSettled(briefNode, { timeoutMs: 120_000 });\n * // or with a predicate:\n * const rich = await awaitSettled(node, {\n * predicate: (v): v is MyShape => typeof v === \"object\" && v != null && \"key\" in v,\n * timeoutMs: 60_000,\n * });\n * // or after kicking off a fresh run:\n * kickOff();\n * const fresh = await awaitSettled(resultNode, { skipCurrent: true });\n * ```\n *\n * Reactive inside, sync propagation — the one async boundary is the\n * returned `Promise<T>` (spec §5.10: async belongs at sources and\n * boundaries, not in the graph).\n *\n * @param source - Upstream node to observe.\n * @param opts - `{ predicate?, timeoutMs?, skipCurrent? }`.\n * @returns Promise that resolves with the first matching value, or rejects on timeout / ERROR / COMPLETE-without-DATA.\n *\n * @category extra\n */\n// Lazy module-cache for the `withTimeout` resilience operator. The dynamic\n// import keeps `settled` free of an eager edge into the resilience family;\n// first call pays the one-shot import, subsequent calls hit cached refs.\nlet _timeoutOp: typeof import(\"../resilience/timeout.js\").withTimeout | undefined;\nlet _nsPerMs: number | undefined;\n\nexport async function awaitSettled<T>(\n\tsource: Node<T>,\n\topts?: {\n\t\tpredicate?: (value: T) => boolean;\n\t\ttimeoutMs?: number;\n\t\tskipCurrent?: boolean;\n\t\t/**\n\t\t * Lock 3.A (Phase 13.6.B): fired AFTER subscribe is in place but\n\t\t * BEFORE the helper's async boundary is exposed to the caller.\n\t\t * Subscribe-before-kick is structurally enforced — the kick's\n\t\t * synchronous wave reaches `sink` before control returns. Replaces\n\t\t * the prior load-bearing-comment pattern (M.20-load-bearing) with\n\t\t * a misuse-impossible API shape.\n\t\t *\n\t\t * Common pattern:\n\t\t * await awaitSettled(node, {\n\t\t * skipCurrent: true,\n\t\t * kick: () => producer.emit(value),\n\t\t * });\n\t\t *\n\t\t * Omit `kick` for external-trigger cases where the wave is fired\n\t\t * by code outside the helper's caller; subscribe still lands\n\t\t * synchronously inside the helper body so the next external wave\n\t\t * is not lost.\n\t\t */\n\t\tkick?: () => void;\n\t},\n): Promise<NonNullable<T>> {\n\tconst predicate = opts?.predicate ?? ((v: T) => v != null);\n\tconst skipCurrent = opts?.skipCurrent;\n\tconst kick = opts?.kick;\n\tif (opts?.timeoutMs == null || opts.timeoutMs <= 0) {\n\t\treturn (await firstWhere(source, predicate, { skipCurrent, kick })) as NonNullable<T>;\n\t}\n\t// Reactive composition: `timeout()` wraps the source as a Node that\n\t// emits ERROR(TimeoutError) on deadline. `firstWhere` then resolves on\n\t// the first matching DATA or rejects on that ERROR. One async boundary\n\t// (the returned Promise), everything inside is sync reactive.\n\tif (_timeoutOp === undefined) {\n\t\tconst [timeoutMod, backoff] = await Promise.all([\n\t\t\timport(\"../resilience/timeout.js\"),\n\t\t\timport(\"../resilience/backoff.js\"),\n\t\t]);\n\t\t_timeoutOp = timeoutMod.withTimeout;\n\t\t_nsPerMs = backoff.NS_PER_MS;\n\t}\n\tconst guarded = _timeoutOp(source, { ns: opts.timeoutMs * (_nsPerMs as number) }).node;\n\treturn (await firstWhere(guarded, predicate, { skipCurrent, kick })) as NonNullable<T>;\n}\n\n/**\n * Converts a reactive `Node<boolean>` into a browser-standard `AbortSignal`\n * that fires when the node settles on `true`. Useful for threading a reactive\n * \"cancel\" flag into any async boundary that accepts a signal (fetch, LLM SDK\n * calls, child-process APIs, timers).\n *\n * **Contract.**\n * - `signal.abort(reason)` fires exactly once, on the first DATA emission with\n * a truthy value. Subsequent emissions are ignored (AbortSignal is\n * single-shot).\n * - Null / `false` / sentinel values are ignored. Push-on-subscribe will\n * check the currently-cached value on subscribe and abort immediately if\n * it's already `true`.\n * - `reason` defaults to `\"cancelled via nodeSignal\"`; pass `opts.reason` to\n * override (`DOMException`, `Error`, or any value accepted by\n * `AbortController.abort`).\n *\n * **Lifecycle.**\n * - Returns a `{signal, dispose}` bundle. Call `dispose()` when you're done\n * with the signal (e.g. in a `finally` after the async operation completes).\n * `dispose()` unsubscribes from the node and is a no-op once the signal has\n * fired.\n * - **Memory note:** without `dispose()` the subscription keeps the reactive\n * node alive for the lifetime of the process. For bridge calls inside a\n * `switchMap` project fn, the switchMap supersede tears the inner subgraph\n * down, which is usually the right lifetime — but still call `dispose()`\n * from the caller's `finally` for clarity.\n *\n * @example\n * ```ts\n * const aborted = state(false);\n * const { signal, dispose } = nodeSignal(aborted);\n * try {\n * const resp = await adapter.invoke(msgs, { signal });\n * return resp;\n * } finally {\n * dispose();\n * }\n * ```\n *\n * @category extra\n */\nexport function nodeSignal(\n\tsource: Node<boolean>,\n\topts?: { reason?: unknown },\n): { signal: AbortSignal; dispose: () => void } {\n\tconst ctrl = new AbortController();\n\tconst reason = opts?.reason ?? new Error(\"cancelled via nodeSignal\");\n\tlet unsub: (() => void) | undefined;\n\tlet shouldUnsub = false;\n\tconst done = () => {\n\t\tif (unsub) {\n\t\t\tunsub();\n\t\t\tunsub = undefined;\n\t\t} else shouldUnsub = true;\n\t};\n\tunsub = source.subscribe((msgs) => {\n\t\tif (ctrl.signal.aborted) return;\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] === DATA && m[1] === true) {\n\t\t\t\tctrl.abort(reason);\n\t\t\t\tdone();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (m[0] === ERROR) {\n\t\t\t\t// Treat an ERROR on the abort source as a cancel signal too —\n\t\t\t\t// a broken control channel should fail closed, not leak the\n\t\t\t\t// in-flight call. Use the error as the abort reason.\n\t\t\t\tctrl.abort(m[1]);\n\t\t\t\tdone();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t// Source completed without aborting — no-op. `done()` already\n\t\t\t\t// released the subscription here, so a later `dispose()` call\n\t\t\t\t// from the caller is a no-op (safe / idempotent).\n\t\t\t\tdone();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t});\n\tif (shouldUnsub) {\n\t\tunsub?.();\n\t\tunsub = undefined;\n\t}\n\treturn {\n\t\tsignal: ctrl.signal,\n\t\tdispose: () => {\n\t\t\tif (unsub) {\n\t\t\t\tunsub();\n\t\t\t\tunsub = undefined;\n\t\t\t}\n\t\t},\n\t};\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 = node([], { initial: 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 * LLM-specific content-addressed cache wrapper over the generic\n * {@link contentAddressedStorage} substrate in `src/extra/`. Handles the\n * ChatMessage + LLMInvokeOptions → stable key shape that both\n * `withReplayCache` and `fallbackAdapter` need, so the two middleware files\n * don't drift on key construction.\n *\n * The generic substrate does the sha256 + canonicalJson + tier IO; this\n * wrapper owns:\n * - Stripping non-serializable `signal` (AbortSignal) and `keyContext`\n * (caller-opaque context) from the default key.\n * - Arity-dispatched legacy `keyFn` support (1-arg ctx-object form vs 2-arg\n * `(messages, opts)` form).\n * - LLM-conventional `llm-replay` default key prefix (override via `keyPrefix`).\n *\n * @module\n */\n\nimport type { KvStorageTier } from \"@graphrefly/pure-ts/extra\";\nimport {\n\ttype ContentAddressedMode,\n\ttype ContentAddressedStorage,\n\tcontentAddressedStorage,\n} from \"@graphrefly/pure-ts/extra\";\nimport type { ChatMessage, LLMInvokeOptions } from \"../core/types.js\";\n\n/**\n * Context object passed to the 1-arg {@link ContentAddressedCacheOptions.keyFn}\n * form. Adding fields here is forward-compatible — existing 1-arg consumers\n * that ignore unknowns keep working.\n */\nexport interface LLMCacheKeyContext {\n\treadonly messages: readonly ChatMessage[];\n\treadonly opts: LLMInvokeOptions | undefined;\n\t/** Shortcut to `opts?.keyContext` — no extra guard in callers. */\n\treadonly context: unknown;\n}\n\nexport interface ContentAddressedCacheOptions<V> {\n\tstorage: KvStorageTier;\n\tmode?: ContentAddressedMode;\n\t/**\n\t * Custom key function. Receives either {@link LLMCacheKeyContext} (1-arg\n\t * form) or `(messages, opts?)` (legacy 2-arg form) — the wrapper dispatches\n\t * on `Function.length`. Return `string` or `Promise<string>`.\n\t */\n\tkeyFn?:\n\t\t| ((ctx: LLMCacheKeyContext) => string | Promise<string>)\n\t\t| ((messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => string | Promise<string>);\n\t/** Prefix applied as `${keyPrefix}:${hash}`. Default `\"llm-replay\"`. */\n\tkeyPrefix?: string;\n\t/**\n\t * Optional value type hint — callers may store anything JSON-serializable.\n\t * `withReplayCache` stores `CachedEntry` (response + stream cadence);\n\t * `fallbackAdapter` stores the raw `LLMResponse`.\n\t */\n\t_valueType?: V;\n}\n\n/** Handle returned by {@link contentAddressedCache}. */\nexport interface ContentAddressedCache<V> {\n\tkeyFor(messages: readonly ChatMessage[], invokeOpts?: LLMInvokeOptions): Promise<string>;\n\tlookup(messages: readonly ChatMessage[], invokeOpts?: LLMInvokeOptions): Promise<V | undefined>;\n\tstore(\n\t\tmessages: readonly ChatMessage[],\n\t\tinvokeOpts: LLMInvokeOptions | undefined,\n\t\tvalue: V,\n\t): Promise<void>;\n\tforget(messages: readonly ChatMessage[], invokeOpts?: LLMInvokeOptions): Promise<void>;\n}\n\n/**\n * Builds an LLM-shaped content-addressed cache over `storage`. Default keying\n * hashes `(messages, opts minus signal/keyContext)` via\n * {@link contentAddressedStorage} — the generic extra-tier substrate.\n *\n * Used by `withReplayCache` (full response cache) and `fallbackAdapter`\n * (fixture lookup). Both consumers wrap this to add their divergent features\n * (singleflight / stream cadence / canned miss response) around the shared\n * substrate.\n *\n * @category internal\n */\nexport function contentAddressedCache<V>(\n\topts: ContentAddressedCacheOptions<V>,\n): ContentAddressedCache<V> {\n\tconst { storage, mode = \"read-write\", keyFn, keyPrefix = \"llm-replay\" } = opts;\n\n\t// Substrate mode: translate `\"read-strict\"` to `\"read\"` so the substrate\n\t// returns `undefined` on miss. The LLM-middleware callers (`withReplayCache`,\n\t// `fallbackAdapter`) own the strict-mode throw because they emit\n\t// domain-specific error types (`ReplayCacheMissError` / `FallbackMissError`)\n\t// that carry context the substrate shouldn't know about.\n\tconst substrateMode = mode === \"read-strict\" ? \"read\" : mode;\n\n\t// When `keyFn` is supplied, we wire it through the substrate's raw-key API\n\t// (via a synthesized keyContext passthrough). When omitted, we let the\n\t// substrate hash the default shape (messages + opts minus non-serializable\n\t// fields) with the standard prefix.\n\tconst substrate: ContentAddressedStorage<\n\t\t{ messages: readonly ChatMessage[]; opts: LLMInvokeOptions | undefined },\n\t\tV\n\t> = contentAddressedStorage({\n\t\tstorage,\n\t\tkeyPrefix,\n\t\tmode: substrateMode,\n\t\tkeyContext: ({ messages, opts: invokeOpts }) => {\n\t\t\t// Drop `signal` (not serializable) and `keyContext` (caller-opaque\n\t\t\t// context should only participate when user opts in via keyFn).\n\t\t\tconst { signal: _signal, keyContext: _keyContext, ...rest } = invokeOpts ?? {};\n\t\t\treturn { messages, opts: rest };\n\t\t},\n\t});\n\n\tasync function keyFor(\n\t\tmessages: readonly ChatMessage[],\n\t\tinvokeOpts?: LLMInvokeOptions,\n\t): Promise<string> {\n\t\tif (keyFn) {\n\t\t\t// Arity-dispatch: Function.length === 1 → ctx-object form;\n\t\t\t// otherwise → legacy 2-arg (messages, opts). Both may return\n\t\t\t// sync or async strings.\n\t\t\tif (keyFn.length <= 1) {\n\t\t\t\tconst ctx: LLMCacheKeyContext = {\n\t\t\t\t\tmessages,\n\t\t\t\t\topts: invokeOpts,\n\t\t\t\t\tcontext: invokeOpts?.keyContext,\n\t\t\t\t};\n\t\t\t\tconst raw = await (keyFn as (c: LLMCacheKeyContext) => string | Promise<string>)(ctx);\n\t\t\t\treturn `${keyPrefix}:${raw}`;\n\t\t\t}\n\t\t\tconst raw = await (\n\t\t\t\tkeyFn as (m: readonly ChatMessage[], o?: LLMInvokeOptions) => string | Promise<string>\n\t\t\t)(messages, invokeOpts);\n\t\t\treturn `${keyPrefix}:${raw}`;\n\t\t}\n\t\treturn substrate.keyFor({ messages, opts: invokeOpts });\n\t}\n\n\treturn {\n\t\tkeyFor,\n\n\t\tasync lookup(messages, invokeOpts) {\n\t\t\tif (mode === \"write\") return undefined;\n\t\t\tif (keyFn) {\n\t\t\t\t// Custom keyFn path: we can't use substrate.lookup (it hashes\n\t\t\t\t// from its own keyContext). Build the key ourselves and load.\n\t\t\t\t// Strict-mode throw is the CALLER'S responsibility — we return\n\t\t\t\t// undefined on miss so callers can wrap the throw with their\n\t\t\t\t// domain-specific error type.\n\t\t\t\tconst key = await keyFor(messages, invokeOpts);\n\t\t\t\tconst raw = await storage.load(key);\n\t\t\t\tif (raw === undefined) return undefined;\n\t\t\t\treturn raw as V;\n\t\t\t}\n\t\t\treturn substrate.lookup({ messages, opts: invokeOpts });\n\t\t},\n\n\t\tasync store(messages, invokeOpts, value) {\n\t\t\tif (mode === \"read\") return;\n\t\t\tif (keyFn) {\n\t\t\t\tconst key = await keyFor(messages, invokeOpts);\n\t\t\t\tawait storage.save(key, value as unknown);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait substrate.store({ messages, opts: invokeOpts }, value);\n\t\t},\n\n\t\tasync forget(messages, invokeOpts) {\n\t\t\tif (mode === \"read\" || mode === \"write\") return;\n\t\t\tif (!storage.delete) return;\n\t\t\tif (keyFn) {\n\t\t\t\tconst key = await keyFor(messages, invokeOpts);\n\t\t\t\tawait storage.delete(key);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait substrate.forget({ messages, opts: invokeOpts });\n\t\t},\n\t};\n}\n","/**\n * Shared shell + shape-dispatch helpers for the LLM adapter layer.\n *\n * Wave A Unit 11 decision: the 9 middleware files and the observable adapter\n * all repeated the same three boilerplate patterns:\n *\n * 1. Building the returned `LLMAdapter` shell (provider/model/capabilities\n * pass-through). → `adapterWrapper(inner, {invoke, stream})`.\n * 2. Dispatching the adapter's `NodeInput<LLMResponse>` result across its\n * three possible shapes (Promise / Node / plain value) + a `recordedOnce`\n * double-record guard on the reactive path. → `adaptInvokeResult`.\n * 3. Constructing a `CallStatsEvent` from provider / model / tier / usage /\n * latency. → `buildCallStats`.\n *\n * Two small additions:\n * - `withLayer(adapter, layerName)` stamps a `meta.middlewareLayer` tag on\n * the returned adapter via a non-enumerable property, enabling\n * `describeAdapterStack(adapter)` to walk the wrap chain bottom-up.\n * - `describeAdapterStack(adapter)` returns the list of layer names from\n * innermost to outermost so users can inspect the resilient stack the same\n * way they inspect graph topology.\n */\n\nimport { ERROR, monotonicNs, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, onFirstData } from \"@graphrefly/pure-ts/extra\";\nimport type { CallStatsEvent } from \"../core/observable.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tNodeInput,\n\tStreamDelta,\n\tTokenUsage,\n} from \"../core/types.js\";\n\n// ---------------------------------------------------------------------------\n// adapterWrapper — LLMAdapter shell with provider/model/capabilities pass-through\n// ---------------------------------------------------------------------------\n\n/** Callable shape for the invoke / stream bodies that `adapterWrapper` composes. */\nexport type AdapterInvokeFn = (\n\tmessages: readonly ChatMessage[],\n\topts?: LLMInvokeOptions,\n) => NodeInput<LLMResponse>;\n\nexport type AdapterStreamFn = (\n\tmessages: readonly ChatMessage[],\n\topts?: LLMInvokeOptions,\n) => AsyncIterable<StreamDelta>;\n\n/**\n * Builds an `LLMAdapter` shell around the given `invoke` / `stream`\n * implementations. Pass-through fields — `provider`, `model`, `capabilities`\n * — come from `inner` unless the caller overrides (`override.provider` etc.).\n *\n * Middleware files used to repeat `provider: inner.provider, model: inner.model,\n * capabilities: inner.capabilities?.bind(inner)` verbatim; this helper\n * captures that once.\n *\n * @category internal\n */\nexport function adapterWrapper(\n\tinner: LLMAdapter,\n\timpl: { invoke: AdapterInvokeFn; stream: AdapterStreamFn },\n\toverride?: Partial<Pick<LLMAdapter, \"provider\" | \"model\" | \"capabilities\">>,\n): LLMAdapter {\n\treturn {\n\t\tprovider: override?.provider ?? inner.provider,\n\t\tmodel: override?.model ?? inner.model,\n\t\tcapabilities: override?.capabilities ?? inner.capabilities?.bind(inner),\n\t\tinvoke: impl.invoke,\n\t\tstream: impl.stream,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// adaptInvokeResult — shape-dispatch for NodeInput<LLMResponse>\n// ---------------------------------------------------------------------------\n\n/**\n * Shape-dispatch helper for `inner.invoke(...)` return values. Converts any of\n * the three `NodeInput<LLMResponse>` shapes (Promise, plain value, Node /\n * iterable) into the caller-requested output, applying `onResp` exactly once\n * on the first DATA emission.\n *\n * **Paths.**\n * - `Promise<LLMResponse>` → `Promise<R>` (chains `onResp` via `.then`; if\n * `onError` is provided, wires `.catch` so rejected Promises flow to the\n * error path just like the stream body does).\n * - Plain `LLMResponse` (object with `content` field) → `R` (calls `onResp`\n * synchronously and returns the mapped value).\n * - Anything else → reactive `Node<R>` via `fromAny` + `onFirstData(onResp)`\n * so late subscribers don't re-fire the side effect.\n *\n * @category internal\n */\nexport function adaptInvokeResult<R>(\n\tinput: NodeInput<LLMResponse>,\n\topts: {\n\t\tonResp: (resp: LLMResponse) => R;\n\t\t/**\n\t\t * If provided, rejected Promises are piped through this handler (for\n\t\t * stats / budget recording) before re-throwing. Signature mirrors the\n\t\t * stream try/catch shape so callers can share a single error-recording\n\t\t * closure across both paths.\n\t\t */\n\t\tonError?: (err: unknown) => void;\n\t\t/** Optional node name for the reactive-path derived (describe-friendly). */\n\t\tname?: string;\n\t},\n): Promise<R> | R | Node<R> {\n\tconst { onResp, onError, name } = opts;\n\n\t// Promise / thenable: chain .then, optionally .catch.\n\tif (input != null && typeof (input as PromiseLike<LLMResponse>).then === \"function\") {\n\t\tconst p = input as Promise<LLMResponse>;\n\t\tif (onError) {\n\t\t\treturn p.then(onResp).catch((err: unknown) => {\n\t\t\t\tonError(err);\n\t\t\t\tthrow err;\n\t\t\t});\n\t\t}\n\t\treturn p.then(onResp);\n\t}\n\t// Plain LLMResponse (synchronous).\n\tif (input != null && typeof input === \"object\" && \"content\" in (input as object)) {\n\t\treturn onResp(input as LLMResponse);\n\t}\n\t// Reactive / iterable — map inside a `derived` guarded by `onFirstData`\n\t// so the side-effect fires exactly once per node lifetime (push-on-\n\t// subscribe replay on late subscribers is silent).\n\tconst bridged = fromAny(input);\n\t// Wire `onError` via a side-subscription on the bridged node. `onFirstData`\n\t// only handles DATA — ERROR messages need their own hook so stats /\n\t// budget recording fires symmetrically with the Promise path. The\n\t// subscription runs for the lifetime of the derived below (keepalive via\n\t// the downstream derived's activation), and fires at most once per ERROR\n\t// frame. Without this, ERRORs on Node-shaped adapter returns silently\n\t// bypass budget/observable recording.\n\tif (onError) {\n\t\tlet errored = false;\n\t\tbridged.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (errored) return;\n\t\t\t\tif ((m as readonly [symbol, unknown])[0] === ERROR) {\n\t\t\t\t\terrored = true;\n\t\t\t\t\tonError((m as readonly [symbol, unknown])[1]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\t// `captured` holds the mapped value from the first DATA so re-subscribers\n\t// and re-emissions see a stable mapped value without re-firing `onResp`.\n\t// Use a distinct `mapped` sentinel (not nullish) because `onResp` may\n\t// legitimately return `null` / `undefined` / `0` — the prior\n\t// `captured ?? onResp(v)` guard re-fired `onResp` on falsy captured, which\n\t// broke the \"exactly once per node lifetime\" contract.\n\tlet captured: R;\n\tlet mapped = false;\n\tconst tapped = onFirstData(bridged, (v) => {\n\t\tcaptured = onResp(v);\n\t\tmapped = true;\n\t});\n\treturn node<R>(\n\t\t[tapped],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst v = data[0];\n\t\t\tif (v == null) {\n\t\t\t\tactions.emit(null as R);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (mapped) {\n\t\t\t\tactions.emit(captured);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit(onResp(v as LLMResponse));\n\t\t},\n\t\t{ describeKind: \"derived\", name: name ?? \"adapt/invokeTap\" },\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// buildCallStats — CallStatsEvent constructor\n// ---------------------------------------------------------------------------\n\nexport interface BuildCallStatsArgs {\n\tprovider: string;\n\tmodel: string;\n\ttier?: string;\n\tusage: TokenUsage;\n\tstartNs: number;\n\tmethod: \"invoke\" | \"stream\";\n\terror?: { readonly type: string; readonly message: string };\n\t/** Override the wall-clock stamp (useful for tests / replay). */\n\tstartWallClockNs?: number;\n\t/** Override the monotonic end stamp (useful for tests). */\n\tendNs?: number;\n}\n\n/**\n * Constructs a {@link CallStatsEvent} from the arguments observable.ts and\n * budget-gate.ts used to assemble inline. The `timestamp` / `latencyMs` are\n * computed from `startNs` + (optional) `endNs`; `wallClock` is snapshot at\n * call-start via `wallClockNs()` unless overridden.\n *\n * @category internal\n */\nexport function buildCallStats(args: BuildCallStatsArgs): CallStatsEvent {\n\tconst end = args.endNs ?? monotonicNs();\n\treturn {\n\t\ttimestamp: end,\n\t\twallClock: args.startWallClockNs ?? wallClockNs(),\n\t\tprovider: args.provider,\n\t\tmodel: args.model,\n\t\ttier: args.tier,\n\t\tusage: args.usage,\n\t\tlatencyMs: Math.max(0, (end - args.startNs) / 1e6),\n\t\tmethod: args.method,\n\t\t...(args.error ? { error: args.error } : {}),\n\t};\n}\n\n/** Convenience — empty disaggregated usage stub used by every middleware. */\nexport function emptyUsageStub(): TokenUsage {\n\treturn { input: { regular: 0 }, output: { regular: 0 } };\n}\n\n// ---------------------------------------------------------------------------\n// meta.middlewareLayer + describeAdapterStack (Unit 11 Q1 user directive)\n// ---------------------------------------------------------------------------\n\n/** Symbol key carrying the wrap chain on the returned adapter. Non-enumerable. */\nconst MIDDLEWARE_LAYERS = Symbol.for(\"graphrefly.adapter.middlewareLayers\");\n\n/**\n * Stamp `adapter` with a middleware-layer name and return it. The stamp is a\n * non-enumerable property keyed by `Symbol.for(\"graphrefly.adapter.middlewareLayers\")`\n * — opaque to users, visible via {@link describeAdapterStack}.\n *\n * Each wrap prepends its layer to `inner`'s chain so the stack can be walked\n * bottom-up (innermost first). Providers have no layer stamp — they show up\n * as the bottom of the chain via their `provider` / `model` identity.\n *\n * @category internal\n */\nexport function withLayer<A extends LLMAdapter>(\n\tadapter: A,\n\tlayerName: string,\n\tinner?: LLMAdapter,\n): A {\n\tconst innerLayers = inner ? readLayers(inner) : [];\n\tconst chain = [...innerLayers, layerName];\n\tObject.defineProperty(adapter, MIDDLEWARE_LAYERS, {\n\t\tvalue: Object.freeze(chain),\n\t\tenumerable: false,\n\t\twritable: false,\n\t\tconfigurable: false,\n\t});\n\treturn adapter;\n}\n\n/**\n * Returns the middleware-layer names stamped on `adapter`, innermost first.\n * An adapter that has never been wrapped returns `[]` — callers combine the\n * result with `adapter.provider` / `adapter.model` for a full stack render.\n *\n * @example\n * ```ts\n * const stack = describeAdapterStack(resilientAdapter(anthropicAdapter(), opts).adapter);\n * // → [\"withLLMTimeout\", \"withRetry\", \"withLLMBreaker\", \"withBudgetGate\", \"withRateLimiter\", \"cascade\"]\n * ```\n *\n * @category extra\n */\nexport function describeAdapterStack(adapter: LLMAdapter): readonly string[] {\n\treturn readLayers(adapter);\n}\n\nfunction readLayers(adapter: LLMAdapter): readonly string[] {\n\tconst v = (adapter as unknown as Record<symbol, unknown>)[MIDDLEWARE_LAYERS];\n\treturn Array.isArray(v) ? (v as readonly string[]) : [];\n}\n","/**\n * GoogleAdapter — default fetch-backed, optional SDK-backed.\n *\n * The SDK-backed path targets the `@google/genai` SDK shape:\n * `client.models.generateContent({ model, contents, config })` — single\n * param, with generation params and `abortSignal` under `config`. The\n * legacy `@google/generative-ai` two-arg `(params, {signal})` shape is no\n * longer accepted; pass a `GoogleGenAI` instance via `opts.sdk`.\n *\n * Maps Gemini `usageMetadata`:\n * - `promptTokenCount` minus `cachedContentTokenCount` → `input.regular`\n * - `cachedContentTokenCount` → `input.cacheRead`\n * - `candidatesTokenCount` → `output.regular`\n * - `thoughtsTokenCount` → `output.reasoning`\n * - `toolUsePromptTokenCount` → `input.toolUse`\n * - `promptTokensDetails[]` → `input.{image,audio,video}` per modality\n */\n\nimport { monotonicNs } from \"@graphrefly/pure-ts/core\";\nimport { makeHttpError } from \"../../../../base/io/http-error.js\";\nimport { parseSSEStream } from \"../../../../base/io/sse.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n\tToolDefinition,\n} from \"../core/types.js\";\n\nexport interface GoogleAdapterOptions {\n\t/** API key. Falls back to `process.env.GOOGLE_API_KEY` / `GEMINI_API_KEY` on Node. */\n\tapiKey?: string;\n\tmodel?: string;\n\tbaseURL?: string;\n\t/** Extra headers on every request. */\n\theaders?: Record<string, string>;\n\t/**\n\t * Optional `@google/genai` SDK instance (e.g. `new GoogleGenAI({apiKey})`).\n\t * When omitted, the adapter uses the fetch-backed path against the\n\t * Generative Language REST API.\n\t */\n\tsdk?: GoogleSdkLike;\n\tfetchImpl?: typeof fetch;\n}\n\n/**\n * Duck-type matching the `@google/genai` (`GoogleGenAI`) SDK shape:\n * single-param `generateContent({ model, contents, config })` where\n * generation parameters and `abortSignal` live under `config`.\n *\n * The `@google/generative-ai` predecessor's two-arg `(params, {signal})`\n * shape is no longer accepted.\n */\nexport interface GoogleSdkLike {\n\tmodels: {\n\t\tgenerateContent(params: GoogleSdkRequestParams): Promise<GeminiResponse>;\n\t\tgenerateContentStream?(\n\t\t\tparams: GoogleSdkRequestParams,\n\t\t): Promise<AsyncIterable<GeminiResponse>> | AsyncIterable<GeminiResponse>;\n\t};\n}\n\n/** Single-param request shape consumed by `@google/genai`'s `models.generateContent`. */\nexport interface GoogleSdkRequestParams {\n\tmodel: string;\n\tcontents: unknown;\n\tconfig?: GoogleSdkRequestConfig;\n}\n\n/**\n * Generation config under the new SDK. `abortSignal` is the cancellation\n * channel — there is no second-arg `{signal}`.\n */\nexport interface GoogleSdkRequestConfig {\n\tabortSignal?: AbortSignal;\n\ttemperature?: number;\n\tmaxOutputTokens?: number;\n\tsystemInstruction?: unknown;\n\ttools?: unknown;\n\tthinkingConfig?: unknown;\n\t[extra: string]: unknown;\n}\n\ninterface GeminiResponse {\n\tcandidates?: ReadonlyArray<{\n\t\tcontent?: {\n\t\t\trole?: string;\n\t\t\tparts?: ReadonlyArray<{\n\t\t\t\ttext?: string;\n\t\t\t\tthought?: boolean;\n\t\t\t\tfunctionCall?: { name: string; args: Record<string, unknown> };\n\t\t\t}>;\n\t\t};\n\t\tfinishReason?: string;\n\t}>;\n\tusageMetadata?: GeminiUsage;\n\tmodelVersion?: string;\n}\n\ninterface GeminiUsage {\n\tpromptTokenCount?: number;\n\tcandidatesTokenCount?: number;\n\ttotalTokenCount?: number;\n\tthoughtsTokenCount?: number;\n\tcachedContentTokenCount?: number;\n\ttoolUsePromptTokenCount?: number;\n\tpromptTokensDetails?: ReadonlyArray<{ modality: string; tokenCount: number }>;\n\tcandidatesTokensDetails?: ReadonlyArray<{ modality: string; tokenCount: number }>;\n\tcacheTokensDetails?: ReadonlyArray<{ modality: string; tokenCount: number }>;\n}\n\nexport function googleAdapter(opts: GoogleAdapterOptions = {}): LLMAdapter {\n\tif (opts.sdk) return sdkBackedGoogle(opts);\n\treturn fetchBackedGoogle(opts);\n}\n\n// ---------------------------------------------------------------------------\n// Mapping\n// ---------------------------------------------------------------------------\n\nfunction toGeminiRequest(\n\tmessages: readonly ChatMessage[],\n\tinvokeOpts: LLMInvokeOptions | undefined,\n): Record<string, unknown> {\n\tconst systemParts: string[] = [];\n\tconst contents: Array<{\n\t\trole: string;\n\t\tparts: Array<{ text?: string; functionCall?: unknown; functionResponse?: unknown }>;\n\t}> = [];\n\tif (invokeOpts?.systemPrompt) systemParts.push(invokeOpts.systemPrompt);\n\n\tfor (const m of messages) {\n\t\tif (m.role === \"system\") {\n\t\t\tsystemParts.push(m.content);\n\t\t\tcontinue;\n\t\t}\n\t\tif (m.role === \"tool\") {\n\t\t\tcontents.push({\n\t\t\t\trole: \"user\",\n\t\t\t\tparts: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfunctionResponse: {\n\t\t\t\t\t\t\tname: m.name ?? m.toolCallId ?? \"tool\",\n\t\t\t\t\t\t\tresponse: { result: m.content },\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\tcontinue;\n\t\t}\n\t\tif (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n\t\t\tconst parts: Array<{ text?: string; functionCall?: unknown }> = [];\n\t\t\tif (m.content) parts.push({ text: m.content });\n\t\t\tfor (const tc of m.toolCalls) {\n\t\t\t\tparts.push({ functionCall: { name: tc.name, args: tc.arguments } });\n\t\t\t}\n\t\t\tcontents.push({ role: \"model\", parts });\n\t\t\tcontinue;\n\t\t}\n\t\tcontents.push({\n\t\t\trole: m.role === \"assistant\" ? \"model\" : \"user\",\n\t\t\tparts: [{ text: m.content }],\n\t\t});\n\t}\n\n\tconst body: Record<string, unknown> = { contents };\n\tif (systemParts.length > 0) {\n\t\tbody.systemInstruction = { role: \"system\", parts: [{ text: systemParts.join(\"\\n\\n\") }] };\n\t}\n\tconst genConfig: Record<string, unknown> = {};\n\tif (invokeOpts?.maxTokens != null) genConfig.maxOutputTokens = invokeOpts.maxTokens;\n\tif (invokeOpts?.temperature != null) genConfig.temperature = invokeOpts.temperature;\n\tif (invokeOpts?.maxReasoningTokens != null) {\n\t\tgenConfig.thinkingConfig = { thinkingBudget: invokeOpts.maxReasoningTokens };\n\t}\n\tif (Object.keys(genConfig).length > 0) body.generationConfig = genConfig;\n\tif (invokeOpts?.tools && invokeOpts.tools.length > 0) {\n\t\tbody.tools = [{ functionDeclarations: invokeOpts.tools.map(toGeminiTool) }];\n\t}\n\tif (invokeOpts?.providerExtras) Object.assign(body, invokeOpts.providerExtras);\n\treturn body;\n}\n\nfunction toGeminiTool(t: ToolDefinition): Record<string, unknown> {\n\treturn {\n\t\tname: t.name,\n\t\tdescription: t.description,\n\t\tparameters: t.parameters,\n\t};\n}\n\n/**\n * Reshape the fetch-API request body into the SDK's `{ model, contents,\n * config }` form. Generation params (`temperature`, `maxOutputTokens`,\n * `thinkingConfig`) move from `body.generationConfig.*` to `config.*`;\n * `systemInstruction` and `tools` move from top-level body keys into\n * `config`; `abortSignal` is threaded into `config`. `providerExtras` keys\n * spread into `config` so escape-hatch usage remains identical.\n */\nfunction toSdkParams(\n\tbody: Record<string, unknown>,\n\tmodel: string,\n\tsignal: AbortSignal | undefined,\n): GoogleSdkRequestParams {\n\tconst config: GoogleSdkRequestConfig = {};\n\tconst gen = body.generationConfig as Record<string, unknown> | undefined;\n\tif (gen) {\n\t\tif (typeof gen.maxOutputTokens === \"number\") config.maxOutputTokens = gen.maxOutputTokens;\n\t\tif (typeof gen.temperature === \"number\") config.temperature = gen.temperature;\n\t\tif (gen.thinkingConfig) config.thinkingConfig = gen.thinkingConfig;\n\t}\n\tif (body.systemInstruction) config.systemInstruction = body.systemInstruction;\n\tif (body.tools) config.tools = body.tools;\n\tfor (const [k, v] of Object.entries(body)) {\n\t\tif (\n\t\t\tk === \"contents\" ||\n\t\t\tk === \"generationConfig\" ||\n\t\t\tk === \"systemInstruction\" ||\n\t\t\tk === \"tools\" ||\n\t\t\t// Skip `abortSignal` so a caller-supplied entry in `providerExtras`\n\t\t\t// can't briefly land in `config.abortSignal` before being\n\t\t\t// overwritten — the canonical signal channel is the second\n\t\t\t// `signal` argument (set on `config.abortSignal` below).\n\t\t\tk === \"abortSignal\" ||\n\t\t\t// Skip `model` so a stray `body.model` (not produced by\n\t\t\t// `toGeminiRequest` today, but defensively guarded) doesn't\n\t\t\t// duplicate the top-level `model` field on the SDK request.\n\t\t\tk === \"model\"\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\t\tconfig[k] = v;\n\t}\n\tif (signal) config.abortSignal = signal;\n\treturn {\n\t\tmodel,\n\t\tcontents: body.contents,\n\t\tconfig: Object.keys(config).length > 0 ? config : undefined,\n\t};\n}\n\nfunction mapUsage(u: GeminiUsage | undefined): TokenUsage {\n\tconst usage: TokenUsage = {\n\t\tinput: { regular: 0 },\n\t\toutput: { regular: 0 },\n\t\traw: u,\n\t};\n\tif (!u) return usage;\n\tconst promptTotal = u.promptTokenCount ?? 0;\n\tconst cached = u.cachedContentTokenCount ?? 0;\n\tusage.input.regular = Math.max(0, promptTotal - cached);\n\tif (cached > 0) usage.input.cacheRead = cached;\n\tif (u.toolUsePromptTokenCount) usage.input.toolUse = u.toolUsePromptTokenCount;\n\tif (u.promptTokensDetails) {\n\t\tfor (const d of u.promptTokensDetails) {\n\t\t\tconst modality = d.modality?.toLowerCase();\n\t\t\tif (modality === \"image\") usage.input.image = (usage.input.image ?? 0) + d.tokenCount;\n\t\t\telse if (modality === \"audio\") usage.input.audio = (usage.input.audio ?? 0) + d.tokenCount;\n\t\t\telse if (modality === \"video\") usage.input.video = (usage.input.video ?? 0) + d.tokenCount;\n\t\t}\n\t}\n\tusage.output.regular = u.candidatesTokenCount ?? 0;\n\tif (u.thoughtsTokenCount) usage.output.reasoning = u.thoughtsTokenCount;\n\treturn usage;\n}\n\nfunction toLLMResponse(json: GeminiResponse, latencyMs: number): LLMResponse {\n\tconst cand = json.candidates?.[0];\n\tconst parts = cand?.content?.parts ?? [];\n\tconst textParts: string[] = [];\n\tconst toolCalls: { id: string; name: string; arguments: Record<string, unknown> }[] = [];\n\tlet i = 0;\n\tfor (const p of parts) {\n\t\tif (typeof p.text === \"string\") textParts.push(p.text);\n\t\tif (p.functionCall) {\n\t\t\ttoolCalls.push({\n\t\t\t\tid: `${p.functionCall.name}-${i++}`,\n\t\t\t\tname: p.functionCall.name,\n\t\t\t\targuments: p.functionCall.args ?? {},\n\t\t\t});\n\t\t}\n\t}\n\treturn {\n\t\tcontent: textParts.join(\"\"),\n\t\ttoolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n\t\tusage: mapUsage(json.usageMetadata),\n\t\tfinishReason: cand?.finishReason,\n\t\tlatencyMs,\n\t\tmodel: json.modelVersion,\n\t\tprovider: \"google\",\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Fetch-backed\n// ---------------------------------------------------------------------------\n\nfunction resolveApiKey(opts: GoogleAdapterOptions): string | undefined {\n\tif (opts.apiKey) return opts.apiKey;\n\tconst env = (globalThis as { process?: { env?: Record<string, string> } }).process?.env;\n\treturn env?.GOOGLE_API_KEY ?? env?.GEMINI_API_KEY;\n}\n\nfunction fetchBackedGoogle(opts: GoogleAdapterOptions): LLMAdapter {\n\tconst baseURL = opts.baseURL ?? \"https://generativelanguage.googleapis.com/v1beta\";\n\tconst fetchImpl = opts.fetchImpl ?? fetch;\n\n\tconst pickModel = (invokeOpts: LLMInvokeOptions | undefined): string => {\n\t\tconst model = invokeOpts?.model ?? opts.model;\n\t\tif (!model)\n\t\t\tthrow new Error(\"googleAdapter: model must be set via options.model or invokeOpts.model\");\n\t\treturn model;\n\t};\n\n\tconst keyParam = (): string => {\n\t\tconst key = resolveApiKey(opts);\n\t\tif (!key) throw new Error(\"googleAdapter: apiKey required for invoke/stream\");\n\t\treturn `key=${encodeURIComponent(key)}`;\n\t};\n\n\treturn {\n\t\tprovider: \"google\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst model = pickModel(invokeOpts);\n\t\t\tconst body = toGeminiRequest(messages, invokeOpts);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst url = `${baseURL}/models/${encodeURIComponent(model)}:generateContent?${keyParam()}`;\n\t\t\tconst resp = await fetchImpl(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"content-type\": \"application/json\", ...(opts.headers ?? {}) },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, \"Google\");\n\t\t\tconst json = (await resp.json()) as GeminiResponse;\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(json, latencyMs);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst model = pickModel(invokeOpts);\n\t\t\tconst body = toGeminiRequest(messages, invokeOpts);\n\t\t\tconst url = `${baseURL}/models/${encodeURIComponent(model)}:streamGenerateContent?alt=sse&${keyParam()}`;\n\t\t\tconst resp = await fetchImpl(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t\t...(opts.headers ?? {}),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, \"Google\");\n\t\t\tif (!resp.body) throw new Error(\"googleAdapter: streaming response has no body\");\n\n\t\t\tlet finalUsage: GeminiUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\n\t\t\tfor await (const event of parseSSEStream(resp.body, { signal: invokeOpts?.signal })) {\n\t\t\t\tif (!event.data) continue;\n\t\t\t\tlet parsed: GeminiResponse;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(event.data) as GeminiResponse;\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst cand = parsed.candidates?.[0];\n\t\t\t\tfor (const p of cand?.content?.parts ?? []) {\n\t\t\t\t\tif (typeof p.text === \"string\") {\n\t\t\t\t\t\tif (p.thought) yield { type: \"thinking\", delta: p.text };\n\t\t\t\t\t\telse yield { type: \"token\", delta: p.text };\n\t\t\t\t\t}\n\t\t\t\t\tif (p.functionCall) {\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\tname: p.functionCall.name,\n\t\t\t\t\t\t\t\targumentsDelta: JSON.stringify(p.functionCall.args ?? {}),\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\tif (cand?.finishReason) finishReason = cand.finishReason;\n\t\t\t\tif (parsed.usageMetadata) finalUsage = parsed.usageMetadata;\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\nfunction sdkBackedGoogle(opts: GoogleAdapterOptions): LLMAdapter {\n\tconst sdk = opts.sdk;\n\tif (!sdk) throw new Error(\"sdkBackedGoogle: sdk instance required\");\n\n\treturn {\n\t\tprovider: \"google\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toGeminiRequest(messages, invokeOpts);\n\t\t\tconst model = invokeOpts?.model ?? opts.model;\n\t\t\tif (!model) throw new Error(\"googleAdapter: model required\");\n\t\t\tconst params = toSdkParams(body, model, invokeOpts?.signal);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await sdk.models.generateContent(params);\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(resp, latencyMs);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (!sdk.models.generateContentStream) {\n\t\t\t\tthrow new Error(\"sdkBackedGoogle: SDK instance does not expose generateContentStream\");\n\t\t\t}\n\t\t\tconst body = toGeminiRequest(messages, invokeOpts);\n\t\t\tconst model = invokeOpts?.model ?? opts.model;\n\t\t\tif (!model) throw new Error(\"googleAdapter: model required\");\n\t\t\tconst params = toSdkParams(body, model, invokeOpts?.signal);\n\t\t\tlet finalUsage: GeminiUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\t// `@google/genai` returns `Promise<AsyncIterable<...>>`; older shapes\n\t\t\t// returned the iterable directly. Awaiting a non-thenable resolves\n\t\t\t// to itself, so this works for both.\n\t\t\tconst stream = await sdk.models.generateContentStream(params);\n\t\t\tfor await (const chunk of stream) {\n\t\t\t\tconst cand = chunk.candidates?.[0];\n\t\t\t\tfor (const p of cand?.content?.parts ?? []) {\n\t\t\t\t\tif (typeof p.text === \"string\") {\n\t\t\t\t\t\tif (p.thought) yield { type: \"thinking\", delta: p.text };\n\t\t\t\t\t\telse yield { type: \"token\", delta: p.text };\n\t\t\t\t\t}\n\t\t\t\t\tif (p.functionCall) {\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\tname: p.functionCall.name,\n\t\t\t\t\t\t\t\targumentsDelta: JSON.stringify(p.functionCall.args ?? {}),\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\tif (cand?.finishReason) finishReason = cand.finishReason;\n\t\t\t\tif (chunk.usageMetadata) finalUsage = chunk.usageMetadata;\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n","/**\n * OpenAICompatAdapter — default fetch-backed, optional SDK-backed.\n *\n * Covers any provider that speaks OpenAI chat/completions. Preset base URLs\n * for OpenAI, OpenRouter, Groq, Ollama, DeepSeek, xAI Grok (all expose the\n * same `/v1/chat/completions` shape).\n *\n * Token usage mapping:\n * - `prompt_tokens` → `input.regular` (minus cached_tokens)\n * - `prompt_tokens_details.cached_tokens` → `input.cacheRead`\n * - `prompt_tokens_details.audio_tokens` → `input.audio`\n * - `completion_tokens` → `output.regular` (minus reasoning)\n * - `completion_tokens_details.reasoning_tokens` → `output.reasoning`\n * - `completion_tokens_details.audio_tokens` → `output.audio`\n * - `completion_tokens_details.accepted_prediction_tokens` → `output.predictionAccepted`\n * - `completion_tokens_details.rejected_prediction_tokens` → `output.predictionRejected`\n *\n * DeepSeek compatibility: `prompt_cache_hit_tokens` / `prompt_cache_miss_tokens`\n * are surfaced in the `raw` field of `TokenUsage`; when present we prefer\n * them over the OpenAI-style `cached_tokens` for cache-read attribution.\n */\n\nimport { monotonicNs } from \"@graphrefly/pure-ts/core\";\nimport { makeHttpError } from \"../../../../base/io/http-error.js\";\nimport { parseSSEStream } from \"../../../../base/io/sse.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n\tToolDefinition,\n} from \"../core/types.js\";\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport type OpenAICompatPreset = \"openai\" | \"openrouter\" | \"groq\" | \"ollama\" | \"deepseek\" | \"xai\";\n\nconst PRESETS: Record<\n\tOpenAICompatPreset,\n\t{ baseURL: string; apiKeyEnv?: string; provider: string }\n> = {\n\topenai: { baseURL: \"https://api.openai.com/v1\", apiKeyEnv: \"OPENAI_API_KEY\", provider: \"openai\" },\n\topenrouter: {\n\t\tbaseURL: \"https://openrouter.ai/api/v1\",\n\t\tapiKeyEnv: \"OPENROUTER_API_KEY\",\n\t\tprovider: \"openrouter\",\n\t},\n\tgroq: { baseURL: \"https://api.groq.com/openai/v1\", apiKeyEnv: \"GROQ_API_KEY\", provider: \"groq\" },\n\tollama: { baseURL: \"http://localhost:11434/v1\", provider: \"ollama\" },\n\tdeepseek: {\n\t\tbaseURL: \"https://api.deepseek.com/v1\",\n\t\tapiKeyEnv: \"DEEPSEEK_API_KEY\",\n\t\tprovider: \"deepseek\",\n\t},\n\txai: { baseURL: \"https://api.x.ai/v1\", apiKeyEnv: \"XAI_API_KEY\", provider: \"xai\" },\n};\n\nexport interface OpenAICompatAdapterOptions {\n\tpreset?: OpenAICompatPreset;\n\t/** Explicit provider label (defaults to preset's provider). */\n\tprovider?: string;\n\t/** API key. Falls back to the preset's default env var on Node. */\n\tapiKey?: string;\n\tmodel?: string;\n\t/** Override base URL (wins over `preset`). */\n\tbaseURL?: string;\n\t/** Extra request headers. */\n\theaders?: Record<string, string>;\n\t/** Extra request-body fields merged on every request (OpenRouter routing etc.). */\n\tbodyExtras?: Record<string, unknown>;\n\t/** User-provided SDK instance (OpenAI-family shape). */\n\tsdk?: OpenAISdkLike;\n\t/** Custom fetch (for tests). */\n\tfetchImpl?: typeof fetch;\n}\n\nexport interface OpenAISdkLike {\n\tchat: {\n\t\tcompletions: {\n\t\t\tcreate(\n\t\t\t\tparams: Record<string, unknown>,\n\t\t\t\topts?: { signal?: AbortSignal },\n\t\t\t): Promise<OpenAIChatResponse>;\n\t\t};\n\t};\n}\n\ninterface OpenAIChatResponse {\n\tid: string;\n\tchoices: ReadonlyArray<{\n\t\tmessage: {\n\t\t\trole: string;\n\t\t\tcontent?: string | null;\n\t\t\ttool_calls?: ReadonlyArray<{\n\t\t\t\tid: string;\n\t\t\t\ttype: \"function\";\n\t\t\t\tfunction: { name: string; arguments: string };\n\t\t\t}>;\n\t\t\treasoning_content?: string;\n\t\t};\n\t\tfinish_reason?: string;\n\t}>;\n\tusage?: OpenAIUsage;\n\tmodel?: string;\n}\n\ninterface OpenAIUsage {\n\tprompt_tokens?: number;\n\tcompletion_tokens?: number;\n\ttotal_tokens?: number;\n\tprompt_tokens_details?: {\n\t\tcached_tokens?: number;\n\t\taudio_tokens?: number;\n\t};\n\tcompletion_tokens_details?: {\n\t\treasoning_tokens?: number;\n\t\taudio_tokens?: number;\n\t\taccepted_prediction_tokens?: number;\n\t\trejected_prediction_tokens?: number;\n\t};\n\t// DeepSeek\n\tprompt_cache_hit_tokens?: number;\n\tprompt_cache_miss_tokens?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function openAICompatAdapter(opts: OpenAICompatAdapterOptions = {}): LLMAdapter {\n\tif (opts.sdk) return sdkBackedOpenAI(opts);\n\treturn fetchBackedOpenAI(opts);\n}\n\n// ---------------------------------------------------------------------------\n// Mapping\n// ---------------------------------------------------------------------------\n\nfunction toOpenAIRequest(\n\tmessages: readonly ChatMessage[],\n\tinvokeOpts: LLMInvokeOptions | undefined,\n\tdefaultModel: string | undefined,\n\tstream: boolean,\n\tbodyExtras: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n\tconst model = invokeOpts?.model ?? defaultModel;\n\tif (!model)\n\t\tthrow new Error(\"openAICompatAdapter: model must be set via options.model or invokeOpts.model\");\n\tconst mapped = messages.map(toOpenAIMessage);\n\tif (invokeOpts?.systemPrompt && !messages.some((m) => m.role === \"system\")) {\n\t\tmapped.unshift({ role: \"system\", content: invokeOpts.systemPrompt });\n\t}\n\tconst body: Record<string, unknown> = { model, messages: mapped };\n\tif (invokeOpts?.maxTokens != null) body.max_tokens = invokeOpts.maxTokens;\n\tif (invokeOpts?.temperature != null) body.temperature = invokeOpts.temperature;\n\tif (invokeOpts?.tools && invokeOpts.tools.length > 0) {\n\t\tbody.tools = invokeOpts.tools.map(toOpenAITool);\n\t}\n\tif (invokeOpts?.maxReasoningTokens != null) {\n\t\tbody.reasoning = { max_tokens: invokeOpts.maxReasoningTokens };\n\t}\n\tif (stream) {\n\t\tbody.stream = true;\n\t\tbody.stream_options = { include_usage: true };\n\t}\n\tif (bodyExtras) Object.assign(body, bodyExtras);\n\tif (invokeOpts?.providerExtras) Object.assign(body, invokeOpts.providerExtras);\n\treturn body;\n}\n\nfunction toOpenAIMessage(m: ChatMessage): Record<string, unknown> {\n\tif (m.role === \"tool\") {\n\t\treturn { role: \"tool\", tool_call_id: m.toolCallId, content: m.content };\n\t}\n\tif (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n\t\treturn {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: m.content || null,\n\t\t\ttool_calls: m.toolCalls.map((tc) => ({\n\t\t\t\tid: tc.id,\n\t\t\t\ttype: \"function\",\n\t\t\t\tfunction: { name: tc.name, arguments: JSON.stringify(tc.arguments) },\n\t\t\t})),\n\t\t};\n\t}\n\treturn { role: m.role, content: m.content };\n}\n\nfunction toOpenAITool(t: ToolDefinition): Record<string, unknown> {\n\treturn {\n\t\ttype: \"function\",\n\t\tfunction: {\n\t\t\tname: t.name,\n\t\t\tdescription: t.description,\n\t\t\tparameters: t.parameters,\n\t\t},\n\t};\n}\n\nfunction mapUsage(u: OpenAIUsage | undefined): TokenUsage {\n\tconst usage: TokenUsage = {\n\t\tinput: { regular: 0 },\n\t\toutput: { regular: 0 },\n\t\traw: u,\n\t};\n\tif (!u) return usage;\n\tconst inputTotal = u.prompt_tokens ?? 0;\n\tlet cacheRead = u.prompt_tokens_details?.cached_tokens ?? 0;\n\tif (u.prompt_cache_hit_tokens != null) {\n\t\t// DeepSeek: prefer explicit hit/miss split when present\n\t\tcacheRead = u.prompt_cache_hit_tokens;\n\t\tusage.input.regular = u.prompt_cache_miss_tokens ?? Math.max(0, inputTotal - cacheRead);\n\t} else {\n\t\tusage.input.regular = Math.max(0, inputTotal - cacheRead);\n\t}\n\tif (cacheRead > 0) usage.input.cacheRead = cacheRead;\n\tif (u.prompt_tokens_details?.audio_tokens)\n\t\tusage.input.audio = u.prompt_tokens_details.audio_tokens;\n\n\tconst outputTotal = u.completion_tokens ?? 0;\n\tconst reasoning = u.completion_tokens_details?.reasoning_tokens ?? 0;\n\tusage.output.regular = Math.max(0, outputTotal - reasoning);\n\tif (reasoning > 0) usage.output.reasoning = reasoning;\n\tif (u.completion_tokens_details?.audio_tokens)\n\t\tusage.output.audio = u.completion_tokens_details.audio_tokens;\n\tif (u.completion_tokens_details?.accepted_prediction_tokens) {\n\t\tusage.output.predictionAccepted = u.completion_tokens_details.accepted_prediction_tokens;\n\t}\n\tif (u.completion_tokens_details?.rejected_prediction_tokens) {\n\t\tusage.output.predictionRejected = u.completion_tokens_details.rejected_prediction_tokens;\n\t}\n\treturn usage;\n}\n\nfunction toLLMResponse(json: OpenAIChatResponse, latencyMs: number, provider: string): LLMResponse {\n\tconst choice = json.choices[0];\n\tconst msg = choice?.message;\n\tconst content = msg?.content ?? \"\";\n\tconst toolCalls = (msg?.tool_calls ?? []).map((tc) => ({\n\t\tid: tc.id,\n\t\tname: tc.function.name,\n\t\targuments: safeJsonParse(tc.function.arguments),\n\t}));\n\treturn {\n\t\tcontent,\n\t\ttoolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n\t\tusage: mapUsage(json.usage),\n\t\tfinishReason: choice?.finish_reason,\n\t\tlatencyMs,\n\t\tmodel: json.model,\n\t\tprovider,\n\t};\n}\n\nfunction safeJsonParse(s: string): Record<string, unknown> {\n\ttry {\n\t\tconst parsed = JSON.parse(s);\n\t\treturn typeof parsed === \"object\" && parsed != null\n\t\t\t? (parsed as Record<string, unknown>)\n\t\t\t: { _raw: s };\n\t} catch {\n\t\treturn { _raw: s };\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Fetch-backed\n// ---------------------------------------------------------------------------\n\nfunction resolveConfig(opts: OpenAICompatAdapterOptions): {\n\tprovider: string;\n\tbaseURL: string;\n\tapiKey: string | undefined;\n} {\n\tconst preset = opts.preset ?? \"openai\";\n\tconst base = PRESETS[preset];\n\tconst baseURL = opts.baseURL ?? base.baseURL;\n\tconst provider = opts.provider ?? base.provider;\n\tconst envKey = base.apiKeyEnv;\n\tconst apiKey =\n\t\topts.apiKey ??\n\t\t(envKey\n\t\t\t? (globalThis as { process?: { env?: Record<string, string> } }).process?.env?.[envKey]\n\t\t\t: undefined);\n\treturn { provider, baseURL, apiKey };\n}\n\nfunction fetchBackedOpenAI(opts: OpenAICompatAdapterOptions): LLMAdapter {\n\tconst { provider, baseURL, apiKey } = resolveConfig(opts);\n\tconst fetchImpl = opts.fetchImpl ?? fetch;\n\tconst needsKey = provider !== \"ollama\"; // Ollama local default: no key required.\n\n\tconst commonHeaders = (): Record<string, string> => {\n\t\tconst h: Record<string, string> = {\n\t\t\t\"content-type\": \"application/json\",\n\t\t\t...(opts.headers ?? {}),\n\t\t};\n\t\tif (needsKey) {\n\t\t\tif (!apiKey)\n\t\t\t\tthrow new Error(`openAICompatAdapter[${provider}]: apiKey required for invoke/stream`);\n\t\t\th.authorization = `Bearer ${apiKey}`;\n\t\t}\n\t\treturn h;\n\t};\n\n\treturn {\n\t\tprovider,\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toOpenAIRequest(messages, invokeOpts, opts.model, false, opts.bodyExtras);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await fetchImpl(`${baseURL}/chat/completions`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: commonHeaders(),\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, provider);\n\t\t\tconst json = (await resp.json()) as OpenAIChatResponse;\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(json, latencyMs, provider);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst body = toOpenAIRequest(messages, invokeOpts, opts.model, true, opts.bodyExtras);\n\t\t\tconst resp = await fetchImpl(`${baseURL}/chat/completions`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { ...commonHeaders(), accept: \"text/event-stream\" },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, provider);\n\t\t\tif (!resp.body)\n\t\t\t\tthrow new Error(`openAICompatAdapter[${provider}]: streaming response has no body`);\n\n\t\t\tlet finalUsage: OpenAIUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\n\t\t\tfor await (const event of parseSSEStream(resp.body, { signal: invokeOpts?.signal })) {\n\t\t\t\tif (!event.data || event.data === \"[DONE]\") continue;\n\t\t\t\tlet parsed: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(event.data) as Record<string, unknown>;\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// Streaming shape: choices[0].delta.{content?, tool_calls?, reasoning_content?}\n\t\t\t\tconst choices = parsed.choices as\n\t\t\t\t\t| ReadonlyArray<{\n\t\t\t\t\t\t\tdelta?: {\n\t\t\t\t\t\t\t\tcontent?: string;\n\t\t\t\t\t\t\t\ttool_calls?: ReadonlyArray<{\n\t\t\t\t\t\t\t\t\tindex: number;\n\t\t\t\t\t\t\t\t\tid?: string;\n\t\t\t\t\t\t\t\t\tfunction?: { name?: string; arguments?: string };\n\t\t\t\t\t\t\t\t}>;\n\t\t\t\t\t\t\t\treasoning_content?: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tfinish_reason?: string;\n\t\t\t\t\t }>\n\t\t\t\t\t| undefined;\n\t\t\t\tif (choices) {\n\t\t\t\t\tconst c = choices[0];\n\t\t\t\t\tif (c?.delta?.content) yield { type: \"token\", delta: c.delta.content };\n\t\t\t\t\tif (c?.delta?.reasoning_content) {\n\t\t\t\t\t\tyield { type: \"thinking\", delta: c.delta.reasoning_content };\n\t\t\t\t\t}\n\t\t\t\t\tif (c?.delta?.tool_calls) {\n\t\t\t\t\t\tfor (const tc of c.delta.tool_calls) {\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\t\t\t\tname: tc.function?.name,\n\t\t\t\t\t\t\t\t\targumentsDelta: tc.function?.arguments,\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\tif (c?.finish_reason) finishReason = c.finish_reason;\n\t\t\t\t}\n\t\t\t\t// Yield every usage delta the provider emits (Anthropic, Groq, and\n\t\t\t\t// some OpenAI-compat providers can emit mid-stream usage). Downstream\n\t\t\t\t// consumers treat the most-recent delta as authoritative. See D5b in\n\t\t\t\t// adapter QA session.\n\t\t\t\tif (parsed.usage) {\n\t\t\t\t\tfinalUsage = parsed.usage as OpenAIUsage;\n\t\t\t\t\tyield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\t\t}\n\t\t\t}\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\nfunction sdkBackedOpenAI(opts: OpenAICompatAdapterOptions): LLMAdapter {\n\tconst sdk = opts.sdk;\n\tif (!sdk) throw new Error(\"sdkBackedOpenAI: sdk instance required\");\n\tconst { provider } = resolveConfig(opts);\n\treturn {\n\t\tprovider,\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toOpenAIRequest(messages, invokeOpts, opts.model, false, opts.bodyExtras);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await sdk.chat.completions.create(body, { signal: invokeOpts?.signal });\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(resp, latencyMs, provider);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst body = toOpenAIRequest(messages, invokeOpts, opts.model, true, opts.bodyExtras);\n\t\t\tconst stream = (await sdk.chat.completions.create(body, {\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t})) as unknown as AsyncIterable<Record<string, unknown>>;\n\t\t\tlet finalUsage: OpenAIUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tfor await (const chunk of stream) {\n\t\t\t\tconst choices = (\n\t\t\t\t\tchunk as {\n\t\t\t\t\t\tchoices?: ReadonlyArray<{\n\t\t\t\t\t\t\tdelta?: {\n\t\t\t\t\t\t\t\tcontent?: string;\n\t\t\t\t\t\t\t\ttool_calls?: ReadonlyArray<{\n\t\t\t\t\t\t\t\t\tid?: string;\n\t\t\t\t\t\t\t\t\tfunction?: { name?: string; arguments?: string };\n\t\t\t\t\t\t\t\t}>;\n\t\t\t\t\t\t\t\treasoning_content?: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tfinish_reason?: string;\n\t\t\t\t\t\t}>;\n\t\t\t\t\t}\n\t\t\t\t).choices;\n\t\t\t\tif (choices) {\n\t\t\t\t\tconst c = choices[0];\n\t\t\t\t\tif (c?.delta?.content) yield { type: \"token\", delta: c.delta.content };\n\t\t\t\t\tif (c?.delta?.reasoning_content)\n\t\t\t\t\t\tyield { type: \"thinking\", delta: c.delta.reasoning_content };\n\t\t\t\t\tif (c?.delta?.tool_calls) {\n\t\t\t\t\t\tfor (const tc of c.delta.tool_calls) {\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\t\t\t\tname: tc.function?.name,\n\t\t\t\t\t\t\t\t\targumentsDelta: tc.function?.arguments,\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\tif (c?.finish_reason) finishReason = c.finish_reason;\n\t\t\t\t}\n\t\t\t\tconst u = (chunk as { usage?: OpenAIUsage }).usage;\n\t\t\t\tif (u) {\n\t\t\t\t\tfinalUsage = u;\n\t\t\t\t\tyield { type: \"usage\", usage: mapUsage(u) };\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!finalUsage) {\n\t\t\t\t// No usage emitted — yield nothing; downstream consumers default\n\t\t\t\t// to empty usage via their own fallback.\n\t\t\t}\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n","/**\n * `createAdapter` — provider-dispatching factory.\n *\n * One entry point, one config object. Picks the right concrete adapter by\n * `provider`, forwards everything else. Users who want finer control import\n * the concrete adapter directly (`anthropicAdapter`, `openAICompatAdapter`,\n * `googleAdapter`, `dryRunAdapter`, `webllmAdapter`, `chromeNanoAdapter`).\n */\n\nimport { type AnthropicAdapterOptions, anthropicAdapter } from \"../providers/anthropic.js\";\nimport { type DryRunAdapterOptions, dryRunAdapter } from \"../providers/dry-run.js\";\nimport { type FallbackAdapterOptions, fallbackAdapter } from \"../providers/fallback.js\";\nimport { type GoogleAdapterOptions, googleAdapter } from \"../providers/google.js\";\nimport {\n\ttype OpenAICompatAdapterOptions,\n\ttype OpenAICompatPreset,\n\topenAICompatAdapter,\n} from \"../providers/openai-compat.js\";\nimport type { LLMAdapter } from \"./types.js\";\n\nexport type AdapterProvider =\n\t| \"anthropic\"\n\t| OpenAICompatPreset // \"openai\" | \"openrouter\" | \"groq\" | \"ollama\" | \"deepseek\" | \"xai\"\n\t| \"google\"\n\t| \"dry-run\"\n\t| \"fallback\";\n\nexport interface CreateAdapterOptions {\n\tprovider: AdapterProvider;\n\tapiKey?: string;\n\tmodel?: string;\n\tbaseURL?: string;\n\theaders?: Record<string, string>;\n\t/** OpenAI-compat bodyExtras (OpenRouter routing, etc.). */\n\tbodyExtras?: Record<string, unknown>;\n\t/** Provider-specific SDK instance (any of AnthropicSdkLike / OpenAISdkLike / GoogleSdkLike). */\n\tsdk?: unknown;\n\t/** Custom fetch (for tests). */\n\tfetchImpl?: typeof fetch;\n\t/** Extra per-provider options forwarded verbatim. */\n\textras?: Record<string, unknown>;\n}\n\nexport function createAdapter(opts: CreateAdapterOptions): LLMAdapter {\n\tswitch (opts.provider) {\n\t\tcase \"anthropic\": {\n\t\t\tconst a: AnthropicAdapterOptions = {\n\t\t\t\tapiKey: opts.apiKey,\n\t\t\t\tmodel: opts.model,\n\t\t\t\tbaseURL: opts.baseURL,\n\t\t\t\theaders: opts.headers,\n\t\t\t\tsdk: opts.sdk as AnthropicAdapterOptions[\"sdk\"],\n\t\t\t\tfetchImpl: opts.fetchImpl,\n\t\t\t\t...(opts.extras as AnthropicAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn anthropicAdapter(a);\n\t\t}\n\t\tcase \"google\": {\n\t\t\tconst g: GoogleAdapterOptions = {\n\t\t\t\tapiKey: opts.apiKey,\n\t\t\t\tmodel: opts.model,\n\t\t\t\tbaseURL: opts.baseURL,\n\t\t\t\theaders: opts.headers,\n\t\t\t\tsdk: opts.sdk as GoogleAdapterOptions[\"sdk\"],\n\t\t\t\tfetchImpl: opts.fetchImpl,\n\t\t\t\t...(opts.extras as GoogleAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn googleAdapter(g);\n\t\t}\n\t\tcase \"dry-run\": {\n\t\t\tconst d: DryRunAdapterOptions = {\n\t\t\t\tmodel: opts.model,\n\t\t\t\t...(opts.extras as DryRunAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn dryRunAdapter(d);\n\t\t}\n\t\tcase \"fallback\": {\n\t\t\t// `provider`/`model` threaded as labels; `fixtures`/`record`/etc.\n\t\t\t// must come through `extras` since `CreateAdapterOptions` doesn't\n\t\t\t// have dedicated slots for them.\n\t\t\tconst f: FallbackAdapterOptions = {\n\t\t\t\tprovider: opts.provider,\n\t\t\t\tmodel: opts.model,\n\t\t\t\t...(opts.extras as FallbackAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn fallbackAdapter(f);\n\t\t}\n\t\t// OpenAI-compat presets\n\t\tcase \"openai\":\n\t\tcase \"openrouter\":\n\t\tcase \"groq\":\n\t\tcase \"ollama\":\n\t\tcase \"deepseek\":\n\t\tcase \"xai\": {\n\t\t\tconst c: OpenAICompatAdapterOptions = {\n\t\t\t\tpreset: opts.provider,\n\t\t\t\tapiKey: opts.apiKey,\n\t\t\t\tmodel: opts.model,\n\t\t\t\tbaseURL: opts.baseURL,\n\t\t\t\theaders: opts.headers,\n\t\t\t\tbodyExtras: opts.bodyExtras,\n\t\t\t\tsdk: opts.sdk as OpenAICompatAdapterOptions[\"sdk\"],\n\t\t\t\tfetchImpl: opts.fetchImpl,\n\t\t\t\t...(opts.extras as OpenAICompatAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn openAICompatAdapter(c);\n\t\t}\n\t\tdefault: {\n\t\t\tconst never: never = opts.provider;\n\t\t\tthrow new Error(`createAdapter: unknown provider: ${String(never)}`);\n\t\t}\n\t}\n}\n","/**\n * Observable adapter wrapper — the \"inverted statistics\" surface.\n *\n * The library emits structured facts (token counts, latency, timestamps)\n * as reactive nodes. Users compose interpretation (pricing, dashboards,\n * telemetry, budget breakers) as derived layers on top.\n */\n\nimport { monotonicNs, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { keepalive, type ReactiveLogBundle, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport {\n\tadapterWrapper,\n\tadaptInvokeResult,\n\tbuildCallStats,\n\temptyUsageStub,\n\twithLayer,\n} from \"../_internal/wrappers.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n} from \"./types.js\";\nimport { sumInputTokens, sumOutputTokens } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// CallStatsEvent\n// ---------------------------------------------------------------------------\n\n/** One call's structured statistics — emitted after `invoke()` / `stream()` settles. */\nexport interface CallStatsEvent {\n\t/** `monotonicNs()` at call completion — use for event ordering. */\n\treadonly timestamp: number;\n\t/** `wallClockNs()` at call start — use for human-readable attribution. */\n\treadonly wallClock: number;\n\treadonly provider: string;\n\treadonly model: string;\n\treadonly tier?: string;\n\treadonly usage: TokenUsage;\n\treadonly latencyMs: number;\n\t/** `\"invoke\"` or `\"stream\"`. */\n\treadonly method: \"invoke\" | \"stream\";\n\t/** Populated when the call errored — usage may be zero or partial. */\n\treadonly error?: { readonly type: string; readonly message: string };\n}\n\n// ---------------------------------------------------------------------------\n// AdapterStats bundle\n// ---------------------------------------------------------------------------\n\nexport interface AdapterStats {\n\t/**\n\t * Reactive node for the most-recent call event. Emits `null` initially\n\t * (no calls yet); emits a {@link CallStatsEvent} after each call. Subscribe\n\t * and filter `!= null` if you want a `Node<CallStatsEvent>`.\n\t */\n\treadonly lastCall: Node<CallStatsEvent | null>;\n\t/** Full event log (bounded by `opts.logMax`, default 1000). */\n\treadonly allCalls: ReactiveLogBundle<CallStatsEvent>;\n\t/** Total calls observed since last reset. */\n\treadonly totalCalls: Node<number>;\n\t/** Sum of every input-token class across observed calls. */\n\treadonly totalInputTokens: Node<number>;\n\t/** Sum of every output-token class across observed calls. */\n\treadonly totalOutputTokens: Node<number>;\n\t/** Reset all counters + clear the log. */\n\treset(): void;\n\t/**\n\t * Release the internal keepalive subscriptions on the three counter\n\t * derives (`totalCalls` / `totalInputTokens` / `totalOutputTokens`) so the\n\t * bundle can be GC'd when the caller discards it. Idempotent. Long-lived\n\t * adapter bundles (module-level singletons) can ignore; transient bundles\n\t * (per-request / per-user) should call on teardown.\n\t */\n\tdispose(): void;\n}\n\n// ---------------------------------------------------------------------------\n// observableAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap any {@link LLMAdapter} with a reactive stats bundle.\n *\n * Implementation (Unit 10 B):\n * - `stats.lastCall` is a `state<CallStatsEvent | null>`.\n * - Counters (`totalCalls` / `totalInputTokens` / `totalOutputTokens`) are\n * **derived views** over `allCalls.entries` — self-maintaining, no manual\n * `.cache + 1 + emit` pattern, visible topology in `describe()`.\n * - `stats.allCalls` is a `reactiveLog<CallStatsEvent>` — bounded, supports\n * `tail(n)` / `slice(start, stop)` for dashboard views.\n * - The wrapped adapter passes DATA through via `adaptInvokeResult`, which\n * uses `onFirstData` internally to guard against re-subscription double-fire\n * and wires `.catch` for Promise-path error recording (Unit 10 A).\n */\nexport function observableAdapter(\n\tinner: LLMAdapter,\n\topts?: { logMax?: number; name?: string },\n): { adapter: LLMAdapter; stats: AdapterStats } {\n\tconst logMax = opts?.logMax ?? 1000;\n\tconst allCalls = reactiveLog<CallStatsEvent>(undefined, {\n\t\tname: opts?.name ? `${opts.name}/stats` : \"adapterStats\",\n\t\tmaxSize: logMax,\n\t});\n\n\tconst lastCall = node<CallStatsEvent | null>([], {\n\t\tname: \"adapterStats/lastCall\",\n\t\tinitial: null,\n\t});\n\n\t// Counters as derived views over the log — self-maintaining (Unit 10 B).\n\t// `initial` seeds them so late subscribers see 0 before any call lands.\n\tconst totalCalls = node<number>(\n\t\t[allCalls.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst entries = data[0] as readonly CallStatsEvent[];\n\t\t\tactions.emit(entries.length);\n\t\t},\n\t\t{ describeKind: \"derived\", name: \"adapterStats/totalCalls\", initial: 0 },\n\t);\n\tconst totalInputTokens = node<number>(\n\t\t[allCalls.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst entries = data[0] as readonly CallStatsEvent[];\n\t\t\tactions.emit(entries.reduce((acc, ev) => acc + sumInputTokens(ev.usage), 0));\n\t\t},\n\t\t{ describeKind: \"derived\", name: \"adapterStats/totalInputTokens\", initial: 0 },\n\t);\n\tconst totalOutputTokens = node<number>(\n\t\t[allCalls.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst entries = data[0] as readonly CallStatsEvent[];\n\t\t\tactions.emit(entries.reduce((acc, ev) => acc + sumOutputTokens(ev.usage), 0));\n\t\t},\n\t\t{ describeKind: \"derived\", name: \"adapterStats/totalOutputTokens\", initial: 0 },\n\t);\n\t// Keepalive — counters track the log whether or not an external subscriber\n\t// is attached, so `.cache` on the counters stays current. Captured as an\n\t// array so `AdapterStats.dispose()` can release them all.\n\tconst unsubKeepalives: Array<() => void> = [\n\t\tkeepalive(totalCalls),\n\t\tkeepalive(totalInputTokens),\n\t\tkeepalive(totalOutputTokens),\n\t];\n\n\tconst record = (ev: CallStatsEvent): void => {\n\t\tallCalls.append(ev);\n\t\tlastCall.emit(ev);\n\t};\n\n\tconst reset = (): void => {\n\t\tallCalls.clear();\n\t\tlastCall.emit(null);\n\t};\n\n\tconst wrap = adapterWrapper(inner, {\n\t\tinvoke(messages, invokeOpts) {\n\t\t\tconst startNs = monotonicNs();\n\t\t\tconst startWallClockNs = wallClockNs();\n\t\t\tconst model = inner.model ?? invokeOpts?.model ?? \"\";\n\t\t\tconst recordResp = (resp: LLMResponse): LLMResponse => {\n\t\t\t\trecord(\n\t\t\t\t\tbuildCallStats({\n\t\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? resp.model ?? \"\",\n\t\t\t\t\t\ttier: invokeOpts?.tier ?? resp.tier,\n\t\t\t\t\t\tusage: resp.usage ?? emptyUsageStub(),\n\t\t\t\t\t\tstartNs,\n\t\t\t\t\t\tstartWallClockNs,\n\t\t\t\t\t\tmethod: \"invoke\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn resp;\n\t\t\t};\n\t\t\tconst recordErr = (err: unknown): void => {\n\t\t\t\tconst e = err as Error | undefined;\n\t\t\t\trecord(\n\t\t\t\t\tbuildCallStats({\n\t\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\t\tusage: emptyUsageStub(),\n\t\t\t\t\t\tstartNs,\n\t\t\t\t\t\tstartWallClockNs,\n\t\t\t\t\t\tmethod: \"invoke\",\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: e?.name ?? \"Error\",\n\t\t\t\t\t\t\tmessage: e?.message ?? String(err),\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\treturn adaptInvokeResult(inner.invoke(messages, invokeOpts), {\n\t\t\t\tonResp: recordResp,\n\t\t\t\tonError: recordErr,\n\t\t\t\tname: \"adapterStats/invokeTap\",\n\t\t\t});\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts) {\n\t\t\tconst startNs = monotonicNs();\n\t\t\tconst startWallClockNs = wallClockNs();\n\t\t\tconst model = inner.model ?? invokeOpts?.model ?? \"\";\n\t\t\tlet finalUsage: TokenUsage | undefined;\n\t\t\ttry {\n\t\t\t\tfor await (const delta of inner.stream(messages, invokeOpts)) {\n\t\t\t\t\tif (delta.type === \"usage\") finalUsage = delta.usage;\n\t\t\t\t\tyield delta;\n\t\t\t\t}\n\t\t\t\trecord(\n\t\t\t\t\tbuildCallStats({\n\t\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\t\tusage: finalUsage ?? emptyUsageStub(),\n\t\t\t\t\t\tstartNs,\n\t\t\t\t\t\tstartWallClockNs,\n\t\t\t\t\t\tmethod: \"stream\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} catch (err) {\n\t\t\t\tconst e = err as Error | undefined;\n\t\t\t\trecord(\n\t\t\t\t\tbuildCallStats({\n\t\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\t\tusage: finalUsage ?? emptyUsageStub(),\n\t\t\t\t\t\tstartNs,\n\t\t\t\t\t\tstartWallClockNs,\n\t\t\t\t\t\tmethod: \"stream\",\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: e?.name ?? \"Error\",\n\t\t\t\t\t\t\tmessage: e?.message ?? String(err),\n\t\t\t\t\t\t},\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\t});\n\n\twithLayer(wrap, \"observableAdapter\", inner);\n\n\tlet disposed = false;\n\tconst dispose = (): void => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tfor (const fn of unsubKeepalives) fn();\n\t\tunsubKeepalives.length = 0;\n\t};\n\n\tconst stats: AdapterStats = {\n\t\tlastCall,\n\t\tallCalls,\n\t\ttotalCalls,\n\t\ttotalInputTokens,\n\t\ttotalOutputTokens,\n\t\treset,\n\t\tdispose,\n\t};\n\n\treturn { adapter: wrap, stats };\n}\n\nexport type { ChatMessage, LLMAdapter, LLMInvokeOptions, LLMResponse, StreamDelta, TokenUsage };\n","/**\n * Core types for LLM adapters (roadmap §9.3d).\n *\n * The library defines the shape of:\n * - Token usage (raw, disaggregated; user decides how to combine)\n * - Responses and streaming deltas\n * - The `LLMAdapter` protocol (reactive-friendly via `NodeInput`)\n * - Chat, tool, and invocation option shapes\n *\n * It ships **zero model data**. Pricing and capability registries are\n * user-populated (see `pricing.ts` and `capabilities.ts`).\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport type { NodeInput } from \"@graphrefly/pure-ts/extra\";\n\n// ---------------------------------------------------------------------------\n// Token usage — raw, disaggregated, extensible\n// ---------------------------------------------------------------------------\n\n/**\n * Input token classes.\n *\n * Every provider's native usage object maps into this shape without loss.\n * All fields except `regular` are optional — providers that don't expose\n * the class simply leave it undefined.\n */\nexport interface InputTokens {\n\t/** Uncached regular input tokens (cache miss or never-cached). */\n\tregular: number;\n\t/** Read from prompt cache (all TTLs — providers don't split reads by TTL today). */\n\tcacheRead?: number;\n\t/** Written to cache with 5-min TTL (Anthropic `ephemeral_5m_input_tokens`). */\n\tcacheWrite5m?: number;\n\t/** Written to cache with 1-hour TTL (Anthropic `ephemeral_1h_input_tokens`). */\n\tcacheWrite1h?: number;\n\t/** Written to cache with other/unspecified TTL (Gemini explicit caches). */\n\tcacheWriteOther?: number;\n\t/** Audio input tokens (OpenAI realtime, Gemini audio). */\n\taudio?: number;\n\t/** Image input tokens (Gemini per-modality). */\n\timage?: number;\n\t/** Video input tokens (Gemini per-modality). */\n\tvideo?: number;\n\t/** Tool-use result tokens fed back to the model (Gemini `toolUsePromptTokenCount`). */\n\ttoolUse?: number;\n\t/** Provider-specific classes not covered above. Open-ended by design. */\n\textensions?: Record<string, number>;\n}\n\n/** Output token classes. */\nexport interface OutputTokens {\n\t/** Regular generated output (non-reasoning, non-audio). */\n\tregular: number;\n\t/** Reasoning / thinking tokens (OpenAI o-series, Gemini thoughts, Grok reasoning). */\n\treasoning?: number;\n\t/** Audio output tokens. */\n\taudio?: number;\n\t/** Predicted-output tokens accepted (OpenAI predictions API). */\n\tpredictionAccepted?: number;\n\t/** Predicted-output tokens rejected (still billed at output rate). */\n\tpredictionRejected?: number;\n\textensions?: Record<string, number>;\n}\n\n/** Per-call token usage in canonical shape. No pricing, no interpretation. */\nexport interface TokenUsage {\n\tinput: InputTokens;\n\toutput: OutputTokens;\n\t/**\n\t * Per-call non-token costs (web-search requests, tool invocations, cache\n\t * storage-hours, etc.). Units are domain-specific — pricing functions\n\t * interpret them via `ModelPricing.auxiliary`.\n\t */\n\tauxiliary?: Record<string, number>;\n\t/**\n\t * Raw provider usage object, unmodified. Escape hatch for anything the\n\t * canonical shape doesn't model.\n\t */\n\traw?: unknown;\n}\n\n/** Sum of every input-token class. Helper for pricing + budget gating. */\nexport function sumInputTokens(u: TokenUsage): number {\n\tconst i = u.input;\n\tconst base =\n\t\ti.regular +\n\t\t(i.cacheRead ?? 0) +\n\t\t(i.cacheWrite5m ?? 0) +\n\t\t(i.cacheWrite1h ?? 0) +\n\t\t(i.cacheWriteOther ?? 0) +\n\t\t(i.audio ?? 0) +\n\t\t(i.image ?? 0) +\n\t\t(i.video ?? 0) +\n\t\t(i.toolUse ?? 0);\n\tif (!i.extensions) return base;\n\tlet ext = 0;\n\tfor (const v of Object.values(i.extensions)) ext += v;\n\treturn base + ext;\n}\n\n/** Sum of every output-token class. */\nexport function sumOutputTokens(u: TokenUsage): number {\n\tconst o = u.output;\n\tconst base =\n\t\to.regular +\n\t\t(o.reasoning ?? 0) +\n\t\t(o.audio ?? 0) +\n\t\t(o.predictionAccepted ?? 0) +\n\t\t(o.predictionRejected ?? 0);\n\tif (!o.extensions) return base;\n\tlet ext = 0;\n\tfor (const v of Object.values(o.extensions)) ext += v;\n\treturn base + ext;\n}\n\n/** Empty `TokenUsage` — useful as a default / starting point. */\nexport function emptyUsage(): TokenUsage {\n\treturn { input: { regular: 0 }, output: { regular: 0 } };\n}\n\n// ---------------------------------------------------------------------------\n// Chat message / tool types (single source of truth for the AI layer)\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/** 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\t/**\n\t * Handler invoked when the LLM requests this tool.\n\t *\n\t * The optional `opts.signal` fires when the reactive surface that owns\n\t * this invocation is torn down (e.g. the agent's `switchMap` over\n\t * `toolCalls` superseded with a fresh batch, the agent was aborted, or\n\t * the parent graph destroyed). Signal-aware handlers should thread it\n\t * into `fetch(url, {signal})`, child-process kill, DB cancel, etc., so\n\t * in-flight side effects actually stop. Handlers that ignore the\n\t * signal still work — but their work continues to completion regardless\n\t * of supersede.\n\t */\n\treadonly handler: (\n\t\targs: Record<string, unknown>,\n\t\topts?: { signal?: AbortSignal },\n\t) => NodeInput<unknown>;\n\t/**\n\t * V0 version of the backing node at tool-definition-creation time.\n\t * Snapshot — re-create the tool definition to refresh.\n\t */\n\treadonly version?: { id: string; version: number };\n};\n\n// ---------------------------------------------------------------------------\n// Response / streaming\n// ---------------------------------------------------------------------------\n\n/** The response from an LLM invocation. */\nexport interface LLMResponse {\n\treadonly content: string;\n\treadonly toolCalls?: readonly ToolCall[];\n\t/**\n\t * Token usage. Optional — provider adapters should always populate it, but\n\t * test mocks and adapter middlewares that synthesize responses can omit it.\n\t * Downstream consumers that compute cost should default to {@link emptyUsage}.\n\t */\n\treadonly usage?: TokenUsage;\n\treadonly finishReason?: string;\n\treadonly latencyMs?: number;\n\treadonly model?: string;\n\treadonly provider?: string;\n\t/** Service tier the call was served with (standard / batch / flex / priority). */\n\treadonly tier?: string;\n\treadonly metadata?: Record<string, unknown>;\n}\n\n/**\n * Adapter-facing incremental stream event.\n *\n * Provider adapters emit these; higher-level surfaces (`streamingPromptNode`,\n * `agentLoop`) assemble them into consumer-facing `StreamChunk` with their own\n * `source`/`accumulated`/`index` context.\n *\n * **Shape rationale — why object tagged-union vs. the framework `[TYPE, data]`\n * tuple?** `StreamDelta` is an *application-layer event payload* that flows\n * inside a single framework `DATA` message, one abstraction level above the\n * reactive protocol. The framework's `[Type, Data?]` tuple (DIRTY / DATA /\n * RESOLVED / COMPLETE / ERROR) is the protocol message form delivered through\n * `subscribe`. Using the protocol form here would force us to invent new\n * framework-level symbols (`TOKEN`, `USAGE`, etc.) that leak into user code,\n * and TypeScript discriminated-union exhaustiveness works much better with\n * objects than tuples. Object-tagged unions match the idiomatic JS/TS\n * convention for discriminated events (Redux actions, DOM events).\n */\nexport type StreamDelta =\n\t| { readonly type: \"token\"; readonly delta: string }\n\t| {\n\t\t\treadonly type: \"tool-call-delta\";\n\t\t\treadonly delta: {\n\t\t\t\treadonly id?: string;\n\t\t\t\treadonly name?: string;\n\t\t\t\treadonly argumentsDelta?: string;\n\t\t\t};\n\t }\n\t| { readonly type: \"thinking\"; readonly delta: string }\n\t| { readonly type: \"usage\"; readonly usage: TokenUsage }\n\t| { readonly type: \"finish\"; readonly reason: string };\n\n// ---------------------------------------------------------------------------\n// Invocation options\n// ---------------------------------------------------------------------------\n\n/** Options passed to `invoke()` / `stream()`. */\nexport interface LLMInvokeOptions {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Budget for reasoning/thinking tokens, if the model supports it. */\n\tmaxReasoningTokens?: number;\n\ttools?: readonly ToolDefinition[];\n\tsystemPrompt?: string;\n\t/** Hint the adapter to cache the prompt. TTL values depend on provider. */\n\tcacheHint?: { ttl?: \"5m\" | \"1h\" | string; minTokens?: number };\n\t/** Service tier: \"standard\" | \"batch\" | \"flex\" | \"priority\" | provider-custom. */\n\ttier?: string;\n\tsignal?: AbortSignal;\n\t/**\n\t * Provider-specific passthrough — merged into the native request body.\n\t * Escape hatch for features not yet in the canonical options.\n\t */\n\tproviderExtras?: Record<string, unknown>;\n\t/**\n\t * Open-ended per-call context threaded to cache / fallback key functions.\n\t * Callers who want to shard caches by tenant, session, feature flag, or\n\t * any other dimension populate this and supply a custom `keyFn` that\n\t * incorporates it. Not sent to providers — stripped from canonical key\n\t * hashing when no custom `keyFn` is supplied. Type is `unknown` to avoid\n\t * prescribing a shape; callers pick their own.\n\t */\n\tkeyContext?: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// LLMAdapter protocol\n// ---------------------------------------------------------------------------\n\n/**\n * Provider-agnostic LLM adapter (spec §5.10 compliant).\n *\n * - `invoke()` returns a `NodeInput<LLMResponse>` — the caller bridges to\n * reactive via `fromAny(...)`. Adapter implementations may return a\n * Promise (simplest), a Node (reactive), or a plain value (testing).\n * - `stream()` returns `AsyncIterable<StreamDelta>` — the terminal delta of\n * type `\"usage\"` carries the final `TokenUsage` for the streamed call.\n */\nexport interface LLMAdapter {\n\treadonly provider: string;\n\treadonly model?: string;\n\tinvoke(messages: readonly ChatMessage[], opts?: LLMInvokeOptions): NodeInput<LLMResponse>;\n\tstream(messages: readonly ChatMessage[], opts?: LLMInvokeOptions): AsyncIterable<StreamDelta>;\n\t/** Optional capability lookup; typically delegates to a `CapabilitiesRegistry`. */\n\tcapabilities?(model?: string): import(\"./capabilities.js\").ModelCapabilities | undefined;\n\t/**\n\t * DS-14.5 / AB-1 — honoring `opts.signal: AbortSignal` end-to-end is a\n\t * **hard adapter contract**, not an opt-in capability. Every adapter MUST\n\t * thread `opts.signal` into its underlying I/O (`fetch` request,\n\t * child-process kill, DB cancel) so a mid-call abort cancels the work and\n\t * surfaces as a rejection / thrown error. The prior optional\n\t * `abortCapable?: boolean` flag (Lock 3.C / QA D3) was removed pre-1.0:\n\t * the capability-flag escape hatch silently permitted token burn-through\n\t * past `valve`-close / `switchMap`-supersede / budget exhaustion. There is\n\t * no longer a flag to set and no dev-mode warning — abort just works.\n\t */\n}\n\n/** Discriminator for downstream type guards. */\nexport function isLLMAdapter(x: unknown): x is LLMAdapter {\n\tif (x == null || typeof x !== \"object\") return false;\n\tconst a = x as Partial<LLMAdapter>;\n\treturn (\n\t\ttypeof a.provider === \"string\" &&\n\t\ttypeof a.invoke === \"function\" &&\n\t\ttypeof a.stream === \"function\"\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Public re-export surface\n// ---------------------------------------------------------------------------\n\nexport type { Node, NodeInput };\n","/**\n * Pluggable pricing for LLM adapters.\n *\n * The library ships the **shape** (types + computation helpers + registry\n * factory) and **zero model data**. Users populate a `PricingRegistry` with\n * the prices for the models they use — either by hand, from a curated table,\n * or by importing a third-party dataset (litellm JSON, etc.).\n *\n * Pricing is a pure function of raw `TokenUsage`. The library does not\n * know current prices, regional rates, tier thresholds, or promotional\n * discounts — those are all user domain.\n */\n\nimport type { TokenUsage } from \"./types.js\";\nimport { sumInputTokens } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Rate shape\n// ---------------------------------------------------------------------------\n\n/**\n * A rate per 1M tokens. Supports threshold-based tiering (Anthropic\n * long-context >200K, Gemini >200K) via optional `thresholdTokens` +\n * `pricePerMillionAbove`.\n *\n * `total input tokens` (sum of every input class) is the axis the threshold\n * applies to — matches how Anthropic and Gemini measure it.\n */\nexport interface TieredRate {\n\tpricePerMillion: number;\n\tthresholdTokens?: number;\n\tpricePerMillionAbove?: number;\n}\n\n/** Shorthand: a plain `number` stands for `{pricePerMillion: n}`. */\nexport type Rate = TieredRate | number;\n\nfunction rateAt(rate: Rate | undefined, totalInput: number): number {\n\tif (rate == null) return 0;\n\tif (typeof rate === \"number\") return rate;\n\tif (\n\t\trate.thresholdTokens != null &&\n\t\trate.pricePerMillionAbove != null &&\n\t\ttotalInput > rate.thresholdTokens\n\t) {\n\t\treturn rate.pricePerMillionAbove;\n\t}\n\treturn rate.pricePerMillion;\n}\n\n// ---------------------------------------------------------------------------\n// ModelPricing\n// ---------------------------------------------------------------------------\n\n/** USD-per-1M rates per token class. All fields optional. */\nexport interface ModelPricing {\n\tinput?: {\n\t\tregular?: Rate;\n\t\tcacheRead?: Rate;\n\t\tcacheWrite5m?: Rate;\n\t\tcacheWrite1h?: Rate;\n\t\tcacheWriteOther?: Rate;\n\t\taudio?: Rate;\n\t\timage?: Rate;\n\t\tvideo?: Rate;\n\t\ttoolUse?: Rate;\n\t\textensions?: Record<string, Rate>;\n\t};\n\toutput?: {\n\t\tregular?: Rate;\n\t\treasoning?: Rate;\n\t\taudio?: Rate;\n\t\tpredictionAccepted?: Rate;\n\t\tpredictionRejected?: Rate;\n\t\textensions?: Record<string, Rate>;\n\t};\n\t/**\n\t * Per-unit costs for non-token axes. Values are USD per unit; units\n\t * match `TokenUsage.auxiliary` keys (e.g. `webSearchRequests`, `cacheStorageHours`).\n\t */\n\tauxiliary?: Record<string, number>;\n\t/**\n\t * Service-tier multipliers. Applied to the summed per-class price.\n\t * E.g. `{ batch: 0.5, flex: 0.5, priority: 1.25 }`. Default (no tier or\n\t * tier not present in the map): multiplier = 1.\n\t */\n\ttierMultipliers?: Record<string, number>;\n\t/** Currency code (ISO 4217). Defaults to \"USD\" when constructed via helpers. */\n\tcurrency: string;\n}\n\n// ---------------------------------------------------------------------------\n// Price breakdown\n// ---------------------------------------------------------------------------\n\n/** Result of computing a price from usage + pricing. */\nexport interface PriceBreakdown {\n\t/** Total charge in `currency`. */\n\ttotal: number;\n\tcurrency: string;\n\t/**\n\t * Optional per-class subtotals. Keys are dot-separated paths like\n\t * `\"input.regular\"`, `\"output.reasoning\"`, `\"auxiliary.webSearchRequests\"`.\n\t */\n\tbreakdown?: Record<string, number>;\n}\n\n/** Zero-charge breakdown — returned when no pricing is available for a model. */\nexport function zeroPrice(currency = \"USD\"): PriceBreakdown {\n\treturn { total: 0, currency };\n}\n\n// ---------------------------------------------------------------------------\n// computePrice — the math\n// ---------------------------------------------------------------------------\n\n/**\n * Compute price from a usage object + model pricing.\n *\n * - Tier-threshold math uses `sumInputTokens(usage)` as the axis.\n * - Service tier (`opts.tier`) multiplies the final total via `tierMultipliers`.\n * - Each token class is priced independently using the matching `Rate` lookup.\n * - `breakdown` is populated when `opts.withBreakdown = true` (default false\n * to keep hot-path allocations low).\n */\nexport function computePrice(\n\tusage: TokenUsage,\n\tpricing: ModelPricing,\n\topts?: { tier?: string; withBreakdown?: boolean },\n): PriceBreakdown {\n\tconst totalInput = sumInputTokens(usage);\n\tconst currency = pricing.currency ?? \"USD\";\n\tconst withBreakdown = opts?.withBreakdown === true;\n\tconst breakdown: Record<string, number> = withBreakdown ? {} : (null as never);\n\n\tlet total = 0;\n\n\tconst addLine = (key: string, tokens: number, rate: Rate | undefined): void => {\n\t\tif (!tokens || rate == null) return;\n\t\tconst rateUsd = rateAt(rate, totalInput);\n\t\tconst line = (tokens * rateUsd) / 1_000_000;\n\t\ttotal += line;\n\t\tif (withBreakdown) breakdown[key] = (breakdown[key] ?? 0) + line;\n\t};\n\n\t// Input classes\n\tconst i = usage.input;\n\tconst pi = pricing.input;\n\tif (pi) {\n\t\taddLine(\"input.regular\", i.regular, pi.regular);\n\t\taddLine(\"input.cacheRead\", i.cacheRead ?? 0, pi.cacheRead);\n\t\taddLine(\"input.cacheWrite5m\", i.cacheWrite5m ?? 0, pi.cacheWrite5m);\n\t\taddLine(\"input.cacheWrite1h\", i.cacheWrite1h ?? 0, pi.cacheWrite1h);\n\t\taddLine(\"input.cacheWriteOther\", i.cacheWriteOther ?? 0, pi.cacheWriteOther);\n\t\taddLine(\"input.audio\", i.audio ?? 0, pi.audio);\n\t\taddLine(\"input.image\", i.image ?? 0, pi.image);\n\t\taddLine(\"input.video\", i.video ?? 0, pi.video);\n\t\taddLine(\"input.toolUse\", i.toolUse ?? 0, pi.toolUse);\n\t\tif (i.extensions && pi.extensions) {\n\t\t\tfor (const [k, v] of Object.entries(i.extensions)) {\n\t\t\t\taddLine(`input.ext.${k}`, v, pi.extensions[k]);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Output classes\n\tconst o = usage.output;\n\tconst po = pricing.output;\n\tif (po) {\n\t\taddLine(\"output.regular\", o.regular, po.regular);\n\t\taddLine(\"output.reasoning\", o.reasoning ?? 0, po.reasoning);\n\t\taddLine(\"output.audio\", o.audio ?? 0, po.audio);\n\t\taddLine(\"output.predictionAccepted\", o.predictionAccepted ?? 0, po.predictionAccepted);\n\t\taddLine(\"output.predictionRejected\", o.predictionRejected ?? 0, po.predictionRejected);\n\t\tif (o.extensions && po.extensions) {\n\t\t\tfor (const [k, v] of Object.entries(o.extensions)) {\n\t\t\t\taddLine(`output.ext.${k}`, v, po.extensions[k]);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Service-tier multiplier applies to token costs only. Auxiliary costs\n\t// (per-request web-search fees, cache storage-hours, etc.) are typically\n\t// priced flat regardless of tier — e.g., Anthropic batch discount applies\n\t// to input/output tokens but NOT to web_search_requests. Apply the\n\t// multiplier to the token total before adding auxiliary lines.\n\tconst tier = opts?.tier;\n\tif (tier && pricing.tierMultipliers) {\n\t\tconst mult = pricing.tierMultipliers[tier];\n\t\tif (mult != null) {\n\t\t\ttotal *= mult;\n\t\t\tif (withBreakdown) {\n\t\t\t\tfor (const k of Object.keys(breakdown)) breakdown[k] *= mult;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Auxiliary (per-unit, not per-million; not tier-multiplied)\n\tconst aux = usage.auxiliary;\n\tconst paux = pricing.auxiliary;\n\tif (aux && paux) {\n\t\tfor (const [k, units] of Object.entries(aux)) {\n\t\t\tconst rate = paux[k];\n\t\t\tif (rate == null || !units) continue;\n\t\t\tconst line = units * rate;\n\t\t\ttotal += line;\n\t\t\tif (withBreakdown) breakdown[`auxiliary.${k}`] = line;\n\t\t}\n\t}\n\n\treturn withBreakdown ? { total, currency, breakdown } : { total, currency };\n}\n\n// ---------------------------------------------------------------------------\n// PricingFn\n// ---------------------------------------------------------------------------\n\n/** Pure function: given usage + call context, produce a price. */\nexport type PricingFn = (\n\tusage: TokenUsage,\n\tctx: { model: string; provider: string; tier?: string; withBreakdown?: boolean },\n) => PriceBreakdown;\n\n// ---------------------------------------------------------------------------\n// PricingRegistry\n// ---------------------------------------------------------------------------\n\n/**\n * A keyed store of `ModelPricing`. Users populate it at app startup.\n * The library ships the factory and zero data.\n *\n * Keys are `(provider, model)` pairs. Lookup attempts exact match first,\n * then longest-prefix match on model (e.g. `\"claude-sonnet-4-6\"` matches a\n * stored `\"claude-sonnet-4-6\"` entry when looking up\n * `\"claude-sonnet-4-6-20260401\"`).\n *\n * **Prefix-match footgun:** a registered `\"gemini-1\"` will also match a\n * lookup for `\"gemini-1.5-pro\"` (since `\"gemini-1.5-pro\".startsWith(\"gemini-1\")`\n * is true). Longest-match tie-breaking mitigates most cases, but when\n * registering a short family-prefix alongside versioned descendants, make sure\n * the versioned entry is present — otherwise the family prefix wins. Best\n * practice: register exact versioned model ids; use short family aliases\n * sparingly and only when all version variants share one pricing schedule.\n */\nexport interface PricingRegistry {\n\tlookup(provider: string, model: string): ModelPricing | undefined;\n\tregister(provider: string, model: string, pricing: ModelPricing): void;\n\t/** Remove a model's entry; returns `true` if it existed. */\n\tremove(provider: string, model: string): boolean;\n\t/** Enumerate all entries (for debugging / dump). */\n\tentries(): IterableIterator<[string, string, ModelPricing]>;\n}\n\nfunction registryKey(provider: string, model: string): string {\n\treturn `${provider}::${model}`;\n}\n\n/** Create a fresh `PricingRegistry`. Optionally seed with entries. */\nexport function createPricingRegistry(\n\tinitial?: ReadonlyArray<readonly [provider: string, model: string, pricing: ModelPricing]>,\n): PricingRegistry {\n\tconst map = new Map<string, { provider: string; model: string; pricing: ModelPricing }>();\n\tconst indexByProvider = new Map<string, Set<string>>();\n\n\tconst register = (provider: string, model: string, pricing: ModelPricing): void => {\n\t\tmap.set(registryKey(provider, model), { provider, model, pricing });\n\t\tlet models = indexByProvider.get(provider);\n\t\tif (!models) {\n\t\t\tmodels = new Set();\n\t\t\tindexByProvider.set(provider, models);\n\t\t}\n\t\tmodels.add(model);\n\t};\n\n\tif (initial) {\n\t\tfor (const [p, m, pricing] of initial) register(p, m, pricing);\n\t}\n\n\treturn {\n\t\tregister,\n\t\tlookup(provider, model) {\n\t\t\tconst exact = map.get(registryKey(provider, model));\n\t\t\tif (exact) return exact.pricing;\n\t\t\t// Prefix fallback within provider.\n\t\t\tconst models = indexByProvider.get(provider);\n\t\t\tif (!models) return undefined;\n\t\t\t// Pick the longest prefix match for stability.\n\t\t\tlet best: { key: string; pricing: ModelPricing } | undefined;\n\t\t\tfor (const candidate of models) {\n\t\t\t\tif (model.startsWith(candidate)) {\n\t\t\t\t\tif (!best || candidate.length > best.key.length) {\n\t\t\t\t\t\tconst entry = map.get(registryKey(provider, candidate));\n\t\t\t\t\t\tif (entry) best = { key: candidate, pricing: entry.pricing };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn best?.pricing;\n\t\t},\n\t\tremove(provider, model) {\n\t\t\tconst existed = map.delete(registryKey(provider, model));\n\t\t\tif (existed) {\n\t\t\t\tconst models = indexByProvider.get(provider);\n\t\t\t\tmodels?.delete(model);\n\t\t\t\tif (models && models.size === 0) indexByProvider.delete(provider);\n\t\t\t}\n\t\t\treturn existed;\n\t\t},\n\t\tentries(): IterableIterator<[string, string, ModelPricing]> {\n\t\t\tconst iter = map.values();\n\t\t\treturn (function* () {\n\t\t\t\tfor (const { provider, model, pricing } of iter) {\n\t\t\t\t\tyield [provider, model, pricing];\n\t\t\t\t}\n\t\t\t})();\n\t\t},\n\t};\n}\n\n/**\n * Build a `PricingFn` from a `PricingRegistry`. If no entry matches, returns\n * `{ total: 0, currency: \"USD\" }` (never throws). Callers who need \"unknown\n * model\" failures can compose their own `PricingFn`.\n */\nexport function registryPricing(registry: PricingRegistry, defaultCurrency = \"USD\"): PricingFn {\n\treturn (usage, ctx) => {\n\t\tconst pricing = registry.lookup(ctx.provider, ctx.model);\n\t\tif (!pricing) return zeroPrice(defaultCurrency);\n\t\treturn computePrice(usage, pricing, { tier: ctx.tier, withBreakdown: ctx.withBreakdown });\n\t};\n}\n\n/** Compose multiple `PricingFn`s — first non-zero wins. Useful for registry layering. */\nexport function composePricing(...fns: readonly PricingFn[]): PricingFn {\n\treturn (usage, ctx) => {\n\t\tfor (const fn of fns) {\n\t\t\tconst p = fn(usage, ctx);\n\t\t\tif (p.total !== 0) return p;\n\t\t}\n\t\treturn fns.length > 0 ? fns[0](usage, ctx) : zeroPrice();\n\t};\n}\n\n/**\n * Convenience: compute a {@link PriceBreakdown} directly from a\n * {@link import(\"./capabilities.js\").ModelCapabilities} object + usage.\n *\n * When callers look up capabilities themselves (via\n * `capabilitiesRegistry.lookup(...)` or `adapter.capabilities?.(model)`),\n * this helper skips the pricing-registry round-trip and computes the price\n * from `capabilities.pricing` directly.\n *\n * Returns `zeroPrice()` when `capabilities.pricing` is undefined — never throws.\n *\n * @param capabilities - Model capabilities object (`capabilities.pricing` may be absent).\n * @param usage - Per-call usage to price.\n * @param opts - Pass-through to {@link computePrice}.\n *\n * @example\n * ```ts\n * const cap = registry.lookup(\"anthropic\", \"claude-sonnet-4-6\");\n * const price = pricingFor(cap, resp.usage, { tier: \"batch\", withBreakdown: true });\n * ```\n *\n * @category ai\n */\nexport function pricingFor(\n\tcapabilities: import(\"./capabilities.js\").ModelCapabilities | undefined,\n\tusage: TokenUsage,\n\topts?: { tier?: string; withBreakdown?: boolean },\n): PriceBreakdown {\n\tif (!capabilities?.pricing) return zeroPrice();\n\treturn computePrice(usage, capabilities.pricing, opts);\n}\n","/**\n * `withBreaker` — circuit-breaker middleware for LLM adapters.\n *\n * Reuses the library's existing `circuitBreaker` primitive from\n * `extra/resilience.ts`. When the breaker is open, calls throw\n * `CircuitOpenError` instead of hitting the provider.\n */\n\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport {\n\ttype CircuitBreaker,\n\ttype CircuitBreakerOptions,\n\tCircuitOpenError,\n\tcircuitBreaker,\n} from \"../../../../utils/resilience/index.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type { LLMAdapter, LLMResponse, StreamDelta } from \"../core/types.js\";\n\nexport interface WithBreakerOptions extends CircuitBreakerOptions {\n\t/**\n\t * Optional external breaker — pass a shared instance to wire the same\n\t * breaker across multiple adapters (e.g. all tiers of a `cascadingLlmAdapter`).\n\t */\n\tbreaker?: CircuitBreaker;\n}\n\nexport function withLLMBreaker(\n\tinner: LLMAdapter,\n\topts: WithBreakerOptions = {},\n): { adapter: LLMAdapter; breaker: CircuitBreaker } {\n\tconst breaker = opts.breaker ?? circuitBreaker(opts);\n\n\tconst adapter: LLMAdapter = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tif (!breaker.canExecute()) throw new CircuitOpenError();\n\t\t\ttry {\n\t\t\t\tconst resp = await firstValueFrom(fromAny(inner.invoke(messages, invokeOpts)));\n\t\t\t\tbreaker.recordSuccess();\n\t\t\t\treturn resp;\n\t\t\t} catch (err) {\n\t\t\t\tbreaker.recordFailure(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (!breaker.canExecute()) throw new CircuitOpenError();\n\t\t\ttry {\n\t\t\t\tfor await (const d of inner.stream(messages, invokeOpts)) yield d;\n\t\t\t\tbreaker.recordSuccess();\n\t\t\t} catch (err) {\n\t\t\t\tbreaker.recordFailure(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t});\n\twithLayer(adapter, \"withLLMBreaker\", inner);\n\n\treturn { adapter, breaker };\n}\n\nexport { CircuitOpenError };\n","/**\n * Retry — re-attempt a node on terminal failure.\n *\n * Two modes selected by the type of `input`:\n * - **Source mode** (`Node<T>`): resubscribes the same node after each ERROR.\n * Upstream must be `resubscribable: true` or retries are silent no-ops.\n * - **Factory mode** (`() => Node<T>`): builds a fresh node per attempt.\n *\n * Shared with `circuitBreaker` / `rateLimiter`: `NodeOrValue<RetryOptions>`\n * lets callers swap retry config reactively (re-validates on each attempt).\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tfactoryTag,\n\ttype Message,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n\tResettableTimer,\n} from \"@graphrefly/pure-ts/core\";\nimport { coerceDelayNs, isNode, msgVal, type NodeOrValue, operatorOpts } from \"./_internal.js\";\nimport {\n\ttype BackoffPreset,\n\ttype BackoffStrategy,\n\tNS_PER_MS,\n\tresolveBackoffPreset,\n} from \"./backoff.js\";\nimport type { StatusValue } from \"./status.js\";\n\n/**\n * Lifecycle-shaped state companion emitted by {@link retry} (DS-13.5.B,\n * locked 2026-05-01). Tracks the retry state machine's current status,\n * the attempt counter, and the last scheduled delay (null before the\n * first retry).\n *\n * @category extra/resilience\n */\nexport interface RetryState {\n\tstatus: StatusValue;\n\tattempt: number;\n\tlastDelay_ns: number | null;\n}\n\n/**\n * Bundle returned by {@link retry}: the retry-wrapped output node and its\n * lifecycle state companion. Pre-1.0 break vs the prior `Node<T>` return.\n *\n * **Single-subscriber / pipeline-only contract (DS-13.5.B QA, N1, 2026-05-03).**\n * The `retryState` companion is allocated once at factory time and shared\n * across all subscribers to `node`. With one subscriber (the typical use\n * case — wire `node` into your downstream chain, optionally observe\n * `retryState` separately) the companion reflects a coherent timeline.\n * With **two or more subscribers** to `node`, each subscriber re-runs the\n * producer body and writes into the same `retryState`, including\n * `publish(\"pending\")` resets that can clobber an in-flight machine's\n * `running`/`paused` state. Don't fan out `node` to multiple subscribers\n * and rely on `retryState` accuracy unless you use\n * {@link keepalive} / `share`-style consolidation.\n *\n * @category extra/resilience\n */\nexport interface RetryBundle<T> {\n\tnode: Node<T>;\n\tretryState: Node<RetryState>;\n}\n\nexport type RetryOptions = {\n\t/**\n\t * Max retry attempts after each terminal `ERROR` (not counting the first failure).\n\t *\n\t * **Required when `backoff` is set.** Pass `Infinity` to opt in to unbounded retries\n\t * — the explicit value rules out the silent-infinite-budget footgun (a flaky provider\n\t * + exponential backoff + omitted `count` would previously default to ~2.1B retries).\n\t */\n\tcount?: number;\n\t/** Delay between attempts; strategies use **nanoseconds**. */\n\tbackoff?: BackoffStrategy | BackoffPreset;\n\t/**\n\t * Caller-supplied metadata merged into the produced node's `meta` (Tier 5.2\n\t * D8 widening). Use {@link domainMeta} to tag the layer for `describe()`\n\t * grouping. The primitive's `factoryTag(\"retry\", …)` always wins against\n\t * caller keys.\n\t */\n\tmeta?: Record<string, unknown>;\n};\n\n/** Factory-mode-only options. `initial` seeds the outer node's cache before the first attempt. */\nexport type RetryFactoryOptions<T> = RetryOptions & {\n\t/** Initial cache value for the outer node before the factory runs the first time. */\n\tinitial?: T;\n};\n\n/**\n * Resolved retry config shared by source-mode and factory-mode wrappers.\n * Centralises the unbounded-retry footgun guard and strategy resolution.\n */\ntype ResolvedRetryConfig = {\n\tmaxRetries: number;\n\tstrategy: BackoffStrategy | null;\n};\n\nfunction resolveRetryConfig(opts?: RetryOptions): ResolvedRetryConfig {\n\tconst count = opts?.count;\n\tconst backoffOpt = opts?.backoff;\n\n\t// Unbounded-retry footgun fix: if `backoff` is set without explicit `count`,\n\t// throw at construction time. Caller must opt in to `Infinity` for unbounded.\n\tif (backoffOpt !== undefined && count === undefined) {\n\t\tthrow new RangeError(\n\t\t\t\"retry({ backoff }) requires explicit count to prevent unbounded retries; pass { count: <n>, backoff: ... }\",\n\t\t);\n\t}\n\n\tconst maxRetries = count !== undefined ? count : 0;\n\tif (maxRetries < 0) throw new RangeError(\"retry count must be >= 0\");\n\n\tconst strategy: BackoffStrategy | null =\n\t\tbackoffOpt === undefined\n\t\t\t? null\n\t\t\t: typeof backoffOpt === \"string\"\n\t\t\t\t? resolveBackoffPreset(backoffOpt)\n\t\t\t\t: backoffOpt;\n\n\treturn { maxRetries, strategy };\n}\n\nfunction retryFactoryArgs(opts?: RetryOptions): Record<string, unknown> | undefined {\n\tconst args: Record<string, unknown> = {};\n\tif (opts?.count !== undefined) args.count = opts.count;\n\tif (typeof opts?.backoff === \"string\") args.backoff = opts.backoff;\n\treturn Object.keys(args).length > 0 ? args : undefined;\n}\n\n/**\n * Shared retry state machine. Both `_retrySource` and `_retryFactory` thin-wrap this:\n * the only per-mode logic is supplied via `acquireSource` (returns a fresh `Node<T>`\n * per attempt — for source-mode it just returns the captured `Node`; for factory-mode\n * it calls the user factory and forwards synchronous throws into the same retry path).\n *\n * **Reactive cfg (Tier 6.5 3.2.2, 2026-04-29).** `getCfg` is invoked at\n * every decision point (`scheduleRetryOrFinish` count + strategy reads)\n * so option swaps mid-flight take effect at the next attempt boundary\n * per the locked semantic rule: \"next attempt fails immediately if\n * already exhausted under new count; `backoff` swap takes effect at next\n * retry's delay calculation.\"\n */\nfunction _runRetryStateMachine<T>(\n\tgetCfg: () => ResolvedRetryConfig,\n\tacquireSource: () => Node<T>,\n\ta: { emit: (v: T) => void; down: (msgs: Message[]) => void },\n\temitState?: (next: RetryState) => void,\n): () => void {\n\tlet attempt = 0;\n\tlet stopped = false;\n\tlet prevDelay: number | null = null;\n\tlet unsub: (() => void) | undefined;\n\tconst timer = new ResettableTimer();\n\tconst publish = (status: StatusValue): void => {\n\t\temitState?.({ status, attempt, lastDelay_ns: prevDelay });\n\t};\n\tpublish(\"pending\");\n\n\tfunction disconnectUpstream(): void {\n\t\tunsub?.();\n\t\tunsub = undefined;\n\t}\n\n\tfunction scheduleRetryOrFinish(err: unknown): void {\n\t\tif (stopped) return;\n\t\tconst cfg = getCfg();\n\t\tif (attempt >= cfg.maxRetries) {\n\t\t\tdisconnectUpstream();\n\t\t\tpublish(\"errored\");\n\t\t\ta.down([[ERROR, err]]);\n\t\t\treturn;\n\t\t}\n\t\tconst raw = cfg.strategy === null ? 0 : cfg.strategy(attempt, err, prevDelay);\n\t\t// null from strategy = \"stop retrying\" (e.g. withMaxAttempts cap reached)\n\t\tif (raw === null || raw === undefined) {\n\t\t\tdisconnectUpstream();\n\t\t\tpublish(\"errored\");\n\t\t\ta.down([[ERROR, err]]);\n\t\t\treturn;\n\t\t}\n\t\t// A misbehaving strategy (returns NaN / non-finite / negative) MUST NOT\n\t\t// escape into the upstream drain. Treat it like `strategy === null`\n\t\t// (stop retrying) and emit the original error — the strategy bug is a\n\t\t// separate concern the user can inspect via the emitted error's stack.\n\t\tlet delayNs: number;\n\t\ttry {\n\t\t\tdelayNs = coerceDelayNs(raw);\n\t\t} catch {\n\t\t\tdisconnectUpstream();\n\t\t\tpublish(\"errored\");\n\t\t\ta.down([[ERROR, err]]);\n\t\t\treturn;\n\t\t}\n\t\tprevDelay = delayNs;\n\t\tattempt += 1;\n\t\tdisconnectUpstream();\n\t\tpublish(\"paused\");\n\t\t// `Math.max(1, …)` floor: every backoff schedule floors at 1ms even when\n\t\t// the strategy returns 0ns. Avoids 0-delay re-entrancy on the active\n\t\t// stack frame (which would risk stack overflow on a tight ERROR loop).\n\t\tconst delayMs = delayNs > 0 ? delayNs / NS_PER_MS : 1;\n\t\t// §5.10: setTimeout (not fromTimer) — retry delay needs clearTimeout/setTimeout;\n\t\t// fromTimer creates a new Node per reset, adding lifecycle overhead per retry.\n\t\ttimer.start(delayMs, () => {\n\t\t\tif (stopped) return;\n\t\t\tconnect();\n\t\t});\n\t}\n\n\tfunction connect(): void {\n\t\ttimer.cancel();\n\t\tdisconnectUpstream();\n\t\tlet src: Node<T>;\n\t\ttry {\n\t\t\tsrc = acquireSource();\n\t\t} catch (err) {\n\t\t\tscheduleRetryOrFinish(err);\n\t\t\treturn;\n\t\t}\n\t\tpublish(\"running\");\n\t\tunsub = src.subscribe((msgs) => {\n\t\t\tif (stopped) return;\n\t\t\tfor (const m of msgs) {\n\t\t\t\tconst t = m[0];\n\t\t\t\tif (t === DIRTY) a.down([[DIRTY]]);\n\t\t\t\telse if (t === DATA) {\n\t\t\t\t\tattempt = 0;\n\t\t\t\t\tprevDelay = null;\n\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\tpublish(\"running\");\n\t\t\t\t} else if (t === RESOLVED) a.down([[RESOLVED]]);\n\t\t\t\telse if (t === COMPLETE) {\n\t\t\t\t\t// DF2 (2026-04-29): set `stopped = true` BEFORE\n\t\t\t\t\t// `disconnectUpstream()` so a re-entrant ERROR delivered\n\t\t\t\t\t// in the same wave (after disconnect runs but before the\n\t\t\t\t\t// teardown closure fires `stopped = true`) hits the\n\t\t\t\t\t// `if (stopped) return` guard at line 159 and cannot\n\t\t\t\t\t// schedule a new retry timer.\n\t\t\t\t\tstopped = true;\n\t\t\t\t\tdisconnectUpstream();\n\t\t\t\t\tpublish(\"completed\");\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\tscheduleRetryOrFinish(msgVal(m));\n\t\t\t\t\treturn;\n\t\t\t\t} else a.down([m]);\n\t\t\t}\n\t\t});\n\t}\n\n\tconnect();\n\n\treturn () => {\n\t\tconst wasStopped = stopped;\n\t\tstopped = true;\n\t\ttimer.cancel();\n\t\tdisconnectUpstream();\n\t\tif (!wasStopped) publish(\"cancelled\");\n\t};\n}\n\n/**\n * Retry operator — two modes selected by the type of `input`:\n *\n * **Source mode** (`input: Node<T>`): resubscribes to the same node after each terminal\n * `ERROR`. The upstream should use `resubscribable: true` if it must emit again after `ERROR`.\n *\n * **Factory mode** (`input: () => Node<T>`): invokes the factory to build a fresh `Node<T>`\n * on every connect / reconnect. Ideal for producers that capture per-attempt resources\n * (sockets, clients, file handles) that become unusable after an error. Synchronous\n * exceptions thrown by the factory are treated as terminal ERROR and run through the\n * same retry pipeline as inner-node ERROR.\n *\n * @param input - Upstream node or factory that returns a fresh node per attempt.\n * @param opts - `count` caps attempts (**required when `backoff` is set**; pass `Infinity` to opt in to unbounded); `backoff` supplies delay in **nanoseconds** (or a preset name); `initial` seeds the outer node cache (factory mode only).\n * @returns Node that retries on error.\n *\n * @throws {RangeError} when `backoff` is provided without an explicit `count` (unbounded-retry footgun guard) or when `count < 0`.\n *\n * @remarks\n * **Protocol:** Forwards unknown message tuples unchanged; handles `DIRTY`, `DATA`, `RESOLVED`, `COMPLETE`, `ERROR`.\n *\n * **Backoff floor:** every scheduled delay is floored at 1ms via `Math.max(1, delayNs / NS_PER_MS)` even when the strategy returns 0ns. This avoids 0-delay re-entrancy on the active stack frame on a tight ERROR loop. Strategies that return `null`/`undefined` stop retrying immediately and forward the original error.\n *\n * @example\n * ```ts\n * // Source mode — resubscribe the same node:\n * import { ERROR, NS_PER_SEC, producer, retry, constant } from \"@graphrefly/graphrefly-ts\";\n *\n * const src = producer(\n * (a) => { a.down([[ERROR, new Error(\"x\")]]); },\n * { resubscribable: true },\n * );\n * const out = retry(src, { count: 2, backoff: constant(0.25 * NS_PER_SEC) });\n *\n * // Factory mode — fresh node per attempt (e.g. reconnecting WebSocket):\n * import { NS_PER_SEC, exponential, retry, fromWebSocket } from \"@graphrefly/graphrefly-ts\";\n *\n * const connected$ = retry(\n * () => fromWebSocket(new WebSocket(\"wss://example/stream\")),\n * { count: 10, backoff: exponential({ baseNs: 1 * NS_PER_SEC }) },\n * );\n * ```\n *\n * @category extra\n */\nexport function retry<T>(input: Node<T>, opts?: NodeOrValue<RetryOptions>): RetryBundle<T>;\nexport function retry<T>(\n\tinput: () => Node<T>,\n\topts?: NodeOrValue<RetryFactoryOptions<T>>,\n): RetryBundle<T>;\nexport function retry<T>(\n\tinput: Node<T> | (() => Node<T>),\n\topts?: NodeOrValue<RetryOptions | RetryFactoryOptions<T>>,\n): RetryBundle<T> {\n\tconst retryState = node<RetryState>([], {\n\t\tname: \"retryState\",\n\t\tdescribeKind: \"state\",\n\t\tinitial: { status: \"pending\", attempt: 0, lastDelay_ns: null },\n\t\tequals: (a, b) =>\n\t\t\ta === b ||\n\t\t\t(a != null &&\n\t\t\t\tb != null &&\n\t\t\t\ttypeof a === \"object\" &&\n\t\t\t\ttypeof b === \"object\" &&\n\t\t\t\tJSON.stringify(a) === JSON.stringify(b)),\n\t});\n\tconst emit = (s: RetryState): void => {\n\t\tretryState.down([[DIRTY], [DATA, s]]);\n\t};\n\tif (typeof input === \"function\") {\n\t\treturn {\n\t\t\tnode: _retryFactory(input, opts as NodeOrValue<RetryFactoryOptions<T>> | undefined, emit),\n\t\t\tretryState,\n\t\t};\n\t}\n\treturn {\n\t\tnode: _retrySource(input, opts as NodeOrValue<RetryOptions> | undefined, emit),\n\t\tretryState,\n\t};\n}\n\n// DS-13.5.B helper: like `resolveReactiveOption` but shallow-merges each\n// reactive emit over the prior opts and treats empty `{}` as a no-op\n// (per the locked cross-cutting rule). Static-form arg returns the value\n// as-is and never subscribes.\nfunction makeMergedOptsMirror<R extends Record<string, unknown>>(\n\targ: NodeOrValue<R> | undefined,\n): { current: () => R | undefined; unsub: () => void } {\n\tif (arg === undefined) {\n\t\treturn { current: () => undefined, unsub: () => undefined };\n\t}\n\tif (!isNode(arg)) {\n\t\treturn { current: () => arg as R, unsub: () => undefined };\n\t}\n\tconst optsNode = arg as Node<R>;\n\tlet merged: R | undefined = (optsNode.cache as R | undefined) ?? undefined;\n\tconst unsub = optsNode.subscribe((msgs) => {\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] !== DATA) continue;\n\t\t\tconst next = m[1] as R | undefined;\n\t\t\tif (next == null || typeof next !== \"object\") continue;\n\t\t\tif (Object.keys(next).length === 0) continue; // empty {} no-op\n\t\t\tmerged = { ...(merged ?? ({} as R)), ...next } as R;\n\t\t}\n\t});\n\treturn { current: () => merged, unsub };\n}\n\n// DF6 (2026-04-29): once-per-source dedup for the source-mode-retry warn.\n// Mirrors the `_bumpCursorWarned` pattern in `extra/mutation/index.ts`.\nconst _retrySourceNonResubscribableWarned = new WeakSet<Node<unknown>>();\n\nfunction _retrySource<T>(\n\tsource: Node<T>,\n\topts?: NodeOrValue<RetryOptions>,\n\temitState?: (s: RetryState) => void,\n): Node<T> {\n\t// Source-mode retry re-subscribes to the SAME source node after each\n\t// terminal ERROR. If the upstream was constructed with the default\n\t// `resubscribable: false`, the second subscribe-after-terminal is a\n\t// silent no-op and retries effectively never re-deliver. Surface\n\t// once-per-source so misconfigurations fail loud without log spam.\n\tconst sourceWithFlag = source as unknown as { _resubscribable?: boolean };\n\tif (\n\t\tsourceWithFlag._resubscribable === false &&\n\t\t!_retrySourceNonResubscribableWarned.has(source)\n\t) {\n\t\t_retrySourceNonResubscribableWarned.add(source);\n\t\tconsole.warn(\n\t\t\t\"retry(source, opts): source-mode requires `resubscribable: true` on the upstream \" +\n\t\t\t\t\"node. Retries will be silent no-ops after the first ERROR. Either pass \" +\n\t\t\t\t\"`resubscribable: true` to the source factory, OR use factory-mode retry \" +\n\t\t\t\t\"`retry(() => buildSource(), opts)` so each attempt builds a fresh node.\",\n\t\t);\n\t}\n\tconst staticOpts = isNode(opts) ? undefined : (opts as RetryOptions | undefined);\n\t// Eager validation for static-form opts (preserves construction-time\n\t// \"backoff without count\" RangeError). Reactive-form opts re-validate\n\t// per `getCfg()` call inside the state machine.\n\tif (!isNode(opts)) resolveRetryConfig(staticOpts);\n\treturn node<T>(\n\t\t(_data, a) => {\n\t\t\tconst merged = makeMergedOptsMirror<RetryOptions>(opts);\n\t\t\tconst getCfg = (): ResolvedRetryConfig => resolveRetryConfig(merged.current());\n\t\t\tconst inner = _runRetryStateMachine(getCfg, () => source, a, emitState);\n\t\t\treturn () => {\n\t\t\t\tinner();\n\t\t\t\tmerged.unsub();\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(),\n\t\t\tinitial: source.cache,\n\t\t\tmeta: {\n\t\t\t\t...(staticOpts?.meta ?? {}),\n\t\t\t\t...factoryTag(\n\t\t\t\t\t\"retry\",\n\t\t\t\t\tisNode(opts) ? { reactiveOpts: true } : retryFactoryArgs(staticOpts),\n\t\t\t\t),\n\t\t\t},\n\t\t},\n\t);\n}\n\nfunction _retryFactory<T>(\n\tfactory: () => Node<T>,\n\topts?: NodeOrValue<RetryFactoryOptions<T>>,\n\temitState?: (s: RetryState) => void,\n): Node<T> {\n\tconst staticOpts = isNode(opts) ? undefined : (opts as RetryFactoryOptions<T> | undefined);\n\t// Eager validation for static-form opts (Tier 3.1 footgun preservation).\n\tif (!isNode(opts)) resolveRetryConfig(staticOpts);\n\treturn node<T>(\n\t\t(_data, a) => {\n\t\t\tconst merged = makeMergedOptsMirror<RetryFactoryOptions<T>>(opts);\n\t\t\tconst getCfg = (): ResolvedRetryConfig => resolveRetryConfig(merged.current());\n\t\t\tconst inner = _runRetryStateMachine(getCfg, factory, a, emitState);\n\t\t\treturn () => {\n\t\t\t\tinner();\n\t\t\t\tmerged.unsub();\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(),\n\t\t\tinitial: staticOpts?.initial as T | undefined,\n\t\t\tmeta: {\n\t\t\t\t...(staticOpts?.meta ?? {}),\n\t\t\t\t...factoryTag(\n\t\t\t\t\t\"retry\",\n\t\t\t\t\tisNode(opts) ? { reactiveOpts: true } : retryFactoryArgs(staticOpts),\n\t\t\t\t),\n\t\t\t},\n\t\t},\n\t);\n}\n","/**\n * Status wrapper — surface lifecycle state alongside output.\n *\n * `withStatus` mirrors a source `Node<T>` and produces companion `status` /\n * `error` reactive nodes for UI and meta-snapshot consumers.\n */\n\nimport {\n\tbatch,\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tfactoryTag,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport { msgVal, operatorOpts } from \"./_internal.js\";\n\n/**\n * Central lifecycle vocabulary for resilience primitives + `processManager`.\n *\n * **DS-13.5.B follow-on (2026-05-01).** Widened from\n * `\"pending\" | \"running\" | \"completed\" | \"errored\"` to add `\"cancelled\"`\n * (replaces `processManager`'s prior `\"compensated\"` semantics) and\n * `\"paused\"` (carried by `<Primitive>State` lifecycle-shaped companions\n * on `retry` / `circuitBreaker` / `rateLimiter`).\n *\n * Resilience primitives use this enum as the literal vocabulary inside\n * lifecycle-shaped state nodes; `withStatus` (legacy) only emits the\n * original four (pre-widening) — the cancelled / paused values are added\n * for downstream consumers that need richer lifecycle reporting.\n */\nexport type StatusValue = \"pending\" | \"running\" | \"completed\" | \"errored\" | \"cancelled\" | \"paused\";\n\nexport type WithStatusBundle<T> = {\n\tnode: Node<T>;\n\tstatus: Node<StatusValue>;\n\terror: Node<unknown | null>;\n};\n\n/**\n * Wraps `src` with `status` and `error` {@link state} companions for UI or meta snapshots.\n *\n * @param src - Upstream node to mirror.\n * @param options - `initialStatus` defaults to `\"pending\"`.\n * @returns `{ node, status, error }` where `out` is the mirrored stream, `status` is a\n * reactive `Node<StatusValue>` (`\"pending\" | \"running\" | \"completed\" | \"errored\"`),\n * and `error` holds the last `ERROR` payload (cleared to `null` on the next `DATA`\n * after `errored`).\n *\n * @remarks\n * **Lifecycle:** `pending` (no DATA yet) → `running` (on first DATA) → `completed`\n * (on COMPLETE) or `errored` (on ERROR). After `errored`, the next `DATA` clears\n * `error` and re-enters `running` inside a {@link batch} so subscribers see one\n * consistent transition (matches graphrefly-py).\n *\n * **Producer-pattern visibility:** `out` is built via `node([], fn, …)`, so `src`\n * appears as the source dependency in `describe()` traversal but the `status` /\n * `error` companions are mirrored via subscribe-callback effects — they appear\n * under `out.meta.status` / `out.meta.error` (and as `<name>::__meta__::status`\n * paths in `describe()`) rather than as separate top-level edges. Subscribers\n * to `out` see the throttled DATA stream; `status` / `error` companions may not\n * appear as edges in `describe()` if no consumer subscribes to them (per\n * COMPOSITION-GUIDE §1, push-on-subscribe semantics).\n *\n * **Per-subscribe lifecycle (DF8, 2026-04-29 doc lock).** When the wrapped\n * source is `resubscribable: true` and multiple consumers attach in\n * sequence, each new subscription cycle re-runs the producer fn AND\n * re-emits the initial `pending` + `null` companion DATAs. Downstream\n * subscribers to the `status` / `error` companions see thrash:\n * `pending → running → completed → pending → running …`. This is the\n * intended fresh-cycle semantic (each subscription cycle reports its own\n * lifecycle); consumers that need a \"stable\" status across cycles should\n * derive a snapshot via a separate `state()` mirror rather than depending\n * on the per-cycle reset.\n *\n * @example\n * ```ts\n * import { withStatus, state } from \"@graphrefly/graphrefly-ts\";\n *\n * const src = state<number>(0);\n * const { node, status, error } = withStatus(src);\n *\n * status.subscribe((msgs) => console.log(\"status:\", msgs));\n * src.down([[DATA, 42]]); // status → \"running\"\n * ```\n *\n * @category extra\n */\nexport function withStatus<T>(\n\tsrc: Node<T>,\n\toptions?: { initialStatus?: StatusValue; meta?: Record<string, unknown> },\n): WithStatusBundle<T> {\n\tconst initialStatus = options?.initialStatus ?? \"pending\";\n\tconst callerMeta = options?.meta;\n\n\tconst out = node<T>(\n\t\t[],\n\t\t(_deps, a) => {\n\t\t\tlet currentStatus: StatusValue = initialStatus;\n\t\t\tout.meta.status.down([[DATA, initialStatus]]);\n\t\t\tout.meta.error.down([[DATA, null]]);\n\n\t\t\tconst unsub = src.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tconst t = m[0];\n\t\t\t\t\tif (t === DIRTY) a.down([[DIRTY]]);\n\t\t\t\t\telse if (t === DATA) {\n\t\t\t\t\t\tif (currentStatus === \"errored\") {\n\t\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\t\tout.meta.error.down([[DATA, null]]);\n\t\t\t\t\t\t\t\tout.meta.status.down([[DATA, \"running\"]]);\n\t\t\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tcurrentStatus = \"running\";\n\t\t\t\t\t\t} else if (currentStatus !== \"running\") {\n\t\t\t\t\t\t\t// First DATA after `pending` (or another non-running state):\n\t\t\t\t\t\t\t// flip status to \"running\" alongside the DATA emit so external\n\t\t\t\t\t\t\t// observers see one coherent wave (no torn reads between the\n\t\t\t\t\t\t\t// status companion and the mirrored stream).\n\t\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\t\tout.meta.status.down([[DATA, \"running\"]]);\n\t\t\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tcurrentStatus = \"running\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// A9 (QA fix 2026-05-01): already in \"running\" — skip the\n\t\t\t\t\t\t\t// redundant status emit that the previous code did on every\n\t\t\t\t\t\t\t// DATA. Saves a wave walk per DATA on hot streams (e.g. SSE\n\t\t\t\t\t\t\t// token streams through withStatus).\n\t\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (t === RESOLVED) a.down([[RESOLVED]]);\n\t\t\t\t\telse if (t === COMPLETE) {\n\t\t\t\t\t\tout.meta.status.down([[DATA, \"completed\"]]);\n\t\t\t\t\t\tcurrentStatus = \"completed\";\n\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\tconst err = msgVal(m);\n\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\tout.meta.error.down([[DATA, err]]);\n\t\t\t\t\t\t\tout.meta.status.down([[DATA, \"errored\"]]);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentStatus = \"errored\";\n\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t} else a.down([m]);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn unsub;\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(),\n\t\t\tmeta: {\n\t\t\t\t...(callerMeta ?? {}),\n\t\t\t\tstatus: initialStatus,\n\t\t\t\terror: null,\n\t\t\t\t...factoryTag(\"withStatus\", { initialStatus }),\n\t\t\t},\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t\tresubscribable: true,\n\t\t\tinitial: src.cache,\n\t\t},\n\t);\n\n\treturn {\n\t\tnode: out,\n\t\tstatus: out.meta.status as Node<StatusValue>,\n\t\terror: out.meta.error as Node<unknown | null>,\n\t};\n}\n","/**\n * Resilience utilities — roadmap §3.1 + §3.1c (retry, breaker, rate limit, status,\n * fallback, cache, timeout, budgetGate).\n *\n * This module is a thin barrel: domain-level primitives live in their own\n * sub-file (`breaker.ts`, `rate-limiter.ts`, `fallback.ts`, plus the\n * standalone `budget-gate.ts`). The zero-domain reactive operators\n * (`retry`, `withStatus`, `withTimeout`, backoff strategies, `NodeOrValue<T>`)\n * are base-layer — they live in `base/resilience/` and are re-surfaced here\n * so the resilience family ships through one barrel. The `resilientPipeline`\n * preset that composes these lives in `presets/resilience/`.\n */\n\n// Zero-domain reactive operators — base-layer, re-surfaced here so the\n// resilience family ships through one barrel.\nexport type { NodeOrValue } from \"../../base/resilience/_internal.js\";\nexport * from \"../../base/resilience/retry.js\";\nexport * from \"../../base/resilience/status.js\";\nexport * from \"../../base/resilience/timeout.js\";\nexport * from \"./breaker.js\";\n// budgetGate lives in its own file per Tier 2.2 (promoted from\n// patterns/reduction/) — re-export here so it ships through the barrel.\nexport {\n\ttype BudgetConstraint,\n\ttype BudgetConstraintSnapshot,\n\ttype BudgetGateBundle,\n\ttype BudgetGateOptions,\n\ttype BudgetGateState,\n\tbudgetGate,\n} from \"./budget-gate.js\";\nexport * from \"./fallback.js\";\nexport type { GateState } from \"./gate-state.js\";\nexport * from \"./rate-limiter.js\";\n","/**\n * Circuit breaker — open/half-open/closed state machine + companion bundle.\n *\n * - {@link circuitBreaker} returns a synchronous breaker handle (counters,\n * state machine, optional reactive-options subscription).\n * - {@link withBreaker} wraps a `Node<T>` and surfaces a reactive\n * `Node<CircuitState>` companion (`bundle.breakerState`) for telemetry.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tfactoryTag,\n\tmonotonicNs,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport {\n\tclampNonNegative,\n\tisNode,\n\tmsgVal,\n\ttype NodeOrValue,\n\toperatorOpts,\n} from \"../../base/resilience/_internal.js\";\nimport { type BackoffStrategy, NS_PER_SEC } from \"../../base/resilience/backoff.js\";\nimport type { GateState } from \"./gate-state.js\";\n\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\n/**\n * Lifecycle-shaped state companion emitted by {@link withBreaker}\n * (DS-13.5.B, locked 2026-05-01). Pre-1.0 break vs the prior\n * `Node<CircuitState>` (string-only) shape.\n *\n * `status` extends {@link GateState} with `\"half-open\"`. The numeric\n * fields surface the breaker's full internal state for telemetry and\n * `describe()` traversal.\n *\n * @category extra/resilience\n */\nexport interface BreakerState {\n\treadonly status: GateState | \"half-open\";\n\treadonly failureCount: number;\n\treadonly openCycle: number;\n\treadonly lastOpenedAtNs: number;\n\treadonly halfOpenAttempts: number;\n\treadonly lastCooldownNs: number;\n}\n\n/**\n * Thrown when {@link withBreaker} is configured with `onOpen: \"error\"` and the breaker rejects work.\n *\n * @category extra\n */\nexport class CircuitOpenError extends Error {\n\toverride name = \"CircuitOpenError\";\n\tconstructor() {\n\t\tsuper(\"Circuit breaker is open\");\n\t}\n}\n\nexport interface CircuitBreakerOptions {\n\t/** Number of consecutive failures before opening. Default: 5. */\n\tfailureThreshold?: number;\n\t/** Base cooldown in nanoseconds before transitioning to half-open. Default: 30s. */\n\tcooldownNs?: number;\n\t/** Backoff strategy for cooldown escalation across consecutive open cycles. Overrides `cooldownNs` when provided. */\n\tcooldown?: BackoffStrategy;\n\t/** Max trial requests allowed in half-open state. Default: 1. */\n\thalfOpenMax?: number;\n\t/**\n\t * Clock function returning **nanoseconds** with `monotonicNs()` semantics\n\t * (monotonically non-decreasing; suitable for elapsed-time arithmetic — never\n\t * use `Date.now()` because wall-clock skew can flip elapsed math negative).\n\t * Default: `monotonicNs` from `core/clock`. Override for deterministic tests.\n\t */\n\tnow?: () => number;\n}\n\nexport interface CircuitBreaker {\n\t/** Whether a request should be allowed through. Triggers open→half-open transition when cooldown expires. */\n\tcanExecute(): boolean;\n\t/** Record a successful execution. Resets to closed. */\n\trecordSuccess(): void;\n\t/** Record a failed execution. May transition to open. */\n\trecordFailure(error?: unknown): void;\n\t/**\n\t * Current circuit state (read-only, does not trigger transitions).\n\t *\n\t * **Telemetry:** wrap with {@link withBreaker} to surface this as a reactive\n\t * `Node<CircuitState>` companion (`bundle.breakerState`) — every state\n\t * transition (`closed`/`open`/`half-open`) emits to subscribers.\n\t */\n\treadonly state: CircuitState;\n\t/** Number of consecutive failures in the current closed period. */\n\treadonly failureCount: number;\n\t/** Manually reset to closed state, clearing all counters. */\n\treset(): void;\n\t/**\n\t * Release the reactive-options subscription (Tier 6.5 3.2.4, 2026-04-29).\n\t * No-op when constructed with static options. Call when retiring a\n\t * breaker whose options came from a `Node<CircuitBreakerOptions>` to\n\t * avoid leaking the option-Node subscription.\n\t */\n\tdispose(): void;\n}\n\n/**\n * Factory for a synchronous circuit breaker with `closed`, `open`, and `half-open` states.\n *\n * Supports escalating cooldown via an optional {@link BackoffStrategy} — each consecutive\n * open→half-open→open cycle increments the backoff attempt.\n *\n * @param options - Threshold, cooldown, half-open limit, and optional clock\n * override; OR a `Node<CircuitBreakerOptions>` carrying the same shape\n * reactively (Tier 6.5 3.2.4).\n * @returns {@link CircuitBreaker} instance.\n *\n * @remarks\n * **Timing:** Uses `monotonicNs()` by default (nanoseconds). Override `now` for tests.\n *\n * **Reactive options (locked semantics, Tier 6.5 3.2.4, 2026-04-29).**\n * When `options` is a `Node<CircuitBreakerOptions>`, the breaker\n * subscribes at construction and re-reads `failureThreshold` /\n * `cooldownNs` / `cooldown` / `halfOpenMax` / `now` on each DATA. **An\n * option swap RESETS the breaker to `\"closed\"`** with all counters\n * cleared — operators tuning a runaway breaker get a clean baseline.\n * If retaining failure history across re-tunings matters, derive a new\n * breaker per-tuning instead. Call `breaker.dispose()` when retiring to\n * release the option-Node subscription.\n *\n * @example\n * ```ts\n * import { circuitBreaker, exponential, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * const b = circuitBreaker({\n * failureThreshold: 3,\n * cooldown: exponential({ baseNs: 1 * NS_PER_SEC }),\n * });\n * ```\n *\n * @category extra\n */\nexport function circuitBreaker(options?: NodeOrValue<CircuitBreakerOptions>): CircuitBreaker {\n\tlet threshold = 5;\n\tlet baseCooldownNs = 30 * NS_PER_SEC;\n\tlet cooldownStrategy: BackoffStrategy | null = null;\n\tlet halfOpenMax = 1;\n\tlet now: () => number = monotonicNs;\n\n\tfunction applyOptions(o: CircuitBreakerOptions | undefined): void {\n\t\tthreshold = Math.max(1, o?.failureThreshold ?? 5);\n\t\tbaseCooldownNs = clampNonNegative(o?.cooldownNs ?? 30 * NS_PER_SEC);\n\t\tcooldownStrategy = o?.cooldown ?? null;\n\t\thalfOpenMax = Math.max(1, o?.halfOpenMax ?? 1);\n\t\tnow = o?.now ?? monotonicNs;\n\t}\n\n\tlet _state: CircuitState = \"closed\";\n\tlet _failureCount = 0;\n\tlet _openCycle = 0;\n\tlet _lastOpenedAt = 0;\n\tlet _lastCooldownNs = baseCooldownNs;\n\tlet _halfOpenAttempts = 0;\n\n\t// DS-13.5.B (locked 2026-05-01): reactive option swaps preserve\n\t// internal state — no reset across rebind. `now` is mode-locked at\n\t// construction (clock override is structural); a mid-flight `now`\n\t// change is logged and skipped (the prior `now` is preserved).\n\t// Empty `{}` emits are no-ops.\n\t//\n\t// QA A2 (2026-05-03): bad-`now` mid-flight does NOT throw — sync\n\t// throw inside a subscribe callback corrupts host scheduler state\n\t// (mirrors timeout's `actions.down([[ERROR]])` rationale; sink-side\n\t// throws break the wave's dispatch contract).\n\t//\n\t// QA A8 (2026-05-03): the push-on-subscribe re-delivery of the\n\t// cached opts fires the subscribe callback once at attach time with\n\t// the same value used for the eager `applyOptions(initialOpts)`\n\t// call above. Skip the first cached emit so opts are not re-applied\n\t// twice on construction.\n\tlet initialOpts: CircuitBreakerOptions | undefined;\n\tlet optsUnsub: (() => void) | undefined;\n\tif (isNode(options)) {\n\t\tconst optsNode = options as Node<CircuitBreakerOptions>;\n\t\tinitialOpts = optsNode.cache as CircuitBreakerOptions | undefined;\n\t\tapplyOptions(initialOpts);\n\t\tconst lockedNow = initialOpts?.now;\n\t\tconst hadInitialCache = initialOpts !== undefined;\n\t\tlet firstEmit = hadInitialCache;\n\t\toptsUnsub = optsNode.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tif (firstEmit) {\n\t\t\t\t\tfirstEmit = false;\n\t\t\t\t\tcontinue; // QA A8: skip push-on-subscribe replay of cached opts\n\t\t\t\t}\n\t\t\t\tconst next = m[1] as CircuitBreakerOptions | undefined;\n\t\t\t\tif (next == null || typeof next !== \"object\") continue;\n\t\t\t\tif (Object.keys(next).length === 0) continue; // empty {} no-op\n\t\t\t\tif (\"now\" in next && next.now !== lockedNow) {\n\t\t\t\t\t// QA A2: log + skip; do NOT throw inside a subscribe\n\t\t\t\t\t// callback — host scheduler corruption hazard.\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"circuitBreaker: ignoring mid-flight `now` change — clock override is mode-locked at construction. Prior `now` preserved.\",\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// State-preserving merge: only re-apply the axes that\n\t\t\t\t// changed; preserve `_state`, `_failureCount`, etc.\n\t\t\t\tconst merged: CircuitBreakerOptions = {\n\t\t\t\t\t...(initialOpts ?? {}),\n\t\t\t\t\t...next,\n\t\t\t\t\t...(lockedNow !== undefined ? { now: lockedNow } : {}),\n\t\t\t\t};\n\t\t\t\tapplyOptions(merged);\n\t\t\t\tinitialOpts = merged;\n\t\t\t}\n\t\t});\n\t} else {\n\t\tapplyOptions(options as CircuitBreakerOptions | undefined);\n\t}\n\t_lastCooldownNs = baseCooldownNs;\n\n\tfunction getCooldownNs(): number {\n\t\tif (!cooldownStrategy) return baseCooldownNs;\n\t\tconst delayNs = cooldownStrategy(_openCycle);\n\t\treturn delayNs !== null ? delayNs : baseCooldownNs;\n\t}\n\n\tfunction transitionToOpen(): void {\n\t\t_state = \"open\";\n\t\t_lastCooldownNs = getCooldownNs();\n\t\t_lastOpenedAt = now();\n\t\t_halfOpenAttempts = 0;\n\t}\n\n\tconst breaker: CircuitBreaker = {\n\t\tcanExecute(): boolean {\n\t\t\tif (_state === \"closed\") return true;\n\n\t\t\tif (_state === \"open\") {\n\t\t\t\tconst elapsed = now() - _lastOpenedAt;\n\t\t\t\tif (elapsed >= _lastCooldownNs) {\n\t\t\t\t\t_state = \"half-open\";\n\t\t\t\t\t_halfOpenAttempts = 1;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (_halfOpenAttempts < halfOpenMax) {\n\t\t\t\t_halfOpenAttempts++;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\n\t\trecordSuccess(): void {\n\t\t\tif (_state === \"half-open\") {\n\t\t\t\t_state = \"closed\";\n\t\t\t\t_failureCount = 0;\n\t\t\t\t_openCycle = 0;\n\t\t\t} else if (_state === \"closed\") {\n\t\t\t\t_failureCount = 0;\n\t\t\t}\n\t\t},\n\n\t\trecordFailure(_error?: unknown): void {\n\t\t\tif (_state === \"half-open\") {\n\t\t\t\t_openCycle++;\n\t\t\t\ttransitionToOpen();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (_state === \"closed\") {\n\t\t\t\t_failureCount++;\n\t\t\t\tif (_failureCount >= threshold) {\n\t\t\t\t\ttransitionToOpen();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tget state(): CircuitState {\n\t\t\treturn _state;\n\t\t},\n\n\t\tget failureCount(): number {\n\t\t\treturn _failureCount;\n\t\t},\n\n\t\treset(): void {\n\t\t\t_state = \"closed\";\n\t\t\t_failureCount = 0;\n\t\t\t_openCycle = 0;\n\t\t\t_halfOpenAttempts = 0;\n\t\t},\n\n\t\tdispose(): void {\n\t\t\toptsUnsub?.();\n\t\t},\n\n\t\t// Internal accessors used by withBreaker for the BreakerState\n\t\t// companion (DS-13.5.B). Not part of the public CircuitBreaker\n\t\t// interface but exposed for the bundle wiring.\n\t};\n\t(breaker as unknown as { _stateSnapshot: () => BreakerState })._stateSnapshot = () => ({\n\t\tstatus: _state,\n\t\tfailureCount: _failureCount,\n\t\topenCycle: _openCycle,\n\t\tlastOpenedAtNs: _lastOpenedAt,\n\t\thalfOpenAttempts: _halfOpenAttempts,\n\t\tlastCooldownNs: _lastCooldownNs,\n\t});\n\n\treturn breaker;\n}\n\nexport type WithBreakerBundle<T> = {\n\tnode: Node<T>;\n\tbreakerState: Node<BreakerState>;\n};\n\n/**\n * Returns a unary wrapper that gates upstream `DATA` through a {@link CircuitBreaker}.\n *\n * @param breaker - Shared breaker instance (typically one per resource).\n * @param options - `onOpen: \"skip\"` emits `RESOLVED` when open; `\"error\"` emits {@link CircuitOpenError}.\n * @returns Function mapping `Node<T>` to `{ node, breakerState }` companion nodes.\n *\n * @remarks\n * **Success path:** `COMPLETE` calls {@link CircuitBreaker.recordSuccess}. **Failure path:** upstream `ERROR` calls {@link CircuitBreaker.recordFailure} and is forwarded.\n *\n * **State telemetry:** `breakerState: Node<CircuitState>` is a reactive companion that mirrors `breaker.state` — every transition (`closed`/`open`/`half-open`) emits a `DATA`. Also accessible via `node.meta.breakerState` for `describe()` traversal.\n *\n * @example\n * ```ts\n * import { state, withBreaker, circuitBreaker } from \"@graphrefly/graphrefly-ts\";\n *\n * const b = circuitBreaker({ failureThreshold: 2 });\n * const s = state(1);\n * const { node, breakerState } = withBreaker(b)(s);\n * ```\n *\n * @category extra\n */\nexport function withBreaker<T>(\n\tbreaker: CircuitBreaker,\n\toptions?: { onOpen?: \"skip\" | \"error\"; meta?: Record<string, unknown> },\n): (source: Node<T>) => WithBreakerBundle<T> {\n\tconst onOpen = options?.onOpen ?? \"skip\";\n\tconst callerMeta = options?.meta;\n\n\treturn (source: Node<T>): WithBreakerBundle<T> => {\n\t\tconst snapshot = (breaker as unknown as { _stateSnapshot?: () => BreakerState })._stateSnapshot;\n\t\tconst initialSnapshot: BreakerState = snapshot\n\t\t\t? snapshot()\n\t\t\t: {\n\t\t\t\t\tstatus: breaker.state,\n\t\t\t\t\tfailureCount: breaker.failureCount,\n\t\t\t\t\topenCycle: 0,\n\t\t\t\t\tlastOpenedAtNs: 0,\n\t\t\t\t\thalfOpenAttempts: 0,\n\t\t\t\t\tlastCooldownNs: 0,\n\t\t\t\t};\n\t\tconst wrapped = node<T>(\n\t\t\t[],\n\t\t\t(_deps, a) => {\n\t\t\t\tfunction syncState(): void {\n\t\t\t\t\tconst s = snapshot\n\t\t\t\t\t\t? snapshot()\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tstatus: breaker.state,\n\t\t\t\t\t\t\t\tfailureCount: breaker.failureCount,\n\t\t\t\t\t\t\t\topenCycle: 0,\n\t\t\t\t\t\t\t\tlastOpenedAtNs: 0,\n\t\t\t\t\t\t\t\thalfOpenAttempts: 0,\n\t\t\t\t\t\t\t\tlastCooldownNs: 0,\n\t\t\t\t\t\t\t};\n\t\t\t\t\twrapped.meta.breakerState.down([[DIRTY], [DATA, s]]);\n\t\t\t\t}\n\n\t\t\t\tconst unsub = source.subscribe((msgs) => {\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\tif (t === DIRTY) a.down([[DIRTY]]);\n\t\t\t\t\t\telse if (t === DATA) {\n\t\t\t\t\t\t\tif (breaker.canExecute()) {\n\t\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t\t\tif (onOpen === \"error\") a.down([[ERROR, new CircuitOpenError()]]);\n\t\t\t\t\t\t\t\telse a.down([[RESOLVED]]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (t === RESOLVED) a.down([[RESOLVED]]);\n\t\t\t\t\t\telse if (t === COMPLETE) {\n\t\t\t\t\t\t\tbreaker.recordSuccess();\n\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\t\tbreaker.recordFailure(msgVal(m));\n\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t\t} else a.down([m]);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tsyncState();\n\t\t\t\treturn unsub;\n\t\t\t},\n\t\t\t{\n\t\t\t\t...operatorOpts(),\n\t\t\t\tmeta: {\n\t\t\t\t\t...(callerMeta ?? {}),\n\t\t\t\t\tbreakerState: initialSnapshot,\n\t\t\t\t\t...factoryTag(\"withBreaker\", { onOpen }),\n\t\t\t\t},\n\t\t\t\tcompleteWhenDepsComplete: false,\n\t\t\t\tinitial: source.cache,\n\t\t\t},\n\t\t);\n\n\t\treturn { node: wrapped, breakerState: wrapped.meta.breakerState as Node<BreakerState> };\n\t};\n}\n","/**\n * `budgetGate` — numeric-constraint flow gate (Tier 2.2 promotion from\n * `patterns/reduction/`).\n *\n * Lives alongside the other `extra/resilience/` flow controls (`retry`,\n * `circuitBreaker`, `rateLimiter`, `tokenBucket`, `fallback`, `withStatus`).\n *\n * @module\n */\n\nimport type { NodeActions } from \"@graphrefly/pure-ts/core\";\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\ttype Message,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n\tPAUSE,\n\tRESOLVED,\n\tRESUME,\n} from \"@graphrefly/pure-ts/core\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport type { GateState } from \"./gate-state.js\";\n\n/** A reactive constraint for {@link budgetGate}. */\nexport type BudgetConstraint<T = unknown> = {\n\t/** Constraint node whose value is checked. */\n\tnode: Node<T>;\n\t/** Returns `true` when the constraint is satisfied (budget available). */\n\tcheck: (value: T) => boolean;\n\t/**\n\t * Optional human-readable name for `BudgetGateState.constraintsSnapshot`.\n\t * Defaults to the constraint Node's `.name` (or `\"\"` when unset).\n\t */\n\tname?: string;\n};\n\n/** Options for {@link budgetGate}. */\nexport type BudgetGateOptions = Omit<NodeOptions<unknown>, \"describeKind\" | \"name\" | \"meta\"> & {\n\tmeta?: Record<string, unknown>;\n};\n\n/**\n * Per-constraint snapshot inside {@link BudgetGateState}. The `value` field is\n * typed as `unknown` because constraint values are generic — most callers\n * carry numeric budgets but the gate doesn't enforce that. Cast at the\n * subscriber site if you need a narrower type.\n *\n * @category extra/resilience\n */\nexport interface BudgetConstraintSnapshot {\n\treadonly name: string;\n\treadonly satisfied: boolean;\n\treadonly value: unknown;\n}\n\n/**\n * Lifecycle-shaped state companion emitted by {@link budgetGate} (DS-13.5.B,\n * locked 2026-05-01). `status` is `\"open\"` when every constraint's `check`\n * returns true; `\"closed\"` otherwise. The `constraintsSnapshot` array\n * preserves constraint ordering and reflects the most recent values seen\n * via per-constraint reactive updates.\n *\n * @category extra/resilience\n */\nexport interface BudgetGateState {\n\treadonly status: GateState;\n\treadonly constraintsSnapshot: ReadonlyArray<BudgetConstraintSnapshot>;\n}\n\n/**\n * Bundle returned by {@link budgetGate}: the gated output node and its\n * gate-state companion. Pre-1.0 break vs. the prior `Node<T>` return —\n * unwrap via `.node` for downstream wiring.\n *\n * @category extra/resilience\n */\nexport interface BudgetGateBundle<T> {\n\tnode: Node<T>;\n\tbudgetGateState: Node<BudgetGateState>;\n}\n\n/**\n * Unbounded head-index queue with O(1) `push` and O(1) `shift`.\n *\n * Distinct from {@link RingBuffer} (drop-oldest, fixed capacity) because\n * `budgetGate` MUST NOT silently drop buffered DATA when the gate is closed —\n * upstream is asked to PAUSE and the buffered items are guaranteed to flush\n * once the constraint relaxes (or on terminal force-flush). A drop-oldest\n * eviction would break that contract by losing items between PAUSE and\n * RESUME.\n *\n * Storage grows on demand and is compacted opportunistically: once the head\n * pointer crosses the midpoint of the underlying array, we slice the consumed\n * prefix away. Memory bound is **worst-case ~3× live size** (DF3, 2026-04-29\n * doc tighten — a queue that grows to N, drains to 0.6N, then re-pushes 0.4N\n * retains ~3× live size between compactions). Amortized footprint trends\n * lower under steady-state usage. Trade-off: keeps `push` and `shift` O(1) —\n * replacing the prior `buffer.slice(1)` per drain which was O(N²) over a\n * long-lived bucket (Tier 3.3.1 fix).\n */\nclass HeadIndexQueue<T> {\n\tprivate buf: T[] = [];\n\tprivate head = 0;\n\n\tget size(): number {\n\t\treturn this.buf.length - this.head;\n\t}\n\n\tpush(item: T): void {\n\t\tthis.buf.push(item);\n\t}\n\n\t/** O(1) — removes and returns the oldest item, or `undefined` when empty. */\n\tshift(): T | undefined {\n\t\tif (this.head >= this.buf.length) return undefined;\n\t\tconst item = this.buf[this.head]!;\n\t\t// Release the slot for GC. Cheaper than splice; cost folded into the\n\t\t// periodic compaction below.\n\t\t(this.buf as Array<T | undefined>)[this.head] = undefined;\n\t\tthis.head++;\n\t\t// Compact when more than half the array is consumed prefix.\n\t\tif (this.head > 32 && this.head * 2 > this.buf.length) {\n\t\t\tthis.buf = this.buf.slice(this.head);\n\t\t\tthis.head = 0;\n\t\t}\n\t\treturn item;\n\t}\n\n\tclear(): void {\n\t\tthis.buf = [];\n\t\tthis.head = 0;\n\t}\n}\n\n/**\n * Pass-through that respects reactive constraint nodes.\n *\n * DATA flows through when all constraints are satisfied. When any constraint\n * is exceeded, `PAUSE` is sent upstream and DATA is buffered in a FIFO queue.\n * When constraints relax, the queue drains in arrival order and `RESUME` is\n * sent upstream.\n *\n * ## Invariants (do not refactor without preserving)\n *\n * 1. **Terminal force-flush.** On `COMPLETE` / `ERROR` arriving from `source`,\n * every buffered item is emitted downstream BEFORE the terminal message is\n * forwarded. The constraint is intentionally bypassed for the flush — once\n * upstream is done, the caller must see the buffered work, not lose it.\n * See COMPOSITION-GUIDE §19 (terminal-emission operators).\n *\n * 2. **PAUSE-release ordering.** When a constraint flips from saturated →\n * released, the queue drains in FIFO order downstream BEFORE `RESUME` is\n * sent upstream. Reversing the order (RESUME-then-drain) would let new\n * upstream DATA interleave with the queue tail, breaking arrival-order\n * delivery. See COMPOSITION-GUIDE §9, §9a (diamond + batch coalescing).\n *\n * 3. **Deferred RESOLVED.** A `RESOLVED` from `source` while the queue is\n * non-empty is held until the queue drains, then forwarded — so downstream\n * sees `[buffered DATA…, RESOLVED]` in causal order rather than\n * `[RESOLVED, buffered DATA…]`.\n *\n * **Stall risk (qa D4):** if the constraint never relaxes AND no terminal\n * arrives from `source`, the deferred RESOLVED is held forever. Downstream\n * consumers that depend on `RESOLVED` for an `awaitSettled`-style\n * coordination wait stall in this case. PAUSE is sent upstream so source\n * backpressure stops further DATA, but the gate itself has no escape\n * hatch — by design (the producer-pattern is fire-and-forget; recovery\n * happens at the compositor level via timeout, retry, or cancellation).\n *\n * 4. **Constraint DIRTY suppression.** Constraint-node DIRTY does NOT\n * propagate downstream — only `source`-DIRTY does. The gate's downstream\n * semantics track `source`'s wave, not constraint waves.\n *\n * 5. **Lazy PAUSE (qa D3).** PAUSE is sent upstream ONLY when a `source` DATA\n * arrives that fails the constraint check (the first blocked item). A\n * constraint flipping closed BEFORE any source DATA arrives does NOT emit\n * a preemptive PAUSE — upstream may push DATA freely until the first\n * item is buffered. This matches the producer-pattern lazy-activation\n * philosophy (don't impose backpressure for hypothetical future blocks).\n * For eager-PAUSE semantics, wrap the gate in a compositor that watches\n * constraints + source independently.\n *\n * ## Queue\n *\n * The internal buffer is an unbounded {@link HeadIndexQueue} (O(1) push,\n * O(1) shift, opportunistic compaction). It does NOT use {@link RingBuffer}\n * because RingBuffer's drop-oldest eviction would silently lose buffered\n * items between PAUSE and RESUME. Backpressure (PAUSE) is the upstream\n * contract for bounding the queue, not capacity-driven eviction here.\n *\n * ## Producer-pattern: source edge is invisible to `describe()`\n *\n * `budgetGate` is constructed via `node([], fn)` and subscribes to `source`\n * and the constraint nodes manually inside its activation fn. Because no\n * dep is declared at construction, **`describe()` shows no edge from\n * `source` (or any constraint) into the returned node** — the gate looks\n * like a standalone leaf source. This is intentional (see COMPOSITION-GUIDE\n * §24 \"Edges are derived, not declared\"): if you want the constraint /\n * source dependency to appear in describe output, surface it at the\n * compositor level (e.g. annotate via `meta.ai.upstream`, or wrap the gate\n * in a parent factory that exposes the deps as constructor args).\n *\n * ## Reference equality + Tier 6.5 3.2.5 locked semantics\n *\n * **Constraint VALUES are reactive.** Each `BudgetConstraint.node` is\n * subscribed at activation; per-value changes flip the gate (re-evaluate\n * in the same wave) and trigger PAUSE/RESUME upstream. Per the locked\n * semantic rule for the reactive-options-widening batch (Tier 6.5 3.2.5,\n * 2026-04-29): \"constraints array re-evaluated immediately against\n * current source; adding/removing constraints triggers gate\n * re-evaluation in the same wave\" — the per-value half is shipped via\n * the existing constraint-Node subscription model.\n *\n * **The constraints ARRAY shape is static.** The factory captures the\n * `constraints` array reference and each `check` function at\n * construction; it does NOT diff subsequent arrays. To add or remove\n * constraints reactively, build the swap at the compositor level (a\n * `switchMap` rebuild over a constraint-shape Node), or construct a new\n * gate. Dynamic constraint-array reactivity is intentionally deferred —\n * the subscription churn (resub on every constraint add/remove) and\n * `latestValues` shape mutation overshoot the budget-gate's\n * fire-and-forget ergonomics.\n *\n * @param source - Input node.\n * @param constraints - Reactive constraint checks. MUST be non-empty.\n * @param opts - Optional node options.\n * @returns Gated node.\n *\n * @throws {RangeError} when `constraints.length === 0`. The gate has no\n * meaningful identity without at least one check — degenerate to plain\n * pass-through (e.g. via `derived([source], ([v]) => v)`) instead.\n *\n * @category resilience\n */\nexport function budgetGate<T>(\n\tsource: Node<T>,\n\tconstraints: ReadonlyArray<BudgetConstraint>,\n\topts?: BudgetGateOptions,\n): BudgetGateBundle<T> {\n\tif (constraints.length === 0) throw new RangeError(\"budgetGate requires at least one constraint\");\n\n\tconst constraintNodes = constraints.map((c) => c.node);\n\tconst allDeps = [source as Node, ...constraintNodes] as Node[];\n\n\tconst buffer = new HeadIndexQueue<T>();\n\tlet paused = false;\n\tlet pendingResolved = false;\n\tconst lockId = Symbol(\"budget-gate\");\n\n\t// Latest DATA from each constraint. Seeded at **activation time** (inside the\n\t// producer fn below) — a wiring-time boundary read, not a reactive-callback\n\t// read — so concurrent constraint updates between factory-time and\n\t// activation-time are reflected before `checkBudget()` first runs. The\n\t// subscribe handler updates this array on each constraint DATA message, so\n\t// `checkBudget` never reads `.cache` from inside a reactive callback.\n\tconst latestValues: unknown[] = new Array(constraints.length);\n\n\tfunction checkBudget(): boolean {\n\t\treturn constraints.every((c, i) => c.check(latestValues[i]));\n\t}\n\n\t// DS-13.5.B (locked 2026-05-01): lifecycle-shaped state companion.\n\t// Initialized with `status: \"closed\"` until activation seeds the values\n\t// and the first `checkBudget()` runs.\n\t//\n\t// QA A3 (2026-05-03): equality uses structural compare on\n\t// `(status, name, satisfied, value)` tuples via `Object.is` per\n\t// `value` — NOT `JSON.stringify`. Caller-supplied constraint values\n\t// (`unknown`) can be circular, BigInt, or otherwise non-serializable;\n\t// `JSON.stringify` would throw and corrupt the wave dispatch.\n\tfunction budgetGateStateEqual(a: BudgetGateState, b: BudgetGateState): boolean {\n\t\tif (a === b) return true;\n\t\tif (a.status !== b.status) return false;\n\t\tconst sa = a.constraintsSnapshot;\n\t\tconst sb = b.constraintsSnapshot;\n\t\tif (sa.length !== sb.length) return false;\n\t\tfor (let i = 0; i < sa.length; i++) {\n\t\t\tconst ai = sa[i];\n\t\t\tconst bi = sb[i];\n\t\t\tif (ai === undefined || bi === undefined) return false;\n\t\t\tif (ai.name !== bi.name) return false;\n\t\t\tif (ai.satisfied !== bi.satisfied) return false;\n\t\t\tif (!Object.is(ai.value, bi.value)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tconst budgetGateState = node<BudgetGateState>([], {\n\t\tname: \"budgetGateState\",\n\t\tdescribeKind: \"state\",\n\t\tinitial: {\n\t\t\tstatus: \"closed\",\n\t\t\tconstraintsSnapshot: constraints.map((c) => ({\n\t\t\t\tname: c.name ?? c.node.name ?? \"\",\n\t\t\t\tsatisfied: false,\n\t\t\t\tvalue: undefined,\n\t\t\t})),\n\t\t},\n\t\tequals: budgetGateStateEqual,\n\t});\n\n\tlet lastEmittedState: BudgetGateState | null = null;\n\n\tfunction publishState(): void {\n\t\tconst snapshot: BudgetConstraintSnapshot[] = constraints.map((c, i) => {\n\t\t\tconst v = latestValues[i];\n\t\t\tlet satisfied = false;\n\t\t\ttry {\n\t\t\t\tsatisfied = c.check(v as never);\n\t\t\t} catch (err) {\n\t\t\t\t// QA A3: log the bug-throw rather than silently mapping to\n\t\t\t\t// `satisfied=false`. The constraint's check function failing\n\t\t\t\t// is a programmer error — at minimum surface it to console.\n\t\t\t\tconsole.error(\n\t\t\t\t\t`budgetGate: constraint \"${c.name ?? c.node.name ?? `[${i}]`}\" check threw; treating as not satisfied.`,\n\t\t\t\t\terr,\n\t\t\t\t);\n\t\t\t\tsatisfied = false;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tname: c.name ?? c.node.name ?? \"\",\n\t\t\t\tsatisfied,\n\t\t\t\tvalue: v,\n\t\t\t};\n\t\t});\n\t\tconst status: GateState = snapshot.every((s) => s.satisfied) ? \"open\" : \"closed\";\n\t\tconst next: BudgetGateState = { status, constraintsSnapshot: snapshot };\n\t\tif (lastEmittedState != null && budgetGateStateEqual(lastEmittedState, next)) {\n\t\t\treturn;\n\t\t}\n\t\tlastEmittedState = next;\n\t\tbudgetGateState.down([[DIRTY], [DATA, next]]);\n\t}\n\n\tfunction flushBuffer(actions: NodeActions): void {\n\t\t// FIFO drain — invariant 2 (PAUSE-release ordering). Stop early if a\n\t\t// later constraint check flips false mid-drain (the queue's tail stays\n\t\t// buffered for the next RESUME).\n\t\twhile (buffer.size > 0 && checkBudget()) {\n\t\t\tconst item = buffer.shift()!;\n\t\t\tactions.emit(item);\n\t\t}\n\t\t// Drain deferred RESOLVED once buffer is empty (invariant 3).\n\t\tif (buffer.size === 0 && pendingResolved) {\n\t\t\tpendingResolved = false;\n\t\t\tactions.down([[RESOLVED]]);\n\t\t}\n\t}\n\n\t// Producer pattern: manually subscribe to all deps for per-message interception.\n\t// Source / constraint edges are intentionally NOT declared as `_deps` — see\n\t// the JSDoc \"Producer-pattern\" section above and COMPOSITION-GUIDE §24.\n\tconst out = node<T>(\n\t\t[],\n\t\t(_data, gateActions) => {\n\t\t\t// Seed `latestValues` at activation (not factory time) so any constraint\n\t\t\t// updates between factory return and first subscribe are captured before\n\t\t\t// source's push-on-subscribe fires `checkBudget()`.\n\t\t\tfor (let i = 0; i < constraints.length; i++) {\n\t\t\t\tlatestValues[i] = constraints[i]!.node.cache;\n\t\t\t}\n\t\t\t// Seed the companion state at activation as well.\n\t\t\tpublishState();\n\t\t\tconst unsubs: Array<() => void> = [];\n\t\t\tfor (let depIdx = 0; depIdx < allDeps.length; depIdx++) {\n\t\t\t\tconst dep = allDeps[depIdx];\n\t\t\t\tunsubs.push(\n\t\t\t\t\tdep.subscribe((msgs) => {\n\t\t\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\t\t\t_handleBudgetMessage(msg, depIdx, gateActions);\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\treturn () => {\n\t\t\t\tfor (const u of unsubs) u();\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t...opts,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: domainMeta(\"resilience\", \"budget_gate\", opts?.meta),\n\t\t} as NodeOptions<T>,\n\t);\n\n\treturn { node: out, budgetGateState };\n\n\tfunction _handleBudgetMessage(msg: Message, depIndex: number, actions: NodeActions): boolean {\n\t\tconst t = msg[0];\n\n\t\t// Source messages (dep 0)\n\t\tif (depIndex === 0) {\n\t\t\tif (t === DATA) {\n\t\t\t\tif (checkBudget() && buffer.size === 0) {\n\t\t\t\t\tactions.emit(msg[1] as T);\n\t\t\t\t} else {\n\t\t\t\t\tbuffer.push(msg[1] as T);\n\t\t\t\t\tif (!paused) {\n\t\t\t\t\t\tpaused = true;\n\t\t\t\t\t\tactions.up([[PAUSE, lockId]]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (t === DIRTY) {\n\t\t\t\tactions.down([[DIRTY]]);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (t === RESOLVED) {\n\t\t\t\tif (buffer.size === 0) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t} else {\n\t\t\t\t\t// Buffer non-empty: defer RESOLVED until buffer drains (invariant 3).\n\t\t\t\t\tpendingResolved = true;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (t === COMPLETE || t === ERROR) {\n\t\t\t\t// Invariant 1: terminal force-flush. Drain every buffered item\n\t\t\t\t// downstream BEFORE forwarding the terminal — bypass the constraint\n\t\t\t\t// since \"upstream done\" must not lose buffered work.\n\t\t\t\twhile (buffer.size > 0) {\n\t\t\t\t\tactions.emit(buffer.shift()!);\n\t\t\t\t}\n\t\t\t\tpendingResolved = false;\n\t\t\t\t// Release PAUSE lock before forwarding terminal so upstream sees a\n\t\t\t\t// clean release rather than a still-paused terminal.\n\t\t\t\tif (paused) {\n\t\t\t\t\tpaused = false;\n\t\t\t\t\tactions.up([[RESUME, lockId]]);\n\t\t\t\t}\n\t\t\t\tactions.down([msg]);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// Constraint node messages (dep 1+): capture DATA then re-check budget\n\t\tif (t === DATA) {\n\t\t\tlatestValues[depIndex - 1] = msg[1];\n\t\t}\n\t\tif (t === DATA || t === RESOLVED) {\n\t\t\t// qa A2: hoist `checkBudget()` to a local — both branches consult it\n\t\t\t// and `c.check(value)` may be expensive or non-pure (closes over time,\n\t\t\t// counters, etc.); calling it twice was a 2× cost amplifier and an\n\t\t\t// inconsistency risk if the predicate flips between calls.\n\t\t\t//\n\t\t\t// qa A3: each constraint's `c.check(latestValues[i])` runs against\n\t\t\t// the constraint's last cached value. If a constraint's cache is\n\t\t\t// `undefined` (constraint Node hasn't emitted DATA yet OR was\n\t\t\t// activated before any push-on-subscribe), the predicate sees\n\t\t\t// `undefined`. Treat undefined as \"constraint not ready ⇒ closed\"\n\t\t\t// (conservative — don't release the gate on incomplete state).\n\t\t\tconst ok = checkBudget();\n\t\t\tif (ok && buffer.size > 0) {\n\t\t\t\t// Invariant 2: drain FIFO downstream BEFORE releasing PAUSE upstream.\n\t\t\t\tflushBuffer(actions);\n\t\t\t\tif (buffer.size === 0 && paused) {\n\t\t\t\t\tpaused = false;\n\t\t\t\t\tactions.up([[RESUME, lockId]]);\n\t\t\t\t}\n\t\t\t} else if (!ok && !paused && buffer.size > 0) {\n\t\t\t\t// Defensive — buffer.size > 0 implies paused=true under normal flow\n\t\t\t\t// (a buffered source DATA always sets paused). Kept for clarity if\n\t\t\t\t// invariants ever shift.\n\t\t\t\tpaused = true;\n\t\t\t\tactions.up([[PAUSE, lockId]]);\n\t\t\t}\n\t\t\t// DS-13.5.B: re-publish gate state on constraint update.\n\t\t\tif (t === DATA) publishState();\n\t\t\treturn true;\n\t\t}\n\t\tif (t === DIRTY) {\n\t\t\t// Invariant 4: constraint DIRTY does not propagate downstream.\n\t\t\treturn true;\n\t\t}\n\t\tif (t === ERROR) {\n\t\t\t// Constraint error → forward downstream\n\t\t\tactions.down([msg]);\n\t\t\treturn true;\n\t\t}\n\t\tif (t === COMPLETE) {\n\t\t\t// Constraint completed — locked at last value, no-op\n\t\t\treturn true;\n\t\t}\n\t\t// Unknown constraint types → default forwarding\n\t\treturn false;\n\t}\n}\n","/**\n * Metadata helpers for pattern-layer nodes (Tier 2.2 promotion from\n * `patterns/_internal/`).\n *\n * Each domain (orchestration, messaging, reduction, ai, cqrs, domain_template,\n * memory, lens, audit, harness) shares the same metadata convention. Promoted\n * to `extra/` so non-patterns code (and downstream consumers building their\n * own domain primitives) can use the same shape.\n *\n * @module\n */\n\n/**\n * Build a domain metadata object for pattern-layer nodes.\n *\n * Each domain 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 */\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 * Fallback — replace upstream ERROR with a static or computed source.\n *\n * Accepts scalar / `Node` / `PromiseLike` / `AsyncIterable` fallbacks; non-Node\n * inputs are routed through `fromAny` so the fallback participates in the\n * reactive protocol uniformly.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tfactoryTag,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n\tTEARDOWN,\n} from \"@graphrefly/pure-ts/core\";\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport {\n\tisAsyncIterable,\n\tisNode,\n\tisThenable,\n\toperatorOpts,\n} from \"../../base/resilience/_internal.js\";\n\n/** Inputs accepted by {@link fallback}. */\nexport type FallbackInput<T> = T | Node<T> | PromiseLike<T> | AsyncIterable<T>;\n\n/**\n * On upstream terminal `ERROR`, switch to a fallback source instead of propagating the error.\n *\n * Accepts any of:\n * - **scalar value** — emits `[[DATA, fb], [COMPLETE]]`\n * - **`Node<T>`** — subscribes and forwards all messages (push-on-subscribe delivers current cache)\n * - **`Promise<T>` / thenable** — resolves into a one-shot `DATA` then `COMPLETE` (via {@link fromAny})\n * - **`AsyncIterable<T>`** — streams each yielded value as `DATA`, then `COMPLETE` (via {@link fromAny})\n *\n * Non-`Node` inputs are routed through {@link fromAny} so the fallback participates in the\n * reactive protocol uniformly. Bare strings, arrays, and other synchronous scalars are treated\n * as single values (NOT split into characters / elements) to avoid the `fromAny`-on-string\n * iteration gotcha.\n *\n * Composes naturally with {@link retry}:\n * `pipe(source, retry({count:3}), fallback(\"default\"))`.\n *\n * @param source - Upstream node.\n * @param fb - Fallback value, node, promise, or async iterable.\n * @returns Node that replaces errors with the fallback.\n *\n * @example\n * ```ts\n * import { fallback, throwError } from \"@graphrefly/graphrefly-ts\";\n *\n * const safe = fallback(throwError(new Error(\"boom\")), \"default\");\n * safe.cache; // \"default\" after subscribe\n * ```\n *\n * @category extra\n */\nexport function fallback<T>(\n\tsource: Node<T>,\n\tfb: FallbackInput<T>,\n\toptions?: { meta?: Record<string, unknown> },\n): Node<T> {\n\tconst callerMeta = options?.meta;\n\treturn node<T>(\n\t\t(_data, a) => {\n\t\t\tlet fallbackUnsub: (() => void) | undefined;\n\t\t\tlet sourceUnsub: (() => void) | undefined;\n\n\t\t\tfunction switchToFallback(): void {\n\t\t\t\tsourceUnsub?.();\n\t\t\t\tsourceUnsub = undefined;\n\t\t\t\tif (isNode(fb) || isThenable(fb) || isAsyncIterable(fb)) {\n\t\t\t\t\tconst fbNode = fromAny(fb as Node<T> | PromiseLike<T> | AsyncIterable<T>);\n\t\t\t\t\tfallbackUnsub = fbNode.subscribe((fMsgs) => {\n\t\t\t\t\t\ta.down(fMsgs);\n\t\t\t\t\t\t// qa A14: clear fallbackUnsub on terminal so the teardown\n\t\t\t\t\t\t// closure doesn't double-call it. Idempotency of\n\t\t\t\t\t\t// fromAny's unsub is implementation-defined; explicit\n\t\t\t\t\t\t// self-clear is safer.\n\t\t\t\t\t\tfor (const fm of fMsgs) {\n\t\t\t\t\t\t\tconst ft = fm[0];\n\t\t\t\t\t\t\tif (ft === COMPLETE || ft === ERROR || ft === TEARDOWN) {\n\t\t\t\t\t\t\t\tfallbackUnsub = undefined;\n\t\t\t\t\t\t\t\treturn;\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\ta.emit(fb as T);\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsourceUnsub = source.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tconst t = m[0];\n\t\t\t\t\tif (t === DIRTY) a.down([[DIRTY]]);\n\t\t\t\t\telse if (t === DATA) a.emit(m[1] as T);\n\t\t\t\t\telse if (t === RESOLVED) a.down([[RESOLVED]]);\n\t\t\t\t\telse if (t === COMPLETE) a.down([[COMPLETE]]);\n\t\t\t\t\telse if (t === ERROR) {\n\t\t\t\t\t\tswitchToFallback();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (t === TEARDOWN) {\n\t\t\t\t\t\tfallbackUnsub?.();\n\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else a.down([m]);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tsourceUnsub?.();\n\t\t\t\tfallbackUnsub?.();\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(),\n\t\t\tinitial: source.cache,\n\t\t\tmeta: { ...(callerMeta ?? {}), ...factoryTag(\"fallback\") },\n\t\t},\n\t);\n}\n","/**\n * Rate limiters — `tokenBucket` (raw meter), `rateLimiter` (operator with\n * bounded queue + reactive backpressure companions), and the re-export of\n * `adaptiveRateLimiter` from its standalone module.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tfactoryTag,\n\tmonotonicNs,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n\tResettableTimer,\n\tRingBuffer,\n\tTEARDOWN,\n} from \"@graphrefly/pure-ts/core\";\nimport {\n\tisNode,\n\ttype NodeOrValue,\n\toperatorOpts,\n\tresolveReactiveOption,\n} from \"../../base/resilience/_internal.js\";\nimport { NS_PER_MS, NS_PER_SEC } from \"../../base/resilience/backoff.js\";\nimport type { GateState } from \"./gate-state.js\";\n\n// `adaptiveRateLimiter` lives in extra/adaptive-rate-limiter.ts (kept independent\n// because it has its own internal control-loop machinery).\nexport * from \"./adaptive-rate-limiter.js\";\n\nexport interface TokenBucket {\n\t/**\n\t * Number of tokens currently available (after refill).\n\t *\n\t * **Float-valued.** When `refillPerSecond` is fractional (or `capacity` × elapsed-fraction\n\t * yields a non-integer), the bucket accumulates fractional refill credit between\n\t * `tryConsume`s. Consumers should not assume integer tokens — e.g. with\n\t * `tokenBucket(10, 2.5)` after 100ms of elapsed time `available()` may report `0.25`.\n\t */\n\tavailable(): number;\n\t/** Try to consume `cost` tokens. Returns `true` if successful. */\n\ttryConsume(cost?: number): boolean;\n\t/**\n\t * Return `cost` tokens to the bucket (capped at capacity). Used when a\n\t * multi-bucket admission fails partway — e.g., `adaptiveRateLimiter`\n\t * consumes from an rpm bucket, then a tpm bucket; if tpm fails, call\n\t * `rpmBucket.putBack(requestCost)` so the rpm slot isn't wasted.\n\t * No-op for non-positive `cost`.\n\t */\n\tputBack(cost?: number): void;\n}\n\n/** Optional configuration for {@link tokenBucket}. */\nexport interface TokenBucketOptions {\n\t/**\n\t * Clock function returning **nanoseconds** with `monotonicNs()` semantics\n\t * (monotonically non-decreasing). Default: `monotonicNs` from `core/clock`.\n\t * Override for deterministic tests — eliminates the need for `vi.useFakeTimers`\n\t * to drive token-refill scheduling.\n\t */\n\tclock?: () => number;\n}\n\n/**\n * Token-bucket meter (capacity + refill rate per second). Use with {@link rateLimiter} or custom gates.\n *\n * @param capacity - Maximum tokens (must be positive).\n * @param refillPerSecond - Tokens added per elapsed second (non-negative; may be fractional).\n * @param opts - Optional `clock` override for deterministic testing.\n * @returns {@link TokenBucket} instance.\n *\n * @remarks\n * **Float behavior:** the internal token counter is float-valued — fractional refill\n * accumulates between `tryConsume` calls. See {@link TokenBucket.available} for caveats.\n *\n * **Clock injection:** pass `opts.clock` to drive refill scheduling deterministically\n * in tests. The contract matches {@link circuitBreaker}'s `now` option: must return\n * `monotonicNs()`-style nanoseconds, never `Date.now()` (wall-clock skew breaks\n * elapsed math).\n *\n * @example\n * ```ts\n * import { tokenBucket } from \"@graphrefly/graphrefly-ts\";\n *\n * const bucket = tokenBucket(10, 2); // capacity 10, refill 2 tokens/sec\n * bucket.tryConsume(3); // true — 7 tokens remaining\n * bucket.available(); // ~7 (plus any elapsed refill — float-valued)\n *\n * // Deterministic test:\n * let t = 0;\n * const tb = tokenBucket(5, 1, { clock: () => t });\n * tb.tryConsume(5); // exhausts\n * t = 1_000_000_000; // advance 1s → +1 refill\n * tb.tryConsume(1); // true\n * ```\n *\n * @category extra\n */\nexport function tokenBucket(\n\tcapacity: number,\n\trefillPerSecond: number,\n\topts?: TokenBucketOptions,\n): TokenBucket {\n\tif (capacity <= 0) throw new RangeError(\"capacity must be > 0\");\n\tif (refillPerSecond < 0) throw new RangeError(\"refillPerSecond must be >= 0\");\n\n\tconst clock = opts?.clock ?? monotonicNs;\n\n\tlet tokens = capacity;\n\tlet updatedAt = clock();\n\n\tfunction refill(now: number): void {\n\t\tif (refillPerSecond > 0) {\n\t\t\tconst elapsedNs = now - updatedAt;\n\t\t\ttokens = Math.min(capacity, tokens + (elapsedNs / NS_PER_SEC) * refillPerSecond);\n\t\t}\n\t\tupdatedAt = now;\n\t}\n\n\treturn {\n\t\tavailable(): number {\n\t\t\trefill(clock());\n\t\t\treturn tokens;\n\t\t},\n\t\ttryConsume(cost = 1): boolean {\n\t\t\tif (cost <= 0) return true;\n\t\t\tconst now = clock();\n\t\t\trefill(now);\n\t\t\tif (tokens >= cost) {\n\t\t\t\ttokens -= cost;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\tputBack(cost = 1): void {\n\t\t\tif (cost <= 0) return;\n\t\t\trefill(clock());\n\t\t\ttokens = Math.min(capacity, tokens + cost);\n\t\t},\n\t};\n}\n\nexport type RateLimiterOverflowPolicy = \"drop-oldest\" | \"drop-newest\" | \"error\";\n\nexport type RateLimiterOptions = {\n\t/** Maximum `DATA` emissions per window (must be > 0). */\n\tmaxEvents: number;\n\t/** Window length in nanoseconds (must be > 0). */\n\twindowNs: number;\n\t/**\n\t * Cap on items queued while waiting for token refill.\n\t *\n\t * **Required.** Pass a finite positive integer (>= 1) for a bounded queue, OR\n\t * the literal `Infinity` to opt in to an unbounded queue (caller acknowledges\n\t * the unbounded-memory-growth risk on a high-rate source). Omitting this\n\t * throws at construction time — the silent-unbounded-buffer footgun is the\n\t * most common rateLimiter mis-configuration.\n\t */\n\tmaxBuffer: number;\n\t/** Overflow policy when `maxBuffer` is exceeded. Default: `\"drop-newest\"`. */\n\tonOverflow?: RateLimiterOverflowPolicy;\n\t/**\n\t * Caller-supplied metadata merged into the produced node's `meta` (Tier 5.2\n\t * D8 widening). Use {@link domainMeta} to tag the layer for `describe()` /\n\t * mermaid grouping (e.g. `domainMeta(\"resilient\", \"rate-limit\")`). The\n\t * primitive's own `factoryTag(\"rateLimiter\", opts)` and the `droppedCount`\n\t * / `rateLimitState` companion seeds always win against caller-supplied\n\t * keys so the audit trail can't be silently overwritten.\n\t */\n\tmeta?: Record<string, unknown>;\n};\n\n/**\n * Thrown by {@link rateLimiter} when `onOverflow: \"error\"` and the pending buffer is full.\n *\n * @category extra\n */\nexport class RateLimiterOverflowError extends Error {\n\toverride name = \"RateLimiterOverflowError\";\n\tconstructor(maxBuffer: number) {\n\t\tsuper(`rateLimiter buffer overflow (maxBuffer=${maxBuffer})`);\n\t}\n}\n\n/**\n * Combined runtime state surfaced by {@link rateLimiter} alongside `droppedCount`.\n * Tier 5.2 D7 widening — exposes pending-buffer occupancy and a `paused`\n * flag so consumers can render backpressure (UI), feed `lens.health`, or\n * gate downstream effects.\n */\n/**\n * Lifecycle-shaped state companion emitted by {@link rateLimiter}.\n *\n * **DS-13.5.B widening (2026-05-01).** `status` extends {@link GateState}\n * with `\"throttled\"` (= `paused === true`). Pre-1.0 break vs the prior\n * shape (which omitted `status`).\n *\n * - `\"open\"` — passing through (no buffering, no recent overflow drops).\n * - `\"throttled\"` — at least one item queued awaiting a token refill.\n * - `\"closed\"` — reserved for future terminal lifecycle reporting.\n */\nexport type RateLimiterState = {\n\t/** DS-13.5.B status field — `\"open\" | \"closed\" | \"throttled\"`. */\n\tstatus: GateState | \"throttled\";\n\t/** Cumulative `DATA` items dropped due to overflow since this subscription cycle started. */\n\tdroppedCount: number;\n\t/** Items currently buffered awaiting a token refill. `0` when the limiter is passing through. */\n\tpendingCount: number;\n\t/** `true` when at least one item is queued (the limiter is actively throttling). */\n\tpaused: boolean;\n};\n\nfunction rateLimiterStateEqual(a: RateLimiterState, b: RateLimiterState): boolean {\n\treturn (\n\t\ta.status === b.status &&\n\t\ta.droppedCount === b.droppedCount &&\n\t\ta.pendingCount === b.pendingCount &&\n\t\ta.paused === b.paused\n\t);\n}\n\nconst RATE_LIMITER_INITIAL_STATE: RateLimiterState = Object.freeze({\n\tstatus: \"open\" as const,\n\tdroppedCount: 0,\n\tpendingCount: 0,\n\tpaused: false,\n});\n\n/** Bundle returned by {@link rateLimiter}. */\nexport type RateLimiterBundle<T> = {\n\t/** The throttled stream — at most `maxEvents` `DATA` per `windowNs`. */\n\tnode: Node<T>;\n\t/**\n\t * Reactive companion: count of `DATA` items dropped since the producer\n\t * activated.\n\t *\n\t * - Increments on every drop under any overflow policy (`drop-newest`,\n\t * `drop-oldest`). The `error` policy terminates the stream after a single\n\t * overflow, so `droppedCount` increments at most once in that path.\n\t * - **Lifecycle scoping (qa A1 + EC7):** the counter retains its final\n\t * value through terminal (`COMPLETE` / `ERROR` / `TEARDOWN`) so consumers\n\t * see the final drop count, not zero. The closure-held counter resets to\n\t * `0` only when the producer fn re-runs — which only happens on a new\n\t * subscription cycle, and only if the producer was constructed with\n\t * `resubscribable: true`. The default `rateLimiter` producer is NOT\n\t * resubscribable, so a single producer-fn run is the typical lifetime.\n\t * - Producer-pattern note: this companion is invisible to `describe()`\n\t * traversal from `node` (effect-mirror limitation; same shape as\n\t * `withBreaker.breakerState` and `withStatus.status`). Surface it via\n\t * `node.meta.droppedCount` if you need it in topology snapshots.\n\t */\n\tdroppedCount: Node<number>;\n\t/**\n\t * Reactive companion: combined `{droppedCount, pendingCount, paused}` view.\n\t *\n\t * - `pendingCount` reflects the live buffer occupancy and updates on every\n\t * push / shift / overflow drop; `paused` is shorthand for\n\t * `pendingCount > 0`.\n\t * - Equality-deduped — re-emits only when one of the three fields actually\n\t * changes (so a busy steady-state where every DATA passes immediately\n\t * produces one `paused: false` emission, not one per DATA).\n\t * - **Lifecycle scoping (qa EC7):** same contract as `droppedCount` —\n\t * retains its final value through terminal; resets to the initial\n\t * `{droppedCount: 0, pendingCount: 0, paused: false}` only on a new\n\t * producer-fn run (resubscribable upstream required).\n\t * - Same producer-pattern caveat as `droppedCount` re: `describe()` visibility.\n\t */\n\trateLimitState: Node<RateLimiterState>;\n};\n\n/**\n * Token-bucket rate limiter: at most `maxEvents` `DATA` values per `windowNs`.\n *\n * Uses {@link tokenBucket} internally (capacity = `maxEvents`, refill = `maxEvents / windowSeconds`).\n * Excess items are queued FIFO (in a fixed-capacity {@link RingBuffer} for O(1) push/shift)\n * until a token is available. The queue is bounded by the **required** `maxBuffer` option\n * with a configurable overflow policy.\n *\n * @param source - Upstream node.\n * @param opts - Rate + bounded-buffer configuration. `maxBuffer` is required (use `Infinity` to opt in to unbounded).\n * @returns `{ node, droppedCount }` bundle. Subscribe to `node` for the throttled stream and to `droppedCount` for backpressure pressure.\n *\n * @throws {RangeError} when `maxEvents` / `windowNs` is non-positive, when `maxBuffer` is omitted, or when `maxBuffer` is a finite value < 1.\n *\n * @remarks\n * **Terminal:** `COMPLETE` / `ERROR` cancel the refill timer, drop the pending queue,\n * reset `droppedCount` to `0`, and propagate.\n *\n * @example\n * ```ts\n * import { rateLimiter, state, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * const src = state(0);\n * // Allow at most 5 DATA values per second; queue up to 100 excess items, drop newest beyond.\n * const { node: limited, droppedCount } = rateLimiter(src, {\n * maxEvents: 5,\n * windowNs: NS_PER_SEC,\n * maxBuffer: 100,\n * });\n * droppedCount.subscribe(([m]) => console.log(\"dropped so far:\", m[1]));\n * ```\n *\n * @category extra\n */\nexport function rateLimiter<T>(\n\tsource: Node<T>,\n\topts: NodeOrValue<RateLimiterOptions>,\n): RateLimiterBundle<T> {\n\t// Eager validation of static-form opts. Reactive-form opts re-validate\n\t// on each emit via `applyOpts` (invalid runtime config keeps the previous\n\t// values rather than throwing — the producer body's swap path never\n\t// throws into the dataplane).\n\tconst isReactive = isNode(opts);\n\tif (!isReactive) {\n\t\tconst o = opts as RateLimiterOptions;\n\t\tif (o.maxEvents <= 0) throw new RangeError(\"maxEvents must be > 0\");\n\t\tif (o.windowNs <= 0) throw new RangeError(\"windowNs must be > 0\");\n\t\tif (o.maxBuffer === undefined) {\n\t\t\tthrow new RangeError(\n\t\t\t\t\"rateLimiter requires explicit maxBuffer (use Infinity to opt in to unbounded)\",\n\t\t\t);\n\t\t}\n\t\tconst isUnbounded0 = o.maxBuffer === Infinity;\n\t\tif (!isUnbounded0 && (!Number.isInteger(o.maxBuffer) || o.maxBuffer < 1)) {\n\t\t\tthrow new RangeError(\"maxBuffer must be a positive integer (or Infinity for unbounded)\");\n\t\t}\n\t}\n\t// Mode (bounded vs unbounded) is locked at construction time per the\n\t// Tier 6.5 3.2.3 swap rule — runtime opt swaps change the cap WITHIN\n\t// the same mode. Toggling between bounded/unbounded requires re-mounting\n\t// the rateLimiter; the queue type is structural, not a tunable. For\n\t// reactive opts we read the FIRST value (cached or undefined) to lock\n\t// the mode; if the cache is undefined at construction we conservatively\n\t// default to bounded with a placeholder cap, and the first emit re-locks.\n\tconst initialOpts: RateLimiterOptions | undefined = isReactive\n\t\t? ((opts as Node<RateLimiterOptions>).cache as RateLimiterOptions | undefined)\n\t\t: (opts as RateLimiterOptions);\n\tconst initialMaxBuffer = initialOpts?.maxBuffer;\n\tconst isUnbounded = initialMaxBuffer === Infinity;\n\n\tconst out = node<T>(\n\t\t(_data, a) => {\n\t\t\t// Mutable closure-state — replaced on each option swap.\n\t\t\tlet maxEvents = initialOpts?.maxEvents ?? 1;\n\t\t\tlet windowNs = initialOpts?.windowNs ?? NS_PER_SEC;\n\t\t\tlet maxBuffer = initialMaxBuffer ?? 1;\n\t\t\tlet onOverflow: RateLimiterOverflowPolicy = initialOpts?.onOverflow ?? \"drop-newest\";\n\t\t\tlet refillPerSec = (maxEvents * NS_PER_SEC) / windowNs;\n\t\t\tlet tokenTimeNs = NS_PER_SEC / refillPerSec;\n\t\t\tlet bucket = tokenBucket(maxEvents, refillPerSec);\n\n\t\t\t// RingBuffer for O(1) push + shift. Unbounded mode falls back to a plain\n\t\t\t// array (RingBuffer requires a positive integer capacity); the caller\n\t\t\t// explicitly opted in via `maxBuffer: Infinity` and accepts the cost.\n\t\t\t// Bounded mode allocates with the INITIAL `maxBuffer`; runtime cap\n\t\t\t// reductions enforce drop-oldest at push time without resizing the ring.\n\t\t\tconst pending: { push: (v: T) => void; shift: () => T | undefined; size: number } =\n\t\t\t\tisUnbounded ? makeArrayQueue<T>() : ringBufferQueue<T>(Math.max(1, maxBuffer));\n\t\t\tconst timer = new ResettableTimer();\n\t\t\tlet terminated = false;\n\t\t\tlet dropped = 0;\n\n\t\t\t// Mirror the dropped counter + combined state to the meta companions.\n\t\t\t// The `emit` call is the same subscribe-callback effect-mirror\n\t\t\t// pattern used by `withBreaker.breakerState` / `withStatus.status`\n\t\t\t// (sanctioned per audit § F.7).\n\t\t\tconst droppedNode = out.meta.droppedCount;\n\t\t\tconst stateNode = out.meta.rateLimitState;\n\t\t\tlet lastState: RateLimiterState = RATE_LIMITER_INITIAL_STATE;\n\t\t\tfunction syncState(): void {\n\t\t\t\tdroppedNode.emit(dropped);\n\t\t\t\tconst isPaused = pending.size > 0;\n\t\t\t\tconst next: RateLimiterState = {\n\t\t\t\t\tstatus: isPaused ? \"throttled\" : \"open\",\n\t\t\t\t\tdroppedCount: dropped,\n\t\t\t\t\tpendingCount: pending.size,\n\t\t\t\t\tpaused: isPaused,\n\t\t\t\t};\n\t\t\t\t// Equality-dedup at the emit boundary so steady-state pass-through\n\t\t\t\t// (every DATA passes immediately — pendingCount stays 0, paused\n\t\t\t\t// stays false) doesn't generate one state DATA per source DATA.\n\t\t\t\tif (!rateLimiterStateEqual(lastState, next)) {\n\t\t\t\t\tlastState = next;\n\t\t\t\t\tstateNode.emit(next);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Reset for this subscription cycle — `dropped` is the closure\n\t\t\t// variable (already 0 at construction); `pending.size` is also 0\n\t\t\t// (fresh queue per producer activation). The companion Node caches\n\t\t\t// may still hold a prior cycle's terminal values, so re-emit the\n\t\t\t// initial state explicitly.\n\t\t\tlastState = RATE_LIMITER_INITIAL_STATE;\n\t\t\tdroppedNode.emit(0);\n\t\t\tstateNode.emit(RATE_LIMITER_INITIAL_STATE);\n\n\t\t\t// Tier 6.5 3.2.3 (2026-04-29): reactive option swap handler.\n\t\t\t// Locked semantics: `maxEvents`/`windowNs` swap rebuilds the\n\t\t\t// token bucket at the next refill window (tokens reset to new\n\t\t\t// capacity, refill rate updates immediately). `maxBuffer` shrink\n\t\t\t// drops oldest pending entries until size ≤ new cap. `onOverflow`\n\t\t\t// swap takes effect at the next overflow check. Mode toggling\n\t\t\t// (bounded ↔ unbounded) is NOT supported — locked at construction.\n\t\t\tconst optMirror = resolveReactiveOption<RateLimiterOptions>(\n\t\t\t\topts as NodeOrValue<RateLimiterOptions>,\n\t\t\t\t(next) => {\n\t\t\t\t\tif (terminated) return;\n\t\t\t\t\tif (next == null) return;\n\t\t\t\t\t// QA A9 (2026-05-03): explicit empty `{}` short-circuit\n\t\t\t\t\t// for symmetry with timeout / retry / circuitBreaker\n\t\t\t\t\t// (DS-13.5.B locked rule: empty `{}` is a no-op — no\n\t\t\t\t\t// rebind, no companion fire). Pre-fix, empty `{}` was\n\t\t\t\t\t// implicitly a no-op via the validation gate's\n\t\t\t\t\t// `next.maxEvents > 0` check on `undefined`; this\n\t\t\t\t\t// makes the rule explicit and resilient to future\n\t\t\t\t\t// validation refactors.\n\t\t\t\t\tif (typeof next === \"object\" && Object.keys(next).length === 0) return;\n\t\t\t\t\t// Validate; if invalid, keep previous values (no throw into dataplane).\n\t\t\t\t\tif (!(next.maxEvents > 0) || !(next.windowNs > 0)) return;\n\t\t\t\t\tconst nextBuf = next.maxBuffer;\n\t\t\t\t\tif (nextBuf === undefined) return;\n\t\t\t\t\tconst nextUnbounded = nextBuf === Infinity;\n\t\t\t\t\tif (nextUnbounded !== isUnbounded) {\n\t\t\t\t\t\t// Mode toggle not supported — skip silently. Caller using\n\t\t\t\t\t\t// reactive opts must keep maxBuffer in the same mode.\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!nextUnbounded && (!Number.isInteger(nextBuf) || nextBuf < 1)) return;\n\n\t\t\t\t\t// qa F-C (Tier 5 /qa pass, 2026-04-29): reactive `maxBuffer`\n\t\t\t\t\t// is monotonically non-increasing. The pending RingBuffer is\n\t\t\t\t\t// allocated once at construction; growing the cap reactively\n\t\t\t\t\t// would let the overflow check pass more pushes than the\n\t\t\t\t\t// ring's capacity → silent drop-oldest at the substrate level\n\t\t\t\t\t// (RingBuffer.push wraps), bypassing our `dropped` counter\n\t\t\t\t\t// and `onOverflow: \"error\"` arm. Reject grow swaps with a\n\t\t\t\t\t// console.warn and keep the previous cap. Shrink stays\n\t\t\t\t\t// supported (drop-oldest below).\n\t\t\t\t\tif (!nextUnbounded && nextBuf > maxBuffer) {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`rateLimiter: reactive maxBuffer grow (${maxBuffer} → ${nextBuf}) ` +\n\t\t\t\t\t\t\t\t\"rejected. The pending ring buffer is allocated at construction; \" +\n\t\t\t\t\t\t\t\t\"reactive maxBuffer is monotonically non-increasing. Recreate \" +\n\t\t\t\t\t\t\t\t\"the rateLimiter with the larger cap if growth is required.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tmaxEvents = next.maxEvents;\n\t\t\t\t\twindowNs = next.windowNs;\n\t\t\t\t\tmaxBuffer = nextBuf;\n\t\t\t\t\tonOverflow = next.onOverflow ?? \"drop-newest\";\n\t\t\t\t\trefillPerSec = (maxEvents * NS_PER_SEC) / windowNs;\n\t\t\t\t\ttokenTimeNs = NS_PER_SEC / refillPerSec;\n\t\t\t\t\t// Rebuild bucket — tokens snap to new capacity. The old refill\n\t\t\t\t\t// timer continues to fire `tryEmit` which will use the new\n\t\t\t\t\t// bucket (same closure variable).\n\t\t\t\t\tbucket = tokenBucket(maxEvents, refillPerSec);\n\n\t\t\t\t\t// Drop-oldest until pending.size <= maxBuffer (bounded only).\n\t\t\t\t\tif (!nextUnbounded) {\n\t\t\t\t\t\twhile (pending.size > maxBuffer) {\n\t\t\t\t\t\t\tpending.shift();\n\t\t\t\t\t\t\tdropped += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tsyncState();\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tfunction tryEmit(): void {\n\t\t\t\twhile (pending.size > 0) {\n\t\t\t\t\tif (bucket.tryConsume(1)) {\n\t\t\t\t\t\ta.emit(pending.shift() as T);\n\t\t\t\t\t\tsyncState();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Wait one full token-refill interval. Avoids calling bucket.available()\n\t\t\t\t\t\t// which would advance the internal refill clock and steal fractional credit.\n\t\t\t\t\t\t// §5.10: setTimeout (not fromTimer) — refill-delay scheduling needs clearTimeout/setTimeout;\n\t\t\t\t\t\t// fromTimer creates a new Node per reset, adding lifecycle overhead per retry.\n\t\t\t\t\t\ttimer.start(Math.max(1, tokenTimeNs / NS_PER_MS), tryEmit);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction recordDrop(): void {\n\t\t\t\tdropped += 1;\n\t\t\t\tsyncState();\n\t\t\t}\n\n\t\t\tfunction resetForTerminal(): void {\n\t\t\t\tterminated = true;\n\t\t\t\ttimer.cancel();\n\t\t\t\t// RingBuffer.clear-equivalent: drain remaining slots so refs GC.\n\t\t\t\twhile (pending.size > 0) pending.shift();\n\t\t\t\t// qa A1: companions retain their last-emitted DATA value\n\t\t\t\t// through terminal (consumer sees the final drop count, not 0).\n\t\t\t\t// The closure-held `dropped` resets to 0 so a re-subscribe\n\t\t\t\t// cycle starts fresh; the activation block above re-emits\n\t\t\t\t// `RATE_LIMITER_INITIAL_STATE` at that point.\n\t\t\t\tdropped = 0;\n\t\t\t}\n\n\t\t\tconst unsub = source.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (terminated) return;\n\t\t\t\t\tconst t = m[0];\n\t\t\t\t\tif (t === DIRTY) a.down([[DIRTY]]);\n\t\t\t\t\telse if (t === DATA) {\n\t\t\t\t\t\tif (!isUnbounded && pending.size >= maxBuffer) {\n\t\t\t\t\t\t\tif (onOverflow === \"drop-newest\") {\n\t\t\t\t\t\t\t\trecordDrop();\n\t\t\t\t\t\t\t} else if (onOverflow === \"drop-oldest\") {\n\t\t\t\t\t\t\t\tpending.shift();\n\t\t\t\t\t\t\t\tpending.push(m[1] as T);\n\t\t\t\t\t\t\t\trecordDrop();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\trecordDrop();\n\t\t\t\t\t\t\t\tresetForTerminal();\n\t\t\t\t\t\t\t\ta.down([[ERROR, new RateLimiterOverflowError(maxBuffer)]]);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpending.push(m[1] as T);\n\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttryEmit();\n\t\t\t\t\t} else if (t === RESOLVED) a.down([[RESOLVED]]);\n\t\t\t\t\telse if (t === COMPLETE) {\n\t\t\t\t\t\tresetForTerminal();\n\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\tresetForTerminal();\n\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t} else if (t === TEARDOWN) {\n\t\t\t\t\t\tresetForTerminal();\n\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else a.down([m]);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tterminated = true;\n\t\t\t\ttimer.cancel();\n\t\t\t\tunsub();\n\t\t\t\toptMirror.unsub();\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t...operatorOpts(),\n\t\t\tinitial: source.cache,\n\t\t\tmeta: {\n\t\t\t\t// Caller-supplied meta first; companion seeds + factoryTag\n\t\t\t\t// override below so they always win.\n\t\t\t\t...(isReactive ? {} : ((opts as RateLimiterOptions).meta ?? {})),\n\t\t\t\tdroppedCount: 0,\n\t\t\t\trateLimitState: RATE_LIMITER_INITIAL_STATE,\n\t\t\t\t...factoryTag(\"rateLimiter\", isReactive ? { reactiveOpts: true } : opts),\n\t\t\t},\n\t\t},\n\t);\n\n\treturn {\n\t\tnode: out,\n\t\tdroppedCount: out.meta.droppedCount as Node<number>,\n\t\trateLimitState: out.meta.rateLimitState as Node<RateLimiterState>,\n\t};\n}\n\n/**\n * RingBuffer-backed queue adapter — exposes the small `{ push, shift, size }`\n * shape rateLimiter needs without leaking the rest of `RingBuffer`'s API.\n */\nfunction ringBufferQueue<T>(capacity: number): {\n\tpush: (v: T) => void;\n\tshift: () => T | undefined;\n\tsize: number;\n} {\n\tconst buf = new RingBuffer<T>(capacity);\n\treturn {\n\t\tpush: (v: T) => buf.push(v),\n\t\tshift: () => buf.shift(),\n\t\tget size(): number {\n\t\t\treturn buf.size;\n\t\t},\n\t} as { push: (v: T) => void; shift: () => T | undefined; size: number };\n}\n\n/**\n * Plain-array fallback queue for `maxBuffer: Infinity`. Accepts the O(N) shift\n * cost — the caller opted in to unbounded growth.\n */\nfunction makeArrayQueue<T>(): {\n\tpush: (v: T) => void;\n\tshift: () => T | undefined;\n\tsize: number;\n} {\n\tconst arr: T[] = [];\n\treturn {\n\t\tpush: (v: T) => {\n\t\t\tarr.push(v);\n\t\t},\n\t\tshift: () => arr.shift(),\n\t\tget size(): number {\n\t\t\treturn arr.length;\n\t\t},\n\t} as { push: (v: T) => void; shift: () => T | undefined; size: number };\n}\n","/**\n * Adaptive rate limiter — reactive, live-tunable, 429-aware.\n *\n * Wraps two `tokenBucket` instances (requests, tokens) with:\n * - Reactive `rpm` / `tpm` knobs that can be re-tuned at runtime via `NodeInput<number>`.\n * - An adaptation signal input (`Node<RateLimitSignal>`) that feeds back\n * provider 429 / retry-after / x-ratelimit-* headers to tighten limits.\n * - A `clampCooldownMs` TTL on signal-induced caps so a transient 429 doesn't\n * permanently throttle — caps decay back to user-configured values after\n * the cooldown elapses.\n * - TPM-miss recovery: consumed RPM tokens are returned to the request\n * bucket when the TPM admit fails, via `TokenBucket.putBack`.\n * - Imperative `acquire()` for bridging to Promise-based call paths\n * (used by the `withRateLimiter` adapter middleware).\n *\n * **Timer policy:** sleeps use `ResettableTimer` (documented spec §5.10\n * escape hatch in `src/extra/timer.ts`) rather than `fromTimer` to avoid\n * allocating a new Node per acquire cycle.\n *\n * Design lives in `docs/optimizations.md` § \"Reactive adaptive rate limiter\".\n */\n\nimport { DATA, monotonicNs, type Node, node, ResettableTimer } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { NS_PER_SEC } from \"../../base/resilience/backoff.js\";\nimport { type TokenBucket, tokenBucket } from \"./rate-limiter.js\";\n\n// ---------------------------------------------------------------------------\n// Signal shape\n// ---------------------------------------------------------------------------\n\n/**\n * Rate-limit signal emitted by an adaptation source (e.g., an HTTP 429 parser).\n *\n * Any subset of fields may be present. The adaptive rate limiter uses:\n * - `retryAfterMs` — blocks acquire() for this duration.\n * - `rpmCap` / `tpmCap` — tightens effective rpm/tpm to this value (decays\n * back to the user-configured cap after `clampCooldownMs`).\n * - `usageHint` — updates the last-known rpm/tpm usage ratio for logging.\n */\nexport interface RateLimitSignal {\n\t/** Throttle duration — pause acquire() for this long. */\n\tretryAfterMs?: number;\n\t/** Hard cap for requests-per-minute; effective rpm = min(current, rpmCap) while clamp is active. */\n\trpmCap?: number;\n\t/** Hard cap for tokens-per-minute; effective tpm = min(current, tpmCap) while clamp is active. */\n\ttpmCap?: number;\n\t/** Observed usage-percentage hint (0..1) — for observability, not gating. */\n\tusageHint?: { rpm?: number; tpm?: number };\n\t/** Free-form provider-specific payload. */\n\tmetadata?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface AdaptiveRateLimiterOptions {\n\tname?: string;\n\t/** Effective requests-per-minute cap. Reactive — reads push-on-subscribe. */\n\trpm?: NodeInput<number>;\n\t/** Effective tokens-per-minute cap. Reactive. */\n\ttpm?: NodeInput<number>;\n\t/** Source of adaptation signals (429 parser output, etc.). */\n\tadaptation?: NodeInput<RateLimitSignal>;\n\t/**\n\t * How long (ms) a signal-induced `rpmCap` / `tpmCap` stays in effect before\n\t * relaxing back to the user-configured value. Default 60_000 (one minute).\n\t * Set to `Infinity` to make signal caps sticky until manually cleared.\n\t * A fresh signal with the same cap resets the cooldown.\n\t */\n\tclampCooldownMs?: number;\n\t/** Burst capacity overshoot above the steady-state rpm/tpm. Default 1 (no burst). */\n\tburstMultiplier?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Bundle\n// ---------------------------------------------------------------------------\n\nexport interface AdaptiveRateLimiterBundle {\n\t/** Effective requests-per-minute (post-signal-clamp). Reactive. */\n\treadonly effectiveRpm: Node<number>;\n\t/** Effective tokens-per-minute (post-signal-clamp). Reactive. */\n\treadonly effectiveTpm: Node<number>;\n\t/** Last adaptation signal observed. */\n\treadonly lastSignal: Node<RateLimitSignal>;\n\t/** Pending `acquire()` callers waiting for capacity. */\n\treadonly pending: Node<number>;\n\t/** Current request-token-bucket fill (approximate). */\n\treadonly rpmAvailable: Node<number>;\n\t/** Current token-bucket fill (approximate). */\n\treadonly tpmAvailable: Node<number>;\n\t/**\n\t * Imperative bridge: wait until `requestCost` request-tokens and\n\t * `tokenCost` tokens are available, then consume them. Honors the\n\t * most recent `retryAfterMs` from adaptation signals. Rejects with\n\t * an `AbortError`-named error if `signal` aborts while waiting.\n\t * `requestCost` defaults to 1; `tokenCost` defaults to 0 (rpm-only gating).\n\t */\n\tacquire(opts?: { requestCost?: number; tokenCost?: number; signal?: AbortSignal }): Promise<void>;\n\t/**\n\t * Feed back observed token usage (post-call) so the TPM bucket reflects\n\t * real consumption rather than the pre-call estimate. A positive `delta`\n\t * debits additional TPM (undershot estimate); a negative `delta` credits\n\t * back overshoot (`putBack`).\n\t */\n\trecordUsage(delta: number): void;\n\t/** Manually feed an adaptation signal — useful for tests. */\n\trecordSignal(sig: RateLimitSignal): void;\n\t/** Dispose internal subscriptions and pending timers. */\n\tdispose(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Error construction\n// ---------------------------------------------------------------------------\n\nfunction makeAbortError(reason: string): Error {\n\tconst err = new Error(reason) as Error & { name: string };\n\terr.name = \"AbortError\";\n\treturn err;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Create an adaptive rate limiter. Compose with any call source via\n * `await limiter.acquire({ requestCost, tokenCost, signal })`.\n */\nexport function adaptiveRateLimiter(\n\topts: AdaptiveRateLimiterOptions = {},\n): AdaptiveRateLimiterBundle {\n\tconst burst = Math.max(1, opts.burstMultiplier ?? 1);\n\tconst clampCooldownMs = opts.clampCooldownMs ?? 60_000;\n\n\t// Resolve reactive rpm/tpm inputs. Callers may pass `NodeInput` which\n\t// could be a literal number or a Node. `fromAny` normalizes to a Node.\n\tconst rpmInputNode =\n\t\topts.rpm != null\n\t\t\t? fromAny(opts.rpm as NodeInput<number>)\n\t\t\t: node<number>([], { initial: Number.POSITIVE_INFINITY });\n\tconst tpmInputNode =\n\t\topts.tpm != null\n\t\t\t? fromAny(opts.tpm as NodeInput<number>)\n\t\t\t: node<number>([], { initial: Number.POSITIVE_INFINITY });\n\n\t// Signal cap state — updated by recordSignal() / adaptation source.\n\t// The decay timer relaxes the cap back to Infinity after `clampCooldownMs`.\n\tconst signalRpmCap = node<number>([], {\n\t\tinitial: Number.POSITIVE_INFINITY,\n\t\tname: \"adaptiveRateLimiter/signalRpmCap\",\n\t});\n\tconst signalTpmCap = node<number>([], {\n\t\tinitial: Number.POSITIVE_INFINITY,\n\t\tname: \"adaptiveRateLimiter/signalTpmCap\",\n\t});\n\tconst lastSignal = node<RateLimitSignal>([], {\n\t\tinitial: {},\n\t\tname: \"adaptiveRateLimiter/lastSignal\",\n\t});\n\n\t// Compute effective rpm/tpm: min of user-configured cap and signal cap.\n\tconst effectiveRpm = node<number>(\n\t\t[rpmInputNode, signalRpmCap],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(Math.min(Number(data[0] ?? Infinity), Number(data[1] ?? Infinity)));\n\t\t},\n\t\t{ name: \"adaptiveRateLimiter/effectiveRpm\", describeKind: \"derived\" },\n\t);\n\tconst effectiveTpm = node<number>(\n\t\t[tpmInputNode, signalTpmCap],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(Math.min(Number(data[0] ?? Infinity), Number(data[1] ?? Infinity)));\n\t\t},\n\t\t{ name: \"adaptiveRateLimiter/effectiveTpm\", describeKind: \"derived\" },\n\t);\n\n\t// Token buckets — rebuilt when effective caps change.\n\tlet rpmBucket: TokenBucket = makeBucket(\n\t\tNumber(rpmInputNode.cache ?? Number.POSITIVE_INFINITY),\n\t\tburst,\n\t);\n\tlet tpmBucket: TokenBucket = makeBucket(\n\t\tNumber(tpmInputNode.cache ?? Number.POSITIVE_INFINITY),\n\t\tburst,\n\t);\n\n\t// A signal `rpmCap`/`tpmCap` of 0 means \"halt admission entirely\" (e.g.,\n\t// some providers emit this during hard quota exhaustion). We honor it by\n\t// marking the bucket as closed via a long throttle-until; the bucket itself\n\t// stays at its previous capacity so decay can relax it naturally.\n\tlet rpmHardStop = false;\n\tlet tpmHardStop = false;\n\n\tconst unsubRpm = effectiveRpm.subscribe((msgs) => {\n\t\tfor (const msg of msgs) {\n\t\t\tif (msg[0] === DATA) {\n\t\t\t\tconst v = Number(msg[1]);\n\t\t\t\tif (Number.isFinite(v) && v > 0) {\n\t\t\t\t\trpmBucket = makeBucket(v, burst);\n\t\t\t\t\trpmHardStop = false;\n\t\t\t\t} else if (v === Infinity) {\n\t\t\t\t\trpmBucket = makeBucket(Infinity, burst);\n\t\t\t\t\trpmHardStop = false;\n\t\t\t\t} else if (v <= 0) {\n\t\t\t\t\t// Hard stop — no admission until cap relaxes.\n\t\t\t\t\trpmHardStop = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\tconst unsubTpm = effectiveTpm.subscribe((msgs) => {\n\t\tfor (const msg of msgs) {\n\t\t\tif (msg[0] === DATA) {\n\t\t\t\tconst v = Number(msg[1]);\n\t\t\t\tif (Number.isFinite(v) && v > 0) {\n\t\t\t\t\ttpmBucket = makeBucket(v, burst);\n\t\t\t\t\ttpmHardStop = false;\n\t\t\t\t} else if (v === Infinity) {\n\t\t\t\t\ttpmBucket = makeBucket(Infinity, burst);\n\t\t\t\t\ttpmHardStop = false;\n\t\t\t\t} else if (v <= 0) {\n\t\t\t\t\ttpmHardStop = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\t// Throttle-until: set by retryAfterMs signals.\n\tlet throttleUntilNs = 0;\n\n\t// Clamp-decay timers — when they fire, the signal cap is relaxed back to Infinity.\n\tconst rpmDecayTimer = new ResettableTimer();\n\tconst tpmDecayTimer = new ResettableTimer();\n\n\t// Adaptation source subscription.\n\tlet unsubAdapt: (() => void) | undefined;\n\tif (opts.adaptation != null) {\n\t\tconst adaptNode = fromAny(opts.adaptation as NodeInput<RateLimitSignal>);\n\t\tunsubAdapt = adaptNode.subscribe((msgs) => {\n\t\t\tfor (const msg of msgs) {\n\t\t\t\tif (msg[0] === DATA) applySignal(msg[1] as RateLimitSignal);\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction applySignal(sig: RateLimitSignal): void {\n\t\tlastSignal.emit(sig);\n\t\t// Accept `rpmCap`/`tpmCap` of 0 as a valid hard-stop signal. Only\n\t\t// reject non-finite caps (NaN/Infinity).\n\t\tif (sig.rpmCap != null && Number.isFinite(sig.rpmCap) && sig.rpmCap >= 0) {\n\t\t\tsignalRpmCap.emit(sig.rpmCap);\n\t\t\t// Schedule decay. Uses ResettableTimer — each new clamp resets the cooldown.\n\t\t\tif (Number.isFinite(clampCooldownMs) && clampCooldownMs > 0) {\n\t\t\t\trpmDecayTimer.start(clampCooldownMs, () => signalRpmCap.emit(Number.POSITIVE_INFINITY));\n\t\t\t}\n\t\t}\n\t\tif (sig.tpmCap != null && Number.isFinite(sig.tpmCap) && sig.tpmCap >= 0) {\n\t\t\tsignalTpmCap.emit(sig.tpmCap);\n\t\t\tif (Number.isFinite(clampCooldownMs) && clampCooldownMs > 0) {\n\t\t\t\ttpmDecayTimer.start(clampCooldownMs, () => signalTpmCap.emit(Number.POSITIVE_INFINITY));\n\t\t\t}\n\t\t}\n\t\tif (sig.retryAfterMs != null && sig.retryAfterMs > 0) {\n\t\t\tconst resumeAt = monotonicNs() + sig.retryAfterMs * 1_000_000;\n\t\t\tif (resumeAt > throttleUntilNs) throttleUntilNs = resumeAt;\n\t\t}\n\t}\n\n\tconst pending = node<number>([], { initial: 0, name: \"adaptiveRateLimiter/pending\" });\n\tconst rpmAvailableNode = node<number>([], {\n\t\tinitial: Number.POSITIVE_INFINITY,\n\t\tname: \"adaptiveRateLimiter/rpmAvailable\",\n\t});\n\tconst tpmAvailableNode = node<number>([], {\n\t\tinitial: Number.POSITIVE_INFINITY,\n\t\tname: \"adaptiveRateLimiter/tpmAvailable\",\n\t});\n\n\tconst bumpPending = (delta: number): void => {\n\t\tpending.emit((pending.cache ?? 0) + delta);\n\t};\n\tconst refreshAvailable = (): void => {\n\t\trpmAvailableNode.emit(rpmBucket.available());\n\t\ttpmAvailableNode.emit(tpmBucket.available());\n\t};\n\n\tasync function acquire(\n\t\tacquireOpts: { requestCost?: number; tokenCost?: number; signal?: AbortSignal } = {},\n\t): Promise<void> {\n\t\tconst requestCost = acquireOpts.requestCost ?? 1;\n\t\tconst tokenCost = acquireOpts.tokenCost ?? 0;\n\t\tconst abortSignal = acquireOpts.signal;\n\n\t\tbumpPending(1);\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tif (abortSignal?.aborted) throw makeAbortError(\"AdaptiveRateLimiter.acquire aborted\");\n\n\t\t\t\t// Honor retry-after window.\n\t\t\t\tconst now = monotonicNs();\n\t\t\t\tif (throttleUntilNs > now) {\n\t\t\t\t\tconst waitMs = Math.ceil((throttleUntilNs - now) / 1_000_000);\n\t\t\t\t\tawait sleepReactive(waitMs, abortSignal);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Hard-stop (cap=0) → wait for the decay timer to relax.\n\t\t\t\tif ((requestCost > 0 && rpmHardStop) || (tokenCost > 0 && tpmHardStop)) {\n\t\t\t\t\tawait sleepReactive(250, abortSignal);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Capture local refs so a concurrent rpm/tpm cap-change rebuilding\n\t\t\t\t// the bucket doesn't send `putBack` to a different bucket than\n\t\t\t\t// `tryConsume` debited. If the cap relaxes mid-flight, the OLD\n\t\t\t\t// bucket gets the credit (safe — it's closed over a closure the\n\t\t\t\t// new acquires don't see), and new acquires pick up the new\n\t\t\t\t// bucket on their own next iteration.\n\t\t\t\tconst rpmAtAcquire = rpmBucket;\n\t\t\t\tconst tpmAtAcquire = tpmBucket;\n\n\t\t\t\t// Try consume RPM first.\n\t\t\t\tconst gotRpm = rpmAtAcquire.tryConsume(requestCost);\n\t\t\t\tif (!gotRpm) {\n\t\t\t\t\tawait sleepReactive(estimateWaitMs(rpmAtAcquire, requestCost), abortSignal);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// Then TPM — if it fails, return the RPM token (no wasted slot).\n\t\t\t\tconst gotTpm = tokenCost > 0 ? tpmAtAcquire.tryConsume(tokenCost) : true;\n\t\t\t\tif (!gotTpm) {\n\t\t\t\t\trpmAtAcquire.putBack(requestCost);\n\t\t\t\t\tawait sleepReactive(estimateWaitMs(tpmAtAcquire, tokenCost), abortSignal);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\trefreshAvailable();\n\t\t\t\treturn;\n\t\t\t}\n\t\t} finally {\n\t\t\tbumpPending(-1);\n\t\t}\n\t}\n\n\tfunction recordUsage(delta: number): void {\n\t\tif (delta > 0) {\n\t\t\t// Undershoot: debit additional tokens. Non-blocking — if it fails, the\n\t\t\t// next acquire will just wait longer.\n\t\t\ttpmBucket.tryConsume(delta);\n\t\t} else if (delta < 0) {\n\t\t\t// Overshoot: credit back.\n\t\t\ttpmBucket.putBack(-delta);\n\t\t}\n\t\trefreshAvailable();\n\t}\n\n\tfunction dispose(): void {\n\t\tunsubRpm();\n\t\tunsubTpm();\n\t\tunsubAdapt?.();\n\t\trpmDecayTimer.cancel();\n\t\ttpmDecayTimer.cancel();\n\t}\n\n\treturn {\n\t\teffectiveRpm,\n\t\teffectiveTpm,\n\t\tlastSignal,\n\t\tpending,\n\t\trpmAvailable: rpmAvailableNode,\n\t\ttpmAvailable: tpmAvailableNode,\n\t\tacquire,\n\t\trecordUsage,\n\t\trecordSignal: applySignal,\n\t\tdispose,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\nfunction makeBucket(perMinute: number, burst: number): TokenBucket {\n\tif (!Number.isFinite(perMinute) || perMinute === Infinity) {\n\t\treturn tokenBucket(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);\n\t}\n\tconst capacity = Math.max(1, perMinute * burst);\n\tconst refillPerSecond = perMinute / 60;\n\treturn tokenBucket(capacity, refillPerSecond);\n}\n\nfunction estimateWaitMs(bucket: TokenBucket, needed: number): number {\n\tconst have = bucket.available();\n\tconst deficit = Math.max(0, needed - have);\n\tif (deficit <= 0) return 25; // retry quickly; primary path already failed so pacing is forced\n\t// Heuristic: wait 100ms per missing unit, clamped.\n\treturn Math.min(5_000, Math.max(50, deficit * 100));\n}\n\n/**\n * Promise-based sleep using `ResettableTimer` (spec §5.10 escape hatch).\n * Cleanly removes abort listener on both the timer-fires and abort paths;\n * no leaked `AbortSignal.addEventListener` registrations.\n */\nfunction sleepReactive(ms: number, signal?: AbortSignal): Promise<void> {\n\tif (ms <= 0) return Promise.resolve();\n\tif (signal?.aborted) return Promise.reject(makeAbortError(\"AdaptiveRateLimiter.acquire aborted\"));\n\treturn new Promise((resolve, reject) => {\n\t\tconst timer = new ResettableTimer();\n\t\tlet onAbort: (() => void) | undefined;\n\t\tconst cleanup = (): void => {\n\t\t\ttimer.cancel();\n\t\t\tif (signal && onAbort) signal.removeEventListener(\"abort\", onAbort);\n\t\t};\n\t\ttimer.start(ms, () => {\n\t\t\tcleanup();\n\t\t\tresolve();\n\t\t});\n\t\tif (signal) {\n\t\t\tonAbort = (): void => {\n\t\t\t\tcleanup();\n\t\t\t\treject(makeAbortError(\"AdaptiveRateLimiter.acquire aborted\"));\n\t\t\t};\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t});\n}\n\nexport { NS_PER_SEC };\n","/**\n * `withBudgetGate` — cap an adapter by calls / tokens / USD.\n *\n * Totals are an O(1)-per-event running accumulator (a `state<BudgetTotals>`\n * updated imperatively inside `record()`), not a derived reduce over the\n * full log — avoids the quadratic cost at sustained traffic while preserving\n * the reactive surface. The full log is still exposed via the bundle for\n * dashboards / auditors.\n *\n * Budgets are enforced imperatively at `invoke()` / `stream()` entry — the\n * running totals + `isOpen.cache` are read; if closed, the call rejects /\n * throws `BudgetExhaustedError` without hitting the wrapped adapter. On\n * success, the call's usage is appended to the log AND debits the running\n * totals in a single synchronous update.\n *\n * Wave A Unit 11 Q4: rejected-Promise path now wires `.catch` (via\n * `adaptInvokeResult.onError`) so failed invoke calls record a CallStatsEvent\n * with `error` populated. Prior code silently dropped rejection from the\n * `totals` / `log` surface.\n */\n\nimport { DATA, monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { keepalive, type ReactiveLogBundle, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport {\n\tadapterWrapper,\n\tadaptInvokeResult,\n\tbuildCallStats,\n\temptyUsageStub,\n\twithLayer,\n} from \"../_internal/wrappers.js\";\nimport type { CallStatsEvent } from \"../core/observable.js\";\nimport type { PricingFn } from \"../core/pricing.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n} from \"../core/types.js\";\nimport { sumInputTokens, sumOutputTokens } from \"../core/types.js\";\n\nexport class BudgetExhaustedError extends Error {\n\toverride name = \"BudgetExhaustedError\";\n\tconstructor(\n\t\tpublic readonly which: string,\n\t\tpublic readonly limit: number,\n\t\tpublic readonly observed: number,\n\t) {\n\t\tsuper(`Budget exhausted: ${which} (limit=${limit}, observed=${observed})`);\n\t}\n}\n\nexport interface BudgetCaps {\n\tcalls?: number;\n\tinputTokens?: number;\n\toutputTokens?: number;\n\tusd?: number;\n}\n\nexport interface BudgetTotals {\n\tcalls: number;\n\tinputTokens: number;\n\toutputTokens: number;\n\tusd: number;\n}\n\nexport interface LLMBudgetGateBundle {\n\ttotals: Node<BudgetTotals>;\n\tisOpen: Node<boolean>;\n\tlog: ReactiveLogBundle<CallStatsEvent>;\n\treset(): void;\n\t/**\n\t * QA D2 (Phase 13.6.B QA pass): release every long-lived\n\t * subscription this gate holds — `keepalive(isOpen)`, the optional\n\t * `onExhausted` subscription, and the Lock 3.C abort fan-out\n\t * subscription on `isOpen`. Aborts any in-flight controllers as a\n\t * defensive last gasp so callers waiting on a soon-to-be-disposed\n\t * adapter don't hang.\n\t *\n\t * Idempotent: subsequent calls are no-ops. After `dispose()` the\n\t * adapter wrapper continues to wrap `inner.invoke` / `inner.stream`\n\t * but the budget machinery is best-effort: `record()` no longer\n\t * emits `totals` updates, abort fan-out no longer fires. Treat the\n\t * bundle as terminated once disposed; long-running apps should\n\t * `dispose()` per gate instance to avoid the sub-leak documented\n\t * in `docs/optimizations.md`.\n\t */\n\tdispose(): void;\n}\n\nexport interface WithBudgetGateOptions {\n\tcaps: BudgetCaps;\n\t/**\n\t * Optional pricing function for USD gating. If omitted, `caps.usd` is\n\t * ignored (caps.calls / caps.inputTokens / caps.outputTokens still apply).\n\t */\n\tpricingFn?: PricingFn;\n\t/**\n\t * Edge-triggered: fires exactly once when the gate transitions from\n\t * open to closed. Subsequent invoke/stream attempts against a closed\n\t * gate do NOT re-fire `onExhausted` — use the reactive `isOpen` node\n\t * if you need per-attempt notifications. Receives the cap key that\n\t * triggered the transition.\n\t */\n\tonExhausted?: (which: keyof BudgetCaps) => void;\n\t/** Name for logs / describe output. */\n\tname?: string;\n\t/** Max events retained in the log (default 1000). */\n\tlogMax?: number;\n}\n\n// Frozen baseline shared for `totals.cache ?? EMPTY_TOTALS` reads. Consumers\n// that mutate their snapshot in place would otherwise poison every budget-gate\n// instance in the process. `reset()` emits a freshly-constructed object so\n// downstream identity-equals checks on the frozen constant don't false-equal.\nconst EMPTY_TOTALS: Readonly<BudgetTotals> = Object.freeze({\n\tcalls: 0,\n\tinputTokens: 0,\n\toutputTokens: 0,\n\tusd: 0,\n});\nconst makeEmptyTotals = (): BudgetTotals => ({\n\tcalls: 0,\n\tinputTokens: 0,\n\toutputTokens: 0,\n\tusd: 0,\n});\n\n/**\n * Wrap an adapter with budget enforcement. Returns `{adapter, budget}` so\n * callers can subscribe to the bundle for dashboards.\n */\nexport function withBudgetGate(\n\tinner: LLMAdapter,\n\topts: WithBudgetGateOptions,\n): { adapter: LLMAdapter; budget: LLMBudgetGateBundle } {\n\tconst log = reactiveLog<CallStatsEvent>(undefined, {\n\t\tname: opts.name ? `${opts.name}/log` : \"budgetGate/log\",\n\t\tmaxSize: opts.logMax ?? 1000,\n\t});\n\n\t// O(1) running totals — incremented per `record()` rather than reduced over\n\t// the full log. Reactive surface preserved via `state<BudgetTotals>`.\n\tconst totals = node<BudgetTotals>([], {\n\t\tname: opts.name ? `${opts.name}/totals` : \"budgetGate/totals\",\n\t\tinitial: makeEmptyTotals(),\n\t});\n\n\tconst isOpen = node<boolean>(\n\t\t[totals],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst tt = data[0] as BudgetTotals;\n\t\t\tif (opts.caps.calls != null && tt.calls >= opts.caps.calls) {\n\t\t\t\tactions.emit(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (opts.caps.inputTokens != null && tt.inputTokens >= opts.caps.inputTokens) {\n\t\t\t\tactions.emit(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (opts.caps.outputTokens != null && tt.outputTokens >= opts.caps.outputTokens) {\n\t\t\t\tactions.emit(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (opts.caps.usd != null && tt.usd >= opts.caps.usd) {\n\t\t\t\tactions.emit(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit(true);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tname: opts.name ? `${opts.name}/isOpen` : \"budgetGate/isOpen\",\n\t\t\tinitial: true,\n\t\t},\n\t);\n\t// QA D2: capture every subscription/keepalive disposer so `dispose()`\n\t// can release the lot. Pre-D2 these were leaked for the process\n\t// lifetime; the leak grew with B9's abort-wire subscription.\n\tconst disposers: Array<() => void> = [];\n\tlet disposed = false;\n\t// Keep the isOpen derived live so `.cache` stays current without an external subscriber.\n\tdisposers.push(keepalive(isOpen));\n\n\t// Edge-trigger `onExhausted` on the open→closed transition. Subscribing\n\t// here (instead of firing from `buildClosedError`) ensures the callback\n\t// fires exactly once per transition, regardless of how many invoke/stream\n\t// attempts hit the closed gate afterward. Callers that want per-attempt\n\t// notifications should subscribe to `isOpen` directly.\n\tif (opts.onExhausted != null) {\n\t\tconst handler = opts.onExhausted;\n\t\t// Seed `wasOpen` from the FIRST observed DATA rather than assuming\n\t\t// `true`. If caps are already exhausted at construction (e.g.\n\t\t// `calls: 0` or a pre-filled totals source), the push-on-subscribe\n\t\t// DATA=`false` would otherwise be interpreted as an open→closed\n\t\t// transition and fire `onExhausted` before any invoke has been\n\t\t// attempted. `seeded` guards that first observation.\n\t\tlet seeded = false;\n\t\tlet wasOpen = true;\n\t\tconst unsub = isOpen.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 boolean;\n\t\t\t\t\tif (seeded && wasOpen && v === false) {\n\t\t\t\t\t\tconst which = pickExhaustedKey(totals.cache ?? EMPTY_TOTALS, opts.caps);\n\t\t\t\t\t\tif (which) handler(which);\n\t\t\t\t\t}\n\t\t\t\t\twasOpen = v;\n\t\t\t\t\tseeded = true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tdisposers.push(unsub);\n\t}\n\n\tconst buildClosedError = (): BudgetExhaustedError | undefined => {\n\t\tif (isOpen.cache === false) {\n\t\t\tconst t = totals.cache ?? EMPTY_TOTALS;\n\t\t\tconst which = pickExhaustedKey(t, opts.caps);\n\t\t\treturn new BudgetExhaustedError(\n\t\t\t\twhich ?? \"budget\",\n\t\t\t\topts.caps[which ?? \"calls\"] ?? 0,\n\t\t\t\twhichValue(t, which ?? \"calls\"),\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tconst record = (\n\t\tusage: TokenUsage,\n\t\tmeta: {\n\t\t\tmodel: string;\n\t\t\ttier?: string;\n\t\t\tstartNs: number;\n\t\t\tmethod: \"invoke\" | \"stream\";\n\t\t\terror?: { type: string; message: string };\n\t\t},\n\t): void => {\n\t\tconst provider = inner.provider;\n\t\tconst event: CallStatsEvent = buildCallStats({\n\t\t\tprovider,\n\t\t\tmodel: meta.model,\n\t\t\ttier: meta.tier,\n\t\t\tusage,\n\t\t\tstartNs: meta.startNs,\n\t\t\tmethod: meta.method,\n\t\t\t...(meta.error ? { error: meta.error } : {}),\n\t\t});\n\t\tlog.append(event);\n\t\tconst prev = totals.cache ?? EMPTY_TOTALS;\n\t\tconst usd = opts.pricingFn\n\t\t\t? prev.usd + opts.pricingFn(usage, { model: meta.model, provider, tier: meta.tier }).total\n\t\t\t: prev.usd;\n\t\ttotals.emit({\n\t\t\tcalls: prev.calls + 1,\n\t\t\tinputTokens: prev.inputTokens + sumInputTokens(usage),\n\t\t\toutputTokens: prev.outputTokens + sumOutputTokens(usage),\n\t\t\tusd,\n\t\t});\n\t};\n\n\tconst reset = (): void => {\n\t\tlog.clear();\n\t\ttotals.emit(makeEmptyTotals());\n\t};\n\n\t// Lock 3.C (Phase 13.6.B): auto-wire adapter abort. Track in-flight\n\t// controllers so the open→closed transition can cancel calls that\n\t// started before the budget exhausted. Encodes L2.42-honest-cost's\n\t// \"two pieces needed\" rule (observability bubble + auto-wired abort)\n\t// into the primitive itself — no manual hookup required.\n\t//\n\t// DS-14.5 / AB-1: honoring `opts.signal` is now a hard adapter\n\t// contract (the `abortCapable` flag + this dev-mode warning were\n\t// removed pre-1.0). The budget gate fans out the AbortSignal on\n\t// exhaustion and every adapter is required to cancel its underlying\n\t// I/O — no escape hatch, no silent burn-through.\n\tconst inflight = new Set<AbortController>();\n\tlet isOpenSeeded = false;\n\tlet isOpenWasOpen = true;\n\tconst isOpenAbortUnsub = isOpen.subscribe((msgs) => {\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] !== DATA) continue;\n\t\t\tconst v = m[1] as boolean;\n\t\t\tif (isOpenSeeded && isOpenWasOpen && v === false && inflight.size > 0) {\n\t\t\t\tconst reason = buildClosedError() ?? new Error(\"budget exhausted\");\n\t\t\t\tfor (const ctrl of inflight) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tctrl.abort(reason);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* best-effort abort fan-out */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tisOpenWasOpen = v;\n\t\t\tisOpenSeeded = true;\n\t\t}\n\t});\n\tdisposers.push(isOpenAbortUnsub);\n\n\tfunction combineSignals(callerSignal: AbortSignal | undefined): {\n\t\tctrl: AbortController;\n\t\tcleanup: () => void;\n\t} {\n\t\tconst ctrl = new AbortController();\n\t\t// If the budget is already closed when invoke starts, abort\n\t\t// immediately so the inner call never starts.\n\t\tif (isOpen.cache === false) {\n\t\t\tctrl.abort(buildClosedError() ?? new Error(\"budget exhausted\"));\n\t\t}\n\t\tconst onCallerAbort = (): void => {\n\t\t\tif (!ctrl.signal.aborted) ctrl.abort((callerSignal as AbortSignal).reason);\n\t\t};\n\t\tif (callerSignal != null) {\n\t\t\tif (callerSignal.aborted) {\n\t\t\t\tctrl.abort(callerSignal.reason);\n\t\t\t} else {\n\t\t\t\tcallerSignal.addEventListener(\"abort\", onCallerAbort, { once: true });\n\t\t\t}\n\t\t}\n\t\tinflight.add(ctrl);\n\t\tconst cleanup = (): void => {\n\t\t\tinflight.delete(ctrl);\n\t\t\tif (callerSignal != null) callerSignal.removeEventListener(\"abort\", onCallerAbort);\n\t\t};\n\t\treturn { ctrl, cleanup };\n\t}\n\n\tconst wrap: LLMAdapter = adapterWrapper(inner, {\n\t\tinvoke(messages, invokeOpts) {\n\t\t\tconst closedErr = buildClosedError();\n\t\t\tif (closedErr) return Promise.reject(closedErr);\n\t\t\tconst startNs = monotonicNs();\n\t\t\tconst model = inner.model ?? invokeOpts?.model ?? \"\";\n\t\t\tconst { ctrl, cleanup } = combineSignals(invokeOpts?.signal);\n\t\t\tconst recordResp = (resp: LLMResponse): LLMResponse => {\n\t\t\t\tcleanup();\n\t\t\t\trecord(resp.usage ?? emptyUsageStub(), {\n\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? resp.model ?? \"\",\n\t\t\t\t\ttier: invokeOpts?.tier ?? resp.tier,\n\t\t\t\t\tstartNs,\n\t\t\t\t\tmethod: \"invoke\",\n\t\t\t\t});\n\t\t\t\treturn resp;\n\t\t\t};\n\t\t\tconst recordErr = (err: unknown): void => {\n\t\t\t\tcleanup();\n\t\t\t\tconst e = err as Error | undefined;\n\t\t\t\trecord(emptyUsageStub(), {\n\t\t\t\t\tmodel,\n\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\tstartNs,\n\t\t\t\t\tmethod: \"invoke\",\n\t\t\t\t\terror: { type: e?.name ?? \"Error\", message: e?.message ?? String(err) },\n\t\t\t\t});\n\t\t\t};\n\t\t\tconst innerOpts = { ...(invokeOpts ?? {}), signal: ctrl.signal };\n\t\t\treturn adaptInvokeResult(inner.invoke(messages, innerOpts), {\n\t\t\t\tonResp: recordResp,\n\t\t\t\tonError: recordErr,\n\t\t\t\tname: \"budgetGate/invokeTap\",\n\t\t\t});\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst closedErr = buildClosedError();\n\t\t\tif (closedErr) throw closedErr;\n\t\t\tconst startNs = monotonicNs();\n\t\t\tlet finalUsage: TokenUsage | undefined;\n\t\t\tconst { ctrl, cleanup } = combineSignals(invokeOpts?.signal);\n\t\t\tconst innerOpts = { ...(invokeOpts ?? {}), signal: ctrl.signal };\n\t\t\ttry {\n\t\t\t\tfor await (const delta of inner.stream(messages, innerOpts)) {\n\t\t\t\t\tif (delta.type === \"usage\") finalUsage = delta.usage;\n\t\t\t\t\tyield delta;\n\t\t\t\t}\n\t\t\t\tcleanup();\n\t\t\t\trecord(finalUsage ?? emptyUsageStub(), {\n\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? \"\",\n\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\tstartNs,\n\t\t\t\t\tmethod: \"stream\",\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tcleanup();\n\t\t\t\tconst error = err as Error;\n\t\t\t\trecord(finalUsage ?? emptyUsageStub(), {\n\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? \"\",\n\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\tstartNs,\n\t\t\t\t\tmethod: \"stream\",\n\t\t\t\t\terror: { type: error?.name ?? \"Error\", message: error?.message ?? String(err) },\n\t\t\t\t});\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t});\n\n\twithLayer(wrap, \"withBudgetGate\", inner);\n\n\tconst dispose = (): void => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\t// Defensive last gasp: abort any in-flight controllers so the\n\t\t// awaited Promises don't strand their callers waiting on a soon-\n\t\t// to-be-disposed adapter.\n\t\tconst reason = new Error(\"withBudgetGate disposed\");\n\t\tfor (const ctrl of inflight) {\n\t\t\ttry {\n\t\t\t\tctrl.abort(reason);\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t}\n\t\tinflight.clear();\n\t\tfor (const d of disposers) {\n\t\t\ttry {\n\t\t\t\td();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t}\n\t\tdisposers.length = 0;\n\t};\n\n\treturn { adapter: wrap, budget: { totals, isOpen, log, reset, dispose } };\n}\n\nfunction pickExhaustedKey(t: BudgetTotals, caps: BudgetCaps): keyof BudgetCaps | undefined {\n\tif (caps.calls != null && t.calls >= caps.calls) return \"calls\";\n\tif (caps.inputTokens != null && t.inputTokens >= caps.inputTokens) return \"inputTokens\";\n\tif (caps.outputTokens != null && t.outputTokens >= caps.outputTokens) return \"outputTokens\";\n\tif (caps.usd != null && t.usd >= caps.usd) return \"usd\";\n\treturn undefined;\n}\n\nfunction whichValue(t: BudgetTotals, which: keyof BudgetCaps): number {\n\tswitch (which) {\n\t\tcase \"calls\":\n\t\t\treturn t.calls;\n\t\tcase \"inputTokens\":\n\t\t\treturn t.inputTokens;\n\t\tcase \"outputTokens\":\n\t\t\treturn t.outputTokens;\n\t\tcase \"usd\":\n\t\t\treturn t.usd;\n\t}\n}\n\nexport type { ChatMessage, LLMInvokeOptions };\n","/**\n * `withDryRun` — short-circuit to a fake adapter when a flag is on.\n *\n * Useful for CI / preflight / cost-safety pipelines: wrap a real adapter,\n * pass `enabled: true` (or a reactive flag) to bypass the wire call. Default\n * shim is {@link dryRunAdapter}; callers can supply their own.\n *\n * **Returns `{adapter, dispose}`** — call `dispose()` to release the internal\n * keepalive on the reactive `enabled` input. Long-lived adapter instances\n * (module-level singletons) can ignore dispose; transient adapters (per-\n * request or per-user) should call it on teardown to allow the source to\n * be GC'd.\n */\n\nimport { fromAny, keepalive, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type { LLMAdapter } from \"../core/types.js\";\nimport { dryRunAdapter } from \"../providers/dry-run.js\";\n\nexport interface WithDryRunOptions {\n\t/**\n\t * Toggle — `true` always dry-runs; `false` always passes through; a\n\t * `NodeInput<boolean>` reads the current value at call time (factory-time\n\t * seed pattern, live-tunable).\n\t */\n\tenabled: NodeInput<boolean>;\n\t/** Dry-run adapter override. Default: `dryRunAdapter({ provider: inner.provider, model: inner.model })`. */\n\tmock?: LLMAdapter;\n}\n\nexport interface WithDryRunBundle {\n\tadapter: LLMAdapter;\n\t/**\n\t * Release the internal keepalive subscription on the reactive `enabled`\n\t * input. Idempotent. Safe to ignore on long-lived adapters.\n\t */\n\tdispose(): void;\n}\n\nexport function withDryRun(inner: LLMAdapter, opts: WithDryRunOptions): WithDryRunBundle {\n\tconst mock = opts.mock ?? dryRunAdapter({ provider: inner.provider, model: inner.model });\n\n\t// Normalize the enabled input: literal boolean stays literal; NodeInput<boolean>\n\t// gets bridged so we can read .cache at call time (factory-time seed per\n\t// COMPOSITION-GUIDE §28). Keep the node alive so push-on-subscribe and\n\t// derived-chain recomputation keep the cache current — otherwise a reactive\n\t// flag would stay at its initial value forever.\n\tconst enabledLiteral = typeof opts.enabled === \"boolean\" ? (opts.enabled as boolean) : undefined;\n\tconst enabledNode =\n\t\tenabledLiteral === undefined ? fromAny(opts.enabled as NodeInput<boolean>) : undefined;\n\tlet unsubKeepalive: (() => void) | undefined;\n\tif (enabledNode) unsubKeepalive = keepalive(enabledNode);\n\n\tconst isEnabled = (): boolean => {\n\t\tif (enabledLiteral !== undefined) return enabledLiteral;\n\t\treturn Boolean(enabledNode?.cache);\n\t};\n\n\tconst adapter: LLMAdapter = adapterWrapper(inner, {\n\t\tinvoke(messages, invokeOpts) {\n\t\t\treturn isEnabled() ? mock.invoke(messages, invokeOpts) : inner.invoke(messages, invokeOpts);\n\t\t},\n\n\t\tstream(messages, invokeOpts) {\n\t\t\treturn isEnabled() ? mock.stream(messages, invokeOpts) : inner.stream(messages, invokeOpts);\n\t\t},\n\t});\n\twithLayer(adapter, \"withDryRun\", inner);\n\n\tconst dispose = (): void => {\n\t\tif (unsubKeepalive) {\n\t\t\tunsubKeepalive();\n\t\t\tunsubKeepalive = undefined;\n\t\t}\n\t};\n\n\treturn { adapter, dispose };\n}\n","/**\n * HTTP 429 / rate-limit parser.\n *\n * Produces a {@link RateLimitSignal} from provider HTTP errors so adaptive\n * rate limiters can tighten effective limits. Normalizes:\n * - `Retry-After` (seconds or HTTP-date)\n * - `x-ratelimit-reset` / `x-ratelimit-reset-tokens` (epoch secs or duration)\n * - `x-ratelimit-remaining-{requests,tokens}` + `x-ratelimit-limit-*`\n * - Anthropic `anthropic-ratelimit-*` headers\n * - OpenAI / OpenRouter / Groq headers (same family)\n * - Error message regex fallbacks for providers without structured headers\n */\n\nimport type { RateLimitSignal } from \"../../../resilience/adaptive-rate-limiter.js\";\n\nexport interface HttpErrorLike {\n\tstatus?: number;\n\theaders?: Headers | Record<string, string | string[] | undefined>;\n\tmessage?: string;\n}\n\n/**\n * Extract a {@link RateLimitSignal} from a fetch-style error object, a Response,\n * or any object exposing `.status` + `.headers` + `.message`.\n *\n * Returns `undefined` if no rate-limit information can be extracted.\n */\nexport function parseRateLimitFromError(err: unknown): RateLimitSignal | undefined {\n\tif (err == null || typeof err !== \"object\") return undefined;\n\tconst like = err as HttpErrorLike;\n\tconst status = like.status;\n\tconst headerLookup = toHeaderGetter(like.headers);\n\n\t// Only respond on 429 or 503 (some providers use 503 for rate-limits).\n\tif (status !== 429 && status !== 503 && !looksLikeRateLimitMessage(like.message)) {\n\t\treturn undefined;\n\t}\n\n\tconst sig: RateLimitSignal = {};\n\n\tconst retryAfter = headerLookup(\"retry-after\");\n\tconst retryAfterMs = parseRetryAfter(retryAfter);\n\tif (retryAfterMs != null) sig.retryAfterMs = retryAfterMs;\n\n\t// Anthropic: anthropic-ratelimit-requests-reset (ISO-8601 timestamp)\n\tconst anthReqReset = headerLookup(\"anthropic-ratelimit-requests-reset\");\n\tif (anthReqReset) {\n\t\tconst ms = parseIsoResetHeaderToDelayMs(anthReqReset);\n\t\tif (ms != null) sig.retryAfterMs = Math.max(sig.retryAfterMs ?? 0, ms);\n\t}\n\tconst anthTokReset = headerLookup(\"anthropic-ratelimit-tokens-reset\");\n\tif (anthTokReset) {\n\t\tconst ms = parseIsoResetHeaderToDelayMs(anthTokReset);\n\t\tif (ms != null) sig.retryAfterMs = Math.max(sig.retryAfterMs ?? 0, ms);\n\t}\n\n\t// OpenAI / OpenRouter / Groq: x-ratelimit-limit-requests, -reset-requests, etc.\n\tconst limitRequests = numHeader(headerLookup, \"x-ratelimit-limit-requests\");\n\tif (limitRequests != null) sig.rpmCap = limitRequests;\n\tconst limitTokens = numHeader(headerLookup, \"x-ratelimit-limit-tokens\");\n\tif (limitTokens != null) sig.tpmCap = limitTokens;\n\n\t// Usage hint: remaining / limit\n\tconst remainingReq = numHeader(headerLookup, \"x-ratelimit-remaining-requests\");\n\tconst remainingTok = numHeader(headerLookup, \"x-ratelimit-remaining-tokens\");\n\tif (remainingReq != null && limitRequests != null && limitRequests > 0) {\n\t\tsig.usageHint ??= {};\n\t\tsig.usageHint.rpm = 1 - remainingReq / limitRequests;\n\t}\n\tif (remainingTok != null && limitTokens != null && limitTokens > 0) {\n\t\tsig.usageHint ??= {};\n\t\tsig.usageHint.tpm = 1 - remainingTok / limitTokens;\n\t}\n\n\t// Fallback: parse retry-after from error message if no header was found.\n\tif (sig.retryAfterMs == null && like.message) {\n\t\tconst msgMs = parseRetryAfterFromMessage(like.message);\n\t\tif (msgMs != null) sig.retryAfterMs = msgMs;\n\t}\n\n\t// Preserve raw headers for user-specific downstream logic.\n\tif (like.headers) sig.metadata = { headers: serializeHeaders(like.headers) };\n\n\tif (\n\t\tsig.retryAfterMs == null &&\n\t\tsig.rpmCap == null &&\n\t\tsig.tpmCap == null &&\n\t\tsig.usageHint == null\n\t) {\n\t\t// Nothing actionable extracted — still emit empty signal so consumers can\n\t\t// count occurrences (metadata carries the headers).\n\t\treturn sig.metadata ? sig : undefined;\n\t}\n\n\treturn sig;\n}\n\n// ---------------------------------------------------------------------------\n// Header access\n// ---------------------------------------------------------------------------\n\ntype HeaderGetter = (name: string) => string | undefined;\n\nfunction toHeaderGetter(h: HttpErrorLike[\"headers\"]): HeaderGetter {\n\tif (!h) return () => undefined;\n\tif (typeof (h as Headers).get === \"function\") {\n\t\tconst hh = h as Headers;\n\t\treturn (name) => hh.get(name) ?? hh.get(name.toLowerCase()) ?? undefined;\n\t}\n\tconst record = h as Record<string, string | string[] | undefined>;\n\tconst lc: Record<string, string | undefined> = {};\n\tfor (const [k, v] of Object.entries(record)) {\n\t\tconst sv = Array.isArray(v) ? v.join(\", \") : v;\n\t\tif (sv != null) lc[k.toLowerCase()] = sv;\n\t}\n\treturn (name) => lc[name.toLowerCase()];\n}\n\nfunction serializeHeaders(h: NonNullable<HttpErrorLike[\"headers\"]>): Record<string, string> {\n\tconst out: Record<string, string> = {};\n\tif (typeof (h as Headers).forEach === \"function\") {\n\t\t(h as Headers).forEach((v, k) => {\n\t\t\tout[k] = v;\n\t\t});\n\t\treturn out;\n\t}\n\tfor (const [k, v] of Object.entries(h as Record<string, string | string[] | undefined>)) {\n\t\tif (v != null) out[k] = Array.isArray(v) ? v.join(\", \") : v;\n\t}\n\treturn out;\n}\n\nfunction numHeader(getter: HeaderGetter, name: string): number | undefined {\n\tconst raw = getter(name);\n\tif (raw == null) return undefined;\n\tconst n = Number(raw);\n\treturn Number.isFinite(n) ? n : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Retry-after parsing\n// ---------------------------------------------------------------------------\n\nfunction parseRetryAfter(raw: string | undefined): number | undefined {\n\tif (!raw) return undefined;\n\tconst trimmed = raw.trim();\n\tconst asNum = Number(trimmed);\n\tif (Number.isFinite(asNum) && asNum >= 0) return asNum * 1000;\n\t// HTTP-date fallback.\n\tconst ts = Date.parse(trimmed);\n\tif (Number.isFinite(ts)) {\n\t\tconst delta = ts - Date.now();\n\t\tif (delta > 0) return delta;\n\t}\n\treturn undefined;\n}\n\n/**\n * Parse an Anthropic `anthropic-ratelimit-{requests,tokens}-reset` header\n * into a delay (milliseconds until reset). These headers are documented\n * as ISO-8601 absolute timestamps; we use `Date.parse` and clamp to zero\n * for headers that have already elapsed. Returns `undefined` for unparseable\n * values — no numeric-epoch heuristic (providers don't send numeric resets\n * here, and the old heuristic was ambiguous across seconds-vs-millis).\n */\nfunction parseIsoResetHeaderToDelayMs(raw: string): number | undefined {\n\tif (!raw) return undefined;\n\tconst ts = Date.parse(raw);\n\tif (Number.isFinite(ts)) return Math.max(0, ts - Date.now());\n\treturn undefined;\n}\n\nconst RETRY_MSG_RE = /retry\\s+(?:in|after)\\s+(\\d+(?:\\.\\d+)?)\\s*(ms|s|sec|seconds?|m|min|minutes?)/i;\n\nfunction parseRetryAfterFromMessage(msg: string): number | undefined {\n\tconst m = RETRY_MSG_RE.exec(msg);\n\tif (!m) return undefined;\n\tconst n = Number(m[1]);\n\tif (!Number.isFinite(n)) return undefined;\n\tconst unit = (m[2] ?? \"s\").toLowerCase();\n\tif (unit === \"ms\") return n;\n\tif (unit.startsWith(\"s\")) return n * 1000;\n\tif (unit.startsWith(\"m\")) return n * 60_000;\n\treturn undefined;\n}\n\nconst RATE_LIMIT_MSG_RE = /rate\\s*limit|too\\s*many\\s*requests|quota|429/i;\n\nfunction looksLikeRateLimitMessage(msg: string | undefined): boolean {\n\treturn !!msg && RATE_LIMIT_MSG_RE.test(msg);\n}\n","/**\n * `withRateLimiter` — adapter middleware bridging to the reactive\n * `adaptiveRateLimiter` primitive.\n *\n * - Consumes live `rpm`/`tpm` caps as reactive `NodeInput<number>` so\n * callers can retune at runtime (e.g. from a `ModelLimits.rpm` node).\n * - Adapts to provider 429 responses via `http429Parser` fed into the\n * limiter's `adaptation` signal.\n * - `costFn` estimates token cost pre-call (e.g. char-based approximation);\n * the post-call actual usage is fed back via `limiter.recordUsage()`.\n */\n\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport {\n\ttype AdaptiveRateLimiterBundle,\n\tadaptiveRateLimiter,\n\ttype RateLimitSignal,\n} from \"../../../resilience/adaptive-rate-limiter.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n} from \"../core/types.js\";\nimport { emptyUsage, sumInputTokens, sumOutputTokens } from \"../core/types.js\";\nimport { parseRateLimitFromError } from \"./http429-parser.js\";\n\nexport interface WithRateLimiterOptions {\n\t/** Live rpm cap (defaults to `Infinity`). */\n\trpm?: NodeInput<number>;\n\t/** Live tpm cap (defaults to `Infinity`). */\n\ttpm?: NodeInput<number>;\n\t/**\n\t * Pre-call token-cost estimate. Default: 0 (only rpm gates). Override with\n\t * e.g. a char-based heuristic:\n\t * `(msgs) => Math.ceil(msgs.reduce((s, m) => s + m.content.length, 0) / 4)`.\n\t */\n\tcostFn?: (messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => number;\n\t/**\n\t * Manual adaptation signal source. Defaults to a signal derived from\n\t * provider errors via `parseRateLimitFromError` — users can supply a\n\t * custom signal chain if they route errors elsewhere.\n\t */\n\tadaptation?: NodeInput<RateLimitSignal>;\n\tburstMultiplier?: number;\n\tname?: string;\n\t/**\n\t * Share an existing {@link AdaptiveRateLimiterBundle} across multiple\n\t * adapter wraps. When provided, `withRateLimiter` reuses this bundle\n\t * instead of constructing a new one — useful when the RPM/TPM cap is\n\t * logically per-provider but the caller wants to harden multiple adapters\n\t * (e.g. primary + fallback of the same vendor) against the shared cap.\n\t *\n\t * When `limiter` is set, `rpm` / `tpm` / `adaptation` / `burstMultiplier`\n\t * / `name` are ignored (the supplied bundle owns those). `costFn` is still\n\t * used per-wrap — each wrap supplies its own cost estimator.\n\t */\n\tlimiter?: AdaptiveRateLimiterBundle;\n}\n\n/**\n * Wrap an adapter with adaptive rate limiting. Returns `{adapter, limiter}`\n * so callers can subscribe to limiter internals (rpmAvailable, pending, etc.)\n * for dashboards.\n */\nexport function withRateLimiter(\n\tinner: LLMAdapter,\n\topts: WithRateLimiterOptions = {},\n): { adapter: LLMAdapter; limiter: AdaptiveRateLimiterBundle } {\n\tconst limiter =\n\t\topts.limiter ??\n\t\tadaptiveRateLimiter({\n\t\t\tname: opts.name ?? \"rateLimiter\",\n\t\t\trpm: opts.rpm,\n\t\t\ttpm: opts.tpm,\n\t\t\tadaptation: opts.adaptation,\n\t\t\tburstMultiplier: opts.burstMultiplier,\n\t\t});\n\n\tconst estimateCost = (\n\t\tmessages: readonly ChatMessage[],\n\t\tinvokeOpts: LLMInvokeOptions | undefined,\n\t): number => {\n\t\tif (opts.costFn) return opts.costFn(messages, invokeOpts);\n\t\treturn 0;\n\t};\n\n\tconst handleError = (err: unknown): void => {\n\t\tconst sig = parseRateLimitFromError(err);\n\t\tif (sig) limiter.recordSignal(sig);\n\t};\n\n\tconst wrap: LLMAdapter = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst tokenCost = estimateCost(messages, invokeOpts);\n\t\t\tawait limiter.acquire({ requestCost: 1, tokenCost, signal: invokeOpts?.signal });\n\t\t\ttry {\n\t\t\t\tconst resp = await firstValueFrom(fromAny(inner.invoke(messages, invokeOpts)));\n\t\t\t\tconst usage = resp.usage ?? emptyUsage();\n\t\t\t\tconst actual = sumInputTokens(usage) + sumOutputTokens(usage);\n\t\t\t\tconst delta = actual - tokenCost;\n\t\t\t\tif (delta > 0) limiter.recordUsage(delta);\n\t\t\t\treturn resp;\n\t\t\t} catch (err) {\n\t\t\t\thandleError(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst tokenCost = estimateCost(messages, invokeOpts);\n\t\t\tawait limiter.acquire({ requestCost: 1, tokenCost, signal: invokeOpts?.signal });\n\t\t\ttry {\n\t\t\t\tlet finalTokens = 0;\n\t\t\t\tfor await (const delta of inner.stream(messages, invokeOpts)) {\n\t\t\t\t\tif (delta.type === \"usage\") {\n\t\t\t\t\t\tfinalTokens = sumInputTokens(delta.usage) + sumOutputTokens(delta.usage);\n\t\t\t\t\t}\n\t\t\t\t\tyield delta;\n\t\t\t\t}\n\t\t\t\tconst d = finalTokens - tokenCost;\n\t\t\t\tif (d > 0) limiter.recordUsage(d);\n\t\t\t} catch (err) {\n\t\t\t\thandleError(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t});\n\twithLayer(wrap, \"withRateLimiter\", inner);\n\n\treturn { adapter: wrap, limiter };\n}\n","/**\n * `cascadingLlmAdapter` — N-tier fallback over any mix of LLM adapters.\n *\n * Same structural pattern as `cascadingCache` and `Graph.attachSnapshotStorage`:\n * ordered list, first-success wins, per-tier breaker optional, filter gates\n * per request. Semantics:\n *\n * - `invoke()`: try tier 0 first. On error (or breaker-open), fall through\n * to tier 1, 2, ... until one succeeds or all fail.\n * - `stream()`: tries to start the stream on tier 0; once tokens begin, it\n * commits — failures in mid-stream surface rather than re-starting on the\n * next tier (would double-bill and confuse consumers). **State-machine\n * consumers (usage accounting, UI accumulators) must handle errors in a\n * catch block — no synthetic `{type: \"finish\"}` is emitted after a thrown\n * stream error.**\n * - `filter`: skips a tier for requests that use features it doesn't\n * support (e.g., Chrome Nano can't do tool use).\n * - `breaker`: per-tier circuit; when open, cascade treats the tier as\n * unavailable and moves on immediately.\n *\n * On exhaustion, throws `AllTiersExhaustedError` with separate `skipped` and\n * `failed` collections so consumers can distinguish \"no tier applicable\"\n * from \"all tiers failed\".\n */\n\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport {\n\ttype CircuitBreaker,\n\ttype CircuitBreakerOptions,\n\tcircuitBreaker,\n} from \"../../../../utils/resilience/index.js\";\nimport { withLayer } from \"../_internal/wrappers.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n} from \"../core/types.js\";\n\nexport interface AdapterTier {\n\tname: string;\n\tadapter: LLMAdapter;\n\t/** Per-tier circuit breaker. If omitted, no breaker on this tier. */\n\tbreaker?: CircuitBreakerOptions | CircuitBreaker;\n\t/** Skip this tier when the request doesn't fit (e.g. Chrome Nano + tools). */\n\tfilter?: (messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => boolean;\n}\n\nexport interface CascadeExhaustionReport {\n\t/** Tiers that never ran (filter returned false, or breaker was open). */\n\treadonly skipped: ReadonlyArray<{ name: string; reason: \"filter\" | \"breaker\" }>;\n\t/** Tiers that ran and threw. */\n\treadonly failed: ReadonlyMap<string, unknown>;\n}\n\nexport interface CascadingLlmAdapterOptions {\n\tonFallback?: (from: string, to: string, error: unknown) => void;\n\tonExhausted?: (report: CascadeExhaustionReport) => void;\n\t/** Whether to attempt stream retry on subsequent tiers before first chunk. Default true. */\n\tstreamRetryBeforeFirstChunk?: boolean;\n}\n\ninterface ResolvedTier {\n\tname: string;\n\tadapter: LLMAdapter;\n\tbreaker?: CircuitBreaker;\n\tfilter?: (messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => boolean;\n}\n\nexport class AllTiersExhaustedError extends Error {\n\toverride name = \"AllTiersExhaustedError\";\n\treadonly skipped: ReadonlyArray<{ name: string; reason: \"filter\" | \"breaker\" }>;\n\treadonly failed: ReadonlyMap<string, unknown>;\n\tconstructor(report: CascadeExhaustionReport) {\n\t\tconst parts: string[] = [];\n\t\tif (report.failed.size > 0) parts.push(`failed=[${[...report.failed.keys()].join(\",\")}]`);\n\t\tif (report.skipped.length > 0) {\n\t\t\tparts.push(`skipped=[${report.skipped.map((s) => `${s.name}(${s.reason})`).join(\",\")}]`);\n\t\t}\n\t\tsuper(`All LLM adapter tiers exhausted: ${parts.join(\" \")}`);\n\t\tthis.skipped = report.skipped;\n\t\tthis.failed = report.failed;\n\t}\n}\n\nexport function cascadingLlmAdapter(\n\ttiers: readonly AdapterTier[],\n\topts: CascadingLlmAdapterOptions = {},\n): LLMAdapter {\n\tif (tiers.length === 0) throw new RangeError(\"cascadingLlmAdapter: tiers must be non-empty\");\n\n\tconst resolved: ResolvedTier[] = tiers.map((t) => ({\n\t\tname: t.name,\n\t\tadapter: t.adapter,\n\t\tfilter: t.filter,\n\t\tbreaker: t.breaker\n\t\t\t? \"canExecute\" in t.breaker\n\t\t\t\t? (t.breaker as CircuitBreaker)\n\t\t\t\t: circuitBreaker(t.breaker as CircuitBreakerOptions)\n\t\t\t: undefined,\n\t}));\n\n\tconst streamRetryBeforeFirstChunk = opts.streamRetryBeforeFirstChunk ?? true;\n\n\tconst cascade: LLMAdapter = {\n\t\tprovider: \"cascading\",\n\t\tmodel: undefined,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst skipped: Array<{ name: string; reason: \"filter\" | \"breaker\" }> = [];\n\t\t\tconst failed = new Map<string, unknown>();\n\t\t\tfor (let i = 0; i < resolved.length; i++) {\n\t\t\t\tconst t = resolved[i];\n\t\t\t\tif (t.filter && !t.filter(messages, invokeOpts)) {\n\t\t\t\t\tskipped.push({ name: t.name, reason: \"filter\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (t.breaker && !t.breaker.canExecute()) {\n\t\t\t\t\tskipped.push({ name: t.name, reason: \"breaker\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst resp = await firstValueFrom(fromAny(t.adapter.invoke(messages, invokeOpts)));\n\t\t\t\t\tt.breaker?.recordSuccess();\n\t\t\t\t\treturn { ...resp, metadata: { ...(resp.metadata ?? {}), tier: t.name } };\n\t\t\t\t} catch (err) {\n\t\t\t\t\tfailed.set(t.name, err);\n\t\t\t\t\tt.breaker?.recordFailure(err);\n\t\t\t\t\tconst next = resolved[i + 1];\n\t\t\t\t\tif (next) opts.onFallback?.(t.name, next.name, err);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst report: CascadeExhaustionReport = { skipped, failed };\n\t\t\topts.onExhausted?.(report);\n\t\t\tthrow new AllTiersExhaustedError(report);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst skipped: Array<{ name: string; reason: \"filter\" | \"breaker\" }> = [];\n\t\t\tconst failed = new Map<string, unknown>();\n\t\t\tfor (let i = 0; i < resolved.length; i++) {\n\t\t\t\tconst t = resolved[i];\n\t\t\t\tif (t.filter && !t.filter(messages, invokeOpts)) {\n\t\t\t\t\tskipped.push({ name: t.name, reason: \"filter\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (t.breaker && !t.breaker.canExecute()) {\n\t\t\t\t\tskipped.push({ name: t.name, reason: \"breaker\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet yieldedAny = false;\n\t\t\t\ttry {\n\t\t\t\t\tfor await (const delta of t.adapter.stream(messages, invokeOpts)) {\n\t\t\t\t\t\tyieldedAny = true;\n\t\t\t\t\t\tyield delta;\n\t\t\t\t\t}\n\t\t\t\t\tt.breaker?.recordSuccess();\n\t\t\t\t\treturn;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tfailed.set(t.name, err);\n\t\t\t\t\tt.breaker?.recordFailure(err);\n\t\t\t\t\tif (yieldedAny || !streamRetryBeforeFirstChunk) {\n\t\t\t\t\t\t// Past first chunk — stream commitment. Propagate immediately.\n\t\t\t\t\t\t// Consumers handle the thrown error in their catch; no synthetic\n\t\t\t\t\t\t// finish delta is emitted (see JSDoc at top of file). We do NOT\n\t\t\t\t\t\t// call `onExhausted` here because other tiers were never tried —\n\t\t\t\t\t\t// the error is a single-tier commitment failure, not a\n\t\t\t\t\t\t// \"no-tier-worked\" condition.\n\t\t\t\t\t\tthrow err;\n\t\t\t\t\t}\n\t\t\t\t\tconst next = resolved[i + 1];\n\t\t\t\t\tif (next) opts.onFallback?.(t.name, next.name, err);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst report: CascadeExhaustionReport = { skipped, failed };\n\t\t\topts.onExhausted?.(report);\n\t\t\tthrow new AllTiersExhaustedError(report);\n\t\t},\n\t};\n\twithLayer(cascade, `cascade[${resolved.map((t) => t.name).join(\",\")}]`);\n\treturn cascade;\n}\n\n/**\n * Tiny type-safe constructor for an {@link AdapterTier}. Cleans up the\n * heterogeneous array-type cast users (and `browser-presets.ts`) had to write\n * by hand. Per Wave A Unit 13 decision.\n *\n * @example\n * ```ts\n * cascadingLlmAdapter([\n * tier(\"local\", webllmAdapter(...)),\n * tier(\"cloud\", anthropicAdapter(...), { breaker: { failureThreshold: 5 } }),\n * ]);\n * ```\n *\n * @category ai\n */\nexport function tier(\n\tname: string,\n\tadapter: LLMAdapter,\n\topts?: { breaker?: CircuitBreakerOptions | CircuitBreaker; filter?: AdapterTier[\"filter\"] },\n): AdapterTier {\n\tconst out: AdapterTier = { name, adapter };\n\tif (opts?.breaker) out.breaker = opts.breaker;\n\tif (opts?.filter) out.filter = opts.filter;\n\treturn out;\n}\n","/**\n * `withRetry` — retry `invoke()` / `stream()` on transient errors.\n *\n * Streaming retry is tricky: we retry only if the stream fails before\n * yielding any tokens. Once tokens have started flowing, we surface the\n * error to avoid replaying from scratch (which would double-bill and\n * confuse consumers). Opt out of streaming retry via `opts.retryStreaming = false`.\n *\n * Uses `ResettableTimer` for backoff sleeps (spec §5.10 escape hatch, same\n * pattern as `extra/resilience.ts`). Abort-aware — early-aborts before the\n * first attempt and cleans up the abort listener on both the timer-fires\n * and abort paths.\n */\n\nimport { ResettableTimer } from \"@graphrefly/pure-ts/core\";\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type { LLMAdapter, LLMResponse, StreamDelta } from \"../core/types.js\";\n\nexport interface WithRetryOptions {\n\t/** Max total attempts (including the first). Default 3. */\n\tattempts?: number;\n\t/** Base delay in ms. Default 500. */\n\tbaseDelayMs?: number;\n\t/** Max delay in ms. Default 10_000. */\n\tmaxDelayMs?: number;\n\t/**\n\t * Delay strategy. Default `\"decorrelated\"` — AWS-style `random(baseDelay,\n\t * min(maxDelay, prev * 3))` which smooths retry storms and matches common\n\t * SDK expectations. `\"exp\"` and `\"linear\"` produce deterministic schedules\n\t * when `jitter: false`.\n\t */\n\tstrategy?: \"exp\" | \"linear\" | \"decorrelated\";\n\t/**\n\t * Add randomized jitter. Ignored for `strategy: \"decorrelated\"` (which is\n\t * inherently jittered). For `exp`/`linear`, symmetric jitter in `[0.5x,\n\t * 1.5x]` of the nominal delay.\n\t */\n\tjitter?: boolean;\n\t/**\n\t * Predicate: should this error trigger a retry? Default retries network /\n\t * 5xx / 429 / transient errors, but not 4xx (other than 429), aborts, or\n\t * `BudgetExhaustedError` from upstream middleware.\n\t */\n\tshouldRetry?: (err: unknown, attempt: number) => boolean;\n\t/** Retry streaming calls if they fail pre-first-token. Default true. */\n\tretryStreaming?: boolean;\n}\n\nfunction makeAbortError(reason = \"aborted\"): Error {\n\tconst err = new Error(reason) as Error & { name: string };\n\terr.name = \"AbortError\";\n\treturn err;\n}\n\n/**\n * Promise-based abort-aware sleep using `ResettableTimer`.\n * Spec §5.10 escape hatch — same pattern as `extra/resilience.ts`.\n */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\tif (ms <= 0) return Promise.resolve();\n\tif (signal?.aborted) return Promise.reject(makeAbortError());\n\treturn new Promise((resolve, reject) => {\n\t\tconst timer = new ResettableTimer();\n\t\tlet onAbort: (() => void) | undefined;\n\t\tconst cleanup = (): void => {\n\t\t\ttimer.cancel();\n\t\t\tif (signal && onAbort) signal.removeEventListener(\"abort\", onAbort);\n\t\t};\n\t\ttimer.start(ms, () => {\n\t\t\tcleanup();\n\t\t\tresolve();\n\t\t});\n\t\tif (signal) {\n\t\t\tonAbort = (): void => {\n\t\t\t\tcleanup();\n\t\t\t\treject(makeAbortError());\n\t\t\t};\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t});\n}\n\nexport function withRetry(inner: LLMAdapter, opts: WithRetryOptions = {}): LLMAdapter {\n\tconst attempts = opts.attempts ?? 3;\n\tconst baseDelayMs = opts.baseDelayMs ?? 500;\n\tconst maxDelayMs = opts.maxDelayMs ?? 10_000;\n\tconst strategy = opts.strategy ?? \"decorrelated\";\n\tconst jitter = opts.jitter ?? true;\n\tconst shouldRetry = opts.shouldRetry ?? defaultShouldRetry;\n\tconst retryStreaming = opts.retryStreaming ?? true;\n\n\t// Decorrelated state — carried across the same acquire's retries.\n\tconst delay = (attempt: number, prevDelay: number): number => {\n\t\tif (strategy === \"decorrelated\") {\n\t\t\t// AWS-style: random(baseDelay, min(maxDelay, prevDelay * 3))\n\t\t\tconst upper = Math.min(maxDelayMs, Math.max(baseDelayMs, prevDelay * 3));\n\t\t\treturn baseDelayMs + Math.random() * (upper - baseDelayMs);\n\t\t}\n\t\tconst nominal = strategy === \"exp\" ? baseDelayMs * 2 ** (attempt - 1) : baseDelayMs * attempt;\n\t\tconst bounded = Math.min(maxDelayMs, nominal);\n\t\tif (!jitter) return bounded;\n\t\t// Symmetric jitter: bounded * [0.5, 1.5), clamped.\n\t\tconst jittered = bounded * (0.5 + Math.random());\n\t\treturn Math.min(maxDelayMs, jittered);\n\t};\n\n\tconst wrap = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\tlet lastErr: unknown;\n\t\t\tlet prevDelay = baseDelayMs;\n\t\t\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await firstValueFrom(fromAny(inner.invoke(messages, invokeOpts)));\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlastErr = err;\n\t\t\t\t\tif (attempt >= attempts || !shouldRetry(err, attempt)) throw err;\n\t\t\t\t\tconst waitMs = delay(attempt, prevDelay);\n\t\t\t\t\tprevDelay = waitMs;\n\t\t\t\t\tawait sleep(waitMs, invokeOpts?.signal);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow lastErr;\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\tif (!retryStreaming) {\n\t\t\t\tfor await (const d of inner.stream(messages, invokeOpts)) yield d;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet lastErr: unknown;\n\t\t\tlet prevDelay = baseDelayMs;\n\t\t\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\t\t\tlet yieldedAny = false;\n\t\t\t\ttry {\n\t\t\t\t\tfor await (const d of inner.stream(messages, invokeOpts)) {\n\t\t\t\t\t\tyieldedAny = true;\n\t\t\t\t\t\tyield d;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlastErr = err;\n\t\t\t\t\tif (yieldedAny) throw err;\n\t\t\t\t\tif (attempt >= attempts || !shouldRetry(err, attempt)) throw err;\n\t\t\t\t\tconst waitMs = delay(attempt, prevDelay);\n\t\t\t\t\tprevDelay = waitMs;\n\t\t\t\t\tawait sleep(waitMs, invokeOpts?.signal);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow lastErr;\n\t\t},\n\t});\n\twithLayer(wrap, \"withRetry\", inner);\n\treturn wrap;\n}\n\nfunction defaultShouldRetry(err: unknown, _attempt: number): boolean {\n\tif (err == null) return false;\n\tconst e = err as { name?: string; status?: number; code?: string; message?: string };\n\t// Timeout-family errors — retry by default so each attempt re-arms the\n\t// per-attempt deadline set by `withLLMTimeout`. Checked BEFORE the abort\n\t// guards below because `withLLMTimeout` re-throws its timer-fire path as\n\t// `LLMTimeoutError` even when the underlying fetch rejected with\n\t// AbortError.\n\tif (e.name === \"LLMTimeoutError\") return true;\n\t// Abort-family errors — never retry (caller initiated).\n\tif (e.name === \"AbortError\") return false;\n\tif (e.message === \"aborted\") return false;\n\tif (e.name === \"DOMException\" && e.code != null && Number(e.code) === 20 /* ABORT_ERR */) {\n\t\treturn false;\n\t}\n\tif (e.name === \"BudgetExhaustedError\") return false;\n\tif (e.name === \"CircuitOpenError\") return false;\n\tif (e.status != null) {\n\t\tif (e.status === 429) return true;\n\t\tif (e.status >= 500 && e.status < 600) return true;\n\t\treturn false;\n\t}\n\t// Network-level errors often have codes like ECONNRESET, ENOTFOUND, etc.\n\tif (e.code && typeof e.code === \"string\") {\n\t\tif (/^E[A-Z]+$/.test(e.code)) return true;\n\t}\n\tif (e.message) {\n\t\treturn /network|timeout|socket|fetch|econn|eai_/i.test(e.message);\n\t}\n\treturn false;\n}\n","/**\n * `withLLMTimeout` — cancel `invoke()` / `stream()` after `ms` elapse.\n *\n * Wires a child AbortSignal so provider adapters can honor the cancellation\n * (all shipped adapters forward `signal` through to their fetch / SDK call).\n *\n * Uses `ResettableTimer` rather than raw `setTimeout` — same pattern as\n * `extra/resilience.ts` (spec §5.10 escape hatch documented on the class).\n */\n\nimport { ResettableTimer } from \"@graphrefly/pure-ts/core\";\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type { LLMAdapter, LLMResponse, StreamDelta } from \"../core/types.js\";\n\nexport class LLMTimeoutError extends Error {\n\toverride name = \"LLMTimeoutError\";\n\tconstructor(public readonly ms: number) {\n\t\tsuper(`LLM call timed out after ${ms}ms`);\n\t}\n}\n\nexport function withLLMTimeout(inner: LLMAdapter, ms: number): LLMAdapter {\n\tif (ms <= 0) throw new RangeError(\"withLLMTimeout: ms must be > 0\");\n\n\tconst linkedSignal = (\n\t\tparent?: AbortSignal,\n\t): {\n\t\tsignal: AbortSignal;\n\t\tcancel: () => void;\n\t\t/** `true` once our timer fired — distinguishes our-timeout vs external abort. */\n\t\ttimedOut: () => boolean;\n\t} => {\n\t\tconst ac = new AbortController();\n\t\tlet timerFired = false;\n\t\tlet onParentAbort: (() => void) | undefined;\n\t\tconst timer = new ResettableTimer();\n\t\t// Cancel the timer synchronously when the parent aborts — otherwise a\n\t\t// parent-abort at `t = ms - ε` followed by our timer firing at\n\t\t// `t = ms` would set `timerFired = true`, causing\n\t\t// `convertAbortToTimeout` to incorrectly promote the user-initiated\n\t\t// abort to an `LLMTimeoutError`.\n\t\tif (parent) {\n\t\t\tif (parent.aborted) ac.abort(parent.reason);\n\t\t\telse {\n\t\t\t\tonParentAbort = () => {\n\t\t\t\t\ttimer.cancel();\n\t\t\t\t\tac.abort(parent.reason);\n\t\t\t\t};\n\t\t\t\tparent.addEventListener(\"abort\", onParentAbort, { once: true });\n\t\t\t}\n\t\t}\n\t\ttimer.start(ms, () => {\n\t\t\ttimerFired = true;\n\t\t\tac.abort(new LLMTimeoutError(ms));\n\t\t});\n\t\treturn {\n\t\t\tsignal: ac.signal,\n\t\t\tcancel: () => {\n\t\t\t\ttimer.cancel();\n\t\t\t\tif (parent && onParentAbort) parent.removeEventListener(\"abort\", onParentAbort);\n\t\t\t},\n\t\t\ttimedOut: () => timerFired,\n\t\t};\n\t};\n\n\t/**\n\t * When our own timer fired, real `fetch`/SDK adapters reject with\n\t * `AbortError`/DOMException regardless of `signal.reason`. We convert\n\t * that rejection into {@link LLMTimeoutError} so downstream predicates\n\t * (notably {@link defaultShouldRetry}) can distinguish \"we hit the\n\t * deadline\" from \"caller aborted us\" without relying on the adapter\n\t * preserving `signal.reason`.\n\t *\n\t * External aborts bubble through unchanged so caller-supplied\n\t * `invokeOpts.signal` still propagates as an abort.\n\t */\n\tconst convertAbortToTimeout = (err: unknown, timedOut: boolean): never => {\n\t\tif (!timedOut) throw err;\n\t\tif (err instanceof LLMTimeoutError) throw err;\n\t\tconst e = err as { name?: string; code?: string | number };\n\t\tconst isAbort =\n\t\t\te?.name === \"AbortError\" ||\n\t\t\t(e?.name === \"DOMException\" && Number(e.code) === 20) /* ABORT_ERR */ ||\n\t\t\t(err as Error)?.message === \"aborted\";\n\t\tif (isAbort) {\n\t\t\tconst timeout = new LLMTimeoutError(ms);\n\t\t\t(timeout as Error & { cause?: unknown }).cause = err;\n\t\t\tthrow timeout;\n\t\t}\n\t\tthrow err;\n\t};\n\n\tconst wrap = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst { signal, cancel, timedOut } = linkedSignal(invokeOpts?.signal);\n\t\t\ttry {\n\t\t\t\treturn await firstValueFrom(fromAny(inner.invoke(messages, { ...invokeOpts, signal })));\n\t\t\t} catch (err) {\n\t\t\t\treturn convertAbortToTimeout(err, timedOut());\n\t\t\t} finally {\n\t\t\t\tcancel();\n\t\t\t}\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst { signal, cancel, timedOut } = linkedSignal(invokeOpts?.signal);\n\t\t\ttry {\n\t\t\t\tfor await (const d of inner.stream(messages, { ...invokeOpts, signal })) yield d;\n\t\t\t} catch (err) {\n\t\t\t\tconvertAbortToTimeout(err, timedOut());\n\t\t\t} finally {\n\t\t\t\tcancel();\n\t\t\t}\n\t\t},\n\t});\n\twithLayer(wrap, \"withLLMTimeout\", inner);\n\treturn wrap;\n}\n","/**\n * `resilientAdapter` — compose `withRateLimiter` + `withBudgetGate` +\n * `withLLMBreaker` + `withLLMTimeout` + `withRetry` + fallback over an {@link LLMAdapter}.\n *\n * Call-path peer of {@link resilientPipeline} (which operates on a reactive\n * `Node<T>` chain). Use `resilientPipeline` when composing graph sources; use\n * `resilientAdapter` when wrapping an adapter so downstream users see a\n * single hardened `invoke`/`stream` surface.\n *\n * Composition order (innermost to outermost, mirrors `resilientPipeline`):\n *\n * ```text\n * rateLimit → budget → breaker → timeout → retry → fallback\n * ```\n *\n * Rationale:\n * - **rateLimit innermost** — each attempt acquires a fresh slot; a retry\n * after a 429 waits for admission rather than bursting past the cap.\n * - **budget next** — per-attempt gate close short-circuits retries once a\n * cap trips.\n * - **breaker next** — each attempt observes circuit health; open breaker\n * fast-fails retries into fallback.\n * - **timeout before retry** — each retry re-arms a fresh per-attempt\n * deadline. If `timeout` wrapped `retry`, a single deadline would cover\n * the entire retry chain — surprising for callers.\n * - **retry before fallback** — fallback is entered only after the primary\n * exhausts its retry budget (or immediately fails in a way the predicate\n * doesn't retry).\n *\n * Every option is optional — omit the field and that layer is skipped. The\n * returned bundle exposes the primary adapter plus the internal bundles\n * (`rateLimiter`, `budget`, `breaker`) so callers can wire them into\n * dashboards, alerts, or `graphLens`.\n *\n * Fallback is implemented via {@link cascadingLlmAdapter}: when `fallback`\n * is provided, the wrapped primary adapter is placed at tier 0 and the\n * fallback adapter at tier 1. For N-tier cascades, use `cascadingLlmAdapter`\n * directly and wrap each tier with `resilientAdapter`.\n *\n * @module\n */\n\nimport type { AdaptiveRateLimiterBundle } from \"../../../resilience/adaptive-rate-limiter.js\";\nimport type { CircuitBreaker } from \"../../../resilience/breaker.js\";\nimport type { LLMAdapter } from \"../core/types.js\";\nimport type { CascadeExhaustionReport } from \"../routing/cascading.js\";\nimport { cascadingLlmAdapter } from \"../routing/cascading.js\";\nimport { type WithBreakerOptions, withLLMBreaker } from \"./breaker.js\";\nimport {\n\ttype LLMBudgetGateBundle,\n\ttype WithBudgetGateOptions,\n\twithBudgetGate,\n} from \"./budget-gate.js\";\nimport { type WithRateLimiterOptions, withRateLimiter } from \"./rate-limiter.js\";\nimport { type WithReplayCacheOptions, withReplayCache } from \"./replay-cache.js\";\nimport { type WithRetryOptions, withRetry } from \"./retry.js\";\nimport { withLLMTimeout } from \"./timeout.js\";\n\n/** Options for {@link resilientAdapter}. Every field is optional — omit to skip that layer. */\nexport interface ResilientAdapterOptions {\n\t/** Admission control. See {@link withRateLimiter}. */\n\trateLimit?: WithRateLimiterOptions;\n\t/** Cost/cap gate. See {@link withBudgetGate}. */\n\tbudget?: WithBudgetGateOptions;\n\t/** Circuit breaker. See {@link withBreaker}. */\n\tbreaker?: WithBreakerOptions;\n\t/** Per-attempt deadline in milliseconds. Omit to skip the timeout wrap. */\n\ttimeoutMs?: number;\n\t/** Retry policy on transient errors. See {@link withRetry}. */\n\tretry?: WithRetryOptions;\n\t/**\n\t * Fallback adapter engaged when the primary (post-retry) fails. Implemented\n\t * via {@link cascadingLlmAdapter} — the primary becomes tier 0, the\n\t * fallback becomes tier 1. For N-tier cascades, use `cascadingLlmAdapter`\n\t * directly and wrap each tier with `resilientAdapter` as needed.\n\t */\n\tfallback?: LLMAdapter;\n\t/** Name used as the primary tier name in the fallback cascade. Default `\"primary\"`. */\n\tname?: string;\n\t/**\n\t * Called when the cascade switches from one tier to the next after a\n\t * failure. Only fires when `fallback` is set. Threaded directly to the\n\t * inner {@link cascadingLlmAdapter}.\n\t */\n\tonFallback?: (from: string, to: string, error: unknown) => void;\n\t/**\n\t * Called when every tier in the cascade has been exhausted (all failed,\n\t * skipped by filter, or skipped by breaker). Only fires when `fallback`\n\t * is set. Threaded directly to the inner {@link cascadingLlmAdapter}.\n\t */\n\tonExhausted?: (report: CascadeExhaustionReport) => void;\n\t/**\n\t * Content-addressed replay cache wrapped OUTERMOST — a cache HIT short-\n\t * circuits the entire stack (rate-limit / budget / breaker / retry /\n\t * fallback), saving money and latency. Cache MISSes flow through the\n\t * normal stack; the successful result is stored on success. See\n\t * {@link withReplayCache}.\n\t */\n\tcache?: WithReplayCacheOptions;\n}\n\n/** Output bundle of {@link resilientAdapter}. */\nexport interface ResilientAdapterBundle {\n\t/** The final hardened adapter. */\n\tadapter: LLMAdapter;\n\t/** Rate-limiter internals (for dashboards). Present only when `opts.rateLimit` was set. */\n\trateLimiter?: AdaptiveRateLimiterBundle;\n\t/** Budget gate internals (for dashboards). Present only when `opts.budget` was set. */\n\tbudget?: LLMBudgetGateBundle;\n\t/** Circuit breaker (for dashboards). Present only when `opts.breaker` was set. */\n\tbreaker?: CircuitBreaker;\n}\n\n/**\n * Wrap `inner` with the standard resilience stack. See module docs for the\n * composition order and rationale.\n *\n * @example\n * ```ts\n * const { adapter, budget, breaker } = resilientAdapter(openai, {\n * rateLimit: { rpm: 60, tpm: 90_000 },\n * budget: { caps: { usd: 5 } },\n * breaker: { failureThreshold: 5, resetTimeoutMs: 30_000 },\n * timeoutMs: 30_000,\n * retry: { attempts: 3 },\n * fallback: webllm, // cascades to local on exhaustion\n * });\n *\n * // `adapter` is drop-in for anything expecting LLMAdapter.\n * // Subscribe to `budget.totals`, `breaker.state`, etc. for dashboards.\n * ```\n */\nexport function resilientAdapter(\n\tinner: LLMAdapter,\n\topts: ResilientAdapterOptions = {},\n): ResilientAdapterBundle {\n\tconst bundle: ResilientAdapterBundle = { adapter: inner };\n\tlet current: LLMAdapter = inner;\n\n\tif (opts.rateLimit) {\n\t\tconst wrapped = withRateLimiter(current, opts.rateLimit);\n\t\tcurrent = wrapped.adapter;\n\t\tbundle.rateLimiter = wrapped.limiter;\n\t}\n\tif (opts.budget) {\n\t\tconst wrapped = withBudgetGate(current, opts.budget);\n\t\tcurrent = wrapped.adapter;\n\t\tbundle.budget = wrapped.budget;\n\t}\n\tif (opts.breaker) {\n\t\tconst wrapped = withLLMBreaker(current, opts.breaker);\n\t\tcurrent = wrapped.adapter;\n\t\tbundle.breaker = wrapped.breaker;\n\t}\n\tif (opts.timeoutMs != null) {\n\t\tcurrent = withLLMTimeout(current, opts.timeoutMs);\n\t}\n\tif (opts.retry) {\n\t\tcurrent = withRetry(current, opts.retry);\n\t}\n\tif (opts.fallback) {\n\t\t// Secondary tier is named `\"fallback\"` internally; reject the same\n\t\t// label as the primary name so CascadeExhaustionReport.failed (a\n\t\t// Map keyed by tier name) and `resp.metadata.tier` stamping stay\n\t\t// unambiguous.\n\t\tif (opts.name === \"fallback\") {\n\t\t\tthrow new RangeError(\n\t\t\t\t'resilientAdapter: `name` cannot be \"fallback\" — collides with the secondary tier label.',\n\t\t\t);\n\t\t}\n\t\tconst cascadeOpts: {\n\t\t\tonFallback?: (from: string, to: string, error: unknown) => void;\n\t\t\tonExhausted?: (report: CascadeExhaustionReport) => void;\n\t\t} = {};\n\t\tif (opts.onFallback) cascadeOpts.onFallback = opts.onFallback;\n\t\tif (opts.onExhausted) cascadeOpts.onExhausted = opts.onExhausted;\n\t\tcurrent = cascadingLlmAdapter(\n\t\t\t[\n\t\t\t\t{ name: opts.name ?? \"primary\", adapter: current },\n\t\t\t\t{ name: \"fallback\", adapter: opts.fallback },\n\t\t\t],\n\t\t\tcascadeOpts,\n\t\t);\n\t}\n\tif (opts.cache) {\n\t\t// Outermost — a cache HIT skips the entire stack below.\n\t\tcurrent = withReplayCache(current, opts.cache);\n\t}\n\n\tbundle.adapter = current;\n\treturn bundle;\n}\n","/**\n * `frozenContext` — prefix-cache-friendly snapshot of upstream context.\n *\n * @module\n */\n\nimport { factoryTag, type Node, node as nodeFactory } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { aiMeta } from \"../_internal.js\";\n\nexport type FrozenContextOptions = {\n\t/**\n\t * Reactive signal that triggers re-materialization. Each `DATA` emission\n\t * from this node re-reads the source and refreshes the frozen value.\n\t * Typical shapes: `fromTimer(ms)` for periodic refresh, a stage-transition\n\t * node for event-driven refresh, or a manual `state<number>` the caller\n\t * increments via `setState(n + 1)`.\n\t *\n\t * When omitted, the frozen value is materialized exactly once (on first\n\t * subscribe) and never refreshes for the lifetime of the activation —\n\t * use this for session-start snapshots that must stay stable. The\n\t * single-shot latch IS reset on `INVALIDATE` (graph-wide flush via\n\t * `graph.signal([[INVALIDATE]])`), so callers who need an \"evict and\n\t * re-materialize\" escape hatch get one through the standard graph\n\t * lifecycle without having to wire a `refreshTrigger`.\n\t */\n\trefreshTrigger?: NodeInput<unknown>;\n\tname?: string;\n};\n\n/**\n * Freeze a reactive source into a stable snapshot that only re-materializes\n * on explicit trigger. Built for long-running harness loops where system\n * prompts include `agentMemory` / stage context — every reactive change to\n * the source invalidates the LLM provider's prefix cache, so re-rendering\n * the prompt every turn is expensive.\n *\n * `frozenContext(source)` reads the source once and caches the value;\n * downstream `promptNode` compositions see a stable reference until the\n * optional `refreshTrigger` fires.\n *\n * Trade-off: slightly stale context vs. prefix cache hit rate. For most\n * harness apps, the memory snapshot at session start is \"good enough\" —\n * refreshing on a coarse-grained trigger (`fromCron(\"*\\/30min\")`, stage\n * transition) preserves 90%+ prefix cache hits while keeping context useful.\n *\n * @example\n * ```ts\n * // Freeze agent memory for the duration of a stage.\n * const frozen = frozenContext(memory.context, {\n * refreshTrigger: stage, // re-materialize on stage change\n * });\n * const reply = promptNode({ context: frozen, ... });\n * ```\n *\n * @category patterns.ai\n */\nexport function frozenContext<T>(\n\tsource: NodeInput<T>,\n\topts?: FrozenContextOptions,\n): Node<T | null> {\n\tconst src = fromAny(source);\n\tconst trigger = opts?.refreshTrigger != null ? fromAny(opts.refreshTrigger) : null;\n\n\t// JSON-serializable subset of opts: omit `refreshTrigger` (a NodeInput).\n\tconst frozenArgs: Record<string, unknown> | undefined =\n\t\topts?.name !== undefined ? { name: opts.name } : undefined;\n\tconst frozenTag = factoryTag(\"frozenContext\", frozenArgs);\n\n\t// Single-shot path: deps = [src] only. Emit the first src value and then\n\t// hold regardless of source drift.\n\tif (trigger == null) {\n\t\treturn nodeFactory<T | null>(\n\t\t\t[src],\n\t\t\t(data, actions, ctx) => {\n\t\t\t\tconst alreadyEmitted = ctx.store.emitted === true;\n\t\t\t\tif (alreadyEmitted) return;\n\t\t\t\tconst srcBatch = data[0];\n\t\t\t\tconst srcValue =\n\t\t\t\t\tsrcBatch != null && srcBatch.length > 0 ? srcBatch.at(-1) : ctx.prevData[0];\n\t\t\t\t// Only emit once src has produced a settled value.\n\t\t\t\tif (srcValue === undefined) return;\n\t\t\t\tctx.store.emitted = true;\n\t\t\t\tactions.emit(srcValue as T);\n\t\t\t\t// On INVALIDATE (graph-wide flush), reset the \"already emitted\"\n\t\t\t\t// latch so the next fn re-run captures a fresh snapshot.\n\t\t\t\t// Without this, INVALIDATE clears the cache but the latch stays\n\t\t\t\t// armed, so subscribers stay on the cleared (null) state forever.\n\t\t\t\t//\n\t\t\t\t// Lock 6.D (Phase 13.6.B): clear `emitted` on deactivation —\n\t\t\t\t// the pre-flip auto-wipe handled this implicitly.\n\t\t\t\t//\n\t\t\t\t// QA D1 (Phase 13.6.B QA pass): `onResubscribableReset` covers\n\t\t\t\t// the multi-sub-stayed terminal-resubscribable path where\n\t\t\t\t// `_deactivate` does NOT run but the lifecycle reset still\n\t\t\t\t// needs to clear the latch. Without this slot, a sibling sink\n\t\t\t\t// that keeps the node alive past terminal would pin\n\t\t\t\t// `emitted === true` into the next subscription cycle and\n\t\t\t\t// suppress every future emission.\n\t\t\t\tconst store = ctx.store;\n\t\t\t\treturn {\n\t\t\t\t\tonInvalidate: () => {\n\t\t\t\t\t\tstore.emitted = false;\n\t\t\t\t\t},\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.emitted;\n\t\t\t\t\t},\n\t\t\t\t\tonResubscribableReset: () => {\n\t\t\t\t\t\tdelete store.emitted;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: opts?.name ?? \"frozenContext\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tinitial: null,\n\t\t\t\tmeta: aiMeta(\"frozen_context\", { ...frozenTag }),\n\t\t\t},\n\t\t);\n\t}\n\n\t// Refresh-on-trigger path: deps = [src, trigger]. Emit the current src\n\t// value ONLY when the trigger dep is involved in the wave. Source-only\n\t// changes are silently held so downstream prompt composition sees the\n\t// same value between triggers, preserving the LLM provider's prefix cache.\n\t//\n\t// Uses raw `node()` to inspect per-dep wave involvement — `derived` fires\n\t// on any dep change and can't distinguish. The declaration-order semantic\n\t// gap in multi-dep push-on-subscribe (§2.7) works in our favor on\n\t// activation: src fires first (captured into ctx.prevData), trigger fires\n\t// in a second wave → emit via prevData[0] fallback.\n\treturn nodeFactory<T | null>(\n\t\t[src, trigger],\n\t\t(data, actions, ctx) => {\n\t\t\tconst triggerBatch = data[1];\n\t\t\tconst triggered = triggerBatch != null && triggerBatch.length > 0;\n\t\t\tif (!triggered) return;\n\t\t\tconst srcBatch = data[0];\n\t\t\tconst srcValue = srcBatch != null && srcBatch.length > 0 ? srcBatch.at(-1) : ctx.prevData[0];\n\t\t\tactions.emit(srcValue as T);\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"frozenContext\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: null,\n\t\t\tmeta: aiMeta(\"frozen_context\", { ...frozenTag }),\n\t\t},\n\t);\n}\n","/**\n * @internal — shared helpers for the AI pattern modules.\n *\n * NOT part of the public API. Consumers reach public symbols through\n * `@graphrefly/graphrefly/patterns/ai` (the barrel).\n *\n * @module\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tERROR,\n\ttype Messages,\n\ttype Node,\n\tnode,\n\tResettableTimer,\n} from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n} from \"./adapters/core/types.js\";\n\nexport function aiMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"ai\", kind, extra);\n}\n\nexport function isPromiseLike(x: unknown): x is PromiseLike<unknown> {\n\treturn x != null && typeof (x as PromiseLike<unknown>).then === \"function\";\n}\n\nexport function 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\nexport function 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). */\nexport function firstDataFromNode(\n\tresolved: Node<unknown>,\n\topts?: { timeoutMs?: number },\n): Promise<unknown> {\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`. */\nexport async 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/** Strip markdown code fences, handling trailing commentary after closing fence. */\nexport function stripFences(text: string): string {\n\tconst match = text.match(/^```(?:json)?\\s*([\\s\\S]*?)\\s*```[\\s\\S]*$/);\n\treturn match ? match[1]! : text;\n}\n\n/**\n * Bridge-layer failure kind reported to {@link OneShotLlmCallConfig.onFailure}.\n *\n * - `\"throw\"` — synchronous throw from `adapter.invoke()`.\n * - `\"error\"` — `[ERROR, value]` message on the bridged Node.\n * - `\"complete\"` — the bridged Node closed without emitting DATA.\n * - `\"onSuccess-threw\"` — `onSuccess(resp)` itself threw (uncaught parse /\n * builder error). Caller's `onFailure` decides the failure-payload shape.\n */\nexport type OneShotLlmFailureKind = \"throw\" | \"error\" | \"complete\" | \"onSuccess-threw\";\n\n/** Configuration for {@link _oneShotLlmCall}. */\nexport interface OneShotLlmCallConfig<T> {\n\t/**\n\t * Build the success payload from the adapter's first DATA message.\n\t * MAY throw — the helper catches and routes through `onFailure(kind:\n\t * \"onSuccess-threw\", err)` so callers don't need their own try/catch.\n\t */\n\tonSuccess: (resp: LLMResponse) => T;\n\t/**\n\t * Build a failure payload when the bridge layer reports any of the\n\t * {@link OneShotLlmFailureKind} categories. Caller chooses the detail\n\t * string format and any error-class metadata.\n\t */\n\tonFailure: (kind: OneShotLlmFailureKind, err: unknown) => T;\n\t/**\n\t * Forwarded to `adapter.invoke(messages, opts)` — `signal` is set\n\t * by the helper from the producer's AbortController and CANNOT be\n\t * overridden here (cancellation is a hard contract of this helper).\n\t */\n\tinvokeOpts?: Omit<LLMInvokeOptions, \"signal\">;\n\t/**\n\t * Optional parent abort signal (e.g. JobFlow pump's per-claim signal).\n\t * When the parent aborts, the helper aborts its inner AbortController —\n\t * so `adapter.invoke({ signal })` and `fromAny({ signal })` see the\n\t * cascade and cancel in-flight work. Pump-driven harness teardown\n\t * (`harness.destroy()`) propagates through this hook (Tier 6.5 2.5b).\n\t */\n\tparentSignal?: AbortSignal;\n}\n\n/**\n * Internal — one-shot bridge from `adapter.invoke()` (a `NodeInput<LLMResponse>`)\n * into a producer that emits exactly one DATA + COMPLETE.\n *\n * **Why this exists.** The harness's `defaultLlmExecutor` and\n * `defaultLlmVerifier` (Tier 6.5 C2) both call `adapter.invoke()` once\n * per claimed JobFlow job and need to:\n * 1. Subscribe to the bridged Node, capture the first DATA, parse, emit\n * a domain payload.\n * 2. Map adapter throws / ERROR / COMPLETE-without-DATA to a domain\n * failure payload (rather than nack the JobFlow claim).\n * 3. Thread `signal: ac.signal` into BOTH `adapter.invoke()` (via\n * `LLMInvokeOptions.signal`) and `fromAny()` (covers Node-shaped\n * invokeResults) so teardown actually aborts in-flight HTTP work.\n * 4. Tear down the inner subscription cleanly when DATA captures or\n * when the producer is unsubscribed.\n *\n * Pre-extraction this body was duplicated ~80 LOC across the two default\n * bridges; symmetric fixes had to land twice (qa F1 / F2 / F5). This\n * helper centralizes the producer body so future bridge-layer fixes apply\n * once.\n *\n * **Not part of the public API.** Callers in `patterns/ai/_internal.ts`'s\n * import surface (the harness defaults today) use this; user code should\n * use `promptNode` for cross-wave reactive transforms or call\n * `adapter.invoke()` directly.\n */\nexport function _oneShotLlmCall<T>(\n\tadapter: LLMAdapter,\n\tmessages: readonly ChatMessage[],\n\tconfig: OneShotLlmCallConfig<T>,\n): NodeInput<T> {\n\treturn node<T>(\n\t\t(_data, actions) => {\n\t\t\tconst ac = new AbortController();\n\t\t\t// Link parent signal (e.g. pump per-claim signal) so cascading\n\t\t\t// teardown propagates: parent abort → inner ac.abort → adapter +\n\t\t\t// fromAny cancel.\n\t\t\tconst parentSignal = config.parentSignal;\n\t\t\tlet unlinkParent: () => void = () => undefined;\n\t\t\tif (parentSignal) {\n\t\t\t\tif (parentSignal.aborted) {\n\t\t\t\t\tac.abort();\n\t\t\t\t} else {\n\t\t\t\t\tconst onParentAbort = (): void => ac.abort();\n\t\t\t\t\tparentSignal.addEventListener(\"abort\", onParentAbort, { once: true });\n\t\t\t\t\tunlinkParent = () => parentSignal.removeEventListener(\"abort\", onParentAbort);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet captured = false;\n\t\t\tlet unsub: (() => void) | null = null;\n\t\t\tconst emitOnce = (value: T): void => {\n\t\t\t\tif (captured) return;\n\t\t\t\tcaptured = true;\n\t\t\t\tactions.down([[DATA, value], [COMPLETE]] satisfies Messages);\n\t\t\t\tunsub?.();\n\t\t\t\tunsub = null;\n\t\t\t};\n\t\t\tlet invokeResult: NodeInput<LLMResponse>;\n\t\t\ttry {\n\t\t\t\tinvokeResult = adapter.invoke(messages, { ...config.invokeOpts, signal: ac.signal });\n\t\t\t} catch (err) {\n\t\t\t\temitOnce(config.onFailure(\"throw\", err));\n\t\t\t\treturn () => {\n\t\t\t\t\tunlinkParent();\n\t\t\t\t\tac.abort();\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst callNode = fromAny<LLMResponse>(invokeResult, { signal: ac.signal });\n\t\t\tunsub = callNode.subscribe((batch) => {\n\t\t\t\tfor (const m of batch) {\n\t\t\t\t\tif (captured) return;\n\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\temitOnce(config.onSuccess(m[1] as LLMResponse));\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\temitOnce(config.onFailure(\"onSuccess-threw\", err));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m[0] === ERROR) {\n\t\t\t\t\t\temitOnce(config.onFailure(\"error\", m[1]));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\t\t// COMPLETE without prior DATA — without this arm the JobFlow\n\t\t\t\t\t\t// pump's claim would stall (qa F1 regression). Helper handles\n\t\t\t\t\t\t// for ALL callers; defaults can't regress.\n\t\t\t\t\t\temitOnce(config.onFailure(\"complete\", undefined));\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\t// Sync DATA delivery (cached state / `fromAny` over a sync value):\n\t\t\t// the callback ran reentrantly before `unsub` was assigned, so the\n\t\t\t// `unsub?.()` call inside `emitOnce` was a no-op. Drop the upstream\n\t\t\t// subscription now that we have the handle.\n\t\t\tif (captured && unsub) {\n\t\t\t\tunsub();\n\t\t\t\tunsub = null;\n\t\t\t}\n\t\t\treturn () => {\n\t\t\t\tunlinkParent();\n\t\t\t\tac.abort();\n\t\t\t\tunsub?.();\n\t\t\t\tunsub = null;\n\t\t\t};\n\t\t},\n\t\t{ describeKind: \"producer\" },\n\t);\n}\n","// ---------------------------------------------------------------------------\n// promptCall — public single-shot LLM JSON helper (Tier 4.6 Wave AM Unit 4\n// promotion from the previously-internal `llmJsonCall` in\n// `patterns/ai/memory/llm-memory.ts`).\n//\n// Wraps {@link promptNode} for the common \"one-shot LLM JSON call per input\"\n// shape: a per-call `node([], { initial: input })` is wrapped, the prompt builder runs against\n// it, and the returned `NodeInput<TOut>` slots into reactive callbacks like\n// `distill`'s `extractFn` / `consolidateFn`. Inherits markdown-fence stripping\n// and content-preview parse errors from `promptNode({format: \"json\"})`.\n//\n// `llmExtractor` / `llmConsolidator` are now thin wrappers over `promptCall`.\n// ---------------------------------------------------------------------------\n\nimport { node } from \"@graphrefly/pure-ts/core\";\nimport type { NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport type { Extraction } from \"../../../base/composition/distill.js\";\nimport type { LLMAdapter } from \"../adapters/core/types.js\";\nimport { promptNode } from \"./prompt-node.js\";\n\n/** Options accepted by {@link promptCall}, {@link llmExtractor}, and {@link llmConsolidator}. */\nexport type PromptCallOptions = {\n\tadapter: LLMAdapter;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/**\n\t * Optional name forwarded to the underlying `promptNode` (used as the\n\t * `<name>::messages` / `<name>::response` / `<name>::output` path prefix).\n\t * Defaults differ per call site so multiple `promptCall`s wired into the\n\t * same graph don't collide on `prompt_node::output`.\n\t */\n\tname?: string;\n};\n\n/**\n * Build a one-shot LLM JSON-call factory: each invocation wraps `input` in a\n * fresh `node([], { initial: input })`, delegates to `promptNode({format: \"json\"})`, and\n * returns a `NodeInput<TOut>` that the caller plugs into `distill` /\n * `agentLoop` / any reactive composition that accepts `NodeInput`.\n *\n * **Per-call lifecycle.** The returned `NodeInput<TOut>` is a producer that\n * emits exactly one `DATA` per upstream input (per Tier 1.2 Session C lock —\n * `promptNode` guarantees one DATA per wave). When the consumer's switchMap\n * supersedes it, the per-call `node([], { initial: input })` and the inner `prompt_node::response`\n * tear down together.\n *\n * @param systemPrompt - System message sent on every call.\n * @param buildUserContent - Per-input user-content builder (must be JSON-stringifiable).\n * @param opts - Adapter + model/temperature/maxTokens + optional name prefix.\n * @param defaultName - Path-prefix fallback when `opts.name` is omitted.\n * @returns Factory `(input: TIn) => NodeInput<TOut>`.\n *\n * @category patterns\n */\nexport function promptCall<TIn, TOut>(\n\tsystemPrompt: string,\n\tbuildUserContent: (input: TIn) => string,\n\topts: PromptCallOptions,\n\tdefaultName: string,\n): (input: TIn) => NodeInput<TOut> {\n\tconst name = opts.name ?? defaultName;\n\treturn (input: TIn) => {\n\t\t// One-shot node([], { initial: input }) per call — switchMap teardown inside the\n\t\t// consumer (e.g. distill) reclaims the node when the next upstream\n\t\t// arrives or the bundle disposes.\n\t\tconst inputState = node<TIn>([], { initial: input });\n\t\treturn promptNode<TOut>(\n\t\t\topts.adapter,\n\t\t\t[inputState as never],\n\t\t\t(value: unknown) => buildUserContent(value as TIn),\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tformat: \"json\",\n\t\t\t\tsystemPrompt,\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) as NodeInput<TOut>;\n\t};\n}\n\n/** Options accepted by {@link llmExtractor} and {@link llmConsolidator}. */\nexport type LLMExtractorOptions = PromptCallOptions & {\n\t/**\n\t * Cap the dedup-hint slice of `existingKeys` passed to the LLM. Larger\n\t * stores ship more keys (better dedup recall) at the cost of prompt size.\n\t * Default 100. Set to `Infinity` to forward every key.\n\t */\n\tmaxExistingKeys?: number;\n};\n\n/** Alias for backward compatibility. */\nexport type LLMConsolidatorOptions = LLMExtractorOptions;\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 *\n * Built on `promptNode({format: \"json\"})` — inherits markdown-fence stripping\n * and content-preview parse errors. Stack `withRetry` on the adapter for\n * transient-error tolerance (see `patterns/ai/adapters/middleware/retry.ts`).\n */\nexport function llmExtractor<TRaw, TMem>(\n\tsystemPrompt: string,\n\topts: LLMExtractorOptions,\n): (raw: TRaw, existing: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>> {\n\tconst cap = opts.maxExistingKeys ?? 100;\n\tconst call = promptCall<{ raw: TRaw; existingKeys: string[] }, Extraction<TMem>>(\n\t\tsystemPrompt,\n\t\t(input) => JSON.stringify({ input: input.raw, existingKeys: input.existingKeys }),\n\t\topts,\n\t\t\"llmExtractor\",\n\t);\n\treturn (raw: TRaw, existing: ReadonlyMap<string, TMem>) => {\n\t\tconst existingKeys =\n\t\t\tcap === Number.POSITIVE_INFINITY ? [...existing.keys()] : [...existing.keys()].slice(0, cap);\n\t\treturn call({ raw, existingKeys });\n\t};\n}\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\tconst call = promptCall<readonly { key: string; value: TMem }[], Extraction<TMem>>(\n\t\tsystemPrompt,\n\t\t(memories) => JSON.stringify({ memories }),\n\t\topts,\n\t\t\"llmConsolidator\",\n\t);\n\treturn (entries: ReadonlyMap<string, TMem>) => {\n\t\tconst memories = [...entries.entries()].map(([key, value]) => ({ key, value }));\n\t\treturn call(memories);\n\t};\n}\n","/**\n * `promptNode` — universal LLM transform as a reactive derived node.\n *\n * The shape: `deps → messagesNode (derived) → switchMap → response (producer) → output`.\n * Each upstream wave is one LLM call; superseding waves cancel the in-flight\n * call via the abort signal threaded through `nodeSignal(opts.abort)`.\n *\n * The producer-shape on the inner is load-bearing: it emits exactly one DATA\n * + COMPLETE per wave, so the outer switchMap sees one DATA per wave (matches\n * the `HarnessExecutor` contract). A `node([response], (batchData, actions, ctx) => {\n * const data = ...; actions.emit(parse(data[0]));\n * }, { describeKind: \"derived\" })` would have its\n * own first-run / push-on-subscribe semantics that can leak a transient null\n * before the real response arrives — observed and reverted in an earlier\n * attempt; see SESSION-ai-harness-module-review.md line 3654 for context.\n * Locked as path (b) producer-based by Session C (2026-04-27); inner-node\n * naming aligned to `prompt_node::response` per the C+D widening (2026-04-30).\n *\n * **Retry / replay-cache.** Stack middleware on the adapter:\n *\n * ```ts\n * import { withRetry, withReplayCache } from \"@graphrefly/graphrefly/patterns/ai\";\n *\n * const adapter = withRetry(\n * withReplayCache(baseAdapter, { keyFn: (ctx) => ctx.messages[0].content }),\n * { count: 3, backoff: 200 },\n * );\n * const result = promptNode(adapter, [input], (q) => q);\n * ```\n *\n * `promptNode` no longer ships `retries` / `cache` options — they duplicated\n * middleware already at the adapter layer.\n *\n * **Cross-wave cache (COMPOSITION-GUIDE §32).** The switchMap output cache\n * survives across new outer DATAs — `promptNode`'s cached value persists\n * until the next wave fully resolves. Consumers that need to distinguish\n * \"fresh value for THIS session\" from \"stale cache from a prior session\"\n * (e.g. `agentLoop` resetting on new `run()`) must add a `node([])` mirror\n * at their session boundary and depend on the mirror, not the `promptNode`\n * output directly. `promptNode` itself stays primitive — it does not\n * embed a state-mirror.\n *\n * @module\n */\n\nimport { COMPLETE, DATA, ERROR, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport { nodeSignal } from \"../../../base/sources/settled.js\";\nimport { aiMeta, stripFences } from \"../_internal.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tToolDefinition,\n} from \"../adapters/core/types.js\";\n\nexport type PromptNodeOptions = {\n\tname?: string;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/**\n\t * Output format:\n\t * - `\"text\"` (default) — emit the response content as a string.\n\t * - `\"json\"` — `JSON.parse` the content (markdown fences stripped).\n\t * - `\"raw\"` — emit the full {@link LLMResponse} object (subsumes the\n\t * pre-Tier-2.3 `fromLLM` shape; use this when you need `usage` /\n\t * `toolCalls` / `finishReason` alongside `content`).\n\t */\n\tformat?: \"text\" | \"json\" | \"raw\";\n\t/**\n\t * Reactive tool definitions forwarded to the adapter. Pair with\n\t * `format: \"raw\"` (or read `toolCalls` from a downstream parser) when\n\t * tool-calling is in scope.\n\t *\n\t * **Reactive declared edge** (DF12, Tier 7): `tools` is a `Node` so the\n\t * tools list participates in `describe()` topology and `explain()` causal\n\t * chains. The tools Node is added to `messagesNode`'s declared deps —\n\t * tools changes re-invoke the LLM (treated as a new call envelope).\n\t * Wrap with `distinctUntilChanged` upstream if your tool selector emits\n\t * noisy duplicates that would otherwise spam the adapter. See\n\t * COMPOSITION-GUIDE §31 (Dynamic tool selection) for the canonical\n\t * `toolSelector` pattern that produces this Node.\n\t *\n\t * **Activation note:** since `tools` is a real declared dep, `messagesNode`\n\t * waits for the tools Node to DATA at least once before firing\n\t * (push-on-subscribe SENTINEL gate). Pass a `node<ToolDefinition[]>([], { initial: [] })`\n\t * if you want immediate activation with no tools, or the latest published\n\t * `toolSelector.tools` Node.\n\t */\n\ttools?: Node<readonly ToolDefinition[]>;\n\t/**\n\t * Optional system prompt. Forwarded via `opts.systemPrompt` to the adapter\n\t * only — never pushed as a `{role:\"system\"}` message (avoiding the\n\t * double-send class of bug where adapters that normalize both shapes end\n\t * up with two system entries).\n\t */\n\tsystemPrompt?: string;\n\t/**\n\t * Optional reactive abort signal. When the node emits `true`, the in-flight\n\t * `adapter.invoke()` call is cancelled via `AbortController.abort()`.\n\t * Threaded through `nodeSignal(abort)` — a one-shot bridge. Useful inside\n\t * agent state machines where a separate `aborted` state should cancel the\n\t * current LLM call without superseding via switchMap.\n\t */\n\tabort?: Node<boolean>;\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\nfunction previewContent(text: string, max = 200): string {\n\tif (text.length <= max) return text;\n\treturn `${text.slice(0, max)}…`;\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 * **Topology** (visible in `describe()`):\n * ```\n * <deps...>, [tools?] → <name>::messages (derived, meta.ai = prompt_node::messages)\n * <name>::messages → <name>::output (switchMap product, meta.ai = prompt_node::output)\n * per-wave inner: <name>::response (producer, meta.ai = prompt_node::response)\n * ```\n * When `opts.tools` is supplied, the tools `Node` is appended to\n * `messagesNode`'s declared deps so it appears as a real edge in `describe()`\n * / `explain()` (DF12, Tier 7).\n *\n * **No-input semantics** (matches the codebase-wide SENTINEL convention):\n * - **Initial no-input** (no real input has ever arrived) — emits nothing.\n * Outer cache stays `undefined`; `subscribe` consumers see no DATA event.\n * Use this to keep downstream gating clean: a `withLatestFrom`-paired\n * trigger won't fire until the LLM has actually produced something.\n * - **Mid-flow no-input** (input dropped to nullish after at least one\n * real LLM call) — emits `null` as a domain \"input went away\" signal.\n * Downstream consumers can distinguish \"haven't started\" from \"input\n * gone.\"\n *\n * **Retries / caching:** stack `withRetry` / `withReplayCache` middleware on the\n * `adapter` argument — `promptNode` no longer ships its own duplicated retry /\n * cache loops (pre-1.0 cleanup, see review session 1).\n *\n * @param adapter - LLM adapter (provider-agnostic). Wrap with `withRetry` /\n * `withReplayCache` middleware for transient-error tolerance\n * or replay caching.\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 */\n// Overload 1: `format: \"raw\"` constrains the emit type to `LLMResponse | null`\n// (the full adapter response, with `usage` / `toolCalls` / `finishReason`).\n// Subsumes the pre-Tier-2.3 `fromLLM` shape.\nexport function promptNode(\n\tadapter: LLMAdapter,\n\tdeps: readonly Node<unknown>[],\n\tprompt: string | ((...depValues: unknown[]) => string),\n\topts: PromptNodeOptions & { format: \"raw\" },\n): Node<LLMResponse | null>;\n// Overload 2: `format: \"text\" | \"json\"` (default text) — emit-type is the\n// caller's `T` (defaults to `string`). For `\"json\"` callers typically pass\n// the parsed shape (e.g. `promptNode<MyShape>(...)`).\nexport function promptNode<T = string>(\n\tadapter: LLMAdapter,\n\tdeps: readonly Node<unknown>[],\n\tprompt: string | ((...depValues: unknown[]) => string),\n\topts?: Omit<PromptNodeOptions, \"format\"> & { format?: \"text\" | \"json\" },\n): Node<T | null>;\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 baseName = opts?.name ?? \"prompt_node\";\n\n\t// qa A8: tools without `format: \"raw\"` is a footgun — adapter receives\n\t// the tool definitions and may produce `toolCalls`, but the emit path\n\t// only extracts `content`. Warn at construction; downstream parsers\n\t// reading `toolCalls` from a custom `format: \"raw\"` consumer pattern\n\t// can ignore by setting `format: \"raw\"` (intent now matches behavior).\n\tif (opts?.tools !== undefined && format !== \"raw\") {\n\t\tconsole.warn(\n\t\t\t\"promptNode: `tools` is set but `format !== 'raw'`. \" +\n\t\t\t\t\"Tool calls in the response will be silently dropped — set \" +\n\t\t\t\t\"`format: 'raw'` to receive the full LLMResponse with `toolCalls`.\",\n\t\t);\n\t}\n\n\t// SENTINEL semantics rely on the universal first-run gate + standard\n\t// prevData semantics (undefined = SENTINEL, any other value = DATA seen):\n\t// - **Initial no-input** (no dep has ever DATA'd, so prevData is\n\t// undefined across the board): the `derived`'s first-run gate blocks\n\t// `messagesNode`'s fn entirely. It never emits, switchMap never\n\t// fires, outer cache stays `undefined`.\n\t// - **Mid-flow no-input** (deps previously DATA'd then went nullish):\n\t// fn runs, returns `[]`, switchMap dispatches the `node([], { initial: null })`\n\t// branch → outer emits `null` as the domain \"input went away\" signal.\n\t// No `initial: []` and no closure flag — `prevData === undefined` is\n\t// already the sentinel marker, and the gate already enforces \"don't fire\n\t// fn until every dep has DATA'd at least once.\"\n\t//\n\t// DF12: when `opts.tools` is a Node, it's appended to `messagesNode`'s\n\t// declared deps. The fn slices values into user-deps + tools, and emits\n\t// an envelope `{ messages, tools }` so switchMap's per-wave inner can\n\t// read the latest tools via the reactive edge instead of a closure.\n\ttype Envelope = {\n\t\tmessages: readonly ChatMessage[];\n\t\ttools: readonly ToolDefinition[] | undefined;\n\t};\n\tconst userDepsLength = deps.length;\n\tconst allDeps: readonly Node<unknown>[] =\n\t\topts?.tools !== undefined ? [...deps, opts.tools as Node<unknown>] : deps;\n\tconst messagesNode = node<Envelope>(\n\t\tallDeps as Node<unknown>[],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst userValues = data.slice(0, userDepsLength);\n\t\t\tconst toolsValue =\n\t\t\t\topts?.tools !== undefined\n\t\t\t\t\t? (data[userDepsLength] as readonly ToolDefinition[] | undefined)\n\t\t\t\t\t: undefined;\n\t\t\t// Dep-level null guard (composition guide §8): if any USER dep is\n\t\t\t// nullish, emit empty messages → switchMap emits null (mid-flow\n\t\t\t// drop-out). The tools dep can legitimately be empty `[]`; only\n\t\t\t// user deps gate the call.\n\t\t\tif (userValues.some((v) => v == null)) {\n\t\t\t\tactions.emit({ messages: [], tools: toolsValue });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst text = typeof prompt === \"string\" ? prompt : prompt(...userValues);\n\t\t\tif (!text) {\n\t\t\t\tactions.emit({ messages: [], tools: toolsValue });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// systemPrompt forwarded through invoke opts only (no double-send).\n\t\t\tactions.emit({\n\t\t\t\tmessages: [{ role: \"user\" as const, content: text }],\n\t\t\t\ttools: toolsValue,\n\t\t\t});\n\t\t},\n\t\t{\n\t\t\tname: `${baseName}::messages`,\n\t\t\tmeta: aiMeta(\"prompt_node::messages\"),\n\t\t},\n\t);\n\n\tconst result = switchMap<Envelope, T | null>(\n\t\tmessagesNode,\n\t\t(envelope) => {\n\t\t\tconst { messages: msgs, tools } = envelope;\n\t\t\tif (!msgs || msgs.length === 0) {\n\t\t\t\treturn node<T | null>([], { initial: null }) as NodeInput<T | null>;\n\t\t\t}\n\n\t\t\t// Producer ensures exactly one DATA + COMPLETE per wave; switchMap\n\t\t\t// sees one DATA, the harness's \"one emission per wave\" contract is\n\t\t\t// honored. Earlier attempts using a derived node leaked\n\t\t\t// transient nulls via the derived's first-run gate.\n\t\t\treturn node<T | null>(\n\t\t\t\t(_data, actions) => {\n\t\t\t\t\tlet done = false;\n\t\t\t\t\tlet cancelled = false;\n\t\t\t\t\tlet abortDispose: (() => void) | undefined;\n\n\t\t\t\t\tconst invokeOpts: LLMInvokeOptions = {\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\t...(tools !== undefined ? { tools } : {}),\n\t\t\t\t\t};\n\t\t\t\t\tif (opts?.abort) {\n\t\t\t\t\t\tconst sig = nodeSignal(opts.abort);\n\t\t\t\t\t\tinvokeOpts.signal = sig.signal;\n\t\t\t\t\t\tabortDispose = sig.dispose;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet invokeResult: NodeInput<LLMResponse>;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinvokeResult = adapter.invoke(msgs, invokeOpts);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\t\treturn () => {\n\t\t\t\t\t\t\tabortDispose?.();\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\tconst callNode = fromAny(invokeResult);\n\n\t\t\t\t\tconst sub = callNode.subscribe((batch) => {\n\t\t\t\t\t\tif (cancelled || done) return;\n\t\t\t\t\t\tfor (const msg of batch) {\n\t\t\t\t\t\t\t// F-11: re-check `cancelled` (and `done`) at the top of\n\t\t\t\t\t\t\t// each per-message iteration so a teardown / abort that\n\t\t\t\t\t\t\t// fires synchronously between messages stops processing\n\t\t\t\t\t\t\t// further batched messages immediately.\n\t\t\t\t\t\t\tif (cancelled || done) return;\n\t\t\t\t\t\t\tif (msg[0] === DATA) {\n\t\t\t\t\t\t\t\tconst resp = msg[1] as LLMResponse;\n\t\t\t\t\t\t\t\t// `format: \"raw\"` bypasses parsing — emit the full\n\t\t\t\t\t\t\t\t// LLMResponse object (subsumes the pre-Tier-2.3 `fromLLM`\n\t\t\t\t\t\t\t\t// output shape).\n\t\t\t\t\t\t\t\tif (format === \"raw\") {\n\t\t\t\t\t\t\t\t\tactions.emit(resp as unknown as T);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// F-12: cache the extracted content once on the\n\t\t\t\t\t\t\t\t\t// parse-failure path so we don't call\n\t\t\t\t\t\t\t\t\t// `extractContent(resp)` twice (once for parsing,\n\t\t\t\t\t\t\t\t\t// once for the error-message preview).\n\t\t\t\t\t\t\t\t\tlet content: string;\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tcontent = extractContent(resp);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\t// extractContent itself failed — propagate as\n\t\t\t\t\t\t\t\t\t\t// an ERROR with a generic raw-extraction message.\n\t\t\t\t\t\t\t\t\t\tconst wrapped = new Error(\n\t\t\t\t\t\t\t\t\t\t\t`promptNode: failed to extract content from LLM response: ${\n\t\t\t\t\t\t\t\t\t\t\t\t(err as Error).message\n\t\t\t\t\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t// F-7: dispose abort hook on terminal-error\n\t\t\t\t\t\t\t\t\t\t// branches so we don't retain the AbortController\n\t\t\t\t\t\t\t\t\t\t// after the wave terminates. Idempotent.\n\t\t\t\t\t\t\t\t\t\tabortDispose?.();\n\t\t\t\t\t\t\t\t\t\tabortDispose = undefined;\n\t\t\t\t\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\t\t\t\t\tactions.down([[ERROR, wrapped]]);\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tconst parsed: T =\n\t\t\t\t\t\t\t\t\t\t\tformat === \"json\"\n\t\t\t\t\t\t\t\t\t\t\t\t? (JSON.parse(stripFences(content)) as T)\n\t\t\t\t\t\t\t\t\t\t\t\t: (content as unknown as T);\n\t\t\t\t\t\t\t\t\t\tactions.emit(parsed);\n\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\tconst wrapped = new Error(\n\t\t\t\t\t\t\t\t\t\t\t`promptNode: failed to parse LLM response as JSON: ${\n\t\t\t\t\t\t\t\t\t\t\t\t(err as Error).message\n\t\t\t\t\t\t\t\t\t\t\t}\\n Raw content (first 200 chars): ${previewContent(content)}`,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t// F-7: dispose abort hook on parse-error\n\t\t\t\t\t\t\t\t\t\t// terminal branch.\n\t\t\t\t\t\t\t\t\t\tabortDispose?.();\n\t\t\t\t\t\t\t\t\t\tabortDispose = undefined;\n\t\t\t\t\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\t\t\t\t\tactions.down([[ERROR, wrapped]]);\n\t\t\t\t\t\t\t\t\t\treturn;\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} else if (msg[0] === ERROR) {\n\t\t\t\t\t\t\t\t// F-7: dispose abort hook on terminal ERROR branch.\n\t\t\t\t\t\t\t\tabortDispose?.();\n\t\t\t\t\t\t\t\tabortDispose = undefined;\n\t\t\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\t\t\tactions.down([[ERROR, msg[1]]]);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t} else if (msg[0] === COMPLETE) {\n\t\t\t\t\t\t\t\t// Adapter completed — propagate. emit() above already\n\t\t\t\t\t\t\t\t// queued the parsed value so the wave carries DATA + COMPLETE.\n\t\t\t\t\t\t\t\t// F-7: dispose abort hook on terminal COMPLETE branch.\n\t\t\t\t\t\t\t\tabortDispose?.();\n\t\t\t\t\t\t\t\tabortDispose = undefined;\n\t\t\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Spec §1.3.6 forward-unknown — DIRTY/RESOLVED/INVALIDATE/\n\t\t\t\t\t\t\t\t// PAUSE/RESUME etc. should propagate so downstream caches /\n\t\t\t\t\t\t\t\t// flow-control hooks aren't starved. Re-typed `as never`\n\t\t\t\t\t\t\t\t// because the call's NodeInput<LLMResponse> message tuple\n\t\t\t\t\t\t\t\t// is wider than the unbound `T` projection.\n\t\t\t\t\t\t\t\tactions.down([msg as never]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tcancelled = true;\n\t\t\t\t\t\tsub();\n\t\t\t\t\t\t// F-7: cleanup callback's abortDispose call is idempotent —\n\t\t\t\t\t\t// the terminal-branch dispose above sets `abortDispose =\n\t\t\t\t\t\t// undefined` so this is a no-op when terminal-fired.\n\t\t\t\t\t\tabortDispose?.();\n\t\t\t\t\t\tabortDispose = undefined;\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdescribeKind: \"producer\",\n\t\t\t\t\tname: `${baseName}::response`,\n\t\t\t\t\tmeta: aiMeta(\"prompt_node::response\"),\n\t\t\t\t},\n\t\t\t) as NodeInput<T | null>;\n\t\t},\n\t\t{\n\t\t\tname: `${baseName}::output`,\n\t\t\tmeta: opts?.meta\n\t\t\t\t? { ...aiMeta(\"prompt_node::output\"), ...opts.meta }\n\t\t\t\t: aiMeta(\"prompt_node::output\"),\n\t\t},\n\t);\n\n\treturn result;\n}\n","/**\n * `streamingPromptNode` + `gatedStream` — streaming LLM transforms.\n *\n * **Wave A Unit 2 rewrite:**\n * - `StreamChunk` retired. The live stream surface is now `deltaTopic:\n * TopicGraph<StreamDelta & {seq, ts}>` — every adapter delta (token,\n * thinking, tool-call, usage, finish) is published in order. The previous\n * shape retained the accumulated text per-chunk, producing O(N²) memory;\n * the new shape stores only per-delta payloads (O(N)).\n * - New `accumulatedText: Node<string>` on the bundle — lazy-built via\n * `ctx.store` over token-type deltas. Text-only extractors (`streamExtractor`,\n * `keywordFlagExtractor`, `toolCallExtractor`) consume this node.\n * - `retainedLimit?: number` option exposed for the delta topic (no default —\n * session scale is domain-specific per Unit 2 Q2).\n * - Unconditional `keepalive(output)` removed — callers subscribe as needed.\n * - System-prompt double-send fixed (matches promptNode Unit 1 fix).\n * - `format: \"json\"` throws on parse error with a content-preview diagnostic\n * (parity with `promptNode`).\n * - Shared body between `streamingPromptNode` and `gatedStream` extracted\n * into `streamingInvoke` per Unit 2 locked scope.\n *\n * @module\n */\n\nimport { batch, factoryTag, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { filter, fromAny, keepalive, type NodeInput, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { type TopicGraph, topic } from \"../../messaging/index.js\";\nimport { type GateController, type GateOptions, pipelineGraph } from \"../../orchestration/index.js\";\nimport { aiMeta, stripFences } from \"../_internal.js\";\nimport type { ChatMessage, LLMAdapter, StreamDelta } from \"../adapters/core/types.js\";\n\n/**\n * A single delta published to the `deltaTopic`. Every adapter emission is\n * forwarded — not just token deltas — so consumers see the full event log\n * (thinking, tool-call-delta, usage, finish).\n */\nexport type StampedDelta = StreamDelta & {\n\t/** Monotonic per-stream counter starting at 0. */\n\treadonly seq: number;\n\t/** Wall-clock nanoseconds at publish time (spec §5.11 central timer). */\n\treadonly ts: number;\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 accumulated text. Throws on parse failure. Default: `\"text\"`. */\n\tformat?: \"text\" | \"json\";\n\tsystemPrompt?: string;\n\tmeta?: Record<string, unknown>;\n\t/**\n\t * Optional retention cap on the delta topic. Omit for unbounded retention\n\t * (the topic grows until `dispose()`). Recommended values: `8_192` for\n\t * single-shot 8K-token responses, `1_000_000` for persistent session\n\t * topics, or explicit `dispose()` for worker-pool patterns.\n\t */\n\tretainedLimit?: number;\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 delta topic — every adapter delta in order, stamped with `seq` + `ts`. */\n\tdeltaTopic: TopicGraph<StampedDelta>;\n\t/**\n\t * Reactive accumulated-text view — lazy-built over `deltaTopic.latest`\n\t * filtered on `type === \"token\"`. Text-only extractors compose on this.\n\t * Emits the empty string before any token arrives.\n\t */\n\taccumulatedText: Node<string>;\n\t/** Tear down the delta topic and release resources. */\n\tdispose: () => void;\n};\n\n/**\n * Internal pump: open a stream against `adapter`, stamp each delta, publish\n * to `deltaTopic`, and return the final accumulated text. Extracted so\n * `gatedStream` can reuse the body (Unit 2 locked scope).\n */\nasync function streamingInvoke(\n\tadapter: LLMAdapter,\n\tmsgs: readonly ChatMessage[],\n\tinvokeOpts: {\n\t\tmodel?: string;\n\t\ttemperature?: number;\n\t\tmaxTokens?: number;\n\t\tsystemPrompt?: string;\n\t\tsignal: AbortSignal;\n\t},\n\tdeltaTopic: TopicGraph<StampedDelta>,\n): Promise<string> {\n\tlet accumulated = \"\";\n\tlet seq = 0;\n\tfor await (const delta of adapter.stream(msgs, invokeOpts)) {\n\t\tdeltaTopic.publish({ ...delta, seq: seq++, ts: wallClockNs() } as StampedDelta);\n\t\tif (delta.type === \"token\") accumulated += delta.delta;\n\t}\n\treturn accumulated;\n}\n\n/** Parse accumulated text per `format`. Throws on JSON parse failure. */\nfunction parseAccumulated<T>(accumulated: string, format: \"text\" | \"json\"): T | null {\n\tif (format === \"json\") {\n\t\ttry {\n\t\t\treturn JSON.parse(stripFences(accumulated)) as T;\n\t\t} catch (err) {\n\t\t\tconst preview = accumulated.slice(0, 160);\n\t\t\tthrow new Error(\n\t\t\t\t`streamingPromptNode: format:\"json\" — failed to parse accumulated text as JSON: ${(err as Error).message}; content preview: ${preview}`,\n\t\t\t);\n\t\t}\n\t}\n\treturn accumulated as unknown as T;\n}\n\n/**\n * Build the lazy `accumulatedText` derived that maintains a running string\n * over `deltaTopic.latest` filtered on token deltas. Uses `ctx.store` per\n * COMPOSITION-GUIDE §20 — accumulator clears on deactivation.\n */\nfunction makeAccumulatedText(deltaTopic: TopicGraph<StampedDelta>, name: string): Node<string> {\n\t// Lock 6.D (Phase 13.6.B): clear acc on deactivation so a resubscribed\n\t// accumulator starts fresh. Pre-flip this came for free via\n\t// `_deactivate`'s store wipe.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<string>(\n\t\t[deltaTopic.latest],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.acc;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst d = data[0];\n\t\t\tconst store = ctx.store as { acc?: string };\n\t\t\tif (d === undefined) {\n\t\t\t\tactions.emit(store.acc ?? \"\");\n\t\t\t\treturn cleanup;\n\t\t\t}\n\t\t\tconst delta = d as StampedDelta;\n\t\t\t// `seq === 0` marks the first delta of a fresh invocation — reset\n\t\t\t// the accumulator so runs don't concatenate across switchMap\n\t\t\t// supersedes. Without this, invocation 2's text would be appended\n\t\t\t// to invocation 1's text (the `deltaTopic` outlives each switchMap\n\t\t\t// inner, so `ctx.store.acc` would otherwise persist).\n\t\t\tif (delta.seq === 0) store.acc = \"\";\n\t\t\tif (delta.type === \"token\") {\n\t\t\t\tstore.acc = (store.acc ?? \"\") + delta.delta;\n\t\t\t}\n\t\t\tactions.emit(store.acc ?? \"\");\n\t\t\treturn cleanup;\n\t\t},\n\t\t{\n\t\t\tname,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: aiMeta(\"accumulated_text\"),\n\t\t\tinitial: \"\",\n\t\t},\n\t);\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 * Every adapter delta is published to `deltaTopic` stamped with `seq` + `ts`.\n * Text consumers subscribe to `accumulatedText` (auto-maintained). Delta-\n * specific consumers (`costMeterExtractor` on `usage` deltas) subscribe to\n * `deltaTopic` directly and filter by `delta.type`.\n *\n * The async boundary is handled by `fromAny(asyncGenerator)` (spec §5.10).\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 deltaTopic = topic<StampedDelta>(`${sourceName}/stream`, {\n\t\t...(opts?.retainedLimit != null ? { retainedLimit: opts.retainedLimit } : {}),\n\t});\n\n\tconst messagesNode = node<readonly ChatMessage[]>(\n\t\tdeps as Node<unknown>[],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tif (data.some((v) => v == null)) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst text = typeof prompt === \"string\" ? prompt : prompt(...data);\n\t\t\tif (!text) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit([{ role: \"user\", content: text }]);\n\t\t},\n\t\t{\n\t\t\tname: `${sourceName}::messages`,\n\t\t\tmeta: aiMeta(\"prompt_node::messages\"),\n\t\t\tinitial: [] as readonly ChatMessage[],\n\t\t},\n\t);\n\n\tconst output = switchMap(\n\t\tmessagesNode,\n\t\t(msgs) => {\n\t\t\tconst chatMsgs = msgs as readonly ChatMessage[];\n\t\t\tif (!chatMsgs || chatMsgs.length === 0) {\n\t\t\t\treturn node<T | null>([], { initial: null }) as NodeInput<T | null>;\n\t\t\t}\n\t\t\tconst ac = new AbortController();\n\t\t\tasync function* pumpAndCollect(): AsyncGenerator<T | null> {\n\t\t\t\ttry {\n\t\t\t\t\tconst accumulated = await streamingInvoke(\n\t\t\t\t\t\tadapter,\n\t\t\t\t\t\tchatMsgs,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmodel: opts?.model,\n\t\t\t\t\t\t\ttemperature: opts?.temperature,\n\t\t\t\t\t\t\tmaxTokens: opts?.maxTokens,\n\t\t\t\t\t\t\tsystemPrompt: opts?.systemPrompt,\n\t\t\t\t\t\t\tsignal: ac.signal,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdeltaTopic,\n\t\t\t\t\t);\n\t\t\t\t\tyield parseAccumulated<T>(accumulated, format);\n\t\t\t\t} finally {\n\t\t\t\t\tac.abort();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fromAny(pumpAndCollect());\n\t\t},\n\t\t{ meta: factoryTag(\"streamingPromptNode\") },\n\t);\n\n\tconst accumulatedText = makeAccumulatedText(deltaTopic, `${sourceName}::accumulatedText`);\n\n\t// Keepalive on `output` — a caller who subscribes ONLY to `deltaTopic` or\n\t// `accumulatedText` expects the stream to run (that's the bundle contract\n\t// — three reactive surfaces, any one of them activates the pipeline).\n\t// Without this, the lazy `switchMap` stays cold until someone subscribes\n\t// to `.output` directly, and deltas never flow. The original\n\t// `streamingPromptNode` carried this keepalive; the Unit 2 \"zero overhead\n\t// if nobody subscribes\" removal broke the bundle-activation contract.\n\t// Restored here with explicit dispose so the keepalive follows the bundle.\n\tconst unsubOutput = keepalive(output);\n\n\treturn {\n\t\toutput,\n\t\tdeltaTopic,\n\t\taccumulatedText,\n\t\tdispose: () => {\n\t\t\tunsubOutput();\n\t\t\tdeltaTopic.destroy();\n\t\t},\n\t};\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 delta topic — every adapter delta in order, stamped with `seq` + `ts`. */\n\tdeltaTopic: TopicGraph<StampedDelta>;\n\t/** Reactive accumulated-text view. */\n\taccumulatedText: Node<string>;\n\t/**\n\t * Gate controller — approve, reject (aborts in-flight stream), modify.\n\t * The gate's DATA domain is `T` (not `T | null`): the pre-gate `filter`\n\t * drops nulls, so the pending queue never holds a null. The controller's\n\t * `node` output type stays `T | null` only because `gate.approve()` on an\n\t * empty queue would surface `null` — callers should treat `null` as \"no\n\t * value\" rather than as a modeled null signal.\n\t */\n\tgate: GateController<T>;\n\t/** Tear down the delta topic + gate keepalive. */\n\tdispose: () => void;\n};\n\n/**\n * Streaming LLM transform with human-in-the-loop gate integration.\n *\n * Composes {@link streamingPromptNode} with `gate` so that:\n * - `gate.reject()` discards the pending value **and** aborts the in-flight\n * stream (toggles an internal cancel signal → switchMap restart → abort).\n * - `gate.modify()` transforms the pending value before forwarding downstream.\n * - `gate.approve()` forwards the final result as normal.\n *\n * Wave A Unit 2 defers full `gatedStream` review to Wave B Unit 17 (the\n * `gate()` primitive itself is reviewed there). This implementation retains\n * the existing gate API while adopting the Unit 2 delta-topic shape.\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\tconst cancelSignal = node<number>([], { name: `${name}/cancel`, initial: 0 });\n\tlet cancelCounter = 0;\n\n\tconst allDeps = [...deps, cancelSignal] as readonly Node<unknown>[];\n\n\tconst sourceName = opts?.name ?? name;\n\tconst format = opts?.format ?? \"text\";\n\tconst deltaTopic = topic<StampedDelta>(`${sourceName}/stream`, {\n\t\t...(opts?.retainedLimit != null ? { retainedLimit: opts.retainedLimit } : {}),\n\t});\n\n\tconst messagesNode = node<readonly ChatMessage[]>(\n\t\tallDeps as Node<unknown>[],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\t// Last dep is the cancel signal — exclude from prompt args.\n\t\t\tconst depValues = data.slice(0, -1);\n\t\t\tif (depValues.some((v) => v == null)) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst text = typeof prompt === \"string\" ? prompt : prompt(...depValues);\n\t\t\tif (!text) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit([{ role: \"user\", content: text }]);\n\t\t},\n\t\t{\n\t\t\tname: `${sourceName}::messages`,\n\t\t\tmeta: aiMeta(\"prompt_node::messages\"),\n\t\t\tinitial: [] as readonly ChatMessage[],\n\t\t},\n\t);\n\n\tconst output = switchMap(\n\t\tmessagesNode,\n\t\t(msgs) => {\n\t\t\tconst chatMsgs = msgs as readonly ChatMessage[];\n\t\t\tif (!chatMsgs || chatMsgs.length === 0) {\n\t\t\t\treturn node<T | null>([], { initial: null }) as NodeInput<T | null>;\n\t\t\t}\n\t\t\tconst ac = new AbortController();\n\t\t\tasync function* pumpAndCollect(): AsyncGenerator<T | null> {\n\t\t\t\ttry {\n\t\t\t\t\tconst accumulated = await streamingInvoke(\n\t\t\t\t\t\tadapter,\n\t\t\t\t\t\tchatMsgs,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmodel: opts?.model,\n\t\t\t\t\t\t\ttemperature: opts?.temperature,\n\t\t\t\t\t\t\tmaxTokens: opts?.maxTokens,\n\t\t\t\t\t\t\tsystemPrompt: opts?.systemPrompt,\n\t\t\t\t\t\t\tsignal: ac.signal,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdeltaTopic,\n\t\t\t\t\t);\n\t\t\t\t\tyield parseAccumulated<T>(accumulated, format);\n\t\t\t\t} finally {\n\t\t\t\t\tac.abort();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fromAny(pumpAndCollect());\n\t\t},\n\t\t{ meta: factoryTag(\"gatedStream\") },\n\t);\n\n\tconst accumulatedText = makeAccumulatedText(deltaTopic, `${sourceName}::accumulatedText`);\n\n\t// Filter out null stream results so the gate only sees real values. Using\n\t// `filter()` (not a `derived` with `return undefined`) is load-bearing:\n\t// `derived`'s wrapper always calls `actions.emit(fn(data))`, so returning\n\t// `undefined` would still emit `DATA(undefined)` into the gate's pending\n\t// queue — approve/modify would then surface `undefined` to downstream\n\t// consumers. `filter` propagates RESOLVED for falsey matches, keeping the\n\t// queue clean. (This was the second half of the gatedStream activation\n\t// fix — the first was keepalive-ing `gateCtrl.output`.)\n\tconst nonNullOutput = filter<T | null>(output, (v) => v != null) as Node<T>;\n\tgraph.add(nonNullOutput, { name: `${name}/raw` });\n\n\t// Wire gate on the output. Type parameter is `T` (not `T | null`) — the\n\t// `filter` above drops nulls before they reach the gate, so the pending\n\t// queue's DATA domain is `T` only.\n\t//\n\t// C3 — `nonNullOutput` is owned by the parent `graph`. Pass it as a Node\n\t// ref to `approvalGate`; the gate's foreign-source path wraps it in a\n\t// local proxy derived registered under `${name}/gate/source` inside\n\t// gateSubgraph. The dual-add pattern (`graph.add` + `gateSubgraph.add`)\n\t// is retired — Session B.1's \"no wrapper\" invariant gave way to the\n\t// single-owner invariant per the C3 lock.\n\tconst gateSubgraph = pipelineGraph(`${name}/gate-graph`);\n\tgraph.mount(`${name}/gate-graph`, gateSubgraph);\n\tconst gateCtrl = gateSubgraph.approvalGate<T>(\n\t\t`${name}/gate`,\n\t\tnonNullOutput as Node<unknown>,\n\t\topts?.gate,\n\t);\n\n\t// Keepalive the switchMap product, the gate's output node, AND the\n\t// accumulator so the full bundle contract (\"three reactive surfaces, any\n\t// one activates the pipeline\") holds:\n\t//\n\t// - `keepalive(output)` activates the streaming switchMap so the adapter\n\t// generator runs even before a downstream subscriber attaches.\n\t// - `keepalive(gateCtrl.output)` activates the gate's fn body — which is\n\t// what writes into the internal `pending` queue. Without it, a caller\n\t// that only subscribes to `gate.count` / `gate.pending` / `deltaTopic`\n\t// (but not `gate.output`) would see `count` stuck at 0 indefinitely:\n\t// stream values reach the gate's input but the gate's fn never runs.\n\t// - `keepalive(accumulatedText)` ensures `.cache` reflects the running\n\t// total for callers that read the accumulator as a snapshot instead of\n\t// subscribing to it.\n\t//\n\t// Dropping any of the three surfaces as a silent stall in `ai.test.ts`'s\n\t// gatedStream suite.\n\t//\n\t// All three unsubs are also registered with the host graph so\n\t// `parent.destroy()` reclaims them even if the caller forgets to call\n\t// `dispose()`. `dispose()` itself runs them eagerly for prompt teardown.\n\tconst unsubOutput = keepalive(output);\n\tconst unsubGate = keepalive(gateCtrl.output);\n\tconst unsubAccumulated = keepalive(accumulatedText);\n\tgraph.addDisposer(unsubOutput);\n\tgraph.addDisposer(unsubGate);\n\tgraph.addDisposer(unsubAccumulated);\n\n\t// Wrap reject to also abort the in-flight stream. Both mutations happen\n\t// inside `batch()` so downstream subscribers never observe a torn state\n\t// where `gate.count` has decremented but `cancelSignal` hasn't yet\n\t// advanced (spec §2 two-phase DIRTY-before-DATA atomicity).\n\tconst originalReject = gateCtrl.reject.bind(gateCtrl);\n\tconst gateWithAbort: GateController<T> = {\n\t\t...gateCtrl,\n\t\treject(count = 1) {\n\t\t\tbatch(() => {\n\t\t\t\toriginalReject(count);\n\t\t\t\tcancelSignal.emit(++cancelCounter);\n\t\t\t});\n\t\t},\n\t};\n\n\treturn {\n\t\toutput: gateCtrl.output,\n\t\tdeltaTopic,\n\t\taccumulatedText,\n\t\tgate: gateWithAbort,\n\t\tdispose: () => {\n\t\t\tunsubOutput();\n\t\t\tunsubGate();\n\t\t\tunsubAccumulated();\n\t\t\tdeltaTopic.destroy();\n\t\t},\n\t};\n}\n","/**\n * Messaging audit-record schemas (DS-13.5.E, locked 2026-05-01 alt A).\n *\n * Per-site discriminated-union audit records for the four messaging mutation\n * sites that route through `mutate`:\n *\n * - {@link TopicPublishRecord} — `Topic.publish`\n * - {@link SubscriptionAckRecord} — `Subscription.ack`\n * - {@link SubscriptionPullAndAckRecord} — `Subscription.pullAndAck`\n * - {@link HubRemoveTopicRecord} — `Hub.removeTopic`\n *\n * **Opt-in usage.** None of the four mutation sites enable an audit log by\n * default — caller wires audit visibility by composing `mutate` with\n * an audit `ReactiveLogBundle<R>` of the matching record type and an\n * `onSuccess`/`onFailure` builder:\n *\n * ```ts\n * import { createAuditLog, mutate } from \"@graphrefly/graphrefly/extra\";\n * import {\n * type TopicPublishRecord,\n * topicPublishKeyOf,\n * } from \"@graphrefly/graphrefly/patterns/messaging\";\n *\n * const audit = createAuditLog<TopicPublishRecord>({ name: \"publishes\" });\n * const publish = mutate(\n * (item: MyMessage) => topic.publish(item),\n * {\n * frame: \"inline\",\n * log: audit,\n * onSuccessRecord: ([item], _r, m) => ({\n * t_ns: m.t_ns,\n * seq: m.seq,\n * kind: \"topic.publish\",\n * topicName: topic.name,\n * itemKey: keyOf(item),\n * }),\n * },\n * );\n * ```\n *\n * **Stability.** The `kind` discriminator strings are pre-1.0 stable;\n * renaming downstream breaks external auditors.\n *\n * **Composability.** All four records extend {@link BaseAuditRecord} so they\n * carry the cross-cutting `t_ns` / `seq?` / `handlerVersion?` fields stamped\n * by `mutate` (Audit 2 / Audit 5).\n *\n * **Per-record keyOf.** Each record exports a recommended `keyOf` for\n * keyed-storage adapters (Rule G.27-keyOf-recommended) — partition the audit\n * log by the most natural identity (`topicName::itemKey`,\n * `subscriptionId::cursor`, etc.).\n *\n * **Hub.addTopic deferred.** No `HubAddTopicRecord` ships now; the lazy\n * topic-creation site has no caller signal asking for an audit record.\n * Re-add when a consumer surfaces.\n *\n * @category patterns\n * @module patterns/messaging/audit-records\n */\n\nimport type { BaseAuditRecord } from \"../../base/mutation/index.js\";\n\n// ── Topic.publish ────────────────────────────────────────────────────────\n\n/**\n * Audit record for a single {@link TopicGraph.publish} call.\n *\n * - `topicName` — the topic the publish targeted.\n * - `itemKey` — caller-supplied identity for the published item (typically\n * the result of the topic's own `keyOf` derivation, when one exists).\n */\nexport interface TopicPublishRecord extends BaseAuditRecord {\n\treadonly kind: \"topic.publish\";\n\treadonly topicName: string;\n\treadonly itemKey: string;\n}\n\n/**\n * Recommended `keyOf` for {@link TopicPublishRecord} — formats as\n * `${topicName}::${itemKey}` for keyed-storage partitioning. Caller may\n * override per Rule G.27-keyOf-recommended.\n */\nexport const topicPublishKeyOf = (r: TopicPublishRecord): string => `${r.topicName}::${r.itemKey}`;\n\n// ── Subscription.ack ─────────────────────────────────────────────────────\n\n/**\n * Audit record for a single {@link SubscriptionGraph.ack} call.\n *\n * - `subscriptionId` — the subscription the ack advanced.\n * - `cursor` — the post-ack cursor position.\n */\nexport interface SubscriptionAckRecord extends BaseAuditRecord {\n\treadonly kind: \"subscription.ack\";\n\treadonly subscriptionId: string;\n\treadonly cursor: number;\n}\n\n/**\n * Recommended `keyOf` for {@link SubscriptionAckRecord} — formats as\n * `${subscriptionId}::${cursor}`.\n */\nexport const subscriptionAckKeyOf = (r: SubscriptionAckRecord): string =>\n\t`${r.subscriptionId}::${r.cursor}`;\n\n// ── Subscription.pullAndAck ──────────────────────────────────────────────\n\n/**\n * Audit record for a single {@link SubscriptionGraph.pullAndAck} call.\n *\n * - `subscriptionId` — the subscription the pullAndAck advanced.\n * - `cursor` — the post-pullAndAck cursor position.\n * - `itemCount` — number of items returned to the caller in this call.\n */\nexport interface SubscriptionPullAndAckRecord extends BaseAuditRecord {\n\treadonly kind: \"subscription.pullAndAck\";\n\treadonly subscriptionId: string;\n\treadonly cursor: number;\n\treadonly itemCount: number;\n}\n\n/**\n * Recommended `keyOf` for {@link SubscriptionPullAndAckRecord} — formats as\n * `${subscriptionId}::${cursor}` (identical shape to ack records so the\n * combined audit-log partitioning matches a per-cursor-frame view).\n */\nexport const subscriptionPullAndAckKeyOf = (r: SubscriptionPullAndAckRecord): string =>\n\t`${r.subscriptionId}::${r.cursor}`;\n\n// ── Hub.removeTopic ──────────────────────────────────────────────────────\n\n/**\n * Audit record for a single {@link MessagingHubGraph.removeTopic} call.\n *\n * - `topicName` — the topic that was unmounted from the hub.\n */\nexport interface HubRemoveTopicRecord extends BaseAuditRecord {\n\treadonly kind: \"hub.removeTopic\";\n\treadonly topicName: string;\n}\n\n/**\n * Recommended `keyOf` for {@link HubRemoveTopicRecord} — the topic name itself\n * is already the natural identity.\n */\nexport const hubRemoveTopicKeyOf = (r: HubRemoveTopicRecord): string => r.topicName;\n\n// ── Discriminated-union convenience ──────────────────────────────────────\n\n/**\n * Discriminated union over every messaging audit record. Useful for callers\n * that aggregate records from multiple sites into one log; switch on\n * `record.kind` to narrow.\n */\nexport type MessagingAuditRecord =\n\t| TopicPublishRecord\n\t| SubscriptionAckRecord\n\t| SubscriptionPullAndAckRecord\n\t| HubRemoveTopicRecord;\n","/**\n * Standard `TopicMessage<T>` envelope for hub topics + well-known topic name\n * constants (Phase 13.B; spec source: archive/docs/SESSION-human-llm-intervention-primitives.md\n * §6 + archive/docs/SESSION-multi-agent-gap-analysis.md §6 cross-cut).\n *\n * `TopicMessage<T>` is the **recommended** wrapper for cross-agent / cross-graph\n * topic payloads — it carries identity, schema, deadline, and correlation\n * metadata alongside the typed `payload`. It is NOT a required protocol\n * type; raw `topic<T>` continues to work for in-process payloads where the\n * envelope fields would be noise.\n *\n * Use the envelope when:\n * - Two or more graphs (or human + LLM consumers) communicate over a topic\n * and need a stable wire shape — `correlationId` is the join key, `schema`\n * gates payload validation, `expiresAt` enables TTL enforcement.\n * - A topic carries multiple payload kinds and consumers need to discriminate\n * without parsing structurally.\n *\n * The standard well-known topic constants below are **conventions** — string\n * literals callers can pass to `messagingHub().topic(NAME)` to get a\n * predictable lookup. The hub does not enforce any topic to actually exist;\n * topics are still lazy on first access.\n */\n\n// ---------------------------------------------------------------------------\n// JSON Schema — minimal local type\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal JSON Schema shape, scoped to what `TopicMessage<T>` validates against.\n * Locked DS-13.B (2026-04-30): zero-dep posture, structural shape only — no\n * full validator shipped. Callers that want full validation supply their own\n * (e.g. `ajv`, `zod`, `valibot`) and read `Message.schema` as the rule\n * source. The shape covers the JSON-Schema-7 subset that hub-topic payload\n * descriptions actually need:\n * - `type` / `properties` / `required` / `additionalProperties` for objects.\n * - `items` for arrays.\n * - `enum` / `const` for value constraints.\n * - `$ref` / `definitions` for shared sub-schemas.\n *\n * If a concrete consumer needs a richer shape (oneOf, allOf, format, etc.),\n * extend this type — it's a structural contract, not a tagged union, so\n * additive fields don't break existing producers.\n */\nexport interface JsonSchema {\n\treadonly type?:\n\t\t| \"string\"\n\t\t| \"number\"\n\t\t| \"integer\"\n\t\t| \"boolean\"\n\t\t| \"object\"\n\t\t| \"array\"\n\t\t| \"null\"\n\t\t| readonly (\"string\" | \"number\" | \"integer\" | \"boolean\" | \"object\" | \"array\" | \"null\")[];\n\treadonly properties?: Readonly<Record<string, JsonSchema>>;\n\treadonly required?: readonly string[];\n\treadonly additionalProperties?: boolean | JsonSchema;\n\treadonly items?: JsonSchema | readonly JsonSchema[];\n\treadonly enum?: readonly unknown[];\n\treadonly const?: unknown;\n\treadonly $ref?: string;\n\treadonly definitions?: Readonly<Record<string, JsonSchema>>;\n\treadonly description?: string;\n\treadonly title?: string;\n}\n\n// ---------------------------------------------------------------------------\n// TopicMessage<T> envelope\n// ---------------------------------------------------------------------------\n\n/**\n * Recommended envelope for hub topic payloads. Carries identity, optional\n * schema reference, optional expiry, optional correlation, and the typed\n * payload itself.\n *\n * - `id` — globally-unique identifier for this message instance. Producers\n * mint it (UUID, ULID, hash, etc.); consumers use it for deduplication and\n * trace correlation. **Required.**\n * - `schema` — optional structural description of `payload`. Validators\n * (caller-supplied) read this to gate or shape consumption. Writers MAY\n * include the schema inline for self-describing topics, or omit when the\n * payload type is statically known to all consumers.\n * - `expiresAt` — ISO 8601 timestamp; consumers SHOULD drop / fallback past\n * this point. Substrate enforcement is via composition (`timeout(source,\n * ms)` + `fallback`), not a hub-level rule.\n * - `correlationId` — links related messages across topics (request /\n * response pairs, conversation threads, multi-agent handoffs). Producers\n * propagate it; consumers filter / group on it.\n * - `payload` — the typed body. Type parameter `T` is the consumer-agreed\n * shape; the envelope adds metadata around it without coupling consumers\n * to a concrete payload type.\n *\n * Reactive composition with the envelope:\n *\n * ```ts\n * const requests = hub.topic<TopicMessage<RequestBody>>(PROMPTS_TOPIC);\n * const responses = hub.topic<TopicMessage<ResponseBody>>(RESPONSES_TOPIC);\n *\n * // Filter responses to one correlation\n * const myResponse = derived([responses.latest], ([msg]) =>\n * msg?.correlationId === requestId ? [msg.payload] : [],\n * );\n * ```\n */\nexport interface TopicMessage<T> {\n\treadonly id: string;\n\treadonly schema?: JsonSchema;\n\treadonly expiresAt?: string;\n\treadonly correlationId?: string;\n\treadonly payload: T;\n}\n\n// ---------------------------------------------------------------------------\n// Standard topic name constants\n// ---------------------------------------------------------------------------\n\n/**\n * Well-known topic name for human / LLM prompts directed at the harness.\n * Example payload: `TopicMessage<{ prompt: string; context?: object }>`.\n *\n * Co-locked with {@link RESPONSES_TOPIC} per the human-LLM intervention\n * session §6 #4 (paired request / response convention).\n */\nexport const PROMPTS_TOPIC = \"prompts\";\n\n/**\n * Well-known topic name for responses to {@link PROMPTS_TOPIC} entries.\n * Producers pair the response to its prompt via `correlationId`. Example\n * payload: `TopicMessage<{ content: string; finishReason?: string }>`.\n */\nexport const RESPONSES_TOPIC = \"responses\";\n\n/**\n * Well-known topic name for out-of-band injections — runtime overrides /\n * hot-fixes / human nudges that bypass the normal request flow. Example\n * payload: `TopicMessage<{ kind: \"context-patch\" | \"policy-override\" | ...;\n * data: unknown }>`. Per-injection consumers decide how (and whether) to\n * apply.\n */\nexport const INJECTIONS_TOPIC = \"injections\";\n\n/**\n * Well-known topic name for items the harness deferred for later attention\n * (parked queue, follow-up tracker, \"I'll get back to this\"). Producer is\n * usually the harness itself; consumer is a tracker / dashboard / human.\n * Example payload: `TopicMessage<{ reason: string; original: unknown }>`.\n */\nexport const DEFERRED_TOPIC = \"deferred\";\n\n/**\n * Well-known topic name for spawn requests (Phase 13.I `spawnable()`\n * surface). Producer emits a `TopicMessage<SpawnRequest>` to request a child\n * agent / subgraph; consumer is the materializer that mints the slot.\n * Example payload: `TopicMessage<{ presetId: string; taskInput: unknown;\n * depth?: number }>`. `correlationId` links the spawn to its parent\n * conversation; `expiresAt` enforces TTL on long-lived requests.\n */\nexport const SPAWNS_TOPIC = \"spawns\";\n\n/**\n * DS-14.6.A D-B3 — well-known topic for the dynamic `actorPool()` shared\n * tagged-context pool. Actors publish `ContextEntry` here; per-actor views\n * render their own compressed slice.\n */\nexport const CONTEXT_TOPIC = \"context\";\n\n/**\n * DS-14.6.A D-B3 — well-known topic for the `actorPool()` shared todo list.\n * Any actor may `enqueueTodo`; actors pull assigned todos via their cursor.\n */\nexport const TODOS_TOPIC = \"todos\";\n\n/**\n * Tuple of all well-known topic constants — useful for \"register all\n * standard topics on a hub\" patterns and for compile-time exhaustiveness\n * checks.\n */\nexport const STANDARD_TOPICS = [\n\tPROMPTS_TOPIC,\n\tRESPONSES_TOPIC,\n\tINJECTIONS_TOPIC,\n\tDEFERRED_TOPIC,\n\tSPAWNS_TOPIC,\n\tCONTEXT_TOPIC,\n\tTODOS_TOPIC,\n] as const;\n\n/**\n * Union of all well-known topic name string literals.\n */\nexport type StandardTopic = (typeof STANDARD_TOPICS)[number];\n","/**\n * Messaging patterns (roadmap §4.2).\n *\n * Pulsar-inspired messaging primitives modeled as graph factories:\n * - `topic()` for append-only topic streams with a retained window.\n * - `subscription()` for cursor-based consumers.\n * - `topicBridge()` for autonomous topic-to-topic relay.\n * - `messagingHub()` for a lazy topic registry.\n *\n * Plus the Phase 13.B standard `Message<T>` envelope and well-known topic\n * name constants ({@link PROMPTS_TOPIC} / {@link RESPONSES_TOPIC} /\n * {@link INJECTIONS_TOPIC} / {@link DEFERRED_TOPIC} / {@link SPAWNS_TOPIC})\n * — recommended (not enforced) wire shape for cross-graph topic payloads.\n *\n * Job queue / job flow primitives live in `patterns/job-queue` — they are a\n * distinct domain that happens to share reactive-log / reactive-map\n * infrastructure with topics.\n */\n\nexport {\n\ttype HubRemoveTopicRecord,\n\thubRemoveTopicKeyOf,\n\ttype MessagingAuditRecord,\n\ttype SubscriptionAckRecord,\n\ttype SubscriptionPullAndAckRecord,\n\tsubscriptionAckKeyOf,\n\tsubscriptionPullAndAckKeyOf,\n\ttype TopicPublishRecord,\n\ttopicPublishKeyOf,\n} from \"./audit-records.js\";\nexport {\n\tCONTEXT_TOPIC,\n\tDEFERRED_TOPIC,\n\tINJECTIONS_TOPIC,\n\ttype JsonSchema,\n\tPROMPTS_TOPIC,\n\tRESPONSES_TOPIC,\n\tSPAWNS_TOPIC,\n\tSTANDARD_TOPICS,\n\ttype StandardTopic,\n\tTODOS_TOPIC,\n\ttype TopicMessage,\n} from \"./message.js\";\n\nimport { batch, COMPLETE, DATA, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { keepalive, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport { mutate } from \"../../base/mutation/index.js\";\n\nconst DEFAULT_MAX_PER_PUMP = 256;\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\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\t/** Bounded retention; default 1024 per cross-cutting policy (Audit 2/4). */\n\tretainedLimit?: number;\n};\n\nconst DEFAULT_TOPIC_RETAINED_LIMIT = 1024;\n\nexport class TopicGraph<T> extends Graph {\n\tprivate readonly _log;\n\tprivate readonly _publishImpl: (value: T) => void;\n\treadonly events: Node<readonly T[]>;\n\t/**\n\t * Most recently published value. Stays in the protocol SENTINEL state\n\t * (`cache === undefined`, no DATA emitted) until the first publish, then\n\t * tracks the latest entry. Spec §5.12 reserves `undefined` as the\n\t * \"never sent DATA\" sentinel — and `TopicGraph.publish(undefined)` is\n\t * rejected — so `cache === undefined` unambiguously signals \"empty topic\"\n\t * even when `T` itself includes `null` (i.e., `topic<number | null>`).\n\t *\n\t * **Within a reactive fn:** detect the empty-topic case via\n\t * `ctx.prevData[i] === undefined` for the dep slot holding `topic.latest`,\n\t * or check `latest.cache === undefined` outside reactive code. No\n\t * separate `hasLatest` companion needed — the SENTINEL is the answer.\n\t */\n\treadonly latest: Node<T>;\n\n\tconstructor(name: string, opts: TopicOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\tthis._log = reactiveLog<T>([], {\n\t\t\tname: \"events\",\n\t\t\tmaxSize: opts.retainedLimit ?? DEFAULT_TOPIC_RETAINED_LIMIT,\n\t\t});\n\t\tthis.events = this._log.entries;\n\t\tthis.add(this.events, { name: \"events\" });\n\t\t// `this.derived(\"latest\", [\"events\"], …)` is expressible after the\n\t\t// 2026-04-30 self-resolve fix in `Graph._resolveFromSegments` — a\n\t\t// single-segment path matching the graph's own name (e.g.\n\t\t// `topic(\"events\").resolve(\"events\")`) no longer collapses to empty\n\t\t// and falls through to local-node lookup. Replaces the prior\n\t\t// `node([events], …) + this.add(...)` workaround.\n\t\t//\n\t\t// SENTINEL on empty: returning `[]` here yields a RESOLVED-only wave\n\t\t// (no DATA), so `latest.cache` stays `undefined` until the first\n\t\t// publish. `TopicGraph.publish(undefined)` is rejected (line below),\n\t\t// so `undefined` cache is unambiguously \"empty topic\" even when `T`\n\t\t// itself includes `null`. Drops the prior `hasLatest` companion as\n\t\t// redundant.\n\t\tthis.latest = this.derived<T>(\n\t\t\t\"latest\",\n\t\t\t[\"events\"],\n\t\t\t(batchData, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst entries = data[0] as readonly T[];\n\t\t\t\treturn entries.length === 0 ? [] : [entries[entries.length - 1] as T];\n\t\t\t},\n\t\t\t{ meta: messagingMeta(\"topic_latest\") },\n\t\t);\n\t\tthis.addDisposer(keepalive(this.latest));\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\t//\n\t\t// EC16 (verified 2026-04-30): the COMPLETE-then-disposeAllViews order\n\t\t// is intentional. COMPLETE propagates SYNCHRONOUSLY through every\n\t\t// subscriber (cursor views, derived chains) so they self-unsubscribe\n\t\t// in their terminal handler before `disposeAllViews` runs. Swapping\n\t\t// the order would clear view caches before subscribers receive the\n\t\t// terminal — strictly worse. Reading `.cache` outside a reactive fn\n\t\t// across teardown is an anti-pattern (spec §5.12) and not a use case\n\t\t// this ordering needs to preserve.\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 (typical reactive subscribers\n\t\t// have already unsubscribed in their COMPLETE handler above).\n\t\tthis.addDisposer(() => this._log.disposeAllViews());\n\n\t\t// Tier 8 / COMPOSITION-GUIDE §35: route publish through `mutate`\n\t\t// for centralized freeze + re-throw semantics. No audit log surface\n\t\t// (per Tier 8 γ-0): the topic's `events` log already records every\n\t\t// successful publish, so a separate audit Node would be redundant.\n\t\t// `freeze: false` because topic payloads can be large and per-publish\n\t\t// cost matters on hot paths.\n\t\tthis._publishImpl = mutate<[T], void, never>(\n\t\t\t(value): void => {\n\t\t\t\tthis._log.append(value);\n\t\t\t},\n\t\t\t{ frame: \"inline\", freeze: false },\n\t\t);\n\t}\n\n\tpublish(value: T): void {\n\t\t// SENTINEL alignment (Wave B.1 Unit 11 lock): `undefined` is the\n\t\t// protocol-level \"never sent DATA\" sentinel — refusing it here\n\t\t// preserves `lastValue: Node<T | undefined>` semantics.\n\t\tif (value === undefined) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`TopicGraph \"${this.name}\": publish(undefined) is not allowed (spec §5.12 SENTINEL).`,\n\t\t\t);\n\t\t}\n\t\tthis._publishImpl(value);\n\t}\n\n\t/**\n\t * Wire one or more append-log storage tiers (Audit 4). Each tier receives\n\t * appended events per wave; rollback honors the wave-as-transaction model.\n\t *\n\t * Named `attachEventStorage` (not `attachStorage`) to avoid colliding with\n\t * the inherited {@link Graph.attachSnapshotStorage} which takes the\n\t * paired `AttachSnapshotTierPair[]` shape (Phase 14.6) — distinct\n\t * concerns, distinct surfaces.\n\t *\n\t * @returns Disposer.\n\t */\n\tattachEventStorage(\n\t\ttiers: readonly import(\"@graphrefly/pure-ts/extra\").AppendLogStorageTier<T>[],\n\t): () => void {\n\t\treturn this._log.attachStorage(tiers);\n\t}\n\n\tretained(): readonly T[] {\n\t\treturn this.events.cache as readonly T[];\n\t}\n\n\t/** Internal log bundle — used by TopicBridgeGraph for `attach`. */\n\tget _logBundle() {\n\t\treturn this._log;\n\t}\n}\n\nexport type SubscriptionOptions = {\n\tgraph?: GraphOptions;\n\t/**\n\t * Starting cursor position.\n\t * @deprecated Use `from` instead.\n\t */\n\tcursor?: number;\n\t/**\n\t * Starting position for the subscription.\n\t * - `\"retained\"` (default) — cursor starts at 0; consumer sees all retained history.\n\t * - `\"now\"` — cursor starts at current topic length; consumer ignores history.\n\t * - `number` — explicit cursor position.\n\t */\n\tfrom?: \"now\" | \"retained\" | number;\n\t/**\n\t * When this signal node emits DATA, the subscription auto-advances cursor\n\t * to current `available.length`. Useful for \"ack everything when X happens\"\n\t * patterns. The reactive edge `advanceOn → cursor` is visible in `explain()`.\n\t */\n\tadvanceOn?: Node<unknown>;\n};\n\n/** Result of {@link SubscriptionGraph.pullAndAck}. */\nexport type PullAndAckResult<T> = {\n\titems: readonly T[];\n\tcursor: number;\n};\n\nexport class SubscriptionGraph<T> extends Graph {\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\tprivate _disposed = false;\n\tprivate readonly _ackImpl: (count: number | undefined) => number;\n\tprivate readonly _pullAndAckImpl: (limit: number | undefined) => PullAndAckResult<T>;\n\n\tconstructor(name: string, topicGraph: TopicGraph<T>, opts: SubscriptionOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\tthis.topic = topicGraph;\n\n\t\t// Resolve initial cursor from `from` option, falling back to legacy `cursor` option.\n\t\tlet initialCursor: number;\n\t\tif (opts.from !== undefined) {\n\t\t\tif (opts.from === \"retained\") {\n\t\t\t\tinitialCursor = 0;\n\t\t\t} else if (opts.from === \"now\") {\n\t\t\t\t// §28 sanctioned factory-time boundary read.\n\t\t\t\tinitialCursor = (topicGraph.events.cache as readonly T[]).length;\n\t\t\t} else {\n\t\t\t\tinitialCursor = requireNonNegativeInt(opts.from, \"subscription from\");\n\t\t\t}\n\t\t} else {\n\t\t\tinitialCursor = requireNonNegativeInt(opts.cursor ?? 0, \"subscription cursor\");\n\t\t}\n\n\t\tthis.cursor = this.state<number>(\"cursor\", initialCursor, {\n\t\t\tmeta: messagingMeta(\"subscription_cursor\"),\n\t\t});\n\n\t\t// B.1 Unit 12 lock: `available` depends directly on topic.events + cursor\n\t\t// via `view({ kind: \"fromCursor\" })`. No `source` passthrough node —\n\t\t// describe shows `topic::events → available` (cross-graph edge) and\n\t\t// `cursor → available` (local edge). One fewer node per subscription.\n\t\tthis.available = topicGraph._logBundle.view({ kind: \"fromCursor\", cursor: this.cursor });\n\t\tthis.add(this.available, { name: \"available\" });\n\t\tthis.addDisposer(keepalive(this.available));\n\n\t\t// Optional reactive auto-advance: when `advanceOn` emits a NEW DATA\n\t\t// (after construction), cursor advances by `available.length` atomically.\n\t\t// Edge visible in describe: advancePump depends on advanceOn.\n\t\t// `_advanceInitialized` guards against the initial push-on-subscribe fire\n\t\t// that would advance cursor before the user has a chance to read.\n\t\tif (opts.advanceOn !== undefined) {\n\t\t\tconst advanceOn = opts.advanceOn;\n\t\t\tlet advanceInitialized = false;\n\t\t\tconst advancePump = node<unknown>(\n\t\t\t\t[advanceOn],\n\t\t\t\t() => {\n\t\t\t\t\t// Skip the initial push-on-subscribe wave.\n\t\t\t\t\tif (!advanceInitialized) {\n\t\t\t\t\t\tadvanceInitialized = true;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (this._disposed) return;\n\t\t\t\t\tconst avail = this.available.cache as readonly T[];\n\t\t\t\t\tif (avail.length === 0) return;\n\t\t\t\t\tconst next = (this.cursor.cache as number) + avail.length;\n\t\t\t\t\tthis.cursor.emit(next);\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"advancePump\",\n\t\t\t\t\tdescribeKind: \"effect\",\n\t\t\t\t\tmeta: messagingMeta(\"subscription_advance_pump\"),\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.add(advancePump, { name: \"advancePump\" });\n\t\t\tthis.addDisposer(keepalive(advancePump));\n\t\t}\n\n\t\t// Tier 8 / COMPOSITION-GUIDE §35: route ack + pullAndAck through\n\t\t// `mutate` for centralized freeze + re-throw semantics. No audit\n\t\t// log surface (per Tier 8 γ-0): the cursor's own emission stream already\n\t\t// records every advance, so a separate audit Node would be redundant.\n\t\t// `freeze: false` because count/limit are simple numbers; freezing is\n\t\t// pointless overhead. Disposed-checks stay outside the wrapper so a\n\t\t// no-op call doesn't unnecessarily run the wrapper.\n\t\tthis._ackImpl = mutate<[number | undefined], number, never>(\n\t\t\t(count): number => {\n\t\t\t\tconst available = this.available.cache as readonly T[];\n\t\t\t\tconst requested =\n\t\t\t\t\tcount === undefined\n\t\t\t\t\t\t? available.length\n\t\t\t\t\t\t: requireNonNegativeInt(count, \"subscription ack count\");\n\t\t\t\tconst step = Math.min(requested, available.length);\n\t\t\t\tif (step <= 0) return this.cursor.cache as number;\n\t\t\t\tconst next = (this.cursor.cache as number) + step;\n\t\t\t\t// F8: use emit() so the pipeline auto-prefixes DIRTY, runs equals\n\t\t\t\t// substitution, and produces a proper two-phase wave (the raw\n\t\t\t\t// `down([[DATA, next]])` path bypassed those contracts).\n\t\t\t\tthis.cursor.emit(next);\n\t\t\t\treturn next;\n\t\t\t},\n\t\t\t{ frame: \"inline\", freeze: false },\n\t\t);\n\n\t\tthis._pullAndAckImpl = mutate<[number | undefined], PullAndAckResult<T>, never>(\n\t\t\t(limit): PullAndAckResult<T> => {\n\t\t\t\tconst available = this.available.cache as readonly T[];\n\t\t\t\tconst max =\n\t\t\t\t\tlimit === undefined\n\t\t\t\t\t\t? available.length\n\t\t\t\t\t\t: requireNonNegativeInt(limit, \"subscription pullAndAck limit\");\n\t\t\t\tconst items = available.slice(0, max);\n\t\t\t\tif (items.length === 0) return { items, cursor: this.cursor.cache as number };\n\t\t\t\tconst next = (this.cursor.cache as number) + items.length;\n\t\t\t\tthis.cursor.emit(next);\n\t\t\t\treturn { items, cursor: next };\n\t\t\t},\n\t\t\t{ frame: \"inline\", freeze: false },\n\t\t);\n\t}\n\n\tack(count?: number): number {\n\t\tif (this._disposed) return this.cursor.cache as number;\n\t\treturn this._ackImpl(count);\n\t}\n\n\tpull(limit?: number): readonly T[] {\n\t\tif (this._disposed) return [];\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\treturn available.slice(0, max);\n\t}\n\n\t/**\n\t * Atomic pull-and-acknowledge. Returns `{ items, cursor }` where `cursor`\n\t * is the new cursor position after advancing. Under single-threaded JS the\n\t * snapshot and advance are atomic; PY callers use a per-subscription Lock.\n\t *\n\t * Replaces `pull(limit, { ack: true })`.\n\t */\n\tpullAndAck(limit?: number): PullAndAckResult<T> {\n\t\tif (this._disposed) return { items: [], cursor: this.cursor.cache as number };\n\t\treturn this._pullAndAckImpl(limit);\n\t}\n\n\t/**\n\t * Release internal subscriptions and mark the subscription torn-down.\n\t * Subsequent `pull`, `pullAndAck`, `ack` return empty / current cursor.\n\t * Emits COMPLETE on `cursor` so derived consumers (e.g. `available`) see\n\t * the termination signal. Also drains `addDisposer` callbacks (including\n\t * the `keepalive(advancePump)` subscription) so no keepalive leak occurs.\n\t */\n\tdispose(): void {\n\t\tif (this._disposed) return;\n\t\tthis._disposed = true;\n\t\tthis.cursor.down([[COMPLETE]]);\n\t\t// m4: drain addDisposer callbacks to release the keepalive subscription.\n\t\tthis.destroy();\n\t}\n}\n\nexport type TopicBridgeOptions<TIn, TOut> = {\n\tgraph?: GraphOptions;\n\tcursor?: number;\n\tmaxPerPump?: number;\n\t/**\n\t * Optional transform/filter applied to each item before republishing.\n\t *\n\t * **At-most-once with silent drop:** when `map` returns `undefined`, the\n\t * input is consumed from the source cursor but NOT republished. Filtered\n\t * items are not retained for retry. If you need filter-with-retry\n\t * semantics, do the filtering in a downstream subscription on the bridged\n\t * output rather than in the `map` function.\n\t */\n\tmap?: (value: TIn) => TOut | undefined;\n};\n\nexport class TopicBridgeGraph<TIn, TOut = TIn> extends Graph {\n\tprivate readonly _sourceSub;\n\treadonly bridgedCount: Node<number>;\n\t/**\n\t * Emits each mapped batch as DATA — gives downstream observers a reactive\n\t * stream of bridged values. Also the link target for `target._log.attach`.\n\t */\n\treadonly output: Node<readonly TOut[]>;\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.mount(\"subscription\", this._sourceSub);\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\n\t\t// Reactive output node: derives a mapped batch from `available`.\n\t\t// §24 compliant — output is a real derived edge, visible in describe.\n\t\t// Replaces imperative publish loop. Items where mapValue returns undefined\n\t\t// are filtered out (opt-out / filter).\n\t\tthis.output = node<readonly TOut[]>(\n\t\t\t[this._sourceSub.available],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst arr = data[0] as readonly TIn[];\n\t\t\t\tconst outBatch: TOut[] = [];\n\t\t\t\tconst take = Math.min(arr.length, maxPerPump);\n\t\t\t\tfor (let i = 0; i < take; i++) {\n\t\t\t\t\tconst mapped = mapValue(arr[i] as TIn);\n\t\t\t\t\tif (mapped !== undefined) outBatch.push(mapped);\n\t\t\t\t}\n\t\t\t\tactions.emit(outBatch);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"output\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: messagingMeta(\"topic_bridge_output\", { targetRef: targetTopic.name }),\n\t\t\t\tinitial: [],\n\t\t\t},\n\t\t);\n\t\tthis.add(this.output, { name: \"output\" });\n\t\tthis.addDisposer(keepalive(this.output));\n\n\t\t// bridgedCount: state node accumulating total bridged items.\n\t\t// Updated by ackPump after each batch — edge visible via ackPump dep on output.\n\t\tthis.bridgedCount = this.state<number>(\"bridgedCount\", 0, {\n\t\t\tmeta: messagingMeta(\"topic_bridge_count\"),\n\t\t});\n\t\tthis.addDisposer(keepalive(this.bridgedCount));\n\n\t\t// ackPump: effect that advances the subscription cursor and updates\n\t\t// bridgedCount after each batch. Runs after `output` settles.\n\t\t// Captures refs to `this.output`, `this._sourceSub`, `this.bridgedCount`\n\t\t// to avoid `this` inside the fn body.\n\t\tconst outputRef = this.output;\n\t\tconst subRef = this._sourceSub;\n\t\tconst countRef = this.bridgedCount;\n\t\tconst ackPump = this.effect(\n\t\t\t\"ackPump\",\n\t\t\t[\"output\"],\n\t\t\t() => {\n\t\t\t\tconst outBatch = outputRef.cache as readonly TOut[];\n\t\t\t\tif (outBatch.length === 0) return;\n\t\t\t\tconst availLen = (subRef.available.cache as readonly TIn[]).length;\n\t\t\t\tconst toAck = Math.min(availLen, maxPerPump);\n\t\t\t\tif (toAck > 0) {\n\t\t\t\t\tsubRef.ack(toAck);\n\t\t\t\t\tconst prev = (countRef.cache as number) ?? 0;\n\t\t\t\t\tcountRef.emit(prev + outBatch.length);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tmeta: messagingMeta(\"topic_bridge_ack_pump\"),\n\t\t\t},\n\t\t);\n\t\tthis.addDisposer(keepalive(ackPump));\n\n\t\t// Wire output into target topic's log reactively.\n\t\t// _attachArrayToLog subscribes to output and publishes each item to targetTopic.\n\t\t// Teardown: disposer runs before mount teardown.\n\t\tconst detach = _attachArrayToLog(this.output, targetTopic);\n\t\tthis.addDisposer(detach);\n\t}\n}\n\n/**\n * Attaches each element of an array-valued Node to a TopicGraph's log.\n * Every DATA emission on `source` appends all items in the array to `targetTopic`.\n * Returns a disposer.\n */\nfunction _attachArrayToLog<T>(source: Node<readonly T[]>, targetTopic: TopicGraph<T>): () => void {\n\treturn source.subscribe((msgs) => {\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] !== DATA) continue;\n\t\t\tconst arr = m[1] as readonly T[];\n\t\t\tif (arr.length === 0) continue;\n\t\t\tbatch(() => {\n\t\t\t\tfor (const v of arr) targetTopic.publish(v);\n\t\t\t});\n\t\t}\n\t});\n}\n\n// ── TopicRegistry ─────────────────────────────────────────────────────────\n\n/**\n * Private pure data structure managing a named set of {@link TopicGraph}\n * instances. Extracted from {@link MessagingHubGraph} for separation of\n * concerns (B.2 Unit 14 lock: D — split into TopicRegistry + facade).\n *\n * Reusable if other domain consumers (e.g. cqrs.eventLogs) want a shared\n * topic registry later.\n *\n * @internal\n */\nexport class TopicRegistry {\n\tprivate readonly _map = new Map<string, TopicGraph<unknown>>();\n\t/** Reactive monotonic version counter. Advances on topic create/remove. */\n\treadonly version: Node<number>;\n\n\tconstructor(versionNode: Node<number>) {\n\t\tthis.version = versionNode;\n\t}\n\n\tget size(): number {\n\t\treturn this._map.size;\n\t}\n\n\thas(name: string): boolean {\n\t\treturn this._map.has(name);\n\t}\n\n\tget<T>(name: string): TopicGraph<T> | undefined {\n\t\treturn this._map.get(name) as TopicGraph<T> | undefined;\n\t}\n\n\tset<T>(name: string, t: TopicGraph<T>): void {\n\t\tthis._map.set(name, t as TopicGraph<unknown>);\n\t}\n\n\tdelete(name: string): boolean {\n\t\treturn this._map.delete(name);\n\t}\n\n\tkeys(): IterableIterator<string> {\n\t\treturn this._map.keys();\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 * Internally delegates to {@link TopicRegistry} for topic map management\n * (B.2 Unit 14 lock: D facade split).\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 _registry: TopicRegistry;\n\t/** Reactive monotonic version counter — advances on topic create/remove. */\n\treadonly version: Node<number>;\n\tprivate readonly _defaultTopicOptions: TopicOptions;\n\tprivate readonly _removeTopicImpl: (name: string) => void;\n\n\tconstructor(name: string, opts: MessagingHubOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\t// B.2 Unit 14 lock: promote _version → version: Node<number>.\n\t\tconst versionNode = this.state<number>(\"version\", 0, {\n\t\t\tmeta: messagingMeta(\"hub_version\"),\n\t\t});\n\t\tthis.version = versionNode;\n\t\tthis._registry = new TopicRegistry(versionNode);\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\n\t\t// Tier 8 / COMPOSITION-GUIDE §35: route the registry-delete branch of\n\t\t// `removeTopic` through `mutate` for centralized re-throw\n\t\t// semantics. No audit log surface (per Tier 8 γ-0).\n\t\t// `freeze: false` because the only arg is a string name (freeze pointless).\n\t\t// **Closure-state caveat (γ-4):** the inner `try/finally` mutates\n\t\t// `_registry` (a `Map`) and emits the version bump. mutate has no\n\t\t// `batch()` frame, so reactive emissions are NOT rolled back on throw —\n\t\t// and even if it did, `Map.delete` on closure state is invisible to the\n\t\t// batch and can't be unwound. The pre-existing try/finally on\n\t\t// `Graph.remove` is what guarantees registry/version converge to a\n\t\t// consistent state when `remove()` throws; `mutate` adds nothing\n\t\t// to that contract beyond the re-throw.\n\t\tthis._removeTopicImpl = mutate<[string], void, never>(\n\t\t\t(topicName): void => {\n\t\t\t\ttry {\n\t\t\t\t\tthis.remove(topicName); // unmounts, drops edges, tears down\n\t\t\t\t} finally {\n\t\t\t\t\tthis._registry.delete(topicName);\n\t\t\t\t\tconst cur = (this.version.cache as number) ?? 0;\n\t\t\t\t\tthis.version.emit(cur + 1);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ frame: \"inline\", freeze: false },\n\t\t);\n\t}\n\n\t/** Number of topics currently in the hub. */\n\tget size(): number {\n\t\treturn this._registry.size;\n\t}\n\n\t/** Checks topic existence without creating. */\n\thas(name: string): boolean {\n\t\treturn this._registry.has(name);\n\t}\n\n\t/** Iterator over topic names. */\n\ttopicNames(): IterableIterator<string> {\n\t\treturn this._registry.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._registry.get<T>(name);\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._registry.set(name, t);\n\t\t\tthis.mount(name, t);\n\t\t\tconst cur = (this.version.cache as number) ?? 0;\n\t\t\tthis.version.emit(cur + 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\t * **Closure-state caveat:** the registry mutation (`_registry.delete`) and\n\t * version bump happen in a `try/finally`, so registry/version converge to\n\t * a consistent state even when {@link Graph.remove} throws. `mutate`\n\t * does not roll back this mutation on throw — `Map.delete` on closure\n\t * state is invisible to any batch frame. The pre-existing try/finally is\n\t * load-bearing for that invariant.\n\t */\n\tremoveTopic(name: string): boolean {\n\t\tif (!this._registry.has(name)) return false;\n\t\t// P1 / P3: Graph.remove first — if it throws, `_registry` 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). The `try/finally`\n\t\t// inside `_removeTopicImpl`'s action body preserves that invariant.\n\t\tthis._removeTopicImpl(name);\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/patterns/messaging\";\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 an autonomous cursor-based topic relay graph.\n *\n * When `opts.map` is provided, items where `map` returns `undefined` are\n * consumed from the source cursor but NOT republished (at-most-once with\n * silent drop). For filter-with-retry semantics, apply the filter in a\n * downstream subscription on the bridge's `output` node instead.\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 * Universal mutation framework (Phase 14 — DS-14 locked 2026-05-05).\n *\n * Single `mutate(act, opts)` factory replaces the prior `lightMutation` +\n * `wrapMutation` two-tier split (pre-1.0 break per Q-O2).\n *\n * Two frames:\n * - `\"inline\"` — no batch; up() runs raw. Seq bumps before action; persists\n * on throw. Hot-path-friendly for atomic single-write mutations.\n * - `\"transactional\"` — opens `batch(() => up(...))`. On throw: batch discards\n * deferred deliveries, then `down()` runs (if provided), then failure record.\n *\n * Phase-4 primitives share the same shape: imperative mutation methods +\n * closure state + reactive audit log + freeze-at-entry + rollback-on-throw.\n * This module factors out the common machinery so each primitive becomes\n * declarative wiring over typed audit records.\n */\n\nimport {\n\tbatch,\n\tDATA,\n\tDIRTY,\n\ttype Node,\n\ttype NodeGuard,\n\tnode,\n\tpolicy,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport {\n\ttype ReactiveLogBundle,\n\ttype ReactiveLogOptions,\n\treactiveLog,\n} from \"@graphrefly/pure-ts/extra\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\n\n// ── tryIncrementBounded ──────────────────────────────────────────────────\n\n/**\n * Bounded increment for a self-owned counter state node.\n *\n * Reads `counter.cache`, bumps by `by` (default 1) if `cur + by <= cap`,\n * writes back. Returns `false` when the cap would be exceeded (no-op write).\n * Documented P3 exception: the counter is not a declared dep of the caller —\n * it's a private budget read+written from a single call site. This helper\n * keeps the `.cache` access in one named place so caller bodies (which may\n * be inside reactive fn execution paths) stay free of cross-node `.cache`\n * reads.\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 * @param counter - Self-owned counter Node. Caller is the sole writer.\n * @param cap - Upper bound (inclusive). Pass `Number.MAX_SAFE_INTEGER` for\n * \"effectively unbounded\" use cases (e.g. token meters).\n * @param by - Delta to add (default `1`). Must be a finite non-negative\n * number; callers should pre-validate. Overflow-safe via\n * `by > cap - cur` check rather than `cur + by >= cap`.\n */\nexport function tryIncrementBounded(counter: Node<number>, cap: number, by = 1): boolean {\n\tconst cur = (counter.cache as number | undefined) ?? 0;\n\tif (by > cap - cur) return false;\n\tcounter.down([[DIRTY], [DATA, cur + by]]);\n\treturn true;\n}\n\n// ── Audit record schema ──────────────────────────────────────────────────\n\n/** Shared base shape for every audit record. Per-primitive types extend this. */\nexport interface BaseAuditRecord {\n\treadonly t_ns: number;\n\treadonly seq?: number;\n\treadonly handlerVersion?: { id: string; version: string | number };\n}\n\n// ── Default audit guard ──────────────────────────────────────────────────\n\n/**\n * Allow `observe` and `signal`; deny external `write` on the audit log so\n * consumers can subscribe + signal-bridge but cannot inject fake records.\n */\nexport const DEFAULT_AUDIT_GUARD: NodeGuard = policy((allow, deny) => {\n\tallow(\"observe\");\n\tallow(\"signal\");\n\tdeny(\"write\");\n});\n\n// ── createAuditLog ───────────────────────────────────────────────────────\n\nexport type AuditLogOpts<R extends BaseAuditRecord> = {\n\tname: string;\n\t/** Bounded retention; default 1024 per Audit 2 / cross-cutting bounded-default policy. */\n\tretainedLimit?: number;\n\t/** Override the default audit guard. */\n\tguard?: NodeGuard;\n\t/** Mount the audit `entries` Node under this graph (and activate withLatest). */\n\tgraph?: Graph;\n\t/** Pass-through to {@link reactiveLog}. */\n\tversioning?: ReactiveLogOptions<R>[\"versioning\"];\n};\n\n/**\n * Build a reactive audit log with sane defaults: bounded retention, deny-write\n * guard, `withLatest()` companions activated. Returns the {@link ReactiveLogBundle}\n * directly — primitives expose this as `<primitive>.events` / `.decisions` /\n * `.dispatches` / `.invocations` and alias it as `.audit`.\n *\n * @category internal\n */\nexport function createAuditLog<R extends BaseAuditRecord>(\n\topts: AuditLogOpts<R>,\n): ReactiveLogBundle<R> {\n\tconst log = reactiveLog<R>([], {\n\t\tname: opts.name,\n\t\tmaxSize: opts.retainedLimit ?? 1024,\n\t\tguard: opts.guard ?? DEFAULT_AUDIT_GUARD,\n\t\t...(opts.versioning != null ? { versioning: opts.versioning } : {}),\n\t});\n\t// Lazy companion activation up-front so `bundle.lastValue` / `hasLatest`\n\t// are queryable without an explicit `withLatest()` call.\n\tlog.withLatest();\n\tif (opts.graph) {\n\t\topts.graph.add(log.entries, { name: opts.name });\n\t}\n\treturn log;\n}\n\n// ── Universal mutation factory (Phase 14 — DS-14 lock Q-O2/Q-O3) ────────\n//\n// Single `mutate(act, opts)` factory. Two frames:\n//\n// - `\"inline\"` — no batch frame; up() runs raw. Seq bumps before action;\n// persists on throw. Hot-path-friendly for atomic single-write mutations.\n//\n// - `\"transactional\"` — opens `batch(() => up(...))`. On throw: batch discards\n// deferred deliveries, then `down()` runs, then failure record persists.\n//\n// **Heuristic:** if your imperative method's body is one or two lines (mutate\n// state, emit), use `frame: \"inline\"`. If it runs a user-supplied handler or\n// has multiple steps that could leave inconsistent state mid-throw, use\n// `frame: \"transactional\"`.\n\nexport type FailureMeta = {\n\tt_ns: number;\n\tseq?: number;\n\terrorType: string;\n};\n\nexport type SuccessMeta = {\n\tt_ns: number;\n\tseq?: number;\n};\n\n/**\n * Mutation action shape. Plain function shorthand auto-wraps as `{ up: fn }`.\n *\n * - `up` — the mutation action (the \"up migration\").\n * - `down` — optional rollback for closure mutations that `batch()` can't\n * reach. Receives the SAME frozen args as `up`. Runs AFTER batch reactive\n * rollback, BEFORE the failure record. Throws inside `down` are\n * console.error'd without masking the original error. Only meaningful\n * with `frame: \"transactional\"`.\n */\nexport type MutationAct<TArgs extends readonly unknown[], TResult> = {\n\tup: (...args: TArgs) => TResult;\n\tdown?: (...args: TArgs) => void;\n};\n\nexport type MutationFrame = \"inline\" | \"transactional\";\n\nexport type MutateOpts<TArgs extends readonly unknown[], TResult, R extends BaseAuditRecord> = {\n\t/** Frame mode. `\"inline\"` = no batch; `\"transactional\"` = batch + rollback. */\n\tframe: MutationFrame;\n\t/**\n\t * Optional log to append records to. When omitted, the wrapper still\n\t * provides freeze / seq-advance / rollback-on-throw but skips record\n\t * emission — useful for primitives that want centralized mutation\n\t * semantics without a dedicated log surface (e.g. `Topic.publish`).\n\t */\n\tlog?: ReactiveLogBundle<R>;\n\t/** Build the success record from the action's args + result + meta. */\n\tonSuccessRecord?: (args: TArgs, result: TResult, meta: SuccessMeta) => R | undefined;\n\t/** Build the failure record from the args + error + meta. */\n\tonFailureRecord?: (args: TArgs, error: unknown, meta: FailureMeta) => R | undefined;\n\t/** Deep-freeze args at entry (default `true`). Opt out for hot paths. */\n\tfreeze?: boolean;\n\t/** Optional sequence cursor — auto-advanced and stamped onto records. */\n\tseq?: Node<number>;\n\t/** Optional handler version — stamped per Audit 5. */\n\thandlerVersion?: { id: string; version: string | number };\n};\n\nfunction deepFreeze<T>(value: T): T {\n\tif (value === null || typeof value !== \"object\" || Object.isFrozen(value)) return value;\n\tfor (const k of Object.keys(value as Record<string, unknown>)) {\n\t\tdeepFreeze((value as Record<string, unknown>)[k]);\n\t}\n\treturn Object.freeze(value);\n}\n\n/**\n * Universal mutation factory (Phase 14 — DS-14 Q-O2).\n *\n * Replaces the prior `lightMutation` + `wrapMutation` two-tier split.\n * Single factory with `frame: \"inline\" | \"transactional\"` discriminant.\n *\n * @param act - The mutation action. Either a plain function (auto-wrapped as\n * `{ up: fn }`) or a `{ up, down? }` object for explicit rollback.\n * @param opts - Configuration: frame, log, record builders, freeze, seq.\n * @returns A typed wrapper function with the same signature as `act.up`.\n */\nexport function mutate<TArgs extends readonly unknown[], TResult, R extends BaseAuditRecord>(\n\tact: MutationAct<TArgs, TResult> | ((...args: TArgs) => TResult),\n\topts: MutateOpts<TArgs, TResult, R>,\n): (...args: TArgs) => TResult {\n\tconst { up, down } = typeof act === \"function\" ? { up: act, down: undefined } : act;\n\tconst freeze = opts.freeze ?? true;\n\n\tif (opts.frame === \"inline\") {\n\t\treturn function wrapped(...args: TArgs): TResult {\n\t\t\tconst sealed = freeze ? (args.map(deepFreeze) as unknown as TArgs) : args;\n\t\t\tconst t_ns = wallClockNs();\n\t\t\tconst seq = opts.seq ? bumpCursor(opts.seq) : undefined;\n\t\t\ttry {\n\t\t\t\tconst result = up(...sealed);\n\t\t\t\tif (opts.log && opts.onSuccessRecord) {\n\t\t\t\t\tappendAudit<TArgs, TResult, R, SuccessMeta>(\n\t\t\t\t\t\topts.log,\n\t\t\t\t\t\topts.onSuccessRecord,\n\t\t\t\t\t\tsealed,\n\t\t\t\t\t\tresult,\n\t\t\t\t\t\t{ t_ns, seq },\n\t\t\t\t\t\topts.handlerVersion,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.log && opts.onFailureRecord) {\n\t\t\t\t\tconst errorType = err instanceof Error ? err.name : typeof err;\n\t\t\t\t\tappendAudit<TArgs, unknown, R, FailureMeta>(\n\t\t\t\t\t\topts.log,\n\t\t\t\t\t\topts.onFailureRecord,\n\t\t\t\t\t\tsealed,\n\t\t\t\t\t\terr,\n\t\t\t\t\t\t{ t_ns, seq, errorType },\n\t\t\t\t\t\topts.handlerVersion,\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\t}\n\n\t// frame === \"transactional\"\n\treturn function wrapped(...args: TArgs): TResult {\n\t\tconst sealed = freeze ? (args.map(deepFreeze) as unknown as TArgs) : args;\n\t\tconst t_ns = wallClockNs();\n\t\tlet result: TResult;\n\t\tlet captured: unknown;\n\t\tlet captureSet = false;\n\t\tlet seq: number | undefined;\n\t\ttry {\n\t\t\tbatch(() => {\n\t\t\t\tif (opts.seq) seq = bumpCursor(opts.seq);\n\t\t\t\ttry {\n\t\t\t\t\tresult = up(...sealed);\n\t\t\t\t\tif (opts.log && opts.onSuccessRecord) {\n\t\t\t\t\t\tappendAudit<TArgs, TResult, R, SuccessMeta>(\n\t\t\t\t\t\t\topts.log,\n\t\t\t\t\t\t\topts.onSuccessRecord,\n\t\t\t\t\t\t\tsealed,\n\t\t\t\t\t\t\tresult,\n\t\t\t\t\t\t\t{ t_ns, seq },\n\t\t\t\t\t\t\topts.handlerVersion,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tcaptured = err;\n\t\t\t\t\tcaptureSet = true;\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (outerErr) {\n\t\t\t// Fire `down` AFTER batch's reactive rollback, BEFORE failure record.\n\t\t\t// Gate on `captureSet` — if the throw came from outside the inner try\n\t\t\t// (framework-level batch error before action ran), don't fire down.\n\t\t\tif (captureSet && down) {\n\t\t\t\ttry {\n\t\t\t\t\tdown(...sealed);\n\t\t\t\t} catch (downErr) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`mutate: down hook threw — original action error preserved (${\n\t\t\t\t\t\t\tcaptured instanceof Error ? captured.name : typeof captured\n\t\t\t\t\t\t}). Down error:`,\n\t\t\t\t\t\tdownErr,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (captureSet && opts.log && opts.onFailureRecord) {\n\t\t\t\tconst errorType = captured instanceof Error ? captured.name : typeof captured;\n\t\t\t\tappendAudit<TArgs, unknown, R, FailureMeta>(\n\t\t\t\t\topts.log,\n\t\t\t\t\topts.onFailureRecord,\n\t\t\t\t\tsealed,\n\t\t\t\t\tcaptured,\n\t\t\t\t\t{ t_ns, seq, errorType },\n\t\t\t\t\topts.handlerVersion,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow captureSet ? captured : outerErr;\n\t\t}\n\t\treturn result!;\n\t};\n}\n\n/**\n * Advance a cursor node and return the new value. Emits `[DIRTY], [DATA, next]`\n * directly on the cursor — atomic outside a batch, rollback-discardable inside.\n *\n * Resets to `0` if the cursor cache is missing, non-numeric, `NaN`, or\n * non-finite (e.g. corrupted by `restore()` from a malformed snapshot, or\n * by a misbehaving codec). `??` alone would let `NaN` and `\"\"` pass through\n * and silently corrupt audit ordering downstream.\n *\n * **Silent reset diagnostic (EH-12).** When the cache holds a non-numeric\n * value at bump time, the cursor restarts at 0 and the next bump returns 1\n * — colliding with the seq stamped on the very first record after construct.\n * To make seq-monotonicity violations after a restore visible to operators,\n * the helper emits a one-shot `console.warn` per cursor instance describing\n * the offending value. The cursor is identified by a `WeakSet<Node<number>>`\n * so the warning fires exactly once per node — repeat malformed bumps stay\n * quiet to avoid log spam. Production callers wanting to suppress can swap\n * the global `console` (universal-safe code path; no Node-only API used).\n *\n * Works whether or not the cursor has any subscribers — `down` updates the\n * cache regardless, so primitives that bump before consumers attach (e.g.\n * `JobQueueGraph.enqueue`) still see a coherent sequence.\n *\n * @category internal\n */\nconst _bumpCursorWarned = new WeakSet<Node<number>>();\nexport function bumpCursor(seq: Node<number>): number {\n\tconst raw = seq.cache;\n\tconst valid = typeof raw === \"number\" && Number.isFinite(raw);\n\tif (!valid && raw !== undefined && !_bumpCursorWarned.has(seq)) {\n\t\t_bumpCursorWarned.add(seq);\n\t\tconsole.warn(\n\t\t\t`bumpCursor: cursor cache held a non-numeric value (${String(raw)}); resetting to 0. ` +\n\t\t\t\t\"Causes include: a snapshot codec round-tripping the cursor as a string / null / NaN, \" +\n\t\t\t\t\"OR a malformed initial seed (e.g. state<number>(NaN)). \" +\n\t\t\t\t\"Audit consumers may see colliding seq values after this point.\",\n\t\t);\n\t}\n\tconst cur = valid ? raw : 0;\n\tconst next = cur + 1;\n\tseq.down([[DIRTY], [DATA, next]]);\n\treturn next;\n}\n\n/**\n * Build a record via the supplied builder, stamp `handlerVersion` if present,\n * and append it to the audit log. `undefined` records are skipped (callers\n * pass an `onSuccess` / `onFailure` that returns `undefined` to opt out per\n * call).\n *\n * @category internal\n */\nexport function appendAudit<\n\tTArgs extends readonly unknown[],\n\tTValue,\n\tR extends BaseAuditRecord,\n\tM extends SuccessMeta | FailureMeta,\n>(\n\taudit: ReactiveLogBundle<R>,\n\tbuilder: (args: TArgs, value: TValue, meta: M) => R | undefined,\n\targs: TArgs,\n\tvalue: TValue,\n\tmeta: M,\n\thandlerVersion?: { id: string; version: string | number },\n): void {\n\tconst record = builder(args, value, meta);\n\tif (record === undefined) return;\n\tconst stamped = handlerVersion != null ? ({ ...record, handlerVersion } as R) : record;\n\taudit.append(stamped);\n}\n\n// ── registerCursor / registerCursorMap ───────────────────────────────────\n\n/**\n * Promote a closure counter to a state node mounted under `graph`.\n * Replaces ad-hoc `let _seq = 0` patterns with a node observable in\n * `describe()` and persistable via storage tiers.\n *\n * @category internal\n */\nexport function registerCursor(graph: Graph, name: string, initial = 0): Node<number> {\n\tconst cursor = node<number>([], { initial, name, describeKind: \"state\" });\n\tgraph.add(cursor, { name });\n\treturn cursor;\n}\n\n/**\n * Promote a closure `Map<K, number>` to N state nodes (one per key) mounted\n * under `<graph>::<name>::<key>`. Used by saga (per-event-type cursor).\n *\n * @category internal\n */\nexport function registerCursorMap<K extends string>(\n\tgraph: Graph,\n\tname: string,\n\tkeys: readonly K[],\n\tinitial = 0,\n): { readonly [P in K]: Node<number> } {\n\tconst out = {} as { [P in K]: Node<number> };\n\t// Mount cursors under a child plain-Graph so per-key node names stay flat\n\t// (path-separator `::` is reserved by Graph.add). Using `Graph` directly\n\t// rather than `graph.constructor` avoids spawning a typed subclass with\n\t// an incompatible constructor signature (e.g., CqrsGraph(name, opts)).\n\tconst sub = new Graph(name);\n\tfor (const k of keys) {\n\t\tconst cursor = node<number>([], {\n\t\t\tinitial,\n\t\t\tname: k,\n\t\t\tdescribeKind: \"state\",\n\t\t});\n\t\tsub.add(cursor, { name: k });\n\t\tout[k] = cursor;\n\t}\n\tgraph.mount(name, sub);\n\treturn out;\n}\n","/**\n * Phase 13.F — `humanInput<T>` sibling preset.\n *\n * Source: `archive/docs/SESSION-human-llm-intervention-primitives.md` §5\n * \"Sibling presets on the substrate\" + §9 Phase 2.\n *\n * **Role.** LLM↔human runtime Q&A channel. The agent (or any consumer)\n * reactively asks for human input by emitting a prompt; humanInput\n * publishes a {@link Message} envelope to the well-known\n * {@link PROMPTS_TOPIC} on the hub and watches {@link RESPONSES_TOPIC} for\n * the matching `correlationId`. When the response arrives, humanInput's\n * output Node emits the typed payload `T`.\n *\n * **Sibling to `approvalGate`** ([pipeline-graph.ts](pipeline-graph.ts)):\n * approvalGate is design-time veto on a topology edge; humanInput is a\n * runtime Q&A channel. They share substrate (hub + envelope) but differ\n * in role and initiator.\n *\n * **No imperative `.run()` / `.ask()`** — caller writes to `prompt` (any\n * `NodeInput<string>`) and reads `humanInput()`'s output Node.\n *\n * **Multi-prompt.** Each new `prompt` DATA mints a fresh correlationId\n * and a new pending request. The output Node's emission tracks the latest\n * correlationId — earlier in-flight requests are abandoned (switchMap\n * semantics). To run parallel requests, instantiate two humanInput nodes.\n */\n\nimport { COMPLETE, DATA, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport {\n\ttype JsonSchema,\n\ttype MessagingHubGraph,\n\tPROMPTS_TOPIC,\n\tRESPONSES_TOPIC,\n\ttype TopicMessage,\n} from \"../messaging/index.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Outbound prompt envelope payload. */\nexport interface HumanPromptPayload {\n\treadonly prompt: string;\n\treadonly schema?: JsonSchema;\n}\n\n/**\n * Options for {@link humanInput}.\n */\nexport interface HumanInputOpts {\n\t/**\n\t * Messaging hub. {@link PROMPTS_TOPIC} is created lazily for outbound\n\t * prompts; {@link RESPONSES_TOPIC} is read for incoming responses.\n\t */\n\treadonly hub: MessagingHubGraph;\n\t/**\n\t * Reactive prompt source. Any `NodeInput<string>` is accepted (Node,\n\t * Promise, AsyncIterable, scalar) — coerced via `fromAny`. Each new\n\t * DATA on this input mints a fresh request.\n\t */\n\treadonly prompt: NodeInput<string>;\n\t/**\n\t * Optional response-shape schema. Carried in the prompt envelope for\n\t * UI / consumer-side validation. Caller-supplied validators (ajv,\n\t * zod, valibot) consume this field; the substrate doesn't validate.\n\t */\n\treadonly schema?: JsonSchema;\n\t/**\n\t * Optional ID generator for the per-prompt correlationId. Default is\n\t * a monotonic counter derived from a tight closure (sufficient for\n\t * in-process correlation; cross-process consumers should supply UUID\n\t * / ULID generation).\n\t */\n\treadonly idGenerator?: () => string;\n}\n\n// ---------------------------------------------------------------------------\n// humanInput\n// ---------------------------------------------------------------------------\n\n/**\n * Constructs a reactive human-input request channel. Each DATA on\n * `prompt` mints a fresh request:\n *\n * 1. Mints a fresh `correlationId` (via `opts.idGenerator` if provided).\n * 2. Publishes `TopicMessage<HumanPromptPayload>` to {@link PROMPTS_TOPIC}\n * (`{ id, schema?, correlationId, payload: { prompt, schema? } }`).\n * 3. Watches {@link RESPONSES_TOPIC} for an envelope whose\n * `correlationId` matches.\n * 4. When matched, emits the response payload as the output Node's DATA.\n *\n * **Switchmap semantics.** A new prompt arriving before the prior\n * response abandons the prior wait. Output Node emits the response for\n * the latest in-flight request only.\n *\n * **Output type `T`** is the response payload type. Caller is responsible\n * for ensuring the response producer (UI / human-side) sends the right\n * shape — `schema` is the wire-level convention for validation.\n *\n * @example\n * ```ts\n * import {\n * humanInput,\n * messagingHub,\n * PROMPTS_TOPIC,\n * RESPONSES_TOPIC,\n * } from \"@graphrefly/graphrefly-ts\";\n *\n * const hub = messagingHub(\"hub\");\n * const promptN = state<string>(\"prompt\");\n * const reply = humanInput<{ ok: boolean; reason: string }>({\n * hub,\n * prompt: promptN,\n * schema: { type: \"object\", required: [\"ok\", \"reason\"] },\n * });\n *\n * // UI / human side: subscribe to PROMPTS_TOPIC, present, then publish to\n * // RESPONSES_TOPIC with the matching correlationId.\n * promptN.emit(\"Approve change?\");\n * const decision = await awaitSettled(reply); // resolves when human responds\n * ```\n *\n * @category patterns\n */\nexport function humanInput<T>(opts: HumanInputOpts): Node<T> {\n\tconst { hub, prompt, schema, idGenerator } = opts;\n\tconst promptNode = fromAny<string>(prompt);\n\tconst promptsTopic = hub.topic<TopicMessage<HumanPromptPayload>>(PROMPTS_TOPIC);\n\tconst responsesTopic = hub.topic<TopicMessage<T>>(RESPONSES_TOPIC);\n\n\tconst nextId = idGenerator ?? defaultIdGenerator();\n\n\treturn node<T>(\n\t\t(_data, a) => {\n\t\t\tlet activeCorrelationId: string | undefined;\n\t\t\tlet respUnsub: (() => void) | undefined;\n\n\t\t\tconst promptUnsub = promptNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\t\trespUnsub?.();\n\t\t\t\t\t\trespUnsub = undefined;\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\tif (m[0] !== DATA) continue;\n\t\t\t\t\tconst promptStr = m[1] as string;\n\t\t\t\t\t// Switch-map semantics: drop the prior in-flight watcher.\n\t\t\t\t\trespUnsub?.();\n\t\t\t\t\trespUnsub = undefined;\n\t\t\t\t\t// Mint new correlationId.\n\t\t\t\t\tconst correlationId = nextId();\n\t\t\t\t\tactiveCorrelationId = correlationId;\n\n\t\t\t\t\t// Snapshot the responses topic length BEFORE publishing so\n\t\t\t\t\t// we only consider envelopes that arrive AFTER this\n\t\t\t\t\t// subscription. Eliminates the stale-replay-on-subscribe\n\t\t\t\t\t// hazard (push-on-subscribe of `events` delivers the full\n\t\t\t\t\t// retained log, which could include an unrelated old\n\t\t\t\t\t// envelope whose `correlationId` happens to match if the\n\t\t\t\t\t// caller's id-generator is non-unique).\n\t\t\t\t\tconst responseCursorAtSubscribe =\n\t\t\t\t\t\t(responsesTopic.events.cache as readonly TopicMessage<T>[] | undefined)?.length ?? 0;\n\n\t\t\t\t\t// Publish the prompt envelope. Schema is carried at\n\t\t\t\t\t// envelope-level only (Phase 13.B TopicMessage<T> contract);\n\t\t\t\t\t// the payload itself is `HumanPromptPayload` and stays\n\t\t\t\t\t// schema-free.\n\t\t\t\t\tconst envelope: TopicMessage<HumanPromptPayload> = {\n\t\t\t\t\t\tid: correlationId,\n\t\t\t\t\t\tcorrelationId,\n\t\t\t\t\t\tpayload: { prompt: promptStr },\n\t\t\t\t\t\t...(schema != null && { schema }),\n\t\t\t\t\t};\n\t\t\t\t\tpromptsTopic.publish(envelope);\n\n\t\t\t\t\t// Watch responses topic for matching correlationId, but\n\t\t\t\t\t// skip the retained log (only consider envelopes at index\n\t\t\t\t\t// >= responseCursorAtSubscribe).\n\t\t\t\t\trespUnsub = responsesTopic.events.subscribe((rspMsgs) => {\n\t\t\t\t\t\tfor (const rm of rspMsgs) {\n\t\t\t\t\t\t\tif (rm[0] !== DATA) continue;\n\t\t\t\t\t\t\tconst arr = rm[1] as readonly TopicMessage<T>[];\n\t\t\t\t\t\t\tfor (let i = responseCursorAtSubscribe; i < arr.length; i++) {\n\t\t\t\t\t\t\t\tconst env = arr[i] as TopicMessage<T>;\n\t\t\t\t\t\t\t\tif (env.correlationId === activeCorrelationId) {\n\t\t\t\t\t\t\t\t\ta.emit(env.payload);\n\t\t\t\t\t\t\t\t\t// One-shot per prompt — next prompt re-arms the watcher.\n\t\t\t\t\t\t\t\t\trespUnsub?.();\n\t\t\t\t\t\t\t\t\trespUnsub = undefined;\n\t\t\t\t\t\t\t\t\treturn;\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}\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tpromptUnsub();\n\t\t\t\trespUnsub?.();\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tname: \"humanInput\",\n\t\t\t// Each new prompt may produce a structurally-equal response (e.g.\n\t\t\t// from a deterministic UI mock) — disable framework dedup so\n\t\t\t// repeat emissions propagate. Same precedent as `agent.out`.\n\t\t\tequals: () => false,\n\t\t},\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Default ID generator\n// ---------------------------------------------------------------------------\n\nfunction defaultIdGenerator(): () => string {\n\tlet n = 0;\n\t// `wallClockNs()` routes through the central clock per CLAUDE.md \"Time\n\t// utility rule\" — testing harnesses that monkey-patch the clock can pin\n\t// id generation deterministically.\n\tconst base = wallClockNs().toString(36);\n\treturn () => {\n\t\tn += 1;\n\t\treturn `humanInput-${base}-${n.toString(36)}`;\n\t};\n}\n","/**\n * PipelineGraph subclass (Wave A.1 Unit 1 — locked 2026-04-24).\n *\n * Specialized {@link Graph} that hosts workflow-DAG sugar methods:\n * `task` / `classify` / `combine` / `approval` / `approvalGate` / `catch`.\n * The legacy `pipeline` / `task` / `branch` / `join` / `subPipeline` /\n * `approval` / `loop` / `onFailure` factories from {@link ./index} continue\n * to work for migration ease; new code should prefer methods on this class.\n *\n * **Tier 2.3 rename:** the prior `gate(...)` method is now `approvalGate(...)`,\n * disambiguating it from the other gate-family primitives (`budgetGate` for\n * numeric constraints, `valve` for boolean switching, `policyGate` for ABAC\n * rules). The \"gating dimension\" here is **human judgment**.\n *\n * Construction: `pipelineGraph(name, opts?)` or `new PipelineGraph(name, opts)`.\n */\n\nimport type { NodeActions } from \"@graphrefly/pure-ts/core\";\nimport {\n\tbatch,\n\tCOMPLETE,\n\tDATA,\n\tERROR,\n\tfactoryTag,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n\tplaceholderArgs,\n\tRESOLVED,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport type { ReactiveLogBundle } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport { type BaseAuditRecord, createAuditLog, mutate } from \"../../base/mutation/index.js\";\n\nexport type StepRef = string | Node<unknown>;\n\nfunction meta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"orchestration\", kind, extra);\n}\n\n// ── Decision audit record (Audit 2 + Wave A.2 Unit 8) ─────────────────────\n\nexport type DecisionAction =\n\t| \"approve\"\n\t| \"reject\"\n\t| \"modify\"\n\t| \"drop\"\n\t| \"open\"\n\t| \"close\"\n\t| \"teardown\";\n\nexport interface Decision<T = unknown> extends BaseAuditRecord {\n\treadonly action: DecisionAction;\n\treadonly count?: number;\n\treadonly items?: readonly T[];\n\treadonly unflushed?: number;\n}\n\n/** Recommended `keyOf` for keyed-storage adapters (Audit 2 #7). */\nexport const decisionKeyOf = <T>(d: Decision<T>): string => d.action;\n\n// ── Gate ─────────────────────────────────────────────────────────────────\n\nexport interface GateOptions<_T = unknown> {\n\t/** Bounded default 1000 (Audit 2 cross-cutting). `Infinity` is opt-in. */\n\tmaxPending?: number;\n\tstartOpen?: boolean;\n\t/**\n\t * Reactive auto-approve: gate's `latestIsOpen` mirrors this node's truthy\n\t * value. False→true transition drains the pending queue.\n\t *\n\t * **`COMPLETE` / `ERROR` on the approver are silently ignored** — the gate\n\t * stays in its current state. For permanent-open latching, use\n\t * `onceOnly: true` (the first truthy approval latches; subsequent falsy\n\t * values are ignored). The gate has no graceful terminal-state behavior\n\t * for the approver itself.\n\t */\n\tapprover?: Node<unknown>;\n\t/** Latch — first truthy approval opens permanently; `close()` becomes no-op. */\n\tonceOnly?: boolean;\n\tmeta?: Record<string, unknown>;\n\thandlerVersion?: { id: string; version: string | number };\n}\n\nexport interface GateController<T> {\n\t/**\n\t * The post-gate output node. Renamed from `node` (Tier 5.2 / EC6,\n\t * 2026-04-29) to avoid shadowing `Graph.node(name)` when a gate is\n\t * accessed off a `PipelineGraph` instance.\n\t */\n\treadonly output: Node<T>;\n\treadonly pending: Node<readonly T[]>;\n\treadonly count: Node<number>;\n\treadonly isOpen: Node<boolean>;\n\treadonly droppedCount: Node<number>;\n\treadonly decisions: ReactiveLogBundle<Decision<T>>;\n\treadonly audit: ReactiveLogBundle<Decision<T>>;\n\tapprove(count?: number): void;\n\treject(count?: number): void;\n\tmodify(fn: (value: T, index: number, pending: readonly T[]) => T, count?: number): void;\n\topen(): void;\n\tclose(): void;\n}\n\n// ── catch (rename of onFailure; Wave A.2 Unit 10) ─────────────────────────\n\n/**\n * Terminal-cause discriminator for the {@link PipelineGraph.catch} recovery\n * handler. Tier 1.6.3 status-enum migration: was `{ kind: \"complete\" | \"error\" }`\n * pre-1.0; aligned with the canonical lifecycle enum\n * (`status: \"running\" | \"completed\" | \"errored\" | \"cancelled\"`). The variant\n * structure is preserved — `errored` still carries `error: unknown` and\n * `completed` carries no payload.\n */\nexport type TerminalCause = { kind: \"errored\"; error: unknown } | { kind: \"completed\" };\n\nexport interface CatchOptions<_T> {\n\t/**\n\t * Which terminal cause to recover. Default `\"errored\"` (Tier 1.6.3 rename\n\t * of `\"error\"`). `\"completed\"` recovers COMPLETE; `\"terminal\"` recovers\n\t * either. Aligns with the canonical lifecycle enum that\n\t * {@link TerminalCause.kind} now uses.\n\t */\n\ton?: \"errored\" | \"completed\" | \"terminal\";\n\tcompleteWhenDepsComplete?: boolean;\n\tmeta?: Record<string, unknown>;\n\thandlerVersion?: { id: string; version: string | number };\n}\n\n// ── classify result envelope (Wave A.1 Unit 3) ───────────────────────────\n\nexport interface ClassifyResult<TTag extends string, T> {\n\treadonly tag: TTag | \"error\";\n\treadonly value: T;\n\treadonly error?: unknown;\n}\n\n// ── PipelineGraph ────────────────────────────────────────────────────────\n\nexport class PipelineGraph extends Graph {\n\t// -- task -----------------------------------------------------------------\n\n\t/**\n\t * Register a workflow task (`node` + auto-add). String deps resolve via\n\t * `this.resolve(path)`; Node deps via {@link Graph.nameOf} O(1) lookup.\n\t *\n\t * `run` receives `(data: readonly unknown[], ctx)` — the snapshot of latest\n\t * values per dep (same shape as the old `DerivedFn` sugar).\n\t */\n\ttask<T>(\n\t\tname: string,\n\t\trun: (data: readonly unknown[], ctx: { prevData: readonly unknown[] }) => T | undefined | null,\n\t\topts: { deps?: ReadonlyArray<StepRef>; meta?: Record<string, unknown> } = {},\n\t): Node<T> {\n\t\tconst deps = (opts.deps ?? []).map((d) => this._resolveStep(d));\n\t\tconst step = node<T>(\n\t\t\tdeps,\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst result = run(data, ctx);\n\t\t\t\tif (result !== undefined && result !== null) actions.emit(result);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: meta(\"task\", opts.meta),\n\t\t\t} as NodeOptions<T>,\n\t\t);\n\t\tthis.add(step, { name });\n\t\treturn step;\n\t}\n\n\t// -- classify (n-way; replaces binary `branch`) --------------------------\n\n\tclassify<TTag extends string, T>(\n\t\tname: string,\n\t\tsource: StepRef,\n\t\ttagger: (value: T) => TTag,\n\t\topts: { meta?: Record<string, unknown> } = {},\n\t): Node<ClassifyResult<TTag, T>> {\n\t\tconst src = this._resolveStep(source);\n\t\tconst step = node<ClassifyResult<TTag, T>>(\n\t\t\t[src],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst value = data[0];\n\t\t\t\ttry {\n\t\t\t\t\tactions.emit({ tag: tagger(value as T), value: value as T });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tactions.emit({ tag: \"error\" as const, value: value as T, error });\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: meta(\"classify\", opts.meta),\n\t\t\t} as NodeOptions<ClassifyResult<TTag, T>>,\n\t\t);\n\t\tthis.add(step, { name });\n\t\treturn step;\n\t}\n\n\t// -- combine (keyed-record fan-in; replaces positional `join`) -----------\n\n\tcombine<R extends Record<string, StepRef>>(\n\t\tname: string,\n\t\tdeps: R,\n\t\topts: { meta?: Record<string, unknown> } = {},\n\t): Node<{ [K in keyof R]: unknown }> {\n\t\tconst keys = Object.keys(deps) as Array<keyof R & string>;\n\t\tconst nodes = keys.map((k) => this._resolveStep(deps[k] as StepRef));\n\t\tconst step = node<{ [K in keyof R]: unknown }>(\n\t\t\tnodes,\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst values = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst out = {} as { [K in keyof R]: unknown };\n\t\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\t\t(out as Record<string, unknown>)[keys[i] as string] = values[i];\n\t\t\t\t}\n\t\t\t\tactions.emit(out);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: meta(\"combine\", opts.meta),\n\t\t\t} as NodeOptions<{ [K in keyof R]: unknown }>,\n\t\t);\n\t\tthis.add(step, { name });\n\t\treturn step;\n\t}\n\n\t// -- approvalGate ---------------------------------------------------------\n\n\tapprovalGate<T>(name: string, source: StepRef, opts: GateOptions<T> = {}): GateController<T> {\n\t\tconst maxPending = opts.maxPending ?? 1000;\n\t\tif (maxPending < 1 && maxPending !== Number.POSITIVE_INFINITY) {\n\t\t\tthrow new RangeError(\"approvalGate: maxPending must be >= 1\");\n\t\t}\n\t\tconst startOpen = opts.startOpen ?? false;\n\n\t\t// C3 — wrap a foreign Node source in a local proxy derived. The proxy\n\t\t// is owned by THIS graph; downstream wiring uses the proxy (not the\n\t\t// foreign Node) so the cross-graph ownership invariant holds. Causal\n\t\t// chain is preserved via the dep edge — `describe()` still surfaces\n\t\t// the foreign Node's path through the proxy.\n\t\tlet src: Node<unknown>;\n\t\tif (typeof source === \"string\") {\n\t\t\tsrc = this._resolveStep(source);\n\t\t} else if (this.nameOf(source) !== undefined) {\n\t\t\tsrc = source;\n\t\t} else {\n\t\t\tconst proxy = node<unknown>(\n\t\t\t\t[source],\n\t\t\t\t(batchData, actions) => {\n\t\t\t\t\tconst batch0 = batchData[0];\n\t\t\t\t\tif (batch0 == null || batch0.length === 0) return;\n\t\t\t\t\tfor (const v of batch0) actions.emit(v);\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\tmeta: factoryTag(\"proxy\"),\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.add(proxy, { name: `${name}/source` });\n\t\t\tsrc = proxy;\n\t\t}\n\n\t\t// State subgraph\n\t\tconst internal = new Graph(`${name}-state`);\n\t\tconst pendingNode = internal.state<readonly T[]>(\"pending\", [], {\n\t\t\tequals: () => false,\n\t\t});\n\t\tconst isOpenNode = internal.state<boolean>(\"isOpen\", startOpen);\n\t\tconst countNode = internal.derived<number>(\"count\", [\"pending\"], (batchData, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\treturn [(data[0] as readonly T[]).length];\n\t\t});\n\t\tconst droppedCountNode = internal.state<number>(\"droppedCount\", 0);\n\t\tconst decisions = createAuditLog<Decision<T>>({\n\t\t\tname: \"decisions\",\n\t\t\tretainedLimit: 1024,\n\t\t\tgraph: internal,\n\t\t});\n\t\tthis.mount(`${name}-state`, internal);\n\n\t\tlet queue: T[] = [];\n\t\tlet torn = false;\n\t\tlet latched = false;\n\t\t// Closure-mirror per COMPOSITION-GUIDE §28 factory-time seed pattern.\n\t\t// `output` samples `latestIsOpen` inside its fn body when deciding\n\t\t// emit-vs-enqueue; reading a closure variable is NOT a P3 violation\n\t\t// (§28). An in-session Phase 9 plan would have relocated the value to\n\t\t// `internal.derived(\"latestIsOpen\", ...)` + `.cache` reads (which IS\n\t\t// a P3 violation); plan was reverted at the design level after\n\t\t// re-reading §28 — pattern preserved here. See `archive/docs/SESSION-\n\t\t// graph-narrow-waist.md` § \"Status of existing modifications\".\n\t\tlet latestIsOpen = startOpen;\n\t\tconst isOpenUnsub = isOpenNode.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) latestIsOpen = m[1] as boolean;\n\t\t\t}\n\t\t});\n\t\tthis.addDisposer(isOpenUnsub);\n\n\t\tfunction syncPending(): void {\n\t\t\tpendingNode.emit([...queue]);\n\t\t}\n\n\t\tfunction recordDecision(\n\t\t\taction: DecisionAction,\n\t\t\titems?: readonly T[],\n\t\t\tunflushed?: number,\n\t\t): void {\n\t\t\tdecisions.append({\n\t\t\t\taction,\n\t\t\t\tt_ns: wallClockNs(),\n\t\t\t\t...(items !== undefined ? { items, count: items.length } : {}),\n\t\t\t\t...(unflushed !== undefined ? { unflushed } : {}),\n\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t} as Decision<T>);\n\t\t}\n\n\t\tfunction enqueue(value: T): void {\n\t\t\tqueue.push(value);\n\t\t\tif (queue.length > maxPending) {\n\t\t\t\tconst dropped = queue.shift() as T;\n\t\t\t\tdroppedCountNode.emit((droppedCountNode.cache as number) + 1);\n\t\t\t\trecordDecision(\"drop\", [dropped]);\n\t\t\t}\n\t\t\tsyncPending();\n\t\t}\n\n\t\tfunction dequeue(n: number): T[] {\n\t\t\tconst items = queue.splice(0, n);\n\t\t\tsyncPending();\n\t\t\treturn items;\n\t\t}\n\n\t\tconst output = node<T>(\n\t\t\t[src],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst terminal = ctx.terminalDeps[0];\n\t\t\t\tif (terminal !== undefined) {\n\t\t\t\t\ttorn = true;\n\t\t\t\t\tconst unflushed = queue.length;\n\t\t\t\t\tqueue = [];\n\t\t\t\t\tsyncPending();\n\t\t\t\t\trecordDecision(\"teardown\", undefined, unflushed);\n\t\t\t\t\tactions.down(terminal === true ? [[COMPLETE]] : [[ERROR, terminal]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst batch0 = batchData[0];\n\t\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const v of batch0 as T[]) {\n\t\t\t\t\tif (latestIsOpen) {\n\t\t\t\t\t\tactions.emit(v);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenqueue(v);\n\t\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: meta(\"approval_gate\", opts.meta),\n\t\t\t},\n\t\t);\n\t\tthis.add(output, { name });\n\n\t\t// Reactive approver mode: mirror latestIsOpen to the approver's value.\n\t\t// **m1:** approver `COMPLETE` / `ERROR` are silently ignored — gate stays\n\t\t// in current state. For latching behavior, use `onceOnly: true`.\n\t\tif (opts.approver != null) {\n\t\t\tconst initialApproved = Boolean(opts.approver.cache);\n\t\t\tif (initialApproved) {\n\t\t\t\tisOpenNode.emit(true);\n\t\t\t\tlatestIsOpen = true;\n\t\t\t\tif (opts.onceOnly) latched = true;\n\t\t\t}\n\t\t\tconst approverSub = opts.approver.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\t\tconst truthy = Boolean(m[1]);\n\t\t\t\t\tif (truthy && !latestIsOpen) {\n\t\t\t\t\t\t// false → true transition\n\t\t\t\t\t\tif (opts.onceOnly) {\n\t\t\t\t\t\t\tif (latched) continue;\n\t\t\t\t\t\t\tlatched = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\tisOpenNode.emit(true);\n\t\t\t\t\t\t\tconst items = dequeue(queue.length);\n\t\t\t\t\t\t\t// M11: include items count in approver-driven open decisions\n\t\t\t\t\t\t\t// so audit consumers see how many items were flushed.\n\t\t\t\t\t\t\trecordDecision(\"open\", items);\n\t\t\t\t\t\t\tfor (const item of items) {\n\t\t\t\t\t\t\t\tif (torn) break;\n\t\t\t\t\t\t\t\toutput.emit(item);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (!truthy && latestIsOpen) {\n\t\t\t\t\t\tif (opts.onceOnly && latched) continue;\n\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\tisOpenNode.emit(false);\n\t\t\t\t\t\t\trecordDecision(\"close\");\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\tthis.addDisposer(approverSub);\n\t\t}\n\n\t\tconst guardTorn = (method: string): void => {\n\t\t\tif (torn) throw new Error(`approvalGate: ${method}() called after the gate was torn down`);\n\t\t};\n\n\t\tconst approveImpl = (count = 1): void => {\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.emit(item);\n\t\t\t}\n\t\t};\n\t\tconst rejectImpl = (count = 1): void => {\n\t\t\tguardTorn(\"reject\");\n\t\t\tdequeue(count);\n\t\t};\n\t\tconst modifyImpl = (\n\t\t\tfn: (value: T, index: number, pending: readonly T[]) => T,\n\t\t\tcount = 1,\n\t\t): void => {\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.emit(fn(items[i], i, snapshot));\n\t\t\t}\n\t\t};\n\t\tconst openImpl = (): void => {\n\t\t\tguardTorn(\"open\");\n\t\t\tisOpenNode.emit(true);\n\t\t\tconst items = dequeue(queue.length);\n\t\t\tfor (const item of items) {\n\t\t\t\tif (torn) break;\n\t\t\t\toutput.emit(item);\n\t\t\t}\n\t\t};\n\t\tconst closeImpl = (): void => {\n\t\t\tguardTorn(\"close\");\n\t\t\tif (opts.onceOnly && latched) return;\n\t\t\tisOpenNode.emit(false);\n\t\t};\n\n\t\tconst approve = mutate(approveImpl, {\n\t\t\tframe: \"transactional\",\n\t\t\tlog: decisions,\n\t\t\tfreeze: false,\n\t\t\tonSuccessRecord: (args, _r, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"approve\",\n\t\t\t\t\tcount: (args[0] as number | undefined) ?? 1,\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t\tonFailureRecord: (_a, _e, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"drop\",\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\terrorType: m.errorType,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t});\n\t\tconst reject = mutate(rejectImpl, {\n\t\t\tframe: \"transactional\",\n\t\t\tlog: decisions,\n\t\t\tfreeze: false,\n\t\t\tonSuccessRecord: (args, _r, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"reject\",\n\t\t\t\t\tcount: (args[0] as number | undefined) ?? 1,\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t\tonFailureRecord: (_a, _e, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"drop\",\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\terrorType: m.errorType,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t});\n\t\tconst modify = mutate(modifyImpl, {\n\t\t\tframe: \"transactional\",\n\t\t\tlog: decisions,\n\t\t\tfreeze: false,\n\t\t\tonSuccessRecord: (args, _r, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"modify\",\n\t\t\t\t\tcount: (args[1] as number | undefined) ?? 1,\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t\tonFailureRecord: (_a, _e, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"drop\",\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\terrorType: m.errorType,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t});\n\t\tconst open = mutate(openImpl, {\n\t\t\tframe: \"transactional\",\n\t\t\tlog: decisions,\n\t\t\tfreeze: false,\n\t\t\tonSuccessRecord: (_a, _r, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"open\",\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t\tonFailureRecord: (_a, _e, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"drop\",\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\terrorType: m.errorType,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t});\n\t\tconst close = mutate(closeImpl, {\n\t\t\tframe: \"transactional\",\n\t\t\tlog: decisions,\n\t\t\tfreeze: false,\n\t\t\tonSuccessRecord: (_a, _r, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"close\",\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t\tonFailureRecord: (_a, _e, m) =>\n\t\t\t\t({\n\t\t\t\t\taction: \"drop\",\n\t\t\t\t\tt_ns: m.t_ns,\n\t\t\t\t\terrorType: m.errorType,\n\t\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t}) as Decision<T>,\n\t\t});\n\n\t\tthis.addDisposer(countNode.subscribe(() => undefined));\n\n\t\tconst controller: GateController<T> = {\n\t\t\toutput,\n\t\t\tpending: pendingNode,\n\t\t\tcount: countNode,\n\t\t\tisOpen: isOpenNode,\n\t\t\tdroppedCount: droppedCountNode,\n\t\t\tdecisions,\n\t\t\taudit: decisions,\n\t\t\tapprove,\n\t\t\treject,\n\t\t\tmodify,\n\t\t\topen,\n\t\t\tclose,\n\t\t};\n\t\treturn controller;\n\t}\n\n\t// -- approval (thin alias over approvalGate({ approver, maxPending: 1 })) -\n\n\t/**\n\t * Reactive approval step: passes items through when `approver` is truthy;\n\t * holds at most one pending item (maxPending: 1) when falsy. A thin alias\n\t * over `approvalGate({ approver, maxPending: 1 })` — use `approvalGate()`\n\t * directly for finer control (maxPending, onceOnly, manual approve/reject).\n\t */\n\tapproval<T>(\n\t\tname: string,\n\t\tsource: StepRef,\n\t\tapprover: Node<unknown>,\n\t\topts: Omit<GateOptions<T>, \"approver\" | \"maxPending\"> = {},\n\t): GateController<T> {\n\t\treturn this.approvalGate<T>(name, source, { ...opts, approver, maxPending: 1 });\n\t}\n\n\t// -- catch (renamed onFailure; dep-channel intercept) -------------------\n\n\tcatch<T>(\n\t\tname: string,\n\t\tsource: StepRef,\n\t\trecover: (cause: TerminalCause, actions: NodeActions) => T,\n\t\topts: CatchOptions<T> = {},\n\t): Node<T> {\n\t\tconst src = this._resolveStep(source);\n\t\tconst mode = opts.on ?? \"errored\";\n\t\tconst step = node<T>(\n\t\t\t[src],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst terminal = ctx.terminalDeps[0];\n\t\t\t\tif (terminal !== undefined) {\n\t\t\t\t\tconst cause: TerminalCause =\n\t\t\t\t\t\tterminal === true ? { kind: \"completed\" } : { kind: \"errored\", error: terminal };\n\t\t\t\t\tif (mode === \"terminal\" || mode === cause.kind) {\n\t\t\t\t\t\tactions.emit(recover(cause, actions));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tactions.down(cause.kind === \"completed\" ? [[COMPLETE]] : [[ERROR, cause.error]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst batch0 = batchData[0];\n\t\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const v of batch0 as T[]) actions.emit(v);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tcompleteWhenDepsComplete:\n\t\t\t\t\topts.completeWhenDepsComplete ?? !(mode === \"completed\" || mode === \"terminal\"),\n\t\t\t\terrorWhenDepsError: !(mode === \"errored\" || mode === \"terminal\"),\n\t\t\t\tmeta: meta(\"catch\", opts.meta),\n\t\t\t} as NodeOptions<T>,\n\t\t);\n\t\tthis.add(step, { name });\n\t\treturn step;\n\t}\n\n\t// -- internals ----------------------------------------------------------\n\n\tprivate _resolveStep(dep: StepRef): Node<unknown> {\n\t\tif (typeof dep === \"string\") return this.resolve(dep);\n\t\tconst existing = this.nameOf(dep);\n\t\tif (existing === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`PipelineGraph \"${this.name}\": Node dep is not registered. Pass a string path or call graph.add(node) first.`,\n\t\t\t);\n\t\t}\n\t\treturn dep;\n\t}\n}\n\n/** Factory wrapper — `pipelineGraph(name, opts?)`. Equivalent to `new PipelineGraph(name, opts)`. */\nexport function pipelineGraph(name: string, opts?: GraphOptions): PipelineGraph {\n\tconst g = new PipelineGraph(name, opts);\n\t// Tier 1.5.3 Phase 2.5 (DG1=B): tag the Graph with its constructing\n\t// factory so `describe()` exposes provenance. `factoryArgs` is the\n\t// constructor opts (sans the `factory`/`factoryArgs` keys themselves to\n\t// avoid recursive nesting). QA F13: route through `placeholderArgs` for\n\t// consistency with sibling factories — `GraphOptions[key: string]: unknown`\n\t// is open-ended, so user-extension keys may carry non-JSON content.\n\tconst { factory: _f, factoryArgs: _fa, ...tagArgs } = (opts ?? {}) as Record<string, unknown>;\n\tg.tagFactory(\"pipelineGraph\", placeholderArgs(tagArgs));\n\treturn g;\n}\n","/**\n * Phase 13.F — `tracker` sibling preset.\n *\n * Source: `archive/docs/SESSION-human-llm-intervention-primitives.md` §5\n * \"Sibling presets on the substrate\" + `archive/docs/SKETCH-reactive-tracker-factory.md`\n * + `project_reactive_tracker` memory.\n *\n * **Role.** Park-as-deferred queue consumer. The tracker is the\n * cursor-based read surface over the well-known {@link DEFERRED_TOPIC}\n * — items the harness (or any consumer) defers for later attention.\n * Sibling to `humanInput` and `approvalGate`; all three share substrate\n * (hub + envelope + reactive cursor) but differ in role.\n *\n * **Cursor handle.** Per the SESSION's \"Cursor handle\" return — tracker\n * exposes the cursor-based pull / ack surface so the consumer (a\n * dashboard, a post-run review, an LLM watcher) can iterate over\n * unconsumed items in order.\n *\n * **Naming locked (open question §11 #3 resolved):** `tracker`. The\n * SESSION mentioned `tracker` vs `parkedQueue` vs `deferredTracker`;\n * `tracker` is the simplest and most general — the deferred-queue\n * semantic is a recipe, not a name overload. Other use cases (issue\n * tracker, todo tracker, retrospective tracker per\n * `project_reactive_tracker`) reuse the same primitive.\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport {\n\tDEFERRED_TOPIC,\n\ttype MessagingHubGraph,\n\ttype SubscriptionGraph,\n\tsubscription,\n\ttype TopicGraph,\n} from \"../messaging/index.js\";\n\n// ---------------------------------------------------------------------------\n// Bundle\n// ---------------------------------------------------------------------------\n\n/**\n * Bundle returned by {@link tracker}. Wraps a topic + cursor-based\n * subscription with imperative `add` / `ack` helpers.\n */\nexport interface TrackerBundle<T> {\n\t/**\n\t * The underlying topic. Either freshly minted on the hub at\n\t * `topicName` (default {@link DEFERRED_TOPIC}) or reused if the topic\n\t * already exists.\n\t */\n\treadonly topic: TopicGraph<T>;\n\t/** Cursor-based subscription view over `topic.events`. */\n\treadonly subscription: SubscriptionGraph<T>;\n\t/**\n\t * Items beyond the current cursor — i.e. the deferred queue's\n\t * \"pending\" head. Reactive `Node<readonly T[]>`.\n\t */\n\treadonly pending: Node<readonly T[]>;\n\t/** Current cursor position (number of items already acked). */\n\treadonly cursor: Node<number>;\n\t/**\n\t * Reactive total count of items added since construction (matches the\n\t * topic's retained-events length until the topic's retention cap is\n\t * reached).\n\t */\n\treadonly total: Node<number>;\n\t/** Append an item to the deferred queue. */\n\tadd(item: T): void;\n\t/**\n\t * Advance the cursor past `n` items (default 1). Acks the next batch\n\t * of pending items; subsequent reads of `pending` exclude them.\n\t */\n\tack(n?: number): void;\n\t/**\n\t * Pull-and-ack at most `limit` items in one shot. Returns the items\n\t * + the new cursor position (matches `subscription.pullAndAck`).\n\t */\n\tpullAndAck(limit?: number): { items: readonly T[]; cursor: number };\n}\n\n// ---------------------------------------------------------------------------\n// tracker()\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link tracker}.\n */\nexport interface TrackerOpts {\n\t/**\n\t * Messaging hub. The tracker creates / reuses a topic on this hub\n\t * named `topicName` (default {@link DEFERRED_TOPIC}).\n\t */\n\treadonly hub: MessagingHubGraph;\n\t/**\n\t * Topic name on the hub. Default {@link DEFERRED_TOPIC}. Override to\n\t * use a non-deferred topic (e.g. a custom domain queue).\n\t */\n\treadonly topicName?: string;\n\t/**\n\t * Subscription graph name. Default `\"tracker\"`. Multiple trackers on\n\t * the same hub topic must use distinct names.\n\t */\n\treadonly name?: string;\n\t/**\n\t * Initial cursor. Forwarded to the underlying subscription. See\n\t * {@link SubscriptionOptions.from}.\n\t */\n\treadonly from?: \"now\" | \"retained\" | number;\n}\n\n/**\n * Mints a tracker bundle over a hub topic.\n *\n * @example\n * ```ts\n * import { messagingHub, tracker } from \"@graphrefly/graphrefly-ts\";\n *\n * const hub = messagingHub(\"hub\");\n * const issues = tracker<{ summary: string }>({ hub });\n *\n * issues.add({ summary: \"investigate flaky test\" });\n * issues.add({ summary: \"follow up on auth refactor\" });\n *\n * // Subscribe to the pending queue (for a dashboard, watcher, etc.)\n * issues.pending.subscribe((msgs) => { ... });\n *\n * // Imperative pull + ack\n * const next = issues.pullAndAck(1);\n * console.log(next.items[0]?.summary);\n * ```\n *\n * @category patterns\n */\nexport function tracker<T>(opts: TrackerOpts): TrackerBundle<T> {\n\tconst { hub, topicName, name, from } = opts;\n\tconst effectiveTopicName = topicName ?? DEFERRED_TOPIC;\n\tconst effectiveName = name ?? \"tracker\";\n\n\t// Reuse existing topic on the hub or lazy-create.\n\tconst topicGraph = hub.topic<T>(effectiveTopicName);\n\n\t// Cursor-based subscription. The subscription is owned by the tracker\n\t// (not mounted on the hub) — multiple trackers can share the topic with\n\t// independent cursors.\n\tconst sub: SubscriptionGraph<T> = subscription<T>(effectiveName, topicGraph, {\n\t\t...(from != null && { from }),\n\t});\n\n\t// `total` derives from topic.events.length. Use a derived node owned by\n\t// the subscription for a self-contained surface. `keepAlive: true` so\n\t// `total.cache` stays current even without external subscribers.\n\tconst total = sub.derived<number>(\n\t\t\"tracker-total\",\n\t\t[topicGraph.events],\n\t\t(data, ctx) => {\n\t\t\tconst b0 = data[0];\n\t\t\tconst arr =\n\t\t\t\tb0 != null && b0.length > 0\n\t\t\t\t\t? (b0.at(-1) as readonly T[])\n\t\t\t\t\t: ((ctx.prevData[0] as readonly T[] | undefined) ?? []);\n\t\t\treturn [arr.length];\n\t\t},\n\t\t{ keepAlive: true },\n\t);\n\n\treturn {\n\t\ttopic: topicGraph,\n\t\tsubscription: sub,\n\t\tpending: sub.available,\n\t\tcursor: sub.cursor,\n\t\ttotal,\n\t\tadd: (item) => topicGraph.publish(item),\n\t\tack: (n) => sub.ack(n ?? 1),\n\t\tpullAndAck: (limit) => sub.pullAndAck(limit),\n\t};\n}\n","/**\n * `systemPromptBuilder` — assembles a reactive system prompt from sections.\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\n\nimport { fromAny, keepalive, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { aiMeta } from \"../_internal.js\";\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) =>\n\t\ttypeof s === \"string\" ? node([], { initial: s }) : fromAny(s),\n\t);\n\tconst prompt = node(\n\t\tsectionNodes,\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit((data as string[]).filter((v) => v != null && v !== \"\").join(separator));\n\t\t},\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 * Cost meter extractor — derives live cost readings from the delta topic.\n *\n * **Wave A Unit 3 rewrite:** signature takes `deltaTopic: TopicGraph<StampedDelta>`\n * instead of the old `TopicGraph<StreamChunk>`. The meter prefers real\n * `usage` deltas from the adapter; when no `usage` has been seen yet it\n * falls back to a char-based estimate over token deltas and stamps\n * `estimated: true` on the reading. Chunk count is the count of\n * token-type deltas seen (was `chunk.index + 1`).\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport type { TopicGraph } from \"../../messaging/index.js\";\nimport { aiMeta } from \"../_internal.js\";\nimport { sumInputTokens, sumOutputTokens } from \"../adapters/core/types.js\";\nimport type { StampedDelta } from \"../prompts/streaming.js\";\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\t/**\n\t * `true` when no adapter `usage` delta has been observed yet —\n\t * `estimatedTokens` is a char-based heuristic and should be treated as an\n\t * approximation. Flips to `false` once a real `usage` delta arrives.\n\t */\n\treadonly estimated: boolean;\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\ta.estimated === b.estimated\n\t);\n};\n\n/**\n * Mounts a cost meter on the delta topic. Prefers real `usage` deltas from\n * the provider; falls back to char-based estimation on token deltas alone\n * (with `meta.estimated: true` on the reading).\n *\n * Default structural equals suppresses DATA emission when two consecutive\n * readings are identical.\n */\nexport function costMeterExtractor(\n\tdeltaTopic: TopicGraph<StampedDelta>,\n\topts?: CostMeterOptions,\n): Node<CostMeterReading> {\n\tconst charsPerToken = opts?.charsPerToken ?? 4;\n\tconst ZERO: CostMeterReading = {\n\t\tchunkCount: 0,\n\t\tcharCount: 0,\n\t\testimatedTokens: 0,\n\t\testimated: true,\n\t};\n\t// Lock 6.D (Phase 13.6.B): clear per-stream counters on deactivation\n\t// so a resubscribed cost meter starts at zero on the next cycle.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<CostMeterReading>(\n\t\t[deltaTopic.latest],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.chunkCount;\n\t\t\t\t\t\tdelete store.charCount;\n\t\t\t\t\t\tdelete store.usageTokens;\n\t\t\t\t\t\tdelete store.sawUsage;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst d = data[0];\n\t\t\tif (d === undefined) {\n\t\t\t\tactions.emit(ZERO);\n\t\t\t\treturn cleanup;\n\t\t\t}\n\t\t\tconst delta = d as StampedDelta;\n\n\t\t\tif (!(\"chunkCount\" in ctx.store)) {\n\t\t\t\tctx.store.chunkCount = 0;\n\t\t\t\tctx.store.charCount = 0;\n\t\t\t\tctx.store.usageTokens = 0;\n\t\t\t\tctx.store.sawUsage = false;\n\t\t\t}\n\t\t\tconst store = ctx.store as {\n\t\t\t\tchunkCount: number;\n\t\t\t\tcharCount: number;\n\t\t\t\tusageTokens: number;\n\t\t\t\tsawUsage: boolean;\n\t\t\t};\n\n\t\t\tif (delta.type === \"token\") {\n\t\t\t\tstore.chunkCount += 1;\n\t\t\t\tstore.charCount += delta.delta.length;\n\t\t\t} else if (delta.type === \"usage\") {\n\t\t\t\tstore.sawUsage = true;\n\t\t\t\tstore.usageTokens = sumInputTokens(delta.usage) + sumOutputTokens(delta.usage);\n\t\t\t}\n\n\t\t\tconst estimatedTokens = store.sawUsage\n\t\t\t\t? store.usageTokens\n\t\t\t\t: Math.ceil(store.charCount / charsPerToken);\n\t\t\tactions.emit({\n\t\t\t\tchunkCount: store.chunkCount,\n\t\t\t\tcharCount: store.charCount,\n\t\t\t\testimatedTokens,\n\t\t\t\testimated: !store.sawUsage,\n\t\t\t});\n\t\t\treturn cleanup;\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"cost-meter\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: ZERO,\n\t\t\tmeta: aiMeta(\"cost_meter_extractor\"),\n\t\t\tequals: costMeterEqual,\n\t\t},\n\t);\n}\n","/**\n * Keyword-flag extractor — scans accumulated stream text for configured patterns.\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { aiMeta } from \"../_internal.js\";\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 accumulated text. Scans for all\n * configured patterns and emits an array of matches.\n *\n * **Wave A Unit 3 rewrite:** signature takes `accumulatedText: Node<string>`\n * instead of the old `TopicGraph<StreamChunk>`. Patterns are compiled once\n * at factory time (was per-chunk). `maxPatternLength` is validated at\n * factory time — any pattern whose source exceeds the window throws\n * immediately.\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 waves in `ctx.store`\n * so each emission scans only the delta region `accumulated.slice(scannedTo -\n * maxPatternLength)` — not the full string. Reactivation clears `ctx.store`\n * and resumes from offset 0 (COMPOSITION-GUIDE §20 RAM semantics).\n *\n * Default structural equals suppresses DATA emission when no new flags were\n * found this wave.\n */\nexport function keywordFlagExtractor(\n\taccumulatedText: Node<string>,\n\topts: KeywordFlagExtractorOptions,\n): Node<readonly KeywordFlag[]> {\n\tconst maxPatternLength = opts.maxPatternLength ?? 128;\n\t// Factory-time: validate pattern literal lengths + compile once.\n\tfor (const p of opts.patterns) {\n\t\tif (p.pattern.source.length > maxPatternLength) {\n\t\t\tthrow new Error(\n\t\t\t\t`keywordFlagExtractor: pattern \"${p.label}\" literal exceeds maxPatternLength (${p.pattern.source.length} > ${maxPatternLength}); raise the option or shorten the pattern.`,\n\t\t\t);\n\t\t}\n\t}\n\tconst compiled = opts.patterns.map((p) => ({\n\t\tlabel: p.label,\n\t\tpattern: p.pattern,\n\t\tcompiled: new RegExp(p.pattern.source, `${p.pattern.flags.replace(\"g\", \"\")}g`),\n\t}));\n\t// Lock 6.D (Phase 13.6.B): clear scan state on deactivation so a\n\t// resubscribed extractor doesn't carry over per-stream cursors.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<readonly KeywordFlag[]>(\n\t\t[accumulatedText],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.flags;\n\t\t\t\t\t\tdelete store.scannedTo;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst text = data[0];\n\t\t\tif (text == null) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn cleanup;\n\t\t\t}\n\t\t\tconst accumulated = text as string;\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, compiled: re } of compiled) {\n\t\t\t\tre.lastIndex = 0;\n\t\t\t\tfor (const m of region.matchAll(re)) {\n\t\t\t\t\tconst pos = startOffset + (m.index ?? 0);\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\t\t\tactions.emit(added ? [...flags] : flags.slice());\n\t\t\treturn cleanup;\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 * Generic stream extractor — mounts an extract function on accumulated text.\n *\n * **Wave A Unit 3 rewrite:** signature changed from\n * `streamExtractor(topic: TopicGraph<StreamChunk>, fn)` to\n * `streamExtractor(accumulatedText: Node<string>, fn)`. The Unit 2 delta-\n * topic redesign removed the per-chunk `accumulated` field; callers pass\n * `streamingPromptNode(...).accumulatedText` (or any other `Node<string>`\n * source of accumulated text). Source-agnostic — the extractor doesn't care\n * whether the text came from an LLM, WebSocket, SSE tail, or file reader.\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { aiMeta } from \"../_internal.js\";\n\n/**\n * Mounts an extractor function on a reactive accumulated-text source. Returns\n * a derived node that emits extracted values as the text grows.\n *\n * @param accumulatedText - Reactive `Node<string>` of accumulated text.\n * @param extractFn - `(accumulated: string) => T | null`.\n * @param opts - Optional name + structural equals.\n * @returns Derived node emitting extracted values.\n */\nexport function streamExtractor<T>(\n\taccumulatedText: Node<string>,\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 node<T | null>(\n\t\t[accumulatedText],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst text = data[0];\n\t\t\tactions.emit(text == null ? null : extractFn(text as string));\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 * Tool-call extractor — scans accumulated stream text for complete JSON tool call objects.\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { aiMeta } from \"../_internal.js\";\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\taccumulatedText: Node<string>,\n\topts?: { name?: string },\n): Node<readonly ExtractedToolCall[]> {\n\t// Lock 6.D (Phase 13.6.B): clear scan state on deactivation so a\n\t// resubscribed extractor doesn't ship stale per-stream cursors.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<readonly ExtractedToolCall[]>(\n\t\t[accumulatedText],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.calls;\n\t\t\t\t\t\tdelete store.scanFrom;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst text = data[0];\n\t\t\tif (text == null) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn cleanup;\n\t\t\t}\n\t\t\tconst accumulated = text as string;\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\tactions.emit(added ? [...calls] : calls.slice());\n\t\t\treturn cleanup;\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 * Content gate — classifies accumulated stream text as allow / review / block.\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\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 * **Wave A Unit 3 rewrite:** signature now takes `accumulatedText: Node<string>`\n * instead of a `TopicGraph<StreamChunk>` (the `StreamChunk` shape was retired\n * when the delta topic replaced the per-chunk accumulated-text shape).\n *\n * Emits a three-way decision on every text change:\n * - `\"allow\"` — score below `threshold`\n * - `\"review\"` — score in `[threshold, threshold × hardMultiplier)`\n * - `\"block\"` — score at or above `threshold × hardMultiplier`\n *\n * @param accumulatedText - Reactive accumulated-text source\n * (`streamingPromptNode(...).accumulatedText`).\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\taccumulatedText: Node<string>,\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>[] = [accumulatedText];\n\tif (isNodeClassifier) deps.push(classifier as Node<unknown>);\n\n\treturn node<ContentDecision>(\n\t\tdeps,\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst text = (data[0] as string | undefined) ?? \"\";\n\t\t\tif (text.length === 0) {\n\t\t\t\tactions.emit(\"allow\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst score = isNodeClassifier\n\t\t\t\t? ((data[1] as number | undefined) ?? 0)\n\t\t\t\t: (classifier as (t: string) => number)(text);\n\n\t\t\tif (score >= hardThreshold) {\n\t\t\t\tactions.emit(\"block\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (score >= threshold) {\n\t\t\t\tactions.emit(\"review\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit(\"allow\");\n\t\t},\n\t\t{ describeKind: \"derived\", name: opts?.name ?? \"content-gate\", initial: \"allow\" },\n\t);\n}\n","/**\n * Redactor — stream extractor that replaces matched patterns in accumulated text.\n *\n * **Wave A Unit 3 rewrite:** signature now takes `accumulatedText: Node<string>`\n * instead of the retired `TopicGraph<StreamChunk>`. The output is a\n * `Node<string>` carrying the sanitized accumulated text — compose with\n * `contentGate` or downstream UI directly.\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\n\n/** Options for {@link redactor}. */\nexport type RedactorOptions = {\n\tname?: string;\n};\n\n/**\n * Derived node that replaces matched patterns in accumulated text.\n *\n * @param accumulatedText - Reactive accumulated-text source.\n * @param patterns - Array of RegExps to match against the text.\n * @param replaceFn - Replacement producer (default: always `\"[REDACTED]\"`).\n * @returns `Node<string>` emitting the sanitized accumulated text.\n */\nexport function redactor(\n\taccumulatedText: Node<string>,\n\tpatterns: RegExp[],\n\treplaceFn?: (match: string, pattern: RegExp) => string,\n\topts?: RedactorOptions,\n): Node<string> {\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 node<string>(\n\t\t[accumulatedText],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(sanitize((data[0] as string | undefined) ?? \"\"));\n\t\t},\n\t\t{ describeKind: \"derived\", name: opts?.name ?? \"redactor\", initial: \"\" },\n\t);\n}\n","import { type Node, node, RESOLVED } from \"@graphrefly/pure-ts/core\";\nimport { keepalive, type ReactiveLogBundle, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { aiMeta } from \"../_internal.js\";\nimport type { ChatMessage } from \"../adapters/core/types.js\";\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\t/**\n\t * Most recently appended message. Stays in the protocol SENTINEL state\n\t * (`cache === undefined`, no DATA emitted) until the first append, then\n\t * tracks the latest entry. Per COMPOSITION-GUIDE §1a, the SENTINEL is\n\t * the canonical \"no value yet\" signal — consumers detect empty via\n\t * `data[i] === undefined` inside reactive fns or `latest.cache === undefined`\n\t * outside. No `T | null` placeholder, no `hasLatest` companion.\n\t */\n\treadonly latest: Node<ChatMessage>;\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(this.messages, { name: \"messages\" });\n\n\t\t// SENTINEL on empty (COMPOSITION-GUIDE §1a): return `[]` for\n\t\t// RESOLVED-only on empty stream, `[T]` to emit DATA. `latest.cache`\n\t\t// stays `undefined` until the first append.\n\t\tthis.latest = node<ChatMessage>(\n\t\t\t[this.messages],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst entries = data[0] as readonly ChatMessage[];\n\t\t\t\tif (entries.length === 0) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tactions.emit(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(this.latest, { name: \"latest\" });\n\t\tthis.addDisposer(keepalive(this.latest));\n\n\t\tthis.messageCount = node<number>(\n\t\t\t[this.messages],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tactions.emit((data[0] as readonly ChatMessage[]).length);\n\t\t\t},\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(this.messageCount, { name: \"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","import { factoryTag, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput, switchMap } from \"@graphrefly/pure-ts/extra\";\n\n// ---------------------------------------------------------------------------\n// handoff — multi-agent routing sugar (B10)\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link handoff}.\n */\nexport type HandoffOptions = {\n\t/**\n\t * Reactive gate: when this node's value is `true`, output flows from\n\t * `from` to the `to` specialist; when `false`, `from`'s output flows\n\t * through unchanged and `to` stays dormant. Omit to always hand off —\n\t * useful when `from` is itself a router whose output shape already\n\t * encodes routing intent.\n\t */\n\tcondition?: NodeInput<boolean>;\n\tname?: string;\n};\n\n/**\n * Multi-agent handoff recipe — route `from`'s output into a specialist\n * agent `toFactory` when `condition` is open. Thin composition over\n * `switchMap` + gate; not a new primitive, just a named shape.\n *\n * The \"handoff\" pattern (popularized by the OpenAI Agents SDK) covers two\n * idioms:\n *\n * 1. **Full handoff** — a triage agent routes the conversation to a\n * specialist, and the specialist becomes the active agent for the rest\n * of the turn. Accumulated context (memory, tool definitions) can travel\n * along by threading the same `agentMemory` bundle into both.\n * 2. **Agents-as-tools** — the manager keeps control and calls the\n * specialist like a tool for a bounded subtask. Build this by registering\n * a `promptNode` instance as a `ToolDefinition` on the parent via\n * `toolRegistry`.\n *\n * This sugar covers (1) — a reactive route from one agent's output into a\n * specialist factory. For (2) wire a tool registry manually; the pattern is\n * additive with this one.\n *\n * @example Full handoff on a triage signal.\n * ```ts\n * import { handoff, promptNode } from \"@graphrefly/graphrefly/patterns/ai\";\n *\n * const triage = promptNode(adapter, [userMessage], (msg) =>\n * `Classify urgency of: ${msg}. Reply \"high\" or \"normal\".`);\n * const isUrgent = derived([triage], ([v]) => v === \"high\");\n *\n * const specialist = handoff(\n * userMessage,\n * (input) => promptNode(specialistAdapter, [input], (m) => `Respond urgently: ${m}`),\n * { condition: isUrgent },\n * );\n * ```\n *\n * @param from - Source node whose value is threaded into the specialist.\n * @param toFactory - Factory that takes `from` (as a reactive source) and\n * returns the specialist node. Called once, lazily, when the first\n * subscriber activates.\n * @param opts - Optional reactive `condition` gate + name.\n * @returns Node emitting the specialist's output when the gate is open, or\n * `from`'s value when the gate is closed. Null when `from` is null.\n *\n * **Performance caveat (Wave A Unit 5):** the specialist is mounted per\n * source emission — each `v != null` DATA on `from` allocates a fresh\n * `state<T>(v)` + invokes `toFactory`, and switchMap cancels the prior\n * branch. For per-turn routing (≤1 emit/sec) this is negligible. For\n * high-frequency sources (per-token routing, tight event loops), batch\n * upstream (e.g. via `audit`, `throttle`, or `distinctUntilChanged`) before\n * handing off — each mount/unmount cycle spins up full subgraphs\n * (`messagesNode` + adapter bridge + output for a `promptNode` specialist).\n *\n * @category patterns.ai\n */\nexport function handoff<T>(\n\tfrom: NodeInput<T | null>,\n\ttoFactory: (input: Node<T>) => Node<T | null>,\n\topts?: HandoffOptions,\n): Node<T | null> {\n\tconst src = fromAny(from);\n\tconst cond = opts?.condition != null ? fromAny(opts.condition) : null;\n\n\t// Shared `null` state — reused across null source emissions so repeated\n\t// nulls don't allocate a fresh node per switchMap project call.\n\tconst nullState: Node<T | null> = node<T | null>([], {\n\t\tinitial: null,\n\t\tname: opts?.name ? `${opts.name}::null` : \"handoff::null\",\n\t});\n\n\t// When no condition is supplied, always route through the specialist.\n\tif (cond == null) {\n\t\treturn switchMap<T | null, T | null>(\n\t\t\tsrc,\n\t\t\t(v) => {\n\t\t\t\tif (v == null) return nullState as NodeInput<T | null>;\n\t\t\t\tconst input = node<T>([], { initial: v });\n\t\t\t\treturn toFactory(input) as NodeInput<T | null>;\n\t\t\t},\n\t\t\t{ meta: factoryTag(\"handoff\") },\n\t\t);\n\t}\n\n\t// With a condition: pair src + cond into a router object, then switchMap\n\t// to either the specialist (when open) or a pass-through state (when\n\t// closed). Each router emission may re-instantiate the specialist — the\n\t// switchMap cancels the stale branch.\n\tconst router = node<{ v: T | null; open: boolean }>(\n\t\t[src, cond],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit({ v: data[0] as T | null, open: data[1] === true });\n\t\t},\n\t\t{ name: opts?.name ? `${opts.name}::router` : \"handoff::router\", describeKind: \"derived\" },\n\t);\n\treturn switchMap<{ v: T | null; open: boolean }, T | null>(\n\t\trouter,\n\t\t({ v, open }) => {\n\t\t\tif (v == null) return nullState as NodeInput<T | null>;\n\t\t\tif (!open) return node<T | null>([], { initial: v }) as NodeInput<T | null>;\n\t\t\tconst input = node<T>([], { initial: v });\n\t\t\treturn toFactory(input) as NodeInput<T | null>;\n\t\t},\n\t\t{ meta: factoryTag(\"handoff\") },\n\t);\n}\n","/**\n * `toolExecution` — reactive per-tool-call executor with retry + rescue.\n *\n * Lifted from the inlined `executeToolReactively` helper inside `agent-loop.ts`\n * so it can be consumed standalone by any caller with a reactive `toolCalls`\n * batch — not just `agentLoop`. The shape is: one input `Node<readonly\n * ToolCall[]>` + a `ToolRegistryGraph` → one output `Node<readonly\n * ToolResult[]>`. Each call maps to a per-call `retrySource(executeReactive)`\n * → optional `rescue` chain that emits the handler result on success, or a\n * JSON-wrapped `{ error }` payload on terminal failure so the LLM can see the\n * error as tool output and decide whether to try again via another tool call.\n *\n * **Cancellation.** `executeReactive` mints a per-call `AbortController` and\n * threads its signal into the handler call. When `switchMap` supersedes the\n * inner (a fresh `toolCalls` batch arrives) or the outer graph tears down,\n * the per-call node unsubscribes and `ac.abort()` fires. Signal-aware\n * handlers (`fetch(url, {signal})`, child-process kill, DB cancel) actually\n * stop in-flight work; handlers that ignore the signal still complete to\n * their original termination, but their result is discarded.\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { rescue, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport { retry } from \"../../../base/resilience/retry.js\";\nimport type { ToolCall } from \"../adapters/core/types.js\";\nimport type { ToolRegistryGraph } from \"./tool-registry.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A single tool execution outcome: `{id, content}` where content is a JSON string. */\nexport interface ToolResult {\n\treadonly id: string;\n\treadonly content: string;\n}\n\nexport type ToolExecutionOptions = {\n\t/**\n\t * Reactive tool-call batch. Each non-empty emission triggers a fresh\n\t * per-call execution fan-out; superseding emissions cancel the prior fan.\n\t */\n\ttoolCalls: Node<readonly ToolCall[]>;\n\t/** Registry that resolves tool name → handler. */\n\ttools: ToolRegistryGraph;\n\t/**\n\t * Retry count per individual tool call. `retrySource({count: N})` retries\n\t * up to N times on error (N retries = N+1 total attempts). Default: 1.\n\t */\n\tretryCount?: number;\n\t/**\n\t * How to surface a terminal error after retries are exhausted.\n\t * - `\"rescue\"` (default): emit `{id, content: JSON.stringify({error})}`\n\t * so the LLM sees the failure as structured tool output and can decide\n\t * how to react. Sibling calls in the same batch continue to their own\n\t * completion; one call's failure does not affect the others.\n\t * - `\"propagate\"`: let the ERROR propagate downstream. **Blast radius:**\n\t * the per-batch `derived` join auto-errors when any per-call node\n\t * terminates with ERROR, so one call's failure discards every sibling's\n\t * DATA (even ones that already settled with a valid ToolResult). Use\n\t * `\"propagate\"` only when a single tool failure should be fatal for the\n\t * whole batch; prefer `\"rescue\"` when you want the LLM to see partial\n\t * results plus per-call error markers.\n\t */\n\tonError?: \"rescue\" | \"propagate\";\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Reactive executor for a batch of LLM tool calls.\n *\n * Each DATA emission on `toolCalls` dispatches a fresh per-call fan-out: for\n * every call in the batch, construct a `retrySource(fromAny(tools.execute(\n * name, args)))` node, optionally `rescue` it into a JSON error shape, and\n * join the results via a `derived` whose first-run gate waits for every call\n * to settle before emitting the batch. Empty batches (`calls.length === 0`)\n * are a caller-side invariant violation (the upstream gate should emit\n * RESOLVED for empty batches, not DATA) and trigger a loud error — callers\n * that want to accept empty batches should upstream-filter them first.\n *\n * Reference-equality + content-equality dedup is applied to the output batch\n * so duplicate re-emissions from a completing retrySource don't propagate.\n *\n * @param opts - `{ toolCalls, tools, retryCount?, onError? }`.\n * @returns `Node<readonly ToolResult[]>` — one ToolResult per input ToolCall.\n */\nexport function toolExecution(opts: ToolExecutionOptions): Node<readonly ToolResult[]> {\n\tconst { toolCalls, tools } = opts;\n\tconst retryCount = opts.retryCount ?? 1;\n\tconst onError = opts.onError ?? \"rescue\";\n\n\tconst batchEquals = (a: readonly ToolResult[], b: readonly ToolResult[]): boolean => {\n\t\tif (a === b) return true;\n\t\tif (a.length !== b.length) return false;\n\t\tfor (let i = 0; i < a.length; i++) {\n\t\t\tconst ai = a[i];\n\t\t\tconst bi = b[i];\n\t\t\tif (ai?.id !== bi?.id) return false;\n\t\t\tif (ai?.content !== bi?.content) return false;\n\t\t}\n\t\treturn true;\n\t};\n\n\treturn switchMap<readonly ToolCall[], readonly ToolResult[]>(toolCalls, (calls) => {\n\t\tif (calls == null || calls.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t\"toolExecution: received an empty tool-call batch as DATA — callers must upstream-filter empty batches (emit RESOLVED) so switchMap is only dispatched for non-empty batches.\",\n\t\t\t);\n\t\t}\n\t\tconst perCall = calls.map((call) => executeOne(call, tools, retryCount, onError));\n\t\t// `executeOne` returns `Node<ToolResult>` in both \"rescue\" and\n\t\t// \"propagate\" modes (the rescue handler builds a `ToolResult`\n\t\t// shape; the success `derived` builds one directly). The join\n\t\t// just forwards the per-call values — no shape coercion needed.\n\t\treturn node(\n\t\t\tperCall,\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tactions.emit(data as readonly ToolResult[]);\n\t\t\t},\n\t\t\t{ describeKind: \"derived\", name: \"toolExecution::batch\", equals: batchEquals },\n\t\t);\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\n/**\n * Per-call reactive executor. `retrySource` re-invokes the factory on ERROR\n * (each attempt mints a fresh `executeReactive` node, which in turn mints a\n * fresh `AbortController` and handler invocation). `executeReactive` itself\n * handles synchronous handler throws — they surface as `[[ERROR, err]]`\n * inside the producer, so `retrySource`'s reactive ERROR path fires\n * consistently regardless of handler shape. No `Promise.resolve().then(...)`\n * thunk needed — the reactive path is end-to-end.\n *\n * Handlers that return a plain string are surfaced as-is; anything else is\n * `JSON.stringify`'d so LLMs that parse tool results can roundtrip\n * structured data without surprise quoting.\n */\nfunction executeOne(\n\tcall: ToolCall,\n\ttools: ToolRegistryGraph,\n\tretryCount: number,\n\tonError: \"rescue\" | \"propagate\",\n): Node<ToolResult> {\n\tconst attempted: Node<unknown> = retry(() => tools.executeReactive(call.name, call.arguments), {\n\t\tcount: retryCount,\n\t}).node;\n\tconst onSuccess = node<ToolResult>(\n\t\t[attempted],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst val = data[0];\n\t\t\tactions.emit({\n\t\t\t\tid: call.id,\n\t\t\t\tcontent: typeof val === \"string\" ? val : JSON.stringify(val),\n\t\t\t});\n\t\t},\n\t\t{ describeKind: \"derived\" },\n\t);\n\tif (onError === \"propagate\") return onSuccess;\n\treturn rescue(onSuccess, (err) => ({\n\t\tid: call.id,\n\t\tcontent: JSON.stringify({ error: String(err) }),\n\t}));\n}\n","import { ERROR, type Messages, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAsyncIter, fromPromise, keepalive, reactiveMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { aiMeta, isNodeLike } from \"../_internal.js\";\nimport type { ToolDefinition } from \"../adapters/core/types.js\";\n\n// ---------------------------------------------------------------------------\n// toolRegistry\n// ---------------------------------------------------------------------------\n\nexport type ToolRegistryOptions = {\n\tgraph?: GraphOptions;\n};\n\n/**\n * `ToolRegistryGraph` — name-keyed registry of {@link ToolDefinition}s.\n *\n * **Reactive-only execution.** The only execution path is\n * {@link executeReactive}, which returns a `Node<unknown>` for the handler\n * result. Composing factories (`toolExecution`, `agentLoop`) consume it\n * directly inside `retrySource` / `switchMap` chains. There is intentionally\n * no imperative `execute()` Promise method — the registry was originally a\n * dual-boundary class (imperative + reactive) and the imperative path was\n * the only thing in the codebase bridging through `Promise.resolve().then()`\n * to feed `fromAny`. Removing it left every consumer on a single\n * reactive-all-the-way path with real abort propagation.\n *\n * For non-reactive callers (debug scripts, one-shot tests), bridge with\n * `awaitSettled(toolRegistry.executeReactive(name, args))`.\n *\n * **Wave A Unit 6 refactor:** internal storage migrated from `state<Map>`\n * (O(N) Map-copy per mutation) to `ReactiveMapBundle<string, ToolDefinition>`\n * (O(1) mutations + version counter).\n */\nexport class ToolRegistryGraph extends Graph {\n\treadonly definitions: Node<ReadonlyMap<string, ToolDefinition>>;\n\treadonly schemas: Node<readonly ToolDefinition[]>;\n\tprivate readonly _bundle: ReturnType<typeof reactiveMap<string, ToolDefinition>>;\n\n\tconstructor(name: string, opts: ToolRegistryOptions = {}) {\n\t\tsuper(name, opts.graph);\n\n\t\tthis._bundle = reactiveMap<string, ToolDefinition>({\n\t\t\tname: \"definitions\",\n\t\t});\n\t\tthis.definitions = this._bundle.entries;\n\t\tthis.add(this.definitions, { name: \"definitions\" });\n\n\t\tthis.schemas = node<readonly ToolDefinition[]>(\n\t\t\t[this.definitions],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst defs = data[0];\n\t\t\t\tactions.emit([...((defs ?? new Map()) as ReadonlyMap<string, ToolDefinition>).values()]);\n\t\t\t},\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(this.schemas, { name: \"schemas\" });\n\t\tthis.addDisposer(keepalive(this.schemas));\n\t}\n\n\tregister(tool: ToolDefinition): void {\n\t\tthis._bundle.set(tool.name, tool);\n\t}\n\n\tunregister(name: string): void {\n\t\tthis._bundle.delete(name);\n\t}\n\n\t/**\n\t * Reactive execution — returns a `Node<unknown>` that emits the handler\n\t * result. The returned node is a `producer` that:\n\t *\n\t * 1. Mints a per-call `AbortController` whose `signal` is threaded into\n\t * the handler call AND into `fromAny` (so a `fromPromise` /\n\t * `fromAsyncIter` inner abandons cleanly when the consumer\n\t * unsubscribes).\n\t * 2. Runs `tool.handler(args, {signal})` inside a try/catch — a\n\t * synchronous throw surfaces as `[[ERROR, err]]` downstream instead\n\t * of escaping the producer.\n\t * 3. Forwards every message from the inner `fromAny` chain to the\n\t * producer's outputs.\n\t * 4. On teardown (subscriber count drops to zero, e.g. `switchMap`\n\t * supersede) calls `ac.abort()` and unsubscribes the inner.\n\t * Signal-aware handlers (e.g. `fetch(url, {signal})`) actually stop.\n\t *\n\t * Each call mints a fresh node tied to a fresh `handler(args, ...)`\n\t * invocation — call `executeReactive` again for repeated invocations.\n\t *\n\t * @throws `Error` synchronously when `name` is not registered (no node is\n\t * constructed — the caller gets a pre-wiring failure rather than a\n\t * silent ERROR wave on an empty graph).\n\t */\n\texecuteReactive(name: string, args: Record<string, unknown>): Node<unknown> {\n\t\tconst tool = this._bundle.get(name);\n\t\tif (!tool) throw new Error(`toolRegistry: unknown tool \"${name}\"`);\n\t\treturn node<unknown>(\n\t\t\t[],\n\t\t\t(_data, actions) => {\n\t\t\t\tconst ac = new AbortController();\n\t\t\t\tlet inner: Node<unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tconst raw = tool.handler(args, { signal: ac.signal });\n\t\t\t\t\tinner = handlerResultToNode(raw, ac.signal);\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// Synchronous throw from handler → ERROR. Producer cleanup\n\t\t\t\t\t// still aborts the controller for symmetry (no-op if no\n\t\t\t\t\t// signal listeners attached).\n\t\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tac.abort();\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst unsub = inner.subscribe((batch) => {\n\t\t\t\t\tactions.down(batch as Messages);\n\t\t\t\t});\n\t\t\t\treturn () => {\n\t\t\t\t\tac.abort();\n\t\t\t\t\tunsub();\n\t\t\t\t};\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: `executeReactive::${name}`,\n\t\t\t\tdescribeKind: \"producer\",\n\t\t\t\tmeta: aiMeta(\"tool_execute_reactive\"),\n\t\t\t},\n\t\t);\n\t}\n\n\tgetDefinition(name: string): ToolDefinition | undefined {\n\t\t// Pure read via the snapshot cache — avoids the bundle's\n\t\t// `wrapMutation` path (which would run the version-bump check and\n\t\t// any configured retention eviction on every lookup). Safe because\n\t\t// `getDefinition` is a boundary API, not a reactive fn body.\n\t\treturn this._bundle.entries.cache?.get(name);\n\t}\n}\n\nexport function toolRegistry(name: string, opts?: ToolRegistryOptions): ToolRegistryGraph {\n\treturn new ToolRegistryGraph(name, opts);\n}\n\n/**\n * Coerce a tool handler return value into a `Node<unknown>`.\n *\n * Differs from `fromAny` by treating **strings, arrays, plain iterables, and\n * scalar objects as single DATA values** rather than iterating them. A tool\n * handler that returns `\"hello world\"` should surface as one `DATA(\"hello\n * world\")`, not 11 `DATA` events of single characters; an array `[1, 2, 3]`\n * should surface as `DATA([1, 2, 3])`, not three separate emissions.\n *\n * Reactive shapes (Node, Promise, AsyncIterable) are unwrapped as expected.\n *\n * @internal\n */\nfunction handlerResultToNode(raw: unknown, signal: AbortSignal): Node<unknown> {\n\tif (isNodeLike(raw)) {\n\t\treturn raw as Node<unknown>;\n\t}\n\tif (raw != null && typeof (raw as PromiseLike<unknown>).then === \"function\") {\n\t\treturn fromPromise(raw as PromiseLike<unknown>, { signal });\n\t}\n\tif (raw != null && typeof raw === \"object\" && Symbol.asyncIterator in (raw as object)) {\n\t\treturn fromAsyncIter(raw as AsyncIterable<unknown>, { signal });\n\t}\n\t// String, number, boolean, null, undefined, plain object, array,\n\t// sync iterable — treat as a single DATA value via a resolved Promise so\n\t// `fromPromise`'s scalar-DATA-emit + COMPLETE semantics match the\n\t// pre-refactor `tools.execute` behavior (which always wrapped via async).\n\treturn fromPromise(Promise.resolve(raw), { signal });\n}\n","import { factoryTag, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { aiMeta } from \"../_internal.js\";\nimport type { ToolDefinition } from \"../adapters/core/types.js\";\n\n// ---------------------------------------------------------------------------\n// toolSelector — reactive tool availability (D8 / COMPOSITION-GUIDE §31)\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link toolSelector}.\n */\nexport interface ToolSelectorOptions {\n\treadonly name?: string;\n}\n\n/**\n * Reactive tool availability (COMPOSITION-GUIDE §31). Given a base tool set\n * (reactive or static) and one or more reactive predicates, emit the filtered\n * subset of tools currently allowed. Feeds into `promptNode({ tools: Node<...> })`\n * so the LLM sees a reactive menu instead of a frozen config.\n *\n * Each predicate is a `NodeInput<(tool) => boolean>`. A tool is included iff\n * **every** predicate returns `true`. When any predicate value is `null` /\n * `undefined` (e.g. upstream not yet ready) that predicate is treated as a\n * pass-through — the tool isn't excluded on its basis. Predicate updates\n * recompute the selected set.\n *\n * Pairs with `toolInterceptor` (§D9 / §31): **selection** controls what's\n * offered to the LLM (pre-generation UX); **interception** gates what's\n * executed after the LLM chooses (post-generation security). Tool selection\n * is NOT a security boundary — an LLM can hallucinate tool calls outside\n * its offered set; always pair with `toolInterceptor` for enforcement.\n *\n * @example\n * ```ts\n * const hasBudget = node([costMeter], (batchData, actions, ctx) => {\n * const data = batchData.map((batch, i) => batch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i]);\n * actions.emit((data[0] as CostMeter).total < BUDGET);\n * }, { describeKind: \"derived\" });\n * const canDestroy = state(false, { name: \"destructive-allowed\" });\n * const tools = toolSelector(registry.schemas, [\n * node([hasBudget], (batchData, actions, ctx) => {\n * const data = batchData.map((batch, i) => batch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i]);\n * actions.emit((t) => !t.meta?.expensive || data[0] === true);\n * }, { describeKind: \"derived\" }),\n * node([canDestroy], (batchData, actions, ctx) => {\n * const data = batchData.map((batch, i) => batch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i]);\n * actions.emit((t) => !t.meta?.destructive || data[0] === true);\n * }, { describeKind: \"derived\" }),\n * ]);\n * const agent = promptNode(graph, \"agent\", { ..., tools });\n * ```\n */\nexport function toolSelector(\n\tallTools: NodeInput<readonly ToolDefinition[]>,\n\tconstraints: readonly NodeInput<(tool: ToolDefinition) => boolean>[],\n\topts?: ToolSelectorOptions,\n): Node<readonly ToolDefinition[]> {\n\tconst allToolsNode = fromAny(allTools);\n\tconst constraintNodes = constraints.map((c) => fromAny(c));\n\tconst deps = [allToolsNode, ...constraintNodes] as const;\n\treturn node<readonly ToolDefinition[]>(\n\t\tdeps,\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst tools = (data[0] as readonly ToolDefinition[] | null | undefined) ?? [];\n\t\t\tconst preds = data.slice(1) as ReadonlyArray<\n\t\t\t\t((t: ToolDefinition) => boolean) | null | undefined\n\t\t\t>;\n\t\t\tactions.emit(\n\t\t\t\ttools.filter((tool) => {\n\t\t\t\t\tfor (const pred of preds) {\n\t\t\t\t\t\t// Pass-through when a predicate hasn't settled — callers with\n\t\t\t\t\t\t// async constraints should not have every tool silently dropped\n\t\t\t\t\t\t// on the first emit. Constraints are \"deny when false\", not\n\t\t\t\t\t\t// \"deny when not yet ready\".\n\t\t\t\t\t\tif (pred == null) continue;\n\t\t\t\t\t\tif (!pred(tool)) return false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"tool-selector\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: { ...aiMeta(\"tool_selector\"), ...factoryTag(\"toolSelector\") },\n\t\t\tequals: (a, b) => {\n\t\t\t\tconst la = a as readonly ToolDefinition[];\n\t\t\t\tconst lb = b as readonly ToolDefinition[];\n\t\t\t\tif (la.length !== lb.length) return false;\n\t\t\t\tfor (let i = 0; i < la.length; i++) {\n\t\t\t\t\tif (la[i] !== lb[i]) return false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n}\n","// ---------------------------------------------------------------------------\n// Admission scoring (generic + 3D sugar)\n// ---------------------------------------------------------------------------\n//\n// `admissionScored<Dims>` is the generic primitive: a user-supplied scoreFn\n// returns one number per named dimension; the filter rejects whenever any\n// scored dimension falls below its configured threshold. Dimensions absent\n// from the thresholds config are ignored — they may still be useful for\n// telemetry, but don't gate admission.\n//\n// `admissionFilter3D` is a thin wrapper for the persistence / structure /\n// personalValue triple borrowed from the LLM memory literature; ship this\n// when callers want the named-axes shape, otherwise compose `admissionScored`\n// directly with whatever dimensions fit the domain.\n//\n// The earlier `defaultAdmissionScorer` (always-0.5 across all dims) was\n// retired in Unit 8 — it admitted everything in disguise. Callers must\n// supply a real `scoreFn`.\n\n/** Generic per-dimension thresholds. Any dim below its threshold → reject. */\nexport type AdmissionThresholds<Dims extends string> = Partial<Record<Dims, number>>;\n\nexport type AdmissionScoredOptions<Dims extends string, TRaw = unknown> = {\n\t/** Score function — must return a finite number for every dimension named in `thresholds`. */\n\tscoreFn: (raw: TRaw) => Readonly<Record<Dims, number>>;\n\t/** Per-dim minimums. Dims absent here are scored but not gated. */\n\tthresholds?: AdmissionThresholds<Dims>;\n};\n\n/**\n * Generic N-dimension admission filter. Rejects any input where one of the\n * configured threshold dimensions scores below its minimum. Missing scores\n * (`undefined` / `null`) AND non-finite values (`NaN`, `±Infinity`) are\n * treated as below all thresholds — reject by default rather than admit.\n *\n * @example\n * ```ts\n * const filter = admissionScored({\n * scoreFn: (raw: Note) => ({ relevance: scoreRelevance(raw), age: ageScore(raw) }),\n * thresholds: { relevance: 0.4 }, // age scored but ungated\n * });\n * ```\n */\nexport function admissionScored<Dims extends string, TRaw = unknown>(\n\topts: AdmissionScoredOptions<Dims, TRaw>,\n): (raw: TRaw) => boolean {\n\tconst thresholds = opts.thresholds ?? ({} as AdmissionThresholds<Dims>);\n\treturn (raw: TRaw): boolean => {\n\t\tconst scores = opts.scoreFn(raw);\n\t\tfor (const dim of Object.keys(thresholds) as Dims[]) {\n\t\t\tconst min = thresholds[dim];\n\t\t\tif (min === undefined) continue;\n\t\t\tconst s = scores[dim];\n\t\t\t// `??` falls back on null/undefined but lets NaN through; we want\n\t\t\t// non-finite to also reject so a buggy scoreFn returning NaN doesn't\n\t\t\t// silently admit. `Number.isFinite(NaN) === false`.\n\t\t\tconst safe = Number.isFinite(s) ? (s as number) : Number.NEGATIVE_INFINITY;\n\t\t\tif (safe < min) return false;\n\t\t}\n\t\treturn true;\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// 3D sugar\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. Required — the previous always-0.5 default was misleading. */\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 * 3D admission sugar — the persistence / structure / personalValue triple\n * commonly used in agent-memory literature. Composes `admissionScored`\n * with thresholds derived from the option fields. Use directly when those\n * three named dimensions match your domain, or use `admissionScored` with\n * an arbitrary dimension set instead.\n *\n * `requireStructured: true` rejects entries where `structure <= 0` (matches\n * the pre-Unit-8 `requireStructured && scores.structure <= 0` check).\n * Implemented as a final-step predicate around `admissionScored` rather\n * than a `Number.MIN_VALUE` threshold, which would have been a footgun for\n * future readers.\n */\nexport function admissionFilter3D(opts: AdmissionScore3DOptions): (raw: unknown) => boolean {\n\tconst thresholds: AdmissionThresholds<keyof AdmissionScores> = {\n\t\tpersistence: opts.persistenceThreshold ?? 0.3,\n\t\tpersonalValue: opts.personalValueThreshold ?? 0.3,\n\t};\n\tconst base = admissionScored<keyof AdmissionScores, unknown>({\n\t\tscoreFn: opts.scoreFn,\n\t\tthresholds,\n\t});\n\tif (!opts.requireStructured) return base;\n\treturn (raw: unknown): boolean => {\n\t\tif (!base(raw)) return false;\n\t\tconst s = opts.scoreFn(raw).structure;\n\t\treturn Number.isFinite(s) && s > 0;\n\t};\n}\n","// ---------------------------------------------------------------------------\n// memory composers — Unit 7 C-factoring (2026-04-23 doc decision).\n//\n// Each composer attaches one capability (vectors, KG, tiers, retrieval) to a\n// `DistillBundle`. `agentMemory` continues to ship as the ergonomic sugar\n// over the full pipeline; power users who want a subset call these factories\n// directly.\n//\n// Class B audit (2026-04-30): the composers were migrated from\n// bundle-returning factories to **Graph subclasses** so they participate in\n// `describe()` / `destroy()` like every other Phase 4+ Graph (mirrors\n// `AuditTrailGraph`, `PolicyGateGraph`, `CqrsGraph`). The factory functions\n// remain as ergonomic constructors (`memoryWithVectors(opts) → MemoryWithVectorsGraph`).\n//\n// Tier 4.1 B + 4.3 B (2026-04-29): `memoryWithTiers` is the construction site\n// for the distill bundle when tiers are configured (`reactiveMap.retention`\n// wired at construction eliminates the §7 feedback cycle the prior\n// `tierClassifier` effect carried). `permanentKeys` and `entryCreatedAtNs`\n// are reactive maps mounted on the graph (not closure state) so\n// `describe()`/`explain()` can walk to the inputs that fed an archival\n// decision.\n// ---------------------------------------------------------------------------\n\nimport { batch, DATA, monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport type { StorageHandle } from \"@graphrefly/pure-ts/extra\";\nimport {\n\tfromAny,\n\tkeepalive,\n\ttype NodeInput,\n\ttype ReactiveMapBundle,\n\ttype ReactiveMapRetention,\n\treactiveMap,\n} from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport {\n\ttype DistillBundle,\n\ttype DistillOptions,\n\tdistill,\n\ttype Extraction,\n} from \"../../../base/composition/distill.js\";\nimport { decay } from \"../../../base/utils/decay.js\";\nimport {\n\tcollection,\n\tcosineSimilarity,\n\ttype KnowledgeEdge,\n\ttype KnowledgeGraph,\n\tknowledgeGraph,\n\ttype VectorIndexGraph,\n\ttype VectorRecord,\n\ttype VectorSearchResult,\n\tvectorIndex,\n} from \"../../memory/index.js\";\nimport { aiMeta } from \"../_internal.js\";\nimport type { RetrievalEntry, RetrievalQuery, RetrievalTrace } from \"./retrieval.js\";\nimport {\n\tDEFAULT_DECAY_RATE,\n\ttype MemoryTier,\n\ttype MemoryTiersBundle,\n\ttype MemoryTiersOptions,\n} from \"./tiers.js\";\n\n// Tier 4.7 (Wave AM Unit 5 carry): the pre-rebuild defensive `extractStoreMap`\n// helper (runtime `instanceof Map` check before casting) was deleted in favor\n// of a typed `as` cast at each callsite. The upstream `ReactiveMapBundle`\n// always emits a real Map on the live emit path; non-Map snapshots only\n// surface on `Graph.restore` from a codec that round-tripped Map → JSON →\n// plain object (handled in `extra/composite.ts:mapFromSnapshot` for distill\n// internals). Empty map is the canonical \"no entries yet\" value —\n// `node([], { initial: undefined })` would stall a derived/effect's first-run gate.\n//\n// qa F3 (deferred): the typed cast lies if upstream contract ever breaks\n// (e.g. `entries` emits a non-Map non-undefined value). Failure mode is a\n// TypeError at iteration instead of a silent empty-map fallback —\n// deliberate trade-off, surfacing real upstream-contract violations beats\n// hiding them. Upstream-narrowing follow-up filed in `docs/optimizations.md`\n// under \"Tier 4.7 follow-up — narrow `ReactiveMapBundle.entries` callback typing\".\n\n// ---------------------------------------------------------------------------\n// memoryWithVectors\n// ---------------------------------------------------------------------------\n\nexport interface MemoryWithVectorsOptions<TMem> {\n\t/** Optional Graph identity — passed through to the underlying `Graph` ctor. */\n\tgraph?: GraphOptions;\n\t/** Subgraph name. Default: `\"memory-vectors\"`. */\n\tname?: string;\n\t/** The substrate distill store to index. */\n\tstore: DistillBundle<TMem>;\n\t/** Embedding dimension. Must match the `embedFn` output length. */\n\tdimension: number;\n\t/** Extract an embedding vector for a memory entry. */\n\tembedFn: (mem: TMem) => readonly number[] | undefined;\n}\n\n/**\n * Graph subclass that attaches a vector index to a `DistillBundle`. The inner\n * `VectorIndexGraph` is mounted at `\"vectorIndex\"`; an internal effect\n * subscribes to the substrate store and re-indexes on every change.\n *\n * Mirrors `AuditTrailGraph` / `PolicyGateGraph` shape — fully self-contained,\n * teardown via the Graph's `destroy()` cascade.\n */\nexport class MemoryWithVectorsGraph<TMem> extends Graph {\n\treadonly vectors: VectorIndexGraph<TMem>;\n\n\tconstructor(opts: MemoryWithVectorsOptions<TMem>) {\n\t\tsuper(opts.name ?? \"memory-vectors\", opts.graph);\n\t\tthis.vectors = vectorIndex<TMem>({ dimension: opts.dimension });\n\t\tthis.mount(\"vectorIndex\", this.vectors);\n\n\t\tconst embedFn = opts.embedFn;\n\t\tconst vectorsRef = this.vectors;\n\n\t\t// Indexer effect — subscribes to the substrate's store entries, upserts\n\t\t// vectors. Pure side-effect; restricted `effect` fn (no emit/down).\n\t\t// Cross-graph dep on `opts.store.store.entries` is fine — the substrate\n\t\t// is the upstream wired in by the parent factory.\n\t\tconst indexer = node(\n\t\t\t[opts.store.store.entries],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst storeMap =\n\t\t\t\t\t(data[0] as ReadonlyMap<string, TMem> | undefined) ?? new Map<string, TMem>();\n\t\t\t\tfor (const [key, mem] of storeMap) {\n\t\t\t\t\tconst vec = embedFn(mem);\n\t\t\t\t\tif (vec) vectorsRef.upsert(key, vec, mem);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ name: \"indexer\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(indexer, { name: \"indexer\" });\n\t\tthis.addDisposer(keepalive(indexer));\n\t}\n}\n\n/**\n * Attach a vector index to a `DistillBundle`. Indexes every entry in the\n * store as it changes. Returns the `MemoryWithVectorsGraph` whose `vectors`\n * field exposes the underlying `VectorIndexGraph`.\n *\n * Teardown is handled by `Graph.destroy()` — typically inherited via\n * mounting the result on a parent graph (see `agentMemory`).\n */\nexport function memoryWithVectors<TMem>(\n\topts: MemoryWithVectorsOptions<TMem>,\n): MemoryWithVectorsGraph<TMem> {\n\treturn new MemoryWithVectorsGraph<TMem>(opts);\n}\n\n// ---------------------------------------------------------------------------\n// memoryWithKG\n// ---------------------------------------------------------------------------\n\nexport interface MemoryWithKGOptions<TMem> {\n\t/** Optional Graph identity. */\n\tgraph?: GraphOptions;\n\t/** Subgraph name. Default: `\"memory-kg\"`. */\n\tname?: string;\n\t/** The substrate distill store to index. */\n\tstore: DistillBundle<TMem>;\n\t/** Inner KnowledgeGraph name. Default: `${name}-kg`. */\n\tkgName?: string;\n\t/**\n\t * Mount path within this Graph for the KnowledgeGraph. Default:\n\t * `\"knowledge-kg\"` (B5c — symmetric with the outer `knowledge` mount so\n\t * describe paths render `knowledge::knowledge-kg::*`).\n\t */\n\tmountPath?: string;\n\t/**\n\t * Extract entities + relations for a memory entry. Omit to mount an empty\n\t * KG without an indexer effect — caller upserts entities / relations\n\t * directly on the `kg` field.\n\t */\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\n/**\n * Graph subclass that attaches a knowledge graph alongside a `DistillBundle`.\n * Mounts the inner `KnowledgeGraph` at `mountPath` (default `\"knowledge-kg\"`); when\n * `entityFn` is provided, an indexer effect populates entities/relations on\n * every store change.\n */\nexport class MemoryWithKGGraph<TMem> extends Graph {\n\treadonly kg: KnowledgeGraph<unknown, string>;\n\n\tconstructor(opts: MemoryWithKGOptions<TMem>) {\n\t\tconst name = opts.name ?? \"memory-kg\";\n\t\tsuper(name, opts.graph);\n\t\tconst kgName = opts.kgName ?? `${name}-kg`;\n\t\tconst mountPath = opts.mountPath ?? \"knowledge-kg\";\n\t\tthis.kg = knowledgeGraph<unknown, string>(kgName);\n\t\tthis.mount(mountPath, this.kg);\n\n\t\tif (!opts.entityFn) return;\n\t\tconst entityFn = opts.entityFn;\n\t\tconst kgRef = this.kg;\n\t\tconst indexer = node(\n\t\t\t[opts.store.store.entries],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst storeMap =\n\t\t\t\t\t(data[0] as ReadonlyMap<string, TMem> | undefined) ?? new Map<string, TMem>();\n\t\t\t\tfor (const [key, mem] of storeMap) {\n\t\t\t\t\tconst extracted = entityFn(key, mem);\n\t\t\t\t\tif (!extracted) continue;\n\t\t\t\t\tfor (const ent of extracted.entities ?? []) {\n\t\t\t\t\t\tkgRef.upsertEntity(ent.id, ent.value);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const rel of extracted.relations ?? []) {\n\t\t\t\t\t\tkgRef.link(rel.from, rel.to, rel.relation, rel.weight);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ name: \"indexer\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(indexer, { name: \"indexer\" });\n\t\tthis.addDisposer(keepalive(indexer));\n\t}\n}\n\n/**\n * Attach a knowledge graph alongside a `DistillBundle`. Returns the\n * `MemoryWithKGGraph` whose `kg` field exposes the inner `KnowledgeGraph`.\n */\nexport function memoryWithKG<TMem>(opts: MemoryWithKGOptions<TMem>): MemoryWithKGGraph<TMem> {\n\treturn new MemoryWithKGGraph<TMem>(opts);\n}\n\n// ---------------------------------------------------------------------------\n// memoryWithTiers\n// ---------------------------------------------------------------------------\n\n/**\n * Full options for {@link memoryWithTiers} (Tier 4.1 B + 4.3 B refactor,\n * 2026-04-29). Combines tier-policy options with the distill-side options\n * needed to construct the underlying store — `memoryWithTiers` is the\n * **construction site** for the distill bundle so it can wire\n * `reactiveMap.retention` into the store at construction (eliminating the\n * §7 feedback cycle the previous `tierClassifier` effect carried).\n */\nexport type MemoryWithTiersOptions<TRaw, TMem> = MemoryTiersOptions<TMem> &\n\tOmit<DistillOptions<TMem>, \"mapOptions\" | \"score\" | \"context\"> & {\n\t\t/** Optional Graph identity. */\n\t\tgraph?: GraphOptions;\n\t\t/** Subgraph name. Default: `\"memory-tiers\"`. */\n\t\tname?: string;\n\t\t/** Raw source feeding distill. */\n\t\tsource: NodeInput<TRaw>;\n\t\t/** Reactive extraction wiring (same shape as `distill`). */\n\t\textractFn: (\n\t\t\traw: Node<TRaw>,\n\t\t\texisting: Node<ReadonlyMap<string, TMem>>,\n\t\t) => NodeInput<Extraction<TMem>>;\n\t\t/** Score function — same signature as `agentMemory.score`. */\n\t\tscore: (mem: TMem, context: unknown) => number;\n\t\t/** Optional reactive context node (passed to `score`). */\n\t\tcontext?: NodeInput<unknown>;\n\t};\n\n/**\n * Graph subclass attaching 3-tier storage (active / archived / permanent) to\n * a fresh distill store, wiring `reactiveMap.retention` at construction so\n * archival happens synchronously inside the substrate's mutation pipeline\n * (no §7 feedback cycle). Promotes `permanentKeys` and `entryCreatedAtNs` to\n * reactive maps registered on this graph (Tier 4.3 B — Unit 7 Q3) so\n * `describe()` / `explain()` can walk to \"why was X archived?\".\n *\n * Public-face fields:\n * - `store` — the distill bundle (construction site, exposed for downstream\n * composers).\n * - `tiers` — tier classification + permanent promotion handles.\n * - `compact`, `size` — alias for `store.compact` / `store.size` (registered\n * under their canonical names so `describe()` keys match `agentMemory`'s\n * pre-migration layout).\n */\nexport class MemoryWithTiersGraph<TRaw, TMem> extends Graph {\n\treadonly store: DistillBundle<TMem>;\n\treadonly tiers: MemoryTiersBundle<TMem>;\n\treadonly compact: Node<Array<{ key: string; value: TMem; score: number }>>;\n\treadonly size: Node<number>;\n\treadonly permanent: ReturnType<typeof collection<TMem>>;\n\treadonly permanentKeys: ReactiveMapBundle<string, true>;\n\treadonly entryCreatedAtNs: ReactiveMapBundle<string, number>;\n\n\tconstructor(opts: MemoryWithTiersOptions<TRaw, TMem>) {\n\t\tsuper(opts.name ?? \"memory-tiers\", opts.graph);\n\n\t\tconst decayRate = opts.decayRate ?? DEFAULT_DECAY_RATE;\n\t\tconst maxActive = opts.maxActive ?? 1000;\n\t\tconst archiveThreshold = opts.archiveThreshold ?? 0.1;\n\t\tconst permanentFilter = opts.permanentFilter ?? (() => false);\n\n\t\t// Tier 2.3 fold: `lightCollection` was merged into\n\t\t// `collection({ranked: false})`. The unified factory returns a Graph (not\n\t\t// a detached bundle), so it's mounted as a subgraph for `describe()`.\n\t\tthis.permanent = collection<TMem>(\"permanent\", { ranked: false });\n\t\tthis.mount(\"permanent\", this.permanent);\n\n\t\t// 4.3 B (Unit 7 Q3, 2026-04-29): closure-state promotion. `permanentKeys`\n\t\t// and `entryCreatedAtNs` are reactive maps registered on this graph so\n\t\t// `describe()` can walk to them and `explain()` can trace the inputs\n\t\t// that fed an archival decision.\n\t\tthis.permanentKeys = reactiveMap<string, true>({ name: \"permanentKeys\" });\n\t\tthis.add(this.permanentKeys.entries, { name: \"permanentKeys\" });\n\t\tthis.entryCreatedAtNs = reactiveMap<string, number>({ name: \"entryCreatedAtNs\" });\n\t\tthis.add(this.entryCreatedAtNs.entries, { name: \"entryCreatedAtNs\" });\n\n\t\t// Closure-mirror for ctx (§28 factory-time seed). `score(mem, ctx)` runs\n\t\t// inside `retention.score` which is invoked synchronously from store\n\t\t// mutations — no reactive dep on contextNode there. The mirror keeps\n\t\t// `latestCtx` current via subscribe.\n\t\t//\n\t\t// Topology visibility: the local-default branch registers the context\n\t\t// state node so it appears in `describe()`. The user-supplied-Node\n\t\t// branch deliberately leaves the node unregistered — `fromAny` returns\n\t\t// the caller's owned Node, which is owned by their graph; mounting it\n\t\t// here would corrupt cross-graph ownership.\n\t\tlet contextNode: Node<unknown>;\n\t\tif (opts.context) {\n\t\t\tcontextNode = fromAny(opts.context);\n\t\t} else {\n\t\t\tcontextNode = node<unknown>([], { initial: null });\n\t\t\tthis.add(contextNode, { name: \"context\" });\n\t\t}\n\t\tlet latestCtx: unknown = contextNode.cache;\n\t\tconst ctxUnsub = contextNode.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) if (m[0] === DATA) latestCtx = m[1];\n\t\t});\n\t\tthis.addDisposer(ctxUnsub);\n\n\t\tconst permanentKeysRef = this.permanentKeys;\n\t\tconst entryCreatedAtNsRef = this.entryCreatedAtNs;\n\t\tconst score = opts.score;\n\n\t\t// Build retention. `score` runs synchronously inside store mutations.\n\t\t// Permanent matches return Infinity to bypass eviction.\n\t\t//\n\t\t// DS-13.5.F (2026-05-01): `score` is read-only against\n\t\t// `entryCreatedAtNs` — the first-write side-effect was extracted into\n\t\t// the `entryCreatedAtNs/sync` effect below. Race window for the very\n\t\t// first call on a new key is mitigated by the `?? nowNs` fallback\n\t\t// (yields ageSeconds = 0, i.e. fresh-decay), and the sync effect\n\t\t// populates the map after the wave settles so subsequent score calls\n\t\t// see the persisted timestamp.\n\t\tconst retention: ReactiveMapRetention<string, TMem> = {\n\t\t\tscore: (key, value) => {\n\t\t\t\tif (permanentFilter(key, value)) return Number.POSITIVE_INFINITY;\n\t\t\t\tif (permanentKeysRef.has(key)) return Number.POSITIVE_INFINITY;\n\t\t\t\tconst nowNs = monotonicNs();\n\t\t\t\tconst createdNs = entryCreatedAtNsRef.get(key) ?? nowNs;\n\t\t\t\tconst ageSeconds = Number(nowNs - createdNs) / 1e9;\n\t\t\t\treturn decay(score(value, latestCtx), ageSeconds, decayRate);\n\t\t\t},\n\t\t\tarchiveThreshold,\n\t\t\tmaxSize: maxActive,\n\t\t};\n\n\t\t// Construct distill with retention wired into mapOptions.\n\t\tthis.store = distill<TRaw, TMem>(opts.source, opts.extractFn, {\n\t\t\tscore: opts.score,\n\t\t\tcost: opts.cost,\n\t\t\t...(opts.budget !== undefined ? { budget: opts.budget } : {}),\n\t\t\t...(opts.evict !== undefined ? { evict: opts.evict } : {}),\n\t\t\t...(opts.consolidate !== undefined ? { consolidate: opts.consolidate } : {}),\n\t\t\t...(opts.consolidateTrigger !== undefined\n\t\t\t\t? { consolidateTrigger: opts.consolidateTrigger }\n\t\t\t\t: {}),\n\t\t\t...(opts.context !== undefined ? { context: opts.context } : {}),\n\t\t\tmapOptions: { retention },\n\t\t});\n\n\t\t// Register the distill bundle's exposed nodes under their canonical\n\t\t// names so consumers (and `describe()`) see the same shape as the\n\t\t// pre-migration top-level surface on `agentMemory`.\n\t\tthis.add(this.store.store.entries, { name: \"store\" });\n\t\tthis.compact = this.store.compact;\n\t\tthis.add(this.compact, { name: \"compact\" });\n\t\tthis.size = this.store.size;\n\t\tthis.add(this.size, { name: \"size\" });\n\n\t\tconst storeRef = this.store;\n\t\tconst tierOf = (key: string): MemoryTier => {\n\t\t\tif (permanentKeysRef.has(key)) return \"permanent\";\n\t\t\tconst m =\n\t\t\t\t(storeRef.store.entries.cache as ReadonlyMap<string, TMem> | undefined) ??\n\t\t\t\tnew Map<string, TMem>();\n\t\t\tif (m.has(key)) return \"active\";\n\t\t\treturn \"archived\";\n\t\t};\n\t\tconst permanentRef = this.permanent;\n\t\tconst markPermanent = (key: string, value: TMem): void => {\n\t\t\tpermanentKeysRef.set(key, true);\n\t\t\tpermanentRef.upsert(key, value);\n\t\t};\n\n\t\t// DS-13.5.F (2026-05-01): first-write of `entryCreatedAtNs[key]` runs\n\t\t// here (extracted from `retention.score` to keep score pure). Reads\n\t\t// `store.store.entries`, writes `entryCreatedAtNs` — distinct nodes,\n\t\t// no §7 feedback cycle. Idempotent: re-emissions for already-tracked\n\t\t// keys skip via `entryCreatedAtNsRef.has(key)`.\n\t\tconst syncCreatedAt = node(\n\t\t\t[this.store.store.entries],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst map = (data[0] as ReadonlyMap<string, TMem> | undefined) ?? new Map<string, TMem>();\n\t\t\t\tconst nowNs = monotonicNs();\n\t\t\t\tconst toAdd: string[] = [];\n\t\t\t\tfor (const key of map.keys()) {\n\t\t\t\t\tif (!entryCreatedAtNsRef.has(key)) toAdd.push(key);\n\t\t\t\t}\n\t\t\t\tif (toAdd.length > 0) {\n\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\tfor (const key of toAdd) entryCreatedAtNsRef.set(key, nowNs);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ name: \"entryCreatedAtNs/sync\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(syncCreatedAt, { name: \"entryCreatedAtNs/sync\" });\n\t\tthis.addDisposer(keepalive(syncCreatedAt));\n\n\t\t// GC entryCreatedAtNs entries that no longer exist in the active store.\n\t\t// (Adds happen via the syncCreatedAt effect above; removals piggyback\n\t\t// on the store-snapshot subscriber here so the map stays in sync.)\n\t\tconst entriesUnsub = this.store.store.entries.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tconst map = m[1] as ReadonlyMap<string, TMem>;\n\t\t\t\tconst created = entryCreatedAtNsRef.entries.cache as\n\t\t\t\t\t| ReadonlyMap<string, number>\n\t\t\t\t\t| undefined;\n\t\t\t\tif (created == null) continue;\n\t\t\t\tconst toDelete: string[] = [];\n\t\t\t\tfor (const key of created.keys()) {\n\t\t\t\t\tif (!map.has(key)) toDelete.push(key);\n\t\t\t\t}\n\t\t\t\tif (toDelete.length > 0) {\n\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\tfor (const key of toDelete) entryCreatedAtNsRef.delete(key);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthis.addDisposer(entriesUnsub);\n\n\t\t// Permanent-promotion effect. Writes to `permanent` collection +\n\t\t// `permanentKeys` (NOT to the active store), so no §7 cycle: the effect's\n\t\t// dep is `store.store.entries`, but it doesn't write back to that node.\n\t\tconst promoter = node(\n\t\t\t[this.store.store.entries],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst map = (data[0] as ReadonlyMap<string, TMem> | undefined) ?? new Map<string, TMem>();\n\t\t\t\tfor (const [key, mem] of map) {\n\t\t\t\t\tif (permanentKeysRef.has(key)) continue;\n\t\t\t\t\tif (permanentFilter(key, mem)) {\n\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\tmarkPermanent(key, mem);\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\t{ name: \"promoter\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(promoter, { name: \"promoter\" });\n\t\tthis.addDisposer(keepalive(promoter));\n\n\t\tlet archiveHandle: StorageHandle | null = null;\n\t\tif (opts.archiveTier) {\n\t\t\tarchiveHandle = this.attachSnapshotStorage(\n\t\t\t\t[{ snapshot: opts.archiveTier }],\n\t\t\t\topts.archiveStorageOptions ?? {},\n\t\t\t);\n\t\t\tthis.addDisposer(() => archiveHandle?.dispose());\n\t\t}\n\n\t\tthis.tiers = {\n\t\t\tpermanent: this.permanent,\n\t\t\tactiveEntries: this.store.store.entries,\n\t\t\tarchiveHandle,\n\t\t\ttierOf,\n\t\t\tmarkPermanent,\n\t\t};\n\t}\n}\n\n/**\n * Attach 3-tier storage (active / archived / permanent) over a fresh distill\n * store. Returns a `MemoryWithTiersGraph` whose `store` and `tiers` fields\n * mirror the previous bundle shape.\n *\n * **API shape** (Class B audit, 2026-04-30 — breaking change vs.\n * pre-migration): the factory takes a single opts bag including `source`\n * and `extractFn`. The bundle is exposed as `result.store` for downstream\n * composers (vectors / KG / retrieval).\n *\n * - `permanentFilter`-matching entries score `Infinity` in retention →\n * never archived. Independent permanent-promotion effect upserts them\n * into the `permanent` collection.\n * - Below-threshold entries → retention archives synchronously.\n * - Over-`maxActive` entries → retention's `maxSize` evicts lowest-scored.\n */\nexport function memoryWithTiers<TRaw, TMem>(\n\topts: MemoryWithTiersOptions<TRaw, TMem>,\n): MemoryWithTiersGraph<TRaw, TMem> {\n\treturn new MemoryWithTiersGraph<TRaw, TMem>(opts);\n}\n\n// ---------------------------------------------------------------------------\n// memoryRetrieval\n// ---------------------------------------------------------------------------\n\nexport interface MemoryRetrievalOptions<TMem> {\n\t/** Optional Graph identity. */\n\tgraph?: GraphOptions;\n\t/** Subgraph name. Default: `\"memory-retrieval\"`. */\n\tname?: string;\n\t/** The substrate distill store. */\n\tstore: DistillBundle<TMem>;\n\t/** Optional vector index for similarity search. */\n\tvectors?: VectorIndexGraph<TMem> | null;\n\t/** Optional knowledge graph for entity-relation expansion. */\n\tkg?: KnowledgeGraph<unknown, string> | null;\n\t/** Score function (same shape as `agentMemory.score`). */\n\tscore: (mem: TMem, context: unknown) => number;\n\t/** Cost function for budget packing. */\n\tcost: (mem: TMem) => number;\n\t/** Token / cost budget. Default 2000. */\n\tbudget?: number;\n\t/** Top-K vector candidates. Default 20. */\n\ttopK?: number;\n\t/** KG expansion depth in hops. Default 1. */\n\tgraphDepth?: number;\n\t/** Hierarchical-context boost weight. Default 0. */\n\tcontextWeight?: number;\n\t/** Hierarchical-context accessor for entries. */\n\tcontextOf?: (mem: TMem) => readonly string[] | undefined;\n\t/** Optional reactive context node (passed to `score`). */\n\tcontext?: NodeInput<unknown>;\n}\n\nfunction sharedPrefixDepth(\n\tq: readonly string[] | undefined,\n\te: readonly string[] | undefined,\n): number {\n\tif (!q || !e) return 0;\n\tconst n = Math.min(q.length, e.length);\n\tlet i = 0;\n\twhile (i < n && q[i] === e[i]) i++;\n\treturn i;\n}\n\n// QA-fix: element-wise reference-equality dedup so subscribers don't wake\n// up when an identical packed array lands (runRetrieval allocates a new\n// outer array reference every call).\nconst packedEquals = <T>(a: readonly T[], b: readonly T[]): boolean => {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;\n\treturn true;\n};\n\n/**\n * Graph subclass that builds the retrieval pipeline (vector + KG + budget\n * packing) over a `DistillBundle` and optional vectors / kg substrates.\n *\n * **C1 rework (2026-04-30):** retrieval is reactive-only. Each\n * `retrieveReactive(input)` call constructs its own per-input subgraph\n * mounted at `retrieve_${id}` with named nodes `context`, `result`, and\n * `projection`. Subgraphs register their own scoped disposers so teardown\n * is local to the per-call mount.\n *\n * **QA F-9 (2026-04-30):** the shared `retrieval` / `retrievalTrace`\n * state-node mirrors are dropped — they were last-writer-wins under\n * concurrent `retrieveReactive(...)` calls. Consumers must subscribe to\n * the per-call `projection` node directly. One-shot consumers use\n * `awaitSettled(retrieveReactive(input))`.\n *\n * **QA F-6 (2026-04-30):** the per-call `result` derived declares\n * `vectors.entries` / `kg.adjacencyOut` / `kg.adjacencyIn` as deps when\n * configured, so a vector upsert / KG mutation re-runs retrieval even\n * when the query / context / store-snapshot are unchanged. Resolves the\n * §28 closure-mirror gap where these `.cache` reads were undeclared.\n */\nexport class MemoryRetrievalGraph<TMem> extends Graph {\n\tprivate readonly _store: DistillBundle<TMem>;\n\tprivate readonly _vectors: VectorIndexGraph<TMem> | null;\n\tprivate readonly _kg: KnowledgeGraph<unknown, string> | null;\n\tprivate readonly _opts: MemoryRetrievalOptions<TMem>;\n\tprivate readonly _contextNode: Node<unknown>;\n\tprivate readonly _topK: number;\n\tprivate readonly _graphDepth: number;\n\tprivate readonly _budget: number;\n\tprivate readonly _contextWeight: number;\n\tprivate _retrieveSeq = 0;\n\n\tconstructor(opts: MemoryRetrievalOptions<TMem>) {\n\t\tsuper(opts.name ?? \"memory-retrieval\", opts.graph);\n\n\t\tthis._store = opts.store;\n\t\tthis._vectors = opts.vectors ?? null;\n\t\tthis._kg = opts.kg ?? null;\n\t\tthis._opts = opts;\n\t\tthis._topK = opts.topK ?? 20;\n\t\tthis._graphDepth = opts.graphDepth ?? 1;\n\t\tthis._budget = opts.budget ?? 2000;\n\t\tthis._contextWeight = opts.contextWeight ?? 0;\n\t\t// DS-13.5.C: synthesized branch (no `opts.context` supplied) registers\n\t\t// on this graph as `_context` so describe()/explain() can walk to it.\n\t\t// User-supplied branch stays unregistered — `fromAny` returns the\n\t\t// caller's owned Node, which is owned by their graph; mounting it\n\t\t// here would corrupt cross-graph ownership (mirrors MemoryWithTiers's\n\t\t// context-branch policy).\n\t\tif (opts.context) {\n\t\t\tthis._contextNode = fromAny(opts.context);\n\t\t} else {\n\t\t\tthis._contextNode = this.state<unknown>(\"_context\", null);\n\t\t}\n\t}\n\n\tprivate _runRetrieval(\n\t\tstoreMap: ReadonlyMap<string, TMem>,\n\t\tctx: unknown,\n\t\tquery: RetrievalQuery,\n\t): { packed: RetrievalEntry<TMem>[]; trace: RetrievalTrace<TMem> } {\n\t\tconst opts = this._opts;\n\t\tconst candidateMap = new Map<\n\t\t\tstring,\n\t\t\t{ value: TMem; sources: Set<\"vector\" | \"graph\" | \"store\"> }\n\t\t>();\n\n\t\tlet vectorCandidates: VectorSearchResult<TMem>[] = [];\n\t\tif (this._vectors && query.vector) {\n\t\t\t// Wave A migrated `vectorIndex` to a reactive-only read API\n\t\t\t// (`searchNode`); inline the equivalent flat-cosine snapshot scan\n\t\t\t// here since `_runRetrieval` is sync and `searchNode` is async-shaped.\n\t\t\t// `patterns/ai/memory/` is queued for its own audit per the Wave A\n\t\t\t// session doc § D.1.\n\t\t\tconst q = query.vector;\n\t\t\tconst snapshot = this._vectors.entries.cache as\n\t\t\t\t| ReadonlyMap<string, VectorRecord<TMem>>\n\t\t\t\t| undefined;\n\t\t\tif (snapshot && snapshot.size > 0 && this._topK > 0) {\n\t\t\t\tconst scored = [...snapshot.values()]\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(row): VectorSearchResult<TMem> => ({\n\t\t\t\t\t\t\tid: row.id,\n\t\t\t\t\t\t\tscore: cosineSimilarity(q, row.vector),\n\t\t\t\t\t\t\t...(row.meta !== undefined ? { meta: row.meta } : {}),\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t\t.sort((a, b) => b.score - a.score)\n\t\t\t\t\t.slice(0, this._topK);\n\t\t\t\tvectorCandidates = scored;\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) candidateMap.set(vc.id, { value: mem, sources: new Set([\"vector\"]) });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst graphExpanded: string[] = [];\n\t\tif (this._kg) {\n\t\t\t// Wave A migrated `knowledgeGraph` to a reactive-only `relatedNode`\n\t\t\t// API; inline the equivalent adjacency-snapshot scan here for the\n\t\t\t// sync expansion. `adjacencyOut` / `adjacencyIn` are kept warm by\n\t\t\t// the kg's own internal keepalive disposers, so `.cache` is always\n\t\t\t// populated post-construction.\n\t\t\tconst adjOut = this._kg.adjacencyOut.cache as\n\t\t\t\t| ReadonlyMap<string, readonly KnowledgeEdge<string>[]>\n\t\t\t\t| undefined;\n\t\t\tconst adjIn = this._kg.adjacencyIn.cache as\n\t\t\t\t| ReadonlyMap<string, readonly KnowledgeEdge<string>[]>\n\t\t\t\t| undefined;\n\t\t\tconst seedIds = [...(query.entityIds ?? []), ...[...candidateMap.keys()]];\n\t\t\tconst visited = new Set<string>();\n\t\t\tlet frontier = seedIds;\n\t\t\tfor (let depth = 0; depth < this._graphDepth; depth++) {\n\t\t\t\tconst nextFrontier: string[] = [];\n\t\t\t\tfor (const id of frontier) {\n\t\t\t\t\tif (visited.has(id)) continue;\n\t\t\t\t\tvisited.add(id);\n\t\t\t\t\tconst outEdges = adjOut?.get(id) ?? [];\n\t\t\t\t\tconst inEdges = adjIn?.get(id) ?? [];\n\t\t\t\t\tfor (const edge of outEdges) {\n\t\t\t\t\t\tconst targetId = edge.to;\n\t\t\t\t\t\tif (!visited.has(targetId)) {\n\t\t\t\t\t\t\tnextFrontier.push(targetId);\n\t\t\t\t\t\t\tconst mem = storeMap.get(targetId);\n\t\t\t\t\t\t\tif (mem) {\n\t\t\t\t\t\t\t\tconst existing = candidateMap.get(targetId);\n\t\t\t\t\t\t\t\tif (existing) existing.sources.add(\"graph\");\n\t\t\t\t\t\t\t\telse candidateMap.set(targetId, { value: mem, sources: new Set([\"graph\"]) });\n\t\t\t\t\t\t\t\tgraphExpanded.push(targetId);\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\t// Inbound edges: traverse to the `from` side. Match the\n\t\t\t\t\t// previous `kg.related(id)` semantics, which returned both\n\t\t\t\t\t// `from === id` and `to === id` matches.\n\t\t\t\t\tfor (const edge of inEdges) {\n\t\t\t\t\t\tconst targetId = edge.from;\n\t\t\t\t\t\tif (!visited.has(targetId)) {\n\t\t\t\t\t\t\tnextFrontier.push(targetId);\n\t\t\t\t\t\t\tconst mem = storeMap.get(targetId);\n\t\t\t\t\t\t\tif (mem) {\n\t\t\t\t\t\t\t\tconst existing = candidateMap.get(targetId);\n\t\t\t\t\t\t\t\tif (existing) existing.sources.add(\"graph\");\n\t\t\t\t\t\t\t\telse candidateMap.set(targetId, { value: mem, sources: new Set([\"graph\"]) });\n\t\t\t\t\t\t\t\tgraphExpanded.push(targetId);\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\tfrontier = nextFrontier;\n\t\t\t}\n\t\t}\n\t\tfor (const [key, mem] of storeMap) {\n\t\t\tif (!candidateMap.has(key)) {\n\t\t\t\tcandidateMap.set(key, { value: mem, sources: new Set([\"store\"]) });\n\t\t\t}\n\t\t}\n\n\t\tconst qDepth = query.context?.length ?? 0;\n\t\tconst ranked: RetrievalEntry<TMem>[] = [];\n\t\tfor (const [key, { value, sources }] of candidateMap) {\n\t\t\tconst entryContext = opts.contextOf ? opts.contextOf(value) : undefined;\n\t\t\tlet score = opts.score(value, ctx);\n\t\t\tif (this._contextWeight > 0 && qDepth > 0) {\n\t\t\t\tconst shared = sharedPrefixDepth(query.context, entryContext);\n\t\t\t\tif (shared > 0) score = score * (1 + (this._contextWeight * shared) / qDepth);\n\t\t\t}\n\t\t\tconst entry: RetrievalEntry<TMem> = entryContext\n\t\t\t\t? { key, value, score, sources: [...sources], context: entryContext }\n\t\t\t\t: { key, value, score, sources: [...sources] };\n\t\t\tranked.push(entry);\n\t\t}\n\t\tranked.sort((a, b) => b.score - a.score);\n\n\t\tconst packed: RetrievalEntry<TMem>[] = [];\n\t\tlet usedBudget = 0;\n\t\tfor (const entry of ranked) {\n\t\t\tconst c = opts.cost(entry.value);\n\t\t\tif (usedBudget + c > this._budget && packed.length > 0) break;\n\t\t\tpacked.push(entry);\n\t\t\tusedBudget += c;\n\t\t}\n\n\t\treturn { packed, trace: { vectorCandidates, graphExpanded, ranked, packed } };\n\t}\n\n\t/**\n\t * Reactive consumer API — chain into the graph.\n\t *\n\t * Each call constructs its own per-input subgraph mounted at\n\t * `retrieve_${id}` (auto-incrementing within this MemoryRetrievalGraph\n\t * instance) with named nodes:\n\t *\n\t * - `context` — `fromAny(queryInput)` projection (so the input node is\n\t * visible to `describe()` even when callers pass a raw value).\n\t * - `result` — pure derived `{ packed, trace }`.\n\t * - `projection` — the packed-array node returned to the caller.\n\t *\n\t * `result` declares the substrate's `store.entries`, the optional\n\t * `context` Node, the local `context` projection, and (when configured)\n\t * `vectors.entries` / `kg.adjacencyOut` / `kg.adjacencyIn` as deps —\n\t * so vector upserts and KG mutations re-trigger retrieval even when\n\t * the input is unchanged.\n\t *\n\t * **Lifecycle contract (DS-13.5.C, 2026-05-01).** The per-call subgraph\n\t * stays mounted while the returned `projection` has at least one\n\t * subscriber. When the last subscriber unsubscribes, projection's\n\t * `deactivate` cleanup hook fires (canonical \"last unsubscribe\" signal\n\t * via the existing `NodeFnCleanup.onDeactivation` protocol), which calls\n\t * `parent.remove(retrieve_${id})` and tears the per-call topology\n\t * down via TEARDOWN cascade (post-DS-13.5.A Q16, COMPLETE auto-precedes).\n\t *\n\t * **Single-shot lifecycle.** This auto-unmount is keyed to the FIRST\n\t * last-unsubscribe event — projection is non-resubscribable from the\n\t * caller's perspective. Callers who need to subscribe / unsubscribe /\n\t * re-subscribe should hold a long-lived subscription externally (e.g.\n\t * `keepalive(projection)`) or call `retrieveReactive(...)` again to\n\t * mount a fresh per-call subgraph.\n\t *\n\t * **Caller obligation.** Either subscribe to `projection` (and\n\t * eventually unsubscribe to trigger cleanup) OR drop the returned\n\t * reference without subscribing — in the no-subscribe case the\n\t * subgraph is dormant (no compute fires) and a parent `destroy()`\n\t * cascade reclaims it. Holding `projection` without subscribing AND\n\t * without ever destroying the parent is the leak case the JSDoc above\n\t * the C1 rework covers.\n\t *\n\t * One-shot callers use `awaitSettled(retrieveReactive(input))`.\n\t */\n\tretrieveReactive(\n\t\tqueryInput: NodeInput<RetrievalQuery | null>,\n\t): Node<ReadonlyArray<RetrievalEntry<TMem>>> {\n\t\tconst id = ++this._retrieveSeq;\n\t\tconst segment = `retrieve_${id}`;\n\n\t\t// Per-call subgraph — owns the wiring, the keepalive, and the\n\t\t// teardown. Mounted on `this` so it's visible in `describe()` and\n\t\t// reachable via `${parent}::retrieve_${id}::result` etc.\n\t\tconst sub = new Graph(segment);\n\n\t\t// Wrap the input as a local pass-through so the per-call subgraph\n\t\t// shows the query source in `describe()` regardless of where the\n\t\t// caller's node lives in the broader topology. `fromAny` returns\n\t\t// the original Node when given a Node, otherwise wraps a\n\t\t// value/promise into a producer.\n\t\t//\n\t\t// DS-13.5.C: registered via `sub.derived(...)` (Graph helper) for\n\t\t// equals plumbing + automatic registration; replaces the prior raw\n\t\t// `node([inputNode], fn) + sub.add(...)` shape.\n\t\tconst inputNode = fromAny(queryInput);\n\t\tconst localContext = sub.derived<RetrievalQuery | null>(\n\t\t\t\"context\",\n\t\t\t[inputNode],\n\t\t\t(batchData, ctx) => {\n\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\treturn [(data[0] as RetrievalQuery | null) ?? null];\n\t\t\t},\n\t\t\t{\n\t\t\t\tmeta: aiMeta(\"retrieval_query_input\"),\n\t\t\t\tinitial: null,\n\t\t\t},\n\t\t);\n\n\t\t// /qa F-6 (2026-04-30): declare vectors / kg substrate Node refs as\n\t\t// deps so vector upserts / KG mutations re-trigger retrieval even\n\t\t// when query / context / store snapshots are unchanged. The\n\t\t// `_runRetrieval` body reads `.cache` from these substrates; before\n\t\t// this fix those reads were undeclared §28 closure-mirrors.\n\t\tconst resultDeps: (string | Node<unknown>)[] = [\n\t\t\tthis._store.store.entries,\n\t\t\tthis._contextNode,\n\t\t\tlocalContext,\n\t\t];\n\t\tif (this._vectors) resultDeps.push(this._vectors.entries as Node<unknown>);\n\t\tif (this._kg) {\n\t\t\tresultDeps.push(this._kg.adjacencyOut as Node<unknown>);\n\t\t\tresultDeps.push(this._kg.adjacencyIn as Node<unknown>);\n\t\t}\n\n\t\t// DS-13.5.C: migrated to `sub.derived(...)` for equals plumbing +\n\t\t// automatic registration.\n\t\tconst result = sub.derived<{\n\t\t\tpacked: ReadonlyArray<RetrievalEntry<TMem>>;\n\t\t\ttrace: RetrievalTrace<TMem> | null;\n\t\t}>(\n\t\t\t\"result\",\n\t\t\tresultDeps,\n\t\t\t(batchData, ctx) => {\n\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst query = data[2];\n\t\t\t\tif (query == null) {\n\t\t\t\t\treturn [{ packed: [] as ReadonlyArray<RetrievalEntry<TMem>>, trace: null }];\n\t\t\t\t}\n\t\t\t\tconst storeMap =\n\t\t\t\t\t(data[0] as ReadonlyMap<string, TMem> | undefined) ?? new Map<string, TMem>();\n\t\t\t\tconst { packed, trace } = this._runRetrieval(storeMap, data[1], query as RetrievalQuery);\n\t\t\t\treturn [{ packed, trace }];\n\t\t\t},\n\t\t\t{\n\t\t\t\tmeta: aiMeta(\"retrieval_reactive_result\"),\n\t\t\t\tinitial: { packed: [] as ReadonlyArray<RetrievalEntry<TMem>>, trace: null },\n\t\t\t},\n\t\t);\n\n\t\t// DS-13.5.C: projection stays as raw `node()` (not `sub.derived`)\n\t\t// because the keepalive disposer is wired via the fn's\n\t\t// `NodeFnCleanup.onDeactivation` hook — projection's cleanup-on-last-\n\t\t// unsubscribe is what drives `parent.remove(segment)`. The Graph\n\t\t// `.derived()` helper drops the cleanup return, so the raw form\n\t\t// is required here. `equals: packedEquals` is preserved verbatim.\n\t\tconst projection = node<ReadonlyArray<RetrievalEntry<TMem>>>(\n\t\t\t[result],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tactions.emit((data[0] as { packed: ReadonlyArray<RetrievalEntry<TMem>> }).packed);\n\t\t\t\treturn {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\t// Auto-unmount on last unsubscribe (DS-13.5.C).\n\t\t\t\t\t\t// Idempotent: try/catch covers the case where the\n\t\t\t\t\t\t// segment was already removed (e.g. parent destroy\n\t\t\t\t\t\t// cascade ran first, or the caller called remove()\n\t\t\t\t\t\t// manually).\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tthis.remove(segment);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* best-effort cleanup */\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\t{\n\t\t\t\tname: \"projection\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"retrieval_reactive\"),\n\t\t\t\tinitial: [] as ReadonlyArray<RetrievalEntry<TMem>>,\n\t\t\t\tequals: packedEquals,\n\t\t\t},\n\t\t);\n\t\tsub.add(projection, { name: \"projection\" });\n\n\t\tthis.mount(segment, sub);\n\t\treturn projection;\n\t}\n}\n\n/**\n * Build the retrieval pipeline (vector + KG + budget packing) over a\n * `DistillBundle` and optional `vectors` / `kg` substrates. Returns a\n * `MemoryRetrievalGraph` exposing `retrieval` / `retrievalTrace` reactive\n * state and the `retrieveReactive(input)` consumer method.\n */\nexport function memoryRetrieval<TMem>(\n\topts: MemoryRetrievalOptions<TMem>,\n): MemoryRetrievalGraph<TMem> {\n\treturn new MemoryRetrievalGraph<TMem>(opts);\n}\n","/**\n * Budget-constrained reactive memory composition (roadmap §3.2b).\n *\n * Moved to base/composition/distill.ts during cleave A2.\n */\n\nimport { batch, factoryTag, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport {\n\tfromAny,\n\ttype NodeInput,\n\ttype ReactiveMapBundle,\n\ttype ReactiveMapOptions,\n\treactiveMap,\n\tswitchMap,\n\twithLatestFrom,\n} from \"@graphrefly/pure-ts/extra\";\nimport { forEach } from \"../sources/async.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\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\n/**\n * Defensive snapshot → ReadonlyMap coercion (D2 /qa lock, Tier 9.1).\n *\n * `ReactiveMapBundle.entries` always emits a real `Map` on the live emit\n * path. The non-Map case happens on snapshot **restore**: the default\n * `JsonGraphCodec` serializes a `Map` to `null`/`{}`/`[]` depending on the\n * codec configuration, and `Graph.restore` writes that decoded value back\n * to the cache. A naive `(snapshot as ReadonlyMap) ?? new Map()` would\n * pass a plain object through and then `.entries()` / `.size` access would\n * silently yield wrong results (or throw). The runtime `instanceof Map`\n * check below restores the safety net the previous `mapFromSnapshot` helper\n * provided before its initial deletion in Tier 10.1.\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 *\n * **Tier 1.5.4 (Session A.5 lock, 2026-04-27):** `extractFn` receives the\n * source and existing-store as `Node`s. Distill calls `extractFn` ONCE at\n * wiring time and consumes the returned stream of extractions. The user\n * controls reactive composition — wrap with `switchMap` for cancel-on-new-input,\n * `mergeMap` for parallel, `derived` for sync transforms. See COMPOSITION-GUIDE\n * §40 for the recipe.\n */\nexport function distill<TRaw, TMem>(\n\tsource: NodeInput<TRaw>,\n\textractFn: (\n\t\traw: Node<TRaw>,\n\t\texisting: Node<ReadonlyMap<string, TMem>>,\n\t) => 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) : node<unknown>([], { initial: null });\n\n\t// `latestStore` (formerly a §28 closure-mirror) is no longer needed —\n\t// Phase 10.5 (`withLatestFrom` flipped to `partial: false`) fixed the\n\t// W1 initial-pair drop. `consolidate` now uses\n\t// `withLatestFrom(trigger, store.entries)` below to pair each trigger\n\t// with the latest store snapshot via a real reactive edge (visible in\n\t// `describe()`). The `mapFromSnapshot` transform runs inside the\n\t// switchMap fn body.\n\n\t// Tier 1.5.4: one-shot wire. User's `extractFn` returns the reactive\n\t// extraction stream — distill just `forEach`s and applies. No internal\n\t// switchMap; user picks the cancellation / queueing semantics.\n\tconst extractionStream = fromAny(\n\t\textractFn(sourceNode, store.entries as Node<ReadonlyMap<string, TMem>>),\n\t);\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 = node<string[]>(\n\t\t\t[store.entries],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst batch0 = batchData[0];\n\t\t\t\tconst snapshot = batch0 != null && batch0.length > 0 ? batch0.at(-1) : ctx.prevData[0];\n\t\t\t\tconst out: string[] = [];\n\t\t\t\tconst entries = mapFromSnapshot<TMem>(snapshot);\n\t\t\t\t// Clean up verdict subscriptions for removed keys.\n\t\t\t\tfor (const key of verdictUnsubs.keys()) {\n\t\t\t\t\tif (!entries.has(key)) {\n\t\t\t\t\t\tverdictUnsubs.get(key)!();\n\t\t\t\t\t\tverdictUnsubs.delete(key);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (const [key, mem] of entries) {\n\t\t\t\t\tconst verdict = opts.evict!(key, mem);\n\t\t\t\t\tif (isNodeLike<boolean>(verdict)) {\n\t\t\t\t\t\t// Subscribe if not already — push-on-subscribe fires with\n\t\t\t\t\t\t// the verdict's current value on first subscribe, so an\n\t\t\t\t\t\t// already-true verdict deletes via the callback without\n\t\t\t\t\t\t// needing a `verdict.cache` read (closes P3 audit #3).\n\t\t\t\t\t\t// Future transitions to `true` flow through the same path.\n\t\t\t\t\t\tif (!verdictUnsubs.has(key)) {\n\t\t\t\t\t\t\tconst unsub = forEach(verdict, (val) => {\n\t\t\t\t\t\t\t\tif (val === true && store.has(key)) {\n\t\t\t\t\t\t\t\t\tstore.delete(key);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tverdictUnsubs.set(key, unsub);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof verdict === \"boolean\") {\n\t\t\t\t\t\tif (verdict) out.push(key);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tthrow new TypeError(\"distill evict() must return boolean or Node<boolean>\");\n\t\t\t\t}\n\t\t\t\tactions.emit(out);\n\t\t\t},\n\t\t\t{ describeKind: \"derived\" },\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 consolidatePaired = withLatestFrom(\n\t\t\tconsolidateTriggerNode,\n\t\t\tstore.entries as Node<unknown>,\n\t\t);\n\t\tconst consolidationStream = switchMap(consolidatePaired, ([, entries]) =>\n\t\t\topts.consolidate!(mapFromSnapshot<TMem>(entries)),\n\t\t);\n\t\tforEach(consolidationStream, (extraction) => {\n\t\t\tapplyExtraction(store, extraction);\n\t\t});\n\t}\n\n\tconst compact = node<Array<{ key: string; value: TMem; score: number }>>(\n\t\t[store.entries, contextNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst snapshot = data[0];\n\t\t\tconst context = data[1];\n\t\t\tconst map = mapFromSnapshot<TMem>(snapshot);\n\t\t\tconst entries = [...map.entries()].map(([key, value]) => ({\n\t\t\t\tkey,\n\t\t\t\tvalue,\n\t\t\t\tscore: opts.score(value, context),\n\t\t\t\tcost: opts.cost(value),\n\t\t\t}));\n\t\t\tentries.sort((a, b) => b.score - a.score);\n\n\t\t\tconst packed: Array<{ key: string; value: TMem; score: number }> = [];\n\t\t\tlet remaining = budget;\n\t\t\tfor (const item of entries) {\n\t\t\t\tif (item.cost <= remaining) {\n\t\t\t\t\tpacked.push({ key: item.key, value: item.value, score: item.score });\n\t\t\t\t\tremaining -= item.cost;\n\t\t\t\t}\n\t\t\t}\n\t\t\tactions.emit(packed);\n\t\t},\n\t\t{ describeKind: \"derived\", meta: { ...factoryTag(\"distill\", { budget }) } },\n\t);\n\n\tconst size = node<number>(\n\t\t[store.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst batch0 = batchData[0];\n\t\t\tconst snapshot = batch0 != null && batch0.length > 0 ? batch0.at(-1) : ctx.prevData[0];\n\t\t\tactions.emit(mapFromSnapshot<TMem>(snapshot).size);\n\t\t},\n\t\t{ describeKind: \"derived\" },\n\t);\n\tkeepalive(compact);\n\tkeepalive(size);\n\n\treturn { store, compact, size };\n}\n","/**\n * Async sources, sinks, and multicast — presentation layer.\n *\n * `fromPromise`, `fromAsyncIter`, `fromAny` are substrate primitives; they are\n * re-exported here from `@graphrefly/pure-ts` for ergonomic single-import use.\n * This file owns the presentation-only async utilities: `defer`, `forEach`,\n * `toArray`, `share`, `replay`, `cached`, `shareReplay`.\n *\n * `singleFromAny` and `singleNodeFromAny` (keyed singleflight) live in\n * `base/composition/single-from-any.ts`.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tERROR,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n\tRESOLVED,\n\tSTART,\n} from \"@graphrefly/pure-ts/core\";\nimport { type AsyncSourceOpts, type NodeInput, sourceOpts } from \"@graphrefly/pure-ts/extra\";\n\n/** Options for presentation-layer async operators: NodeOptions without `describeKind`. */\ntype ExtraOpts = Omit<NodeOptions, \"describeKind\">;\n\n// Import fromAny from substrate — used internally by defer. The three async\n// substrate sources (fromAny, fromAsyncIter, fromPromise) are already\n// re-exported from @graphrefly/pure-ts; do NOT re-export here to avoid\n// duplicate-export conflicts at the root barrel level.\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\n\n/**\n * Lazily constructs a {@link Node} from a thunk that runs at **activation\n * time** (first subscriber after a teardown to zero sinks), not factory time.\n *\n * **Resubscribable by default.** Diverges from `fromPromise` / `fromIter` /\n * `fromAsyncIter` (which are single-shot — second subscriber sees the cached\n * terminal value). `defer`'s contract matches RxJS `defer`: every fresh\n * activation cycle re-runs the thunk. To opt out and get one-shot semantics,\n * pass `{ resubscribable: false }`.\n *\n * **Sharing across overlapping subscribers.** The thunk only re-runs on a\n * fresh activation cycle (zero → one sink). Overlapping subscribers share\n * the single activation; the thunk does NOT re-run for each subscriber. If\n * the thunk returns an existing `Node`, that Node is shared across activations\n * — `defer` will subscribe to it on each activation but does not isolate state\n * across subscribers. For per-subscriber isolation, the thunk must construct\n * a fresh source (`state(...)`, `fromPromise(fetch(...))`, etc.) on each call.\n *\n * **Use cases:**\n * - Lazy upstream construction (avoid eager evaluation of expensive factories\n * at module load — the thunk runs only when something subscribes).\n * - Per-activation resource construction (open a connection / file handle on\n * subscribe, when paired with full teardown between sessions).\n * - Bridging non-Node inputs (Promise, AsyncIterable, Iterable, scalar) into\n * the graph behind a lazy boundary.\n *\n * The thunk's return value is bridged via {@link fromAny}. Errors thrown by\n * the thunk surface as a single `[[ERROR, err]]` on the output (with `err`\n * coerced to a non-`undefined` value to satisfy spec §1.3 — bare `throw` and\n * `throw undefined` are wrapped in a `defer: thunk threw undefined` Error).\n *\n * Upstream messages are forwarded transparently (DIRTY / DATA / RESOLVED /\n * COMPLETE / ERROR / INVALIDATE / PAUSE / RESUME / TEARDOWN), preserving\n * batch boundaries. The producer's own `START` handshake is delivered to\n * subscribers automatically; the upstream's `START` is filtered.\n *\n * @param thunk - Called on each activation; returns the upstream input.\n * @param opts - Forwarded to `fromAny` (e.g. `signal` for async inputs).\n * `signal` is only consumed by `fromAny` for async input shapes (Promise,\n * AsyncIterable); it does NOT abort a Node-input or scalar-input defer.\n * @returns `Node<T>` — lazy upstream-on-activation.\n *\n * @example\n * ```ts\n * import { defer } from \"@graphrefly/graphrefly-ts\";\n *\n * // Lazy fetch — runs on the first activation, NOT at factory time.\n * // Each fresh activation cycle (after teardown) re-runs the thunk →\n * // a new fetch. Overlapping subscribers share the single activation.\n * const live = defer(() => fetch(\"/api/feed\").then((r) => r.json()));\n * ```\n *\n * @category extra\n */\nexport function defer<T>(thunk: () => NodeInput<T>, opts?: AsyncSourceOpts): Node<T> {\n\t// A4: strip `signal` before forwarding to NodeOptions — sibling sources\n\t// (fromTimer / fromPromise / fromAsyncIter) destructure first; signal\n\t// continues to flow into fromAny(input, opts) for async input shapes.\n\tconst { signal: _sig, ...nodeOpts } = (opts ?? {}) as AsyncSourceOpts;\n\tconst sOpts = sourceOpts<T>(nodeOpts);\n\tconst merged = sOpts.resubscribable === undefined ? { ...sOpts, resubscribable: true } : sOpts;\n\treturn node<T>((_data, a) => {\n\t\tlet unsub: (() => void) | undefined;\n\t\tlet stopped = false;\n\t\ttry {\n\t\t\tconst input = thunk();\n\t\t\t// `iter: true` preserves defer's RxJS-aligned per-element\n\t\t\t// streaming for sync iterable thunk returns (post DS-13.5\n\t\t\t// fromAny default flip; defer's documented contract is\n\t\t\t// \"forwards iterable values\" per-element).\n\t\t\tconst src = fromAny(input, { ...opts, iter: true });\n\t\t\tunsub = src.subscribe((msgs) => {\n\t\t\t\tif (stopped) return;\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tconst t = m[0];\n\t\t\t\t\tif (t === START) continue; // producer's own START is delivered separately\n\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t} else if (t === COMPLETE) {\n\t\t\t\t\t\tstopped = true;\n\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\tbreak; // A2: don't forward post-terminal messages in the same batch\n\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\tstopped = true;\n\t\t\t\t\t\ta.down([[ERROR, m[1]]]);\n\t\t\t\t\t\tbreak; // A2\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Forward DIRTY / RESOLVED / INVALIDATE / PAUSE / RESUME /\n\t\t\t\t\t\t// TEARDOWN, plus any unknown types (spec §1.3.6 forward-compat).\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} catch (err) {\n\t\t\t// A5: spec §1.3 — ERROR payload must not be undefined. Wrap a\n\t\t\t// `throw` or `throw undefined` so dispatch doesn't reject the emit.\n\t\t\tconst safe = err === undefined ? new Error(\"defer: thunk threw undefined\") : err;\n\t\t\ta.down([[ERROR, safe]]);\n\t\t}\n\t\treturn () => {\n\t\t\tstopped = true;\n\t\t\tunsub?.();\n\t\t};\n\t}, merged);\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\t// Lock 6.D (Phase 13.6.B): clear the accumulator buffer on\n\t// deactivation so a resubscribable toArray restarts with an empty\n\t// array on the next cycle — pre-flip this came for free via\n\t// `_deactivate`'s store wipe.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<T[]>(\n\t\t[source as Node],\n\t\t(data, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.buf;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\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 cleanup;\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\treturn cleanup;\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 node<T>(\n\t\t(_data, 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\t// Spec §2.5 / Lock 6.G: the built-in `replayBuffer` NodeOption retains the\n\t// last-N outgoing DATA and `defaultOnSubscribe` delivers them to a late\n\t// subscriber INSTEAD of the cache-DATA push — so there is no double-deliver\n\t// of the most-recent value. Supersedes the old `wrapSubscribeHook` +\n\t// manual-buffer pattern (which flushed the buffer AND then push-on-\n\t// subscribed the cache, double-delivering the last value).\n\treturn node<T>(\n\t\t(_data, 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, replayBuffer: bufferSize },\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// 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 * Pure exponential-decay utility (Tier 2.2 promotion from `patterns/memory/`).\n *\n * Used by `collection`, `agentMemory`, harness `strategy.ts`, and any\n * downstream consumer that needs decay-with-floor scoring. Promoted to\n * `extra/utils/` because the math has zero domain semantics and is reusable\n * by non-memory primitives (e.g. routing weight decay, retry-attempt aging).\n *\n * @module\n */\n\n/**\n * Default exponential-decay rate corresponding to a 7-day half-life.\n *\n * `Math.LN2 / (7 × 86_400)` ≈ `1.146e-6`. Imported by memory tiers + any\n * consumer that wants the same default cadence as `agentMemory`'s active\n * tier. Tier 4.4 (Wave AM Unit 1) — promoted from\n * `patterns/ai/memory/tiers.ts` so non-memory consumers can share the\n * canonical default without reaching across domains.\n */\nexport const DEFAULT_DECAY_RATE = Math.LN2 / (7 * 86_400);\n\n/**\n * Exponential decay with floor: `score = max(minScore, baseScore * exp(-ratePerSecond * ageSeconds))`.\n *\n * Tolerant fallbacks (deliberate for use inside reactive derived fns):\n * - non-finite `baseScore` → `minScore`\n * - non-positive `ageSeconds` (incl. clock skew) → `max(minScore, baseScore)` (no decay)\n * - non-positive `ratePerSecond` → `max(minScore, baseScore)` (no decay; rate=0 disables)\n *\n * Underflow boundary: `Math.exp(-745) === 0`. For very long ages × rates the\n * result clamps to `minScore`; if you need slow decay over years, choose a\n * smaller `ratePerSecond` rather than relying on graceful underflow.\n *\n * Half-life conversion: `ratePerSecond = Math.LN2 / halfLifeSeconds`.\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","/**\n * Memory patterns (roadmap §4.3) — public-face Phase-4 primitives audited under\n * `archive/docs/SESSION-public-face-blocks-review.md` (Wave A, locked 2026-04-25).\n *\n * Three primitives (the pure `decay` helper was promoted to `extra/utils/decay.ts`\n * per Tier 2.2 and is no longer re-exported here; `lightCollection` was folded\n * into `collection({ranked:false})` per Tier 2.3 and is no longer a separate\n * factory):\n * - {@link collection} / {@link CollectionGraph} — keyed memory store with\n * optional decay-aware ranking. Pass `{ ranked: false }` for the previous\n * `lightCollection` shape (Map + LRU + audit, no scoring).\n * - {@link vectorIndex} / {@link VectorIndexGraph} — reactive vector store with\n * optional HNSW backend, retention, and reactive {@link VectorIndexGraph.searchNode}.\n * - {@link knowledgeGraph} / {@link KnowledgeGraph} — entities + typed edges with\n * symmetric adjacency indexes and reactive {@link KnowledgeGraph.relatedNode}.\n *\n * **No imperative reads.** Per the API-style policy locked 2026-04-25, public-face\n * primitives expose reactive reads only — `itemNode` / `hasNode` / `searchNode` /\n * `relatedNode`. One-shot snapshots use `node.cache` after `awaitSettled`, or\n * `firstValueFrom(node)`.\n *\n * **Audit logs.** Every imperative mutation (`upsert / remove / clear / link /\n * unlink / rescore / reindex`) is wrapped via {@link mutate} and appends a\n * typed record to a public `events` log on the bundle / graph.\n *\n * @module\n */\n\nimport { monotonicNs, type Node, NodeImpl, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport type { ReactiveLogBundle } from \"@graphrefly/pure-ts/extra\";\nimport { fromTimer, keepalive, reactiveMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport {\n\ttype BaseAuditRecord,\n\tbumpCursor,\n\tcreateAuditLog,\n\tmutate,\n\tregisterCursor,\n} from \"../../base/mutation/index.js\";\nimport type { NodeOrValue } from \"../../base/resilience/_internal.js\";\nimport { decay } from \"../../base/utils/decay.js\";\n\n// ── Shared helpers ───────────────────────────────────────────────────────\n\nconst NS_PER_SEC = 1_000_000_000;\n\nfunction memoryMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"memory\", kind, extra);\n}\n\n/**\n * Coerce a value-or-Node argument into a `Node<T>`. Pass-through if already a\n * Node; otherwise wraps in `state(value, {name})`. Used by reactive read\n * factories (`itemNode` / `searchNode` / `relatedNode`) so callers can supply\n * a static value without manually creating a state node.\n *\n * Heuristic: anything that is a `NodeImpl` instance is a Node; everything else\n * is treated as a raw value to wrap.\n */\nfunction toNode<T>(v: T | Node<T>, name?: string): Node<T> {\n\tif (v instanceof NodeImpl) return v as Node<T>;\n\treturn node<T>([], { initial: v as T, ...(name ? { name } : undefined) });\n}\n\nfunction ageSeconds(now: number, lastNs: number): number {\n\treturn (now - lastNs) / NS_PER_SEC;\n}\n\n// `decay` was promoted to `extra/utils/decay.ts` per Tier 2.2 — it is no longer\n// re-exported from this module. Import from `@graphrefly/graphrefly/extra` (or\n// `../../extra/utils/decay.js` internally) instead.\n\n/**\n * Cosine similarity over `(a, b)`. When lengths differ, the shorter is\n * implicitly zero-padded to the longer length. Returns `0` if either vector\n * has zero norm. Public utility — used by {@link VectorIndexGraph.searchNode}\n * and exposed for downstream consumers (e.g. `patterns/ai/memory/`) that need\n * the same scoring at the boundary.\n *\n * **Numeric guards.** Returns `0` for non-finite results (overflow producing\n * `Infinity`/`NaN` from very-large vectors, or `NaN` propagating from any\n * `NaN`/`Infinity` component). Without this guard, downstream sort\n * comparators would order NaN-scored rows arbitrarily.\n *\n * **Depth.** This is a per-call computation; no internal caching. For very\n * large indexes (>10k) consider precomputing norms or using HNSW.\n *\n * @category memory\n */\nexport function 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\tconst score = dot / Math.sqrt(na * nb);\n\treturn Number.isFinite(score) ? score : 0;\n}\n\n/**\n * Equality predicate for {@link VectorIndexGraph.searchNode} results. Compares\n * `id` AND `score` AND `meta` reference per position so that score-only changes\n * (re-upsert with new vector keeping the same top-K order) propagate to\n * downstream subscribers. The previous id-only comparator silently dropped\n * those updates.\n */\nfunction searchResultsEqual<TMeta>(\n\ta: readonly VectorSearchResult<TMeta>[] | undefined,\n\tb: readonly VectorSearchResult<TMeta>[] | undefined,\n): boolean {\n\tif (a === b) return true;\n\tif (a == null || b == null) return false;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i += 1) {\n\t\tconst x = a[i]!;\n\t\tconst y = b[i]!;\n\t\tif (x.id !== y.id || x.score !== y.score || x.meta !== y.meta) return false;\n\t}\n\treturn true;\n}\n\n// ── Common types ─────────────────────────────────────────────────────────\n\n/** Public alias for the `Node | value` shape accepted by reactive read factories. */\nexport type { NodeOrValue } from \"../../base/resilience/_internal.js\";\n\n// ── Unit 2 (Tier 2.3 fold): collection (formerly lightCollection + collection)\n//\n// Pre-Tier-2.3 the module shipped `lightCollection` (no Graph, no ranking,\n// just LRU + audit) alongside `collection` (Graph-mounted with timer-driven\n// decay-aware ranking). Per the consolidation plan §1 Rule 4, the two are\n// folded into a single `collection({ranked: true|false})` factory: when\n// `ranked: false`, no `ranked` derived / refresh tick / scoring is wired.\n// `LightCollectionEntry` is gone — `CollectionEntry<T>` is the unified entry\n// shape (`baseScore` reads `0` in unranked mode).\n\nexport type CollectionEntry<T> = {\n\treadonly id: string;\n\treadonly value: T;\n\treadonly createdAtNs: number;\n\treadonly lastAccessNs: number;\n\treadonly baseScore: number;\n};\n\nexport type RankedCollectionEntry<T> = CollectionEntry<T> & {\n\treadonly score: number;\n};\n\nexport type CollectionScoreFn<T> = (value: T) => number;\n\nexport type CollectionOptions<T> = {\n\tmaxSize?: number;\n\t/**\n\t * Whether to expose a live decay-aware `ranked` node + `rescore` mutator.\n\t * Default `true`. Pass `false` to fold in the previous `lightCollection`\n\t * shape — entries are still keyed/audited/LRU-evicted, but the timer-driven\n\t * `ranked` + scoring machinery is skipped. `ranked` then resolves to a\n\t * static empty array Node and `rescore()` is a no-op (so callers writing\n\t * type-generic code don't need to special-case the unranked path).\n\t */\n\tranked?: boolean;\n\t/**\n\t * Produces a base score at insert/update time. Static fn or a reactive\n\t * `Node<(value: T) => number>` — when supplied as a Node, `ranked` re-derives\n\t * whenever the score fn changes, but `baseScore` on each entry is only\n\t * recomputed via {@link CollectionGraph.rescore}. Default `() => 1`.\n\t *\n\t * Ignored when `ranked: false` (entries record `baseScore: 0`).\n\t */\n\tscore?: CollectionScoreFn<T> | Node<CollectionScoreFn<T>>;\n\t/**\n\t * Exponential decay rate per second. `0` disables decay (default). When\n\t * positive, `ranked` becomes fully reactive on time via a `fromTimer` source\n\t * (cadence auto-derived from `decayRate` unless overridden via\n\t * `refreshIntervalMs`). Half-life: `ratePerSecond = Math.LN2 / halfLifeSeconds`.\n\t *\n\t * Ignored when `ranked: false`.\n\t */\n\tdecayRate?: number;\n\t/** Minimum score floor after decay. Default `0`. */\n\tminScore?: number;\n\t/**\n\t * Override for the `ranked` refresh tick cadence (milliseconds). When\n\t * unset and `decayRate > 0`, defaults to `1000 * Math.LN2 / (10 * decayRate)`\n\t * — roughly one tick per 10% of the half-life (~10% staleness budget).\n\t */\n\trefreshIntervalMs?: number;\n};\n\nexport interface CollectionAuditRecord extends BaseAuditRecord {\n\treadonly action: \"upsert\" | \"remove\" | \"clear\" | \"rescore\";\n\treadonly id?: string;\n}\n\nexport type CollectionGraph<T> = Graph & {\n\treadonly events: ReactiveLogBundle<CollectionAuditRecord>;\n\treadonly items: Node<ReadonlyMap<string, CollectionEntry<T>>>;\n\t/**\n\t * Live decay-aware ranking, sorted by score descending. When the\n\t * collection was constructed with `ranked: false`, this is a static\n\t * empty-array Node (kept for type uniformity).\n\t */\n\treadonly ranked: Node<readonly RankedCollectionEntry<T>[]>;\n\treadonly size: Node<number>;\n\tupsert: (id: string, value: T, opts?: { score?: number }) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\t/**\n\t * Recompute every entry's `baseScore` via the latest score fn. O(N). Useful\n\t * when a reactive `score` Node has emitted a new fn and the caller wants\n\t * existing entries re-scored without an explicit re-upsert.\n\t *\n\t * No-op (still records an audit entry) when constructed with\n\t * `ranked: false`.\n\t */\n\trescore: () => void;\n\titemNode: (id: NodeOrValue<string>) => Node<CollectionEntry<T> | undefined>;\n\t/** Reactive `true` once the entry exists; tracks upsert / remove. */\n\thasNode: (id: NodeOrValue<string>) => Node<boolean>;\n};\n\nfunction rankedEqual<T>(\n\ta: readonly RankedCollectionEntry<T>[] | undefined,\n\tb: readonly RankedCollectionEntry<T>[] | undefined,\n): boolean {\n\tif (a === b) return true;\n\tif (a == null || b == null) return false;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i += 1) {\n\t\tconst x = a[i]!;\n\t\tconst y = b[i]!;\n\t\t// Compare value reference too — if `upsert(id, newValue)` runs and\n\t\t// `score(newValue) === score(oldValue)` AND timestamps coincide\n\t\t// (rare on platforms where consecutive `monotonicNs()` calls in the\n\t\t// same microtask collide), the prior comparator suppressed the\n\t\t// emission and consumers reading `entry.value` saw stale data.\n\t\t// Value identity catches it cheaply (`value !== value` only on NaN\n\t\t// payloads, which behave correctly here).\n\t\tif (\n\t\t\tx.id !== y.id ||\n\t\t\tx.score !== y.score ||\n\t\t\tx.lastAccessNs !== y.lastAccessNs ||\n\t\t\tx.value !== y.value\n\t\t)\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Scored memory store with live decay-aware ranking.\n *\n * Topology (mounted on the returned graph):\n * - `items` — `reactiveMap<id, CollectionEntry<T>>` (with `retention` configured\n * for score-based eviction when `maxSize` is set).\n * - `ranked` — `Node<readonly RankedCollectionEntry<T>[]>`, sorted by live\n * decayed score. **Lazy** — does NOT compute until subscribed (no internal\n * keepalive). Use `keepalive(coll.ranked)` for eager activation.\n * - `size` — `Node<number>`, count of entries.\n * - `_refreshTick` — `fromTimer`-driven `monotonicNs()` source, mounted only\n * when `decayRate > 0`. Drives `ranked`'s time-dependent re-derivation.\n * - `_seq` — sequence cursor for the audit log.\n * - `events` — bounded reactive log of every mutation.\n *\n * **Time as a reactive dep.** When `decayRate > 0`, `ranked`'s deps are\n * `[items, refreshTick]` — the tick payload IS `monotonicNs()`, so the fn is\n * pure of deps and dry-run-reproducible with a mocked clock.\n *\n * **Lazy timer.** With no subscriber to `ranked`, the timer source does not\n * fire — the activation chain is downstream-driven. To keep the timer warm\n * without consuming results, register `graph.addDisposer(keepalive(coll.ranked))`.\n *\n * **Eviction at write-time.** Score-based retention runs on every successful\n * `upsert / remove / clear` (it is mutation-driven, not tick-driven). The\n * retention scorer reads `monotonicNs()` to compute decayed scores at eviction\n * time — this is a deliberate impurity vs. `ReactiveMapRetention.score`'s\n * \"pure of `(key, value)`\" docstring: write-time is the right moment to evict\n * stale-by-decay entries.\n *\n * **No imperative reads.** Subscribe to `items` / `ranked` for live snapshots,\n * or use `itemNode(id)` for single-key reactive reads.\n *\n * **`rescore` ordering caveat.** `rescore()` reads `items.entries.cache`\n * (the post-emission snapshot) and writes via `setMany`. When called\n * stand-alone it sees the latest committed state. When wrapped inside a\n * user-level `batch(() => { coll.upsert(...); coll.rescore(); })`, the\n * `cache` snapshot reflects state BEFORE the batch — so a just-staged\n * upsert is invisible to the rescore scan. If you need rescore to include\n * the staged upsert, either call `rescore()` after the batch settles or\n * pass the new `baseScore` directly via `upsert(id, value, { score })`.\n *\n * **Audit no-op records.** Like `lightCollection`, mutations record audit\n * entries even when the impl was a no-op (e.g., `rescore()` on an empty\n * store). Intentional — the framework records attempts.\n *\n * @category memory\n */\nexport function collection<T>(name: string, opts: CollectionOptions<T> = {}): CollectionGraph<T> {\n\tconst maxSize = opts.maxSize;\n\tconst ranked = opts.ranked ?? true;\n\t// `decayRate` / `score` / `refreshIntervalMs` are no-ops when ranked is off\n\t// (they only feed the `ranked` derived). The audit + LRU paths still run.\n\tconst decayRate = ranked ? (opts.decayRate ?? 0) : 0;\n\tconst minScore = opts.minScore ?? 0;\n\tif (maxSize !== undefined && maxSize < 1) {\n\t\tthrow new RangeError(\"collection: maxSize must be >= 1\");\n\t}\n\n\t// Resolve score fn — supports static fn or reactive Node<fn>. When\n\t// `ranked: false` the score is constant `0` and `readScoreFn` is unused\n\t// (the upsert path takes the `_opts.score ?? readScoreFn()(value)` branch\n\t// only when ranking is requested).\n\tconst scoreFnDefault: CollectionScoreFn<T> = () => (ranked ? 1 : 0);\n\tconst scoreInput = opts.score ?? scoreFnDefault;\n\tconst scoreNode: Node<CollectionScoreFn<T>> | undefined =\n\t\tranked && scoreInput instanceof NodeImpl\n\t\t\t? (scoreInput as Node<CollectionScoreFn<T>>)\n\t\t\t: undefined;\n\tconst readScoreFn = (): CollectionScoreFn<T> => {\n\t\tif (scoreNode) return scoreNode.cache ?? scoreFnDefault;\n\t\treturn scoreInput as CollectionScoreFn<T>;\n\t};\n\n\tconst graph = new Graph(name);\n\n\t// Score-based retention scorer for `reactiveMap`. When unranked the base\n\t// score is `0`, so retention falls back to LRU-by-`lastAccessNs` (the\n\t// older the access, the lower the decayed score → first to evict).\n\tconst retentionScore = (_k: string, v: CollectionEntry<T>): number =>\n\t\tranked\n\t\t\t? decay(v.baseScore, ageSeconds(monotonicNs(), v.lastAccessNs), decayRate, minScore)\n\t\t\t: v.lastAccessNs;\n\n\tconst items = reactiveMap<string, CollectionEntry<T>>({\n\t\tname: \"items\",\n\t\t...(maxSize !== undefined ? { retention: { score: retentionScore, maxSize } } : {}),\n\t});\n\n\tgraph.add(items.entries, { name: \"items\" });\n\n\t// Refresh tick — only mounted when ranking + decay are configured. Tick\n\t// payload is `monotonicNs()`, so `rankedNode`'s fn is pure-of-deps and\n\t// dry-run-reproducible.\n\tlet refreshTick: Node<number> | undefined;\n\tif (ranked && decayRate > 0) {\n\t\tconst intervalMs = opts.refreshIntervalMs ?? Math.max(1, (1000 * Math.LN2) / (10 * decayRate));\n\t\tconst tickCounter = fromTimer(intervalMs, { period: intervalMs });\n\t\t// Map each tick to the wall-clock `monotonicNs` — the tick payload IS\n\t\t// the time stamp downstream consumers use. Reading the central clock\n\t\t// inside this fn is sanctioned: this derived's purpose is to publish\n\t\t// \"now\" reactively (cf. spec §5.11 — central timer), and downstream\n\t\t// `rankedNode` reads it from its dep array, never from the clock\n\t\t// directly.\n\t\t//\n\t\t// `initial: monotonicNs()` seeds the cache with construction-time\n\t\t// `now` so push-on-subscribe delivers DATA to `rankedNode` before the\n\t\t// first tick fires — without this, `rankedNode` would stall in pending\n\t\t// status until ~`refreshIntervalMs` after first activation, and a\n\t\t// caller reading `rankedNode.cache` immediately after `upsert` would\n\t\t// see `undefined`.\n\t\trefreshTick = node(\n\t\t\t[tickCounter],\n\t\t\t(_batchData, actions) => {\n\t\t\t\tactions.emit(monotonicNs());\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"refresh_tick_ns\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tinitial: monotonicNs(),\n\t\t\t\tmeta: memoryMeta(\"clock\"),\n\t\t\t},\n\t\t);\n\t\tgraph.add(refreshTick, { name: \"refresh_tick_ns\" });\n\t}\n\n\t// `rankedNode` derived — pure of (items, refreshTick?, scoreNode?). When\n\t// `ranked: false`, `rankedNode` is a static empty-array node so the\n\t// public type stays uniform without re-running the sort.\n\tlet rankedNode: Node<readonly RankedCollectionEntry<T>[]>;\n\tif (ranked) {\n\t\tconst rankedDeps: Node<unknown>[] = [items.entries];\n\t\tif (refreshTick) rankedDeps.push(refreshTick);\n\t\tif (scoreNode) rankedDeps.push(scoreNode);\n\t\trankedNode = node(\n\t\t\trankedDeps,\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst values = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst snapshot = values[0] as ReadonlyMap<string, CollectionEntry<T>> | undefined;\n\t\t\t\tlet now: number;\n\t\t\t\tif (refreshTick) {\n\t\t\t\t\tconst tickValue = values[1] as number | undefined;\n\t\t\t\t\tnow = typeof tickValue === \"number\" ? tickValue : monotonicNs();\n\t\t\t\t} else {\n\t\t\t\t\tnow = monotonicNs();\n\t\t\t\t}\n\t\t\t\tif (!snapshot || snapshot.size === 0) {\n\t\t\t\t\tactions.emit([] as readonly RankedCollectionEntry<T>[]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst out: RankedCollectionEntry<T>[] = [];\n\t\t\t\tfor (const entry of snapshot.values()) {\n\t\t\t\t\tout.push({\n\t\t\t\t\t\t...entry,\n\t\t\t\t\t\tscore: decay(entry.baseScore, ageSeconds(now, entry.lastAccessNs), decayRate, minScore),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tout.sort((a, b) => b.score - a.score || b.lastAccessNs - a.lastAccessNs);\n\t\t\t\tactions.emit(out as readonly RankedCollectionEntry<T>[]);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"ranked\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tequals: rankedEqual,\n\t\t\t\tmeta: memoryMeta(\"ranked\"),\n\t\t\t},\n\t\t) as Node<readonly RankedCollectionEntry<T>[]>;\n\t\tgraph.add(rankedNode, { name: \"ranked\" });\n\t} else {\n\t\trankedNode = node<readonly RankedCollectionEntry<T>[]>([], {\n\t\t\tinitial: [] as readonly RankedCollectionEntry<T>[],\n\t\t\tname: \"ranked\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: memoryMeta(\"ranked_disabled\"),\n\t\t}) as Node<readonly RankedCollectionEntry<T>[]>;\n\t\tgraph.add(rankedNode, { name: \"ranked\" });\n\t}\n\n\tconst size = node(\n\t\t[items.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst snapshot = data[0] as ReadonlyMap<string, CollectionEntry<T>> | undefined;\n\t\t\tactions.emit(((snapshot ?? new Map()) as ReadonlyMap<string, CollectionEntry<T>>).size);\n\t\t},\n\t\t{\n\t\t\tname: \"size\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: 0,\n\t\t\tmeta: memoryMeta(\"size\"),\n\t\t},\n\t);\n\tgraph.add(size, { name: \"size\" });\n\t// Keepalive only on `size` (cheap; pure of items). `ranked` is intentionally\n\t// lazy so the refresh timer doesn't fire when nothing consumes the ranking.\n\tgraph.addDisposer(keepalive(size));\n\n\t// Audit log + seq cursor.\n\tconst events = createAuditLog<CollectionAuditRecord>({\n\t\tname: \"events\",\n\t\tretainedLimit: 1024,\n\t\tgraph,\n\t});\n\tconst seqCursor = registerCursor(graph, \"seq\", 0);\n\n\tconst upsertImpl = (id: string, value: T, _opts?: { score?: number }): void => {\n\t\tconst now = monotonicNs();\n\t\tconst prev = items.get(id);\n\t\tconst baseScore = _opts?.score ?? readScoreFn()(value);\n\t\titems.set(id, {\n\t\t\tid,\n\t\t\tvalue,\n\t\t\tbaseScore,\n\t\t\tcreatedAtNs: prev?.createdAtNs ?? now,\n\t\t\tlastAccessNs: now,\n\t\t});\n\t};\n\tconst removeImpl = (id: string): void => {\n\t\tif (!items.has(id)) return;\n\t\titems.delete(id);\n\t};\n\tconst clearImpl = (): void => {\n\t\tif (items.size === 0) return;\n\t\titems.clear();\n\t};\n\tconst rescoreImpl = (): void => {\n\t\t// `ranked: false` short-circuit — there's no live `ranked` node to\n\t\t// re-derive and `baseScore` is held at its insertion-time value, so\n\t\t// rescore is a no-op. The audit record is still emitted so consumers\n\t\t// see the attempt.\n\t\tif (!ranked) return;\n\t\tconst fn = readScoreFn();\n\t\tconst snapshot = items.entries.cache as ReadonlyMap<string, CollectionEntry<T>> | undefined;\n\t\tif (!snapshot || snapshot.size === 0) return;\n\t\tconst updates: Array<[string, CollectionEntry<T>]> = [];\n\t\tfor (const entry of snapshot.values()) {\n\t\t\tupdates.push([entry.id, { ...entry, baseScore: fn(entry.value) }]);\n\t\t}\n\t\titems.setMany(updates);\n\t};\n\n\tconst upsert = mutate(upsertImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: ([id], _r, m) => ({ action: \"upsert\" as const, id, t_ns: m.t_ns, seq: m.seq }),\n\t});\n\tconst remove = mutate(removeImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: ([id], _r, m) => ({ action: \"remove\" as const, id, t_ns: m.t_ns, seq: m.seq }),\n\t});\n\tconst clear = mutate(clearImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: (_args, _r, m) => ({ action: \"clear\" as const, t_ns: m.t_ns, seq: m.seq }),\n\t});\n\tconst rescore = mutate(rescoreImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: (_args, _r, m) => ({ action: \"rescore\" as const, t_ns: m.t_ns, seq: m.seq }),\n\t});\n\n\tfunction itemNode(id: NodeOrValue<string>): Node<CollectionEntry<T> | undefined> {\n\t\tconst idN = toNode(id, \"id\");\n\t\treturn node(\n\t\t\t[items.entries, idN],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst map = data[0] as ReadonlyMap<string, CollectionEntry<T>> | undefined;\n\t\t\t\tconst key = data[1] as string;\n\t\t\t\tactions.emit(map?.get(key));\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: memoryMeta(\"collection_item\"),\n\t\t\t},\n\t\t);\n\t}\n\n\tfunction hasNode(id: NodeOrValue<string>): Node<boolean> {\n\t\tconst idN = toNode(id, \"id\");\n\t\treturn node(\n\t\t\t[items.entries, idN],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst map = data[0] as ReadonlyMap<string, CollectionEntry<T>> | undefined;\n\t\t\t\tconst key = data[1] as string;\n\t\t\t\tactions.emit(map?.has(key) ?? false);\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: memoryMeta(\"collection_has\"),\n\t\t\t},\n\t\t);\n\t}\n\n\tconst out = Object.assign(graph, {\n\t\tevents,\n\t\titems: items.entries,\n\t\tranked: rankedNode,\n\t\tsize,\n\t\tupsert,\n\t\tremove,\n\t\tclear,\n\t\trescore,\n\t\titemNode,\n\t\thasNode,\n\t}) as CollectionGraph<T>;\n\treturn out;\n}\n\n// ── Unit 4: vectorIndex ──────────────────────────────────────────────────\n\nexport type VectorBackend = \"flat\" | \"hnsw\";\n\nexport type VectorRecord<TMeta> = {\n\treadonly id: string;\n\treadonly vector: readonly number[];\n\treadonly meta?: TMeta;\n\t/** Wall-clock-monotonic timestamp at last upsert; used for the default LRU retention. */\n\treadonly upsertedAtNs: number;\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\t/** Optional adapter teardown. Called from `graph.destroy()` via `addDisposer`. */\n\tdispose?: () => void;\n};\n\nexport type VectorIndexOptions<TMeta> = {\n\tname?: string;\n\tbackend?: VectorBackend;\n\tdimension?: number;\n\t/**\n\t * Strict-dimension default. When `true` (default) AND `dimension` is unset,\n\t * mixed-length upserts throw `RangeError`. Set `false` to opt into the\n\t * lenient zero-padding behavior of {@link VectorIndexGraph.searchNode}.\n\t */\n\tstrictDimension?: boolean;\n\t/** Optional dependency seam for HNSW. */\n\thnswFactory?: () => HnswAdapter<TMeta>;\n\t/** Maximum live entries (LRU-by-upsert-time when set; user-overridable via `retentionScore`). */\n\tmaxSize?: number;\n\t/** Custom retention scorer. Higher score = kept. Defaults to `r => r.upsertedAtNs`. */\n\tretentionScore?: (record: VectorRecord<TMeta>) => number;\n};\n\nexport interface VectorIndexAuditRecord extends BaseAuditRecord {\n\treadonly action: \"upsert\" | \"remove\" | \"clear\" | \"reindex\" | \"evict\";\n\treadonly id?: string;\n}\n\nexport type VectorIndexGraph<TMeta> = Graph & {\n\treadonly backend: VectorBackend;\n\treadonly events: ReactiveLogBundle<VectorIndexAuditRecord>;\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\t/** Re-push every live entry into the optional HNSW adapter. No-op for `flat`. */\n\treindex: () => void;\n\t/**\n\t * Reactive top-K search. Re-derives whenever entries / query / k change.\n\t * Lazy. Use `firstValueFrom(searchNode(...))` for one-shot reads.\n\t */\n\tsearchNode: (\n\t\tquery: Node<readonly number[]>,\n\t\tk?: NodeOrValue<number>,\n\t) => Node<readonly VectorSearchResult<TMeta>[]>;\n};\n\n/**\n * Reactive vector store with optional HNSW backend.\n *\n * **Storage on `reactiveMap`.** `entries` is a `reactiveMap<id, VectorRecord<TMeta>>`\n * with optional score-based retention (`maxSize` + LRU-by-`upsertedAtNs` by\n * default; user can supply a custom `retentionScore`). On retention eviction,\n * the HNSW adapter (if configured) is also notified via `adapter.remove(id)`.\n *\n * **Reactive search.** `searchNode(queryNode, k)` returns a `Node<readonly\n * VectorSearchResult<TMeta>[]>` that re-derives on entries / query / k change.\n * Lazy — only computes when subscribed. Imperative `search()` is intentionally\n * not exposed (no-imperative-reads policy). Use `firstValueFrom(searchNode(...))`\n * for one-shot reads.\n *\n * **Strict dimension.** Default `strictDimension: true` — if `dimension` is\n * unset and an upsert produces a vector of a different length than the first\n * upserted, throws `RangeError`. Pass `strictDimension: false` to opt into\n * the lenient zero-padding fallback (the previous default).\n *\n * **Adapter lifecycle.** When the HNSW adapter exposes a `dispose()` method,\n * it is bound to the graph's teardown via `addDisposer`. When retention\n * evicts an entry, `adapter.remove(id)` is invoked synchronously inside the\n * retention `onArchive` callback.\n *\n * **Cosine zero-pad.** The flat backend uses cosine similarity over the\n * pairwise max-length zero-pad. Mixing dimensions silently degrades scores\n * unless strict mode catches it at upsert time. For embedding-model vectors,\n * L2-normalize at the source — `vectorIndex` does not normalize.\n *\n * @category memory\n */\nexport function vectorIndex<TMeta>(opts: VectorIndexOptions<TMeta> = {}): VectorIndexGraph<TMeta> {\n\tconst backend = opts.backend ?? \"flat\";\n\tconst dimension = opts.dimension;\n\tconst strictDimension = opts.strictDimension ?? true;\n\tconst maxSize = opts.maxSize;\n\tconst userRetentionScore = opts.retentionScore;\n\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 graph = new Graph(opts.name ?? \"vector_index\");\n\n\t// Track an inferred dimension when the user didn't lock it but strict mode\n\t// is on — first upsert sets it; subsequent mismatches throw.\n\tlet inferredDimension: number | undefined;\n\tfunction assertDimension(vector: readonly number[]): void {\n\t\tif (dimension !== undefined) {\n\t\t\tif (vector.length !== dimension) {\n\t\t\t\tthrow new RangeError(\n\t\t\t\t\t`vector dimension mismatch: expected ${dimension}, got ${vector.length}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!strictDimension) return;\n\t\tif (inferredDimension === undefined) {\n\t\t\tinferredDimension = vector.length;\n\t\t\treturn;\n\t\t}\n\t\tif (vector.length !== inferredDimension) {\n\t\t\tthrow new RangeError(\n\t\t\t\t`vector dimension mismatch: inferred ${inferredDimension} from first upsert, got ${vector.length}. ` +\n\t\t\t\t\t`Pass \\`strictDimension: false\\` to opt into zero-pad behavior, or set an explicit \\`dimension\\`.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst baseRetentionScore = userRetentionScore ?? ((r: VectorRecord<TMeta>) => r.upsertedAtNs);\n\t// `clearInProgress` lets us short-circuit the per-entry `onArchive` →\n\t// `hnsw.remove(id)` cascade when the user calls `clearImpl()`. Retention\n\t// fires `onArchive` for every evicted entry; followed by an explicit\n\t// `hnsw.clear()` we'd double-touch the adapter. Inside `clearImpl` we\n\t// flip this flag, then call `hnsw.clear()` once at the end. (G fix.)\n\tlet clearInProgress = false;\n\n\t// `clearAuditPending` defers the per-entry `evict` audit emission when a\n\t// `clear()` is in flight — those evictions are reported as a single\n\t// `clear` action, not a flurry of `evict` records.\n\tconst events = createAuditLog<VectorIndexAuditRecord>({\n\t\tname: \"events\",\n\t\tretainedLimit: 1024,\n\t\tgraph,\n\t});\n\tconst seqCursor = registerCursor(graph, \"seq\", 0);\n\n\tconst entries = reactiveMap<string, VectorRecord<TMeta>>({\n\t\tname: \"entries\",\n\t\t...(maxSize !== undefined\n\t\t\t? {\n\t\t\t\t\tretention: {\n\t\t\t\t\t\tscore: (_k, v) => baseRetentionScore(v),\n\t\t\t\t\t\tmaxSize,\n\t\t\t\t\t\tonArchive: (key) => {\n\t\t\t\t\t\t\tif (clearInProgress) return;\n\t\t\t\t\t\t\tif (backend === \"hnsw\") hnsw!.remove(key);\n\t\t\t\t\t\t\t// E1: surface retention-driven evictions in the audit log\n\t\t\t\t\t\t\t// so replay consumers can reconstruct the live snapshot\n\t\t\t\t\t\t\t// from `events` alone. `seq` is bumped via the cursor;\n\t\t\t\t\t\t\t// the `t_ns` matches `wallClockNs()` for consistency\n\t\t\t\t\t\t\t// with `lightMutation`'s record stamping.\n\t\t\t\t\t\t\tevents.append({\n\t\t\t\t\t\t\t\taction: \"evict\" as const,\n\t\t\t\t\t\t\t\tid: key,\n\t\t\t\t\t\t\t\tt_ns: wallClockNs(),\n\t\t\t\t\t\t\t\tseq: bumpCursor(seqCursor),\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});\n\tgraph.add(entries.entries, { name: \"entries\" });\n\t// F1: keep `entries` warm so downstream consumers reading\n\t// `vectors.entries.cache` (e.g. `patterns/ai/memory/runRetrieval`) don't\n\t// rely on an external subscriber to activate the node. State nodes are\n\t// ROM and retain `.cache` regardless of subscribers — this `keepalive`\n\t// is defense-in-depth and matches the kg's adjacency keepalive pattern.\n\tgraph.addDisposer(keepalive(entries.entries));\n\n\t// HNSW dispose runs BEFORE state-node teardown via standard disposer\n\t// ordering (disposers drain first, then `[[TEARDOWN]]` propagates per\n\t// `Graph.destroy()`). This is the right ordering: free the adapter's\n\t// native resources before the reactive layer tears down.\n\tif (hnsw?.dispose) {\n\t\tconst disposeAdapter = hnsw.dispose.bind(hnsw);\n\t\tgraph.addDisposer(() => disposeAdapter());\n\t}\n\n\tconst upsertImpl = (id: string, vector: readonly number[], meta?: TMeta): void => {\n\t\tassertDimension(vector);\n\t\t// B1: mutate HNSW first so a throw aborts the reactive write. With\n\t\t// the prior order (entries.set then hnsw.upsert), an adapter throw\n\t\t// would leave entries holding a row HNSW didn't index. Now: HNSW\n\t\t// commits first; if it throws, entries is untouched and audit log\n\t\t// records the failure.\n\t\tif (backend === \"hnsw\") hnsw!.upsert(id, vector, meta);\n\t\t// Defensive copies: vector via `[...vector]`; meta via shallow spread\n\t\t// when it's a non-null object (Array.isArray covered first since arrays\n\t\t// are objects). Primitives, `null`, functions etc. pass through\n\t\t// unchanged. Documented depth limitation: nested objects in `meta` are\n\t\t// shared by reference.\n\t\tconst copiedMeta: TMeta | undefined = (() => {\n\t\t\tif (meta === undefined) return undefined;\n\t\t\tif (meta === null || typeof meta !== \"object\") return meta;\n\t\t\treturn Array.isArray(meta) ? ([...meta] as unknown as TMeta) : ({ ...meta } as TMeta);\n\t\t})();\n\t\tconst record: VectorRecord<TMeta> = {\n\t\t\tid,\n\t\t\tvector: [...vector],\n\t\t\t...(copiedMeta !== undefined ? { meta: copiedMeta } : {}),\n\t\t\tupsertedAtNs: monotonicNs(),\n\t\t};\n\t\tentries.set(id, record);\n\t};\n\tconst removeImpl = (id: string): void => {\n\t\tif (!entries.has(id)) return;\n\t\t// B1: HNSW first, then entries.\n\t\tif (backend === \"hnsw\") hnsw!.remove(id);\n\t\tentries.delete(id);\n\t};\n\tconst clearImpl = (): void => {\n\t\tif (entries.size === 0) return;\n\t\t// B1 + G: mark the clear-in-progress flag so retention `onArchive`\n\t\t// suppresses per-entry HNSW removes AND per-entry `evict` audit\n\t\t// records. Then call `entries.clear()` (drains the backend through\n\t\t// retention archival without side effects), and finally call\n\t\t// `hnsw.clear()` once. Reset `inferredDimension` so a fresh start\n\t\t// re-infers from the next upsert.\n\t\tclearInProgress = true;\n\t\ttry {\n\t\t\tentries.clear();\n\t\t\tif (backend === \"hnsw\") hnsw!.clear();\n\t\t} finally {\n\t\t\tclearInProgress = false;\n\t\t}\n\t\tinferredDimension = undefined;\n\t};\n\tconst reindexImpl = (): void => {\n\t\tif (backend !== \"hnsw\") return;\n\t\tconst snapshot = entries.entries.cache as ReadonlyMap<string, VectorRecord<TMeta>> | undefined;\n\t\tif (!snapshot) return;\n\t\thnsw!.clear();\n\t\tfor (const r of snapshot.values()) {\n\t\t\thnsw!.upsert(r.id, r.vector, r.meta);\n\t\t}\n\t};\n\n\t// `freeze: false` for `upsert` — deep-freezing a 768-dim vector is a\n\t// measurable hot-path tax, and the wrapper does its own defensive copy\n\t// (`vector: [...vector]`) before persisting. See §B.2 of the audit lock.\n\tconst upsert = mutate(upsertImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tfreeze: false,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: ([id], _r, m) => ({ action: \"upsert\" as const, id, t_ns: m.t_ns, seq: m.seq }),\n\t});\n\tconst remove = mutate(removeImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: ([id], _r, m) => ({ action: \"remove\" as const, id, t_ns: m.t_ns, seq: m.seq }),\n\t});\n\tconst clear = mutate(clearImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: (_args, _r, m) => ({ action: \"clear\" as const, t_ns: m.t_ns, seq: m.seq }),\n\t});\n\tconst reindex = mutate(reindexImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: (_args, _r, m) => ({ action: \"reindex\" as const, t_ns: m.t_ns, seq: m.seq }),\n\t});\n\n\tfunction searchNode(\n\t\tquery: Node<readonly number[]>,\n\t\tk: NodeOrValue<number> = 5,\n\t): Node<readonly VectorSearchResult<TMeta>[]> {\n\t\tconst kN = toNode<number>(k, \"k\");\n\t\treturn node(\n\t\t\t[entries.entries, query, kN],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst values = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst snapshot = values[0] as ReadonlyMap<string, VectorRecord<TMeta>> | undefined;\n\t\t\t\tconst q = values[1] as readonly number[] | undefined;\n\t\t\t\tconst kRaw = values[2] as number;\n\t\t\t\t// Auto-fix: `Math.max(0, Math.floor(k))` — `| 0` is a 32-bit\n\t\t\t\t// signed truncation that collapses Infinity to 0 and wraps\n\t\t\t\t// values > 2^31. Use a proper floor with a non-negative floor.\n\t\t\t\tconst kVal = Number.isFinite(kRaw) ? Math.max(0, Math.floor(kRaw)) : 0;\n\t\t\t\tif (!snapshot || snapshot.size === 0 || kVal <= 0) {\n\t\t\t\t\tactions.emit([] as readonly VectorSearchResult<TMeta>[]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Auto-fix: defensive guard for unset / empty query — earlier\n\t\t\t\t// the fn would TypeError on `q.length` reading `undefined`,\n\t\t\t\t// or compute meaningless all-zero scores against an empty\n\t\t\t\t// vector. With strict-dimension OR an explicit `dimension`,\n\t\t\t\t// also reject mismatched-length queries (the imperative path\n\t\t\t\t// used to throw; reactive deriveds shouldn't throw, so\n\t\t\t\t// degrade to empty results).\n\t\t\t\tif (q == null || q.length === 0) {\n\t\t\t\t\tactions.emit([] as readonly VectorSearchResult<TMeta>[]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst expectedDim = dimension ?? (strictDimension ? inferredDimension : undefined);\n\t\t\t\tif (expectedDim !== undefined && q.length !== expectedDim) {\n\t\t\t\t\tactions.emit([] as readonly VectorSearchResult<TMeta>[]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (backend === \"hnsw\") {\n\t\t\t\t\t// Defensive copy of the adapter's return — HNSW libs\n\t\t\t\t\t// sometimes hand back internal buffers; downstream\n\t\t\t\t\t// subscribers must not be able to corrupt adapter state.\n\t\t\t\t\tconst adapterResults = hnsw!.search(q, kVal);\n\t\t\t\t\tactions.emit([...adapterResults] as readonly VectorSearchResult<TMeta>[]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst ranked = [...snapshot.values()]\n\t\t\t\t\t.map((row) => {\n\t\t\t\t\t\tconst result: VectorSearchResult<TMeta> = {\n\t\t\t\t\t\t\tid: row.id,\n\t\t\t\t\t\t\tscore: cosineSimilarity(q, row.vector),\n\t\t\t\t\t\t\t...(row.meta !== undefined ? { meta: row.meta } : {}),\n\t\t\t\t\t\t};\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t})\n\t\t\t\t\t.sort((a, b) => b.score - a.score)\n\t\t\t\t\t.slice(0, kVal);\n\t\t\t\tactions.emit(ranked as readonly VectorSearchResult<TMeta>[]);\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t// A1: include `score` in equality. The previous id-only\n\t\t\t\t// comparator suppressed re-emissions when the same set of\n\t\t\t\t// IDs/order had different scores (re-upsert with new\n\t\t\t\t// vector; query change preserving ranking order).\n\t\t\t\tequals: (a, b) => searchResultsEqual(a, b),\n\t\t\t\tmeta: memoryMeta(\"vector_search\"),\n\t\t\t},\n\t\t) as Node<readonly VectorSearchResult<TMeta>[]>;\n\t}\n\n\tconst out = Object.assign(graph, {\n\t\tbackend,\n\t\tevents,\n\t\tentries: entries.entries,\n\t\tupsert,\n\t\tremove,\n\t\tclear,\n\t\treindex,\n\t\tsearchNode,\n\t}) as VectorIndexGraph<TMeta>;\n\treturn out;\n}\n\n// ── Unit 5: knowledgeGraph ───────────────────────────────────────────────\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 KnowledgeGraphOptions = {\n\t/** Cap on entity count (LRU-by-upsert-time when set). */\n\tentitiesMaxSize?: number;\n\t/** Cap on edge count (LRU-by-upsert-time when set). */\n\tedgesMaxSize?: number;\n\t/**\n\t * Orphan-entity garbage collection. `\"keep\"` (default) leaves entities\n\t * untouched when their last edge is unlinked; `\"remove\"` deletes the\n\t * entity post-`unlink` if no edges reference it.\n\t */\n\torphanGC?: \"keep\" | \"remove\";\n};\n\nexport interface KnowledgeGraphAuditRecord extends BaseAuditRecord {\n\treadonly action: \"upsertEntity\" | \"removeEntity\" | \"link\" | \"unlink\" | \"orphanRemove\";\n\treadonly id?: string;\n\treadonly from?: string;\n\treadonly to?: string;\n\treadonly relation?: string;\n\t/** Edge weight at the time of the `link`. Omitted for non-edge actions. */\n\treadonly weight?: number;\n}\n\nexport type KnowledgeGraph<TEntity, TRelation extends string = string> = Graph & {\n\treadonly events: ReactiveLogBundle<KnowledgeGraphAuditRecord>;\n\treadonly entities: Node<ReadonlyMap<string, TEntity>>;\n\treadonly edges: Node<ReadonlyMap<string, KnowledgeEdge<TRelation>>>;\n\treadonly adjacencyOut: Node<ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>>;\n\treadonly adjacencyIn: Node<ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>>;\n\treadonly entityCount: Node<number>;\n\treadonly edgeCount: Node<number>;\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\trelatedNode: (\n\t\tid: NodeOrValue<string>,\n\t\trelation?: NodeOrValue<TRelation>,\n\t) => Node<readonly KnowledgeEdge<TRelation>[]>;\n};\n\nconst TRIPLE_SEP = \"\u0000\";\nfunction tripleKey(from: string, to: string, relation: string): string {\n\treturn `${from}${TRIPLE_SEP}${to}${TRIPLE_SEP}${relation}`;\n}\n\nfunction buildAdjacency<TRelation extends string>(\n\tedges: ReadonlyMap<string, KnowledgeEdge<TRelation>> | undefined,\n\tside: \"from\" | \"to\",\n): ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]> {\n\tif (!edges || edges.size === 0) return new Map();\n\tconst buckets = new Map<string, KnowledgeEdge<TRelation>[]>();\n\tfor (const edge of edges.values()) {\n\t\tconst key = side === \"from\" ? edge.from : edge.to;\n\t\tlet bucket = buckets.get(key);\n\t\tif (!bucket) {\n\t\t\tbucket = [];\n\t\t\tbuckets.set(key, bucket);\n\t\t}\n\t\tbucket.push(edge);\n\t}\n\tconst out = new Map<string, readonly KnowledgeEdge<TRelation>[]>();\n\tfor (const [key, bucket] of buckets) out.set(key, Object.freeze(bucket));\n\treturn out;\n}\n\nfunction adjacencyEqual<TRelation extends string>(\n\ta: ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]> | undefined,\n\tb: ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]> | undefined,\n): boolean {\n\tif (a === b) return true;\n\tif (a == null || b == null) return false;\n\tif (a.size !== b.size) return false;\n\tfor (const [k, av] of a) {\n\t\tconst bv = b.get(k);\n\t\tif (!bv || av.length !== bv.length) return false;\n\t\tfor (let i = 0; i < av.length; i += 1) {\n\t\t\tconst ae = av[i]!;\n\t\t\tconst be = bv[i]!;\n\t\t\tif (\n\t\t\t\tae.from !== be.from ||\n\t\t\t\tae.to !== be.to ||\n\t\t\t\tae.relation !== be.relation ||\n\t\t\t\tae.weight !== be.weight\n\t\t\t)\n\t\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Reactive knowledge graph: entities + typed edges + symmetric adjacency.\n *\n * Topology (mounted on the returned graph):\n * - `entities` — `reactiveMap<id, TEntity>` (optional `entitiesMaxSize` LRU).\n * - `edges` — `reactiveMap<tripleKey, KnowledgeEdge<TRelation>>` keyed by\n * `${from}\u0000${to}\u0000${relation}` (optional `edgesMaxSize` LRU).\n * Entity IDs / relations must NOT contain `\u0000`.\n * - `adjacencyOut` — `Node<ReadonlyMap<from, readonly edge[]>>`. **Full O(E)\n * rebuild on every `link` / `unlink` mutation.** (Prior JSDoc claim of\n * \"O(E) build\" referred to a single rebuild — the per-mutation cost is\n * O(E), not O(1) amortized. For very large graphs with frequent edge\n * churn, consider batching via `reactiveMap.setMany`.)\n * - `adjacencyIn` — `Node<ReadonlyMap<to, readonly edge[]>>`. Same O(E) per\n * mutation rebuild characteristic.\n * - `entityCount` / `edgeCount` — observability deriveds.\n * - `events` — bounded reactive audit log.\n *\n * **`link()` semantics.** Calling `link(a, b, rel, w)` twice with different\n * weights replaces the weight on the existing edge (keyed by the triple).\n * `unlink` then `link` re-creates the edge (and bumps `lastUpsertNs` for\n * retention purposes).\n *\n * **Edge weight convention.** Higher weight = stronger relation. Default `1`.\n *\n * **Orphan GC.** `orphanGC: \"remove\"` deletes an entity from `entities` after\n * an `unlink` that empties its adjacency on both sides. Default `\"keep\"`.\n *\n * **No imperative reads.** Use `relatedNode(id, relation?)` for reactive reads.\n *\n * @category memory\n */\nexport function knowledgeGraph<TEntity, TRelation extends string = string>(\n\tname: string,\n\topts: KnowledgeGraphOptions = {},\n): KnowledgeGraph<TEntity, TRelation> {\n\tconst orphanGC = opts.orphanGC ?? \"keep\";\n\tif (opts.entitiesMaxSize !== undefined && opts.entitiesMaxSize < 1) {\n\t\tthrow new RangeError(\"knowledgeGraph: entitiesMaxSize must be >= 1\");\n\t}\n\tif (opts.edgesMaxSize !== undefined && opts.edgesMaxSize < 1) {\n\t\tthrow new RangeError(\"knowledgeGraph: edgesMaxSize must be >= 1\");\n\t}\n\n\tconst graph = new Graph(name);\n\n\tconst entitiesMap = reactiveMap<string, TEntity>({\n\t\tname: \"entities\",\n\t\t...(opts.entitiesMaxSize !== undefined ? { maxSize: opts.entitiesMaxSize } : {}),\n\t});\n\tconst edgesMap = reactiveMap<string, KnowledgeEdge<TRelation>>({\n\t\tname: \"edges\",\n\t\t...(opts.edgesMaxSize !== undefined ? { maxSize: opts.edgesMaxSize } : {}),\n\t});\n\tgraph.add(entitiesMap.entries, { name: \"entities\" });\n\tgraph.add(edgesMap.entries, { name: \"edges\" });\n\n\tconst adjacencyOut = node(\n\t\t[edgesMap.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst snapshot = data[0] as ReadonlyMap<string, KnowledgeEdge<TRelation>> | undefined;\n\t\t\tactions.emit(buildAdjacency<TRelation>(snapshot, \"from\"));\n\t\t},\n\t\t{\n\t\t\tname: \"adjacencyOut\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: new Map() as ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>,\n\t\t\tequals: adjacencyEqual,\n\t\t\tmeta: memoryMeta(\"adjacency_out\"),\n\t\t},\n\t) as Node<ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>>;\n\tconst adjacencyIn = node(\n\t\t[edgesMap.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst snapshot = data[0] as ReadonlyMap<string, KnowledgeEdge<TRelation>> | undefined;\n\t\t\tactions.emit(buildAdjacency<TRelation>(snapshot, \"to\"));\n\t\t},\n\t\t{\n\t\t\tname: \"adjacencyIn\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: new Map() as ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>,\n\t\t\tequals: adjacencyEqual,\n\t\t\tmeta: memoryMeta(\"adjacency_in\"),\n\t\t},\n\t) as Node<ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>>;\n\tgraph.add(adjacencyOut, { name: \"adjacencyOut\" });\n\tgraph.add(adjacencyIn, { name: \"adjacencyIn\" });\n\tgraph.addDisposer(keepalive(adjacencyOut));\n\tgraph.addDisposer(keepalive(adjacencyIn));\n\n\tconst entityCount = node(\n\t\t[entitiesMap.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst m = data[0] as ReadonlyMap<string, TEntity> | undefined;\n\t\t\tactions.emit(((m ?? new Map()) as ReadonlyMap<string, TEntity>).size);\n\t\t},\n\t\t{ name: \"entityCount\", describeKind: \"derived\", initial: 0, meta: memoryMeta(\"entity_count\") },\n\t);\n\tconst edgeCount = node(\n\t\t[edgesMap.entries],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst m = data[0] as ReadonlyMap<string, KnowledgeEdge<TRelation>> | undefined;\n\t\t\tactions.emit(((m ?? new Map()) as ReadonlyMap<string, KnowledgeEdge<TRelation>>).size);\n\t\t},\n\t\t{ name: \"edgeCount\", describeKind: \"derived\", initial: 0, meta: memoryMeta(\"edge_count\") },\n\t);\n\tgraph.add(entityCount, { name: \"entityCount\" });\n\tgraph.add(edgeCount, { name: \"edgeCount\" });\n\tgraph.addDisposer(keepalive(entityCount));\n\tgraph.addDisposer(keepalive(edgeCount));\n\n\tconst events = createAuditLog<KnowledgeGraphAuditRecord>({\n\t\tname: \"events\",\n\t\tretainedLimit: 1024,\n\t\tgraph,\n\t});\n\tconst seqCursor = registerCursor(graph, \"seq\", 0);\n\n\t/**\n\t * O(1) orphan check via the kept-warm `adjacency*` deriveds. Reading\n\t * `adjacencyOut.cache` / `adjacencyIn.cache` is safe here because both\n\t * are activated via `addDisposer(keepalive(...))` at construction time\n\t * (a derived's RAM cache only persists with at least one subscriber, and\n\t * the keepalive registers exactly that). The previous implementation\n\t * scanned `edgesMap.entries.cache` post-`deleteMany`, which depended on\n\t * the (sync) snapshot-emit timing of `reactiveMap` — fragile. The\n\t * `adjacency*.cache` approach is both faster (O(1) vs O(E) per check)\n\t * and timing-robust because the reactiveMap snapshot has already\n\t * propagated through the derived chain by the time we read.\n\t */\n\tfunction entityHasReferences(id: string): boolean {\n\t\tconst out = adjacencyOut.cache as\n\t\t\t| ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>\n\t\t\t| undefined;\n\t\tconst inb = adjacencyIn.cache as\n\t\t\t| ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>\n\t\t\t| undefined;\n\t\tif ((out?.get(id)?.length ?? 0) > 0) return true;\n\t\tif ((inb?.get(id)?.length ?? 0) > 0) return true;\n\t\treturn false;\n\t}\n\n\t/**\n\t * Apply orphan GC to a list of candidate entity ids. Used by both\n\t * {@link unlinkImpl} (post-edge-removal) and {@link removeEntityImpl}\n\t * (post-cascade) so semantics are consistent. Each removed entity\n\t * records a separate `orphanRemove` audit entry with its own monotonic\n\t * `seq` value (D1 fix — the previous bare `events.append(...)` skipped\n\t * the cursor advance, leaving gaps in the audit replay sequence).\n\t */\n\tfunction applyOrphanGC(candidates: readonly string[]): void {\n\t\tif (orphanGC !== \"remove\") return;\n\t\tfor (const candidate of candidates) {\n\t\t\tif (!entitiesMap.has(candidate)) continue;\n\t\t\tif (entityHasReferences(candidate)) continue;\n\t\t\tentitiesMap.delete(candidate);\n\t\t\tevents.append({\n\t\t\t\taction: \"orphanRemove\" as const,\n\t\t\t\tid: candidate,\n\t\t\t\tt_ns: wallClockNs(),\n\t\t\t\tseq: bumpCursor(seqCursor),\n\t\t\t});\n\t\t}\n\t}\n\n\tconst upsertEntityImpl = (id: string, value: TEntity): void => {\n\t\tentitiesMap.set(id, value);\n\t};\n\tconst removeEntityImpl = (id: string): void => {\n\t\tconst snapshot = edgesMap.entries.cache as\n\t\t\t| ReadonlyMap<string, KnowledgeEdge<TRelation>>\n\t\t\t| undefined;\n\t\t// Collect both the edge-keys to drop AND the entity ids those edges\n\t\t// reference (other than `id` itself) — the latter become orphan-GC\n\t\t// candidates after the cascade. (C1 fix — the previous impl only\n\t\t// applied orphan GC inside `unlink`, so cascading entity removal\n\t\t// could leave dangling orphans.)\n\t\tconst cascadedNeighbors = new Set<string>();\n\t\tif (snapshot) {\n\t\t\tconst toDrop: string[] = [];\n\t\t\tfor (const [key, edge] of snapshot) {\n\t\t\t\tif (edge.from === id || edge.to === id) {\n\t\t\t\t\ttoDrop.push(key);\n\t\t\t\t\tif (edge.from !== id) cascadedNeighbors.add(edge.from);\n\t\t\t\t\tif (edge.to !== id) cascadedNeighbors.add(edge.to);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (toDrop.length > 0) edgesMap.deleteMany(toDrop);\n\t\t}\n\t\tif (entitiesMap.has(id)) entitiesMap.delete(id);\n\t\tapplyOrphanGC([...cascadedNeighbors]);\n\t};\n\tconst linkImpl = (from: string, to: string, relation: TRelation, weight = 1): void => {\n\t\tedgesMap.set(tripleKey(from, to, relation), { from, to, relation, weight });\n\t};\n\tconst unlinkImpl = (from: string, to: string, relation?: TRelation): void => {\n\t\tif (relation !== undefined) {\n\t\t\tedgesMap.delete(tripleKey(from, to, relation));\n\t\t} else {\n\t\t\tconst snapshot = edgesMap.entries.cache as\n\t\t\t\t| ReadonlyMap<string, KnowledgeEdge<TRelation>>\n\t\t\t\t| undefined;\n\t\t\tif (!snapshot) return;\n\t\t\tconst toDrop: string[] = [];\n\t\t\tfor (const [key, edge] of snapshot) {\n\t\t\t\tif (edge.from === from && edge.to === to) toDrop.push(key);\n\t\t\t}\n\t\t\tif (toDrop.length > 0) edgesMap.deleteMany(toDrop);\n\t\t}\n\t\tapplyOrphanGC([from, to]);\n\t};\n\n\tconst upsertEntity = mutate(upsertEntityImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: ([id], _r, m) => ({\n\t\t\taction: \"upsertEntity\" as const,\n\t\t\tid,\n\t\t\tt_ns: m.t_ns,\n\t\t\tseq: m.seq,\n\t\t}),\n\t});\n\tconst removeEntity = mutate(removeEntityImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: ([id], _r, m) => ({\n\t\t\taction: \"removeEntity\" as const,\n\t\t\tid,\n\t\t\tt_ns: m.t_ns,\n\t\t\tseq: m.seq,\n\t\t}),\n\t});\n\tconst link = mutate(linkImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: ([from, to, relation, weight], _r, m) => ({\n\t\t\taction: \"link\" as const,\n\t\t\tfrom,\n\t\t\tto,\n\t\t\trelation: relation as string,\n\t\t\tweight: weight ?? 1,\n\t\t\tt_ns: m.t_ns,\n\t\t\tseq: m.seq,\n\t\t}),\n\t});\n\tconst unlink = mutate(unlinkImpl, {\n\t\tframe: \"inline\",\n\t\tlog: events,\n\t\tseq: seqCursor,\n\t\tonSuccessRecord: ([from, to, relation], _r, m) => ({\n\t\t\taction: \"unlink\" as const,\n\t\t\tfrom,\n\t\t\tto,\n\t\t\t...(relation !== undefined ? { relation: relation as string } : {}),\n\t\t\tt_ns: m.t_ns,\n\t\t\tseq: m.seq,\n\t\t}),\n\t});\n\n\tfunction relatedNode(\n\t\tid: NodeOrValue<string>,\n\t\trelation?: NodeOrValue<TRelation>,\n\t): Node<readonly KnowledgeEdge<TRelation>[]> {\n\t\tconst idN = toNode(id, \"id\");\n\t\t// `relation` is OPTIONAL. We deliberately do NOT include it as a dep\n\t\t// when omitted — `state(undefined)` would be a SENTINEL and the\n\t\t// derived's first-run gate would never open. Callers pass a Node\n\t\t// when they want reactive filtering; pass a value to lock the\n\t\t// filter; omit to disable filtering.\n\t\tconst relN = relation !== undefined ? toNode(relation, \"relation\") : undefined;\n\t\tconst deps: Node<unknown>[] = relN\n\t\t\t? [adjacencyOut, adjacencyIn, idN, relN]\n\t\t\t: [adjacencyOut, adjacencyIn, idN];\n\t\treturn node(\n\t\t\tdeps,\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst values = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst out = values[0] as ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>;\n\t\t\t\tconst inb = values[1] as ReadonlyMap<string, readonly KnowledgeEdge<TRelation>[]>;\n\t\t\t\tconst key = values[2] as string;\n\t\t\t\tconst rel = relN ? (values[3] as TRelation | undefined) : undefined;\n\t\t\t\tconst outE = out?.get(key) ?? [];\n\t\t\t\tconst inE = inb?.get(key) ?? [];\n\t\t\t\t// Concatenate, then dedupe by triple key (a self-loop would appear in both).\n\t\t\t\tconst seen = new Set<string>();\n\t\t\t\tconst acc: KnowledgeEdge<TRelation>[] = [];\n\t\t\t\tfor (const edge of outE) {\n\t\t\t\t\tconst k = tripleKey(edge.from, edge.to, edge.relation);\n\t\t\t\t\tif (seen.has(k)) continue;\n\t\t\t\t\tif (rel !== undefined && edge.relation !== rel) continue;\n\t\t\t\t\tseen.add(k);\n\t\t\t\t\tacc.push(edge);\n\t\t\t\t}\n\t\t\t\tfor (const edge of inE) {\n\t\t\t\t\tconst k = tripleKey(edge.from, edge.to, edge.relation);\n\t\t\t\t\tif (seen.has(k)) continue;\n\t\t\t\t\tif (rel !== undefined && edge.relation !== rel) continue;\n\t\t\t\t\tseen.add(k);\n\t\t\t\t\tacc.push(edge);\n\t\t\t\t}\n\t\t\t\tactions.emit(acc as readonly KnowledgeEdge<TRelation>[]);\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tequals: (a, b) => {\n\t\t\t\t\tconst av = a as readonly KnowledgeEdge<TRelation>[] | undefined;\n\t\t\t\t\tconst bv = b as readonly KnowledgeEdge<TRelation>[] | undefined;\n\t\t\t\t\tif (av === bv) return true;\n\t\t\t\t\tif (av == null || bv == null) return false;\n\t\t\t\t\tif (av.length !== bv.length) return false;\n\t\t\t\t\tfor (let i = 0; i < av.length; i += 1) {\n\t\t\t\t\t\tconst x = av[i]!;\n\t\t\t\t\t\tconst y = bv[i]!;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tx.from !== y.from ||\n\t\t\t\t\t\t\tx.to !== y.to ||\n\t\t\t\t\t\t\tx.relation !== y.relation ||\n\t\t\t\t\t\t\tx.weight !== y.weight\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\t\t\t\tmeta: memoryMeta(\"related\"),\n\t\t\t},\n\t\t) as Node<readonly KnowledgeEdge<TRelation>[]>;\n\t}\n\n\tconst out = Object.assign(graph, {\n\t\tevents,\n\t\tentities: entitiesMap.entries,\n\t\tedges: edgesMap.entries,\n\t\tadjacencyOut,\n\t\tadjacencyIn,\n\t\tentityCount,\n\t\tedgeCount,\n\t\tupsertEntity,\n\t\tremoveEntity,\n\t\tlink,\n\t\tunlink,\n\t\trelatedNode,\n\t}) as KnowledgeGraph<TEntity, TRelation>;\n\treturn out;\n}\n\n// ── DS-14.7: reactiveFactStore (static-topology MEME L2/L3 substrate) ─────\n// Lives in its own file (`fact-store.ts`) — re-exported here so the\n// `utils/memory` barrel stays the single import surface alongside\n// collection / vectorIndex / knowledgeGraph.\nexport {\n\ttype AdmissionFilter,\n\ttype CascadeEvent,\n\ttype CascadeOverflow,\n\ttype CascadeReason,\n\ttype DecayPolicy,\n\ttype DependentsIndex,\n\ttype FactId,\n\ttype FactStore,\n\ttype FactStoreAuditRecord,\n\ttype MemoryAnswer,\n\ttype MemoryFragment,\n\ttype MemoryQuery,\n\ttype OutcomeSignal,\n\ttype ReactiveFactStoreConfig,\n\ttype ReactiveFactStoreGraph,\n\ttype ReviewRequest,\n\treactiveFactStore,\n\ttype ScoringPolicy,\n\ttype ShardKey,\n\ttype StoreReadHandle,\n} from \"./fact-store.js\";\n","/**\n * DS-14.7 — Reactive Fact Store / Live Knowledge Graph (locked 2026-05-13).\n *\n * Static-topology agent-memory substrate that satisfies MEME L2 (cascade\n * invalidation) and L3 (obsolescence reasoning) plus Hassabis's\n * filter/consolidate/continual-learning frame, **without** materializing one\n * reactive node per fact. ~12 fixed operator nodes never grow regardless of how\n * many facts the store holds; facts live as columnar DATA inside an indexed\n * `state<FactStore>` (optionally sharded), and cascade is implemented as\n * bounded recursive message emission. Termination rests on a per-root\n * semantic contract — a fact only drives the cascade when it transitions to\n * obsolete (`validTo` set), and each obsolete root emits its cascade exactly\n * once across all waves — plus an empty-array fixpoint short-circuit. The\n * cascade is modeled as DATA arrays (NOT INVALIDATE messages), so spec §1.4's\n * idempotent-within-a-wave INVALIDATE guarantee does NOT govern this loop;\n * convergence is the per-root contract, not a spec §1.4 diamond-merge.\n *\n * Canonical design: `archive/docs/SESSION-DS-14.7-reactive-fact-store.md`\n * (9Q walk complete; Q9-open items 1–9 all resolved).\n *\n * Locked decisions baked in here:\n * - `cascadeMaxIterations` default **8**; overflow emits a per-batch summary\n * `{ droppedCount, sample, rootFactId }` to `cascadeOverflow` (Q9-open-4).\n * The overflow `sample` is capped at `OVERFLOW_SAMPLE_SIZE` (8),\n * independent of `cascadeMaxIterations`.\n * - `shardBy` default hash-mod **4**; caller override; `dependentsIndex`\n * unsharded for v1 (Q9-open-1).\n * - `MemoryFragment` adds `embedding? / parent_fragment_id? / provenance?`\n * (Q9-open-3).\n * - `dependentsIndex` updates synchronous + atomic with `factStore` commit\n * (Q9-open-2).\n * - Scoring contract `(fragment, storeReadHandle) => number` — read-only\n * handle, no mutation exposure (Q9-open-5).\n * - Consolidator emits to a dedicated `consolidated` topic that the pattern\n * default-wires back to `ingest`; caller can intercept (Q9-open-6).\n * - Query surface = structured `MemoryQuery` via the `query` topic (default);\n * function-shaped is caller-side `derived` over `factStore` (Q9-open-7).\n * - Bi-temporal is pattern-layer only — no DS-14 envelope shape change\n * (Q9-open-9); `simpleFactStore()` deferred to v1.1 (Q9-open-8 — NOT built).\n *\n * **Cascade cycle visibility.** `cascadeProcessor` stays synchronous (preserves\n * spec §1.4 batch-dedupe — LLM-driven dependency extraction lives UPSTREAM of\n * the cascade topic, never inside the recursion). Every cascade message carries\n * a `causalReason` field and the cycle nodes are tagged `meta.cycle:\"cascade\"`\n * so `describe()` / `explain()` surface the otherwise-invisible\n * `dependentsIndex` fn-body lookup.\n *\n * @module\n */\n\nimport { type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport type { ReactiveLogBundle } from \"@graphrefly/pure-ts/extra\";\nimport { keepalive, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport {\n\ttype BaseAuditRecord,\n\tbumpCursor,\n\tcreateAuditLog,\n\tregisterCursor,\n} from \"../../base/mutation/index.js\";\n\n// ── Public types ─────────────────────────────────────────────────────────\n\n/** Stable identity for a stored fact. */\nexport type FactId = string;\n\n/** Shard partition key (string | number — any hashable scalar). */\nexport type ShardKey = string | number;\n\n/**\n * A single stored memory fact. Pattern convention only — NOT a spec primitive\n * and NOT a DS-14 envelope field (bi-temporal stays pattern-layer per\n * Q9-open-9). Each field is a reactive lever (see design PART 2.3):\n * `validTo` set → cascade fires; `confidence < θ` → review; `sources` →\n * `dependentsIndex` edges feeding cascade.\n */\nexport interface MemoryFragment<T> {\n\treadonly id: FactId;\n\treadonly payload: T;\n\t/** Transaction time (when learned). `bigint` ns (e.g. `BigInt(monotonicNs())`). */\n\treadonly t_ns: bigint;\n\t/** Valid-time start. `undefined` = unbounded past. */\n\treadonly validFrom?: bigint;\n\t/** Valid-time end. Setting this is the MEME L3 obsolescence lever. */\n\treadonly validTo?: bigint;\n\t/** Confidence 0..1. Dropping below the review threshold emits a review. */\n\treadonly confidence: number;\n\treadonly tags: readonly string[];\n\t/** Dependency edges — fact IDs this fact is derived from / depends on. */\n\treadonly sources: readonly FactId[];\n\t/** Optional dense embedding (recipes use it for retrieval). */\n\treadonly embedding?: readonly number[];\n\t/** Version-chain pointer — consolidator emits successor fragments. */\n\treadonly parent_fragment_id?: FactId;\n\t/** Free-form provenance string for audit. */\n\treadonly provenance?: string;\n}\n\n/**\n * Columnar in-memory store. Held as DATA inside a `state<FactStore<T>>` node\n * (one per shard). `byId` is the authoritative map; the typed companions are\n * kept for the recipe layer (`bitemporal-query`, `influence-analysis`) — v1\n * stores fragments directly and lazily projects columns on demand.\n */\nexport interface FactStore<T> {\n\treadonly byId: ReadonlyMap<FactId, MemoryFragment<T>>;\n}\n\n/** Reverse dependency index: fact → IDs that depend on it. Unsharded (v1). */\nexport type DependentsIndex = ReadonlyMap<FactId, readonly FactId[]>;\n\n/** Read-only projection passed to scoring policies (no mutation surface). */\nexport interface StoreReadHandle<T> {\n\tget(id: FactId): MemoryFragment<T> | undefined;\n\thas(id: FactId): boolean;\n\treadonly size: number;\n\tvalues(): IterableIterator<MemoryFragment<T>>;\n}\n\nexport type ScoringPolicy<T> = (fragment: MemoryFragment<T>, store: StoreReadHandle<T>) => number;\nexport type DecayPolicy = (confidence: number, ageNs: bigint) => number;\nexport type AdmissionFilter<T> = (fragment: MemoryFragment<T>) => boolean;\n\n/** Outcome / RL signal — write-back lever for continual learning. */\nexport interface OutcomeSignal {\n\treadonly factId: FactId;\n\treadonly reward: number;\n}\n\n/** Structured query (Q9-open-7 default surface). Serializable + inspectable. */\nexport interface MemoryQuery {\n\t/** Match any of these tags (OR). Omit for no tag filter. */\n\treadonly tags?: readonly string[];\n\t/** Bi-temporal \"as of\" — only facts valid at this instant. */\n\treadonly asOf?: bigint;\n\t/** Minimum confidence (inclusive). */\n\treadonly minConfidence?: number;\n\t/** Cap results (sorted by confidence desc, then t_ns desc). */\n\treadonly limit?: number;\n}\n\nexport interface MemoryAnswer<T> {\n\treadonly query: MemoryQuery;\n\treadonly results: readonly MemoryFragment<T>[];\n}\n\nexport type CascadeReason = \"cascade\" | \"obsolete\" | \"manual\";\n\n/** A single cascade invalidation message flowing through the cascade cycle. */\nexport interface CascadeEvent {\n\treadonly factId: FactId;\n\treadonly rootFactId: FactId;\n\treadonly reason: CascadeReason;\n\t/**\n\t * The triggering root fact's own `validTo`. Cascade-invalidated dependents\n\t * inherit this (NOT a fresh wall-clock read), so the store is a\n\t * deterministic rebuildable projection: replaying the same ingest stream\n\t * yields byte-identical `validTo` on cascade-invalidated fragments. Each\n\t * dependent inherits the `validTo` of the *nearest obsolete fact that\n\t * drove its invalidation*: in a pure chain A→B→C where only A is\n\t * explicitly obsoleted, B and C both inherit A's `validTo` (B has no own\n\t * `validTo`, so when B becomes a cascade root the detector reads\n\t * `B.validTo` === A's value). If an intermediate B is itself explicitly\n\t * obsoleted with its *own* `validTo`, B's dependents inherit B's value,\n\t * not A's — \"stale from when its driving source was invalidated.\"\n\t * Deterministic either way. Always defined: only obsolete facts\n\t * (`validTo` set) drive the cascade as roots.\n\t */\n\treadonly rootValidTo: bigint;\n\t/** Cascade recursion depth (1 = first wave). Bounded by `cascadeMaxIterations`. */\n\treadonly iteration: number;\n\t/**\n\t * Human-readable causal chain — makes the `dependentsIndex` fn-body lookup\n\t * visible in `explain()` output even though it is not a topology edge\n\t * (design Q3 / COMPOSITION-GUIDE §24 mitigation).\n\t */\n\treadonly causalReason: string;\n}\n\n/** Per-batch overflow summary (Q9-open-4 — never per-message). */\nexport interface CascadeOverflow {\n\treadonly droppedCount: number;\n\treadonly sample: readonly FactId[];\n\treadonly rootFactId: FactId;\n}\n\nexport interface ReviewRequest {\n\treadonly factId: FactId;\n\treadonly confidence: number;\n\treadonly threshold: number;\n}\n\nexport interface FactStoreAuditRecord extends BaseAuditRecord {\n\treadonly action: \"ingest\" | \"invalidate\" | \"outcome\" | \"consolidate\" | \"overflow\";\n\treadonly id?: FactId;\n\treadonly reason?: CascadeReason;\n}\n\nexport interface ReactiveFactStoreConfig<T> {\n\t// ① Function hooks (no reactive policy needed).\n\treadonly extractDependencies: (f: MemoryFragment<T>) => readonly FactId[];\n\t/** Shard partition fn. Default: FNV-1a hash of `id` mod `shardCount`. */\n\treadonly shardBy?: (f: MemoryFragment<T>) => ShardKey;\n\t/** Shard count for the default hash-mod sharder. Default 4 (§3.2). */\n\treadonly shardCount?: number;\n\n\t// ② Node<Policy> hooks (reactive — policy itself can evolve).\n\treadonly scoring?: Node<ScoringPolicy<T>>;\n\treadonly decay?: Node<DecayPolicy>;\n\treadonly admissionFilter?: Node<AdmissionFilter<T>>;\n\n\t// ③ Topic inputs (caller wires upstream sources).\n\treadonly ingest: Node<MemoryFragment<T>>;\n\treadonly outcome?: Node<OutcomeSignal>;\n\treadonly query?: Node<MemoryQuery>;\n\t/**\n\t * Consolidator trigger — a reactive timer/cron Node (e.g. `fromCron(...)`).\n\t * When supplied, the `consolidated` node maps each tick to summarized\n\t * fragments emitted on the `consolidated` topic and default-wired back to\n\t * the internal ingest path.\n\t */\n\treadonly consolidateTrigger?: Node<unknown>;\n\t/**\n\t * Consolidation summarizer. Reads a store snapshot, returns successor\n\t * fragments (typically with `parent_fragment_id` set). Default: no-op\n\t * (emits nothing) so the cron tick is observable without forcing a policy.\n\t */\n\treadonly consolidate?: (store: StoreReadHandle<T>) => readonly MemoryFragment<T>[];\n\n\t// Invariants.\n\t/** Cascade recursion cap (§3.1). Default 8. */\n\treadonly cascadeMaxIterations?: number;\n\t/** Confidence below which a {@link ReviewRequest} is emitted. Default 0.3. */\n\treadonly reviewThreshold?: number;\n\n\t// Persistence.\n\t/**\n\t * Record every committed fragment (post-admission-filter, with full\n\t * payload) into a replayable {@link ReactiveFactStoreGraph.ingestLog}.\n\t * Default `false` (the log retains every fragment in memory — opt in only\n\t * when you intend to persist + replay).\n\t *\n\t * Enables the canonical **rebuildable-projection** recipe: the store is a\n\t * deterministic projection of its ingest stream (cascade `validTo` is\n\t * derived from the triggering root, not wall-clock; consolidator successors\n\t * are re-derived from replayed state, not logged — the projection is still\n\t * deterministic), so persisting the ingest log and replaying it on restart\n\t * reconstructs a byte-identical store. Pair with the BigInt-safe codec\n\t * ({@link MemoryFragment} carries `bigint` time fields). The tier MUST be\n\t * `mode:\"append\"` (the default) — `attachStorage` ships per-wave deltas, so\n\t * an `\"overwrite\"` tier would truncate the log (and `attachStorage` now\n\t * throws on one).\n\t *\n\t * **First run — persist:**\n\t * ```ts\n\t * import { reactiveFactStore } from \"@graphrefly/graphrefly\";\n\t * import { appendLogStorage, bigintJsonCodecFor } from \"@graphrefly/pure-ts/extra\";\n\t *\n\t * const tier = appendLogStorage(backend, {\n\t * name: \"facts-ingest\",\n\t * codec: bigintJsonCodecFor<readonly MemoryFragment<Doc>[]>(),\n\t * });\n\t * const mem = reactiveFactStore<Doc>({ ingest, extractDependencies, recordIngest: true });\n\t * mem.ingestLog!.attachStorage([tier]); // forwards every committed fragment\n\t * ```\n\t *\n\t * **Restart — replay (rebuild the projection):** read the persisted entries\n\t * and feed them through `config.ingest`. Replay is just the reactive input —\n\t * there is no imperative restore primitive.\n\t * ```ts\n\t * const { entries } = await tier.loadEntries!();\n\t * const mem = reactiveFactStore<Doc>({ ingest, extractDependencies });\n\t * for (const f of entries) ingest.emit(f); // identical store rebuilt\n\t * ```\n\t *\n\t * **Do NOT do both at once.** On restart, either replay through `ingest`\n\t * (above) **or** rely on `attachStorage`'s auto-restore — never both:\n\t * `attachStorage` restores the persisted entries into a fresh `ingestLog`,\n\t * and a manual replay loop would then re-append + re-persist them (doubling\n\t * the durable log every restart). If you want continued persistence on the\n\t * rebuilt store, set `recordIngest:true` and call `attachStorage([tier])`\n\t * **after** the replay loop completes (the log already holds the replayed\n\t * fragments, so `attachStorage` ships no spurious deltas).\n\t *\n\t * **Memory:** the in-memory log is unbounded (every committed fragment is\n\t * retained for the store's lifetime). For a long-lived high-volume store,\n\t * `ingestLog.trimHead(n)` after a confirmed `tier.flush()` bounds it (the\n\t * durable tier remains the full record).\n\t */\n\treadonly recordIngest?: boolean;\n}\n\nexport interface ReactiveFactStoreGraph<T> extends Graph {\n\t// ④ Topic outputs (caller subscribes for custom processing).\n\t/** Per-shard `state<FactStore<T>>` nodes (length = shard count). */\n\treadonly shards: readonly Node<FactStore<T>>[];\n\t/** Unified read view across all shards (derived). */\n\treadonly factStore: Node<FactStore<T>>;\n\treadonly dependentsIndex: Node<DependentsIndex>;\n\treadonly answer: Node<MemoryAnswer<T> | null>;\n\treadonly cascade: Node<readonly CascadeEvent[]>;\n\treadonly cascadeOverflow: Node<CascadeOverflow | null>;\n\treadonly review: Node<ReviewRequest | null>;\n\treadonly consolidated: Node<readonly MemoryFragment<T>[]>;\n\treadonly events: ReactiveLogBundle<FactStoreAuditRecord>;\n\t/**\n\t * Payload-carrying, replayable log of every committed fragment. Present iff\n\t * {@link ReactiveFactStoreConfig.recordIngest} is `true`. Unlike\n\t * {@link ReactiveFactStoreGraph.events} (action-only audit), each entry is\n\t * the full {@link MemoryFragment} — `attachStorage` it for a durable,\n\t * replayable projection source (see `recordIngest` docs for the recipe).\n\t */\n\treadonly ingestLog?: ReactiveLogBundle<MemoryFragment<T>>;\n\t/** Reactive read: a single fact by id (SENTINEL until the fact exists). */\n\titemNode(id: FactId): Node<MemoryFragment<T> | undefined>;\n}\n\n// ── Constants ────────────────────────────────────────────────────────────\n\n/**\n * Max number of dropped cascade-target ids included in a {@link CascadeOverflow}\n * `sample`. Deliberately decoupled from `cascadeMaxIterations` — it bounds the\n * diagnostic payload size, not the recursion budget.\n */\nconst OVERFLOW_SAMPLE_SIZE = 8;\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction factMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"memory\", kind, extra);\n}\n\n/** Deterministic, universal-safe FNV-1a 32-bit string hash (no `node:crypto`). */\nfunction fnv1a(s: string): number {\n\tlet h = 0x811c9dc5;\n\tfor (let i = 0; i < s.length; i += 1) {\n\t\th ^= s.charCodeAt(i);\n\t\t// 32-bit FNV prime multiply via shifts (avoids BigInt / float drift).\n\t\th = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;\n\t}\n\treturn h >>> 0;\n}\n\nfunction makeReadHandle<T>(byId: ReadonlyMap<FactId, MemoryFragment<T>>): StoreReadHandle<T> {\n\treturn {\n\t\tget: (id) => byId.get(id),\n\t\thas: (id) => byId.has(id),\n\t\tget size() {\n\t\t\treturn byId.size;\n\t\t},\n\t\tvalues: () => byId.values(),\n\t};\n}\n\n/** Bi-temporal validity test: is `f` valid at instant `asOf`? */\nfunction currentlyValid<T>(f: MemoryFragment<T>, asOf?: bigint): boolean {\n\tif (asOf === undefined) return f.validTo === undefined;\n\tif (f.validFrom !== undefined && asOf < f.validFrom) return false;\n\tif (f.validTo !== undefined && asOf >= f.validTo) return false;\n\treturn true;\n}\n\nfunction lastOf<X>(batch: readonly unknown[] | undefined, prev: unknown): X | undefined {\n\treturn batch != null && batch.length > 0 ? (batch.at(-1) as X) : (prev as X | undefined);\n}\n\n// ── Factory ──────────────────────────────────────────────────────────────\n\n/**\n * Build a static-topology reactive fact store (DS-14.7 architecture C).\n *\n * Topology (~12 fixed nodes — never grows with fact count):\n * - `shards[0..N]` — `state<FactStore<T>>` columnar stores (default 4 shards).\n * - `factStore` — derived union read view across shards.\n * - `dependentsIndex` — `state<DependentsIndex>` reverse-dep map, unsharded,\n * updated synchronously + atomically with each commit (Q9-open-2).\n * - `extractOp` — derived: ingest → admission-filtered fragment + dep edges.\n * - `invalidationDetector` — derived: scans committed store for `validTo`-set\n * / low-confidence facts, resolves dependents via `dependentsIndex`, emits\n * cascade messages.\n * - `cascade` — topic node carrying `CascadeEvent[]`.\n * - `cascadeProcessor` — derived, **synchronous**, `meta.cycle:\"cascade\"`:\n * dedupes by factId, writes invalidations back to shards, recurses until\n * fixpoint OR `cascadeMaxIterations` → `cascadeOverflow`.\n * - `cascadeOverflow` — per-batch overflow summary node.\n * - `queryOp` / `answer` — structured `MemoryQuery` → results (SENTINEL-safe).\n * - `outcomeProcessor` — outcome signal → confidence write-back.\n * - `consolidated` — cron-tick → summarized fragments on the\n * `consolidated` topic,\n * default-wired back into the ingest path.\n * - `review` — low-confidence proactive-verification requests.\n *\n * The cascade cycle (`invalidationDetector → cascade → cascadeProcessor →\n * shards → invalidationDetector`) is a real, bounded reactive cycle. Both\n * `invalidationDetector` and `cascadeProcessor` are tagged\n * `meta.cycle:\"cascade\"` and every cascade message carries `causalReason`, so\n * `describe()` / `explain()` surface the otherwise-invisible\n * `dependentsIndex` lookup (COMPOSITION-GUIDE §24).\n *\n * @category memory\n */\nexport function reactiveFactStore<T>(\n\tconfig: ReactiveFactStoreConfig<T>,\n): ReactiveFactStoreGraph<T> {\n\tconst shardCount = Math.max(1, config.shardCount ?? 4);\n\tconst maxIterations = Math.max(1, config.cascadeMaxIterations ?? 8);\n\tconst reviewThreshold = config.reviewThreshold ?? 0.3;\n\tconst shardBy = config.shardBy ?? ((f: MemoryFragment<T>) => fnv1a(String(f.id)) % shardCount);\n\n\t// Cascade recursion depth counter. Reset to 0 on every external ingest\n\t// (a fresh root = a fresh cascade budget) and on a true fixpoint (detector\n\t// emits `[]`). Bounded by `maxIterations`; overflow stops the recursion.\n\t// This counter is a *backstop* for pathological cycles only — primary\n\t// termination is the per-root semantic contract below (F1/F5).\n\tlet cascadeIteration = 0;\n\n\t// F1/F5 — per-root cascade dedupe across waves. A fact only enters the\n\t// cascade as a root when it transitions to obsolete (`validTo` set), and\n\t// a given obsolete root emits its cascade exactly ONCE across all waves.\n\t// `processedRoots` tracks root ids that have already emitted; a root\n\t// re-detected in a later wave WITHOUT a new obsolescence transition does\n\t// not re-emit. This bounds the loop by the finite set of newly-obsolete\n\t// roots per external change, independent of `cascadeIteration` resets\n\t// (which an ingest / consolidator wire-back would otherwise defeat).\n\tconst processedRoots = new Set<FactId>();\n\n\tconst graph = new Graph(\"reactive_fact_store\") as ReactiveFactStoreGraph<T>;\n\n\tconst events = createAuditLog<FactStoreAuditRecord>({\n\t\tname: \"events\",\n\t\tretainedLimit: 1024,\n\t\tgraph,\n\t});\n\tconst seqCursor = registerCursor(graph, \"seq\", 0);\n\n\t// Opt-in payload-carrying ingest log (rebuildable-projection source).\n\t// Fed from `ingestAudit` (every committed fragment, post-admission).\n\tconst ingestLog: ReactiveLogBundle<MemoryFragment<T>> | undefined = config.recordIngest\n\t\t? reactiveLog<MemoryFragment<T>>([], { name: \"ingest_log\" })\n\t\t: undefined;\n\tif (ingestLog) graph.addDisposer(() => ingestLog.dispose());\n\n\t// ── shards: state<FactStore<T>> ──────────────────────────────────────\n\tconst emptyStore = (): FactStore<T> => ({ byId: new Map() });\n\tconst shards: Node<FactStore<T>>[] = [];\n\tfor (let s = 0; s < shardCount; s += 1) {\n\t\tconst shard = node<FactStore<T>>([], {\n\t\t\tinitial: emptyStore(),\n\t\t\tname: `shard_${s}`,\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: factMeta(\"factstore\", { shard: s }),\n\t\t});\n\t\tgraph.add(shard, { name: `shard_${s}` });\n\t\tgraph.addDisposer(keepalive(shard));\n\t\tshards.push(shard);\n\t}\n\n\tconst shardIndexFor = (f: MemoryFragment<T>): number => {\n\t\tconst key = shardBy(f);\n\t\tconst n = typeof key === \"number\" ? key : fnv1a(String(key));\n\t\tconst idx = ((n % shardCount) + shardCount) % shardCount;\n\t\treturn idx;\n\t};\n\n\t// Resolve which shard a given id lives in by scanning current snapshots\n\t// (cascade write-backs reference ids without re-deriving the fragment).\n\tconst findShardOf = (id: FactId): number => {\n\t\tfor (let s = 0; s < shardCount; s += 1) {\n\t\t\tconst fs = shards[s]!.cache as FactStore<T> | undefined;\n\t\t\tif (fs?.byId.has(id)) return s;\n\t\t}\n\t\treturn -1;\n\t};\n\n\tconst allFacts = (): Map<FactId, MemoryFragment<T>> => {\n\t\tconst out = new Map<FactId, MemoryFragment<T>>();\n\t\tfor (const sh of shards) {\n\t\t\tconst fs = sh.cache as FactStore<T> | undefined;\n\t\t\tif (!fs) continue;\n\t\t\tfor (const [k, v] of fs.byId) out.set(k, v);\n\t\t}\n\t\treturn out;\n\t};\n\n\tconst commitFragment = (f: MemoryFragment<T>): void => {\n\t\tconst idx = shardIndexFor(f);\n\t\tconst cur = (shards[idx]!.cache as FactStore<T> | undefined) ?? emptyStore();\n\t\tconst next = new Map(cur.byId);\n\t\tnext.set(f.id, f);\n\t\tshards[idx]!.emit({ byId: next });\n\t};\n\n\tconst replaceFragment = (\n\t\tid: FactId,\n\t\tmut: (prev: MemoryFragment<T>) => MemoryFragment<T>,\n\t): boolean => {\n\t\tconst idx = findShardOf(id);\n\t\tif (idx < 0) return false;\n\t\tconst cur = shards[idx]!.cache as FactStore<T>;\n\t\tconst prev = cur.byId.get(id);\n\t\tif (!prev) return false;\n\t\tconst next = new Map(cur.byId);\n\t\tnext.set(id, mut(prev));\n\t\tshards[idx]!.emit({ byId: next });\n\t\treturn true;\n\t};\n\n\t// ── dependentsIndex: state<DependentsIndex>, unsharded ───────────────\n\tconst dependentsIndex = node<DependentsIndex>([], {\n\t\tinitial: new Map() as DependentsIndex,\n\t\tname: \"dependents_index\",\n\t\tdescribeKind: \"state\",\n\t\tmeta: factMeta(\"factstore\", { role: \"dependents_index\" }),\n\t});\n\tgraph.add(dependentsIndex, { name: \"dependents_index\" });\n\tgraph.addDisposer(keepalive(dependentsIndex));\n\n\t// Synchronous + atomic with the commit (Q9-open-2): add reverse edges\n\t// `source → [..., fact.id]` for every dependency the fragment declares.\n\tconst indexFragment = (f: MemoryFragment<T>, deps: readonly FactId[]): void => {\n\t\tconst cur = dependentsIndex.cache as DependentsIndex;\n\t\tconst next = new Map<FactId, FactId[]>();\n\t\tfor (const [k, v] of cur) next.set(k, [...v]);\n\t\tfor (const src of deps) {\n\t\t\tconst bucket = next.get(src) ?? [];\n\t\t\tif (!bucket.includes(f.id)) bucket.push(f.id);\n\t\t\tnext.set(src, bucket);\n\t\t}\n\t\tdependentsIndex.emit(next as DependentsIndex);\n\t};\n\n\t// ── factStore: unified read view (derived union over shards) ─────────\n\tconst factStore = node<FactStore<T>>(\n\t\tshards,\n\t\t(batchData, actions, ctx) => {\n\t\t\tvoid batchData;\n\t\t\tvoid ctx;\n\t\t\tactions.emit({ byId: allFacts() });\n\t\t},\n\t\t{\n\t\t\tname: \"fact_store\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: emptyStore(),\n\t\t\tmeta: factMeta(\"factstore\", { role: \"read_view\" }),\n\t\t\t// F10a: `allFacts()` builds a fresh Map every detector retrigger.\n\t\t\t// Fragments are immutable (replaced wholesale on mutation), so a\n\t\t\t// same-size + per-key-identity check is a sound structural equality\n\t\t\t// that stops `factStore` (and its `review` dependent) from re-firing\n\t\t\t// every cascade wave when nothing actually changed.\n\t\t\tequals: (a: FactStore<T>, b: FactStore<T>) => {\n\t\t\t\tif (a === b) return true;\n\t\t\t\tif (a.byId.size !== b.byId.size) return false;\n\t\t\t\tfor (const [k, v] of a.byId) {\n\t\t\t\t\tif (b.byId.get(k) !== v) return false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n\tgraph.add(factStore, { name: \"fact_store\" });\n\tgraph.addDisposer(keepalive(factStore));\n\n\t// ── extractOp: ingest → admission filter → commit + index ────────────\n\tconst extractOp = node<MemoryFragment<T> | null>(\n\t\tconfig.admissionFilter ? [config.ingest, config.admissionFilter] : [config.ingest],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst f = lastOf<MemoryFragment<T>>(batchData[0], ctx.prevData[0]);\n\t\t\tif (f == null) {\n\t\t\t\tactions.emit(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (config.admissionFilter) {\n\t\t\t\tconst filter = lastOf<AdmissionFilter<T>>(batchData[1], ctx.prevData[1]);\n\t\t\t\tif (filter && !filter(f)) {\n\t\t\t\t\tactions.emit(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst deps = config.extractDependencies(f);\n\t\t\t// External ingest = a fresh cascade root → reset the depth budget.\n\t\t\tcascadeIteration = 0;\n\t\t\t// F1/F5: a (re-)ingested id is a fresh fact version. Clear it from\n\t\t\t// `processedRoots` so a NEW obsolescence transition on this id\n\t\t\t// (e.g. re-ingest with `validTo` set) re-drives the cascade exactly\n\t\t\t// once, rather than being permanently suppressed.\n\t\t\tprocessedRoots.delete(f.id);\n\t\t\t// Synchronous + atomic: commit fragment, then index its dep edges.\n\t\t\tcommitFragment(f);\n\t\t\tindexFragment(f, deps);\n\t\t\tactions.emit(f);\n\t\t},\n\t\t{\n\t\t\tname: \"extract_op\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: factMeta(\"extract\"),\n\t\t},\n\t);\n\tgraph.add(extractOp, { name: \"extract_op\" });\n\tgraph.addDisposer(keepalive(extractOp));\n\n\t// ── invalidationDetector: store → cascade messages ───────────────────\n\t// F1/F5 per-root semantic contract: a fact drives the cascade as a root\n\t// ONLY when it is obsolete (`validTo` set). A low-confidence-but-still-live\n\t// fact (no `validTo`) does NOT by itself emit a cascade — it surfaces via\n\t// the `review` topic instead, so it cannot perpetually re-emit a cascade\n\t// every detector pass. Each obsolete root emits its cascade exactly once\n\t// across all waves (`processedRoots` dedupe): a root re-detected in a later\n\t// wave without a fresh obsolescence transition is skipped. Termination is\n\t// therefore bounded by the finite set of newly-obsolete roots per external\n\t// change — robust against `cascadeIteration` resets from ingest /\n\t// consolidator wire-back. The empty-array emit is the fixpoint\n\t// short-circuit; `cascadeMaxIterations` remains a backstop for pathological\n\t// LLM-extracted cycles (A→B→A) only.\n\tconst invalidationDetector = node<readonly CascadeEvent[]>(\n\t\t[...shards],\n\t\t(batchData, actions, ctx) => {\n\t\t\tvoid batchData;\n\t\t\tvoid ctx;\n\t\t\tconst facts = allFacts();\n\t\t\tconst index = dependentsIndex.cache as DependentsIndex;\n\t\t\tconst out: CascadeEvent[] = [];\n\t\t\tconst seen = new Set<FactId>();\n\t\t\tfor (const f of facts.values()) {\n\t\t\t\t// F1/F5(a): ONLY obsolete facts drive the cascade as roots. A\n\t\t\t\t// low-confidence-but-still-live fact is handled by `review`,\n\t\t\t\t// never by the cascade loop.\n\t\t\t\tconst obsolete = f.validTo !== undefined;\n\t\t\t\tif (!obsolete) continue;\n\t\t\t\t// F1/F5(b): each obsolete root emits its cascade exactly once\n\t\t\t\t// across all waves. A root re-detected later (still obsolete,\n\t\t\t\t// no fresh transition) is skipped — convergence is independent\n\t\t\t\t// of `cascadeIteration` resets.\n\t\t\t\tif (processedRoots.has(f.id)) continue;\n\t\t\t\tconst dependents = index.get(f.id) ?? [];\n\t\t\t\tfor (const dep of dependents) {\n\t\t\t\t\t// F3: only cascade onto dependents that are still live. A\n\t\t\t\t\t// non-existent fact (phantom edge — `extractDependencies`\n\t\t\t\t\t// named an un-ingested FactId) is NOT a live dependent;\n\t\t\t\t\t// neither is a dependent already carrying `validTo`.\n\t\t\t\t\tconst depFact = facts.get(dep);\n\t\t\t\t\tif (!depFact || depFact.validTo !== undefined) continue;\n\t\t\t\t\tconst k = `${f.id}->${dep}`;\n\t\t\t\t\tif (seen.has(k)) continue;\n\t\t\t\t\tseen.add(k);\n\t\t\t\t\tout.push({\n\t\t\t\t\t\tfactId: dep,\n\t\t\t\t\t\trootFactId: f.id,\n\t\t\t\t\t\treason: \"obsolete\",\n\t\t\t\t\t\t// `obsolete` guard above guarantees `f.validTo` is set.\n\t\t\t\t\t\trootValidTo: f.validTo as bigint,\n\t\t\t\t\t\titeration: cascadeIteration + 1,\n\t\t\t\t\t\tcausalReason: `dependentsIndex[${f.id}] → ${dep} (obsolete: validTo set)`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// Mark the root processed once considered (whether or not it\n\t\t\t\t// had a still-live dependent) — it must not re-drive a later\n\t\t\t\t// wave without a fresh obsolescence transition.\n\t\t\t\tprocessedRoots.add(f.id);\n\t\t\t}\n\t\t\tif (out.length === 0) {\n\t\t\t\t// True fixpoint — reset the depth counter so the next external\n\t\t\t\t// root starts a fresh cascade budget.\n\t\t\t\tcascadeIteration = 0;\n\t\t\t}\n\t\t\tactions.emit(out);\n\t\t},\n\t\t{\n\t\t\tname: \"invalidation_detector\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: [] as readonly CascadeEvent[],\n\t\t\tmeta: factMeta(\"invalidation\", { cycle: \"cascade\" }),\n\t\t},\n\t);\n\tgraph.add(invalidationDetector, { name: \"invalidation_detector\" });\n\tgraph.addDisposer(keepalive(invalidationDetector));\n\n\t// ── cascade topic node ───────────────────────────────────────────────\n\tconst cascade = node<readonly CascadeEvent[]>(\n\t\t[invalidationDetector],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst evts = lastOf<readonly CascadeEvent[]>(batchData[0], ctx.prevData[0]) ?? [];\n\t\t\tactions.emit(evts);\n\t\t},\n\t\t{\n\t\t\tname: \"cascade\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: [] as readonly CascadeEvent[],\n\t\t\tmeta: factMeta(\"cascade_topic\", { cycle: \"cascade\" }),\n\t\t},\n\t);\n\tgraph.add(cascade, { name: \"cascade\" });\n\tgraph.addDisposer(keepalive(cascade));\n\n\t// ── cascadeOverflow (per-batch summary, Q9-open-4) ───────────────────\n\tconst cascadeOverflow = node<CascadeOverflow | null>([], {\n\t\tinitial: null,\n\t\tname: \"cascade_overflow\",\n\t\tdescribeKind: \"state\",\n\t\tmeta: factMeta(\"cascade_overflow\"),\n\t});\n\tgraph.add(cascadeOverflow, { name: \"cascade_overflow\" });\n\tgraph.addDisposer(keepalive(cascadeOverflow));\n\n\t// ── cascadeProcessor (SYNCHRONOUS, meta.cycle:\"cascade\") ─────────────\n\t// Per-wave dedupe by target factId, mark each dependent obsolete\n\t// (write-back → re-triggers invalidationDetector), bounded by\n\t// `cascadeMaxIterations`. NOTE: this is DATA-array dedupe, NOT spec §1.4\n\t// INVALIDATE idempotency — termination comes from the detector's\n\t// obsolete-only + per-root-once contract plus the empty-array fixpoint\n\t// short-circuit, not a spec §1.4 guarantee.\n\tconst cascadeProcessor = node<readonly CascadeEvent[]>(\n\t\t[cascade],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst evts = lastOf<readonly CascadeEvent[]>(batchData[0], ctx.prevData[0]) ?? [];\n\t\t\tif (evts.length === 0) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Dedupe by target factId (diamond-merge at message granularity).\n\t\t\tconst byId = new Map<FactId, CascadeEvent>();\n\t\t\tfor (const e of evts) if (!byId.has(e.factId)) byId.set(e.factId, e);\n\n\t\t\tcascadeIteration += 1;\n\t\t\tif (cascadeIteration > maxIterations) {\n\t\t\t\t// Cap hit (pathological dependency web / cycle). Emit a\n\t\t\t\t// per-batch overflow summary (Q9-open-4) and STOP the recursion\n\t\t\t\t// definitively: do NOT write back (no shard mutation → detector\n\t\t\t\t// does not re-fire) and settle the cascade topic with `[]` so\n\t\t\t\t// the cycle breaks. `cascadeIteration` stays above the cap until\n\t\t\t\t// the next external ingest resets it (via extractOp), so a\n\t\t\t\t// degenerate cycle cannot immediately re-enter.\n\t\t\t\tconst sample = [...byId.keys()].slice(0, OVERFLOW_SAMPLE_SIZE);\n\t\t\t\tconst rootFactId = evts[0]?.rootFactId ?? \"\";\n\t\t\t\tcascadeOverflow.emit({\n\t\t\t\t\tdroppedCount: byId.size,\n\t\t\t\t\tsample,\n\t\t\t\t\trootFactId,\n\t\t\t\t});\n\t\t\t\tevents.append({\n\t\t\t\t\taction: \"overflow\",\n\t\t\t\t\treason: \"cascade\",\n\t\t\t\t\tid: rootFactId,\n\t\t\t\t\tt_ns: wallClockNs(),\n\t\t\t\t\tseq: bumpCursor(seqCursor),\n\t\t\t\t});\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Write-back: mark each dependent obsolete iff not already. Each\n\t\t\t// shard `emit` re-triggers `invalidationDetector` (it deps on\n\t\t\t// `[...shards]`) — that IS the recursion edge. No separate trigger\n\t\t\t// node is needed; the detector's \"still live\" predicate plus the\n\t\t\t// empty-emit fixpoint reset terminate the cycle.\n\t\t\t// Deterministic: the dependent inherits the triggering root's own\n\t\t\t// `validTo` (NOT a fresh `monotonicNs()` read), so replaying the\n\t\t\t// same ingest stream yields byte-identical `validTo`. Transitive\n\t\t\t// chains inherit the original root's time.\n\t\t\tfor (const [id, e] of byId) {\n\t\t\t\treplaceFragment(id, (prev) =>\n\t\t\t\t\tprev.validTo !== undefined ? prev : { ...prev, validTo: e.rootValidTo },\n\t\t\t\t);\n\t\t\t}\n\t\t\tactions.emit([...byId.values()]);\n\t\t},\n\t\t{\n\t\t\tname: \"cascade_processor\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: [] as readonly CascadeEvent[],\n\t\t\tmeta: factMeta(\"cascade_processor\", { cycle: \"cascade\" }),\n\t\t},\n\t);\n\tgraph.add(cascadeProcessor, { name: \"cascade_processor\" });\n\tgraph.addDisposer(keepalive(cascadeProcessor));\n\n\t// ── review: low-confidence proactive verification ────────────────────\n\tconst review = node<ReviewRequest | null>(\n\t\t[factStore],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst fs = lastOf<FactStore<T>>(batchData[0], ctx.prevData[0]);\n\t\t\tif (fs == null) {\n\t\t\t\tactions.emit(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const f of fs.byId.values()) {\n\t\t\t\tif (f.confidence < reviewThreshold && f.validTo === undefined) {\n\t\t\t\t\tactions.emit({\n\t\t\t\t\t\tfactId: f.id,\n\t\t\t\t\t\tconfidence: f.confidence,\n\t\t\t\t\t\tthreshold: reviewThreshold,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tactions.emit(null);\n\t\t},\n\t\t{\n\t\t\tname: \"review\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: null,\n\t\t\tmeta: factMeta(\"review\"),\n\t\t\t// F10a: dedupe on the requested factId (null === no request) so a\n\t\t\t// stable low-confidence fact does not re-emit a review every wave.\n\t\t\tequals: (a: ReviewRequest | null, b: ReviewRequest | null) =>\n\t\t\t\t(a?.factId ?? null) === (b?.factId ?? null),\n\t\t},\n\t);\n\tgraph.add(review, { name: \"review\" });\n\tgraph.addDisposer(keepalive(review));\n\n\t// ── outcomeProcessor: RL signal → confidence write-back ──────────────\n\tif (config.outcome) {\n\t\tconst outcomeProcessor = node<OutcomeSignal | null>(\n\t\t\tconfig.scoring ? [config.outcome, config.scoring] : [config.outcome],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst sig = lastOf<OutcomeSignal>(batchData[0], ctx.prevData[0]);\n\t\t\t\tif (sig == null) {\n\t\t\t\t\tactions.emit(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treplaceFragment(sig.factId, (prev) => {\n\t\t\t\t\tlet nextConf = prev.confidence;\n\t\t\t\t\tif (config.scoring) {\n\t\t\t\t\t\tconst policy = lastOf<ScoringPolicy<T>>(batchData[1], ctx.prevData[1]);\n\t\t\t\t\t\tif (policy) {\n\t\t\t\t\t\t\tnextConf = policy(prev, makeReadHandle(allFacts()));\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnextConf = Math.max(0, Math.min(1, prev.confidence + sig.reward));\n\t\t\t\t\t}\n\t\t\t\t\treturn { ...prev, confidence: nextConf };\n\t\t\t\t});\n\t\t\t\tactions.emit(sig);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"outcome_processor\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tinitial: null,\n\t\t\t\tmeta: factMeta(\"outcome\"),\n\t\t\t},\n\t\t);\n\t\tgraph.add(outcomeProcessor, { name: \"outcome_processor\" });\n\t\tgraph.addDisposer(keepalive(outcomeProcessor));\n\t}\n\n\t// ── queryOp / answer (structured MemoryQuery, SENTINEL-safe) ─────────\n\t// Per COMPOSITION-GUIDE §3/§10: `answer` emits `null` while there has been\n\t// no query yet (SENTINEL on the query dep). Downstream consumers use the\n\t// `=== null` guard.\n\tconst answer = node<MemoryAnswer<T> | null>(\n\t\tconfig.query ? [config.query, factStore] : [factStore],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (!config.query) {\n\t\t\t\tactions.emit(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst q = lastOf<MemoryQuery>(batchData[0], ctx.prevData[0]);\n\t\t\tconst fs = lastOf<FactStore<T>>(batchData[1], ctx.prevData[1]);\n\t\t\tif (q == null) {\n\t\t\t\t// No query has been issued yet — null per the SENTINEL guard.\n\t\t\t\tactions.emit(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst store = fs ?? emptyStore();\n\t\t\tlet results = [...store.byId.values()].filter((f) => {\n\t\t\t\tif (q.tags && q.tags.length > 0 && !q.tags.some((t) => f.tags.includes(t))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (q.minConfidence !== undefined && f.confidence < q.minConfidence) return false;\n\t\t\t\tif (!currentlyValid(f, q.asOf)) return false;\n\t\t\t\treturn true;\n\t\t\t});\n\t\t\tresults.sort((a, b) => b.confidence - a.confidence || Number(b.t_ns - a.t_ns));\n\t\t\tif (q.limit !== undefined) results = results.slice(0, Math.max(0, q.limit));\n\t\t\tactions.emit({ query: q, results });\n\t\t},\n\t\t{\n\t\t\tname: \"answer\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: null,\n\t\t\tmeta: factMeta(\"query\", { role: \"output\" }),\n\t\t},\n\t);\n\tgraph.add(answer, { name: \"answer\" });\n\tgraph.addDisposer(keepalive(answer));\n\n\t// ── consolidator (cron-fed) → consolidated topic → wired back ────────\n\tconst consolidated = node<readonly MemoryFragment<T>[]>(\n\t\tconfig.consolidateTrigger ? [config.consolidateTrigger] : [],\n\t\t(batchData, actions, ctx) => {\n\t\t\tvoid batchData;\n\t\t\tvoid ctx;\n\t\t\tif (!config.consolidateTrigger || !config.consolidate) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst fragments = config.consolidate(makeReadHandle(allFacts()));\n\t\t\t// Default wire-back into the ingest path (Q9-open-6): the pattern\n\t\t\t// commits + indexes successor fragments; callers that need to gate\n\t\t\t// can subscribe to `consolidated` and intercept.\n\t\t\tfor (const f of fragments) {\n\t\t\t\tconst deps = config.extractDependencies(f);\n\t\t\t\t// F1/F5: wired-back successor is a fresh fact version — same\n\t\t\t\t// processedRoots reset as the ingest path so a later obsolescence\n\t\t\t\t// of this id can re-cascade exactly once.\n\t\t\t\tprocessedRoots.delete(f.id);\n\t\t\t\tcommitFragment(f);\n\t\t\t\tindexFragment(f, deps);\n\t\t\t\tevents.append({\n\t\t\t\t\taction: \"consolidate\",\n\t\t\t\t\tid: f.id,\n\t\t\t\t\tt_ns: wallClockNs(),\n\t\t\t\t\tseq: bumpCursor(seqCursor),\n\t\t\t\t});\n\t\t\t}\n\t\t\tactions.emit(fragments);\n\t\t},\n\t\t{\n\t\t\tname: \"consolidated\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: [] as readonly MemoryFragment<T>[],\n\t\t\tmeta: factMeta(\"consolidator\"),\n\t\t},\n\t);\n\tgraph.add(consolidated, { name: \"consolidated\" });\n\tgraph.addDisposer(keepalive(consolidated));\n\n\t// ── ingest audit (records every committed fragment) ──────────────────\n\tconst ingestAudit = node<MemoryFragment<T> | null>(\n\t\t[extractOp],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst f = lastOf<MemoryFragment<T> | null>(batchData[0], ctx.prevData[0]);\n\t\t\tif (f != null) {\n\t\t\t\tevents.append({\n\t\t\t\t\taction: \"ingest\",\n\t\t\t\t\tid: f.id,\n\t\t\t\t\tt_ns: wallClockNs(),\n\t\t\t\t\tseq: bumpCursor(seqCursor),\n\t\t\t\t});\n\t\t\t\t// Payload-carrying replay log (opt-in). Append the full\n\t\t\t\t// committed fragment so the store is a rebuildable projection.\n\t\t\t\tingestLog?.append(f);\n\t\t\t}\n\t\t\tactions.emit(f ?? null);\n\t\t},\n\t\t{\n\t\t\tname: \"_ingest_audit\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: null,\n\t\t\tmeta: factMeta(\"audit\"),\n\t\t},\n\t);\n\tgraph.add(ingestAudit, { name: \"_ingest_audit\" });\n\tgraph.addDisposer(keepalive(ingestAudit));\n\n\t// ── itemNode reactive read ───────────────────────────────────────────\n\tfunction itemNode(id: FactId): Node<MemoryFragment<T> | undefined> {\n\t\treturn node<MemoryFragment<T> | undefined>(\n\t\t\t[factStore],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst fs = lastOf<FactStore<T>>(batchData[0], ctx.prevData[0]);\n\t\t\t\tactions.emit(fs?.byId.get(id));\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: `item_${id}`,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: factMeta(\"item\"),\n\t\t\t},\n\t\t);\n\t}\n\n\tconst out = Object.assign(graph, {\n\t\tshards: shards as readonly Node<FactStore<T>>[],\n\t\tfactStore,\n\t\tdependentsIndex,\n\t\tanswer,\n\t\tcascade,\n\t\tcascadeOverflow,\n\t\treview,\n\t\tconsolidated,\n\t\tevents,\n\t\t...(ingestLog ? { ingestLog } : {}),\n\t\titemNode,\n\t}) as ReactiveFactStoreGraph<T>;\n\treturn out;\n}\n","// ---------------------------------------------------------------------------\n// gaugesAsContext\n// ---------------------------------------------------------------------------\n\nimport type { Actor } from \"@graphrefly/pure-ts/core\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\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// graphFromSpec\n// ---------------------------------------------------------------------------\n\nimport { COMPLETE, ERROR, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { compileSpec, type GraphSpec, type GraphSpecCatalog } from \"../../graphspec/index.js\";\nimport { resolveToolHandlerResult, stripFences } from \"../_internal.js\";\nimport type { ChatMessage, LLMAdapter, LLMResponse } from \"../adapters/core/types.js\";\n\nexport type GraphFromSpecOptions = {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Fn/source catalog for resolving named node factories from the LLM-generated spec. */\n\tcatalog?: GraphSpecCatalog;\n\t/** Extra instructions appended to the system prompt. */\n\tsystemPromptExtra?: string;\n\t/**\n\t * Optional AbortSignal forwarded to `adapter.invoke({ signal })`. Lets\n\t * callers cancel the in-flight LLM call (e.g. when the reactive variant\n\t * supersedes mid-flight). When the signal aborts, the underlying call\n\t * propagates the abort and `graphFromSpec` rejects with the abort reason.\n\t */\n\tsignal?: AbortSignal;\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 specification with this structure:\n\n{\n \"name\": \"<graph_name>\",\n \"nodes\": {\n \"<node_name>\": {\n \"type\": \"state\" | \"derived\" | \"producer\" | \"effect\" | \"operator\",\n \"initial\": <initial_value_for_state_nodes>,\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}\n\nRules:\n- \"state\" nodes have no deps and hold user/LLM-writable values (knobs). Use \"initial\" for the starting value.\n- \"derived\" nodes have deps and compute from them (pure, no side effects).\n- \"effect\" nodes have deps but produce side effects (no return value).\n- \"producer\" nodes have no deps but generate values asynchronously.\n- \"operator\" nodes are parameterized transformations with deps.\n- Use \"deps\" inside each node to declare dependencies — no separate \"edges\" array.\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 {@link GraphSpec} which is validated, catalog-expanded,\n * and instantiated via {@link compileSpec} (gains catalog validation, template\n * expansion, and feedback wiring that `Graph.fromSnapshot` bypasses).\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 catalog for named node factories.\n * @returns A constructed Graph.\n * @throws On invalid LLM output, validation failure, or unresolvable deps.\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\tsignal: opts?.signal,\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\treturn compileSpec(parsed as GraphSpec, { catalog: opts?.catalog });\n}\n\n/**\n * Reactive variant of {@link graphFromSpec}: re-invokes the LLM and\n * recompiles the graph whenever `input` emits a new natural-language\n * description. Useful inside the harness or refine loop when the spec text\n * itself is a reactive value (e.g. fed by a `node([], { initial: ... })` knob, a memory\n * snapshot, or an upstream `promptNode` output).\n *\n * **Supersede:** when the input changes mid-flight, switchMap tears the\n * inner producer down. The producer's cleanup aborts the in-flight LLM\n * call via an internal `AbortController` (threaded into `graphFromSpec`'s\n * new `signal` option) AND destroys any Graph that lands after cancel —\n * no token leak, no unreferenced compiled graphs. If the user's input\n * already changed by the time the LLM responds, the about-to-be-discarded\n * Graph is freed instead of orphaned.\n *\n * **Lifetime of the latest emitted Graph:** the caller owns each Graph\n * that actually reaches them. If you keep multiple historical values, call\n * `prev?.destroy()` before storing the new one.\n *\n * @param input - Reactive source of natural-language descriptions.\n * @param adapter - LLM adapter for the generation call.\n * @param opts - Model options and optional catalog for named node factories.\n * @returns `Node<Graph | null>` — emits the latest compiled graph, or `null`\n * while the input is empty / unsettled.\n */\nexport function graphFromSpecReactive(\n\tinput: NodeInput<string>,\n\tadapter: LLMAdapter,\n\topts?: GraphFromSpecOptions,\n): Node<Graph | null> {\n\tconst inputNode = fromAny(input);\n\treturn switchMap<string, Graph | null>(inputNode, (nl) => {\n\t\tif (!nl || typeof nl !== \"string\" || nl.trim().length === 0) {\n\t\t\treturn node<Graph | null>([], { initial: null });\n\t\t}\n\t\t// Producer guarantees a single DATA + COMPLETE per upstream wave —\n\t\t// matches the `promptNode` shape (see Unit 1 review). On supersede,\n\t\t// switchMap tears down the producer; cleanup aborts the in-flight LLM\n\t\t// call AND destroys any Graph that lands post-abort (would otherwise\n\t\t// leak its mounted state nodes / storage handles until GC).\n\t\treturn node<Graph | null>(\n\t\t\t(_data, actions) => {\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tlet cancelled = false;\n\t\t\t\tgraphFromSpec(nl, adapter, { ...opts, signal: controller.signal })\n\t\t\t\t\t.then((g) => {\n\t\t\t\t\t\tif (cancelled) {\n\t\t\t\t\t\t\tg.destroy();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactions.emit(g);\n\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tif (cancelled) return;\n\t\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\t});\n\t\t\t\treturn () => {\n\t\t\t\t\tcancelled = true;\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ describeKind: \"producer\", ...{ name: \"graphFromSpec::call\" } },\n\t\t);\n\t});\n}\n","/**\n * LLM graph composition (roadmap §8.3).\n *\n * Declarative GraphSpec schema + compiler/decompiler for graph topology.\n * The LLM designs graphs as JSON; `compileSpec` instantiates them;\n * `decompileSpec` extracts them back. Templates support reusable subgraph\n * patterns. Feedback edges express bounded cycles via §8.1 feedback().\n *\n * **Tier 1.5.3 Phase 3 (2026-04-27):** `GraphSpec` is a structural alias of\n * {@link GraphDescribeOutput} with two LLM-author-friendly extras\n * (`templates?` / `feedback?`). Per-node factory references are encoded in\n * `meta.factory` + `meta.factoryArgs` (no more `fn` / `source` / `config` /\n * `initial` fields). State node initial values live in\n * `meta.factoryArgs.initial` (state self-tags with\n * `factoryTag(\"state\", { initial })`).\n *\n * @module\n */\n\nimport type { DescribeNodeOutput } from \"@graphrefly/pure-ts/core\";\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { GRAPH_META_SEGMENT, Graph, type GraphDescribeOutput } from \"@graphrefly/pure-ts/graph\";\nimport type { ChatMessage, LLMAdapter, LLMResponse } from \"../ai/index.js\";\nimport { feedback as feedbackPrimitive } from \"../reduction/index.js\";\n\n// ---------------------------------------------------------------------------\n// GraphSpec types — structural alias of GraphDescribeOutput\n// ---------------------------------------------------------------------------\n\n/**\n * A single node declaration in a GraphSpec — structural alias of\n * {@link DescribeNodeOutput}.\n *\n * Per-node factory provenance lives in `meta.factory` + `meta.factoryArgs`\n * (use {@link factoryTag} to stamp them at construction time). State node\n * initial values come through `meta.factoryArgs.initial` for tagged states,\n * with fallback to `value` (since spec projection retains state values).\n */\nexport type GraphSpecNode = DescribeNodeOutput;\n\n/** Template instantiation node — expanded at compile time. */\nexport type GraphSpecTemplateRef = {\n\ttype: \"template\";\n\t/** Name of the template to instantiate. */\n\ttemplate: string;\n\t/** Parameter bindings: template param name → node name. */\n\tbind: Record<string, string>;\n};\n\n/** A reusable subgraph pattern with parameter substitution. */\nexport type GraphSpecTemplate = {\n\t/** Parameter names (prefixed with $ in node refs). */\n\tparams: string[];\n\t/** Node declarations within the template. */\n\tnodes: Record<string, GraphSpecNode>;\n\t/** Which node's output is the template's output. */\n\toutput: string;\n};\n\n/** A feedback edge: bounded cycle from condition to reentry. */\nexport type GraphSpecFeedbackEdge = {\n\t/** Node whose DATA triggers the feedback. */\n\tfrom: string;\n\t/** State node that receives the feedback value. */\n\tto: string;\n\t/** Max iterations before stopping (default: 10). */\n\tmaxIterations?: number;\n};\n\n/**\n * Declarative graph topology for LLM composition (§8.3).\n *\n * Tier 1.5.3 Phase 3 (2026-04-27): structural alias of\n * {@link GraphDescribeOutput} extended with optional `templates` /\n * `feedback` fields for LLM-author convenience. Top-level `factory` /\n * `factoryArgs` (Phase 2.5 carry) ride along on every describe output.\n *\n * Round-trip property: `decompileSpec(g) === g.describe({ detail: \"spec\" })`\n * (modulo the small feedback-edge extraction sugar).\n */\nexport type GraphSpec = Omit<GraphDescribeOutput, \"nodes\" | \"expand\"> & {\n\t/** Node declarations (keyed by node name). Either a structural describe entry or a template ref. */\n\tnodes: Record<string, GraphSpecNode | GraphSpecTemplateRef>;\n\t/** Reusable subgraph templates (LLM-author extra; not present in `describe()` output). */\n\ttemplates?: Record<string, GraphSpecTemplate>;\n\t/** Feedback edges (bounded cycles, LLM-author extra). */\n\tfeedback?: GraphSpecFeedbackEdge[];\n};\n\n/**\n * Extract `meta.factory` from a node, if any. Pure read — no normalization.\n */\nfunction readFactory(node: GraphSpecNode): string | undefined {\n\tconst f = (node.meta as Record<string, unknown> | undefined)?.factory;\n\treturn typeof f === \"string\" ? f : undefined;\n}\n\n/**\n * Extract `meta.factoryArgs` from a node as a plain Record. Pure read.\n */\nfunction readFactoryArgs(node: GraphSpecNode): Record<string, unknown> {\n\tconst a = (node.meta as Record<string, unknown> | undefined)?.factoryArgs;\n\treturn a != null && typeof a === \"object\" ? (a as Record<string, unknown>) : {};\n}\n\n/**\n * Resolve the initial value for a state node. Prefers\n * `meta.factoryArgs.initial` (the path the `state()` factory itself stamps)\n * and falls back to `value` (in case the spec carries the resolved value\n * without a factory tag, e.g. from a hand-written spec).\n */\nfunction readStateInitial(node: GraphSpecNode): unknown {\n\tconst args = readFactoryArgs(node);\n\tif (\"initial\" in args) return args.initial;\n\treturn node.value;\n}\n\n// ---------------------------------------------------------------------------\n// Catalog types\n// ---------------------------------------------------------------------------\n\n/**\n * Factory for creating a derived/effect/operator node from catalog.\n * Receives resolved dep nodes and the config from the spec.\n */\nexport type FnFactory = (deps: Node<unknown>[], config: Record<string, unknown>) => Node<unknown>;\n\n/**\n * Factory for creating a producer node from catalog.\n * Receives the config from the spec.\n */\nexport type SourceFactory = (config: Record<string, unknown>) => Node<unknown>;\n\n// ---------------------------------------------------------------------------\n// Rich catalog entries (§9.1b — auto-prompt, catalog-aware validation)\n// ---------------------------------------------------------------------------\n\n/** Simple config field descriptor for LLM prompt generation and validation. */\nexport type ConfigFieldSchema = {\n\t/** Human-readable type: \"string\", \"number\", \"boolean\", \"string[]\", etc. */\n\ttype: string;\n\t/** Whether this field is required (default: true). */\n\trequired?: boolean;\n\t/** Allowed values (enum constraint). */\n\tenum?: readonly (string | number | boolean)[];\n\t/** Human-readable description for LLM context. */\n\tdescription?: string;\n\t/** Default value if omitted. */\n\tdefault?: unknown;\n};\n\n/**\n * Rich catalog entry: bundles a runtime factory with LLM-facing metadata.\n *\n * The metadata is used to:\n * 1. Auto-generate prompt text for {@link llmCompose} (replaces manual `catalogDescription`)\n * 2. Validate LLM output in {@link validateSpec} (catch wrong fn names, invalid config)\n * 3. Provide actionable error messages for {@link llmRefine} feedback loops\n *\n * Developers register ONE object; the library handles prompt generation and validation.\n */\nexport type CatalogFnEntry = {\n\t/** Runtime factory. */\n\tfactory: FnFactory;\n\t/** One-line description for LLM prompt (what it does, not how). */\n\tdescription: string;\n\t/** Config field schemas. Keys are config field names. */\n\tconfigSchema?: Record<string, ConfigFieldSchema>;\n\t/** Example config objects (shown in prompt for complex fns). */\n\texamples?: Record<string, unknown>[];\n\t/** Category tags for grouping in prompt (e.g., \"resilience\", \"reduction\", \"ai\"). */\n\ttags?: string[];\n};\n\n/** Rich catalog entry for producer sources. */\nexport type CatalogSourceEntry = {\n\t/** Runtime factory. */\n\tfactory: SourceFactory;\n\t/** One-line description for LLM prompt. */\n\tdescription: string;\n\t/** Config field schemas. */\n\tconfigSchema?: Record<string, ConfigFieldSchema>;\n\t/** Example config objects. */\n\texamples?: Record<string, unknown>[];\n\t/** Category tags. */\n\ttags?: string[];\n};\n\n/**\n * Top-level Graph factory — used when a spec was produced from a graph that\n * called `Graph.prototype.tagFactory(name, args)`. The catalog supplies a\n * function that takes the recorded `factoryArgs` (JSON-serializable subset)\n * and returns a fully-wired Graph. Runtime context (LLMAdapter instances,\n * callbacks, embedders) is captured by the closure — the args themselves are\n * a documentation fragment, not a complete construction recipe.\n *\n * Tier 1.5.3 Phase 2.5 (DG1=B, 2026-04-27).\n */\nexport type GraphSpecFactory = (factoryArgs: unknown) => Graph;\n\n/**\n * Fn/source lookup table passed to compileSpec and llmCompose.\n *\n * Accepts both bare factories (backward-compatible) and rich {@link CatalogFnEntry}\n * / {@link CatalogSourceEntry} objects. When rich entries are provided, the library\n * auto-generates LLM prompts and validates LLM output against the catalog.\n *\n * `graphFactories` (Tier 1.5.3 Phase 2.5) handles top-level Graph-returning\n * factories — when `spec.factory` matches a key, `compileSpec` delegates the\n * entire reconstruction to that factory.\n */\nexport type GraphSpecCatalog = {\n\tfns?: Record<string, FnFactory | CatalogFnEntry>;\n\tsources?: Record<string, SourceFactory | CatalogSourceEntry>;\n\tgraphFactories?: Record<string, GraphSpecFactory>;\n};\n\n// ---------------------------------------------------------------------------\n// Catalog helpers\n// ---------------------------------------------------------------------------\n\n/** Type guard: is this a rich catalog fn entry (vs bare factory)? */\nexport function isRichFnEntry(entry: FnFactory | CatalogFnEntry): entry is CatalogFnEntry {\n\treturn typeof entry === \"object\" && entry !== null && \"factory\" in entry;\n}\n\n/** Type guard: is this a rich catalog source entry (vs bare factory)? */\nexport function isRichSourceEntry(\n\tentry: SourceFactory | CatalogSourceEntry,\n): entry is CatalogSourceEntry {\n\treturn typeof entry === \"object\" && entry !== null && \"factory\" in entry;\n}\n\n/** Extract the runtime factory from a catalog entry (rich or bare). */\nexport function extractFnFactory(entry: FnFactory | CatalogFnEntry): FnFactory {\n\treturn isRichFnEntry(entry) ? entry.factory : entry;\n}\n\n/** Extract the runtime factory from a catalog source entry (rich or bare). */\nexport function extractSourceFactory(entry: SourceFactory | CatalogSourceEntry): SourceFactory {\n\treturn isRichSourceEntry(entry) ? entry.factory : entry;\n}\n\n/**\n * Auto-generate catalog prompt text from rich catalog entries.\n *\n * Groups fns by tag, formats each as `- name: description. Config: { ... }`.\n * Falls back to listing names only for bare factories.\n */\nexport function generateCatalogPrompt(catalog: GraphSpecCatalog): string {\n\tconst sections: string[] = [];\n\n\tif (catalog.fns) {\n\t\t// Group by first tag (or \"Other\")\n\t\tconst groups = new Map<string, string[]>();\n\t\tfor (const [name, entry] of Object.entries(catalog.fns)) {\n\t\t\tconst tag = isRichFnEntry(entry) ? (entry.tags?.[0] ?? \"Other\") : \"Other\";\n\t\t\tif (!groups.has(tag)) groups.set(tag, []);\n\t\t\tgroups.get(tag)!.push(formatFnEntry(name, entry));\n\t\t}\n\t\tfor (const [tag, lines] of groups) {\n\t\t\tsections.push(`${tag}:\\n${lines.join(\"\\n\")}`);\n\t\t}\n\t}\n\n\tif (catalog.sources) {\n\t\tconst lines: string[] = [];\n\t\tfor (const [name, entry] of Object.entries(catalog.sources)) {\n\t\t\tlines.push(formatSourceEntry(name, entry));\n\t\t}\n\t\tif (lines.length > 0) {\n\t\t\tsections.push(`Sources:\\n${lines.join(\"\\n\")}`);\n\t\t}\n\t}\n\n\treturn sections.join(\"\\n\\n\");\n}\n\nfunction formatFnEntry(name: string, entry: FnFactory | CatalogFnEntry): string {\n\tif (!isRichFnEntry(entry)) return `- ${name}`;\n\tlet line = `- ${name}: ${entry.description}`;\n\tif (entry.configSchema) {\n\t\tconst fields = Object.entries(entry.configSchema).map(([k, v]) => {\n\t\t\tlet desc = `${k}: ${v.type}`;\n\t\t\tif (v.enum) desc += ` (${v.enum.join(\"|\")})`;\n\t\t\tif (v.required === false) desc += \"?\";\n\t\t\treturn desc;\n\t\t});\n\t\tline += `. Config: { ${fields.join(\", \")} }`;\n\t}\n\treturn line;\n}\n\nfunction formatSourceEntry(name: string, entry: SourceFactory | CatalogSourceEntry): string {\n\tif (!isRichSourceEntry(entry)) return `- ${name}`;\n\tlet line = `- ${name}: ${entry.description}`;\n\tif (entry.configSchema) {\n\t\tconst fields = Object.entries(entry.configSchema).map(([k, v]) => {\n\t\t\tlet desc = `${k}: ${v.type}`;\n\t\t\tif (v.required === false) desc += \"?\";\n\t\t\treturn desc;\n\t\t});\n\t\tline += `. Config: { ${fields.join(\", \")} }`;\n\t}\n\treturn line;\n}\n\n/**\n * Validate a GraphSpec against a catalog.\n *\n * Checks that fn/source names reference actual catalog entries, and validates\n * config fields against configSchema when rich entries are available.\n * Returns additional errors beyond structural {@link validateSpec} checks.\n */\nexport function validateSpecAgainstCatalog(\n\tspec: GraphSpec,\n\tcatalog: GraphSpecCatalog,\n): GraphSpecValidation {\n\tconst errors: string[] = [];\n\tconst fnNames = new Set(Object.keys(catalog.fns ?? {}));\n\tconst sourceNames = new Set(Object.keys(catalog.sources ?? {}));\n\n\tfor (const [nodeName, nodeRaw] of Object.entries(spec.nodes)) {\n\t\tif (nodeRaw.type === \"template\") continue;\n\t\tconst node = nodeRaw as GraphSpecNode;\n\t\tconst factoryName = readFactory(node);\n\t\tif (factoryName == null) continue;\n\n\t\tconst isProducer = node.type === \"producer\";\n\t\t// State nodes self-tag with `factory: \"state\"` — never expected to live\n\t\t// in the catalog. Skip.\n\t\tif (node.type === \"state\" && factoryName === \"state\") continue;\n\n\t\t// Producers may resolve via either sources (preferred) or fns; non-\n\t\t// producers only resolve via fns. Mismatched-side suggestions (e.g.\n\t\t// using a source name on a derived node) match the legacy diagnostic.\n\t\tif (isProducer) {\n\t\t\tconst inSources = sourceNames.has(factoryName);\n\t\t\tconst inFns = fnNames.has(factoryName);\n\t\t\tif (!inSources && !inFns && (sourceNames.size > 0 || fnNames.size > 0)) {\n\t\t\t\tconst suggestion =\n\t\t\t\t\tfindClosest(factoryName, sourceNames) ?? findClosest(factoryName, fnNames);\n\t\t\t\terrors.push(\n\t\t\t\t\t`Node \"${nodeName}\": source \"${factoryName}\" not found in catalog` +\n\t\t\t\t\t\t(suggestion ? `. Did you mean \"${suggestion}\"?` : \"\"),\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tif (fnNames.size > 0 && !fnNames.has(factoryName)) {\n\t\t\t\tif (sourceNames.has(factoryName)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Node \"${nodeName}\": fn \"${factoryName}\" is a source, not a function. ` +\n\t\t\t\t\t\t\t`Use it as a producer source instead, or use a function from: ${[...fnNames].join(\", \")}`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconst suggestion = findClosest(factoryName, fnNames);\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Node \"${nodeName}\": fn \"${factoryName}\" not found in catalog` +\n\t\t\t\t\t\t\t(suggestion ? `. Did you mean \"${suggestion}\"?` : \"\"),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate config (`meta.factoryArgs`) against schema (if rich entry).\n\t\tconst factoryArgs = readFactoryArgs(node);\n\t\tif (!isProducer && catalog.fns?.[factoryName]) {\n\t\t\tconst entry = catalog.fns[factoryName];\n\t\t\tif (isRichFnEntry(entry) && entry.configSchema) {\n\t\t\t\tfor (const [field, schema] of Object.entries(entry.configSchema)) {\n\t\t\t\t\tif (schema.required !== false && !(field in factoryArgs)) {\n\t\t\t\t\t\terrors.push(`Node \"${nodeName}\": config missing required field \"${field}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tif (field in factoryArgs && schema.enum) {\n\t\t\t\t\t\tconst val = factoryArgs[field];\n\t\t\t\t\t\tif (!schema.enum.includes(val as string | number | boolean)) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`Node \"${nodeName}\": config.${field} = ${JSON.stringify(val)}, ` +\n\t\t\t\t\t\t\t\t\t`expected one of: ${schema.enum.join(\", \")}`,\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}\n\t\tif (isProducer && catalog.sources?.[factoryName]) {\n\t\t\tconst entry = catalog.sources[factoryName];\n\t\t\tif (isRichSourceEntry(entry) && entry.configSchema) {\n\t\t\t\tfor (const [field, schema] of Object.entries(entry.configSchema)) {\n\t\t\t\t\tif (schema.required !== false && !(field in factoryArgs)) {\n\t\t\t\t\t\terrors.push(`Node \"${nodeName}\": config missing required field \"${field}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tif (field in factoryArgs && schema.enum) {\n\t\t\t\t\t\tconst val = factoryArgs[field];\n\t\t\t\t\t\tif (!schema.enum.includes(val as string | number | boolean)) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`Node \"${nodeName}\": config.${field} = ${JSON.stringify(val)}, ` +\n\t\t\t\t\t\t\t\t\t`expected one of: ${schema.enum.join(\", \")}`,\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}\n\t}\n\n\t// Also check template inner nodes\n\tif (spec.templates) {\n\t\tfor (const [tName, template] of Object.entries(spec.templates)) {\n\t\t\tfor (const [nodeName, node] of Object.entries(template.nodes)) {\n\t\t\t\tconst factoryName = readFactory(node);\n\t\t\t\tif (factoryName == null) continue;\n\t\t\t\tif (node.type === \"state\" && factoryName === \"state\") continue;\n\t\t\t\tif (node.type === \"producer\") continue; // template producer/source skipped (parity with legacy)\n\t\t\t\tif (fnNames.size > 0 && !fnNames.has(factoryName)) {\n\t\t\t\t\tconst suggestion = findClosest(factoryName, fnNames);\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Template \"${tName}\" node \"${nodeName}\": fn \"${factoryName}\" not found in catalog` +\n\t\t\t\t\t\t\t(suggestion ? `. Did you mean \"${suggestion}\"?` : \"\"),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { valid: errors.length === 0, errors, warnings: [] };\n}\n\n/** Simple Levenshtein-based closest match for \"did you mean?\" suggestions. */\nfunction findClosest(input: string, candidates: Set<string>): string | null {\n\tlet best: string | null = null;\n\tlet bestDist = Infinity;\n\tconst lower = input.toLowerCase();\n\tfor (const c of candidates) {\n\t\tconst dist = levenshtein(lower, c.toLowerCase());\n\t\tif (dist < bestDist && dist <= Math.max(3, Math.floor(input.length / 2))) {\n\t\t\tbestDist = dist;\n\t\t\tbest = c;\n\t\t}\n\t}\n\treturn best;\n}\n\nfunction levenshtein(a: string, b: string): number {\n\tconst m = a.length;\n\tconst n = b.length;\n\tconst dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>\n\t\tArray.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),\n\t);\n\tfor (let i = 1; i <= m; i++) {\n\t\tfor (let j = 1; j <= n; j++) {\n\t\t\tdp[i][j] =\n\t\t\t\ta[i - 1] === b[j - 1]\n\t\t\t\t\t? dp[i - 1][j - 1]\n\t\t\t\t\t: 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);\n\t\t}\n\t}\n\treturn dp[m][n];\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Validation result from {@link validateSpec}. */\nexport type GraphSpecValidation = {\n\tvalid: boolean;\n\terrors: string[];\n\t/**\n\t * Non-fatal advisories. Currently includes feedback edges whose `from`\n\t * refers to an `effect` node (effects produce no DATA — the feedback\n\t * counter will never advance). Always present (empty array when nothing\n\t * is flagged) — symmetry with `errors` so callers can read\n\t * `result.warnings.length` without a null check.\n\t */\n\twarnings: string[];\n};\n\nconst VALID_NODE_TYPES = new Set([\n\t\"state\",\n\t\"producer\",\n\t\"derived\",\n\t\"effect\",\n\t\"operator\",\n\t\"template\",\n]);\n\nconst INNER_NODE_TYPES = new Set([\"state\", \"producer\", \"derived\", \"effect\", \"operator\"]);\n\n/**\n * Validate a GraphSpec JSON object.\n *\n * Checks structural validity: required fields, node types, dep references,\n * template references, feedback edge targets, self-cycles, and bind completeness.\n *\n * **Effect-node feedback advisory (C24-3).** When a feedback edge's `from`\n * refers to an `effect` node, the validator flags it via `warnings` (not\n * `errors`) — effect nodes produce no DATA emission, so a feedback counter\n * targeting one will never advance. The spec compiles either way; the\n * advisory exists because the misconfiguration is silent at runtime\n * (counter at 0 forever) without it.\n */\nexport function validateSpec(spec: unknown): GraphSpecValidation {\n\tconst errors: string[] = [];\n\tconst warnings: string[] = [];\n\n\tif (spec == null || typeof spec !== \"object\") {\n\t\treturn { valid: false, errors: [\"GraphSpec must be a non-null object\"], warnings };\n\t}\n\n\tconst s = spec as Record<string, unknown>;\n\n\tif (typeof s.name !== \"string\" || s.name.length === 0) {\n\t\terrors.push(\"Missing or empty 'name' field\");\n\t}\n\n\tif (s.nodes == null || typeof s.nodes !== \"object\" || Array.isArray(s.nodes)) {\n\t\terrors.push(\"Missing or invalid 'nodes' field (must be an object)\");\n\t\treturn { valid: false, errors, warnings };\n\t}\n\n\tconst nodeNames = new Set(Object.keys(s.nodes as object));\n\tconst nodeTypes = new Map<string, string>();\n\tconst templateDefs = new Map<string, { params: string[] }>();\n\n\t// Pre-scan template definitions for param validation\n\tif (s.templates != null && typeof s.templates === \"object\" && !Array.isArray(s.templates)) {\n\t\tfor (const [tName, tRaw] of Object.entries(s.templates as Record<string, unknown>)) {\n\t\t\tif (tRaw != null && typeof tRaw === \"object\") {\n\t\t\t\tconst t = tRaw as Record<string, unknown>;\n\t\t\t\ttemplateDefs.set(tName, {\n\t\t\t\t\tparams: Array.isArray(t.params) ? (t.params as string[]) : [],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate templates\n\tif (s.templates != null) {\n\t\tif (typeof s.templates !== \"object\" || Array.isArray(s.templates)) {\n\t\t\terrors.push(\"'templates' must be an object\");\n\t\t} else {\n\t\t\tfor (const [tName, tRaw] of Object.entries(s.templates as Record<string, unknown>)) {\n\t\t\t\tif (tRaw == null || typeof tRaw !== \"object\") {\n\t\t\t\t\terrors.push(`Template \"${tName}\": must be an object`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst t = tRaw as Record<string, unknown>;\n\t\t\t\tif (!Array.isArray(t.params)) {\n\t\t\t\t\terrors.push(`Template \"${tName}\": missing 'params' array`);\n\t\t\t\t}\n\t\t\t\tif (t.nodes == null || typeof t.nodes !== \"object\" || Array.isArray(t.nodes)) {\n\t\t\t\t\terrors.push(`Template \"${tName}\": missing or invalid 'nodes' object`);\n\t\t\t\t} else {\n\t\t\t\t\tconst paramSet = new Set(Array.isArray(t.params) ? (t.params as string[]) : []);\n\t\t\t\t\tconst innerNames = new Set(Object.keys(t.nodes as object));\n\t\t\t\t\tfor (const [nName, nRaw] of Object.entries(t.nodes as Record<string, unknown>)) {\n\t\t\t\t\t\tif (nRaw == null || typeof nRaw !== \"object\") {\n\t\t\t\t\t\t\terrors.push(`Template \"${tName}\" node \"${nName}\": must be an object`);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst n = nRaw as Record<string, unknown>;\n\t\t\t\t\t\tif (typeof n.type !== \"string\" || !INNER_NODE_TYPES.has(n.type)) {\n\t\t\t\t\t\t\terrors.push(`Template \"${tName}\" node \"${nName}\": invalid type`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Array.isArray(n.deps)) {\n\t\t\t\t\t\t\tfor (const dep of n.deps as string[]) {\n\t\t\t\t\t\t\t\tif (!innerNames.has(dep) && !paramSet.has(dep)) {\n\t\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t\t`Template \"${tName}\" node \"${nName}\": dep \"${dep}\" is not an inner node or param`,\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}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof t.output !== \"string\") {\n\t\t\t\t\t\terrors.push(`Template \"${tName}\": missing 'output' string`);\n\t\t\t\t\t} else if (!(t.nodes as Record<string, unknown>)[t.output as string]) {\n\t\t\t\t\t\terrors.push(`Template \"${tName}\": output \"${t.output}\" is not a declared node`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate nodes\n\tfor (const [name, raw] of Object.entries(s.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 n = raw as Record<string, unknown>;\n\t\tif (typeof n.type !== \"string\" || !VALID_NODE_TYPES.has(n.type)) {\n\t\t\terrors.push(\n\t\t\t\t`Node \"${name}\": invalid type \"${String(n.type)}\" (expected: ${[...VALID_NODE_TYPES].join(\", \")})`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tnodeTypes.set(name, n.type);\n\n\t\tif (n.type === \"template\") {\n\t\t\tif (typeof n.template !== \"string\" || !templateDefs.has(n.template)) {\n\t\t\t\terrors.push(`Node \"${name}\": template \"${String(n.template)}\" not found in templates`);\n\t\t\t} else {\n\t\t\t\t// Check bind completeness: all template params must be bound\n\t\t\t\tif (n.bind == null || typeof n.bind !== \"object\" || Array.isArray(n.bind)) {\n\t\t\t\t\terrors.push(`Node \"${name}\": template ref requires 'bind' object`);\n\t\t\t\t} else {\n\t\t\t\t\tconst tmpl = templateDefs.get(n.template as string)!;\n\t\t\t\t\tconst bind = n.bind as Record<string, string>;\n\t\t\t\t\tfor (const param of tmpl.params) {\n\t\t\t\t\t\tif (!(param in bind)) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`Node \"${name}\": template param \"${param}\" is not bound (template \"${n.template}\")`,\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\tfor (const [, target] of Object.entries(bind)) {\n\t\t\t\t\t\tif (typeof target === \"string\" && !nodeNames.has(target)) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`Node \"${name}\": bind target \"${target}\" does not reference an existing node`,\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} else {\n\t\t\tif (Array.isArray(n.deps)) {\n\t\t\t\tfor (const dep of n.deps as string[]) {\n\t\t\t\t\t// Self-referencing dep\n\t\t\t\t\tif (dep === name) {\n\t\t\t\t\t\terrors.push(`Node \"${name}\": self-referencing dep`);\n\t\t\t\t\t} else if (!nodeNames.has(dep)) {\n\t\t\t\t\t\terrors.push(`Node \"${name}\": dep \"${dep}\" does not reference an existing node`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Warn: derived/effect/operator without deps\n\t\t\tif (\n\t\t\t\t(n.type === \"derived\" || n.type === \"effect\" || n.type === \"operator\") &&\n\t\t\t\t!Array.isArray(n.deps)\n\t\t\t) {\n\t\t\t\terrors.push(`Node \"${name}\": ${n.type} node should have a 'deps' array`);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate feedback edges\n\tif (s.feedback != null) {\n\t\tif (!Array.isArray(s.feedback)) {\n\t\t\terrors.push(\"'feedback' must be an array\");\n\t\t} else {\n\t\t\tfor (let i = 0; i < (s.feedback as unknown[]).length; i++) {\n\t\t\t\tconst edge = (s.feedback as unknown[])[i];\n\t\t\t\tif (edge == null || typeof edge !== \"object\") {\n\t\t\t\t\terrors.push(`Feedback [${i}]: must be an object`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst e = edge as Record<string, unknown>;\n\t\t\t\tif (typeof e.from !== \"string\" || !nodeNames.has(e.from)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Feedback [${i}]: 'from' \"${String(e.from)}\" does not reference an existing node`,\n\t\t\t\t\t);\n\t\t\t\t} else if (nodeTypes.get(e.from) === \"effect\") {\n\t\t\t\t\t// Effect nodes produce no DATA — a feedback edge from one will\n\t\t\t\t\t// never trigger the counter / re-entry. Almost certainly a\n\t\t\t\t\t// modelling mistake (caller probably meant the upstream\n\t\t\t\t\t// derived/state node). Warn but don't reject — the spec is\n\t\t\t\t\t// structurally valid; some advanced uses might still be ok.\n\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t`Feedback [${i}]: 'from' \"${e.from}\" is an effect node — effects emit no DATA, so the feedback edge will never fire. Did you mean a derived/state node upstream?`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (typeof e.from === \"string\" && e.from === e.to) {\n\t\t\t\t\terrors.push(`Feedback [${i}]: 'from' and 'to' must be different nodes`);\n\t\t\t\t}\n\t\t\t\tif (typeof e.to !== \"string\" || !nodeNames.has(e.to)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Feedback [${i}]: 'to' \"${String(e.to)}\" does not reference an existing node`,\n\t\t\t\t\t);\n\t\t\t\t} else if (typeof e.to === \"string\" && nodeTypes.get(e.to) !== \"state\") {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Feedback [${i}]: 'to' node \"${e.to}\" must be a state node (got \"${nodeTypes.get(e.to) ?? \"unknown\"}\")`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// validateOwnership — multi-agent subgraph ownership PR lint (DS-14.5.A #5)\n// ---------------------------------------------------------------------------\n\n/**\n * Read `meta.owner` from a spec node. Pure read — no normalization.\n * Empty / non-string is treated as \"no annotation\" (silent, INV-OWNER-2).\n */\nfunction readOwner(node: GraphSpecNode): string | undefined {\n\tconst o = (node.meta as Record<string, unknown> | undefined)?.owner;\n\treturn typeof o === \"string\" && o.length > 0 ? o : undefined;\n}\n\n/**\n * The change-set fed to {@link validateOwnership}. Mirrors the minimal slice\n * of a PR diff the lint needs: the set of factory identifiers whose\n * implementation the diff touches, plus the PR author and (optionally) the\n * raw commit-message text so the `Override-Owner:` trailer can be detected.\n *\n * **Why factory-keyed (not path-keyed) — locked decision (DS-14.5.A Q5\n * sub-flag).** PR-diff → spec-node mapping resolves through `meta.factory`\n * provenance, NOT a `meta.ownerPath` glob. A diff that edits the\n * implementation of factory `\"rateLimiter\"` maps to *every* spec node whose\n * `meta.factory === \"rateLimiter\"`. This reuses the existing\n * `factoryTag` / `decompileSpec` round-trip (the same `meta.factory` field\n * `compileSpec` consumes) — no parallel ownership-path indexing scheme.\n */\nexport type OwnershipPrDiff = {\n\t/**\n\t * Factory identifiers (the `meta.factory` value) whose source the PR\n\t * modifies. A spec node is \"edited by this PR\" iff its `meta.factory` is\n\t * in this set. Nodes without `meta.factory` cannot be mapped from a code\n\t * diff and are therefore never flagged (silent — consistent with the\n\t * un-annotated rule).\n\t */\n\treadonly editedFactories: readonly string[];\n\t/** PR author's `Actor.id`. Compared against each edited node's `meta.owner`. */\n\treadonly author: string;\n\t/**\n\t * Raw commit message(s) text. If any line is an `Override-Owner: <reason>`\n\t * trailer (case-insensitive key, non-empty reason) the lint hard-fail is\n\t * bypassed and recorded as an audit-trail override (Q5 sub-lock i — any\n\t * committer may use it; it is recorded, never silently granted).\n\t */\n\treadonly commitMessage?: string;\n};\n\n/** One cross-owner violation surfaced by {@link validateOwnership}. */\nexport type OwnershipViolation = {\n\t/** Spec node path that carries `meta.owner` and was edited by a non-owner. */\n\treadonly node: string;\n\t/** The `meta.owner` value on that node. */\n\treadonly owner: string;\n\t/** The PR author who edited it. */\n\treadonly author: string;\n\t/** The `meta.factory` that mapped the diff onto this node. */\n\treadonly factory: string;\n};\n\n/** Result of {@link validateOwnership}. */\nexport type OwnershipValidation = {\n\t/**\n\t * `true` when no hard-fail applies — either no cross-owner edit, or every\n\t * cross-owner edit is bypassed by a valid `Override-Owner:` trailer.\n\t */\n\treadonly ok: boolean;\n\t/** Cross-owner edits that hard-fail (empty when `ok`). */\n\treadonly violations: readonly OwnershipViolation[];\n\t/**\n\t * Cross-owner edits that WOULD have failed but were bypassed by an\n\t * `Override-Owner:` commit trailer. Pure audit trail — CI / reviewers\n\t * grep this to surface override abuse. Present (possibly empty) so callers\n\t * can read `.overridden.length` without a null check.\n\t */\n\treadonly overridden: readonly OwnershipViolation[];\n\t/**\n\t * The override reason parsed from the `Override-Owner:` trailer, when one\n\t * was present and applied. `undefined` when no trailer was used.\n\t */\n\treadonly overrideReason?: string;\n};\n\nconst OVERRIDE_OWNER_TRAILER = /^\\s*override-owner\\s*:\\s*(.+?)\\s*$/im;\n\n/**\n * Detect an `Override-Owner: <reason>` commit trailer (case-insensitive key;\n * reason must be non-empty after trim). Returns the trimmed reason, or\n * `undefined` when absent.\n */\nfunction parseOverrideOwner(commitMessage: string | undefined): string | undefined {\n\tif (commitMessage == null) return undefined;\n\tconst m = OVERRIDE_OWNER_TRAILER.exec(commitMessage);\n\tconst reason = m?.[1]?.trim();\n\treturn reason != null && reason.length > 0 ? reason : undefined;\n}\n\n/**\n * Multi-agent subgraph ownership PR lint (DS-14.5.A delta #5, L0 rung;\n * spec §2.3a INV-OWNER-2).\n *\n * Hard-fails a pull request whose code diff edits a spec node carrying\n * `meta.owner` when the PR author is not that owner. Nodes **without**\n * `meta.owner` are silent (no advisory, no failure) — \"shared infrastructure\"\n * is exactly the un-annotated case; no separate allow-list is maintained.\n *\n * **Rules (Q5 lock):**\n * - Edited node has no `meta.owner` → silent.\n * - Edited node has `meta.owner` AND `author === meta.owner` → OK.\n * - Edited node has `meta.owner` AND `author !== meta.owner` → **violation**\n * (hard-fail) unless an `Override-Owner: <reason>` commit trailer is present,\n * in which case the violation is moved to `overridden` (audit trail) and\n * `ok` stays `true`.\n *\n * **PR-diff → spec-node mapping (Q5 sub-flag lock):** `meta.factory`\n * resolution. A node is \"edited\" iff its `meta.factory` appears in\n * `prDiff.editedFactories`. This reuses the `factoryTag` / `decompileSpec`\n * round-trip rather than introducing a `meta.ownerPath` glob. Nodes without\n * `meta.factory` can't be mapped from a code diff and are never flagged.\n *\n * Pure function — no `Node` / `Graph` returned, no side effects. Designed to\n * be called from a `graphrefly check-spec`-adjacent CI step (delta #6, Phase\n * 16) or any host PR gate.\n *\n * @param spec - The committed GraphSpec (or any `describe({ detail: \"spec\" })`\n * projection / structural superset).\n * @param prDiff - The factory-keyed diff slice + author + commit text.\n */\nexport function validateOwnership(spec: unknown, prDiff: OwnershipPrDiff): OwnershipValidation {\n\tconst violations: OwnershipViolation[] = [];\n\tconst overridden: OwnershipViolation[] = [];\n\n\tif (spec == null || typeof spec !== \"object\") {\n\t\treturn { ok: true, violations, overridden };\n\t}\n\tconst s = spec as Record<string, unknown>;\n\tconst nodes = s.nodes;\n\tif (nodes == null || typeof nodes !== \"object\" || Array.isArray(nodes)) {\n\t\treturn { ok: true, violations, overridden };\n\t}\n\n\tconst edited = new Set(prDiff.editedFactories);\n\tif (edited.size > 0) {\n\t\tfor (const [path, nRaw] of Object.entries(nodes as Record<string, unknown>)) {\n\t\t\tif (nRaw == null || typeof nRaw !== \"object\") continue;\n\t\t\tconst n = nRaw as GraphSpecNode;\n\t\t\tconst factory = readFactory(n);\n\t\t\t// Unmappable from a code diff (no factory provenance) → silent.\n\t\t\tif (factory == null || !edited.has(factory)) continue;\n\t\t\tconst owner = readOwner(n);\n\t\t\t// No annotation → silent (INV-OWNER-2: un-annotated == shared).\n\t\t\tif (owner == null) continue;\n\t\t\t// Author IS the owner → OK.\n\t\t\tif (owner === prDiff.author) continue;\n\t\t\tviolations.push({ node: path, owner, author: prDiff.author, factory });\n\t\t}\n\t}\n\n\tconst overrideReason = parseOverrideOwner(prDiff.commitMessage);\n\tif (violations.length > 0 && overrideReason != null) {\n\t\t// Trailer bypasses ALL cross-owner violations in this PR (the trailer\n\t\t// is PR-scoped and a pure audit-trail record per Q5 sub-lock i).\n\t\toverridden.push(...violations);\n\t\treturn { ok: true, violations: [], overridden, overrideReason };\n\t}\n\n\treturn {\n\t\tok: violations.length === 0,\n\t\tviolations,\n\t\toverridden,\n\t\t...(overrideReason != null ? { overrideReason } : {}),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// compileSpec\n// ---------------------------------------------------------------------------\n\n/** Options for {@link compileSpec}. */\nexport type CompileSpecOptions = {\n\t/** Fn/source catalog for resolving named factories. */\n\tcatalog?: GraphSpecCatalog;\n\t/**\n\t * How to handle nodes whose `fn` / `source` is missing from the catalog.\n\t * - `\"placeholder\"` (default): silently substitute identity passthroughs\n\t * (`node([], () => {})` / `node(deps, (bd, a, ctx) => a.emit(bd[0]?.at(-1)))`). Backward-\n\t * compatible — preserves the historical \"soft compile\" behavior.\n\t * - `\"warn\"`: substitute placeholders AND log each missing entry via\n\t * `console.warn`, or via the `onWarn` callback if supplied.\n\t * - `\"error\"`: collect every missing entry across the whole spec, then\n\t * throw an `Error` listing them all (no partial graph returned).\n\t */\n\tonMissing?: \"error\" | \"warn\" | \"placeholder\";\n\t/** Custom warning sink. Used only when `onMissing === \"warn\"`. Defaults to `console.warn`. */\n\tonWarn?: (message: string) => void;\n};\n\ninterface MissingCatalogEntry {\n\t/** Node path (template-prefixed where applicable, e.g. `myMount.inner`). */\n\tpath: string;\n\t/** The catalog kind (`\"fn\"` or `\"source\"`) that was looked up. */\n\tkind: \"fn\" | \"source\";\n\t/** The catalog name string supplied in the spec. */\n\tname: string;\n}\n\n/**\n * Instantiate a Graph from a GraphSpec.\n *\n * Handles template expansion (mounted subgraphs), feedback wiring via §8.1\n * feedback(), node factory lookup from the catalog, and topology validation.\n *\n * @param spec - Declarative graph topology.\n * @param opts - Catalog and compile options.\n * @returns A running Graph.\n * @throws On validation failure, missing catalog entries, or unresolvable deps.\n *\n * @category patterns\n */\nexport function compileSpec(spec: GraphSpec, opts?: CompileSpecOptions): Graph {\n\t// QA F4: validate FIRST, even when the early-dispatch path will delegate to\n\t// a Graph-level factory. The early-dispatch is a *constructor* short-circuit,\n\t// not a *validation* short-circuit — we still want malformed specs to throw\n\t// so a catalog-tagged spec with bogus nodes/templates surfaces the error.\n\tconst validation = validateSpec(spec);\n\tif (!validation.valid) {\n\t\tthrow new Error(`compileSpec: invalid GraphSpec:\\n${validation.errors.join(\"\\n\")}`);\n\t}\n\n\t// Tier 1.5.3 Phase 2.5 (DG1=B): if the spec carries a top-level `factory`\n\t// tag and the catalog has a matching `graphFactories` entry, delegate the\n\t// full reconstruction. This lets Graph-returning factories\n\t// (`agentMemory`, `harnessLoop`, etc.) own their own rebuild path with\n\t// access to user-supplied runtime ctx (LLMAdapter, callbacks).\n\tconst specFactory = spec.factory;\n\tconst specFactoryArgs = spec.factoryArgs;\n\tif (typeof specFactory === \"string\") {\n\t\tconst graphFactory = opts?.catalog?.graphFactories?.[specFactory];\n\t\tif (graphFactory) return graphFactory(specFactoryArgs);\n\t\t// No catalog entry for the named factory — fall through to per-node\n\t\t// compile so the per-node-tagged paths still work.\n\t}\n\n\tconst catalog = opts?.catalog ?? {};\n\tconst onMissing = opts?.onMissing ?? \"placeholder\";\n\tconst g = new Graph(spec.name);\n\tconst templates = spec.templates ?? {};\n\n\t// Catalog-aware validation (when rich entries are available)\n\tconst catalogValidation = validateSpecAgainstCatalog(spec, catalog);\n\tif (!catalogValidation.valid) {\n\t\tthrow new Error(\n\t\t\t`compileSpec: catalog validation errors:\\n${catalogValidation.errors.join(\"\\n\")}`,\n\t\t);\n\t}\n\n\t// Track missing catalog entries across both top-level and template passes;\n\t// the chosen `onMissing` policy is applied once after compile so callers see\n\t// every miss in a single error / warn batch instead of one-at-a-time.\n\tconst missingEntries: MissingCatalogEntry[] = [];\n\n\tconst recordMissing = (nodePath: string, kind: \"fn\" | \"source\", name: string): void => {\n\t\tmissingEntries.push({ path: nodePath, kind, name });\n\t};\n\n\t// Helper: resolve fn/source factories from catalog (handles rich + bare entries)\n\tconst resolveFn = (fnName: string): FnFactory | undefined => {\n\t\tconst entry = catalog.fns?.[fnName];\n\t\treturn entry ? extractFnFactory(entry) : undefined;\n\t};\n\tconst resolveSource = (sourceName: string): SourceFactory | undefined => {\n\t\tconst entry = catalog.sources?.[sourceName];\n\t\treturn entry ? extractSourceFactory(entry) : undefined;\n\t};\n\n\t/**\n\t * Strip the `factory` / `factoryArgs` keys from a spec node's `meta`\n\t * before forwarding to the construction factory. The factory itself\n\t * re-stamps its own `factoryTag(...)` (so the rebuilt node carries the\n\t * canonical factoryArgs); leaving the spec's pre-stamped meta in place\n\t * would shadow that with stale args (esp. after `placeholderArgs`\n\t * scrubbed non-JSON fields).\n\t */\n\tconst stripFactoryMeta = (\n\t\tmeta: Record<string, unknown> | undefined,\n\t): Record<string, unknown> | undefined => {\n\t\tif (!meta) return undefined;\n\t\tconst out: Record<string, unknown> = {};\n\t\tfor (const [k, v] of Object.entries(meta)) {\n\t\t\tif (k === \"factory\" || k === \"factoryArgs\") continue;\n\t\t\tout[k] = v;\n\t\t}\n\t\treturn Object.keys(out).length > 0 ? out : undefined;\n\t};\n\n\t// Phase 1: Create non-template nodes (state/producer first, then derived/effect/operator)\n\tconst created = new Map<string, Node<unknown>>();\n\tconst deferred: [string, GraphSpecNode][] = [];\n\n\tfor (const [name, raw] of Object.entries(spec.nodes)) {\n\t\tif (raw.type === \"template\") continue; // handled in Phase 2\n\n\t\tconst n = raw as GraphSpecNode;\n\t\tconst factoryName = readFactory(n);\n\t\tconst factoryArgs = readFactoryArgs(n);\n\n\t\tif (n.type === \"state\") {\n\t\t\tconst initial = readStateInitial(n);\n\t\t\tconst nd = node([], {\n\t\t\t\tname,\n\t\t\t\tinitial,\n\t\t\t\tmeta: stripFactoryMeta(n.meta),\n\t\t\t});\n\t\t\tg.add(nd, { name: name });\n\t\t\tcreated.set(name, nd);\n\t\t} else if (n.type === \"producer\") {\n\t\t\t// Producer: try sources first (matching the legacy precedence) then fns.\n\t\t\tconst sourceFactory = factoryName ? resolveSource(factoryName) : undefined;\n\t\t\tconst fnFactory = factoryName ? resolveFn(factoryName) : undefined;\n\t\t\tif (sourceFactory) {\n\t\t\t\tconst nd = sourceFactory(factoryArgs);\n\t\t\t\tg.add(nd, { name: name });\n\t\t\t\tcreated.set(name, nd);\n\t\t\t} else if (fnFactory) {\n\t\t\t\tconst nd = fnFactory([], factoryArgs);\n\t\t\t\tg.add(nd, { name: name });\n\t\t\t\tcreated.set(name, nd);\n\t\t\t} else {\n\t\t\t\t// No catalog entry — create a bare producer placeholder.\n\t\t\t\tif (factoryName) recordMissing(name, \"source\", factoryName);\n\t\t\t\tconst nd = node([], () => {}, {\n\t\t\t\t\tname,\n\t\t\t\t\tdescribeKind: \"producer\",\n\t\t\t\t\tmeta: { ...stripFactoryMeta(n.meta), _specSource: factoryName },\n\t\t\t\t});\n\t\t\t\tg.add(nd, { name: name });\n\t\t\t\tcreated.set(name, nd);\n\t\t\t}\n\t\t} else {\n\t\t\tdeferred.push([name, n]);\n\t\t}\n\t}\n\n\t// Resolve deferred nodes (derived/effect/operator) in dependency order\n\tlet progressed = true;\n\tconst pending = new Map(deferred);\n\twhile (pending.size > 0 && progressed) {\n\t\tprogressed = false;\n\t\tfor (const [name, n] of [...pending.entries()]) {\n\t\t\tconst deps = n.deps ?? [];\n\t\t\tif (!deps.every((dep) => created.has(dep))) continue;\n\n\t\t\tconst resolvedDeps = deps.map((dep) => created.get(dep)!);\n\t\t\tconst factoryName = readFactory(n);\n\t\t\tconst factoryArgs = readFactoryArgs(n);\n\t\t\tconst fnFactory = factoryName ? resolveFn(factoryName) : undefined;\n\n\t\t\tlet nd: Node<unknown>;\n\t\t\tif (fnFactory) {\n\t\t\t\tnd = fnFactory(resolvedDeps, factoryArgs);\n\t\t\t} else if (n.type === \"effect\") {\n\t\t\t\tif (factoryName) recordMissing(name, \"fn\", factoryName);\n\t\t\t\tnd = node(resolvedDeps, () => {}, { describeKind: \"effect\" });\n\t\t\t} else {\n\t\t\t\t// derived without catalog fn — identity passthrough\n\t\t\t\tif (factoryName) recordMissing(name, \"fn\", factoryName);\n\t\t\t\tnd = node(\n\t\t\t\t\tresolvedDeps,\n\t\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t\t\t);\n\t\t\t\t\t\tactions.emit(data[0]);\n\t\t\t\t\t},\n\t\t\t\t\t{ describeKind: \"derived\" },\n\t\t\t\t);\n\t\t\t}\n\t\t\tg.add(nd, { name: name });\n\t\t\tcreated.set(name, nd);\n\t\t\tpending.delete(name);\n\t\t\tprogressed = true;\n\t\t}\n\t}\n\tif (pending.size > 0) {\n\t\tconst unresolved = [...pending.keys()].sort().join(\", \");\n\t\tthrow new Error(`compileSpec: unresolvable deps for nodes: ${unresolved}`);\n\t}\n\n\t// Phase 2: Expand template instantiations as mounted subgraphs\n\tfor (const [name, raw] of Object.entries(spec.nodes)) {\n\t\tif (raw.type !== \"template\") continue;\n\t\tconst ref = raw as GraphSpecTemplateRef;\n\t\tconst tmpl = templates[ref.template]!;\n\n\t\tconst sub = new Graph(name);\n\t\tconst subCreated = new Map<string, Node<unknown>>();\n\t\tconst subDeferred: [string, GraphSpecNode][] = [];\n\n\t\t// Create inner nodes, resolving $params to bound nodes\n\t\tfor (const [nName, nSpec] of Object.entries(tmpl.nodes)) {\n\t\t\tconst resolvedDeps = (nSpec.deps ?? []).map((dep) => {\n\t\t\t\tif (dep.startsWith(\"$\") && ref.bind[dep]) {\n\t\t\t\t\treturn ref.bind[dep];\n\t\t\t\t}\n\t\t\t\treturn dep;\n\t\t\t});\n\t\t\tconst specWithResolvedDeps: GraphSpecNode = { ...nSpec, deps: resolvedDeps };\n\t\t\tconst factoryName = readFactory(nSpec);\n\t\t\tconst factoryArgs = readFactoryArgs(nSpec);\n\n\t\t\tif (nSpec.type === \"state\") {\n\t\t\t\tconst initial = readStateInitial(nSpec);\n\t\t\t\tconst nd = node([], {\n\t\t\t\t\tname: nName,\n\t\t\t\t\tinitial,\n\t\t\t\t\tmeta: stripFactoryMeta(nSpec.meta),\n\t\t\t\t});\n\t\t\t\tsub.add(nd, { name: nName });\n\t\t\t\tsubCreated.set(nName, nd);\n\t\t\t} else if (nSpec.type === \"producer\") {\n\t\t\t\tconst sourceFactory = factoryName ? resolveSource(factoryName) : undefined;\n\t\t\t\tconst fnFactory = factoryName ? resolveFn(factoryName) : undefined;\n\t\t\t\tif (sourceFactory) {\n\t\t\t\t\tconst nd = sourceFactory(factoryArgs);\n\t\t\t\t\tsub.add(nd, { name: nName });\n\t\t\t\t\tsubCreated.set(nName, nd);\n\t\t\t\t} else if (fnFactory) {\n\t\t\t\t\tconst nd = fnFactory([], factoryArgs);\n\t\t\t\t\tsub.add(nd, { name: nName });\n\t\t\t\t\tsubCreated.set(nName, nd);\n\t\t\t\t} else {\n\t\t\t\t\tif (factoryName) recordMissing(`${name}.${nName}`, \"source\", factoryName);\n\t\t\t\t\tconst nd = node([], () => {}, {\n\t\t\t\t\t\tname: nName,\n\t\t\t\t\t\tdescribeKind: \"producer\",\n\t\t\t\t\t\tmeta: { ...stripFactoryMeta(nSpec.meta), _specSource: factoryName },\n\t\t\t\t\t});\n\t\t\t\t\tsub.add(nd, { name: nName });\n\t\t\t\t\tsubCreated.set(nName, nd);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsubDeferred.push([nName, specWithResolvedDeps]);\n\t\t\t}\n\t\t}\n\n\t\t// Resolve deferred inner nodes\n\t\tlet subProgressed = true;\n\t\tconst subPending = new Map(subDeferred);\n\t\twhile (subPending.size > 0 && subProgressed) {\n\t\t\tsubProgressed = false;\n\t\t\tfor (const [nName, nSpec] of [...subPending.entries()]) {\n\t\t\t\tconst deps = nSpec.deps ?? [];\n\t\t\t\tconst allReady = deps.every((dep) => subCreated.has(dep) || created.has(dep));\n\t\t\t\tif (!allReady) continue;\n\n\t\t\t\tconst resolvedDeps = deps.map((dep) => subCreated.get(dep) ?? created.get(dep)!);\n\t\t\t\tconst factoryName = readFactory(nSpec);\n\t\t\t\tconst factoryArgs = readFactoryArgs(nSpec);\n\t\t\t\tconst fnFactory = factoryName ? resolveFn(factoryName) : undefined;\n\n\t\t\t\tlet nd: Node<unknown>;\n\t\t\t\tif (fnFactory) {\n\t\t\t\t\tnd = fnFactory(resolvedDeps, factoryArgs);\n\t\t\t\t} else if (nSpec.type === \"effect\") {\n\t\t\t\t\tif (factoryName) recordMissing(`${name}.${nName}`, \"fn\", factoryName);\n\t\t\t\t\tnd = node(resolvedDeps, () => {}, { describeKind: \"effect\" });\n\t\t\t\t} else {\n\t\t\t\t\tif (factoryName) recordMissing(`${name}.${nName}`, \"fn\", factoryName);\n\t\t\t\t\tnd = node(\n\t\t\t\t\t\tresolvedDeps,\n\t\t\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tactions.emit(data[0]);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ describeKind: \"derived\" },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tsub.add(nd, { name: nName });\n\t\t\t\tsubCreated.set(nName, nd);\n\t\t\t\tsubPending.delete(nName);\n\t\t\t\tsubProgressed = true;\n\t\t\t}\n\t\t}\n\t\tif (subPending.size > 0) {\n\t\t\tconst unresolved = [...subPending.keys()].sort().join(\", \");\n\t\t\tthrow new Error(\n\t\t\t\t`compileSpec: template \"${ref.template}\" has unresolvable deps: ${unresolved}`,\n\t\t\t);\n\t\t}\n\n\t\tg.mount(name, sub);\n\t\t// Register template output as a reachable node path\n\t\tconst outputPath = `${name}::${tmpl.output}`;\n\t\tcreated.set(name, g.resolve(outputPath));\n\n\t\t// Store template origin meta on the mounted subgraph's output node\n\t\t// so decompile-style introspection can recover the template name.\n\t\ttry {\n\t\t\tconst outputNode = g.resolve(outputPath);\n\t\t\toutputNode.meta._templateName?.emit(ref.template);\n\t\t\toutputNode.meta._templateBind?.emit(ref.bind);\n\t\t} catch {\n\t\t\t/* meta nodes may not exist; template origin is best-effort */\n\t\t}\n\t}\n\n\t// Edges are derived from node `_deps` (Unit 7) — no explicit edge wiring step.\n\n\t// Phase 4: Wire feedback edges via §8.1 feedback()\n\tfor (const fb of spec.feedback ?? []) {\n\t\tfeedbackPrimitive(g, fb.from, fb.to, {\n\t\t\tmaxIterations: fb.maxIterations,\n\t\t});\n\t}\n\n\t// Apply onMissing policy. We always finish compilation first (for \"warn\"\n\t// + \"placeholder\") so the caller still gets a usable graph in non-strict\n\t// modes. In \"error\" mode we throw before returning.\n\tif (missingEntries.length > 0) {\n\t\tif (onMissing === \"error\") {\n\t\t\tconst lines = missingEntries.map((e) => ` - ${e.path}: missing ${e.kind} \"${e.name}\"`);\n\t\t\tthrow new Error(\n\t\t\t\t`compileSpec: ${missingEntries.length} catalog entr${\n\t\t\t\t\tmissingEntries.length === 1 ? \"y\" : \"ies\"\n\t\t\t\t} missing — pass them via opts.catalog or set opts.onMissing to \"warn\"/\"placeholder\":\\n${lines.join(\"\\n\")}`,\n\t\t\t);\n\t\t}\n\t\tif (onMissing === \"warn\") {\n\t\t\tconst warn = opts?.onWarn ?? ((m: string): void => console.warn(m));\n\t\t\tfor (const e of missingEntries) {\n\t\t\t\twarn(\n\t\t\t\t\t`compileSpec: ${e.path} references missing ${e.kind} \"${e.name}\" — substituted placeholder`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn g;\n}\n\n// ---------------------------------------------------------------------------\n// decompileGraph\n// ---------------------------------------------------------------------------\n\n/** Internal meta keys used by compileSpec/feedback — stripped from output. */\nconst INTERNAL_META_KEYS = new Set([\n\t\"reduction\",\n\t\"reduction_type\",\n\t\"_specFn\",\n\t\"_specSource\",\n\t\"_templateName\",\n\t\"_templateBind\",\n\t\"feedbackFrom\",\n\t\"feedbackTo\",\n\t\"_internal\",\n]);\n\n/**\n * Extract a {@link GraphSpec} from a running graph.\n *\n * Tier 1.5.3 Phase 3 (2026-04-27): thin projection over\n * `graph.describe({ detail: \"spec\" })`. The describe-output already carries\n * structural fields (`type`, `deps`, optional `value`) plus per-node\n * `meta.factory` / `meta.factoryArgs` for tagged factories and top-level\n * `factory` / `factoryArgs` for graph-level tags. The only sugar this helper\n * adds is a feedback-edge recovery scan over `meta.feedbackFrom` /\n * `meta.feedbackTo` companion fields stamped by the §8.1 `feedback()`\n * primitive.\n *\n * **Removed in Phase 3:** template fingerprinting / `_templateName` /\n * `_templateBind` recovery. Mounted subgraphs surface as nested `subname::*`\n * paths in `desc.nodes`; if you need the template-instantiation form, build\n * the spec by hand or read the meta companions directly.\n *\n * @param graph - Running graph to decompile.\n * @returns A GraphSpec representation.\n *\n * @category patterns\n */\nexport function decompileSpec(graph: Graph): GraphSpec {\n\tconst desc = graph.describe({ detail: \"spec\" }) as GraphDescribeOutput;\n\tconst metaSegment = `::${GRAPH_META_SEGMENT}::`;\n\tconst feedbackCounterPattern = /^__feedback_(?!effect_)(.+)$/;\n\tconst feedbackEdges: GraphSpecFeedbackEdge[] = [];\n\n\t// qa D1 — Pre-pass: collect paths whose own node carries `meta.factory`.\n\t// These are \"factory parents\" (e.g. `prompt_node` for the `promptNode`\n\t// compound factory). Their `::`-prefixed sibling paths (`prompt_node::messages`,\n\t// `prompt_node::output`, etc.) are factory-internal and SHOULD NOT round-trip\n\t// as separate spec nodes — `compileSpec` will recreate them when the factory\n\t// runs against the parent's `meta.factory` / `meta.factoryArgs` tag. Without\n\t// this filter, every compound-factory internal would be emitted as a top-level\n\t// spec node, then `compileSpec` would try to re-add them via `g.add(nd, {name})`\n\t// alongside the factory's own outputs — duplicate-name failures or split topology.\n\tconst compoundFactoryPrefixes = new Set<string>();\n\tfor (const [path, nodeDesc] of Object.entries(desc.nodes)) {\n\t\tconst meta = nodeDesc.meta as Record<string, unknown> | undefined;\n\t\tif (meta?.factory != null && !path.includes(\"::\")) {\n\t\t\t// A12 (QA fix 2026-05-01): skip the `proxy` factoryTag — proxies\n\t\t\t// are local wrappers around foreign-source Nodes (used by\n\t\t\t// `pipelineGraph.approvalGate`, `gatedStream`, `stratify` after\n\t\t\t// the C3 ownership migration). They're regenerated by their\n\t\t\t// parent factory and don't have their own catalog entry; treating\n\t\t\t// them as compound-factory roots would cause `compileSpec` to\n\t\t\t// look up \"proxy\" as a registered factory name and fail.\n\t\t\tif (meta.factory === \"proxy\") continue;\n\t\t\tcompoundFactoryPrefixes.add(path);\n\t\t}\n\t}\n\n\t// 5.6 (b) — DF1 hard-require (Tier 5, 2026-04-29). Locked: any `::`-path\n\t// whose parent prefix exists in the graph but does NOT carry\n\t// `meta.factory` is an untagged compound factory. `compileSpec` cannot\n\t// reconstruct it, so the spec round-trip would silently break. Fail\n\t// loud at decompile time so the offending factory author tags the\n\t// parent. Skip well-known internal prefixes that are not factory output\n\t// (meta companions, feedback / bridge infrastructure).\n\tconst allPaths = new Set(Object.keys(desc.nodes));\n\tfor (const path of allPaths) {\n\t\tconst sepIdx = path.indexOf(\"::\");\n\t\tif (sepIdx <= 0) continue;\n\t\tconst parent = path.slice(0, sepIdx);\n\t\t// Skip internal infrastructure prefixes (handled below in the main loop).\n\t\tif (path.includes(metaSegment)) continue;\n\t\tif (path.startsWith(\"__feedback_effect_\") || path.startsWith(\"__bridge_\")) continue;\n\t\t// Parent is a tagged compound factory → covered by the existing pre-pass.\n\t\tif (compoundFactoryPrefixes.has(parent)) continue;\n\t\t// Parent doesn't appear in the graph (untagged child path with no\n\t\t// matching parent) — treat as a regular `::`-named node, not a\n\t\t// compound factory. Allowed.\n\t\tif (!allPaths.has(parent)) continue;\n\t\t// Parent IS in the graph but lacks `meta.factory` — untagged compound\n\t\t// factory. Refuse to round-trip.\n\t\tthrow new Error(\n\t\t\t`decompileSpec: untagged compound factory at \"${parent}\" (child: \"${path}\"). ` +\n\t\t\t\t\"Compound factories that ship `parent::child` topology MUST set `meta.factory` \" +\n\t\t\t\t\"on the parent so `compileSpec` can reconstruct the internals via the catalog. \" +\n\t\t\t\t\"Either tag the parent (`{ meta: factoryTag('myFactory', args) }`) OR rename the \" +\n\t\t\t\t\"child to use `/` instead of `::` if it's not a compound-factory internal \" +\n\t\t\t\t\"(see COMPOSITION-GUIDE §38).\",\n\t\t);\n\t}\n\n\t// Build the spec-shaped node map by walking describe's output. Strip\n\t// meta-companion paths, bridge / feedback-effect internals, AND compound-\n\t// factory `::` internals (per pre-pass above); preserve everything else verbatim.\n\tconst nodes: Record<string, GraphSpecNode | GraphSpecTemplateRef> = {};\n\tfor (const [path, nodeDesc] of Object.entries(desc.nodes)) {\n\t\tif (path.includes(metaSegment)) continue;\n\n\t\t// qa D1 — skip compound-factory `::` internals (e.g. `prompt_node::messages`)\n\t\t// when their parent is a tagged factory. The factory recreates them.\n\t\tconst sepIdx = path.indexOf(\"::\");\n\t\tif (sepIdx > 0 && compoundFactoryPrefixes.has(path.slice(0, sepIdx))) continue;\n\n\t\tconst match = feedbackCounterPattern.exec(path);\n\t\tif (match) {\n\t\t\tconst meta = nodeDesc.meta as Record<string, unknown> | undefined;\n\t\t\tif (meta?.feedbackFrom && meta?.feedbackTo) {\n\t\t\t\tfeedbackEdges.push({\n\t\t\t\t\tfrom: meta.feedbackFrom as string,\n\t\t\t\t\tto: meta.feedbackTo as string,\n\t\t\t\t\t...(meta.maxIterations ? { maxIterations: meta.maxIterations as number } : {}),\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\t// Skip internal infrastructure nodes (feedback-effect, bridge).\n\t\tif (nodeDesc.meta?._internal) continue;\n\t\tif (path.startsWith(\"__feedback_effect_\")) continue;\n\t\tif (path.startsWith(\"__bridge_\")) continue;\n\n\t\t// QA F5 carry: strip runtime-state sibling keys for known stateful factory\n\t\t// tags so the spec doesn't carry transient runtime state into round-trips.\n\t\tconst meta = nodeDesc.meta as Record<string, unknown> | undefined;\n\t\tlet cleanedMeta: Record<string, unknown> | undefined = meta;\n\t\tif (meta && Object.keys(meta).length > 0) {\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tfor (const [k, v] of Object.entries(meta)) {\n\t\t\t\tif (INTERNAL_META_KEYS.has(k)) continue;\n\t\t\t\tout[k] = v;\n\t\t\t}\n\t\t\tif (out.factory === \"withStatus\") {\n\t\t\t\tdelete out.status;\n\t\t\t\tdelete out.error;\n\t\t\t} else if (out.factory === \"withBreaker\") {\n\t\t\t\tdelete out.breakerState;\n\t\t\t} else if (out.factory === \"verifiable\") {\n\t\t\t\tdelete out.sourceVersion;\n\t\t\t}\n\t\t\tcleanedMeta = Object.keys(out).length > 0 ? out : undefined;\n\t\t}\n\n\t\tconst cleaned: GraphSpecNode = { ...nodeDesc };\n\t\tif (cleanedMeta === undefined) delete cleaned.meta;\n\t\telse cleaned.meta = cleanedMeta;\n\t\tnodes[path] = cleaned;\n\t}\n\n\tconst result: GraphSpec = { ...desc, nodes };\n\t// `expand` (a closure injected onto live describe outputs) is not part of\n\t// the GraphSpec wire shape — it leaks function refs into JSON-stringified\n\t// specs. Drop it.\n\tdelete (result as { expand?: unknown }).expand;\n\tif (feedbackEdges.length > 0) result.feedback = feedbackEdges;\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// specDiff\n// ---------------------------------------------------------------------------\n\n/** A single change in a spec diff. */\nexport type SpecDiffEntry = {\n\ttype: \"added\" | \"removed\" | \"changed\";\n\tpath: string;\n\tdetail?: string;\n};\n\n/** Structural diff between two GraphSpecs. */\nexport type SpecDiffResult = {\n\tentries: SpecDiffEntry[];\n\tsummary: string;\n};\n\n/**\n * Compute a structural diff between two GraphSpecs.\n *\n * Template-aware: reports \"changed template definition\" vs \"changed\n * instantiation bindings.\" No runtime needed — pure JSON comparison.\n *\n * @param specA - The \"before\" spec.\n * @param specB - The \"after\" spec.\n * @returns Diff entries and a human-readable summary.\n *\n * @category patterns\n */\nexport function specDiff(specA: GraphSpec, specB: GraphSpec): SpecDiffResult {\n\tconst entries: SpecDiffEntry[] = [];\n\n\t// Diff name\n\tif (specA.name !== specB.name) {\n\t\tentries.push({\n\t\t\ttype: \"changed\",\n\t\t\tpath: \"name\",\n\t\t\tdetail: `\"${specA.name}\" → \"${specB.name}\"`,\n\t\t});\n\t}\n\n\t// Diff nodes\n\tconst nodesA = new Set(Object.keys(specA.nodes));\n\tconst nodesB = new Set(Object.keys(specB.nodes));\n\n\tfor (const name of nodesB) {\n\t\tif (!nodesA.has(name)) {\n\t\t\tconst n = specB.nodes[name]!;\n\t\t\tentries.push({\n\t\t\t\ttype: \"added\",\n\t\t\t\tpath: `nodes.${name}`,\n\t\t\t\tdetail: `type: ${n.type}`,\n\t\t\t});\n\t\t}\n\t}\n\tfor (const name of nodesA) {\n\t\tif (!nodesB.has(name)) {\n\t\t\tentries.push({ type: \"removed\", path: `nodes.${name}` });\n\t\t}\n\t}\n\tfor (const name of nodesA) {\n\t\tif (!nodesB.has(name)) continue;\n\t\tconst a = specA.nodes[name]!;\n\t\tconst b = specB.nodes[name]!;\n\t\tif (JSON.stringify(a) !== JSON.stringify(b)) {\n\t\t\tconst details: string[] = [];\n\t\t\tif (a.type !== b.type) details.push(`type: ${a.type} → ${b.type}`);\n\t\t\tif (JSON.stringify((a as GraphSpecNode).deps) !== JSON.stringify((b as GraphSpecNode).deps)) {\n\t\t\t\tdetails.push(\"deps changed\");\n\t\t\t}\n\t\t\tconst aFactory = a.type === \"template\" ? undefined : readFactory(a as GraphSpecNode);\n\t\t\tconst bFactory = b.type === \"template\" ? undefined : readFactory(b as GraphSpecNode);\n\t\t\tif (aFactory !== bFactory) {\n\t\t\t\tdetails.push(`fn: ${aFactory} → ${bFactory}`);\n\t\t\t}\n\t\t\tconst aArgs = a.type === \"template\" ? undefined : readFactoryArgs(a as GraphSpecNode);\n\t\t\tconst bArgs = b.type === \"template\" ? undefined : readFactoryArgs(b as GraphSpecNode);\n\t\t\tif (JSON.stringify(aArgs) !== JSON.stringify(bArgs)) {\n\t\t\t\tdetails.push(\"config changed\");\n\t\t\t}\n\t\t\tentries.push({\n\t\t\t\ttype: \"changed\",\n\t\t\t\tpath: `nodes.${name}`,\n\t\t\t\tdetail: details.join(\"; \") || \"modified\",\n\t\t\t});\n\t\t}\n\t}\n\n\t// Diff templates\n\tconst tmplA = specA.templates ?? {};\n\tconst tmplB = specB.templates ?? {};\n\tconst tmplNamesA = new Set(Object.keys(tmplA));\n\tconst tmplNamesB = new Set(Object.keys(tmplB));\n\n\tfor (const name of tmplNamesB) {\n\t\tif (!tmplNamesA.has(name)) {\n\t\t\tentries.push({ type: \"added\", path: `templates.${name}` });\n\t\t}\n\t}\n\tfor (const name of tmplNamesA) {\n\t\tif (!tmplNamesB.has(name)) {\n\t\t\tentries.push({ type: \"removed\", path: `templates.${name}` });\n\t\t}\n\t}\n\tfor (const name of tmplNamesA) {\n\t\tif (!tmplNamesB.has(name)) continue;\n\t\tif (JSON.stringify(tmplA[name]) !== JSON.stringify(tmplB[name])) {\n\t\t\tentries.push({\n\t\t\t\ttype: \"changed\",\n\t\t\t\tpath: `templates.${name}`,\n\t\t\t\tdetail: \"template definition changed\",\n\t\t\t});\n\t\t}\n\t}\n\n\t// Diff feedback\n\tconst fbA = specA.feedback ?? [];\n\tconst fbB = specB.feedback ?? [];\n\tconst fbKeyA = new Set(fbA.map((e) => `${e.from}->${e.to}`));\n\tconst fbKeyB = new Set(fbB.map((e) => `${e.from}->${e.to}`));\n\n\tfor (const fb of fbB) {\n\t\tconst key = `${fb.from}->${fb.to}`;\n\t\tif (!fbKeyA.has(key)) {\n\t\t\tentries.push({\n\t\t\t\ttype: \"added\",\n\t\t\t\tpath: `feedback.${key}`,\n\t\t\t\tdetail: `maxIterations: ${fb.maxIterations ?? 10}`,\n\t\t\t});\n\t\t}\n\t}\n\tfor (const fb of fbA) {\n\t\tconst key = `${fb.from}->${fb.to}`;\n\t\tif (!fbKeyB.has(key)) {\n\t\t\tentries.push({ type: \"removed\", path: `feedback.${key}` });\n\t\t}\n\t}\n\tfor (const fb of fbA) {\n\t\tconst key = `${fb.from}->${fb.to}`;\n\t\tconst counterpart = fbB.find((b) => b.from === fb.from && b.to === fb.to);\n\t\tif (counterpart && JSON.stringify(fb) !== JSON.stringify(counterpart)) {\n\t\t\tentries.push({\n\t\t\t\ttype: \"changed\",\n\t\t\t\tpath: `feedback.${key}`,\n\t\t\t\tdetail: `maxIterations: ${fb.maxIterations ?? 10} → ${counterpart.maxIterations ?? 10}`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Build summary\n\tconst added = entries.filter((e) => e.type === \"added\").length;\n\tconst removed = entries.filter((e) => e.type === \"removed\").length;\n\tconst changed = entries.filter((e) => e.type === \"changed\").length;\n\tconst parts: string[] = [];\n\tif (added) parts.push(`${added} added`);\n\tif (removed) parts.push(`${removed} removed`);\n\tif (changed) parts.push(`${changed} changed`);\n\tconst summary = parts.length > 0 ? parts.join(\", \") : \"no changes\";\n\n\treturn { entries, summary };\n}\n\n// ---------------------------------------------------------------------------\n// llmCompose\n// ---------------------------------------------------------------------------\n\n/** Options for {@link llmCompose}. */\nexport type LLMComposeOptions = {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Extra instructions appended to the system prompt. */\n\tsystemPromptExtra?: string;\n\t/**\n\t * Available fn/source catalog names for the LLM to reference.\n\t * When omitted and `catalog` contains rich {@link CatalogFnEntry} entries,\n\t * the prompt is auto-generated via {@link generateCatalogPrompt}.\n\t */\n\tcatalogDescription?: string;\n\t/**\n\t * Catalog for auto-prompt generation and catalog-aware validation.\n\t * When rich entries are provided, the catalog prompt is auto-generated\n\t * and LLM output is validated against fn/source names and config schemas.\n\t */\n\tcatalog?: GraphSpecCatalog;\n\t/**\n\t * Max auto-refine attempts when the LLM output fails catalog validation.\n\t * Each attempt feeds the validation errors back to the LLM via llmRefine.\n\t * Default: 0 (no auto-refine). Set to 2-3 for production use.\n\t */\n\tmaxAutoRefine?: number;\n};\n\nconst LLM_COMPOSE_SYSTEM_PROMPT = `You are a graph architect for GraphReFly, a reactive graph protocol.\n\nGiven a natural-language description, produce a JSON GraphSpec with this structure:\n\n{\n \"name\": \"<graph_name>\",\n \"nodes\": {\n \"<node_name>\": {\n \"type\": \"state\" | \"derived\" | \"producer\" | \"effect\",\n \"deps\": [\"<dep_node_name>\", ...],\n \"value\": <initial_value>,\n \"meta\": {\n \"factory\": \"<catalog_factory_name>\",\n \"factoryArgs\": { ... },\n \"description\": \"<purpose>\"\n }\n },\n \"<template_instance>\": {\n \"type\": \"template\",\n \"template\": \"<template_name>\",\n \"bind\": { \"$param\": \"node_name\" }\n }\n },\n \"templates\": {\n \"<template_name>\": {\n \"params\": [\"$param1\", \"$param2\"],\n \"nodes\": { ... },\n \"output\": \"<output_node>\"\n }\n },\n \"feedback\": [\n { \"from\": \"<condition_node>\", \"to\": \"<state_node>\", \"maxIterations\": 10 }\n ]\n}\n\nRules:\n- \"state\" nodes hold user/LLM-writable values (knobs). Stamp the initial value\n in \"meta.factoryArgs.initial\" (or as the top-level \"value\" field — both work).\n- \"derived\" nodes compute from deps using a catalog function named in\n \"meta.factory\"; pass any config via \"meta.factoryArgs\".\n- \"effect\" nodes produce side effects from deps; same meta.factory shape as derived.\n- \"producer\" nodes generate values from a catalog source named in \"meta.factory\";\n pass any config via \"meta.factoryArgs\".\n- Use \"templates\" when the same subgraph pattern repeats (e.g., per-source resilience).\n- Use \"feedback\" for bounded cycles where a derived value writes back to a state node.\n- meta.description is required for every node.\n- Return ONLY valid JSON, no markdown fences or commentary.`;\n\n/** Strip markdown code fences. */\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\n/**\n * Ask an LLM to compose a GraphSpec from a natural-language problem description.\n *\n * The LLM generates a GraphSpec (with templates + feedback), validated before\n * returning. The spec is for human review before compilation via compileSpec().\n *\n * @param problem - Natural language problem description.\n * @param adapter - LLM adapter for the generation call.\n * @param opts - Model options and catalog description.\n * @returns A validated GraphSpec.\n * @throws On invalid LLM output or validation failure.\n *\n * @category patterns\n */\nexport async function llmCompose(\n\tproblem: string,\n\tadapter: LLMAdapter,\n\topts?: LLMComposeOptions,\n): Promise<GraphSpec> {\n\tlet systemPrompt = LLM_COMPOSE_SYSTEM_PROMPT;\n\n\t// Auto-generate catalog prompt from rich entries, or use manual description\n\tconst catalogPrompt =\n\t\topts?.catalogDescription ?? (opts?.catalog ? generateCatalogPrompt(opts.catalog) : undefined);\n\tif (catalogPrompt) {\n\t\tsystemPrompt += `\\n\\nAvailable catalog (use ONLY these names):\\n${catalogPrompt}`;\n\t}\n\tif (opts?.systemPromptExtra) {\n\t\tsystemPrompt += `\\n\\n${opts.systemPromptExtra}`;\n\t}\n\n\tconst messages: ChatMessage[] = [\n\t\t{ role: \"system\", content: systemPrompt },\n\t\t{ role: \"user\", content: problem },\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\t// System boundary: await the adapter's response (Promise, plain value).\n\tconst response = (await rawResult) as LLMResponse;\n\tlet content = response.content.trim();\n\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(`llmCompose: LLM response is not valid JSON: ${content.slice(0, 200)}`);\n\t}\n\n\tconst validation = validateSpec(parsed);\n\tif (!validation.valid) {\n\t\tthrow new Error(`llmCompose: invalid GraphSpec:\\n${validation.errors.join(\"\\n\")}`);\n\t}\n\n\tlet spec = parsed as GraphSpec;\n\n\t// Catalog-aware validation + auto-refine loop\n\tif (opts?.catalog) {\n\t\tconst maxRefine = opts.maxAutoRefine ?? 0;\n\t\tfor (let attempt = 0; attempt <= maxRefine; attempt++) {\n\t\t\tconst catalogValidation = validateSpecAgainstCatalog(spec, opts.catalog);\n\t\t\tif (catalogValidation.valid) break;\n\n\t\t\tif (attempt === maxRefine) {\n\t\t\t\t// Last attempt failed — return with errors attached as meta\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`llmCompose: catalog validation failed after ${maxRefine} refine attempts:\\n${catalogValidation.errors.join(\"\\n\")}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Auto-refine: feed catalog errors back to LLM\n\t\t\tspec = await llmRefine(\n\t\t\t\tspec,\n\t\t\t\t`Fix these catalog errors:\\n${catalogValidation.errors.join(\"\\n\")}\\n\\nUse ONLY functions and sources from the catalog.`,\n\t\t\t\tadapter,\n\t\t\t\t{ ...opts, catalogDescription: catalogPrompt },\n\t\t\t);\n\t\t}\n\t}\n\n\treturn spec;\n}\n\n// ---------------------------------------------------------------------------\n// llmRefine\n// ---------------------------------------------------------------------------\n\n/** Options for {@link llmRefine}. */\nexport type LLMRefineOptions = LLMComposeOptions;\n\n/**\n * Ask an LLM to modify an existing GraphSpec based on feedback or changed requirements.\n *\n * @param currentSpec - The current GraphSpec to modify.\n * @param feedback - Natural language feedback or changed requirements.\n * @param adapter - LLM adapter for the generation call.\n * @param opts - Model options.\n * @returns A new GraphSpec incorporating the feedback.\n * @throws On invalid LLM output or validation failure.\n *\n * @category patterns\n */\nexport async function llmRefine(\n\tcurrentSpec: GraphSpec,\n\tfeedback: string,\n\tadapter: LLMAdapter,\n\topts?: LLMRefineOptions,\n): Promise<GraphSpec> {\n\tlet systemPrompt = LLM_COMPOSE_SYSTEM_PROMPT;\n\tif (opts?.catalogDescription) {\n\t\tsystemPrompt += `\\n\\nAvailable catalog:\\n${opts.catalogDescription}`;\n\t}\n\tif (opts?.systemPromptExtra) {\n\t\tsystemPrompt += `\\n\\n${opts.systemPromptExtra}`;\n\t}\n\n\tconst messages: ChatMessage[] = [\n\t\t{ role: \"system\", content: systemPrompt },\n\t\t{\n\t\t\trole: \"user\",\n\t\t\tcontent: `Current GraphSpec:\\n${JSON.stringify(currentSpec, null, 2)}\\n\\nModification request: ${feedback}\\n\\nReturn the complete modified GraphSpec as JSON.`,\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\t// System boundary: await the adapter's response.\n\tconst response = (await rawResult) as LLMResponse;\n\tlet content = response.content.trim();\n\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(`llmRefine: LLM response is not valid JSON: ${content.slice(0, 200)}`);\n\t}\n\n\tconst validation = validateSpec(parsed);\n\tif (!validation.valid) {\n\t\tthrow new Error(`llmRefine: invalid GraphSpec:\\n${validation.errors.join(\"\\n\")}`);\n\t}\n\n\treturn parsed as GraphSpec;\n}\n","/**\n * Reduction primitives (roadmap §8.1).\n *\n * Composable building blocks for taking heterogeneous massive inputs and producing\n * prioritized, auditable, human-actionable output. Each primitive is either a Graph\n * factory or a Node factory, built on top of core + extra primitives.\n *\n * @module\n */\n\nimport {\n\tbatch,\n\tCOMPLETE,\n\tDATA,\n\tERROR,\n\ttype Message,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n} from \"@graphrefly/pure-ts/core\";\n\nimport { merge } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\n\n// ---------------------------------------------------------------------------\n// Shared helpers (same pattern as orchestration.ts)\n// ---------------------------------------------------------------------------\n\nexport type { StepRef } from \"../orchestration/pipeline-graph.js\";\n\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport { tryIncrementBounded } from \"../../base/mutation/index.js\";\nimport type { StepRef } from \"../orchestration/pipeline-graph.js\";\n\nfunction baseMeta(kind: string, meta?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"reduction\", kind, meta);\n}\n\n// stratify moved to `src/extra/stratify.ts` (protocol-level primitive).\n\n// ---------------------------------------------------------------------------\n// funnel\n// ---------------------------------------------------------------------------\n\n/** A named stage for {@link funnel}. */\nexport type FunnelStage = {\n\t/** Stage name (mounted as subgraph). */\n\tname: string;\n\t/** Builder: receives a sub-graph, should add an `\"input\"` and `\"output\"` node. */\n\tbuild: (sub: Graph) => void;\n};\n\n/** Options for {@link funnel}. */\nexport type FunnelOptions = GraphOptions & {\n\tmeta?: Record<string, unknown>;\n};\n\n/**\n * Multi-source merge with sequential reduction stages.\n *\n * Sources are merged into a single stream. Each stage is a named subgraph\n * (mounted via `graph.mount()`). Stages connect linearly:\n * `merged → stage[0].input → stage[0].output → stage[1].input → ...`\n *\n * @param name - Graph name.\n * @param sources - Input nodes to merge.\n * @param stages - Sequential reduction stages.\n * @param opts - Optional graph/meta options.\n * @returns Graph with `\"merged\"` and mounted stage subgraphs.\n *\n * @category patterns\n */\nexport function funnel<T>(\n\tname: string,\n\tsources: ReadonlyArray<Node<T>>,\n\tstages: ReadonlyArray<FunnelStage>,\n\topts?: FunnelOptions,\n): Graph {\n\tif (sources.length === 0) throw new RangeError(\"funnel requires at least one source\");\n\tif (stages.length === 0) throw new RangeError(\"funnel requires at least one stage\");\n\n\tconst g = new Graph(name, opts);\n\n\t// Merge all sources\n\tconst merged = sources.length === 1 ? sources[0] : merge(...(sources as unknown as Node<T>[]));\n\tg.add(merged as Node<unknown>, { name: \"merged\" });\n\n\t// Build and mount each stage linearly.\n\t// Stage inputs are standalone state nodes, so we bridge via subscribe\n\t// (connect() requires constructor deps). Bridge effects forward DATA\n\t// from the previous output to the next stage's input.\n\tlet prevOutputPath = \"merged\";\n\tfor (let i = 0; i < stages.length; i++) {\n\t\tconst stage = stages[i];\n\t\tconst sub = new Graph(stage.name);\n\t\tstage.build(sub);\n\n\t\t// Validate that the stage has input and output nodes\n\t\ttry {\n\t\t\tsub.resolve(\"input\");\n\t\t} catch {\n\t\t\tthrow new Error(`funnel stage \"${stage.name}\" must define an \"input\" node`);\n\t\t}\n\t\ttry {\n\t\t\tsub.resolve(\"output\");\n\t\t} catch {\n\t\t\tthrow new Error(`funnel stage \"${stage.name}\" must define an \"output\" node`);\n\t\t}\n\n\t\tg.mount(stage.name, sub);\n\n\t\t// Bridge replacement: effect that forwards DATA from previous output\n\t\t// to the next stage's input. TEARDOWN excluded because stage lifecycle\n\t\t// is managed by the parent graph. Shows up in describe().\n\t\tconst prevNode = g.resolve(prevOutputPath);\n\t\tconst stageInputPath = `${stage.name}::input`;\n\t\tconst stageInput = g.resolve(stageInputPath);\n\t\tconst bridgeName = `__bridge_${prevOutputPath}→${stage.name}_input`;\n\t\tconst br = node(\n\t\t\t[prevNode],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tstageInput.emit(data[0]);\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\t{ describeKind: \"effect\", name: bridgeName },\n\t\t);\n\t\tg.add(br as Node<unknown>, { name: bridgeName });\n\t\tg.addDisposer(keepalive(br));\n\n\t\tprevOutputPath = `${stage.name}::output`;\n\t}\n\n\treturn g;\n}\n\n// ---------------------------------------------------------------------------\n// feedback\n// ---------------------------------------------------------------------------\n\n/** Options for {@link feedback}. */\nexport type FeedbackOptions = {\n\t/** Maximum feedback iterations before stopping (default: 10). */\n\tmaxIterations?: number;\n\t/** Optional budget gate node path for cost-bounded iteration. */\n\tbudgetNode?: StepRef;\n\tmeta?: Record<string, unknown>;\n};\n\n/**\n * Introduce a bounded reactive cycle into an existing graph.\n *\n * When `condition` emits a non-null DATA value, the feedback effect routes it\n * back to the `reentry` state node — creating a cycle. Bounded by\n * `maxIterations` (default 10). The counter node (`__feedback_<condition>`)\n * is the source of truth — reset it to 0 to allow more iterations.\n *\n * To remove the feedback cycle, call `graph.remove(\"__feedback_<condition>\")`.\n *\n * @param graph - Existing graph to augment with a feedback cycle.\n * @param condition - Path to a node whose DATA triggers feedback.\n * @param reentry - Path to a state node that receives the feedback value.\n * @param opts - Iteration bounds and metadata.\n * @returns The same graph (mutated with feedback nodes added).\n *\n * @category patterns\n */\nexport function feedback(\n\tgraph: Graph,\n\tcondition: string,\n\treentry: string,\n\topts?: FeedbackOptions,\n): Graph {\n\tconst maxIter = opts?.maxIterations ?? 10;\n\n\t// Internal counter node — source of truth for iteration bound.\n\t// Reset to 0 to allow more iterations.\n\tconst counterName = `__feedback_${condition}`;\n\tconst counter = node<number>([], {\n\t\t...{\n\t\t\tmeta: baseMeta(\"feedback_counter\", {\n\t\t\t\tmaxIterations: maxIter,\n\t\t\t\tfeedbackFrom: condition,\n\t\t\t\tfeedbackTo: reentry,\n\t\t\t}),\n\t\t},\n\t\tinitial: 0,\n\t});\n\tgraph.add(counter as Node<unknown>, { name: counterName });\n\n\t// Resolve the condition and reentry nodes\n\tconst condNode = graph.resolve(condition);\n\tconst reentryNode = graph.resolve(reentry);\n\n\t// Graph-visible feedback effect: intercepts condition DATA, routes back to\n\t// reentry with iteration counting. Registered in the graph so it shows up\n\t// in describe() and cleans up on graph.destroy().\n\t// Feedback effect: subscribe to condition node for per-message interception\n\t// (onMessage removed in v5 — use producer+subscribe instead)\n\tconst feedbackEffectName = `__feedback_effect_${condition}`;\n\tconst feedbackEffect = node(\n\t\t[],\n\t\t(_data, _feedbackActions) => {\n\t\t\tconst unsub = condNode.subscribe((msgs) => {\n\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\tconst t = msg[0];\n\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\tconst condValue = msg[1];\n\t\t\t\t\t\tif (condValue == null) return;\n\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\tif (tryIncrementBounded(counter, maxIter)) {\n\t\t\t\t\t\t\t\treentryNode.emit(condValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (t === COMPLETE || t === ERROR) {\n\t\t\t\t\t\tconst terminal: Message = t === ERROR && msg.length > 1 ? [ERROR, msg[1]] : [t];\n\t\t\t\t\t\tcounter.down([terminal]);\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\tname: feedbackEffectName,\n\t\t\tdescribeKind: \"effect\",\n\t\t\tmeta: {\n\t\t\t\t...baseMeta(\"feedback_effect\", {\n\t\t\t\t\tfeedbackFrom: condition,\n\t\t\t\t\tfeedbackTo: reentry,\n\t\t\t\t}),\n\t\t\t\t_internal: true,\n\t\t\t},\n\t\t},\n\t);\n\tgraph.add(feedbackEffect as Node<unknown>, { name: feedbackEffectName });\n\tgraph.addDisposer(keepalive(feedbackEffect));\n\n\treturn graph;\n}\n\n// `budgetGate` was promoted to `extra/resilience/budget-gate.ts` per Tier 2.2.\n// Import from `@graphrefly/graphrefly/extra` (or `../../extra/resilience/budget-gate.js`\n// internally) instead. See the resilience family for sibling primitives:\n// `retry`, `circuitBreaker`, `rateLimiter`, `tokenBucket`, `fallback`, `withStatus`.\n\n// ---------------------------------------------------------------------------\n// scorer\n// ---------------------------------------------------------------------------\n\n/** A scored item with full breakdown. */\nexport type ScoredItem<T = unknown> = {\n\t/** Original value. */\n\tvalue: T;\n\t/** Final weighted score. */\n\tscore: number;\n\t/** Per-signal breakdown: signal index → weighted contribution. */\n\tbreakdown: number[];\n};\n\n/** Options for {@link scorer}. */\nexport type ScorerOptions = Omit<NodeOptions<unknown>, \"describeKind\" | \"name\" | \"meta\"> & {\n\tmeta?: Record<string, unknown>;\n\t/** Custom scoring function per signal. Default: identity (signal value IS the score). */\n\tscoreFns?: ReadonlyArray<(value: unknown) => number>;\n};\n\n/**\n * Reactive multi-signal scoring with live weights.\n *\n * Each source emits items to score. Weights are reactive state nodes that\n * LLM or human can adjust live. Output is sorted scored items with full\n * breakdown.\n *\n * @param sources - Signal nodes (each emits a numeric score dimension).\n * @param weights - Reactive weight nodes (one per source).\n * @param opts - Optional node/meta options.\n * @returns Node emitting scored output.\n *\n * @category patterns\n */\nexport function scorer(\n\tsources: ReadonlyArray<Node<number>>,\n\tweights: ReadonlyArray<Node<number>>,\n\topts?: ScorerOptions,\n): Node<ScoredItem<number[]>> {\n\tif (sources.length === 0) throw new RangeError(\"scorer requires at least one source\");\n\tif (sources.length !== weights.length) {\n\t\tthrow new RangeError(\"scorer requires the same number of sources and weights\");\n\t}\n\n\tconst allDeps = [...(sources as unknown as Node[]), ...(weights as unknown as Node[])];\n\tconst n = sources.length;\n\tconst scoreFns = opts?.scoreFns;\n\n\treturn node<ScoredItem<number[]>>(\n\t\tallDeps,\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst vals = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst signals = vals.slice(0, n) as number[];\n\t\t\tconst weightValues = vals.slice(n) as number[];\n\n\t\t\tconst breakdown: number[] = [];\n\t\t\tlet totalScore = 0;\n\n\t\t\tfor (let i = 0; i < n; i++) {\n\t\t\t\tconst sig = signals[i] ?? 0;\n\t\t\t\tconst wt = weightValues[i] ?? 0;\n\t\t\t\tconst rawScore = scoreFns?.[i] ? scoreFns[i](sig) : sig;\n\t\t\t\tconst weighted = (rawScore as number) * wt;\n\t\t\t\tbreakdown.push(weighted);\n\t\t\t\ttotalScore += weighted;\n\t\t\t}\n\n\t\t\tactions.emit({\n\t\t\t\tvalue: signals,\n\t\t\t\tscore: totalScore,\n\t\t\t\tbreakdown,\n\t\t\t});\n\t\t},\n\t\t{\n\t\t\t...(opts\n\t\t\t\t? {\n\t\t\t\t\t\tequals: opts.equals,\n\t\t\t\t\t\tresubscribable: opts.resubscribable,\n\t\t\t\t\t\tresetOnTeardown: opts.resetOnTeardown,\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"scorer\", opts?.meta),\n\t\t},\n\t);\n}\n\n// `effectivenessTracker` was deleted per Class B audit Alt E (2026-04-30).\n// The shared substrate now lives in `extra/composition/audited-success-tracker.ts`\n// — re-exported via `@graphrefly/graphrefly-ts/extra` for general use.\n","// ---------------------------------------------------------------------------\n// 5.4 — LLM tool integration\n// ---------------------------------------------------------------------------\n\nimport type { Actor } from \"@graphrefly/pure-ts/core\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport type { ToolDefinition } from \"../adapters/core/types.js\";\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// suggestStrategy\n// ---------------------------------------------------------------------------\n\nimport type { Actor, Node } from \"@graphrefly/pure-ts/core\";\nimport { COMPLETE, ERROR, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput, switchMap, withLatestFrom } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { resolveToolHandlerResult } from \"../_internal.js\";\nimport type { ChatMessage, LLMAdapter, LLMResponse } from \"../adapters/core/types.js\";\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\t/**\n\t * Optional AbortSignal forwarded to `adapter.invoke({ signal })`. Lets\n\t * callers cancel the in-flight LLM call (e.g. when the reactive variant\n\t * supersedes mid-flight). When the signal aborts, the underlying call\n\t * propagates the abort and `suggestStrategy` rejects with the abort reason.\n\t */\n\tsignal?: AbortSignal;\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\tsignal: opts?.signal,\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/**\n * Reactive variant of {@link suggestStrategy}: re-invokes the LLM whenever\n * the `problem` source emits, sampling the latest `graph` value (via\n * `withLatestFrom`) to describe. The graph is the *secondary* dep — only\n * problem changes re-trigger analysis. This breaks the feedback cycle that\n * would otherwise arise if downstream consumers wired `apply(plan)` back\n * into the same graph node (graph mutation must not auto-fire a re-analysis).\n *\n * @param graph - Reactive source of graphs to analyze.\n * @param problem - Reactive source of natural-language problem statements.\n * @param adapter - LLM adapter for the analysis call.\n * @param opts - Model and actor options.\n * @returns `Node<StrategyPlan | null>` — emits the latest plan, or `null`\n * while inputs are unsettled.\n */\nexport function suggestStrategyReactive(\n\tgraph: Node<Graph | null>,\n\tproblem: NodeInput<string>,\n\tadapter: LLMAdapter,\n\topts?: SuggestStrategyOptions,\n): Node<StrategyPlan | null> {\n\tconst problemNode = fromAny(problem);\n\t// problem is primary (re-triggers on change); graph is sampled — no\n\t// graph-edit-feedback loop to suggestStrategy when callers apply ops.\n\tconst paired = withLatestFrom(problemNode as Node<unknown>, graph as Node<unknown>);\n\treturn switchMap<unknown, StrategyPlan | null>(paired, (pair) => {\n\t\tif (pair == null) return node<StrategyPlan | null>([], { initial: null });\n\t\tconst [pText, g] = pair as [string | null, Graph | null];\n\t\tif (!g || !pText || typeof pText !== \"string\" || pText.trim().length === 0) {\n\t\t\treturn node<StrategyPlan | null>([], { initial: null });\n\t\t}\n\t\t// QA-fix: skip rather than ERROR if the sampled Graph was destroyed\n\t\t// between the `withLatestFrom` sample and this project fn. Common when\n\t\t// a caller's reactive `graph: Node<Graph | null>` cycles graphs faster\n\t\t// than `suggestStrategy` resolves; the supersede was the user's intent,\n\t\t// so emitting null here matches \"input not ready\" semantics rather\n\t\t// than surfacing a spurious ERROR on the StrategyPlan stream.\n\t\tif (g.destroyed) return node<StrategyPlan | null>([], { initial: null });\n\t\treturn node<StrategyPlan | null>(\n\t\t\t(_data, actions) => {\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tlet cancelled = false;\n\t\t\t\tsuggestStrategy(g, pText, adapter, { ...opts, signal: controller.signal })\n\t\t\t\t\t.then((plan) => {\n\t\t\t\t\t\tif (cancelled) return;\n\t\t\t\t\t\tactions.emit(plan);\n\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tif (cancelled) return;\n\t\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\t});\n\t\t\t\treturn () => {\n\t\t\t\t\tcancelled = true;\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ describeKind: \"producer\", ...{ name: \"suggestStrategy::call\" } },\n\t\t);\n\t});\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 * CQRS patterns (roadmap §4.5).\n *\n * Composition layer over reactiveLog (3.2), pipeline/sagas (4.1), event bus (4.2),\n * projections (4.3). Guards (1.5) enforce command/query boundary.\n *\n * - `cqrs(name, opts?)` → `CqrsGraph` — top-level factory\n * - `CqrsGraph.command(name, handler)` — write-only node; guard rejects `observe`\n * - `CqrsGraph.event(name)` — backed by `reactiveLog`; append-only\n * - `CqrsGraph.projection(name, events, reducer, initial)` — read-only derived; guard rejects `write`\n * - `CqrsGraph.saga(name, events, handler)` — event-driven side effects\n */\n\nimport {\n\tDATA,\n\ttype Node,\n\tnode,\n\tplaceholderArgs,\n\tpolicy,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport type { AppendLogStorageTier } from \"@graphrefly/pure-ts/extra\";\nimport { type ReactiveLogBundle, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport {\n\ttype BaseAuditRecord,\n\tcreateAuditLog,\n\tmutate,\n\tregisterCursor,\n\tregisterCursorMap,\n} from \"../../base/mutation/index.js\";\nimport {\n\tCommandHandlerError,\n\tDuplicateRegistrationError,\n\tOptimisticConcurrencyError,\n\tRebuildError,\n\tUndeclaredEmitError,\n\tUnknownCommandError,\n} from \"../_errors/index.js\";\n\n// ---------------------------------------------------------------------------\n// Guards\n// ---------------------------------------------------------------------------\n\n/** Commands: write + signal allowed, observe denied. */\nconst COMMAND_GUARD = policy((allow, deny) => {\n\tallow(\"write\");\n\tallow(\"signal\");\n\tdeny(\"observe\");\n});\n\n/** Projections: observe + signal allowed, write denied. */\nconst PROJECTION_GUARD = policy((allow, deny) => {\n\tallow(\"observe\");\n\tallow(\"signal\");\n\tdeny(\"write\");\n});\n\n/** Events: observe + signal allowed, write denied (appended internally). */\nconst EVENT_GUARD = policy((allow, deny) => {\n\tallow(\"observe\");\n\tallow(\"signal\");\n\tdeny(\"write\");\n});\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\n\nfunction cqrsMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"cqrs\", kind, extra);\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (value === null || typeof value !== \"object\" || Object.isFrozen(value)) return value;\n\tfor (const k of Object.keys(value as Record<string, unknown>)) {\n\t\tdeepFreeze((value as Record<string, unknown>)[k]);\n\t}\n\treturn Object.freeze(value);\n}\n\n// ---------------------------------------------------------------------------\n// Event envelope\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable envelope for events emitted by command handlers.\n *\n * **Wave C.1 Unit 17 (locked 2026-04-24):** Extended ES standard fields —\n * `aggregateId` / `aggregateVersion` for per-aggregate streams; correlation /\n * causation IDs for distributed tracing; `metadata` for free-form context.\n * Optional `handlerVersion` (Audit 5) traces which handler version produced\n * the event.\n *\n * `seq` is a per-graph monotonic counter that provides stable ordering when\n * multiple events share the same `timestampNs` (same wall-clock tick).\n */\nexport type CqrsEvent<T = unknown> = {\n\ttype: string;\n\tpayload: T;\n\t/** Wall-clock nanoseconds (via `wallClockNs()`). */\n\ttimestampNs: number;\n\t/** Monotonic sequence within this CqrsGraph instance. */\n\tseq: number;\n\t/** Aggregate identifier (per-aggregate streams). */\n\taggregateId?: string;\n\t/** Per-aggregate monotonic version (set when `aggregateId` is provided). */\n\taggregateVersion?: number;\n\t/** Distributed-trace correlation id. */\n\tcorrelationId?: string;\n\t/** Causation chain id (this event was caused by event `causationId`). */\n\tcausationId?: string;\n\t/** Free-form metadata frozen at append. */\n\tmetadata?: Readonly<Record<string, unknown>>;\n\t/** V0 identity of the event log node at append time (§6.0b). */\n\tv0?: { id: string; version: number };\n\t/** Handler version stamped on emit (Audit 5). */\n\thandlerVersion?: { id: string; version: string | number };\n};\n\n/** Compile-time event-map registry: `{ \"orderPlaced\": OrderPayload, ... }`. */\nexport type CqrsEventMap = Record<string, unknown>;\n\n/** Recommended `keyOf` for CQRS event-store storage tiers (Audit 4). */\nexport const cqrsEventKeyOf = (e: CqrsEvent): string =>\n\t`${e.type}::${e.aggregateId ?? \"__default__\"}`;\n\n// ── Audit records (Audit 2 cross-cutting) ────────────────────────────────\n\nexport interface DispatchRecord<T = unknown> extends BaseAuditRecord {\n\treadonly commandName: string;\n\treadonly payload: T;\n\t/** Action result. Tier 1.6.2 canonical enum (renamed from `status`). */\n\treadonly outcome: \"success\" | \"failure\";\n\treadonly error?: unknown;\n\treadonly errorType?: string;\n\t/**\n\t * Event names emitted by the handler.\n\t * - `outcome: \"success\"`: events that persisted in the event log.\n\t * - `outcome: \"failure\"`: events the handler ATTEMPTED to emit before throwing;\n\t * they were rolled back and did NOT persist. Documents the failed attempt's\n\t * intentions for debugging handler logic. The actual event log shows only\n\t * what's durable.\n\t */\n\treadonly emittedEvents?: readonly string[];\n}\n\nexport const dispatchKeyOf = <T>(r: DispatchRecord<T>): string => r.commandName;\n\nexport interface SagaInvocation<T = unknown> extends BaseAuditRecord {\n\treadonly eventType: string;\n\t/** Action result. Tier 1.6.2 canonical enum (renamed from `status`). */\n\treadonly outcome: \"success\" | \"failure\";\n\treadonly error?: unknown;\n\treadonly errorType?: string;\n\treadonly aggregateId?: string;\n\treadonly event?: CqrsEvent<T>;\n}\n\nexport const sagaInvocationKeyOf = <T>(i: SagaInvocation<T>): string => i.eventType;\n\n/**\n * Saga registration result (M10) — a typed bundle replacing the prior\n * `Node<unknown>` return that side-attached `_saga` via an unsafe cast.\n *\n * `node` is the saga's effect node (subscribe to observe processing\n * activity). `invocations` is the per-event-type audit log; `audit` aliases\n * `invocations` (Audit 2 `.audit` duplication). `cursors` exposes the\n * per-event-type cursor state nodes for monitoring / testing.\n *\n * @category patterns\n */\nexport interface SagaController<T = unknown> {\n\treadonly node: Node<unknown>;\n\treadonly invocations: ReactiveLogBundle<SagaInvocation<T>>;\n\treadonly audit: ReactiveLogBundle<SagaInvocation<T>>;\n\treadonly cursors: { readonly [eventName: string]: Node<number> };\n}\n\n// ---------------------------------------------------------------------------\n// Handler types\n// ---------------------------------------------------------------------------\n\nexport type CommandActions = {\n\t/** Append an event to a named event log (bypasses event guard). */\n\temit: (eventName: string, payload: unknown) => void;\n};\n\n/**\n * Command handler receives the dispatch payload and actions to emit events.\n *\n * **Purity:** Handlers should not mutate the payload. Event emission via\n * `actions.emit()` is the only sanctioned side effect.\n */\nexport type CommandHandler<T = unknown> = (payload: T, actions: CommandActions) => void;\n\n/**\n * Projection reducer folds events into a read model.\n *\n * **Purity contract:** Reducers MUST be pure — return a new state value\n * without mutating `state` or any event.\n *\n * - In **`\"replay\"`** mode the `state` parameter is always the original\n * `initial` value (full event-sourcing replay on every recompute).\n * - In **`\"scan\"`** mode the `state` parameter is the _previous_ output\n * (incremental fold); `events` contains only the events appended since\n * the last computation.\n */\nexport type ProjectionReducer<TState = unknown, TEvent = unknown> = (\n\tstate: TState,\n\tevents: readonly CqrsEvent<TEvent>[],\n) => TState;\n\n/**\n * Snapshot integration for {@link ProjectionOptions}.\n *\n * `load` is called once at projection construction and the returned value\n * seeds the initial state. `save` (optional) is called after each reducer\n * run, debounced by `saveDebounceMs` (default 1000 ms) and capped by\n * `saveEvery` (default 1000 events).\n */\nexport type ProjectionSnapshotOpts<TState> = {\n\t/** Load a previously-saved state. `undefined` → start from `initial`. */\n\tload: () => TState | undefined | Promise<TState | undefined>;\n\t/** Persist the current state. Called after reducer; may be async. */\n\tsave?: (state: TState) => void | Promise<void>;\n\t/**\n\t * Debounce window (ms) before `save` fires after the last event. Default 1000.\n\t */\n\tsaveDebounceMs?: number;\n\t/**\n\t * Force a save after every Nth state change regardless of debounce.\n\t * Default 1000. Both knobs compose: save fires at whichever condition is\n\t * met first.\n\t */\n\tsaveEvery?: number;\n};\n\n/**\n * Options for {@link CqrsGraph.projection}.\n *\n * **Wave C.3 Unit 21 (locked 2026-04-24):**\n * - `mode: \"scan\"` (default) — incremental fold; `\"replay\"` — full replay\n * each wave.\n * - `snapshot` — load/save integration for cold-start + auto-checkpoint.\n * - `freezeInputs` (default `true`) — freeze event arrays before passing\n * to reducer (purity enforcement).\n * - `rebuild()` / `reset()` on the returned {@link ProjectionController}.\n *\n * @category patterns\n */\nexport type ProjectionOptions<TState> = {\n\tname: string;\n\tevents: readonly string[];\n\treducer: ProjectionReducer<TState>;\n\tinitial: TState;\n\t/**\n\t * Fold strategy. Default `\"scan\"` (incremental). `\"replay\"` = full replay.\n\t *\n\t * **Scan-mode ordering caveat:** scan-mode assumes monotonic per-stream\n\t * arrival order. When multiple event streams are merged for a projection,\n\t * events arriving with a `timestampNs` earlier than the current sort cursor\n\t * are skipped from the incremental sweep. This is an acceptable trade-off\n\t * for incremental fold; use `mode: \"replay\"` for strict cross-stream\n\t * ordering.\n\t */\n\tmode?: \"replay\" | \"scan\";\n\t/** Snapshot integration for rebuild + auto-checkpoint. */\n\tsnapshot?: ProjectionSnapshotOpts<TState>;\n\t/**\n\t * Freeze event arrays before passing to reducer (default `true`).\n\t * Set to `false` only if your reducer intentionally mutates the input\n\t * (strongly discouraged — prefer immutable reducers).\n\t */\n\tfreezeInputs?: boolean;\n};\n\n/**\n * Controller returned by {@link CqrsGraph.projection}.\n *\n * `node` is the reactive read model. `rebuild()` performs a paginated\n * cold-storage replay (requires `attachEventStorage` tiers). `reset()`\n * reloads from `snapshot.load()` and re-folds the live event log on top.\n *\n * @category patterns\n */\nexport interface ProjectionController<TState> {\n\treadonly node: Node<TState>;\n\t/**\n\t * Async paginated rebuild from attached storage tiers. Throws\n\t * {@link RebuildError} on adapter / decode / reducer failure.\n\t *\n\t * @param opts.fromTier - Storage tier to read from (default: first attached).\n\t * @param opts.pageSize - Entries per page (default 1000).\n\t */\n\trebuild(opts?: {\n\t\tfromTier?: AppendLogStorageTier<CqrsEvent>;\n\t\tpageSize?: number;\n\t}): Promise<TState>;\n\t/**\n\t * Reload from `snapshot.load()` (if configured) and re-fold the live\n\t * in-memory event log on top. Returns the rebuilt state. No-op on the\n\t * reactive node if the state is unchanged.\n\t */\n\treset(): Promise<TState>;\n}\n\nexport type SagaHandler<T = unknown> = (event: CqrsEvent<T>) => void;\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport type CqrsOptions = {\n\tgraph?: GraphOptions;\n\t/** Bounded retention for event streams; default 1024 (cross-cutting). */\n\tretainedLimit?: number;\n\t/** Freeze command payloads on dispatch (default `true`). */\n\tfreezeCommandPayload?: boolean;\n\t/** Freeze event payloads on emit (default `true`). */\n\tfreezeEventPayload?: boolean;\n\t/** LRU eviction threshold for per-aggregate streams (default 10_000). */\n\tmaxAggregates?: number;\n};\n\nexport type CommandRegistration<TPayload = unknown> = {\n\thandler: CommandHandler<TPayload>;\n\temits?: readonly string[];\n\thandlerVersion?: { id: string; version: string | number };\n};\n\nexport type DispatchOptions = {\n\tcorrelationId?: string;\n\tcausationId?: string;\n\tmetadata?: Record<string, unknown>;\n\t/**\n\t * Optimistic-concurrency check: if set, dispatch verifies the aggregate\n\t * (identified by `aggregateId`) is at this version. On mismatch, dispatch\n\t * throws {@link OptimisticConcurrencyError} BEFORE the handler runs.\n\t *\n\t * Requires `aggregateId` to be set. Without it the check is a no-op.\n\t */\n\texpectedAggregateVersion?: number;\n\t/**\n\t * Aggregate this dispatch targets. Events emitted by the handler that\n\t * also carry this `aggregateId` participate in per-aggregate versioning\n\t * and LRU eviction (see {@link CqrsOptions.maxAggregates}). Events whose\n\t * handler-supplied `aggregateId` differs from the dispatch's `aggregateId`\n\t * are emitted untouched (their own `aggregateVersion` is computed from\n\t * their own aggregate's stream).\n\t */\n\taggregateId?: string;\n};\n\nexport type SagaOptions = {\n\taggregateId?: string;\n\terrorPolicy?: \"advance\" | \"hold\";\n\thandlerVersion?: { id: string; version: string | number };\n};\n\n// ---------------------------------------------------------------------------\n// CqrsGraph\n// ---------------------------------------------------------------------------\n\ntype EventEntry = {\n\tlog: ReturnType<typeof reactiveLog<CqrsEvent>>;\n\tnode: Node<readonly CqrsEvent[]>;\n};\n\n/**\n * Eviction record emitted on `aggregateEvictions` when an aggregate's\n * per-aggregate stream is removed under `maxAggregates` LRU pressure. The\n * eviction does NOT delete events from the fan-in stream — only the\n * per-aggregate dedicated stream and its version counter.\n */\nexport interface AggregateEvictionRecord {\n\treadonly aggregateId: string;\n\treadonly type: string;\n\treadonly t_ns: number;\n\t/** The version count the aggregate reached before eviction (for diagnostics). */\n\treadonly lastVersion: number;\n}\n\nexport class CqrsGraph<_EM extends CqrsEventMap = Record<string, unknown>> extends Graph {\n\t/** Fan-in event streams (one per type, all aggregates merged). */\n\tprivate readonly _eventLogs = new Map<string, EventEntry>();\n\t/**\n\t * Per-aggregate event streams: type → aggregateId → entry. Used for\n\t * `event(type, aggregateId)` dual-form access and per-aggregate version\n\t * tracking. Only populated when an event with `aggregateId` is emitted.\n\t */\n\tprivate readonly _eventLogsByAggregate = new Map<string, Map<string, EventEntry>>();\n\t/** Per-aggregate version counters: `${type}::${aggregateId}` → current version. */\n\tprivate readonly _aggregateVersions = new Map<string, number>();\n\t/**\n\t * LRU access order for `${type}::${aggregateId}`. Map insertion order\n\t * tracks recency — `delete` + `set` on access moves to the end.\n\t */\n\tprivate readonly _aggregateLru = new Map<string, true>();\n\tprivate readonly _commandRegs = new Map<\n\t\tstring,\n\t\t{\n\t\t\thandler: CommandHandler<any>;\n\t\t\temits?: readonly string[];\n\t\t\thandlerVersion?: { id: string; version: string | number };\n\t\t}\n\t>();\n\tprivate readonly _projections = new Set<string>();\n\tprivate readonly _sagas = new Set<string>();\n\tprivate _seq = 0;\n\tprivate readonly _retainedLimit: number;\n\tprivate readonly _freezeCommandPayload: boolean;\n\tprivate readonly _freezeEventPayload: boolean;\n\tprivate readonly _maxAggregates: number;\n\tprivate readonly _dispatchSeqCursor: Node<number>;\n\t/** Audit log of every command dispatch (Audit 2). */\n\treadonly dispatches: ReactiveLogBundle<DispatchRecord>;\n\t/** Alias for {@link CqrsGraph.dispatches} (Audit 2 `.audit` duplication). */\n\treadonly audit: ReactiveLogBundle<DispatchRecord>;\n\t/** Per-aggregate LRU eviction observability; secondary log to `dispatches`. */\n\treadonly aggregateEvictions: ReactiveLogBundle<AggregateEvictionRecord>;\n\n\tconstructor(name: string, opts: CqrsOptions = {}) {\n\t\tsuper(name, opts.graph);\n\t\tthis._retainedLimit = opts.retainedLimit ?? 1024;\n\t\tthis._freezeCommandPayload = opts.freezeCommandPayload ?? true;\n\t\tthis._freezeEventPayload = opts.freezeEventPayload ?? true;\n\t\tthis._maxAggregates = opts.maxAggregates ?? 10_000;\n\t\tthis.dispatches = createAuditLog<DispatchRecord>({\n\t\t\tname: \"dispatches\",\n\t\t\tretainedLimit: this._retainedLimit,\n\t\t\tgraph: this,\n\t\t});\n\t\tthis.audit = this.dispatches;\n\t\tthis.aggregateEvictions = createAuditLog<AggregateEvictionRecord>({\n\t\t\tname: \"aggregateEvictions\",\n\t\t\tretainedLimit: this._retainedLimit,\n\t\t\tgraph: this,\n\t\t});\n\t\tthis._dispatchSeqCursor = registerCursor(this, \"dispatch_seq\", 0);\n\t}\n\n\t/**\n\t * Read the current per-aggregate version (last emitted `aggregateVersion`\n\t * for that `(type, aggregateId)` pair). Returns `0` if no events have been\n\t * emitted yet for this aggregate. Useful for callers preparing\n\t * {@link DispatchOptions.expectedAggregateVersion}.\n\t */\n\taggregateVersion(type: string, aggregateId: string): number {\n\t\treturn this._aggregateVersions.get(`${type}::${aggregateId}`) ?? 0;\n\t}\n\n\t/** LRU touch — moves the key to the end of the access order. */\n\tprivate _touchAggregate(key: string): void {\n\t\t// Delete + set re-inserts at the end of Map iteration order.\n\t\tthis._aggregateLru.delete(key);\n\t\tthis._aggregateLru.set(key, true);\n\t}\n\n\t/**\n\t * Evict the oldest aggregate streams (least-recently-touched) until the\n\t * aggregate count is back within `_maxAggregates`. Emits one\n\t * `AggregateEvictionRecord` per eviction. The fan-in stream is NOT touched\n\t * — events stay in the type-level log; only the per-aggregate stream and\n\t * version counter are removed.\n\t */\n\tprivate _enforceAggregateLru(): void {\n\t\twhile (this._aggregateLru.size > this._maxAggregates) {\n\t\t\tconst oldest = this._aggregateLru.keys().next();\n\t\t\tif (oldest.done) break;\n\t\t\tconst key = oldest.value;\n\t\t\tthis._aggregateLru.delete(key);\n\t\t\tconst sep = key.indexOf(\"::\");\n\t\t\tif (sep < 0) continue;\n\t\t\tconst type = key.slice(0, sep);\n\t\t\tconst aggregateId = key.slice(sep + 2);\n\t\t\tconst lastVersion = this._aggregateVersions.get(key) ?? 0;\n\t\t\tthis._aggregateVersions.delete(key);\n\t\t\tconst byType = this._eventLogsByAggregate.get(type);\n\t\t\tif (byType) {\n\t\t\t\tbyType.delete(aggregateId);\n\t\t\t\tif (byType.size === 0) this._eventLogsByAggregate.delete(type);\n\t\t\t}\n\t\t\tthis.aggregateEvictions.append({\n\t\t\t\taggregateId,\n\t\t\t\ttype,\n\t\t\t\tlastVersion,\n\t\t\t\tt_ns: wallClockNs(),\n\t\t\t});\n\t\t}\n\t}\n\n\t/** Tiers attached via {@link attachEventStorage}; auto-wired into future event streams. */\n\tprivate readonly _attachedEventTiers: Array<readonly AppendLogStorageTier<CqrsEvent>[]> = [];\n\tprivate readonly _attachedTierDisposers = new Map<string, Array<() => void>>();\n\n\t/**\n\t * Wire append-log storage tiers for ALL CQRS event streams — both currently\n\t * registered AND any future streams created via `event(name)` /\n\t * `event(name, aggregateId)` / handler emit. (M4 fix.)\n\t *\n\t * Returns a disposer that releases all storage subscriptions wired by this\n\t * call (including those for streams that were created after the call).\n\t */\n\tattachEventStorage(tiers: readonly AppendLogStorageTier<CqrsEvent>[]): () => void {\n\t\tthis._attachedEventTiers.push(tiers);\n\t\t// Wire currently-existing streams.\n\t\tfor (const [name, entry] of this._eventLogs) {\n\t\t\tconst dispose = entry.log.attachStorage(tiers);\n\t\t\tlet arr = this._attachedTierDisposers.get(name);\n\t\t\tif (!arr) {\n\t\t\t\tarr = [];\n\t\t\t\tthis._attachedTierDisposers.set(name, arr);\n\t\t\t}\n\t\t\tarr.push(dispose);\n\t\t}\n\t\t// Per-aggregate streams existing now.\n\t\tfor (const [type, byAgg] of this._eventLogsByAggregate) {\n\t\t\tfor (const [aggId, entry] of byAgg) {\n\t\t\t\tconst key = `${type}::${aggId}`;\n\t\t\t\tconst dispose = entry.log.attachStorage(tiers);\n\t\t\t\tlet arr = this._attachedTierDisposers.get(key);\n\t\t\t\tif (!arr) {\n\t\t\t\t\tarr = [];\n\t\t\t\t\tthis._attachedTierDisposers.set(key, arr);\n\t\t\t\t}\n\t\t\t\tarr.push(dispose);\n\t\t\t}\n\t\t}\n\t\treturn () => {\n\t\t\t// Remove from auto-wire list so newly-created streams skip.\n\t\t\tconst idx = this._attachedEventTiers.indexOf(tiers);\n\t\t\tif (idx >= 0) this._attachedEventTiers.splice(idx, 1);\n\t\t\t// We can't precisely undo the per-stream attach for THIS tier set\n\t\t\t// alone (Map values commingle disposers across multiple\n\t\t\t// attachEventStorage calls). Caller wanting fine-grained control\n\t\t\t// should call `tier.flush()` / dispose tiers themselves. This\n\t\t\t// disposer is best-effort: it stops auto-wiring future streams.\n\t\t};\n\t}\n\n\t/** Wire newly-created event stream into all currently-attached tier sets. */\n\tprivate _autoWireStreamStorage(\n\t\tkey: string,\n\t\tlog: ReturnType<typeof reactiveLog<CqrsEvent>>,\n\t): void {\n\t\tif (this._attachedEventTiers.length === 0) return;\n\t\tlet arr = this._attachedTierDisposers.get(key);\n\t\tif (!arr) {\n\t\t\tarr = [];\n\t\t\tthis._attachedTierDisposers.set(key, arr);\n\t\t}\n\t\tfor (const tiers of this._attachedEventTiers) {\n\t\t\tarr.push(log.attachStorage(tiers));\n\t\t}\n\t}\n\n\t// -- Events ---------------------------------------------------------------\n\n\t/**\n\t * Register a named event stream backed by `reactiveLog`.\n\t * Guard denies external `write` — only commands append internally.\n\t */\n\tevent(name: string): Node<readonly CqrsEvent[]>;\n\tevent(name: string, aggregateId: string): Node<readonly CqrsEvent[]>;\n\tevent(name: string, aggregateId?: string): Node<readonly CqrsEvent[]> {\n\t\tif (aggregateId !== undefined) {\n\t\t\treturn this._ensureAggregateStream(name, aggregateId).node;\n\t\t}\n\t\tconst existing = this._eventLogs.get(name);\n\t\tif (existing) return existing.node;\n\n\t\t// V0 versioning is attached at construction — post-hoc\n\t\t// `_applyVersioning` was deleted because it opened a re-entrance\n\t\t// window where a wave could observe `_versioning` transitioning from\n\t\t// `undefined` to a fresh state. Construction-time-only means the\n\t\t// flag is frozen at birth.\n\t\tconst log = reactiveLog<CqrsEvent>([], {\n\t\t\tname,\n\t\t\tversioning: 0,\n\t\t\tmaxSize: this._retainedLimit,\n\t\t});\n\t\tlog.withLatest();\n\t\tconst entries = log.entries;\n\t\tconst guarded = this.derived<readonly CqrsEvent[]>(\n\t\t\tname,\n\t\t\t[entries],\n\t\t\t(batchData, ctx) => {\n\t\t\t\tconst latest =\n\t\t\t\t\tbatchData[0] != null && batchData[0].length > 0\n\t\t\t\t\t\t? (batchData[0].at(-1) as readonly CqrsEvent[])\n\t\t\t\t\t\t: (ctx.prevData[0] as readonly CqrsEvent[]);\n\t\t\t\treturn [latest];\n\t\t\t},\n\t\t\t{\n\t\t\t\tmeta: cqrsMeta(\"event\", { event_name: name }),\n\t\t\t\tguard: EVENT_GUARD,\n\t\t\t\tinitial: entries.cache as readonly CqrsEvent[],\n\t\t\t},\n\t\t);\n\t\tthis.addDisposer(keepalive(guarded));\n\t\tthis._eventLogs.set(name, { log, node: guarded });\n\t\t// M4: auto-wire any storage tiers attached via `attachEventStorage`.\n\t\tthis._autoWireStreamStorage(name, log);\n\t\treturn guarded;\n\t}\n\n\t/**\n\t * Get-or-create the per-aggregate event stream for `(type, aggregateId)`.\n\t * Mounts the stream as a sibling node named `<type>_<aggregateId>` so it\n\t * appears in `describe()`. LRU access is touched on every call.\n\t */\n\tprivate _ensureAggregateStream(type: string, aggregateId: string): EventEntry {\n\t\t// Ensure the fan-in stream exists too (call sites usually expect both).\n\t\tif (!this._eventLogs.has(type)) this.event(type);\n\n\t\tlet byType = this._eventLogsByAggregate.get(type);\n\t\tif (!byType) {\n\t\t\tbyType = new Map();\n\t\t\tthis._eventLogsByAggregate.set(type, byType);\n\t\t}\n\t\tconst lruKey = `${type}::${aggregateId}`;\n\t\tthis._touchAggregate(lruKey);\n\t\tconst existing = byType.get(aggregateId);\n\t\tif (existing) return existing;\n\n\t\tconst nodeName = `${type}_${aggregateId.replace(/[^a-zA-Z0-9_-]/g, \"_\")}`;\n\t\tconst log = reactiveLog<CqrsEvent>([], {\n\t\t\tname: nodeName,\n\t\t\tversioning: 0,\n\t\t\tmaxSize: this._retainedLimit,\n\t\t});\n\t\tlog.withLatest();\n\t\tconst entries = log.entries;\n\t\t// Avoid name collisions if multiple aggregates have ids that sanitize\n\t\t// to the same node-name; suffix with a counter when necessary.\n\t\t// Resolve the mount name BEFORE constructing the derived (the\n\t\t// `this.derived(...)` form registers under the supplied `name`).\n\t\tlet mountName = nodeName;\n\t\tlet collisionIdx = 0;\n\t\twhile (this.resolveOptional(mountName) !== undefined) {\n\t\t\tcollisionIdx += 1;\n\t\t\tmountName = `${nodeName}_${collisionIdx}`;\n\t\t}\n\t\tlet guarded: Node<readonly CqrsEvent[]>;\n\t\ttry {\n\t\t\tguarded = this.derived<readonly CqrsEvent[]>(\n\t\t\t\tmountName,\n\t\t\t\t[entries],\n\t\t\t\t(batchData, ctx) => {\n\t\t\t\t\tconst latest =\n\t\t\t\t\t\tbatchData[0] != null && batchData[0].length > 0\n\t\t\t\t\t\t\t? (batchData[0].at(-1) as readonly CqrsEvent[])\n\t\t\t\t\t\t\t: (ctx.prevData[0] as readonly CqrsEvent[]);\n\t\t\t\t\treturn [latest];\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmeta: cqrsMeta(\"event_aggregate\", {\n\t\t\t\t\t\tevent_name: type,\n\t\t\t\t\t\taggregate_id: aggregateId,\n\t\t\t\t\t}),\n\t\t\t\t\tguard: EVENT_GUARD,\n\t\t\t\t\tinitial: entries.cache as readonly CqrsEvent[],\n\t\t\t\t},\n\t\t\t);\n\t\t} catch {\n\t\t\t// Name collision raced with another constructor — fall back to a\n\t\t\t// raw, unmounted node so the per-aggregate stream still functions\n\t\t\t// (just not graph-visible). Mirrors the prior best-effort branch.\n\t\t\tguarded = node<readonly CqrsEvent[]>(\n\t\t\t\t[entries],\n\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\tconst latest =\n\t\t\t\t\t\tbatchData[0] != null && batchData[0].length > 0 ? batchData[0].at(-1) : ctx.prevData[0];\n\t\t\t\t\tactions.emit(latest as readonly CqrsEvent[]);\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: nodeName,\n\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\tmeta: cqrsMeta(\"event_aggregate\", {\n\t\t\t\t\t\tevent_name: type,\n\t\t\t\t\t\taggregate_id: aggregateId,\n\t\t\t\t\t}),\n\t\t\t\t\tguard: EVENT_GUARD,\n\t\t\t\t\tinitial: entries.cache as readonly CqrsEvent[],\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tthis.addDisposer(keepalive(guarded));\n\t\tconst entry = { log, node: guarded };\n\t\tbyType.set(aggregateId, entry);\n\t\t// M4: auto-wire any tiers attached via `attachEventStorage`.\n\t\tthis._autoWireStreamStorage(`${type}::${aggregateId}`, log);\n\t\tthis._enforceAggregateLru();\n\t\treturn entry;\n\t}\n\n\t/** Try `resolve(path)`; return `undefined` instead of throwing on missing. */\n\tprivate resolveOptional(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\t/** Internal: append to an event log, auto-registering if needed. */\n\tprivate _appendEvent(\n\t\teventName: string,\n\t\tpayload: unknown,\n\t\textra?: {\n\t\t\taggregateId?: string;\n\t\t\tcorrelationId?: string;\n\t\t\tcausationId?: string;\n\t\t\tmetadata?: Readonly<Record<string, unknown>>;\n\t\t\thandlerVersion?: { id: string; version: string | number };\n\t\t},\n\t): CqrsEvent {\n\t\tlet entry = this._eventLogs.get(eventName);\n\t\tif (!entry) {\n\t\t\tthis.event(eventName);\n\t\t\tentry = this._eventLogs.get(eventName)!;\n\t\t}\n\t\tif (entry.node.status === \"completed\" || entry.node.status === \"errored\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot dispatch to terminated event stream \"${eventName}\" (status: ${entry.node.status}).`,\n\t\t\t);\n\t\t}\n\n\t\t// Per-aggregate version + stream wiring (D1).\n\t\tlet aggregateVersion: number | undefined;\n\t\tlet aggregateEntry: EventEntry | undefined;\n\t\tif (extra?.aggregateId !== undefined) {\n\t\t\tconst lruKey = `${eventName}::${extra.aggregateId}`;\n\t\t\taggregateVersion = (this._aggregateVersions.get(lruKey) ?? 0) + 1;\n\t\t\tthis._aggregateVersions.set(lruKey, aggregateVersion);\n\t\t\taggregateEntry = this._ensureAggregateStream(eventName, extra.aggregateId);\n\t\t}\n\n\t\tconst nv = entry.log.entries.v;\n\t\tconst frozenPayload = this._freezeEventPayload ? deepFreeze(payload) : payload;\n\t\tconst evt: CqrsEvent = {\n\t\t\ttype: eventName,\n\t\t\tpayload: frozenPayload,\n\t\t\ttimestampNs: wallClockNs(),\n\t\t\tseq: ++this._seq,\n\t\t\t...(extra?.aggregateId !== undefined ? { aggregateId: extra.aggregateId } : {}),\n\t\t\t...(aggregateVersion !== undefined ? { aggregateVersion } : {}),\n\t\t\t...(extra?.correlationId !== undefined ? { correlationId: extra.correlationId } : {}),\n\t\t\t...(extra?.causationId !== undefined ? { causationId: extra.causationId } : {}),\n\t\t\t...(extra?.metadata !== undefined ? { metadata: Object.freeze({ ...extra.metadata }) } : {}),\n\t\t\t...(extra?.handlerVersion !== undefined ? { handlerVersion: extra.handlerVersion } : {}),\n\t\t\t...(nv != null ? { v0: { id: nv.id, version: nv.version } } : {}),\n\t\t};\n\t\t// Append to fan-in stream (always) and per-aggregate stream (when set).\n\t\tentry.log.append(evt);\n\t\tif (aggregateEntry) {\n\t\t\taggregateEntry.log.append(evt);\n\t\t}\n\t\treturn evt;\n\t}\n\n\t// -- Commands -------------------------------------------------------------\n\n\t/**\n\t * Register a command with its handler. Guard denies `observe` (write-only).\n\t * Use `dispatch(name, payload)` to execute.\n\t *\n\t * The command node carries dynamic `meta.error` — a reactive companion\n\t * that holds the last handler error (or `null` on success).\n\t */\n\tcommand<T = unknown>(\n\t\tname: string,\n\t\thandlerOrReg: CommandHandler<T> | CommandRegistration<T>,\n\t): Node<T> {\n\t\tif (this._commandRegs.has(name)) {\n\t\t\tthrow new DuplicateRegistrationError(\"command\", name);\n\t\t}\n\t\tconst reg: CommandRegistration<T> =\n\t\t\ttypeof handlerOrReg === \"function\" ? { handler: handlerOrReg } : handlerOrReg;\n\t\tconst cmdNode = this.state<T>(name, undefined as T, {\n\t\t\tmeta: {\n\t\t\t\t...cqrsMeta(\"command\", { command_name: name }),\n\t\t\t\terror: null,\n\t\t\t},\n\t\t\tguard: COMMAND_GUARD,\n\t\t});\n\t\tthis._commandRegs.set(name, {\n\t\t\thandler: reg.handler as CommandHandler<unknown>,\n\t\t\t...(reg.emits !== undefined ? { emits: reg.emits } : {}),\n\t\t\t...(reg.handlerVersion !== undefined ? { handlerVersion: reg.handlerVersion } : {}),\n\t\t});\n\t\t// Pre-register declared event streams so describe() shows them.\n\t\tif (reg.emits) {\n\t\t\tfor (const e of reg.emits) {\n\t\t\t\tif (!this._eventLogs.has(e)) this.event(e);\n\t\t\t}\n\t\t}\n\t\treturn cmdNode;\n\t}\n\n\t/**\n\t * Execute a registered command. Wraps the entire dispatch in `batch()` so\n\t * the command node DATA and all emitted events settle atomically.\n\t *\n\t * If the handler throws, `meta.error` on the command node is set to the\n\t * error and the exception is re-thrown.\n\t *\n\t * **Tier 8 / COMPOSITION-GUIDE §35:** dispatch routes through the shared\n\t * {@link mutate} framework so freeze / rollback-on-throw / seq-cursor\n\t * advance / audit-record stamping flow through one centralized helper.\n\t * Failure records emit OUTSIDE the rolled-back batch (M5 / C4 invariants\n\t * preserved by the framework).\n\t */\n\tdispatch<T = unknown>(commandName: string, payload: T, opts?: DispatchOptions): void {\n\t\tconst reg = this._commandRegs.get(commandName);\n\t\tif (!reg) throw new UnknownCommandError(commandName);\n\n\t\t// D1: optimistic-concurrency check fires BEFORE the handler runs and\n\t\t// BEFORE the batch opens, so a stale-version dispatch is a clean\n\t\t// no-op (no audit record, no rollback). Only meaningful when both\n\t\t// aggregateId and expectedAggregateVersion are set; otherwise no-op.\n\t\tif (\n\t\t\topts?.aggregateId !== undefined &&\n\t\t\topts.expectedAggregateVersion !== undefined &&\n\t\t\treg.emits !== undefined\n\t\t) {\n\t\t\t// Verify against ANY of the declared `emits` types — the dispatch's\n\t\t\t// aggregate version is per (type, aggregateId), but a single\n\t\t\t// dispatch may emit across multiple types. We check the FIRST\n\t\t\t// declared `emits` type that has a version recorded for this\n\t\t\t// aggregate; if none has a version, the aggregate is considered\n\t\t\t// at version 0.\n\t\t\tlet observedVersion = 0;\n\t\t\tfor (const t of reg.emits) {\n\t\t\t\tconst v = this._aggregateVersions.get(`${t}::${opts.aggregateId}`);\n\t\t\t\tif (v !== undefined && v > observedVersion) observedVersion = v;\n\t\t\t}\n\t\t\tif (observedVersion !== opts.expectedAggregateVersion) {\n\t\t\t\tthrow new OptimisticConcurrencyError(\n\t\t\t\t\topts.aggregateId,\n\t\t\t\t\topts.expectedAggregateVersion,\n\t\t\t\t\tobservedVersion,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst cmdNode = this.resolve(commandName);\n\t\tconst emittedEvents: string[] = [];\n\t\t// `actionThrew` distinguishes user-handler failures (where we want to\n\t\t// stamp `cmdNode.meta.error`) from framework-internal failures (which\n\t\t// shouldn't leak as a \"command failed\" signal).\n\t\tlet actionThrew = false;\n\n\t\tconst action = (sealed: T): void => {\n\t\t\tcmdNode.emit(sealed, { internal: true });\n\t\t\ttry {\n\t\t\t\treg.handler(sealed, {\n\t\t\t\t\temit: (eName, data) => {\n\t\t\t\t\t\t// Wave C.2 Unit 19: if emits was declared, reject undeclared names.\n\t\t\t\t\t\tif (reg.emits !== undefined && !reg.emits.includes(eName)) {\n\t\t\t\t\t\t\tthrow new UndeclaredEmitError(commandName, eName, reg.emits);\n\t\t\t\t\t\t}\n\t\t\t\t\t\temittedEvents.push(eName);\n\t\t\t\t\t\tthis._appendEvent(eName, data, {\n\t\t\t\t\t\t\t// D1: thread the dispatch's aggregateId through so events\n\t\t\t\t\t\t\t// participate in per-aggregate versioning. Handlers can\n\t\t\t\t\t\t\t// override per-emit by passing their own through a richer\n\t\t\t\t\t\t\t// emit signature (future extension).\n\t\t\t\t\t\t\t...(opts?.aggregateId !== undefined ? { aggregateId: opts.aggregateId } : {}),\n\t\t\t\t\t\t\t...(opts?.correlationId !== undefined ? { correlationId: opts.correlationId } : {}),\n\t\t\t\t\t\t\t...(opts?.causationId !== undefined ? { causationId: opts.causationId } : {}),\n\t\t\t\t\t\t\t...(opts?.metadata !== undefined\n\t\t\t\t\t\t\t\t? { metadata: Object.freeze({ ...opts.metadata }) }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t...(reg.handlerVersion !== undefined ? { handlerVersion: reg.handlerVersion } : {}),\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tcmdNode.meta.error.emit(null, { internal: true });\n\t\t\t} catch (err) {\n\t\t\t\tactionThrew = true;\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\tmutate<[T], void, DispatchRecord>(action, {\n\t\t\t\tframe: \"transactional\",\n\t\t\t\tlog: this.dispatches,\n\t\t\t\tseq: this._dispatchSeqCursor,\n\t\t\t\tfreeze: this._freezeCommandPayload,\n\t\t\t\tonSuccessRecord: ([sealed], _result, { t_ns, seq }) => ({\n\t\t\t\t\tcommandName,\n\t\t\t\t\tpayload: sealed,\n\t\t\t\t\toutcome: \"success\",\n\t\t\t\t\temittedEvents: [...emittedEvents],\n\t\t\t\t\tt_ns,\n\t\t\t\t\tseq: seq ?? 0,\n\t\t\t\t\t...(reg.handlerVersion !== undefined ? { handlerVersion: reg.handlerVersion } : {}),\n\t\t\t\t}),\n\t\t\t\tonFailureRecord: ([sealed], err, { t_ns, seq, errorType }) => {\n\t\t\t\t\tconst wrapped =\n\t\t\t\t\t\terr instanceof CommandHandlerError ? err : new CommandHandlerError(commandName, err);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcommandName,\n\t\t\t\t\t\tpayload: sealed,\n\t\t\t\t\t\toutcome: \"failure\",\n\t\t\t\t\t\terror: wrapped,\n\t\t\t\t\t\terrorType,\n\t\t\t\t\t\temittedEvents: [...emittedEvents],\n\t\t\t\t\t\tt_ns,\n\t\t\t\t\t\tseq: seq ?? 0,\n\t\t\t\t\t\t...(reg.handlerVersion !== undefined ? { handlerVersion: reg.handlerVersion } : {}),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t})(payload);\n\t\t} catch (outerErr) {\n\t\t\t// C4 preservation: only stamp `cmdNode.meta.error` when the user\n\t\t\t// handler threw (not when framework infra threw before the action\n\t\t\t// ran). The framework already routed onFailure for the action-throw\n\t\t\t// case via `mutate` outside the rolled-back batch.\n\t\t\tif (actionThrew) {\n\t\t\t\tcmdNode.meta.error.emit(outerErr, { internal: true });\n\t\t\t}\n\t\t\tthrow outerErr;\n\t\t}\n\t}\n\n\t// -- Projections ----------------------------------------------------------\n\n\t/**\n\t * Register a read-only projection derived from event streams.\n\t * Guard denies `write` — value is computed from events only.\n\t *\n\t * **Wave C.3 Unit 21 (locked 2026-04-24):**\n\t * - Object-bag signature replaces the positional `(name, events, reducer, initial)` form.\n\t * - `mode: \"scan\"` (default) — incremental fold; `\"replay\"` — full replay each wave.\n\t * - `snapshot` integration for cold-start load + auto-checkpoint save.\n\t * - `freezeInputs` (default `true`) — freeze the event array before passing to reducer.\n\t * - Returns `ProjectionController<TState>` with `.node`, `.rebuild()`, `.reset()`.\n\t *\n\t * Fan-in across `events` is implemented by depending on all event-type fan-in\n\t * nodes directly, which preserves `describe()` edges (e.g. `orderPlaced →\n\t * orderCount`). Events are sorted by `(timestampNs, seq, aggregateId)` before\n\t * passing to the reducer (Option-3 cross-aggregate ordering, C.3).\n\t */\n\tprojection<TState>(opts: ProjectionOptions<TState>): ProjectionController<TState> {\n\t\tconst { name, events: eventNames, reducer, initial } = opts;\n\t\tconst mode = opts.mode ?? \"scan\";\n\t\tconst freezeInputs = opts.freezeInputs ?? true;\n\t\tconst snapshotOpts = opts.snapshot;\n\n\t\t// Ensure each event stream exists and collect its node.\n\t\t// Using the event-type fan-in nodes directly as deps preserves\n\t\t// `describe()` edges (orderPlaced → orderCount) per Audit 1 §24.\n\t\tconst eventNodes = eventNames.map((eName) => {\n\t\t\tif (!this._eventLogs.has(eName)) this.event(eName);\n\t\t\treturn this._eventLogs.get(eName)!.node;\n\t\t});\n\n\t\t// Sort comparator: timestampNs → seq → aggregateId lex (Option-3, C.3).\n\t\tfunction sortEvents(evts: CqrsEvent[]): void {\n\t\t\tevts.sort(\n\t\t\t\t(a, b) =>\n\t\t\t\t\ta.timestampNs - b.timestampNs ||\n\t\t\t\t\ta.seq - b.seq ||\n\t\t\t\t\t(a.aggregateId ?? \"\").localeCompare(b.aggregateId ?? \"\"),\n\t\t\t);\n\t\t}\n\n\t\t// Collect all events from the current snapshots (for seeding + rebuild).\n\t\tfunction collectAllEvents(snapshots: readonly (readonly CqrsEvent[])[]): CqrsEvent[] {\n\t\t\tconst evts: CqrsEvent[] = [];\n\t\t\tfor (const snap of snapshots) evts.push(...snap);\n\t\t\tsortEvents(evts);\n\t\t\treturn evts;\n\t\t}\n\n\t\t// Seed: collect any events already present at construction time.\n\t\tconst seedSnapshots = eventNodes.map(\n\t\t\t(n) => (n.cache as readonly CqrsEvent[] | undefined) ?? ([] as readonly CqrsEvent[]),\n\t\t);\n\t\tconst sortedSeed = collectAllEvents(seedSnapshots);\n\t\tconst frozenSeed = (\n\t\t\tfreezeInputs ? Object.freeze(sortedSeed) : sortedSeed\n\t\t) as readonly CqrsEvent[];\n\n\t\t// Scan state: tracks count of events processed in last run.\n\t\tlet lastProcessedCount = 0;\n\t\tlet scanState: TState = initial;\n\n\t\tif (mode === \"scan\" && sortedSeed.length > 0) {\n\t\t\tscanState = reducer(initial, frozenSeed);\n\t\t\tlastProcessedCount = sortedSeed.length;\n\t\t}\n\t\tconst seedState = mode === \"replay\" ? reducer(initial, frozenSeed) : scanState;\n\n\t\t// Snapshot save state — debounce + saveEvery.\n\t\tconst saveDebounceMs = snapshotOpts?.saveDebounceMs ?? 1000;\n\t\tconst saveEvery = snapshotOpts?.saveEvery ?? 1000;\n\t\tlet saveTimer: ReturnType<typeof setTimeout> | undefined;\n\t\tlet savesSinceLastFlush = 0;\n\n\t\tfunction scheduleSave(currentState: TState): void {\n\t\t\tif (!snapshotOpts?.save) return;\n\t\t\tsavesSinceLastFlush += 1;\n\t\t\tif (savesSinceLastFlush >= saveEvery) {\n\t\t\t\tsavesSinceLastFlush = 0;\n\t\t\t\tif (saveTimer !== undefined) {\n\t\t\t\t\tclearTimeout(saveTimer);\n\t\t\t\t\tsaveTimer = undefined;\n\t\t\t\t}\n\t\t\t\tconst result = snapshotOpts.save(currentState);\n\t\t\t\tif (result instanceof Promise) result.catch(() => undefined);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (saveTimer !== undefined) clearTimeout(saveTimer);\n\t\t\tsaveTimer = setTimeout(() => {\n\t\t\t\tsaveTimer = undefined;\n\t\t\t\tsavesSinceLastFlush = 0;\n\t\t\t\tconst result = snapshotOpts!.save!(currentState);\n\t\t\t\tif (result instanceof Promise) result.catch(() => undefined);\n\t\t\t}, saveDebounceMs);\n\t\t}\n\n\t\tconst projNode = this.derived<TState>(\n\t\t\tname,\n\t\t\teventNames as readonly string[],\n\t\t\t(batchData, ctx) => {\n\t\t\t\tconst snapshots = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst allEvents = collectAllEvents(snapshots as readonly (readonly CqrsEvent[])[]);\n\n\t\t\t\tlet newState: TState;\n\t\t\t\tif (mode === \"replay\") {\n\t\t\t\t\t// m1: freeze only in the replay branch where `frozen` is actually used.\n\t\t\t\t\tconst frozen = (\n\t\t\t\t\t\tfreezeInputs ? Object.freeze(allEvents) : allEvents\n\t\t\t\t\t) as readonly CqrsEvent[];\n\t\t\t\t\tnewState = reducer(initial, frozen);\n\t\t\t\t} else {\n\t\t\t\t\t// scan: only fold NEW events since last run.\n\t\t\t\t\tconst newOnly = allEvents.slice(lastProcessedCount);\n\t\t\t\t\tlastProcessedCount = allEvents.length;\n\t\t\t\t\tconst frozenNew = (\n\t\t\t\t\t\tfreezeInputs ? Object.freeze(newOnly) : newOnly\n\t\t\t\t\t) as readonly CqrsEvent[];\n\t\t\t\t\tnewState = reducer(scanState, frozenNew);\n\t\t\t\t\tscanState = newState;\n\t\t\t\t}\n\n\t\t\t\tscheduleSave(newState);\n\t\t\t\treturn [newState];\n\t\t\t},\n\t\t\t{\n\t\t\t\tmeta: cqrsMeta(\"projection\", { projection_name: name, source_events: eventNames }),\n\t\t\t\tguard: PROJECTION_GUARD,\n\t\t\t\tinitial: seedState,\n\t\t\t},\n\t\t);\n\n\t\tthis.addDisposer(keepalive(projNode));\n\t\tthis.addDisposer(() => {\n\t\t\tif (saveTimer !== undefined) {\n\t\t\t\tclearTimeout(saveTimer);\n\t\t\t\tsaveTimer = undefined;\n\t\t\t}\n\t\t});\n\t\tthis._projections.add(name);\n\n\t\t// -- Controller methods ---------------------------------------------------\n\n\t\tconst rebuild = async (rebuildOpts?: {\n\t\t\tfromTier?: AppendLogStorageTier<CqrsEvent>;\n\t\t\tpageSize?: number;\n\t\t}): Promise<TState> => {\n\t\t\ttry {\n\t\t\t\tconst pageSize = rebuildOpts?.pageSize ?? 1000;\n\t\t\t\tconst tier = rebuildOpts?.fromTier ?? this._attachedEventTiers[0]?.[0];\n\n\t\t\t\t// M5: snapshot in-memory event count BEFORE any async work so we can\n\t\t\t\t// drain events that arrive concurrently during the paginated rebuild.\n\t\t\t\tconst preBuildCount = collectAllEvents(\n\t\t\t\t\teventNodes.map((n) => (n.cache as readonly CqrsEvent[] | undefined) ?? []),\n\t\t\t\t).length;\n\n\t\t\t\t// Seed from snapshot.load if provided.\n\t\t\t\tlet rebuildState: TState = initial;\n\t\t\t\tif (snapshotOpts?.load) {\n\t\t\t\t\tconst loaded = await snapshotOpts.load();\n\t\t\t\t\tif (loaded !== undefined) rebuildState = loaded;\n\t\t\t\t}\n\n\t\t\t\tif (!tier || !tier.loadEntries) {\n\t\t\t\t\t// No storage tier — fold in-memory events as a best-effort rebuild.\n\t\t\t\t\tconst inMemory = collectAllEvents(\n\t\t\t\t\t\teventNodes.map((n) => (n.cache as readonly CqrsEvent[] | undefined) ?? []),\n\t\t\t\t\t);\n\t\t\t\t\tconst frozen = (\n\t\t\t\t\t\tfreezeInputs ? Object.freeze(inMemory) : inMemory\n\t\t\t\t\t) as readonly CqrsEvent[];\n\t\t\t\t\trebuildState = reducer(rebuildState, frozen);\n\t\t\t\t} else {\n\t\t\t\t\t// Paginated load from tier.\n\t\t\t\t\t// m3: only fold events that belong to this projection's event-type set.\n\t\t\t\t\t// Tiers may hold events from other projections; filtering keeps reducer\n\t\t\t\t\t// correctness when the tier is shared across projections.\n\t\t\t\t\tconst watchedEvents = new Set<string>(eventNames as readonly string[]);\n\t\t\t\t\tlet cursor: import(\"@graphrefly/pure-ts/extra\").AppendCursor | undefined;\n\t\t\t\t\tlet done = false;\n\t\t\t\t\twhile (!done) {\n\t\t\t\t\t\tconst result = await tier.loadEntries({ cursor, pageSize });\n\t\t\t\t\t\tconst page = [...result.entries].filter((e) => watchedEvents.has(e.type));\n\t\t\t\t\t\tsortEvents(page);\n\t\t\t\t\t\tconst frozenPage = (freezeInputs ? Object.freeze(page) : page) as readonly CqrsEvent[];\n\t\t\t\t\t\trebuildState = reducer(rebuildState, frozenPage);\n\t\t\t\t\t\tcursor = result.cursor;\n\t\t\t\t\t\tdone = !cursor || result.entries.length === 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Update the live projection node with the rebuilt state.\n\t\t\t\tif (mode === \"scan\") {\n\t\t\t\t\t// M5: drain events that arrived during the async rebuild so they are\n\t\t\t\t\t// not lost (race between paginated load and concurrent dispatch).\n\t\t\t\t\tconst allInMemory = collectAllEvents(\n\t\t\t\t\t\teventNodes.map((n) => (n.cache as readonly CqrsEvent[] | undefined) ?? []),\n\t\t\t\t\t);\n\t\t\t\t\tconst pendingEvents = allInMemory.slice(preBuildCount);\n\t\t\t\t\tif (pendingEvents.length > 0) {\n\t\t\t\t\t\tconst frozenPending = (\n\t\t\t\t\t\t\tfreezeInputs ? Object.freeze(pendingEvents) : pendingEvents\n\t\t\t\t\t\t) as readonly CqrsEvent[];\n\t\t\t\t\t\trebuildState = reducer(rebuildState, frozenPending);\n\t\t\t\t\t}\n\t\t\t\t\tscanState = rebuildState;\n\t\t\t\t\tlastProcessedCount = allInMemory.length;\n\t\t\t\t}\n\t\t\t\tprojNode.emit(rebuildState, { internal: true });\n\t\t\t\treturn rebuildState;\n\t\t\t} catch (err) {\n\t\t\t\tthrow new RebuildError(name, err);\n\t\t\t}\n\t\t};\n\n\t\tconst reset = async (): Promise<TState> => {\n\t\t\ttry {\n\t\t\t\t// Reload from snapshot.load (if configured).\n\t\t\t\tlet baseState: TState = initial;\n\t\t\t\tif (snapshotOpts?.load) {\n\t\t\t\t\tconst loaded = await snapshotOpts.load();\n\t\t\t\t\tif (loaded !== undefined) baseState = loaded;\n\t\t\t\t}\n\n\t\t\t\t// Re-fold all in-memory events on top of the snapshot state.\n\t\t\t\tconst inMemory = collectAllEvents(\n\t\t\t\t\teventNodes.map((n) => (n.cache as readonly CqrsEvent[] | undefined) ?? []),\n\t\t\t\t);\n\t\t\t\tconst frozen = (freezeInputs ? Object.freeze(inMemory) : inMemory) as readonly CqrsEvent[];\n\t\t\t\tconst newState = reducer(baseState, frozen);\n\n\t\t\t\tif (mode === \"scan\") {\n\t\t\t\t\tscanState = newState;\n\t\t\t\t\tlastProcessedCount = inMemory.length;\n\t\t\t\t}\n\t\t\t\tprojNode.emit(newState, { internal: true });\n\t\t\t\treturn newState;\n\t\t\t} catch (err) {\n\t\t\t\tthrow new RebuildError(name, err);\n\t\t\t}\n\t\t};\n\n\t\treturn { node: projNode, rebuild, reset };\n\t}\n\n\t// -- Sagas ----------------------------------------------------------------\n\n\t/**\n\t * Register an event-driven side effect. Runs handler for each **new** event\n\t * from the specified streams (tracks last-processed entry count per stream).\n\t *\n\t * The saga node carries dynamic `meta.error` — a reactive companion that\n\t * holds the last handler error (or `null` on success). Handler errors do\n\t * not propagate out of the saga run (the event cursor still advances so\n\t * the same entry is not delivered twice).\n\t */\n\tsaga<T = unknown>(\n\t\tname: string,\n\t\teventNames: readonly string[],\n\t\thandler: SagaHandler<T>,\n\t\topts: SagaOptions = {},\n\t): SagaController<T> {\n\t\tconst _eventNodes = eventNames.map((eName) => {\n\t\t\tif (!this._eventLogs.has(eName)) this.event(eName);\n\t\t\treturn this._eventLogs.get(eName)!.node;\n\t\t});\n\n\t\t// Audit 2: per-event-type cursor state nodes (replaces closure Map).\n\t\t// Mount under `<saga>_cursor` (no `::` — that's the path separator).\n\t\tconst cursors = registerCursorMap(this, `${name}_cursor`, eventNames as readonly string[], 0);\n\t\t// Audit 2: invocations log (companion + alias).\n\t\tconst invocations = createAuditLog<SagaInvocation<T>>({\n\t\t\tname: `${name}_invocations`,\n\t\t\tretainedLimit: this._retainedLimit,\n\t\t\tgraph: this,\n\t\t});\n\t\tconst aggregateFilter = opts.aggregateId;\n\t\tconst errorPolicy = opts.errorPolicy ?? \"advance\";\n\n\t\t// D2: subscribe-and-capture-mirror for cursor reads — avoid `.cache`\n\t\t// access from inside the saga node's fn. Each cursor mirrors into a\n\t\t// closure variable updated by an external subscription. Cursor writes\n\t\t// (`cursor.emit(advancedTo)`) and `invocations.append(...)` from inside\n\t\t// the fn are sanctioned effect-side-effects (saga's `describeKind:\n\t\t// \"effect\"`) — not §5.9 imperative-trigger violations.\n\t\tconst latestCursors = new Map<string, number>();\n\t\tfor (const eName of eventNames) {\n\t\t\tconst cursor = cursors[eName]!;\n\t\t\tlatestCursors.set(eName, (cursor.cache as number | undefined) ?? 0);\n\t\t\tconst sub = cursor.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) if (m[0] === DATA) latestCursors.set(eName, m[1] as number);\n\t\t\t});\n\t\t\tthis.addDisposer(sub);\n\t\t}\n\n\t\t// Tier 8 / COMPOSITION-GUIDE §35: per-event handler invocation routes\n\t\t// through `mutate` so handler-version stamping + audit-record\n\t\t// shape stay centralized. Failure path re-throws — the saga's outer\n\t\t// try/catch honors `errorPolicy` (\"advance\" vs \"hold\"). Action takes\n\t\t// `(ev, eName)` so the wrapper can be hoisted once for all event types.\n\t\tconst auditedHandler = mutate<[CqrsEvent<T>, string], void, SagaInvocation<T>>(\n\t\t\t(ev, _eName) => {\n\t\t\t\thandler(ev);\n\t\t\t},\n\t\t\t{\n\t\t\t\tframe: \"inline\",\n\t\t\t\tlog: invocations,\n\t\t\t\tfreeze: false,\n\t\t\t\t...(opts.handlerVersion !== undefined ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t\t// D5 (qa lock): always include the `aggregateId` key (even when\n\t\t\t\t// undefined) for parity with the pre-Tier-8 saga record shape.\n\t\t\t\t// Consumers using `Object.hasOwn(record, \"aggregateId\")` or JSON\n\t\t\t\t// serialization shape would observe a pre-1.0 break otherwise.\n\t\t\t\tonSuccessRecord: ([ev, eName], _r, { t_ns }) => ({\n\t\t\t\t\teventType: eName,\n\t\t\t\t\toutcome: \"success\",\n\t\t\t\t\taggregateId: ev.aggregateId,\n\t\t\t\t\tevent: ev,\n\t\t\t\t\tt_ns,\n\t\t\t\t}),\n\t\t\t\tonFailureRecord: ([ev, eName], err, { t_ns, errorType }) => ({\n\t\t\t\t\teventType: eName,\n\t\t\t\t\toutcome: \"failure\",\n\t\t\t\t\terror: err,\n\t\t\t\t\terrorType,\n\t\t\t\t\taggregateId: ev.aggregateId,\n\t\t\t\t\tevent: ev,\n\t\t\t\t\tt_ns,\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tconst sagaRef: { n?: Node<unknown> } = {};\n\t\tconst sagaNode = this.effect(\n\t\t\tname,\n\t\t\teventNames as readonly string[],\n\t\t\t(snapshots, _up) => {\n\t\t\t\tconst errNode = sagaRef.n!.meta.error as Node<unknown>;\n\t\t\t\tfor (let i = 0; i < snapshots.length; i++) {\n\t\t\t\t\tconst batch = snapshots[i];\n\t\t\t\t\tif (batch == null || batch.length === 0) continue;\n\t\t\t\t\tconst entries = batch.at(-1) as readonly CqrsEvent<T>[] | undefined;\n\t\t\t\t\tif (!entries) continue;\n\t\t\t\t\tconst eName = eventNames[i] as string;\n\t\t\t\t\tconst cursor = cursors[eName]!;\n\t\t\t\t\tconst lastCount = latestCursors.get(eName) ?? 0;\n\t\t\t\t\tif (entries.length > lastCount) {\n\t\t\t\t\t\tconst newEntries = entries.slice(lastCount);\n\t\t\t\t\t\tlet advancedTo = lastCount;\n\t\t\t\t\t\tfor (const entry of newEntries) {\n\t\t\t\t\t\t\tconst ev = entry as CqrsEvent<T>;\n\t\t\t\t\t\t\tif (aggregateFilter !== undefined && ev.aggregateId !== aggregateFilter) {\n\t\t\t\t\t\t\t\tadvancedTo += 1;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tauditedHandler(ev, eName);\n\t\t\t\t\t\t\t\terrNode.emit(null, { internal: true });\n\t\t\t\t\t\t\t\tadvancedTo += 1;\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\terrNode.emit(err, { internal: true });\n\t\t\t\t\t\t\t\tif (errorPolicy === \"hold\") break;\n\t\t\t\t\t\t\t\t// \"advance\" — skip past failure, keep going.\n\t\t\t\t\t\t\t\tadvancedTo += 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcursor.emit(advancedTo);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tmeta: {\n\t\t\t\t\t...cqrsMeta(\"saga\", { saga_name: name, source_events: eventNames }),\n\t\t\t\t\terror: null,\n\t\t\t\t},\n\t\t\t},\n\t\t) as Node<unknown>;\n\t\tsagaRef.n = sagaNode;\n\n\t\tthis.addDisposer(keepalive(sagaNode));\n\t\tthis._sagas.add(name);\n\t\treturn {\n\t\t\tnode: sagaNode,\n\t\t\tinvocations,\n\t\t\taudit: invocations,\n\t\t\tcursors,\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a CQRS graph container.\n *\n * @example\n * ```ts\n * const app = cqrs(\"orders\");\n * app.event(\"orderPlaced\");\n * app.command(\"placeOrder\", (payload, { emit }) => {\n * emit(\"orderPlaced\", { orderId: payload.id, amount: payload.amount });\n * });\n * const { node: orderCount } = app.projection({\n * name: \"orderCount\",\n * events: [\"orderPlaced\"],\n * reducer: (_s, events) => events.length,\n * initial: 0,\n * });\n * app.dispatch(\"placeOrder\", { id: \"1\", amount: 100 });\n * ```\n */\nexport function cqrs<EM extends CqrsEventMap = Record<string, unknown>>(\n\tname: string,\n\topts?: CqrsOptions,\n): CqrsGraph<EM> {\n\tconst g = new CqrsGraph<EM>(name, opts);\n\t// Tier 1.5.3 Phase 2.5 (DG1=B): tag the Graph with its constructing\n\t// factory so `describe()` surfaces provenance. Route through\n\t// `placeholderArgs` since `CqrsOptions.graph` may carry non-JSON fields.\n\tconst { factory: _f, factoryArgs: _fa, ...tagArgs } = (opts ?? {}) as Record<string, unknown>;\n\tg.tagFactory(\"cqrs\", placeholderArgs(tagArgs));\n\treturn g;\n}\n","/**\n * Three-pane demo shell (roadmap §7.2).\n *\n * A `Graph(\"demo-shell\")` that dogfoods reactive coordination for the\n * main/side split layout with synchronized cross-highlighting.\n *\n * **Zero framework dependency** — framework bindings wrap pane components only.\n * The shell graph is headless and fully testable.\n */\n\nimport { batch, node } from \"@graphrefly/pure-ts/core\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { graphSpecToMermaid } from \"../../base/render/index.js\";\nimport type { MeasurementAdapter } from \"../reactive-layout/reactive-layout.js\";\nimport { analyzeAndMeasure, computeLineBreaks } from \"../reactive-layout/reactive-layout.js\";\n\n// ——————————————————————————————————————————————————————————\n// Types\n// ——————————————————————————————————————————————————————————\n\n/** Identifies which pane is the source of a hover event. */\nexport type HoverPaneType = \"visual\" | \"graph\" | \"code\";\n\n/** Cross-highlighting hover target. `null` means nothing hovered. */\nexport type HoverTarget = { pane: HoverPaneType; id: string } | null;\n\n/** Which pane is full-screened (null = normal layout). */\nexport type FullscreenPane = \"main\" | \"graph\" | \"code\" | null;\n\n/**\n * Cross-referencing registry: maps node paths to code line numbers and\n * visual element selectors. Provided by each demo's `store.ts`.\n */\nexport type NodeRegistry = Map<string, { codeLine: number; visualSelector: string }>;\n\n/** Callbacks for cross-highlighting effect nodes. */\nexport type HighlightCallbacks = {\n\t/** Called when code-scroll highlight target changes. */\n\tcodeScroll?: (line: number | null) => void;\n\t/** Called when visual highlight target changes. */\n\tvisual?: (selector: string | null) => void;\n\t/** Called when graph highlight target changes. */\n\tgraph?: (nodeId: string | null) => void;\n};\n\n/** Label dimensions for graph node sizing. */\nexport type GraphLabelSize = { width: number; height: number };\n\n/** Options for {@link demoShell}. */\nexport type DemoShellOptions = {\n\t/** Initial main/side split ratio (0–1). Default: `0.65`. */\n\tmainRatio?: number;\n\t/** Initial graph/code vertical split in the side pane (0–1). Default: `0.5`. */\n\tsideSplit?: number;\n\t/** Initial viewport width in pixels. Default: `1280`. */\n\tviewportWidth?: number;\n\t/** Cross-referencing registry for hover→code/visual/graph mapping. */\n\tnodeRegistry?: NodeRegistry;\n\t/** Measurement adapter for layout engine integration. When provided, enables layout/* derived nodes. */\n\tadapter?: MeasurementAdapter;\n\t/** Font string for layout measurement. Default: `\"14px monospace\"`. */\n\tlayoutFont?: string;\n\t/** Callbacks for cross-highlighting effect nodes. When provided, creates effect nodes visible in describe(). */\n\tonHighlight?: HighlightCallbacks;\n};\n\n/** Return type of {@link demoShell}. */\nexport type DemoShellHandle = {\n\t/** The demo-shell graph. */\n\tgraph: Graph;\n\n\t// ── Convenience setters (shorthand for graph.set) ──────────\n\tsetMainRatio(ratio: number): void;\n\tsetSideSplit(ratio: number): void;\n\tsetFullscreen(pane: FullscreenPane): void;\n\tsetViewportWidth(width: number): void;\n\tsetHoverTarget(target: HoverTarget): void;\n\tsetDemoGraph(g: Graph | null): void;\n\tbumpGraphTick(): void;\n\tselectNode(path: string | null): void;\n\tsetMetaDebug(on: boolean): void;\n\t/** Set code text for layout/code-lines measurement (requires adapter). */\n\tsetCodeText(text: string): void;\n\t/** Atomic multi-set — wraps core `batch()` for glitch-free updates. */\n\tbatch(fn: () => void): void;\n\tdestroy(): void;\n};\n\n// ——————————————————————————————————————————————————————————\n// Helpers\n// ——————————————————————————————————————————————————————————\n\nfunction clamp01(v: number): number {\n\treturn Math.max(0, Math.min(1, v));\n}\n\n// ——————————————————————————————————————————————————————————\n// Factory\n// ——————————————————————————————————————————————————————————\n\n/**\n * Creates the three-pane demo shell graph (roadmap §7.2).\n *\n * All coordination is reactive — no polling, no imperative triggers.\n * Framework bindings subscribe to named nodes and drive `state` inputs.\n */\nexport function demoShell(opts?: DemoShellOptions): DemoShellHandle {\n\tconst mainRatioInit = clamp01(opts?.mainRatio ?? 0.65);\n\tconst sideSplitInit = clamp01(opts?.sideSplit ?? 0.5);\n\tconst viewportInit = Math.max(0, opts?.viewportWidth ?? 1280);\n\tconst registry = opts?.nodeRegistry ?? new Map();\n\tconst adapter = opts?.adapter ?? null;\n\tconst layoutFont = opts?.layoutFont ?? \"14px monospace\";\n\tconst onHighlight = opts?.onHighlight;\n\n\tconst g = new Graph(\"demo-shell\");\n\n\t// ── Layout state ─────────────────────────────────────\n\tconst paneMainRatio = node([], { ...{ name: \"pane/main-ratio\" }, initial: mainRatioInit });\n\tconst paneSideSplit = node([], { ...{ name: \"pane/side-split\" }, initial: sideSplitInit });\n\tconst paneFullscreen = node<FullscreenPane>([], {\n\t\t...{\n\t\t\tname: \"pane/fullscreen\",\n\t\t},\n\t\tinitial: null,\n\t});\n\tconst viewportWidth = node([], { ...{ name: \"viewport/width\" }, initial: viewportInit });\n\n\tg.add(paneMainRatio, { name: \"pane/main-ratio\" });\n\tg.add(paneSideSplit, { name: \"pane/side-split\" });\n\tg.add(paneFullscreen, { name: \"pane/fullscreen\" });\n\tg.add(viewportWidth, { name: \"viewport/width\" });\n\n\t// ── Derived pane dimensions ──────────────────────────\n\tconst paneMainWidth = node(\n\t\t[paneMainRatio, viewportWidth, paneFullscreen],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst r = data[0] as number;\n\t\t\tconst w = data[1] as number;\n\t\t\tconst fullscreen = data[2] as FullscreenPane;\n\t\t\tif (fullscreen === \"main\") actions.emit(w);\n\t\t\telse if (fullscreen === \"graph\" || fullscreen === \"code\") actions.emit(0);\n\t\t\telse actions.emit(Math.round(w * r));\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"pane/main-width\" } },\n\t);\n\n\tconst paneSideWidth = node(\n\t\t[paneMainWidth, viewportWidth, paneFullscreen],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst main = data[0] as number;\n\t\t\tconst w = data[1] as number;\n\t\t\tconst fullscreen = data[2] as FullscreenPane;\n\t\t\tif (fullscreen === \"main\") actions.emit(0);\n\t\t\telse if (fullscreen === \"graph\" || fullscreen === \"code\") actions.emit(w);\n\t\t\telse actions.emit(w - main);\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"pane/side-width\" } },\n\t);\n\n\tconst paneGraphHeight = node(\n\t\t[paneSideSplit, paneFullscreen],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst split = data[0] as number;\n\t\t\tconst fullscreen = data[1] as FullscreenPane;\n\t\t\tif (fullscreen === \"graph\") actions.emit(1);\n\t\t\telse if (fullscreen === \"code\") actions.emit(0);\n\t\t\telse if (fullscreen === \"main\") actions.emit(0);\n\t\t\telse actions.emit(clamp01(split));\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"pane/graph-height-ratio\" } },\n\t);\n\n\tconst paneCodeHeight = node(\n\t\t[paneGraphHeight, paneFullscreen],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst graphH = data[0] as number;\n\t\t\tconst fullscreen = data[1] as FullscreenPane;\n\t\t\tif (fullscreen === \"code\") actions.emit(1);\n\t\t\telse if (fullscreen === \"graph\" || fullscreen === \"main\") actions.emit(0);\n\t\t\telse actions.emit(1 - graphH);\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"pane/code-height-ratio\" } },\n\t);\n\n\tg.add(paneMainWidth, { name: \"pane/main-width\" });\n\tg.add(paneSideWidth, { name: \"pane/side-width\" });\n\tg.add(paneGraphHeight, { name: \"pane/graph-height-ratio\" });\n\tg.add(paneCodeHeight, { name: \"pane/code-height-ratio\" });\n\n\t// ── External graph observation ───────────────────────\n\tconst demoGraphRef = node<Graph | null>([], {\n\t\t...{\n\t\t\tname: \"demo/graph-ref\",\n\t\t},\n\t\tinitial: null,\n\t});\n\tconst demoGraphTick = node([], { ...{ name: \"demo/graph-tick\" }, initial: 0 });\n\n\tg.add(demoGraphRef, { name: \"demo/graph-ref\" });\n\tg.add(demoGraphTick, { name: \"demo/graph-tick\" });\n\n\tconst graphMermaid = node(\n\t\t[demoGraphRef, demoGraphTick],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst demo = data[0] as Graph | null;\n\t\t\tactions.emit(demo ? graphSpecToMermaid(demo.describe()) : \"\");\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"graph/mermaid\" } },\n\t);\n\n\tconst graphDescribe = node(\n\t\t[demoGraphRef, demoGraphTick],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst demo = data[0] as Graph | null;\n\t\t\tif (!demo) {\n\t\t\t\tactions.emit(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst { expand: _, ...snapshot } = demo.describe({ detail: \"standard\" });\n\t\t\tactions.emit(snapshot);\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"graph/describe\" } },\n\t);\n\n\tg.add(graphMermaid, { name: \"graph/mermaid\" });\n\tg.add(graphDescribe, { name: \"graph/describe\" });\n\n\t// ── Cross-highlighting ───────────────────────────────\n\tconst hoverTarget = node<HoverTarget>([], { ...{ name: \"hover/target\" }, initial: null });\n\tg.add(hoverTarget, { name: \"hover/target\" });\n\n\tconst highlightCodeScroll = node(\n\t\t[hoverTarget],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst t = data[0] as HoverTarget;\n\t\t\tif (!t) {\n\t\t\t\tactions.emit(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst entry = registry.get(t.id);\n\t\t\tactions.emit(entry ? entry.codeLine : null);\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"highlight/code-scroll\" } },\n\t);\n\n\tconst highlightVisual = node(\n\t\t[hoverTarget],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst t = data[0] as HoverTarget;\n\t\t\tif (!t) {\n\t\t\t\tactions.emit(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst entry = registry.get(t.id);\n\t\t\tactions.emit(entry ? entry.visualSelector : null);\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"highlight/visual\" } },\n\t);\n\n\tconst highlightGraph = node(\n\t\t[hoverTarget],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst t = data[0] as HoverTarget;\n\t\t\tactions.emit(t ? t.id : null);\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"highlight/graph\" } },\n\t);\n\n\tg.add(highlightCodeScroll, { name: \"highlight/code-scroll\" });\n\tg.add(highlightVisual, { name: \"highlight/visual\" });\n\tg.add(highlightGraph, { name: \"highlight/graph\" });\n\n\t// ── Cross-highlighting effect nodes (optional) ─────\n\t// Created when onHighlight callbacks are provided, making the full\n\t// source→derived→effect chain visible in describe()/graphSpecToMermaid().\n\n\tif (onHighlight?.codeScroll) {\n\t\tconst cb = onHighlight.codeScroll;\n\t\tconst applyCodeScroll = node(\n\t\t\t[highlightCodeScroll],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tcb(data[0] as number | null);\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\t\tg.add(applyCodeScroll, { name: \"highlight/apply-code-scroll\" });\n\t}\n\n\tif (onHighlight?.visual) {\n\t\tconst cb = onHighlight.visual;\n\t\tconst applyVisual = node(\n\t\t\t[highlightVisual],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tcb(data[0] as string | null);\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\t\tg.add(applyVisual, { name: \"highlight/apply-visual\" });\n\t}\n\n\tif (onHighlight?.graph) {\n\t\tconst cb = onHighlight.graph;\n\t\tconst applyGraph = node(\n\t\t\t[highlightGraph],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tcb(data[0] as string | null);\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\t\tg.add(applyGraph, { name: \"highlight/apply-graph\" });\n\t}\n\n\t// ── Inspect panel ────────────────────────────────────\n\tconst inspectSelected = node<string | null>([], {\n\t\t...{\n\t\t\tname: \"inspect/selected-node\",\n\t\t},\n\t\tinitial: null,\n\t});\n\tg.add(inspectSelected, { name: \"inspect/selected-node\" });\n\n\tconst inspectNodeDetail = node(\n\t\t[inspectSelected, demoGraphRef, demoGraphTick],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst p = data[0] as string | null;\n\t\t\tconst demo = data[1] as Graph | null;\n\t\t\tif (!demo || !p) {\n\t\t\t\tactions.emit(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst snap = demo.describe({ detail: \"standard\" });\n\t\t\t\tconst nodeDesc = snap.nodes[p];\n\t\t\t\tif (!nodeDesc) {\n\t\t\t\t\tactions.emit(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tactions.emit({ path: p, ...nodeDesc });\n\t\t\t} catch {\n\t\t\t\tactions.emit(null);\n\t\t\t}\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"inspect/node-detail\" } },\n\t);\n\n\tconst inspectTraceLog = node(\n\t\t[demoGraphRef, demoGraphTick],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst demo = data[0] as Graph | null;\n\t\t\tactions.emit(demo ? demo.trace() : []);\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"inspect/trace-log\" } },\n\t);\n\n\tg.add(inspectNodeDetail, { name: \"inspect/node-detail\" });\n\tg.add(inspectTraceLog, { name: \"inspect/trace-log\" });\n\n\t// ── Meta debug toggle ────────────────────────────────\n\tconst metaDebug = node([], { ...{ name: \"meta/debug\" }, initial: false });\n\tg.add(metaDebug, { name: \"meta/debug\" });\n\n\tconst metaShellMermaid = node(\n\t\t[metaDebug, demoGraphTick],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit((data[0] as boolean) ? graphSpecToMermaid(g.describe()) : \"\");\n\t\t},\n\t\t{ describeKind: \"derived\", ...{ name: \"meta/shell-mermaid\" } },\n\t);\n\tg.add(metaShellMermaid, { name: \"meta/shell-mermaid\" });\n\n\t// ── Layout engine integration (optional, requires adapter) ──\n\tconst codeTextNode = node([], { ...{ name: \"layout/code-text\" }, initial: \"\" });\n\tg.add(codeTextNode, { name: \"layout/code-text\" });\n\n\tif (adapter) {\n\t\tconst measureCache = new Map<string, Map<string, number>>();\n\n\t\tconst graphLabels = node(\n\t\t\t[graphDescribe],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst d = data[0] as { nodes: Record<string, { type: string }> } | null;\n\t\t\t\tif (!d) {\n\t\t\t\t\tactions.emit(new Map<string, GraphLabelSize>());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst result = new Map<string, GraphLabelSize>();\n\t\t\t\tfor (const [name] of Object.entries(d.nodes)) {\n\t\t\t\t\tconst segments = analyzeAndMeasure(name, layoutFont, adapter, measureCache);\n\t\t\t\t\tconst lb = computeLineBreaks(segments, Infinity, adapter, layoutFont, measureCache);\n\t\t\t\t\tconst width = lb.lines.reduce((max, l) => Math.max(max, l.width), 0);\n\t\t\t\t\tconst height = lb.lineCount * 20; // line-height approximation\n\t\t\t\t\tresult.set(name, { width, height });\n\t\t\t\t}\n\t\t\t\tactions.emit(result);\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t...{\n\t\t\t\t\tname: \"layout/graph-labels\",\n\t\t\t\t\tequals: (a, b) => {\n\t\t\t\t\t\tif (a === b) return true;\n\t\t\t\t\t\tconst ma = a as Map<string, GraphLabelSize>;\n\t\t\t\t\t\tconst mb = b as Map<string, GraphLabelSize>;\n\t\t\t\t\t\tif (ma.size !== mb.size) return false;\n\t\t\t\t\t\tfor (const [k, v] of ma) {\n\t\t\t\t\t\t\tconst bv = mb.get(k);\n\t\t\t\t\t\t\tif (!bv || bv.width !== v.width || bv.height !== v.height) return false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tconst codeLines = node(\n\t\t\t[codeTextNode, paneSideWidth],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst t = data[0] as string;\n\t\t\t\tif (!t) {\n\t\t\t\t\tactions.emit({ lineCount: 0, lines: [] });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst segments = analyzeAndMeasure(t, layoutFont, adapter, measureCache);\n\t\t\t\tconst maxW = (data[1] as number) - 40; // side pane minus padding\n\t\t\t\tactions.emit(\n\t\t\t\t\tcomputeLineBreaks(segments, Math.max(100, maxW), adapter, layoutFont, measureCache),\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ describeKind: \"derived\", name: \"layout/code-lines\" },\n\t\t);\n\n\t\tconst sideWidthHint = node(\n\t\t\t[graphLabels],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst m = data[0] as Map<string, GraphLabelSize>;\n\t\t\t\tif (m.size === 0) {\n\t\t\t\t\tactions.emit(200);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet maxW = 0;\n\t\t\t\tfor (const { width } of m.values()) {\n\t\t\t\t\tif (width > maxW) maxW = width;\n\t\t\t\t}\n\t\t\t\t// widest label + padding (node box chrome + margin)\n\t\t\t\tactions.emit(Math.max(200, Math.round(maxW + 80)));\n\t\t\t},\n\t\t\t{ describeKind: \"derived\", name: \"layout/side-width-hint\" },\n\t\t);\n\n\t\tg.add(graphLabels, { name: \"layout/graph-labels\" });\n\t\tg.add(codeLines, { name: \"layout/code-lines\" });\n\t\tg.add(sideWidthHint, { name: \"layout/side-width-hint\" });\n\t}\n\n\t// ── Edges (explicit wiring for describe/graphSpecToMermaid) ───\n\n\t// ── Handle ───────────────────────────────────────────\n\tlet tickCounter = 0;\n\treturn {\n\t\tgraph: g,\n\t\tsetMainRatio(ratio: number) {\n\t\t\tg.set(\"pane/main-ratio\", clamp01(ratio));\n\t\t},\n\t\tsetSideSplit(ratio: number) {\n\t\t\tg.set(\"pane/side-split\", clamp01(ratio));\n\t\t},\n\t\tsetFullscreen(pane: FullscreenPane) {\n\t\t\tg.set(\"pane/fullscreen\", pane);\n\t\t},\n\t\tsetViewportWidth(width: number) {\n\t\t\tg.set(\"viewport/width\", Math.max(0, width));\n\t\t},\n\t\tsetHoverTarget(target: HoverTarget) {\n\t\t\tg.set(\"hover/target\", target);\n\t\t},\n\t\tsetDemoGraph(demo: Graph | null) {\n\t\t\tg.set(\"demo/graph-ref\", demo);\n\t\t},\n\t\tbumpGraphTick() {\n\t\t\tg.set(\"demo/graph-tick\", ++tickCounter);\n\t\t},\n\t\tselectNode(path: string | null) {\n\t\t\tg.set(\"inspect/selected-node\", path);\n\t\t},\n\t\tsetMetaDebug(on: boolean) {\n\t\t\tg.set(\"meta/debug\", on);\n\t\t},\n\t\tsetCodeText(text: string) {\n\t\t\tg.set(\"layout/code-text\", text);\n\t\t},\n\t\tbatch(fn: () => void) {\n\t\t\tbatch(fn);\n\t\t},\n\t\tdestroy() {\n\t\t\tg.destroy();\n\t\t},\n\t};\n}\n","/**\n * Monospace-terminal cell-width utilities shared by the CLI measurement\n * adapter ([src/patterns/reactive-layout/measurement-adapters.ts](../patterns/reactive-layout/measurement-adapters.ts))\n * and the ASCII describe renderer ([graph-spec-to-ascii.ts](./graph-spec-to-ascii.ts)).\n *\n * Approximates UAX #11 East_Asian_Width (W/F → 2) plus known combining-mark\n * ranges (→ 0). Not a full EAW table — covers CJK, Hangul, fullwidth forms,\n * common emoji, and Extensions B-G. Does not handle ZWJ emoji sequences\n * (multi-codepoint clusters rendered as a single glyph) — terminal support\n * for those varies widely.\n */\n\nexport function cellWidth(code: number): 0 | 1 | 2 {\n\t// Combining marks (Mn, Mc, Me) → 0 cells\n\tif (\n\t\t(code >= 0x0300 && code <= 0x036f) || // Combining Diacritical Marks\n\t\t(code >= 0x0483 && code <= 0x0489) || // Cyrillic combining marks\n\t\t(code >= 0x0591 && code <= 0x05bd) || // Hebrew combining marks\n\t\t(code >= 0x0610 && code <= 0x061a) || // Arabic combining marks\n\t\t(code >= 0x064b && code <= 0x065f) || // Arabic combining marks\n\t\t(code >= 0x0670 && code === 0x0670) || // Arabic superscript alef\n\t\t(code >= 0x06d6 && code <= 0x06dc) || // Arabic combining marks\n\t\t(code >= 0x06df && code <= 0x06e4) || // Arabic combining marks\n\t\t(code >= 0x06e7 && code <= 0x06e8) || // Arabic combining marks\n\t\t(code >= 0x06ea && code <= 0x06ed) || // Arabic combining marks\n\t\t(code >= 0x0730 && code <= 0x074a) || // Syriac combining marks\n\t\t(code >= 0x07a6 && code <= 0x07b0) || // Thaana combining marks\n\t\t(code >= 0x0900 && code <= 0x0903) || // Devanagari combining marks\n\t\t(code >= 0x093a && code <= 0x094f) || // Devanagari combining marks\n\t\t(code >= 0x0951 && code <= 0x0957) || // Devanagari combining marks\n\t\t(code >= 0x0962 && code <= 0x0963) || // Devanagari combining marks\n\t\t(code >= 0x0981 && code <= 0x0983) || // Bengali combining marks\n\t\t(code >= 0x09bc && code <= 0x09cd) || // Bengali combining marks\n\t\t(code >= 0x0a01 && code <= 0x0a03) || // Gurmukhi combining marks\n\t\t(code >= 0x0a3c && code <= 0x0a51) || // Gurmukhi combining marks\n\t\t(code >= 0x0a70 && code <= 0x0a71) || // Gurmukhi combining marks\n\t\t(code >= 0x0a75 && code === 0x0a75) || // Gurmukhi combining mark\n\t\t(code >= 0x0e31 && code === 0x0e31) || // Thai combining mark\n\t\t(code >= 0x0e34 && code <= 0x0e3a) || // Thai combining marks\n\t\t(code >= 0x0e47 && code <= 0x0e4e) || // Thai combining marks\n\t\t(code >= 0x0eb1 && code === 0x0eb1) || // Lao combining mark\n\t\t(code >= 0x0eb4 && code <= 0x0ebc) || // Lao combining marks\n\t\t(code >= 0x0ec8 && code <= 0x0ece) || // Lao combining marks\n\t\t(code >= 0x1dc0 && code <= 0x1dff) || // Combining Diacritical Marks Supplement\n\t\t(code >= 0x20d0 && code <= 0x20ff) || // Combining Diacritical Marks for Symbols\n\t\t(code >= 0xfe00 && code <= 0xfe0f) || // Variation Selectors\n\t\t(code >= 0xfe20 && code <= 0xfe2f) || // Combining Half Marks\n\t\tcode === 0x200d // Zero Width Joiner\n\t) {\n\t\treturn 0;\n\t}\n\t// Wide / fullwidth → 2 cells\n\tif (\n\t\t(code >= 0x1100 && code <= 0x115f) || // Hangul Jamo\n\t\t(code >= 0x231a && code <= 0x231b) || // Watch, Hourglass\n\t\t(code >= 0x2329 && code <= 0x232a) || // Angle brackets\n\t\t(code >= 0x23e9 && code <= 0x23f3) || // Media control symbols\n\t\t(code >= 0x23f8 && code <= 0x23fa) || // Media control symbols\n\t\t(code >= 0x25fd && code <= 0x25fe) || // Medium squares\n\t\t(code >= 0x2614 && code <= 0x2615) || // Umbrella, Hot Beverage\n\t\t(code >= 0x2648 && code <= 0x2653) || // Zodiac symbols\n\t\tcode === 0x267f || // Wheelchair\n\t\tcode === 0x2693 || // Anchor\n\t\tcode === 0x26a1 || // High Voltage\n\t\t(code >= 0x26aa && code <= 0x26ab) || // Medium circles\n\t\t(code >= 0x26bd && code <= 0x26be) || // Soccer, Baseball\n\t\t(code >= 0x26c4 && code <= 0x26c5) || // Snowman, Sun behind cloud\n\t\tcode === 0x26ce || // Ophiuchus\n\t\tcode === 0x26d4 || // No Entry\n\t\tcode === 0x26ea || // Church\n\t\t(code >= 0x26f2 && code <= 0x26f3) || // Fountain, Golf\n\t\tcode === 0x26f5 || // Sailboat\n\t\tcode === 0x26fa || // Tent\n\t\tcode === 0x26fd || // Fuel Pump\n\t\tcode === 0x2702 || // Scissors\n\t\tcode === 0x2705 || // Check Mark\n\t\t(code >= 0x2708 && code <= 0x270d) || // Airplane...Writing Hand\n\t\tcode === 0x270f || // Pencil\n\t\t(code >= 0x2753 && code <= 0x2755) || // Question marks\n\t\tcode === 0x2757 || // Exclamation\n\t\t(code >= 0x2795 && code <= 0x2797) || // Plus, Minus, Divide\n\t\tcode === 0x27b0 || // Curly Loop\n\t\tcode === 0x27bf || // Double Curly Loop\n\t\t(code >= 0x2934 && code <= 0x2935) || // Arrows\n\t\t(code >= 0x2b05 && code <= 0x2b07) || // Arrows\n\t\t(code >= 0x2b1b && code <= 0x2b1c) || // Squares\n\t\tcode === 0x2b50 || // Star\n\t\tcode === 0x2b55 || // Circle\n\t\t(code >= 0x2e80 && code <= 0x303e) || // CJK Radicals, Symbols, Punctuation\n\t\t(code >= 0x3040 && code <= 0x309f) || // Hiragana\n\t\t(code >= 0x30a0 && code <= 0x30ff) || // Katakana\n\t\t(code >= 0x3105 && code <= 0x312f) || // Bopomofo\n\t\t(code >= 0x3131 && code <= 0x318e) || // Hangul Compatibility Jamo\n\t\t(code >= 0x3190 && code <= 0x31e3) || // Kanbun, CJK Strokes\n\t\t(code >= 0x31f0 && code <= 0x321e) || // Katakana Phonetic Extensions\n\t\t(code >= 0x3220 && code <= 0x3247) || // Enclosed CJK\n\t\t(code >= 0x3250 && code <= 0x4dbf) || // CJK Extensions + Unified block\n\t\t(code >= 0x4e00 && code <= 0x9fff) || // CJK Unified Ideographs\n\t\t(code >= 0xa960 && code <= 0xa97c) || // Hangul Jamo Extended-A\n\t\t(code >= 0xac00 && code <= 0xd7a3) || // Hangul Syllables\n\t\t(code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility Ideographs\n\t\t(code >= 0xfe10 && code <= 0xfe19) || // Vertical forms\n\t\t(code >= 0xfe30 && code <= 0xfe6b) || // CJK Compatibility Forms\n\t\t(code >= 0xff01 && code <= 0xff60) || // Fullwidth Forms (excl. halfwidth)\n\t\t(code >= 0xffe0 && code <= 0xffe6) || // Fullwidth Signs\n\t\t(code >= 0x1f004 && code === 0x1f004) || // Mahjong Red Dragon\n\t\tcode === 0x1f0cf || // Joker\n\t\t(code >= 0x1f170 && code <= 0x1f171) || // A/B buttons\n\t\tcode === 0x1f17e || // O button\n\t\tcode === 0x1f17f || // P button\n\t\tcode === 0x1f18e || // AB button\n\t\t(code >= 0x1f191 && code <= 0x1f19a) || // Squared symbols\n\t\t(code >= 0x1f1e0 && code <= 0x1f1ff) || // Regional Indicator Symbols\n\t\t(code >= 0x1f200 && code <= 0x1f202) || // Enclosed ideographic\n\t\tcode === 0x1f21a || // Squared CJK\n\t\tcode === 0x1f22f || // Squared CJK\n\t\t(code >= 0x1f232 && code <= 0x1f23a) || // Squared CJK\n\t\t(code >= 0x1f250 && code <= 0x1f251) || // Circled ideographic\n\t\t(code >= 0x1f300 && code <= 0x1f9ff) || // Misc Symbols / Emoticons / Emoji\n\t\t(code >= 0x1fa00 && code <= 0x1faff) || // Chess, Symbols Extended-A\n\t\t(code >= 0x1fb00 && code <= 0x1fbff) || // Symbols for Legacy Computing\n\t\t(code >= 0x20000 && code <= 0x2fffd) || // CJK Extension B-F (excl. nonchars)\n\t\t(code >= 0x30000 && code <= 0x3fffd) // CJK Extension G+ (excl. nonchars)\n\t) {\n\t\treturn 2;\n\t}\n\treturn 1;\n}\n\n/**\n * Count total display cells for a string in a monospace terminal.\n *\n * Combining marks contribute 0 cells; CJK / fullwidth contribute 2.\n * Does not handle ZWJ emoji sequences.\n */\nexport function countCells(text: string): number {\n\tlet cells = 0;\n\tfor (const ch of text) {\n\t\tcells += cellWidth(ch.codePointAt(0)!);\n\t}\n\treturn cells;\n}\n\n/**\n * Truncate `text` to at most `maxCells` terminal cells, appending an ellipsis\n * (\"…\" → 1 cell) when truncation occurs. Grapheme-unaware — splits at\n * codepoints; ZWJ sequences may be cut mid-cluster.\n */\nexport function truncateToCells(text: string, maxCells: number): string {\n\tif (maxCells <= 0) return \"\";\n\tlet cells = 0;\n\tlet out = \"\";\n\tfor (const ch of text) {\n\t\tconst w = cellWidth(ch.codePointAt(0)!);\n\t\tif (cells + w > maxCells) {\n\t\t\tif (maxCells <= 1) return \"…\";\n\t\t\t// Drop last wide char if we'd exceed budget with the ellipsis\n\t\t\twhile (cells + 1 > maxCells && out.length > 0) {\n\t\t\t\tconst last = [...out].pop()!;\n\t\t\t\tout = out.slice(0, -last.length);\n\t\t\t\tcells -= cellWidth(last.codePointAt(0)!);\n\t\t\t}\n\t\t\treturn `${out}…`;\n\t\t}\n\t\tout += ch;\n\t\tcells += w;\n\t}\n\treturn out;\n}\n","/**\n * Sugiyama-style layered DAG layout on an integer grid.\n *\n * Pipeline:\n * 1. Longest-path layer assignment (sources at layer 0).\n * 2. Virtual-node splitting — every edge spanning more than one layer\n * becomes a chain of synthetic nodes on intermediate layers. Downstream\n * passes treat real and virtual nodes identically; crossing\n * minimization therefore works on wide + deep DAGs, not only\n * adjacent-layer cases.\n * 3. Crossing minimization — barycenter heuristic with alternating up /\n * down sweeps plus an adjacent-transposition polish pass.\n * 4. Coordinate assignment — greedy median-aligned packing with collision\n * resolution. Straightens vertical runs of virtual nodes so long edges\n * become straight lines where topology allows.\n * 5. Orthogonal edge routing — per-gutter x-track assignment; horizontal\n * segments sit at endpoint centerlines, vertical segments pack into the\n * gutter column range without overlap. Remaining crossings are\n * topologically unavoidable and will render as `┼` at draw time.\n *\n * Output coordinates are cell-grid integers (LR direction). TD rendering\n * swaps axes at draw time — the layout is direction-agnostic by\n * construction.\n *\n * Used only by [graph-spec-to-ascii.ts](./graph-spec-to-ascii.ts); not part of the public\n * `extra/render/index.ts` surface (underscore-prefixed).\n */\n\nexport type LayoutDirection = \"LR\" | \"TD\";\n\nexport type LayoutInput = {\n\t/** Node ids in stable iteration order. Determines initial tie-break. */\n\treadonly nodes: readonly string[];\n\t/** Edges by (from, to) path. Endpoints must be present in `nodes`. */\n\treadonly edges: ReadonlyArray<{ from: string; to: string }>;\n\t/** Label width in cells for each node (independent of direction). */\n\treadonly widthCells: (id: string) => number;\n\t/** Label height in cells for each node (independent of direction). */\n\treadonly heightCells: (id: string) => number;\n\t/**\n\t * Gap between layer \"columns\" (LR) or \"rows\" (TD), in cells.\n\t * Must allow enough room for per-gutter edge tracks.\n\t */\n\treadonly layerGap: number;\n\t/**\n\t * Gap between neighboring nodes *within* a layer, in cells.\n\t * LR: vertical gap; TD: horizontal gap.\n\t */\n\treadonly nodeGap: number;\n\t/**\n\t * Axis orientation. LR: layers = columns (x grows), order = rows (y grows).\n\t * TD: layers = rows (y grows), order = columns (x grows).\n\t */\n\treadonly direction: LayoutDirection;\n};\n\nexport type LayoutBox = {\n\treadonly id: string;\n\treadonly layer: number;\n\treadonly order: number;\n\treadonly x: number;\n\treadonly y: number;\n\treadonly w: number;\n\treadonly h: number;\n};\n\nexport type LayoutEdgePoint = { readonly x: number; readonly y: number };\n\nexport type LayoutEdge = {\n\treadonly from: string;\n\treadonly to: string;\n\t/** Polyline of waypoints (start → corners → end). Minimum 2 entries. */\n\treadonly points: readonly LayoutEdgePoint[];\n};\n\nexport type LayoutResult = {\n\treadonly boxes: readonly LayoutBox[];\n\treadonly edges: readonly LayoutEdge[];\n\treadonly width: number;\n\treadonly height: number;\n};\n\n// ---------------------------------------------------------------------------\n// Internal types — carried through the pipeline\n// ---------------------------------------------------------------------------\n\ntype Hop = {\n\tchainId: number;\n\tchainFrom: string;\n\tchainTo: string;\n\tfromId: string;\n\ttoId: string;\n\t/** 0-based hop index along the chain. */\n\thopIndex: number;\n\t/** Total hops in the chain (1 = direct, 2+ = spans virtuals). */\n\tchainLen: number;\n};\n\ntype InternalNode = {\n\tid: string;\n\tisVirtual: boolean;\n\tlayer: number;\n\torder: number;\n\tx: number;\n\ty: number;\n\tw: number;\n\th: number;\n\tin: Hop[];\n\tout: Hop[];\n};\n\ntype Layer = InternalNode[];\n\ntype PipelineState = {\n\tnodes: Map<string, InternalNode>;\n\tlayers: Layer[];\n\thops: Hop[];\n};\n\n// ---------------------------------------------------------------------------\n// Pipeline entry\n// ---------------------------------------------------------------------------\n\nexport function sugiyamaLayout(input: LayoutInput): LayoutResult {\n\tconst state = buildInitial(input);\n\tassignLayers(state);\n\tinsertVirtualNodes(state);\n\tminimizeCrossings(state);\n\tassignCoordinates(state, input);\n\tconst edges = routeEdges(state, input);\n\tconst { width, height } = boundingBox(state);\n\tconst boxes: LayoutBox[] = [];\n\tfor (const layer of state.layers) {\n\t\tfor (const n of layer) {\n\t\t\tif (n.isVirtual) continue;\n\t\t\tboxes.push({\n\t\t\t\tid: n.id,\n\t\t\t\tlayer: n.layer,\n\t\t\t\torder: n.order,\n\t\t\t\tx: n.x,\n\t\t\t\ty: n.y,\n\t\t\t\tw: n.w,\n\t\t\t\th: n.h,\n\t\t\t});\n\t\t}\n\t}\n\treturn { boxes, edges, width, height };\n}\n\n// ---------------------------------------------------------------------------\n// 1. Build internal graph\n// ---------------------------------------------------------------------------\n\nfunction buildInitial(input: LayoutInput): PipelineState {\n\tconst nodes = new Map<string, InternalNode>();\n\tfor (const id of input.nodes) {\n\t\tnodes.set(id, {\n\t\t\tid,\n\t\t\tisVirtual: false,\n\t\t\tlayer: -1,\n\t\t\torder: 0,\n\t\t\tx: 0,\n\t\t\ty: 0,\n\t\t\tw: input.widthCells(id),\n\t\t\th: input.heightCells(id),\n\t\t\tin: [],\n\t\t\tout: [],\n\t\t});\n\t}\n\tconst hops: Hop[] = [];\n\tlet chainId = 0;\n\tfor (const e of input.edges) {\n\t\tif (e.from === e.to) continue; // drop self-loops\n\t\tconst f = nodes.get(e.from);\n\t\tconst t = nodes.get(e.to);\n\t\tif (!f || !t) continue; // drop dangling endpoints\n\t\tconst hop: Hop = {\n\t\t\tchainId: chainId++,\n\t\t\tchainFrom: e.from,\n\t\t\tchainTo: e.to,\n\t\t\tfromId: e.from,\n\t\t\ttoId: e.to,\n\t\t\thopIndex: 0,\n\t\t\tchainLen: 1,\n\t\t};\n\t\tf.out.push(hop);\n\t\tt.in.push(hop);\n\t\thops.push(hop);\n\t}\n\treturn { nodes, layers: [], hops };\n}\n\n// ---------------------------------------------------------------------------\n// 2. Longest-path layer assignment (Kahn's algorithm)\n// ---------------------------------------------------------------------------\n\nfunction assignLayers(state: PipelineState): void {\n\tconst indeg = new Map<string, number>();\n\tfor (const n of state.nodes.values()) indeg.set(n.id, n.in.length);\n\n\tconst queue: InternalNode[] = [];\n\tfor (const n of state.nodes.values()) {\n\t\tif ((indeg.get(n.id) ?? 0) === 0) {\n\t\t\tn.layer = 0;\n\t\t\tqueue.push(n);\n\t\t}\n\t}\n\n\t// Cursor-based BFS — `Array.prototype.shift` is O(n), so the naive form\n\t// is O(n²) and degrades past ~1000 nodes. Cursor keeps it linear.\n\tconst visited = new Set<string>();\n\tlet head = 0;\n\twhile (head < queue.length) {\n\t\tconst n = queue[head++]!;\n\t\tif (visited.has(n.id)) continue;\n\t\tvisited.add(n.id);\n\t\tfor (const hop of n.out) {\n\t\t\tconst t = state.nodes.get(hop.toId)!;\n\t\t\tt.layer = Math.max(t.layer, n.layer + 1);\n\t\t\tconst d = (indeg.get(t.id) ?? 0) - 1;\n\t\t\tindeg.set(t.id, d);\n\t\t\tif (d <= 0) queue.push(t);\n\t\t}\n\t}\n\t// Nodes trapped in a cycle default to layer 0. The edges that would\n\t// close the cycle are dropped in `insertVirtualNodes` (any hop whose\n\t// span is not a positive integer). GraphReFly graphs are DAGs by spec;\n\t// this path is defensive against malformed describe snapshots.\n\tfor (const n of state.nodes.values()) if (n.layer < 0) n.layer = 0;\n}\n\n// ---------------------------------------------------------------------------\n// 3. Virtual-node insertion — critical for scaling past adjacent-layer edges\n// ---------------------------------------------------------------------------\n\nfunction insertVirtualNodes(state: PipelineState): void {\n\tconst maxLayer = Math.max(0, ...Array.from(state.nodes.values(), (n) => n.layer));\n\tconst layers: Layer[] = Array.from({ length: maxLayer + 1 }, () => []);\n\tfor (const n of state.nodes.values()) layers[n.layer]!.push(n);\n\n\tconst newHops: Hop[] = [];\n\tlet virtCounter = 0;\n\tfor (const hop of state.hops) {\n\t\tconst f = state.nodes.get(hop.fromId)!;\n\t\tconst t = state.nodes.get(hop.toId)!;\n\t\tconst span = t.layer - f.layer;\n\t\tif (span <= 0) {\n\t\t\t// Same-layer or back-edge — the input violated the DAG invariant\n\t\t\t// (self-loop was already dropped in `buildInitial`; this catches\n\t\t\t// cycles whose nodes collapsed to layer 0 in `assignLayers`).\n\t\t\t// Drop from both endpoints so routing never sees the hop; same\n\t\t\t// render-best-effort policy as the self-loop / dangling-endpoint\n\t\t\t// filters in `buildInitial`.\n\t\t\tf.out = f.out.filter((h) => h !== hop);\n\t\t\tt.in = t.in.filter((h) => h !== hop);\n\t\t\tcontinue;\n\t\t}\n\t\tif (span === 1) {\n\t\t\thop.hopIndex = 0;\n\t\t\thop.chainLen = 1;\n\t\t\tnewHops.push(hop);\n\t\t\tcontinue;\n\t\t}\n\t\t// Multi-hop: f → v1 → v2 → ... → t\n\t\t// Detach the original edge from f.out / t.in; we rewrite as chain.\n\t\tf.out = f.out.filter((h) => h !== hop);\n\t\tt.in = t.in.filter((h) => h !== hop);\n\n\t\tlet prev = f;\n\t\tfor (let i = 1; i < span; i += 1) {\n\t\t\tconst vid = `__virt_${virtCounter++}__`;\n\t\t\tconst v: InternalNode = {\n\t\t\t\tid: vid,\n\t\t\t\tisVirtual: true,\n\t\t\t\tlayer: f.layer + i,\n\t\t\t\torder: 0,\n\t\t\t\tx: 0,\n\t\t\t\ty: 0,\n\t\t\t\tw: 0,\n\t\t\t\th: 1,\n\t\t\t\tin: [],\n\t\t\t\tout: [],\n\t\t\t};\n\t\t\tstate.nodes.set(vid, v);\n\t\t\tlayers[v.layer]!.push(v);\n\t\t\tconst h: Hop = {\n\t\t\t\tchainId: hop.chainId,\n\t\t\t\tchainFrom: hop.chainFrom,\n\t\t\t\tchainTo: hop.chainTo,\n\t\t\t\tfromId: prev.id,\n\t\t\t\ttoId: vid,\n\t\t\t\thopIndex: i - 1,\n\t\t\t\tchainLen: span,\n\t\t\t};\n\t\t\tprev.out.push(h);\n\t\t\tv.in.push(h);\n\t\t\tnewHops.push(h);\n\t\t\tprev = v;\n\t\t}\n\t\tconst finalHop: Hop = {\n\t\t\tchainId: hop.chainId,\n\t\t\tchainFrom: hop.chainFrom,\n\t\t\tchainTo: hop.chainTo,\n\t\t\tfromId: prev.id,\n\t\t\ttoId: t.id,\n\t\t\thopIndex: span - 1,\n\t\t\tchainLen: span,\n\t\t};\n\t\tprev.out.push(finalHop);\n\t\tt.in.push(finalHop);\n\t\tnewHops.push(finalHop);\n\t}\n\n\t// Stable initial order within each layer.\n\tfor (const layer of layers) {\n\t\tfor (let i = 0; i < layer.length; i += 1) layer[i]!.order = i;\n\t}\n\tstate.layers = layers;\n\tstate.hops = newHops;\n}\n\n// ---------------------------------------------------------------------------\n// 4. Crossing minimization\n// ---------------------------------------------------------------------------\n\nfunction minimizeCrossings(state: PipelineState): void {\n\tconst SWEEPS = 4;\n\tfor (let sweep = 0; sweep < SWEEPS; sweep += 1) {\n\t\t// Down-sweep\n\t\tfor (let li = 1; li < state.layers.length; li += 1) {\n\t\t\tsortByBarycenter(state, state.layers[li]!, \"in\");\n\t\t\treindex(state.layers[li]!);\n\t\t}\n\t\t// Up-sweep\n\t\tfor (let li = state.layers.length - 2; li >= 0; li -= 1) {\n\t\t\tsortByBarycenter(state, state.layers[li]!, \"out\");\n\t\t\treindex(state.layers[li]!);\n\t\t}\n\t}\n\t// Polish — adjacent-transposition pass, bounded iterations.\n\tfor (let iter = 0; iter < 2; iter += 1) {\n\t\tlet improved = false;\n\t\tfor (let li = 1; li < state.layers.length; li += 1) {\n\t\t\tconst layer = state.layers[li]!;\n\t\t\tfor (let i = 0; i + 1 < layer.length; i += 1) {\n\t\t\t\tconst before = pairCrossings(state, layer[i]!, layer[i + 1]!, \"in\");\n\t\t\t\t[layer[i], layer[i + 1]] = [layer[i + 1]!, layer[i]!];\n\t\t\t\treindex(layer);\n\t\t\t\tconst after = pairCrossings(state, layer[i]!, layer[i + 1]!, \"in\");\n\t\t\t\tif (after < before) {\n\t\t\t\t\timproved = true;\n\t\t\t\t} else {\n\t\t\t\t\t[layer[i], layer[i + 1]] = [layer[i + 1]!, layer[i]!];\n\t\t\t\t\treindex(layer);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!improved) break;\n\t}\n}\n\nfunction sortByBarycenter(state: PipelineState, layer: Layer, direction: \"in\" | \"out\"): void {\n\tconst bary = new Map<string, number>();\n\tfor (const n of layer) {\n\t\tconst neighbors = direction === \"in\" ? n.in : n.out;\n\t\tif (neighbors.length === 0) {\n\t\t\tbary.set(n.id, n.order);\n\t\t\tcontinue;\n\t\t}\n\t\tlet sum = 0;\n\t\tlet count = 0;\n\t\tfor (const h of neighbors) {\n\t\t\tconst other = state.nodes.get(direction === \"in\" ? h.fromId : h.toId);\n\t\t\tif (!other) continue;\n\t\t\tsum += other.order;\n\t\t\tcount += 1;\n\t\t}\n\t\tbary.set(n.id, count === 0 ? n.order : sum / count);\n\t}\n\tlayer.sort((a, b) => {\n\t\tconst ba = bary.get(a.id)!;\n\t\tconst bb = bary.get(b.id)!;\n\t\tif (ba !== bb) return ba - bb;\n\t\treturn a.order - b.order;\n\t});\n}\n\nfunction reindex(layer: Layer): void {\n\tfor (let i = 0; i < layer.length; i += 1) layer[i]!.order = i;\n}\n\nfunction pairCrossings(\n\tstate: PipelineState,\n\ta: InternalNode,\n\tb: InternalNode,\n\tdirection: \"in\" | \"out\",\n): number {\n\tconst aEdges = direction === \"in\" ? a.in : a.out;\n\tconst bEdges = direction === \"in\" ? b.in : b.out;\n\tlet crossings = 0;\n\tfor (const ea of aEdges) {\n\t\tfor (const eb of bEdges) {\n\t\t\tconst oa = state.nodes.get(direction === \"in\" ? ea.fromId : ea.toId)?.order ?? 0;\n\t\t\tconst ob = state.nodes.get(direction === \"in\" ? eb.fromId : eb.toId)?.order ?? 0;\n\t\t\tif ((a.order < b.order && oa > ob) || (a.order > b.order && oa < ob)) {\n\t\t\t\tcrossings += 1;\n\t\t\t}\n\t\t}\n\t}\n\treturn crossings;\n}\n\n// ---------------------------------------------------------------------------\n// 5. Coordinate assignment (direction-aware)\n// ---------------------------------------------------------------------------\n\nfunction assignCoordinates(state: PipelineState, input: LayoutInput): void {\n\tif (input.direction === \"LR\") assignCoordinatesLR(state, input);\n\telse assignCoordinatesTD(state, input);\n}\n\nfunction assignCoordinatesLR(state: PipelineState, input: LayoutInput): void {\n\t// x: per-layer column based on cumulative max width.\n\tconst layerX: number[] = [];\n\tlet cursorX = 0;\n\tfor (let li = 0; li < state.layers.length; li += 1) {\n\t\tlayerX.push(cursorX);\n\t\tlet maxW = 0;\n\t\tfor (const n of state.layers[li]!) maxW = Math.max(maxW, n.w);\n\t\tcursorX += maxW + input.layerGap;\n\t}\n\tfor (let li = 0; li < state.layers.length; li += 1) {\n\t\tfor (const n of state.layers[li]!) n.x = layerX[li]!;\n\t}\n\t// y: greedy pack per layer.\n\tfor (const layer of state.layers) {\n\t\tlet y = 0;\n\t\tfor (const n of layer) {\n\t\t\tn.y = y;\n\t\t\ty += n.h + input.nodeGap;\n\t\t}\n\t}\n\t// Median alignment — straightens chains through virtuals.\n\trunMedianPasses(state, input, \"y\");\n}\n\nfunction assignCoordinatesTD(state: PipelineState, input: LayoutInput): void {\n\t// y: per-layer row based on cumulative max height.\n\tconst layerY: number[] = [];\n\tlet cursorY = 0;\n\tfor (let li = 0; li < state.layers.length; li += 1) {\n\t\tlayerY.push(cursorY);\n\t\tlet maxH = 0;\n\t\tfor (const n of state.layers[li]!) maxH = Math.max(maxH, n.h);\n\t\tcursorY += maxH + input.layerGap;\n\t}\n\tfor (let li = 0; li < state.layers.length; li += 1) {\n\t\tfor (const n of state.layers[li]!) n.y = layerY[li]!;\n\t}\n\t// x: greedy pack per layer.\n\tfor (const layer of state.layers) {\n\t\tlet x = 0;\n\t\tfor (const n of layer) {\n\t\t\tn.x = x;\n\t\t\tx += n.w + input.nodeGap;\n\t\t}\n\t}\n\trunMedianPasses(state, input, \"x\");\n}\n\n/**\n * Median alignment passes — pulls each node toward the median position of\n * its in-layer neighbors along the private axis (\"y\" for LR, \"x\" for TD),\n * then resolves collisions greedily while preserving layer order.\n */\nfunction runMedianPasses(state: PipelineState, input: LayoutInput, axis: \"x\" | \"y\"): void {\n\tconst sizeOf = (n: InternalNode) => (axis === \"y\" ? n.h : n.w);\n\tconst gap = input.nodeGap;\n\tfor (let pass = 0; pass < 2; pass += 1) {\n\t\tconst walk = pass === 0 ? state.layers.slice(1) : state.layers.slice(0, -1).reverse();\n\t\tfor (const layer of walk) {\n\t\t\tconst preferred = new Map<string, number>();\n\t\t\tfor (const n of layer) {\n\t\t\t\tconst neighbors = pass === 0 ? n.in : n.out;\n\t\t\t\tif (neighbors.length === 0) continue;\n\t\t\t\tconst centers: number[] = [];\n\t\t\t\tfor (const h of neighbors) {\n\t\t\t\t\tconst other = state.nodes.get(pass === 0 ? h.fromId : h.toId);\n\t\t\t\t\tif (!other) continue;\n\t\t\t\t\tconst base = axis === \"y\" ? other.y : other.x;\n\t\t\t\t\tcenters.push(base + Math.floor(sizeOf(other) / 2));\n\t\t\t\t}\n\t\t\t\tif (centers.length === 0) continue;\n\t\t\t\tcenters.sort((a, b) => a - b);\n\t\t\t\tconst mid = centers[Math.floor(centers.length / 2)]!;\n\t\t\t\tpreferred.set(n.id, mid - Math.floor(sizeOf(n) / 2));\n\t\t\t}\n\t\t\tlet floor = 0;\n\t\t\tfor (const n of layer) {\n\t\t\t\tconst p = preferred.get(n.id);\n\t\t\t\tconst current = axis === \"y\" ? n.y : n.x;\n\t\t\t\tconst target = p ?? current;\n\t\t\t\tconst clamped = Math.max(target, floor);\n\t\t\t\tif (axis === \"y\") n.y = clamped;\n\t\t\t\telse n.x = clamped;\n\t\t\t\tfloor = clamped + sizeOf(n) + gap;\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// 6. Orthogonal edge routing (direction-aware)\n//\n// For both LR and TD the algorithm is symmetric — it just operates on a\n// different pair of \"primary\" vs \"cross\" axes:\n//\n// LR: primary = x (layer axis); cross = y. Gutters are vertical strips\n// between columns; tracks within a gutter are distinct x-values.\n// TD: primary = y (layer axis); cross = x. Gutters are horizontal strips\n// between rows; tracks within a gutter are distinct y-values.\n// ---------------------------------------------------------------------------\n\nfunction routeEdges(state: PipelineState, input: LayoutInput): LayoutEdge[] {\n\t// Group hops by chainId → one LayoutEdge per user-facing edge.\n\tconst byChain = new Map<number, Hop[]>();\n\tfor (const h of state.hops) {\n\t\tconst arr = byChain.get(h.chainId);\n\t\tif (arr) arr.push(h);\n\t\telse byChain.set(h.chainId, [h]);\n\t}\n\tfor (const arr of byChain.values()) arr.sort((a, b) => a.hopIndex - b.hopIndex);\n\n\tconst isLR = input.direction === \"LR\";\n\tconst primary = (n: InternalNode): number => (isLR ? n.x : n.y);\n\tconst primarySize = (n: InternalNode): number => (isLR ? n.w : n.h);\n\tconst crossCenter = (n: InternalNode): number =>\n\t\tisLR ? n.y + Math.floor(n.h / 2) : n.x + Math.floor(n.w / 2);\n\n\t// Per-gutter cross-axis track assignment. Two passes:\n\t// 1. Assign each hop to a track INDEX using disjoint-interval packing\n\t// (an existing track may host multiple hops as long as their\n\t// cross-axis ranges don't overlap pairwise).\n\t// 2. Map each track index to a primary-axis position using the final\n\t// track count so the distribution is uniform across the gutter —\n\t// per-hop recomputation (old behavior) collapsed late tracks onto\n\t// `gEnd`, producing bundled overlaps in dense gutters.\n\tconst hopTrackCross = new Map<Hop, number>();\n\tfor (let g = 0; g + 1 < state.layers.length; g += 1) {\n\t\tconst srcLayer = state.layers[g]!;\n\t\tconst dstLayer = state.layers[g + 1]!;\n\n\t\tlet gutterStart = 0;\n\t\tfor (const n of srcLayer) gutterStart = Math.max(gutterStart, primary(n) + primarySize(n));\n\t\tlet gutterEnd = Number.POSITIVE_INFINITY;\n\t\tfor (const n of dstLayer) gutterEnd = Math.min(gutterEnd, primary(n));\n\t\tconst gEnd = Number.isFinite(gutterEnd) ? (gutterEnd as number) - 1 : gutterStart;\n\t\tconst gutterWidth = Math.max(1, gEnd - gutterStart + 1);\n\n\t\tconst gutterHops: Hop[] = [];\n\t\tfor (const n of srcLayer) for (const h of n.out) gutterHops.push(h);\n\t\tgutterHops.sort((a, b) => {\n\t\t\tconst sa = crossCenter(state.nodes.get(a.fromId)!);\n\t\t\tconst sb = crossCenter(state.nodes.get(b.fromId)!);\n\t\t\tif (sa !== sb) return sa - sb;\n\t\t\tconst da = crossCenter(state.nodes.get(a.toId)!);\n\t\t\tconst db = crossCenter(state.nodes.get(b.toId)!);\n\t\t\treturn da - db;\n\t\t});\n\n\t\t// Pass 1: assign track indexes. Each track is an ARRAY of disjoint\n\t\t// intervals — two hops share a track iff their cross-axis ranges\n\t\t// don't overlap any existing interval on that track.\n\t\tconst tracks: Array<Array<{ lo: number; hi: number }>> = [];\n\t\tconst hopToTrackIdx = new Map<Hop, number>();\n\t\tfor (const h of gutterHops) {\n\t\t\tconst sc = crossCenter(state.nodes.get(h.fromId)!);\n\t\t\tconst dc = crossCenter(state.nodes.get(h.toId)!);\n\t\t\tconst lo = Math.min(sc, dc);\n\t\t\tconst hi = Math.max(sc, dc);\n\t\t\tlet idx = -1;\n\t\t\tfor (let t = 0; t < tracks.length; t += 1) {\n\t\t\t\tconst intervals = tracks[t]!;\n\t\t\t\tlet fits = true;\n\t\t\t\tfor (const iv of intervals) {\n\t\t\t\t\tif (iv.lo <= hi && lo <= iv.hi) {\n\t\t\t\t\t\tfits = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (fits) {\n\t\t\t\t\tintervals.push({ lo, hi });\n\t\t\t\t\tidx = t;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (idx < 0) {\n\t\t\t\ttracks.push([{ lo, hi }]);\n\t\t\t\tidx = tracks.length - 1;\n\t\t\t}\n\t\t\thopToTrackIdx.set(h, idx);\n\t\t}\n\n\t\t// Pass 2: distribute track indexes uniformly across the gutter's\n\t\t// **interior** (reserve 1-cell margin from each boundary when the\n\t\t// gutter is wide enough). A track placed exactly at `gutterStart`\n\t\t// or `gEnd` collapses the final turn-segment into the adjacent\n\t\t// node's border row, producing a visually misleading arrow; the\n\t\t// margin avoids that whenever geometry allows.\n\t\tconst count = tracks.length;\n\t\tconst hasMargin = gutterWidth >= Math.max(3, count + 2);\n\t\tconst usableStart = hasMargin ? gutterStart + 1 : gutterStart;\n\t\tconst usableEnd = hasMargin ? gEnd - 1 : gEnd;\n\t\tconst usableWidth = Math.max(1, usableEnd - usableStart + 1);\n\t\tfor (const h of gutterHops) {\n\t\t\tconst idx = hopToTrackIdx.get(h)!;\n\t\t\tlet trackPrimary: number;\n\t\t\tif (count <= 1) {\n\t\t\t\ttrackPrimary = usableStart + Math.floor(usableWidth / 2);\n\t\t\t} else {\n\t\t\t\tconst step = (usableWidth - 1) / (count - 1);\n\t\t\t\ttrackPrimary = usableStart + Math.floor(idx * step);\n\t\t\t}\n\t\t\thopTrackCross.set(h, Math.max(gutterStart, Math.min(gEnd, trackPrimary)));\n\t\t}\n\t}\n\n\t// Build polylines.\n\tconst out: LayoutEdge[] = [];\n\tfor (const [, hops] of byChain) {\n\t\tconst points: LayoutEdgePoint[] = [];\n\t\tfor (let i = 0; i < hops.length; i += 1) {\n\t\t\tconst h = hops[i]!;\n\t\t\tconst src = state.nodes.get(h.fromId)!;\n\t\t\tconst dst = state.nodes.get(h.toId)!;\n\t\t\tconst track = hopTrackCross.get(h)!;\n\t\t\t// Endpoints in (primary, cross) space.\n\t\t\tconst srcPrimary = src.isVirtual ? primary(src) : primary(src) + primarySize(src);\n\t\t\tconst dstPrimary = dst.isVirtual ? primary(dst) : primary(dst) - 1;\n\t\t\tconst sc = crossCenter(src);\n\t\t\tconst dc = crossCenter(dst);\n\t\t\tif (i === 0) pushPoint(points, isLR, srcPrimary, sc);\n\t\t\tif (sc !== dc) {\n\t\t\t\tpushPoint(points, isLR, track, sc);\n\t\t\t\tpushPoint(points, isLR, track, dc);\n\t\t\t}\n\t\t\tpushPoint(points, isLR, dstPrimary, dc);\n\t\t}\n\t\tconst chain = hops[0]!;\n\t\tout.push({\n\t\t\tfrom: chain.chainFrom,\n\t\t\tto: chain.chainTo,\n\t\t\tpoints: dedupWaypoints(points),\n\t\t});\n\t}\n\treturn out;\n}\n\nfunction pushPoint(acc: LayoutEdgePoint[], isLR: boolean, primary: number, cross: number): void {\n\tacc.push(isLR ? { x: primary, y: cross } : { x: cross, y: primary });\n}\n\nfunction dedupWaypoints(points: readonly LayoutEdgePoint[]): LayoutEdgePoint[] {\n\tconst out: LayoutEdgePoint[] = [];\n\tfor (const p of points) {\n\t\tconst last = out[out.length - 1];\n\t\tif (!last || last.x !== p.x || last.y !== p.y) out.push(p);\n\t}\n\treturn out;\n}\n\n// ---------------------------------------------------------------------------\n// Bounding box\n// ---------------------------------------------------------------------------\n\nfunction boundingBox(state: PipelineState): { width: number; height: number } {\n\tlet w = 0;\n\tlet h = 0;\n\tfor (const layer of state.layers) {\n\t\tfor (const n of layer) {\n\t\t\tw = Math.max(w, n.x + n.w);\n\t\t\th = Math.max(h, n.y + n.h);\n\t\t}\n\t}\n\treturn { width: w, height: h };\n}\n","/**\n * Internal helpers shared across renderers in `extra/render/`.\n *\n * These are pure functions over `GraphDescribeOutput` — no Graph instance\n * dependency. Extracted from `src/graph/graph.ts` (the consolidated\n * ex-dumpGraph / ex-graphSpecToMermaid / ex-graphSpecToD2 renderers) per\n * Tier 2.1 A2.\n */\n\nimport type { GraphDescribeOutput } from \"@graphrefly/pure-ts/graph\";\n\n/** Direction options for diagram exports. */\nexport type DiagramDirection = \"TD\" | \"LR\" | \"BT\" | \"RL\";\n\n/** Recursively sort object keys for deterministic JSON (git-diffable). */\nexport function 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\n/** Escape characters that are illegal inside a quoted Mermaid label. */\nexport function escapeMermaidLabel(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"');\n}\n\n/** Escape characters that are illegal inside a quoted D2 label. */\nexport function escapeD2Label(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"');\n}\n\n/** Map our 4-direction enum to D2's `direction:` keyword. */\nexport function d2DirectionFromGraphDirection(direction: DiagramDirection): 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. */\nexport function 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\n/** Default to \"LR\"; throw on unknown values to surface caller bugs early. */\nexport function normalizeDiagramDirection(direction: unknown): DiagramDirection {\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/** JSON-aware single-value formatter (used by `graphSpecToPretty`). */\nexport function 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","/**\n * `graphSpecToMermaid(g, opts?)` — render a {@link GraphDescribeOutput} as\n * Mermaid flowchart text.\n *\n * Pure function over the describe snapshot; no Graph instance dependency.\n * Compose with `derived` for live formatted output:\n *\n * ```ts\n * import { graphSpecToMermaid } from \"@graphrefly/graphrefly/extra/render\";\n * import { derived } from \"@graphrefly/graphrefly\";\n *\n * const live = derived(\n * [graph.describe({ reactive: true }).node],\n * ([g]) => graphSpecToMermaid(g),\n * );\n * ```\n *\n * @category extra\n */\n\nimport type { GraphDescribeOutput } from \"@graphrefly/pure-ts/graph\";\nimport {\n\tcollectDiagramArrows,\n\ttype DiagramDirection,\n\tescapeMermaidLabel,\n\tnormalizeDiagramDirection,\n} from \"./_internal.js\";\n\nexport type GraphSpecToMermaidOptions = {\n\t/** Diagram direction; default `\"LR\"`. */\n\tdirection?: DiagramDirection;\n};\n\nexport function graphSpecToMermaid(\n\tg: GraphDescribeOutput,\n\topts?: GraphSpecToMermaidOptions,\n): string {\n\tconst direction = normalizeDiagramDirection(opts?.direction);\n\tconst paths = Object.keys(g.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(g)) {\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","/**\n * Reactive text layout engine (roadmap §7.1 — Pretext parity).\n *\n * Pure-arithmetic text measurement and line breaking without DOM thrashing.\n * Inspired by [Pretext](https://github.com/chenglou/pretext), rebuilt as a\n * GraphReFly graph — inspectable via `describe()`, snapshotable, debuggable.\n *\n * Two-tier DX:\n * - `reactiveLayout({ adapter, text?, font?, lineHeight?, maxWidth?, name? })` — convenience factory\n * - `MeasurementAdapter` — pluggable backends (`measureSegment`; optional `clearCache`)\n */\nimport { monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\n\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { emitToMeta } from \"../../base/meta/emit-to-meta.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Pluggable measurement backend. */\nexport interface MeasurementAdapter {\n\tmeasureSegment(text: string, font: string): { width: number };\n\t/** Optional; adapters may omit for read-only / stateless measurement. */\n\tclearCache?(): void;\n}\n\n/** Mutable counters for `analyzeAndMeasure` cache hit ratio (hits / (hits + misses)). */\nexport type SegmentMeasureStats = { hits: number; misses: number };\n\n/** Break kind for each segment (ported from Pretext analysis.ts). */\nexport type SegmentBreakKind = \"text\" | \"space\" | \"zero-width-break\" | \"soft-hyphen\" | \"hard-break\";\n\n/** A measured text segment ready for line breaking. */\nexport type PreparedSegment = {\n\ttext: string;\n\twidth: number;\n\tkind: SegmentBreakKind;\n\t/** Grapheme widths for overflow-wrap: break-word (null if single grapheme). */\n\tgraphemeWidths: number[] | null;\n};\n\n/** A laid-out line with start/end cursors. */\nexport type LayoutLine = {\n\ttext: string;\n\twidth: number;\n\tstartSegment: number;\n\tstartGrapheme: number;\n\tendSegment: number;\n\tendGrapheme: number;\n};\n\n/** Per-character position for hit testing. */\nexport type CharPosition = {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n\tline: number;\n};\n\n/** Full layout result from the line-breaks derived node. */\nexport type LineBreaksResult = {\n\tlines: LayoutLine[];\n\tlineCount: number;\n};\n\n/**\n * A position within `PreparedSegment[]` — segment + grapheme offset.\n * `graphemeIndex: 0` at segment boundaries.\n *\n * Used by {@link layoutNextLine} for cursor-based line walking; needed when\n * lines have varying widths (multi-column flow, text wrapping around obstacles).\n */\nexport type LayoutCursor = {\n\tsegmentIndex: number;\n\tgraphemeIndex: number;\n};\n\n/** A horizontal span `[left, right]` in pixels — used by flow-layout slot carving. */\nexport type Interval = { left: number; right: number };\n\n/** Result of a single `layoutNextLine` call. */\nexport type LayoutNextLineResult = {\n\ttext: string;\n\twidth: number;\n\tstart: LayoutCursor;\n\tend: LayoutCursor;\n};\n\n/** Optional context for `layoutNextLine` — enables soft-hyphen visible-hyphen rendering. */\nexport type LayoutNextLineContext = {\n\tadapter?: MeasurementAdapter;\n\tfont?: string;\n\tcache?: Map<string, Map<string, number>>;\n};\n\n/** Result of the reactive layout graph's describe-accessible state. */\nexport type ReactiveLayoutBundle = {\n\tgraph: Graph;\n\t/** Set input text. */\n\tsetText: (text: string) => void;\n\t/** Set CSS font string. */\n\tsetFont: (font: string) => void;\n\t/** Set line height (px). */\n\tsetLineHeight: (lineHeight: number) => void;\n\t/** Set max width constraint (px). */\n\tsetMaxWidth: (maxWidth: number) => void;\n\t/** Segments node. */\n\tsegments: Node<PreparedSegment[]>;\n\t/** Line breaks node. */\n\tlineBreaks: Node<LineBreaksResult>;\n\t/** Total height node. */\n\theight: Node<number>;\n\t/** Per-character positions node. */\n\tcharPositions: Node<CharPosition[]>;\n};\n\n// ---------------------------------------------------------------------------\n// Text analysis (ported from Pretext analysis.ts — core subset)\n// ---------------------------------------------------------------------------\n\n// CJK detection (Unicode CJK Unified Ideographs + common ranges)\nfunction isCJK(s: string): boolean {\n\tfor (const ch of s) {\n\t\tconst c = ch.codePointAt(0)!;\n\t\tif (\n\t\t\t(c >= 0x4e00 && c <= 0x9fff) || // CJK Unified Ideographs\n\t\t\t(c >= 0x3400 && c <= 0x4dbf) || // CJK Extension A\n\t\t\t(c >= 0x3000 && c <= 0x303f) || // CJK Symbols and Punctuation\n\t\t\t(c >= 0x3040 && c <= 0x309f) || // Hiragana\n\t\t\t(c >= 0x30a0 && c <= 0x30ff) || // Katakana\n\t\t\t(c >= 0xac00 && c <= 0xd7af) || // Hangul\n\t\t\t(c >= 0xff00 && c <= 0xffef) // Fullwidth Forms\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n// Kinsoku: characters that cannot start a line (CJK punctuation)\nconst kinsokuStart = new Set([\n\t\"\\uff0c\",\n\t\"\\uff0e\",\n\t\"\\uff01\",\n\t\"\\uff1a\",\n\t\"\\uff1b\",\n\t\"\\uff1f\",\n\t\"\\u3001\",\n\t\"\\u3002\",\n\t\"\\u30fb\",\n\t\"\\uff09\",\n\t\"\\u3015\",\n\t\"\\u3009\",\n\t\"\\u300b\",\n\t\"\\u300d\",\n\t\"\\u300f\",\n\t\"\\u3011\",\n]);\n\n// Left-sticky punctuation (merges into preceding segment)\nconst leftStickyPunctuation = new Set([\n\t\".\",\n\t\",\",\n\t\"!\",\n\t\"?\",\n\t\":\",\n\t\";\",\n\t\")\",\n\t\"]\",\n\t\"}\",\n\t\"%\",\n\t'\"',\n\t\"\\u201d\",\n\t\"\\u2019\",\n\t\"\\u00bb\",\n\t\"\\u203a\",\n\t\"\\u2026\",\n]);\n\n/** Normalize collapsible whitespace (CSS white-space: normal). */\nfunction normalizeWhitespace(text: string): string {\n\treturn text.replace(/[\\t\\n\\r\\f ]+/g, \" \").replace(/^ | $/g, \"\");\n}\n\n/**\n * Segment text using Intl.Segmenter (word granularity) and classify break kinds.\n * Returns raw segmentation pieces before merging.\n */\nfunction segmentText(normalized: string): {\n\ttexts: string[];\n\tisWordLike: boolean[];\n\tkinds: SegmentBreakKind[];\n}[] {\n\tconst wordSegmenter = new Intl.Segmenter(undefined, { granularity: \"word\" });\n\tconst pieces: {\n\t\ttexts: string[];\n\t\tisWordLike: boolean[];\n\t\tkinds: SegmentBreakKind[];\n\t}[] = [];\n\n\tfor (const s of wordSegmenter.segment(normalized)) {\n\t\tconst text = s.segment;\n\t\tconst isWordLike = s.isWordLike ?? false;\n\n\t\t// Split segment by break-relevant characters\n\t\tconst texts: string[] = [];\n\t\tconst wordLikes: boolean[] = [];\n\t\tconst kinds: SegmentBreakKind[] = [];\n\n\t\tlet currentText = \"\";\n\t\tlet currentKind: SegmentBreakKind | null = null;\n\n\t\tfor (const ch of text) {\n\t\t\tlet kind: SegmentBreakKind;\n\t\t\tif (ch === \" \") kind = \"space\";\n\t\t\telse if (ch === \"\\u200b\") kind = \"zero-width-break\";\n\t\t\telse if (ch === \"\\u00ad\") kind = \"soft-hyphen\";\n\t\t\telse if (ch === \"\\n\") kind = \"hard-break\";\n\t\t\telse kind = \"text\";\n\n\t\t\tif (currentKind !== null && kind === currentKind) {\n\t\t\t\tcurrentText += ch;\n\t\t\t} else {\n\t\t\t\tif (currentKind !== null) {\n\t\t\t\t\ttexts.push(currentText);\n\t\t\t\t\twordLikes.push(currentKind === \"text\" && isWordLike);\n\t\t\t\t\tkinds.push(currentKind);\n\t\t\t\t}\n\t\t\t\tcurrentText = ch;\n\t\t\t\tcurrentKind = kind;\n\t\t\t}\n\t\t}\n\n\t\tif (currentKind !== null) {\n\t\t\ttexts.push(currentText);\n\t\t\twordLikes.push(currentKind === \"text\" && isWordLike);\n\t\t\tkinds.push(currentKind);\n\t\t}\n\n\t\tpieces.push({ texts, isWordLike: wordLikes, kinds });\n\t}\n\treturn pieces;\n}\n\n/**\n * Merge segmentation pieces: sticky punctuation, CJK per-grapheme splitting,\n * and produce the final measured segment list.\n */\nexport function analyzeAndMeasure(\n\ttext: string,\n\tfont: string,\n\tadapter: MeasurementAdapter,\n\tcache: Map<string, Map<string, number>>,\n\tstats?: SegmentMeasureStats,\n): PreparedSegment[] {\n\tconst normalized = normalizeWhitespace(text);\n\tif (normalized.length === 0) return [];\n\n\tconst pieces = segmentText(normalized);\n\tconst graphemeSegmenter = new Intl.Segmenter(undefined, {\n\t\tgranularity: \"grapheme\",\n\t});\n\n\t// Flatten pieces into a single segment list with merging\n\tconst rawTexts: string[] = [];\n\tconst rawKinds: SegmentBreakKind[] = [];\n\tconst rawWordLike: boolean[] = [];\n\n\tfor (const piece of pieces) {\n\t\tfor (let i = 0; i < piece.texts.length; i++) {\n\t\t\trawTexts.push(piece.texts[i]!);\n\t\t\trawKinds.push(piece.kinds[i]!);\n\t\t\trawWordLike.push(piece.isWordLike[i]!);\n\t\t}\n\t}\n\n\t// Merge: left-sticky punctuation and kinsoku-start into preceding text segment\n\tconst mergedTexts: string[] = [];\n\tconst mergedKinds: SegmentBreakKind[] = [];\n\tconst mergedWordLike: boolean[] = [];\n\n\tfor (let i = 0; i < rawTexts.length; i++) {\n\t\tconst t = rawTexts[i]!;\n\t\tconst k = rawKinds[i]!;\n\t\tconst wl = rawWordLike[i]!;\n\n\t\t// Merge left-sticky punctuation into preceding text\n\t\tif (\n\t\t\tk === \"text\" &&\n\t\t\t!wl &&\n\t\t\tmergedTexts.length > 0 &&\n\t\t\tmergedKinds[mergedKinds.length - 1] === \"text\"\n\t\t) {\n\t\t\tconst isSticky = t.length === 1 && (leftStickyPunctuation.has(t) || kinsokuStart.has(t));\n\t\t\tif (isSticky) {\n\t\t\t\tmergedTexts[mergedTexts.length - 1] += t;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// Merge hyphen after word into preceding text (\"well-known\" stays together)\n\t\tif (\n\t\t\tt === \"-\" &&\n\t\t\tmergedTexts.length > 0 &&\n\t\t\tmergedKinds[mergedKinds.length - 1] === \"text\" &&\n\t\t\tmergedWordLike[mergedWordLike.length - 1]\n\t\t) {\n\t\t\tmergedTexts[mergedTexts.length - 1] += t;\n\t\t\tcontinue;\n\t\t}\n\n\t\tmergedTexts.push(t);\n\t\tmergedKinds.push(k);\n\t\tmergedWordLike.push(wl);\n\t}\n\n\t// Get or create font-specific cache\n\tlet fontCache = cache.get(font);\n\tif (!fontCache) {\n\t\tfontCache = new Map<string, number>();\n\t\tcache.set(font, fontCache);\n\t}\n\n\tfunction measureCached(seg: string): number {\n\t\tlet w = fontCache!.get(seg);\n\t\tif (w === undefined) {\n\t\t\tif (stats) stats.misses += 1;\n\t\t\tconst raw = adapter.measureSegment(seg, font).width;\n\t\t\t// Coerce adapter misbehavior (NaN / Infinity / negative) to 0 — downstream\n\t\t\t// arithmetic would propagate NaN widths, breaking line-break decisions and\n\t\t\t// rendering. Cached so the coercion happens once per (font, segment).\n\t\t\tw = Number.isFinite(raw) && raw >= 0 ? raw : 0;\n\t\t\tfontCache!.set(seg, w);\n\t\t} else if (stats) {\n\t\t\tstats.hits += 1;\n\t\t}\n\t\treturn w;\n\t}\n\n\t// Build final prepared segments, splitting CJK into per-grapheme\n\tconst segments: PreparedSegment[] = [];\n\n\tfor (let i = 0; i < mergedTexts.length; i++) {\n\t\tconst t = mergedTexts[i]!;\n\t\tconst k = mergedKinds[i]!;\n\n\t\tif (k !== \"text\") {\n\t\t\t// Non-text segments: space, hard-break, soft-hyphen, zero-width-break\n\t\t\tsegments.push({\n\t\t\t\ttext: t,\n\t\t\t\twidth: k === \"space\" ? measureCached(\" \") * t.length : 0,\n\t\t\t\tkind: k,\n\t\t\t\tgraphemeWidths: null,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// CJK text: split into per-grapheme segments for line breaking\n\t\tif (isCJK(t)) {\n\t\t\tlet unitText = \"\";\n\t\t\tfor (const gs of graphemeSegmenter.segment(t)) {\n\t\t\t\tconst grapheme = gs.segment;\n\n\t\t\t\t// Kinsoku: line-start-prohibited chars stick to preceding unit\n\t\t\t\tif (unitText.length > 0 && kinsokuStart.has(grapheme)) {\n\t\t\t\t\tunitText += grapheme;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (unitText.length > 0) {\n\t\t\t\t\tconst w = measureCached(unitText);\n\t\t\t\t\tsegments.push({\n\t\t\t\t\t\ttext: unitText,\n\t\t\t\t\t\twidth: w,\n\t\t\t\t\t\tkind: \"text\",\n\t\t\t\t\t\tgraphemeWidths: null,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tunitText = grapheme;\n\t\t\t}\n\t\t\tif (unitText.length > 0) {\n\t\t\t\tconst w = measureCached(unitText);\n\t\t\t\tsegments.push({\n\t\t\t\t\ttext: unitText,\n\t\t\t\t\twidth: w,\n\t\t\t\t\tkind: \"text\",\n\t\t\t\t\tgraphemeWidths: null,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Non-CJK text: measure whole segment, pre-compute grapheme widths for break-word\n\t\tconst w = measureCached(t);\n\t\tlet graphemeWidths: number[] | null = null;\n\n\t\tif (mergedWordLike[i] && t.length > 1) {\n\t\t\tconst gWidths: number[] = [];\n\t\t\tfor (const gs of graphemeSegmenter.segment(t)) {\n\t\t\t\tgWidths.push(measureCached(gs.segment));\n\t\t\t}\n\t\t\tif (gWidths.length > 1) {\n\t\t\t\tgraphemeWidths = gWidths;\n\t\t\t}\n\t\t}\n\n\t\tsegments.push({ text: t, width: w, kind: \"text\", graphemeWidths });\n\t}\n\n\treturn segments;\n}\n\n// ---------------------------------------------------------------------------\n// Line breaking (greedy, ported from Pretext line-break.ts — core subset)\n// ---------------------------------------------------------------------------\n\n/**\n * Greedy line-breaking algorithm.\n *\n * Walks segments left to right, accumulating width. Breaks when a segment would\n * overflow maxWidth. Supports:\n * - Trailing space hang (spaces don't trigger breaks)\n * - overflow-wrap: break-word via grapheme widths\n * - Soft hyphens (break opportunity, adds visible hyphen width)\n * - Hard breaks (forced newline)\n */\nexport function computeLineBreaks(\n\tsegments: PreparedSegment[],\n\tmaxWidth: number,\n\tadapter: MeasurementAdapter,\n\tfont: string,\n\tcache: Map<string, Map<string, number>>,\n): LineBreaksResult {\n\tif (segments.length === 0) {\n\t\treturn { lines: [], lineCount: 0 };\n\t}\n\n\tconst lines: LayoutLine[] = [];\n\tlet lineW = 0;\n\tlet hasContent = false;\n\tlet lineStartSeg = 0;\n\tlet lineStartGrapheme = 0;\n\tlet lineEndSeg = 0;\n\tlet lineEndGrapheme = 0;\n\tlet pendingBreakSeg = -1;\n\tlet pendingBreakWidth = 0;\n\n\t// Measure hyphen for soft-hyphen support\n\tlet fontCache = cache.get(font);\n\tif (!fontCache) {\n\t\tfontCache = new Map<string, number>();\n\t\tcache.set(font, fontCache);\n\t}\n\tlet hyphenWidth = fontCache.get(\"-\");\n\tif (hyphenWidth === undefined) {\n\t\thyphenWidth = adapter.measureSegment(\"-\", font).width;\n\t\tfontCache.set(\"-\", hyphenWidth);\n\t}\n\n\tfunction flushLine(endSeg = lineEndSeg, endGrapheme = lineEndGrapheme, width = lineW) {\n\t\t// Build line text\n\t\tlet text = \"\";\n\t\tfor (let i = lineStartSeg; i < endSeg; i++) {\n\t\t\tconst seg = segments[i]!;\n\t\t\tif (seg.kind === \"soft-hyphen\" || seg.kind === \"hard-break\") continue;\n\t\t\tif (i === lineStartSeg && lineStartGrapheme > 0 && seg.graphemeWidths) {\n\t\t\t\t// Partial segment from grapheme break\n\t\t\t\tconst graphemeSegmenter = new Intl.Segmenter(undefined, {\n\t\t\t\t\tgranularity: \"grapheme\",\n\t\t\t\t});\n\t\t\t\tconst graphemes = [...graphemeSegmenter.segment(seg.text)].map((g) => g.segment);\n\t\t\t\ttext += graphemes.slice(lineStartGrapheme).join(\"\");\n\t\t\t} else {\n\t\t\t\ttext += seg.text;\n\t\t\t}\n\t\t}\n\t\t// Handle partial end segment\n\t\tif (endGrapheme > 0 && endSeg < segments.length) {\n\t\t\tconst seg = segments[endSeg]!;\n\t\t\tconst graphemeSegmenter = new Intl.Segmenter(undefined, {\n\t\t\t\tgranularity: \"grapheme\",\n\t\t\t});\n\t\t\tconst graphemes = [...graphemeSegmenter.segment(seg.text)].map((g) => g.segment);\n\t\t\tconst startG = lineStartSeg === endSeg ? lineStartGrapheme : 0;\n\t\t\ttext += graphemes.slice(startG, endGrapheme).join(\"\");\n\t\t}\n\t\t// Add visible hyphen if line ends at soft-hyphen\n\t\tif (\n\t\t\tendSeg > 0 &&\n\t\t\tsegments[endSeg - 1]?.kind === \"soft-hyphen\" &&\n\t\t\t!(lineStartSeg === endSeg && lineStartGrapheme > 0)\n\t\t) {\n\t\t\ttext += \"-\";\n\t\t}\n\n\t\tlines.push({\n\t\t\ttext,\n\t\t\twidth,\n\t\t\tstartSegment: lineStartSeg,\n\t\t\tstartGrapheme: lineStartGrapheme,\n\t\t\tendSegment: endSeg,\n\t\t\tendGrapheme,\n\t\t});\n\t\tlineW = 0;\n\t\thasContent = false;\n\t\tpendingBreakSeg = -1;\n\t\tpendingBreakWidth = 0;\n\t}\n\n\tfunction canBreakAfter(kind: SegmentBreakKind): boolean {\n\t\treturn kind === \"space\" || kind === \"zero-width-break\" || kind === \"soft-hyphen\";\n\t}\n\n\tfunction startLine(segIdx: number, graphemeIdx: number, width: number) {\n\t\thasContent = true;\n\t\tlineStartSeg = segIdx;\n\t\tlineStartGrapheme = graphemeIdx;\n\t\tlineEndSeg = segIdx + 1;\n\t\tlineEndGrapheme = 0;\n\t\tlineW = width;\n\t}\n\n\tfunction startLineAtGrapheme(segIdx: number, graphemeIdx: number, width: number) {\n\t\thasContent = true;\n\t\tlineStartSeg = segIdx;\n\t\tlineStartGrapheme = graphemeIdx;\n\t\tlineEndSeg = segIdx;\n\t\tlineEndGrapheme = graphemeIdx + 1;\n\t\tlineW = width;\n\t}\n\n\tfor (let i = 0; i < segments.length; i++) {\n\t\tconst seg = segments[i]!;\n\n\t\t// Hard break: emit current line, start fresh\n\t\tif (seg.kind === \"hard-break\") {\n\t\t\tif (hasContent) {\n\t\t\t\tflushLine();\n\t\t\t} else {\n\t\t\t\t// Empty line\n\t\t\t\tlines.push({\n\t\t\t\t\ttext: \"\",\n\t\t\t\t\twidth: 0,\n\t\t\t\t\tstartSegment: i,\n\t\t\t\t\tstartGrapheme: 0,\n\t\t\t\t\tendSegment: i,\n\t\t\t\t\tendGrapheme: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t\tlineStartSeg = i + 1;\n\t\t\tlineStartGrapheme = 0;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst w = seg.width;\n\n\t\tif (!hasContent) {\n\t\t\t// First content on a new line\n\t\t\tif (w > maxWidth && seg.graphemeWidths) {\n\t\t\t\t// Word wider than maxWidth: break at grapheme level\n\t\t\t\tappendBreakableSegment(i, 0, seg.graphemeWidths);\n\t\t\t} else {\n\t\t\t\tstartLine(i, 0, w);\n\t\t\t}\n\t\t\tif (canBreakAfter(seg.kind)) {\n\t\t\t\tpendingBreakSeg = i + 1;\n\t\t\t\tpendingBreakWidth = seg.kind === \"space\" ? lineW - w : lineW;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst newW = lineW + w;\n\n\t\tif (newW > maxWidth + 0.005) {\n\t\t\t// Overflow\n\t\t\tif (canBreakAfter(seg.kind)) {\n\t\t\t\t// Trailing space: hang past edge, then break\n\t\t\t\tlineW += w;\n\t\t\t\tlineEndSeg = i + 1;\n\t\t\t\tlineEndGrapheme = 0;\n\t\t\t\tflushLine(i + 1, 0, seg.kind === \"space\" ? lineW - w : lineW);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (pendingBreakSeg >= 0) {\n\t\t\t\t// Break at last break opportunity\n\t\t\t\tflushLine(pendingBreakSeg, 0, pendingBreakWidth);\n\t\t\t\t// Don't advance i — re-process current segment on new line\n\t\t\t\ti--;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (w > maxWidth && seg.graphemeWidths) {\n\t\t\t\t// Break-word: split at grapheme level\n\t\t\t\tflushLine();\n\t\t\t\tappendBreakableSegment(i, 0, seg.graphemeWidths);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// No break opportunity: force break before this segment\n\t\t\tflushLine();\n\t\t\ti--;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Fits on current line\n\t\tlineW = newW;\n\t\tlineEndSeg = i + 1;\n\t\tlineEndGrapheme = 0;\n\n\t\tif (canBreakAfter(seg.kind)) {\n\t\t\tpendingBreakSeg = i + 1;\n\t\t\tpendingBreakWidth = seg.kind === \"space\" ? lineW - w : lineW;\n\t\t}\n\t}\n\n\tif (hasContent) {\n\t\tflushLine();\n\t}\n\n\treturn { lines, lineCount: lines.length };\n\n\tfunction appendBreakableSegment(segIdx: number, startG: number, gWidths: number[]) {\n\t\tfor (let g = startG; g < gWidths.length; g++) {\n\t\t\tconst gw = gWidths[g]!;\n\t\t\tif (!hasContent) {\n\t\t\t\tstartLineAtGrapheme(segIdx, g, gw);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (lineW + gw > maxWidth + 0.005) {\n\t\t\t\tflushLine();\n\t\t\t\tstartLineAtGrapheme(segIdx, g, gw);\n\t\t\t} else {\n\t\t\t\tlineW += gw;\n\t\t\t\tlineEndSeg = segIdx;\n\t\t\t\tlineEndGrapheme = g + 1;\n\t\t\t}\n\t\t}\n\t\t// If we consumed the whole segment, advance end past it\n\t\tif (hasContent && lineEndSeg === segIdx && lineEndGrapheme === gWidths.length) {\n\t\t\tlineEndSeg = segIdx + 1;\n\t\t\tlineEndGrapheme = 0;\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Cursor-based single-line layout (for multi-column flow / shape wrapping)\n// ---------------------------------------------------------------------------\n\nfunction canBreakAfter(kind: SegmentBreakKind): boolean {\n\treturn kind === \"space\" || kind === \"zero-width-break\" || kind === \"soft-hyphen\";\n}\n\n// Module-scoped segmenter — `Intl.Segmenter` construction is non-trivial and\n// its `segment()` method is stateless per-call, so one shared instance is safe\n// and avoids ~N-per-frame allocations when many lines cross segment boundaries.\nlet _graphemeSegmenter: Intl.Segmenter | null = null;\nfunction graphemeSegmenter(): Intl.Segmenter {\n\tif (_graphemeSegmenter === null) {\n\t\t_graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\t}\n\treturn _graphemeSegmenter;\n}\n\nfunction sliceSegmentText(seg: PreparedSegment, startG: number, endG: number): string {\n\tif (startG === 0 && endG < 0) return seg.text;\n\tconst graphemes = [...graphemeSegmenter().segment(seg.text)].map((g) => g.segment);\n\tconst stop = endG < 0 ? graphemes.length : endG;\n\treturn graphemes.slice(startG, stop).join(\"\");\n}\n\nfunction buildLineText(\n\tsegments: PreparedSegment[],\n\tstartSeg: number,\n\tstartG: number,\n\tendSeg: number,\n\tendG: number,\n\tappendHyphen: boolean,\n): string {\n\tlet text = \"\";\n\tfor (let i = startSeg; i < endSeg; i++) {\n\t\tconst seg = segments[i]!;\n\t\tif (seg.kind === \"soft-hyphen\" || seg.kind === \"hard-break\") continue;\n\t\tif (i === startSeg && startG > 0) {\n\t\t\ttext += sliceSegmentText(seg, startG, -1);\n\t\t} else {\n\t\t\ttext += seg.text;\n\t\t}\n\t}\n\tif (endG > 0 && endSeg < segments.length) {\n\t\tconst seg = segments[endSeg]!;\n\t\tconst from = startSeg === endSeg ? startG : 0;\n\t\ttext += sliceSegmentText(seg, from, endG);\n\t}\n\tif (appendHyphen) text += \"-\";\n\treturn text;\n}\n\nfunction resolveHyphenWidth(ctx: LayoutNextLineContext | undefined): number {\n\tif (!ctx?.adapter || !ctx.font) return 0;\n\tconst cache = ctx.cache;\n\tif (cache) {\n\t\tlet fc = cache.get(ctx.font);\n\t\tif (!fc) {\n\t\t\tfc = new Map<string, number>();\n\t\t\tcache.set(ctx.font, fc);\n\t\t}\n\t\tlet hw = fc.get(\"-\");\n\t\tif (hw === undefined) {\n\t\t\thw = ctx.adapter.measureSegment(\"-\", ctx.font).width;\n\t\t\tfc.set(\"-\", hw);\n\t\t}\n\t\treturn hw;\n\t}\n\treturn ctx.adapter.measureSegment(\"-\", ctx.font).width;\n}\n\n/**\n * Lay out the next single line starting from `cursor`, fitting into `slotWidth`.\n *\n * Unlike `computeLineBreaks`, which consumes whole text with one `maxWidth`,\n * this is the cursor-based primitive needed when successive lines have different\n * widths (multi-column flow, text wrapping around shape obstacles, mixed\n * column+pullquote layouts).\n *\n * Returns `null` when the cursor is past all segments (text exhausted).\n * At a hard-break with no preceding content, returns an empty line and advances\n * the cursor past the break so the caller can continue.\n *\n * ```ts\n * let cursor: LayoutCursor = { segmentIndex: 0, graphemeIndex: 0 };\n * while (true) {\n * const line = layoutNextLine(segments, cursor, availableWidth);\n * if (line === null) break;\n * render(line);\n * cursor = line.end;\n * }\n * ```\n */\nexport function layoutNextLine(\n\tsegments: PreparedSegment[],\n\tcursor: LayoutCursor,\n\tslotWidth: number,\n\tctx?: LayoutNextLineContext,\n): LayoutNextLineResult | null {\n\tlet i = cursor.segmentIndex;\n\tconst initialG = cursor.graphemeIndex;\n\n\tif (i >= segments.length) return null;\n\n\tif (initialG === 0) {\n\t\twhile (i < segments.length) {\n\t\t\tconst seg = segments[i]!;\n\t\t\tif (seg.kind === \"hard-break\") {\n\t\t\t\treturn {\n\t\t\t\t\ttext: \"\",\n\t\t\t\t\twidth: 0,\n\t\t\t\t\tstart: { segmentIndex: cursor.segmentIndex, graphemeIndex: 0 },\n\t\t\t\t\tend: { segmentIndex: i + 1, graphemeIndex: 0 },\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (seg.kind === \"space\" || seg.kind === \"zero-width-break\" || seg.kind === \"soft-hyphen\") {\n\t\t\t\ti += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (i >= segments.length) return null;\n\t}\n\n\tconst hyphenWidth = resolveHyphenWidth(ctx);\n\n\tconst startSeg = i;\n\tconst startG = i === cursor.segmentIndex ? initialG : 0;\n\n\tlet lineW = 0;\n\tlet lineEndSeg = startSeg;\n\tlet lineEndG = 0;\n\tlet hasContent = false;\n\tlet pendingBreakSeg = -1;\n\tlet pendingBreakG = 0;\n\tlet pendingBreakWidth = 0;\n\tlet pendingBreakSoftHyphen = false;\n\n\tconst recordPending = (\n\t\tsIdx: number,\n\t\tgIdx: number,\n\t\twidthAtBreak: number,\n\t\tkind: SegmentBreakKind,\n\t): void => {\n\t\tpendingBreakSeg = sIdx;\n\t\tpendingBreakG = gIdx;\n\t\tpendingBreakWidth = widthAtBreak;\n\t\tpendingBreakSoftHyphen = kind === \"soft-hyphen\";\n\t};\n\n\tconst consumeBreakable = (segIdx: number, gStart: number, gWidths: number[]): boolean => {\n\t\tfor (let g = gStart; g < gWidths.length; g++) {\n\t\t\tconst gw = gWidths[g]!;\n\t\t\tif (!hasContent) {\n\t\t\t\tlineW = gw;\n\t\t\t\tlineEndSeg = segIdx;\n\t\t\t\tlineEndG = g + 1;\n\t\t\t\thasContent = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (lineW + gw > slotWidth + 0.005) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tlineW += gw;\n\t\t\tlineEndSeg = segIdx;\n\t\t\tlineEndG = g + 1;\n\t\t}\n\t\tif (lineEndSeg === segIdx && lineEndG === gWidths.length) {\n\t\t\tlineEndSeg = segIdx + 1;\n\t\t\tlineEndG = 0;\n\t\t}\n\t\treturn false;\n\t};\n\n\tif (startG > 0 && startSeg < segments.length) {\n\t\tconst seg = segments[startSeg]!;\n\t\tif (seg.graphemeWidths) {\n\t\t\tconst overflowed = consumeBreakable(startSeg, startG, seg.graphemeWidths);\n\t\t\tif (overflowed) {\n\t\t\t\tconst text = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);\n\t\t\t\treturn {\n\t\t\t\t\ttext,\n\t\t\t\t\twidth: lineW,\n\t\t\t\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\t\t\t\tend: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG },\n\t\t\t\t};\n\t\t\t}\n\t\t\ti = lineEndSeg;\n\t\t} else {\n\t\t\t// Mid-segment cursor on a non-breakable segment is an invariant\n\t\t\t// violation (cursor should only advance to a grapheme boundary via\n\t\t\t// `consumeBreakable` on a segment that HAS graphemeWidths). Treat as\n\t\t\t// segment-start so the caller gets well-formed output instead of\n\t\t\t// silently re-including the prefix.\n\t\t\t//\n\t\t\t// Not reachable through `computeFlowLines` but possible with\n\t\t\t// externally-constructed cursors.\n\t\t}\n\t}\n\n\tfor (; i < segments.length; ) {\n\t\tconst seg = segments[i]!;\n\n\t\tif (seg.kind === \"hard-break\") {\n\t\t\tif (hasContent) {\n\t\t\t\tconst endsAtSoftHyphen = lineEndSeg > 0 && segments[lineEndSeg - 1]?.kind === \"soft-hyphen\";\n\t\t\t\tconst text = buildLineText(\n\t\t\t\t\tsegments,\n\t\t\t\t\tstartSeg,\n\t\t\t\t\tstartG,\n\t\t\t\t\tlineEndSeg,\n\t\t\t\t\tlineEndG,\n\t\t\t\t\tendsAtSoftHyphen,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\ttext,\n\t\t\t\t\twidth: lineW + (endsAtSoftHyphen ? hyphenWidth : 0),\n\t\t\t\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\t\t\t\tend: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG },\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttext: \"\",\n\t\t\t\twidth: 0,\n\t\t\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\t\t\tend: { segmentIndex: i + 1, graphemeIndex: 0 },\n\t\t\t};\n\t\t}\n\n\t\tconst w = seg.width;\n\n\t\tif (!hasContent) {\n\t\t\tif (w > slotWidth && seg.graphemeWidths) {\n\t\t\t\tconst overflowed = consumeBreakable(i, 0, seg.graphemeWidths);\n\t\t\t\tif (overflowed) {\n\t\t\t\t\tconst text = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttext,\n\t\t\t\t\t\twidth: lineW,\n\t\t\t\t\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\t\t\t\t\tend: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t// No `recordPending` here: segments with `graphemeWidths` are always\n\t\t\t\t// `kind === \"text\"` (see `analyzeAndMeasure`), which is not a break-\n\t\t\t\t// after kind, so the check would always fail.\n\t\t\t\ti = lineEndSeg;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlineW = w;\n\t\t\tlineEndSeg = i + 1;\n\t\t\tlineEndG = 0;\n\t\t\thasContent = true;\n\t\t\tif (canBreakAfter(seg.kind)) {\n\t\t\t\trecordPending(i + 1, 0, seg.kind === \"space\" ? lineW - w : lineW, seg.kind);\n\t\t\t}\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst newW = lineW + w;\n\n\t\tif (newW > slotWidth + 0.005) {\n\t\t\tif (canBreakAfter(seg.kind)) {\n\t\t\t\t// `lineW` is carried from before this segment — no mutation needed;\n\t\t\t\t// trailing space/soft-hyphen width is excluded from the line width.\n\t\t\t\tlineEndSeg = i + 1;\n\t\t\t\tlineEndG = 0;\n\t\t\t\tconst endsAtSoftHyphen = seg.kind === \"soft-hyphen\";\n\t\t\t\tconst finalWidth =\n\t\t\t\t\tseg.kind === \"space\" ? lineW : lineW + (endsAtSoftHyphen ? hyphenWidth : 0);\n\t\t\t\tconst text = buildLineText(\n\t\t\t\t\tsegments,\n\t\t\t\t\tstartSeg,\n\t\t\t\t\tstartG,\n\t\t\t\t\tlineEndSeg,\n\t\t\t\t\tlineEndG,\n\t\t\t\t\tendsAtSoftHyphen,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\ttext,\n\t\t\t\t\twidth: finalWidth,\n\t\t\t\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\t\t\t\tend: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (pendingBreakSeg >= 0) {\n\t\t\t\tconst text = buildLineText(\n\t\t\t\t\tsegments,\n\t\t\t\t\tstartSeg,\n\t\t\t\t\tstartG,\n\t\t\t\t\tpendingBreakSeg,\n\t\t\t\t\tpendingBreakG,\n\t\t\t\t\tpendingBreakSoftHyphen,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\ttext,\n\t\t\t\t\twidth: pendingBreakWidth + (pendingBreakSoftHyphen ? hyphenWidth : 0),\n\t\t\t\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\t\t\t\tend: { segmentIndex: pendingBreakSeg, graphemeIndex: pendingBreakG },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (w > slotWidth && seg.graphemeWidths) {\n\t\t\t\tconst text = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);\n\t\t\t\treturn {\n\t\t\t\t\ttext,\n\t\t\t\t\twidth: lineW,\n\t\t\t\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\t\t\t\tend: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst text = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);\n\t\t\treturn {\n\t\t\t\ttext,\n\t\t\t\twidth: lineW,\n\t\t\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\t\t\tend: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG },\n\t\t\t};\n\t\t}\n\n\t\tlineW = newW;\n\t\tlineEndSeg = i + 1;\n\t\tlineEndG = 0;\n\t\tif (canBreakAfter(seg.kind)) {\n\t\t\trecordPending(i + 1, 0, seg.kind === \"space\" ? lineW - w : lineW, seg.kind);\n\t\t}\n\t\ti += 1;\n\t}\n\n\tif (!hasContent) return null;\n\n\tconst endsAtSoftHyphen = lineEndSeg > 0 && segments[lineEndSeg - 1]?.kind === \"soft-hyphen\";\n\tconst text = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, endsAtSoftHyphen);\n\treturn {\n\t\ttext,\n\t\twidth: lineW + (endsAtSoftHyphen ? hyphenWidth : 0),\n\t\tstart: { segmentIndex: startSeg, graphemeIndex: startG },\n\t\tend: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG },\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Slot carving (flow-layout helper)\n// ---------------------------------------------------------------------------\n\n/**\n * Subtract blocked horizontal intervals from a base interval, producing\n * remaining ordered, non-overlapping slots wide enough to fit text.\n *\n * Pure geometry — no text dependency. Used by flow-layout to turn obstacle\n * intersections into per-line layout slots.\n *\n * ```ts\n * carveTextLineSlots({left: 0, right: 600}, [{left: 200, right: 280}])\n * // → [{left: 0, right: 200}, {left: 280, right: 600}]\n * ```\n */\nexport function carveTextLineSlots(\n\tbase: Interval,\n\tblocked: Interval[],\n\tminSlotWidth = 0,\n): Interval[] {\n\tlet slots: Interval[] = [base];\n\tfor (let bi = 0; bi < blocked.length; bi++) {\n\t\tconst block = blocked[bi]!;\n\t\tconst next: Interval[] = [];\n\t\tfor (let si = 0; si < slots.length; si++) {\n\t\t\tconst slot = slots[si]!;\n\t\t\tif (block.right <= slot.left || block.left >= slot.right) {\n\t\t\t\tnext.push(slot);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (block.left > slot.left) next.push({ left: slot.left, right: block.left });\n\t\t\tif (block.right < slot.right) next.push({ left: block.right, right: slot.right });\n\t\t}\n\t\tslots = next;\n\t}\n\tif (minSlotWidth > 0) {\n\t\treturn slots.filter((s) => s.right - s.left >= minSlotWidth);\n\t}\n\treturn slots;\n}\n\n// ---------------------------------------------------------------------------\n// Character positions\n// ---------------------------------------------------------------------------\n\n/** Compute per-character x,y positions from line breaks and segments. */\nexport function computeCharPositions(\n\tlineBreaks: LineBreaksResult,\n\tsegments: PreparedSegment[],\n\tlineHeight: number,\n): CharPosition[] {\n\tconst positions: CharPosition[] = [];\n\tconst graphemeSegmenter = new Intl.Segmenter(undefined, {\n\t\tgranularity: \"grapheme\",\n\t});\n\n\tfor (let lineIdx = 0; lineIdx < lineBreaks.lines.length; lineIdx++) {\n\t\tconst line = lineBreaks.lines[lineIdx]!;\n\t\tconst y = lineIdx * lineHeight;\n\t\tlet x = 0;\n\n\t\tfor (let si = line.startSegment; si < segments.length; si++) {\n\t\t\tconst seg = segments[si]!;\n\t\t\tif (seg.kind === \"soft-hyphen\" || seg.kind === \"hard-break\") {\n\t\t\t\t// Skip non-visual segments but stop if past the line\n\t\t\t\tif (si >= line.endSegment && line.endGrapheme === 0) break;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst graphemes = [...graphemeSegmenter.segment(seg.text)].map((g) => g.segment);\n\t\t\tif (graphemes.length === 0) continue;\n\t\t\tconst startG = si === line.startSegment ? line.startGrapheme : 0;\n\n\t\t\t// Determine how many graphemes of this segment belong to this line\n\t\t\tlet endG: number;\n\t\t\tif (si < line.endSegment) {\n\t\t\t\t// Full segment is on this line\n\t\t\t\tendG = graphemes.length;\n\t\t\t} else if (si === line.endSegment && line.endGrapheme > 0) {\n\t\t\t\t// Partial segment (grapheme-level break)\n\t\t\t\tendG = line.endGrapheme;\n\t\t\t} else {\n\t\t\t\t// Past the line's content\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tfor (let g = startG; g < endG; g++) {\n\t\t\t\tconst gWidth = seg.graphemeWidths ? seg.graphemeWidths[g]! : seg.width / graphemes.length;\n\t\t\t\tpositions.push({ x, y, width: gWidth, height: lineHeight, line: lineIdx });\n\t\t\t\tx += gWidth;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn positions;\n}\n\n// ---------------------------------------------------------------------------\n// Reactive graph factory\n// ---------------------------------------------------------------------------\n\nexport type ReactiveLayoutOptions = {\n\t/** Measurement backend (required). */\n\tadapter: MeasurementAdapter;\n\t/** Graph name (default: \"reactive-layout\"). */\n\tname?: string;\n\t/** Initial text. */\n\ttext?: string;\n\t/** Initial CSS font string. */\n\tfont?: string;\n\t/** Initial line height in px. */\n\tlineHeight?: number;\n\t/** Initial max width in px (clamped to ≥ 0). */\n\tmaxWidth?: number;\n};\n\n/**\n * Create a reactive text layout graph.\n *\n * ```\n * Graph(\"reactive-layout\")\n * ├── node([], { initial: \"text\" })\n * ├── node([], { initial: \"font\" })\n * ├── node([], { initial: \"line-height\" })\n * ├── node([], { initial: \"max-width\" })\n * ├── derived(\"segments\") — text + font → PreparedSegment[]\n * ├── derived(\"line-breaks\") — segments + max-width → LineBreaksResult\n * ├── derived(\"height\") — line-breaks → number\n * └── derived(\"char-positions\") — line-breaks + segments → CharPosition[]\n * ```\n */\nexport function reactiveLayout(opts: ReactiveLayoutOptions): ReactiveLayoutBundle {\n\tconst { adapter, name = \"reactive-layout\" } = opts;\n\tconst g = new Graph(name);\n\n\t// Shared measurement cache: Map<font, Map<segment, width>>\n\tconst measureCache = new Map<string, Map<string, number>>();\n\n\t// --- State nodes ---\n\tconst textNode = node<string>([], { name: \"text\", initial: opts.text ?? \"\" });\n\tconst fontNode = node<string>([], {\n\t\tname: \"font\",\n\t\tinitial: opts.font ?? \"16px sans-serif\",\n\t});\n\tconst lineHeightNode = node<number>([], {\n\t\tname: \"line-height\",\n\t\tinitial: opts.lineHeight ?? 20,\n\t});\n\tconst maxWidthNode = node<number>([], {\n\t\tname: \"max-width\",\n\t\tinitial: Math.max(0, opts.maxWidth ?? 800),\n\t});\n\n\t// --- Derived: segments (text + font → PreparedSegment[]) ---\n\tfunction graphemeWidthsEqual(a: number[] | null, b: number[] | null): boolean {\n\t\tif (a === null || b === null) return a === b;\n\t\tif (a.length !== b.length) return false;\n\t\tfor (let i = 0; i < a.length; i++) {\n\t\t\tif (a[i] !== b[i]!) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// Raw `node(...)` instead of `derived(...)` so the fn can return a\n\t// cleanup function. Core fires function-form cleanup on INVALIDATE (see\n\t// `node.ts:_updateState` INVALIDATE branch), which replaces the old v4\n\t// per-node `onMessage` hook that watched for INVALIDATE/TEARDOWN to flush\n\t// measurement caches.\n\tconst segmentsNode: Node<PreparedSegment[]> = node<PreparedSegment[]>(\n\t\t[textNode, fontNode],\n\t\t(data, actions, ctx) => {\n\t\t\tconst b0 = data[0];\n\t\t\tconst textVal = (b0 != null && b0.length > 0 ? b0.at(-1) : ctx.prevData[0]) as string;\n\t\t\tconst b1 = data[1];\n\t\t\tconst fontVal = (b1 != null && b1.length > 0 ? b1.at(-1) : ctx.prevData[1]) as string;\n\t\t\tconst t0 = monotonicNs();\n\t\t\tconst measureStats: SegmentMeasureStats = { hits: 0, misses: 0 };\n\t\t\tconst result = analyzeAndMeasure(\n\t\t\t\ttextVal as string,\n\t\t\t\tfontVal as string,\n\t\t\t\tadapter,\n\t\t\t\tmeasureCache,\n\t\t\t\tmeasureStats,\n\t\t\t);\n\t\t\tconst elapsed = monotonicNs() - t0;\n\n\t\t\tconst lookups = measureStats.hits + measureStats.misses;\n\t\t\tconst hitRate = lookups === 0 ? 1 : measureStats.hits / lookups;\n\n\t\t\t// After parent `segments` emits, deliver metrics via phase-3 deferral\n\t\t\t// so observers see the parent value first.\n\t\t\t// Forwards via `emitToMeta` (see `patterns/_internal.ts`).\n\t\t\tconst meta = segmentsNode.meta;\n\t\t\tif (meta) {\n\t\t\t\temitToMeta(meta[\"cache-hit-rate\"], hitRate);\n\t\t\t\temitToMeta(meta[\"segment-count\"], result.length);\n\t\t\t\temitToMeta(meta[\"layout-time-ns\"], elapsed);\n\t\t\t}\n\n\t\t\tactions.emit(result);\n\n\t\t\t// Object-form cleanup: fires on deactivation AND on INVALIDATE, but\n\t\t\t// NOT before re-runs. Re-runs that edit text / font retain the\n\t\t\t// measurement cache — the per-segment entries still valid for the\n\t\t\t// new text overlap the previous set and are reused. Before-run\n\t\t\t// flushing (previous behaviour) wiped 100-segment caches on a\n\t\t\t// one-character edit; this shape keeps cache hit-rate proportional\n\t\t\t// to content overlap rather than invalidation frequency.\n\t\t\tconst flush = (): void => {\n\t\t\t\tmeasureCache.clear();\n\t\t\t\tadapter.clearCache?.();\n\t\t\t};\n\t\t\treturn { onDeactivation: flush, onInvalidate: flush };\n\t\t},\n\t\t{\n\t\t\tname: \"segments\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: {\n\t\t\t\t\"cache-hit-rate\": 0,\n\t\t\t\t\"segment-count\": 0,\n\t\t\t\t\"layout-time-ns\": 0,\n\t\t\t},\n\t\t\tequals: (a, b) => {\n\t\t\t\tconst sa = a as PreparedSegment[] | null;\n\t\t\t\tconst sb = b as PreparedSegment[] | null;\n\t\t\t\tif (sa == null || sb == null) return sa === sb;\n\t\t\t\tif (sa.length !== sb.length) return false;\n\t\t\t\tfor (let i = 0; i < sa.length; i++) {\n\t\t\t\t\tconst pa = sa[i]!;\n\t\t\t\t\tconst pb = sb[i]!;\n\t\t\t\t\tif (\n\t\t\t\t\t\tpa.text !== pb.text ||\n\t\t\t\t\t\tpa.width !== pb.width ||\n\t\t\t\t\t\tpa.kind !== pb.kind ||\n\t\t\t\t\t\t!graphemeWidthsEqual(pa.graphemeWidths ?? null, pb.graphemeWidths ?? null)\n\t\t\t\t\t)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n\n\t// --- Derived: line-breaks (segments + max-width + font → LineBreaksResult) ---\n\tconst lineBreaksNode = node<LineBreaksResult>(\n\t\t[segmentsNode, maxWidthNode, fontNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(\n\t\t\t\tcomputeLineBreaks(\n\t\t\t\t\tdata[0] as PreparedSegment[],\n\t\t\t\t\tdata[1] as number,\n\t\t\t\t\tadapter,\n\t\t\t\t\tdata[2] as string,\n\t\t\t\t\tmeasureCache,\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\t{\n\t\t\tname: \"line-breaks\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tequals: (a, b) => {\n\t\t\t\tconst la = a as LineBreaksResult | null;\n\t\t\t\tconst lb = b as LineBreaksResult | null;\n\t\t\t\tif (la == null || lb == null) return la === lb;\n\t\t\t\tif (la.lineCount !== lb.lineCount) return false;\n\t\t\t\tfor (let i = 0; i < la.lines.length; i++) {\n\t\t\t\t\tconst lineA = la.lines[i]!;\n\t\t\t\t\tconst lineB = lb.lines[i]!;\n\t\t\t\t\tif (\n\t\t\t\t\t\tlineA.text !== lineB.text ||\n\t\t\t\t\t\tlineA.width !== lineB.width ||\n\t\t\t\t\t\tlineA.startSegment !== lineB.startSegment ||\n\t\t\t\t\t\tlineA.startGrapheme !== lineB.startGrapheme ||\n\t\t\t\t\t\tlineA.endSegment !== lineB.endSegment ||\n\t\t\t\t\t\tlineA.endGrapheme !== lineB.endGrapheme\n\t\t\t\t\t)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n\n\t// --- Derived: height ---\n\tconst heightNode = node<number>(\n\t\t[lineBreaksNode, lineHeightNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit((data[0] as LineBreaksResult).lineCount * (data[1] as number));\n\t\t},\n\t\t{ describeKind: \"derived\", name: \"height\" },\n\t);\n\n\t// --- Derived: char-positions ---\n\tconst charPositionsNode = node<CharPosition[]>(\n\t\t[lineBreaksNode, segmentsNode, lineHeightNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(\n\t\t\t\tcomputeCharPositions(\n\t\t\t\t\tdata[0] as LineBreaksResult,\n\t\t\t\t\tdata[1] as PreparedSegment[],\n\t\t\t\t\tdata[2] as number,\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\t{\n\t\t\tname: \"char-positions\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tequals: (a, b) => {\n\t\t\t\tconst ca = a as CharPosition[] | null;\n\t\t\t\tconst cb = b as CharPosition[] | null;\n\t\t\t\tif (ca == null || cb == null) return ca === cb;\n\t\t\t\tif (ca.length !== cb.length) return false;\n\t\t\t\tfor (let i = 0; i < ca.length; i++) {\n\t\t\t\t\tif (ca[i]!.x !== cb[i]!.x || ca[i]!.y !== cb[i]!.y || ca[i]!.width !== cb[i]!.width)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n\n\t// --- Register in graph ---\n\tg.add(textNode, { name: \"text\" });\n\tg.add(fontNode, { name: \"font\" });\n\tg.add(lineHeightNode, { name: \"line-height\" });\n\tg.add(maxWidthNode, { name: \"max-width\" });\n\tg.add(segmentsNode, { name: \"segments\" });\n\tg.add(lineBreaksNode, { name: \"line-breaks\" });\n\tg.add(heightNode, { name: \"height\" });\n\tg.add(charPositionsNode, { name: \"char-positions\" });\n\n\t// --- Edges (for describe() visibility) ---\n\n\treturn {\n\t\tgraph: g,\n\t\tsetText: (text: string) => g.set(\"text\", text),\n\t\tsetFont: (font: string) => g.set(\"font\", font),\n\t\tsetLineHeight: (lh: number) => g.set(\"line-height\", lh),\n\t\tsetMaxWidth: (mw: number) => g.set(\"max-width\", Math.max(0, mw)),\n\t\tsegments: segmentsNode,\n\t\tlineBreaks: lineBreaksNode,\n\t\theight: heightNode,\n\t\tcharPositions: charPositionsNode,\n\t};\n}\n","/**\n * emitToMeta — forward DATA to a meta companion node via tier-3 deferral.\n *\n * Extracted from patterns/_internal/index.ts during cleave A2.\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport { DATA, defaultConfig, downWithBatch } from \"@graphrefly/pure-ts/core\";\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","/**\n * Domain templates (roadmap §8.2).\n *\n * Opinionated Graph factories for common \"info → action\" domains.\n * Each template wires up §8.1 reduction primitives (stratify, funnel, feedback,\n * budgetGate, scorer) with domain-specific stages. Users fork/extend by\n * accessing named nodes and swapping stages.\n *\n * **Source injection (option B):** templates accept a `source` node, not a\n * hardcoded adapter. Pass `fromOTel(...)`, `fromGitHook(...)`, or a test\n * `state()` — the topology is the same.\n *\n * @module\n */\n\nimport { batch, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { reactiveLog, type StratifyRule, stratify } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { feedback, scorer } from \"../reduction/index.js\";\n\n// ---------------------------------------------------------------------------\n// Shared\n// ---------------------------------------------------------------------------\n\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\n\nfunction baseMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"domain_template\", kind, extra);\n}\n\n// ---------------------------------------------------------------------------\n// 1. observabilityGraph\n// ---------------------------------------------------------------------------\n\n/** Stratification branch config for observability signals. */\nexport type ObservabilityBranch = {\n\tname: string;\n\tclassify: (value: unknown) => boolean;\n};\n\n/** Options for {@link observabilityGraph}. */\nexport type ObservabilityGraphOptions = GraphOptions & {\n\t/** Ingested signal source (e.g. fromOTel(...) or test state). */\n\tsource: Node<unknown>;\n\n\t/**\n\t * Classification rules for signal stratification.\n\t * Default: errors / traces / metrics branches.\n\t */\n\tbranches?: ObservabilityBranch[];\n\n\t/**\n\t * Correlation function: receives stratified branch values and produces\n\t * correlated insights. Default: identity pass-through.\n\t */\n\tcorrelate?: (values: unknown[]) => unknown;\n\n\t/**\n\t * SLO verification function: returns a verification result for a\n\t * correlated insight. Default: always passes.\n\t */\n\tsloCheck?: (value: unknown) => unknown;\n\n\t/**\n\t * Scorer weights for alert prioritization. One per branch.\n\t * Default: equal weights [1, 1, 1].\n\t */\n\tweights?: number[];\n\n\t/** Max feedback iterations for false-positive learning. Default: 5. */\n\tmaxFeedbackIterations?: number;\n};\n\n/**\n * OTel ingest → stratified reduction → correlation → SLO verification →\n * alert prioritization → output.\n *\n * Well-known node names:\n * - `\"source\"` — injected signal source\n * - `\"stratify::branch/<name>\"` — per-branch classification\n * - `\"correlate\"` — cross-branch correlation\n * - `\"slo_value\"`, `\"slo_verified\"` — SLO verification pair\n * - `\"alerts\"` — scored, prioritized output\n * - `\"output\"` — final output (alias for alerts)\n *\n * @category patterns\n */\nexport function observabilityGraph(name: string, opts: ObservabilityGraphOptions): Graph {\n\tconst g = new Graph(name, opts);\n\n\t// --- Source ---\n\tg.add(opts.source, { name: \"source\" });\n\n\t// --- Stratify ---\n\tconst defaultBranches: ObservabilityBranch[] = [\n\t\t{ name: \"errors\", classify: (v) => isTagged(v, \"error\") },\n\t\t{ name: \"traces\", classify: (v) => isTagged(v, \"trace\") },\n\t\t{ name: \"metrics\", classify: (v) => isTagged(v, \"metric\") },\n\t];\n\tconst branches = opts.branches ?? defaultBranches;\n\tconst rules: StratifyRule<unknown>[] = branches.map((b) => ({\n\t\tname: b.name,\n\t\tclassify: b.classify,\n\t}));\n\tconst strat = stratify(\"stratify\", opts.source, rules);\n\tg.mount(\"stratify\", strat);\n\n\t// --- Correlate ---\n\t// Collect latest value from each branch, produce correlated output.\n\t// Wrap each branch in a derived with `initial: null` so every branch has\n\t// a seed value at subscribe time — this lets the correlate wave reach its\n\t// first-run gate even when the classifier only routes to one branch.\n\tconst branchNodes = branches.map((b) => {\n\t\ttry {\n\t\t\tconst raw = g.resolve(`stratify::branch/${b.name}`);\n\t\t\treturn node(\n\t\t\t\t[raw as Node],\n\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t\t);\n\t\t\t\t\tactions.emit(data[0]);\n\t\t\t\t},\n\t\t\t\t{ initial: null, describeKind: \"derived\" },\n\t\t\t);\n\t\t} catch {\n\t\t\treturn node<unknown>([], { initial: null });\n\t\t}\n\t});\n\tconst correlateFn = opts.correlate ?? ((vals: unknown[]) => vals);\n\tconst correlateNode = node<unknown>(\n\t\tbranchNodes as Node[],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst vals = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(correlateFn(vals as unknown[]));\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"observability\", { stage: \"correlate\" }),\n\t\t},\n\t);\n\tg.add(correlateNode, { name: \"correlate\" });\n\n\t// --- SLO verification ---\n\tconst sloCheckFn = opts.sloCheck ?? (() => ({ pass: true }));\n\tconst sloValue = node<unknown>(\n\t\t[correlateNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(data[0]);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"observability\", { stage: \"slo_value\" }),\n\t\t},\n\t);\n\tconst sloVerified = node<unknown>(\n\t\t[sloValue],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(sloCheckFn(data[0]));\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"observability\", { stage: \"slo_verified\" }),\n\t\t},\n\t);\n\tg.add(sloValue, { name: \"slo_value\" });\n\tg.add(sloVerified, { name: \"slo_verified\" });\n\n\t// --- Alert scorer ---\n\tconst weightValues = opts.weights ?? branches.map(() => 1);\n\tconst signalNodes = branchNodes.map((bn) =>\n\t\tnode<number>(\n\t\t\t[bn],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tactions.emit(data[0] != null ? 1 : 0);\n\t\t\t},\n\t\t\t{ describeKind: \"derived\" },\n\t\t),\n\t);\n\tconst weightNodes = weightValues.map((w) => node<number>([], { initial: w }));\n\tfor (let i = 0; i < signalNodes.length; i++) {\n\t\tg.add(signalNodes[i] as Node<unknown>, { name: `__signal_${i}` });\n\t\tg.add(weightNodes[i] as Node<unknown>, { name: `__weight_${i}` });\n\t}\n\tconst alerts = scorer(\n\t\tsignalNodes as ReadonlyArray<Node<number>>,\n\t\tweightNodes as ReadonlyArray<Node<number>>,\n\t);\n\tg.add(alerts as Node<unknown>, { name: \"alerts\" });\n\n\t// --- Output alias ---\n\tconst output = node<unknown>(\n\t\t[alerts as Node, sloVerified],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst vals = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit({\n\t\t\t\tscored: vals[0],\n\t\t\t\tslo: vals[1],\n\t\t\t});\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"observability\", { stage: \"output\" }),\n\t\t},\n\t);\n\tg.add(output, { name: \"output\" });\n\n\t// --- Feedback (false-positive learning) ---\n\t// SLO failures feed back to re-check with updated context.\n\tconst fbReentry = node<unknown>([], {\n\t\tinitial: null,\n\t\tmeta: baseMeta(\"observability\", { stage: \"feedback_reentry\" }),\n\t});\n\tg.add(fbReentry, { name: \"feedback_reentry\" });\n\tconst fbCondition = node<unknown>(\n\t\t[sloVerified],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst result = data[0] as Record<string, unknown> | null;\n\t\t\tactions.emit(result && result.pass === false ? result : null);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"observability\", { stage: \"feedback_condition\" }),\n\t\t},\n\t);\n\tg.add(fbCondition as Node<unknown>, { name: \"feedback_condition\" });\n\tfeedback(g, \"feedback_condition\", \"feedback_reentry\", {\n\t\tmaxIterations: opts.maxFeedbackIterations ?? 5,\n\t});\n\n\treturn g;\n}\n\n// ---------------------------------------------------------------------------\n// 2. issueTrackerGraph\n// ---------------------------------------------------------------------------\n\n/** A structured issue extracted from raw findings. */\nexport type ExtractedIssue = {\n\tid: string;\n\ttitle: string;\n\tseverity: number;\n\tsource: string;\n\traw: unknown;\n};\n\n/** Options for {@link issueTrackerGraph}. */\nexport type IssueTrackerGraphOptions = GraphOptions & {\n\t/** Findings source (e.g. fromGitHook(...), fromFSWatch(...)). */\n\tsource: Node<unknown>;\n\n\t/**\n\t * Extract structured issues from raw findings.\n\t * Default: wraps raw value as a single issue.\n\t */\n\textract?: (raw: unknown) => ExtractedIssue;\n\n\t/**\n\t * Verify an extracted issue (assertion check).\n\t * Default: always valid.\n\t */\n\tverify?: (issue: ExtractedIssue) => unknown;\n\n\t/**\n\t * Detect regression by comparing against known patterns.\n\t * Receives (current issue, known patterns).\n\t * Default: no regression detected.\n\t */\n\tdetectRegression?: (issue: ExtractedIssue, known: unknown) => unknown;\n\n\t/** Max feedback iterations for re-scanning. Default: 3. */\n\tmaxFeedbackIterations?: number;\n};\n\n/**\n * Findings ingest → extraction → verification → regression detection →\n * distillation → prioritized queue.\n *\n * Well-known node names:\n * - `\"source\"` — injected findings source\n * - `\"extract\"` — structured issue extraction\n * - `\"verify\"` — issue verification\n * - `\"known_patterns\"` — accumulated known issue patterns (state)\n * - `\"regression\"` — regression detection\n * - `\"priority\"` — severity-based prioritization\n * - `\"output\"` — final prioritized output\n *\n * @category patterns\n */\nexport function issueTrackerGraph(name: string, opts: IssueTrackerGraphOptions): Graph {\n\tconst g = new Graph(name, opts);\n\n\t// --- Source ---\n\tg.add(opts.source, { name: \"source\" });\n\n\t// --- Extract ---\n\tlet _issueCounter = 0;\n\tconst defaultExtract = (raw: unknown): ExtractedIssue => ({\n\t\tid: `issue-${++_issueCounter}`,\n\t\ttitle: String(raw),\n\t\tseverity: 1,\n\t\tsource: \"unknown\",\n\t\traw,\n\t});\n\tconst extractFn = opts.extract ?? defaultExtract;\n\tconst extractNode = node<ExtractedIssue>(\n\t\t[opts.source],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(extractFn(data[0]));\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"issue_tracker\", { stage: \"extract\" }),\n\t\t},\n\t);\n\tg.add(extractNode as Node<unknown>, { name: \"extract\" });\n\n\t// --- Verify ---\n\tconst verifyFn = opts.verify ?? (() => ({ valid: true }));\n\tconst verifyNode = node<unknown>(\n\t\t[extractNode as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst issue = data[0] as ExtractedIssue;\n\t\t\tactions.emit({ issue, verification: verifyFn(issue) });\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"issue_tracker\", { stage: \"verify\" }),\n\t\t},\n\t);\n\tg.add(verifyNode, { name: \"verify\" });\n\n\t// --- Known patterns (memory / distillation state) ---\n\tconst knownPatterns = node<unknown[]>([], {\n\t\tinitial: [],\n\t\tmeta: baseMeta(\"issue_tracker\", { stage: \"known_patterns\" }),\n\t});\n\tg.add(knownPatterns as Node<unknown>, { name: \"known_patterns\" });\n\n\t// --- Regression detection ---\n\tconst detectFn = opts.detectRegression ?? (() => ({ regression: false }));\n\tconst regressionNode = node<unknown>(\n\t\t[extractNode as Node, knownPatterns as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst issue = data[0] as ExtractedIssue;\n\t\t\tconst known = data[1];\n\t\t\tactions.emit({ issue, regression: detectFn(issue, known) });\n\t\t},\n\t\t{ describeKind: \"derived\", meta: baseMeta(\"issue_tracker\", { stage: \"regression\" }) },\n\t);\n\tg.add(regressionNode, { name: \"regression\" });\n\n\t// --- Priority scoring ---\n\tconst severitySignal = node<number>(\n\t\t[extractNode as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst issue = data[0] as ExtractedIssue;\n\t\t\tactions.emit(issue?.severity ?? 0);\n\t\t},\n\t\t{ describeKind: \"derived\" },\n\t);\n\tconst regressionSignal = node<number>(\n\t\t[regressionNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst r = data[0] as Record<string, unknown> | null;\n\t\t\tactions.emit(r?.regression ? 2 : 0);\n\t\t},\n\t\t{ describeKind: \"derived\" },\n\t);\n\tg.add(severitySignal as Node<unknown>, { name: \"__severity_signal\" });\n\tg.add(regressionSignal as Node<unknown>, { name: \"__regression_signal\" });\n\n\tconst severityWeight = node<number>([], { initial: 1 });\n\tconst regressionWeight = node<number>([], { initial: 1.5 });\n\tg.add(severityWeight as Node<unknown>, { name: \"__severity_weight\" });\n\tg.add(regressionWeight as Node<unknown>, { name: \"__regression_weight\" });\n\n\tconst priority = scorer([severitySignal, regressionSignal], [severityWeight, regressionWeight]);\n\tg.add(priority as Node<unknown>, { name: \"priority\" });\n\n\t// --- Output ---\n\tconst output = node<unknown>(\n\t\t[verifyNode, regressionNode, priority as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst vals = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit({\n\t\t\t\tverified: vals[0],\n\t\t\t\tregression: vals[1],\n\t\t\t\tpriority: vals[2],\n\t\t\t});\n\t\t},\n\t\t{ describeKind: \"derived\", meta: baseMeta(\"issue_tracker\", { stage: \"output\" }) },\n\t);\n\tg.add(output, { name: \"output\" });\n\n\t// --- Feedback (re-scan on verification failure) ---\n\tconst fbReentry = node<unknown>([], {\n\t\tinitial: null,\n\t\tmeta: baseMeta(\"issue_tracker\", { stage: \"feedback_reentry\" }),\n\t});\n\tg.add(fbReentry, { name: \"feedback_reentry\" });\n\tconst fbCondition = node<unknown>(\n\t\t[verifyNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst result = data[0] as Record<string, unknown> | null;\n\t\t\tif (result) {\n\t\t\t\tconst v = result.verification as Record<string, unknown> | null;\n\t\t\t\tif (v && v.valid === false) {\n\t\t\t\t\tactions.emit(result);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tactions.emit(null);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"issue_tracker\", { stage: \"feedback_condition\" }),\n\t\t},\n\t);\n\tg.add(fbCondition as Node<unknown>, { name: \"feedback_condition\" });\n\tfeedback(g, \"feedback_condition\", \"feedback_reentry\", {\n\t\tmaxIterations: opts.maxFeedbackIterations ?? 3,\n\t});\n\n\treturn g;\n}\n\n// ---------------------------------------------------------------------------\n// 3. contentModerationGraph\n// ---------------------------------------------------------------------------\n\n/** Classification result from LLM moderation. */\nexport type ModerationResult = {\n\tlabel: \"safe\" | \"review\" | \"block\";\n\tconfidence: number;\n\treason?: string;\n\toriginal: unknown;\n};\n\n/** Options for {@link contentModerationGraph}. */\nexport type ContentModerationGraphOptions = GraphOptions & {\n\t/** Content source (text/multimedia ingest). */\n\tsource: Node<unknown>;\n\n\t/**\n\t * Classification function: returns a ModerationResult.\n\t * Default: labels everything \"review\" with confidence 0.5.\n\t */\n\tclassify?: (content: unknown) => ModerationResult;\n\n\t/** System prompt for LLM classification. */\n\tsystemPrompt?: string;\n\n\t/** Scorer weights: [safe, review, block]. Default: [0.1, 1, 2]. */\n\tweights?: [number, number, number];\n\n\t/** Max feedback iterations for policy refinement. Default: 5. */\n\tmaxFeedbackIterations?: number;\n\n\t/** Max review queue size. When set, oldest entries are trimmed on overflow. */\n\tmaxQueueSize?: number;\n};\n\n/**\n * Content ingest → LLM/rule classification → stratified routing (safe/review/block) →\n * human review queue → scorer → feedback (false positives → policy refinement) → output.\n *\n * Well-known node names:\n * - `\"source\"` — content ingest\n * - `\"classify\"` — LLM or rule-based classification\n * - `\"stratify::branch/safe\"`, `\"stratify::branch/review\"`, `\"stratify::branch/block\"` — routed branches\n * - `\"review_queue\"` — state node for human review items\n * - `\"priority\"` — scored priority output\n * - `\"policy\"` — writable state for policy refinement\n * - `\"output\"` — final moderation output\n *\n * @category patterns\n */\nexport function contentModerationGraph(name: string, opts: ContentModerationGraphOptions): Graph {\n\tconst g = new Graph(name, opts);\n\n\t// --- Source ---\n\tg.add(opts.source, { name: \"source\" });\n\n\t// --- Classify ---\n\tconst defaultClassify = (content: unknown): ModerationResult => ({\n\t\tlabel: \"review\",\n\t\tconfidence: 0.5,\n\t\toriginal: content,\n\t});\n\tconst classifyFn = opts.classify ?? defaultClassify;\n\tconst classifyNode = node<ModerationResult>(\n\t\t[opts.source],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(classifyFn(data[0]));\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"content_moderation\", { stage: \"classify\" }),\n\t\t},\n\t);\n\tg.add(classifyNode as Node<unknown>, { name: \"classify\" });\n\n\t// --- Stratify (safe / review / block) ---\n\tconst strat = stratify<ModerationResult>(\"stratify\", classifyNode, [\n\t\t{ name: \"safe\", classify: (v) => v.label === \"safe\" },\n\t\t{ name: \"review\", classify: (v) => v.label === \"review\" },\n\t\t{ name: \"block\", classify: (v) => v.label === \"block\" },\n\t]);\n\tg.mount(\"stratify\", strat);\n\n\t// --- Review queue (reactiveLog — O(1) append, bounded) ---\n\tconst reviewLog = reactiveLog<ModerationResult>([], {\n\t\tname: \"review_queue\",\n\t\tmaxSize: opts.maxQueueSize,\n\t});\n\tg.add(reviewLog.entries as Node<unknown>, { name: \"review_queue\" });\n\n\t// Bridge review branch → review queue accumulator\n\tlet reviewBranch: Node<unknown>;\n\ttry {\n\t\treviewBranch = g.resolve(\"stratify::branch/review\");\n\t} catch {\n\t\treviewBranch = node<unknown>([], { initial: null });\n\t\tg.add(reviewBranch, { name: \"__review_fallback\" });\n\t}\n\tconst reviewAccumulator = node(\n\t\t[reviewBranch],\n\t\t(batchData, _actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst item = data[0] as ModerationResult | null;\n\t\t\tif (item) {\n\t\t\t\treviewLog.append(item);\n\t\t\t}\n\t\t},\n\t\t{ describeKind: \"effect\" },\n\t);\n\tg.add(reviewAccumulator as Node<unknown>, { name: \"__review_accumulator\" });\n\tg.addDisposer(keepalive(reviewAccumulator as Node<unknown>));\n\ttry {\n\t} catch {\n\t\t// fallback branch — no stratify edge to register\n\t}\n\n\t// --- Policy state (human/LLM writable) ---\n\tconst policy = node<Record<string, unknown>>([], {\n\t\tinitial: {},\n\t\tmeta: baseMeta(\"content_moderation\", {\n\t\t\tstage: \"policy\",\n\t\t\taccess: \"both\",\n\t\t\tdescription: \"Moderation policy rules — updated via feedback\",\n\t\t}),\n\t});\n\tg.add(policy as Node<unknown>, { name: \"policy\" });\n\n\t// --- Priority scorer ---\n\tconst weights = opts.weights ?? [0.1, 1, 2];\n\tconst confidenceSignal = node<number>(\n\t\t[classifyNode as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst r = data[0] as ModerationResult | null;\n\t\t\tactions.emit(r?.confidence ?? 0);\n\t\t},\n\t\t{ describeKind: \"derived\" },\n\t);\n\tconst severitySignal = node<number>(\n\t\t[classifyNode as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst r = data[0] as ModerationResult | null;\n\t\t\tif (!r) {\n\t\t\t\tactions.emit(0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit(\n\t\t\t\tr.label === \"block\" ? weights[2] : r.label === \"review\" ? weights[1] : weights[0],\n\t\t\t);\n\t\t},\n\t\t{ describeKind: \"derived\" },\n\t);\n\tg.add(confidenceSignal as Node<unknown>, { name: \"__confidence_signal\" });\n\tg.add(severitySignal as Node<unknown>, { name: \"__severity_signal\" });\n\n\tconst wConfidence = node<number>([], { initial: 1 });\n\tconst wSeverity = node<number>([], { initial: 1 });\n\tg.add(wConfidence as Node<unknown>, { name: \"__w_confidence\" });\n\tg.add(wSeverity as Node<unknown>, { name: \"__w_severity\" });\n\n\tconst priority = scorer([confidenceSignal, severitySignal], [wConfidence, wSeverity]);\n\tg.add(priority as Node<unknown>, { name: \"priority\" });\n\n\t// --- Output ---\n\tconst output = node<unknown>(\n\t\t[classifyNode as Node, priority as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst vals = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit({\n\t\t\t\tclassification: vals[0],\n\t\t\t\tpriority: vals[1],\n\t\t\t});\n\t\t},\n\t\t{ describeKind: \"derived\", meta: baseMeta(\"content_moderation\", { stage: \"output\" }) },\n\t);\n\tg.add(output, { name: \"output\" });\n\n\t// --- Feedback (false positive → policy refinement) ---\n\t// Feedback condition: human marks a review item as false positive.\n\t// When review_queue changes and policy exists, signal for update.\n\tconst fbCondition = node<unknown>(\n\t\t[reviewLog.entries as Node, policy as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst vals = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst entries = vals[0] as readonly ModerationResult[] | null;\n\t\t\tif (entries && entries.length > 0) {\n\t\t\t\tconst latest = entries[entries.length - 1];\n\t\t\t\t// Items explicitly marked as false positive feed back\n\t\t\t\tif (latest && (latest as unknown as Record<string, unknown>).falsePositive) {\n\t\t\t\t\tactions.emit(latest);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tactions.emit(null);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"content_moderation\", { stage: \"feedback_condition\" }),\n\t\t},\n\t);\n\tg.add(fbCondition as Node<unknown>, { name: \"feedback_condition\" });\n\tfeedback(g, \"feedback_condition\", \"policy\", {\n\t\tmaxIterations: opts.maxFeedbackIterations ?? 5,\n\t});\n\n\treturn g;\n}\n\n// ---------------------------------------------------------------------------\n// 4. dataQualityGraph\n// ---------------------------------------------------------------------------\n\n/** Schema validation result. */\nexport type ValidationResult = {\n\tvalid: boolean;\n\terrors: string[];\n\trecord: unknown;\n};\n\n/** Anomaly detection result. */\nexport type AnomalyResult = {\n\tanomaly: boolean;\n\tscore: number;\n\tdetail?: string;\n\trecord: unknown;\n};\n\n/** Options for {@link dataQualityGraph}. */\nexport type DataQualityGraphOptions = GraphOptions & {\n\t/** Data source (e.g. fromPrisma(...), fromKysely(...)). */\n\tsource: Node<unknown>;\n\n\t/**\n\t * Schema validation function.\n\t * Default: always valid.\n\t */\n\tvalidate?: (record: unknown) => ValidationResult;\n\n\t/**\n\t * Anomaly detection function.\n\t * Default: no anomaly.\n\t */\n\tdetectAnomaly?: (record: unknown) => AnomalyResult;\n\n\t/**\n\t * Drift detection: compares current record against baseline.\n\t * Default: no drift.\n\t */\n\tdetectDrift?: (record: unknown, baseline: unknown) => unknown;\n\n\t/**\n\t * Remediation suggestion function.\n\t * Default: no suggestion.\n\t */\n\tsuggest?: (result: { validation: ValidationResult; anomaly: AnomalyResult }) => unknown;\n\n\t/** Max feedback iterations for rule refinement. Default: 3. */\n\tmaxFeedbackIterations?: number;\n};\n\n/**\n * Data ingest → schema validation → anomaly detection → drift alerting →\n * auto-remediation suggestions → output.\n *\n * Well-known node names:\n * - `\"source\"` — data ingest\n * - `\"validate\"` — schema validation\n * - `\"anomaly\"` — anomaly detection\n * - `\"baseline\"` — rolling baseline state\n * - `\"drift\"` — drift detection\n * - `\"remediate\"` — auto-remediation suggestions\n * - `\"output\"` — combined quality report\n *\n * @category patterns\n */\nexport function dataQualityGraph(name: string, opts: DataQualityGraphOptions): Graph {\n\tconst g = new Graph(name, opts);\n\n\t// --- Source ---\n\tg.add(opts.source, { name: \"source\" });\n\n\t// --- Schema validation ---\n\tconst validateFn =\n\t\topts.validate ??\n\t\t((record: unknown): ValidationResult => ({\n\t\t\tvalid: true,\n\t\t\terrors: [],\n\t\t\trecord,\n\t\t}));\n\tconst validateNode = node<ValidationResult | undefined>(\n\t\t[opts.source],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(data[0] != null ? validateFn(data[0]) : undefined);\n\t\t},\n\t\t{ describeKind: \"derived\", meta: baseMeta(\"data_quality\", { stage: \"validate\" }) },\n\t);\n\tg.add(validateNode as Node<unknown>, { name: \"validate\" });\n\n\t// --- Anomaly detection ---\n\tconst detectAnomalyFn =\n\t\topts.detectAnomaly ??\n\t\t((record: unknown): AnomalyResult => ({\n\t\t\tanomaly: false,\n\t\t\tscore: 0,\n\t\t\trecord,\n\t\t}));\n\tconst anomalyNode = node<AnomalyResult | undefined>(\n\t\t[opts.source],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(data[0] != null ? detectAnomalyFn(data[0]) : undefined);\n\t\t},\n\t\t{ describeKind: \"derived\", meta: baseMeta(\"data_quality\", { stage: \"anomaly\" }) },\n\t);\n\tg.add(anomalyNode as Node<unknown>, { name: \"anomaly\" });\n\n\t// --- Baseline (rolling state) ---\n\tconst baseline = node<unknown>([], {\n\t\tinitial: null,\n\t\tmeta: baseMeta(\"data_quality\", {\n\t\t\tstage: \"baseline\",\n\t\t\tdescription: \"Rolling baseline for drift detection\",\n\t\t}),\n\t});\n\tg.add(baseline, { name: \"baseline\" });\n\n\t// Update baseline on valid records\n\tconst baselineUpdater = node(\n\t\t[validateNode as Node],\n\t\t(batchData, _actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst result = data[0] as ValidationResult;\n\t\t\tif (result?.valid) {\n\t\t\t\tbatch(() => {\n\t\t\t\t\tbaseline.emit(result.record);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t{ describeKind: \"effect\" },\n\t);\n\tg.add(baselineUpdater as Node<unknown>, { name: \"__baseline_updater\" });\n\tkeepalive(baselineUpdater as Node<unknown>);\n\n\t// --- Drift detection ---\n\tconst detectDriftFn = opts.detectDrift ?? (() => ({ drift: false }));\n\tconst driftNode = node<unknown>(\n\t\t[opts.source, baseline],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(detectDriftFn(data[0], data[1]));\n\t\t},\n\t\t{ describeKind: \"derived\", meta: baseMeta(\"data_quality\", { stage: \"drift\" }) },\n\t);\n\tg.add(driftNode, { name: \"drift\" });\n\n\t// --- Remediation suggestions ---\n\tconst suggestFn = opts.suggest ?? (() => null);\n\tconst remediateNode = node<unknown>(\n\t\t[validateNode as Node, anomalyNode as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(\n\t\t\t\tsuggestFn({\n\t\t\t\t\tvalidation: data[0] as ValidationResult,\n\t\t\t\t\tanomaly: data[1] as AnomalyResult,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t{ describeKind: \"derived\", meta: baseMeta(\"data_quality\", { stage: \"remediate\" }) },\n\t);\n\tg.add(remediateNode, { name: \"remediate\" });\n\n\t// --- Output ---\n\tconst output = node<unknown>(\n\t\t[validateNode as Node, anomalyNode as Node, driftNode, remediateNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst vals = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit({\n\t\t\t\tvalidation: vals[0],\n\t\t\t\tanomaly: vals[1],\n\t\t\t\tdrift: vals[2],\n\t\t\t\tremediation: vals[3],\n\t\t\t});\n\t\t},\n\t\t{ describeKind: \"derived\", meta: baseMeta(\"data_quality\", { stage: \"output\" }) },\n\t);\n\tg.add(output, { name: \"output\" });\n\n\t// --- Feedback (anomaly → validation rule refinement) ---\n\tconst validationRules = node<unknown[]>([], {\n\t\tinitial: [],\n\t\tmeta: baseMeta(\"data_quality\", { stage: \"validation_rules\" }),\n\t});\n\tg.add(validationRules as Node<unknown>, { name: \"validation_rules\" });\n\n\tconst fbCondition = node<unknown>(\n\t\t[anomalyNode as Node],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst a = data[0] as AnomalyResult | null;\n\t\t\tactions.emit(a?.anomaly ? a : null);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: baseMeta(\"data_quality\", { stage: \"feedback_condition\" }),\n\t\t},\n\t);\n\tg.add(fbCondition as Node<unknown>, { name: \"feedback_condition\" });\n\tfeedback(g, \"feedback_condition\", \"validation_rules\", {\n\t\tmaxIterations: opts.maxFeedbackIterations ?? 3,\n\t});\n\n\treturn g;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Check if a value has a `type` or `kind` tag matching the given label. */\nfunction isTagged(value: unknown, tag: string): boolean {\n\tif (value == null || typeof value !== \"object\") return false;\n\tconst v = value as Record<string, unknown>;\n\treturn v.type === tag || v.kind === tag;\n}\n","/**\n * actuatorExecutor — bridge a side-effecting actuator into the harness\n * EXECUTE work fn.\n *\n * `refineExecutor` covers the artifact-typed case (refine a candidate\n * `T` against an evaluator); `actuatorExecutor` covers the side-effecting\n * case (write a catalog entry, mutate a template registry, edit a doc on\n * disk). The user's `apply` callback owns the side effect; the executor\n * wraps it in the per-claim lifecycle:\n *\n * 1. **One DATA per claim.** The producer captures the first DATA from\n * the bridged `apply` result, emits a {@link HarnessJobPayload} with\n * `execution` filled in, and completes. Subsequent inner DATAs are\n * ignored.\n * 2. **Cancel-on-teardown.** When the JobFlow pump unsubscribes (after\n * capturing first DATA, or on graph teardown), the producer's cleanup\n * fires `ac.abort()` which propagates into `apply`'s `signal`.\n * 3. **Errors surfaced as failure payload.** A thrown / ERROR result is\n * mapped via `onError` into a `failure`-outcome `ExecuteOutput` so the\n * dispatch effect can route the item rather than silently dropping it.\n *\n * **What `apply` may return.** Anything `fromAny` accepts: `Promise<R>`,\n * `Node<R>`, `AsyncIterable<R>`, `Iterable<R>`, or a synchronous `R`.\n * `Promise<R>` is the typical shape (`writeFile`, `fetch`, `db.execute`).\n *\n * **Pairing with `evalVerifier`.** `ExecuteOutput.artifact` is set to\n * the actuation record; an `evalVerifier<R>` whose `extractArtifact`\n * returns the record (or the post-apply world state) closes EXECUTE →\n * VERIFY with consistent typing end-to-end.\n *\n * @module\n */\n\nimport { COMPLETE, DATA, ERROR, type Messages, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport type { JobEnvelope } from \"../job-queue/index.js\";\n\nimport type { ExecuteOutput, HarnessExecutor, HarnessJobPayload, TriagedItem } from \"./types.js\";\n\n/**\n * What an actuator's `apply` may return. Mirrors `NodeInput<R>` plus a\n * raw `R` for synchronous side effects.\n */\nexport type ActuatorResult<R> = NodeInput<R>;\n\n/** Configuration for {@link actuatorExecutor}. */\nexport interface ActuatorExecutorConfig<R> {\n\t/**\n\t * Apply the side effect for this triaged item. Receives the abort\n\t * signal — actuators that own real I/O should thread `signal` into\n\t * `fetch`, `fs.writeFile`, child-process kills, etc. so that the\n\t * pump's teardown actually cancels in-flight work.\n\t *\n\t * The first DATA emitted by the bridged result wins; later DATAs are\n\t * discarded. ERROR (or a synchronous throw) is mapped via `onError`.\n\t */\n\tapply: (item: TriagedItem, opts: { signal: AbortSignal }) => ActuatorResult<R>;\n\n\t/**\n\t * Optional gate — when provided and returning `false`, the actuator\n\t * is skipped and the executor emits an `ExecuteOutput` with\n\t * `outcome: \"failure\"`. Use to route interventions the actuator can't\n\t * handle into the failure path.\n\t */\n\tshouldApply?: (item: TriagedItem) => boolean;\n\n\t/** Detail string for the skip path. Default: includes intervention name. */\n\tskipDetail?: (item: TriagedItem) => string;\n\n\t/**\n\t * Map a successfully-applied actuation record into an `ExecuteOutput<R>`.\n\t */\n\ttoOutput?: (record: R, item: TriagedItem) => ExecuteOutput<R>;\n\n\t/**\n\t * Map a thrown / ERROR result into an `ExecuteOutput<R>`.\n\t */\n\tonError?: (err: unknown, item: TriagedItem) => ExecuteOutput<R>;\n\n\t/** Node name prefix for `describe()` introspection. */\n\tname?: string;\n}\n\nfunction defaultToOutput<R>(record: R, item: TriagedItem): ExecuteOutput<R> {\n\treturn {\n\t\toutcome: \"success\",\n\t\tdetail: `actuator applied ${item.intervention} for ${truncate(item.summary)}`,\n\t\tartifact: record,\n\t};\n}\n\nfunction defaultOnError<R>(err: unknown, item: TriagedItem): ExecuteOutput<R> {\n\tconst message = err instanceof Error ? err.message : String(err);\n\treturn {\n\t\toutcome: \"failure\",\n\t\tdetail: `actuator threw on ${item.intervention}: ${message}`,\n\t};\n}\n\nfunction defaultSkipDetail(item: TriagedItem): string {\n\treturn `actuator skipped ${item.intervention} (shouldApply returned false)`;\n}\n\nfunction truncate(s: string, max = 80): string {\n\treturn s.length <= max ? s : `${s.slice(0, max - 1)}…`;\n}\n\n/**\n * Build a {@link HarnessExecutor} backed by a side-effecting actuator.\n *\n * @example File-system actuator that writes a catalog entry and emits the diff.\n * ```ts\n * const harness = harnessLoop(\"repair\", {\n * adapter,\n * executor: actuatorExecutor<CatalogPatch>({\n * async apply(item, { signal }) {\n * const patch = patchFromItem(item);\n * await fs.writeFile(patch.path, patch.contents, { signal });\n * return patch;\n * },\n * shouldApply: (item) => item.intervention === \"catalog-fn\",\n * }),\n * verifier: evalVerifier<CatalogPatch>({ ... }),\n * });\n * ```\n */\nexport function actuatorExecutor<R>(config: ActuatorExecutorConfig<R>): HarnessExecutor<R> {\n\tconst name = config.name ?? \"actuator-executor\";\n\tconst toOutput = config.toOutput ?? defaultToOutput<R>;\n\tconst onError = config.onError ?? defaultOnError<R>;\n\tconst skipDetail = config.skipDetail ?? defaultSkipDetail;\n\n\treturn (job: JobEnvelope<HarnessJobPayload<R>>, opts) => {\n\t\tconst item = job.payload.item;\n\n\t\tif (config.shouldApply && !config.shouldApply(item)) {\n\t\t\t// Synchronous failure payload — return as a plain object;\n\t\t\t// `fromAny` accepts the bare value and emits one DATA.\n\t\t\treturn {\n\t\t\t\t...job.payload,\n\t\t\t\texecution: { item, outcome: \"failure\", detail: skipDetail(item) },\n\t\t\t} satisfies HarnessJobPayload<R>;\n\t\t}\n\n\t\treturn node<HarnessJobPayload<R>>(\n\t\t\t[],\n\t\t\t(_data, actions) => {\n\t\t\t\tconst ac = new AbortController();\n\t\t\t\t// Link pump-supplied signal (Tier 6.5 2.5b): parent abort\n\t\t\t\t// (e.g. `harness.destroy()`) cascades into the inner AC and\n\t\t\t\t// thus into `apply(item, { signal })` + `fromAny({ signal })`.\n\t\t\t\tconst parentSignal = opts?.signal;\n\t\t\t\tlet unlinkParent: () => void = () => undefined;\n\t\t\t\tif (parentSignal) {\n\t\t\t\t\tif (parentSignal.aborted) {\n\t\t\t\t\t\tac.abort();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst onParentAbort = (): void => ac.abort();\n\t\t\t\t\t\tparentSignal.addEventListener(\"abort\", onParentAbort, { once: true });\n\t\t\t\t\t\tunlinkParent = () => parentSignal.removeEventListener(\"abort\", onParentAbort);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet captured = false;\n\t\t\t\tlet unsub: (() => void) | null = null;\n\t\t\t\tconst emitOnce = (out: ExecuteOutput<R>): void => {\n\t\t\t\t\tif (captured) return;\n\t\t\t\t\tcaptured = true;\n\t\t\t\t\tactions.down([\n\t\t\t\t\t\t[DATA, { ...job.payload, execution: { item, ...out } }],\n\t\t\t\t\t\t[COMPLETE],\n\t\t\t\t\t] satisfies Messages);\n\t\t\t\t\tunsub?.();\n\t\t\t\t\tunsub = null;\n\t\t\t\t};\n\t\t\t\tlet inner: Node<R>;\n\t\t\t\ttry {\n\t\t\t\t\tconst rawResult = config.apply(item, { signal: ac.signal });\n\t\t\t\t\tinner = fromAny<R>(rawResult, { signal: ac.signal });\n\t\t\t\t} catch (err) {\n\t\t\t\t\temitOnce(onError(err, item));\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tunlinkParent();\n\t\t\t\t\t\tac.abort();\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tunsub = inner.subscribe((batch) => {\n\t\t\t\t\tfor (const m of batch) {\n\t\t\t\t\t\tif (captured) return;\n\t\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\t\temitOnce(toOutput(m[1] as R, item));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m[0] === ERROR) {\n\t\t\t\t\t\t\temitOnce(onError(m[1], item));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\t\t\temitOnce(onError(new Error(\"actuator inner completed without emitting DATA\"), item));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// Sync DATA delivery (cached state / `fromAny` over a sync value):\n\t\t\t\t// the callback ran reentrantly before `unsub` was assigned, so\n\t\t\t\t// `emitOnce`'s `unsub?.()` was a no-op. Drop the upstream subscription\n\t\t\t\t// now that we have the handle. Without this, the inner stays\n\t\t\t\t// subscribed until producer teardown — leaks at high volume.\n\t\t\t\tif (captured && unsub) {\n\t\t\t\t\tunsub();\n\t\t\t\t\tunsub = null;\n\t\t\t\t}\n\t\t\t\treturn () => {\n\t\t\t\t\tunlinkParent();\n\t\t\t\t\tac.abort();\n\t\t\t\t\tunsub?.();\n\t\t\t\t\tunsub = null;\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ name: `${name}/inner`, describeKind: \"producer\" },\n\t\t);\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// dispatchActuator\n// ---------------------------------------------------------------------------\n\n/**\n * Apply callback shape consumed by {@link dispatchActuator}. Same shape as\n * {@link ActuatorExecutorConfig.apply}.\n */\nexport type ActuatorApplyFn<R> = (\n\titem: TriagedItem,\n\topts: { signal: AbortSignal },\n) => ActuatorResult<R>;\n\n/** Configuration for {@link dispatchActuator}. */\nexport interface DispatchActuatorConfig<R> {\n\t/**\n\t * Per-intervention apply callbacks. Keyed by `TriagedItem.intervention`.\n\t * Items whose intervention is not in `routes` fall through to `default`\n\t * (when set) or emit a skip-failure `ExecuteOutput`.\n\t */\n\troutes: Readonly<Partial<Record<TriagedItem[\"intervention\"], ActuatorApplyFn<R>>>>;\n\t/** Fallback apply callback for items whose intervention is not in `routes`. */\n\tdefault?: ActuatorApplyFn<R>;\n\t/** Node name prefix for `describe()` introspection. */\n\tname?: string;\n}\n\n/**\n * Multi-intervention actuator — dispatches each `TriagedItem` to one of\n * several `apply` callbacks based on `item.intervention`.\n *\n * Internally builds a single `actuatorExecutor` whose `apply` resolves the\n * intervention → callback at call-time. Items with no matching route and no\n * `default` emit a skip-failure with detail\n * `\"no route for intervention 'X'\"`.\n */\nexport function dispatchActuator<R>(config: DispatchActuatorConfig<R>): HarnessExecutor<R> {\n\tconst name = config.name ?? \"dispatch-actuator\";\n\tconst defaultFn = config.default ?? null;\n\tconst hasDefault = defaultFn != null;\n\treturn actuatorExecutor<R>({\n\t\tapply: (item, opts) => {\n\t\t\tconst fn = Object.hasOwn(config.routes, item.intervention)\n\t\t\t\t? config.routes[item.intervention]!\n\t\t\t\t: defaultFn;\n\t\t\tif (!fn) {\n\t\t\t\tthrow new Error(`dispatchActuator: no route for intervention '${item.intervention}'`);\n\t\t\t}\n\t\t\treturn fn(item, opts);\n\t\t},\n\t\tshouldApply: (item) => Object.hasOwn(config.routes, item.intervention) || hasDefault,\n\t\tskipDetail: (item) => `no route for intervention '${item.intervention}'`,\n\t\tname,\n\t});\n}\n","/**\n * autoSolidify — promote successful VERIFY runs into a durable artifact\n * (catalog entry, skill, template, doc edit, …).\n *\n * Closes the dogfood retrospective loop: when the harness's VERIFY\n * stage reports `verified: true`, the validated intervention should\n * become an authoring artifact the next loop run can rely on. This\n * primitive is the generic substrate — pass a `write` callback that\n * does the actual promotion (e.g. `overlay.upsertTemplate` for the\n * dogfood catalog overlay; `fs.writeFile` for a doc edit; `ctx.skill`\n * for a Hermes-style skill registry).\n *\n * @example Wire the catalog overlay as the solidify target.\n * ```ts\n * const solidified = autoSolidify({\n * verifyResults: harness.verifyResults.latest,\n * extract: (vr) => vr.execution.artifact ?? null,\n * write: (entry, vr) => overlay.upsertFn(`learned-${vr.item.summary}`, entry),\n * });\n * solidified.subscribe(() => {}); // keep alive for log\n * ```\n *\n * **Why a node and not just an effect.** The returned `Node<R>` emits\n * each promoted artifact, so callers can pipe solidifications through\n * the standard reactive surface (`describe()`, `observe()`, replay\n * buffers) instead of side-channel logging. An audit / dashboard that\n * wants \"what was learned this run?\" subscribes to the returned node;\n * the `write` callback owns the durable side effect.\n *\n * **Idempotency is the caller's responsibility.** The primitive\n * promotes every `verified: true` wave that passes the predicate. If\n * the harness re-verifies the same item (e.g. via reingestion), the\n * `write` callback is invoked again. Wrap your write fn with a\n * dedup-by-key guard if your target store would otherwise bloat. The\n * inner `seen` set inside this factory is intentionally absent — the\n * harness already retains via topic logs and the user may want\n * re-promotion semantics that are domain-specific.\n *\n * @module\n */\n\nimport { COMPLETE, DATA, ERROR, type Messages, type Node, node } from \"@graphrefly/pure-ts/core\";\n\nimport type { VerifyResult } from \"./types.js\";\n\n/**\n * Configuration for {@link autoSolidify}.\n *\n * `R` is the artifact type the upstream EXECUTE stage produced (and\n * `evalVerifier` carries through `execution.artifact`). `T` is the\n * promotion shape — what `write` consumes and what the returned node\n * emits. Often `T = R`, but they diverge when the actuator's raw\n * artifact needs a transform before storing (e.g. wrap a `CatalogPatch`\n * into a `CatalogEntry` with effectiveness metadata).\n */\nexport interface AutoSolidifyConfig<R, T = R> {\n\t/** Reactive verify-result stream. Typically `harness.verifyResults.latest`. */\n\tverifyResults: Node<VerifyResult<R> | null>;\n\t/**\n\t * Pull the value-to-promote out of a verified VerifyResult.\n\t * Default: `(vr) => vr.execution.artifact as T | null`. Return `null`\n\t * to skip a particular VerifyResult even when `verified: true` (e.g.\n\t * an LLM-default executor produces no artifact and there's nothing to\n\t * solidify).\n\t */\n\textract?: (vr: VerifyResult<R>) => T | null;\n\t/**\n\t * Optional gate beyond `verified === true`. When provided, the\n\t * primitive only promotes when this returns `true`. Default: pass\n\t * everything verified.\n\t *\n\t * Useful predicates:\n\t * - `(vr) => vr.item.intervention === \"catalog-fn\"` — only catalog work.\n\t * - `(vr) => (vr.findings ?? []).every(f => !/regression/i.test(f))` —\n\t * skip even-passes that mention regressions.\n\t */\n\tpredicate?: (vr: VerifyResult<R>) => boolean;\n\t/**\n\t * Promote — usually a side effect (write to overlay, fs, KG, etc.).\n\t * Receives the extracted artifact AND the originating VerifyResult so\n\t * the writer can use any context it needs (item summary, eval task\n\t * IDs, finding text, …) when shaping the durable record.\n\t */\n\twrite: (artifact: T, vr: VerifyResult<R>) => void;\n\t/** Node name for `describe()` introspection. Default `\"auto-solidify\"`. */\n\tname?: string;\n}\n\n/**\n * Build a `Node<T>` that subscribes to `verifyResults`, filters to\n * verified passes that produced an extractable artifact, runs `write`,\n * and emits the artifact. Use the returned node as a subscription\n * point for audit / dashboard / log pipelines.\n *\n * **Terminal-on-error semantics.** A throw from `predicate`, `extract`,\n * or `write` surfaces as `[[ERROR]]` on the returned node and\n * **terminates** it — the upstream subscription tears down and no\n * further DATA is emitted. This matches the spec's terminal-frame\n * contract for ERROR. If you want the solidify node to stay live\n * across user-callback throws, wrap your callbacks with try/catch\n * internally and emit a sentinel value or no-op on failure. A future\n * non-terminal `errors: Node<unknown>` companion may surface failures\n * without terminating the success stream — flagged as a follow-up.\n *\n * @returns A `Node<T>` that emits one DATA per promoted artifact.\n * Stays live as long as `verifyResults` is live AND no user callback\n * has thrown.\n */\nexport function autoSolidify<R, T = R>(config: AutoSolidifyConfig<R, T>): Node<T> {\n\tconst name = config.name ?? \"auto-solidify\";\n\tconst extract =\n\t\tconfig.extract ?? ((vr: VerifyResult<R>) => (vr.execution.artifact ?? null) as T | null);\n\tconst predicate = config.predicate ?? (() => true);\n\n\treturn node<T>(\n\t\t[],\n\t\t(_data, actions) => {\n\t\t\tlet unsub: (() => void) | null = null;\n\t\t\tlet terminated = false;\n\t\t\tconst tearDown = (): void => {\n\t\t\t\tif (terminated) return;\n\t\t\t\tterminated = true;\n\t\t\t\tunsub?.();\n\t\t\t\tunsub = null;\n\t\t\t};\n\t\t\tconst emitTerminalError = (err: unknown): void => {\n\t\t\t\tif (terminated) return;\n\t\t\t\tactions.down([[ERROR, err]] satisfies Messages);\n\t\t\t\ttearDown();\n\t\t\t};\n\t\t\tunsub = config.verifyResults.subscribe((batch) => {\n\t\t\t\tif (terminated) return;\n\t\t\t\tfor (const m of batch) {\n\t\t\t\t\tif (terminated) return;\n\t\t\t\t\tif (m[0] !== DATA) {\n\t\t\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\t\t\t// Upstream verifyResults completed (rare; harness destroy).\n\t\t\t\t\t\t\t// Forward COMPLETE and tear down — solidify is terminal too.\n\t\t\t\t\t\t\tactions.down([[COMPLETE]] satisfies Messages);\n\t\t\t\t\t\t\ttearDown();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst vr = m[1] as VerifyResult<R> | null;\n\t\t\t\t\tif (vr == null) continue;\n\t\t\t\t\tif (!vr.verified) continue;\n\t\t\t\t\t// User callbacks (predicate / extract / write) are isolated\n\t\t\t\t\t// in try/catch so a throw lands as a single terminal ERROR\n\t\t\t\t\t// rather than propagating into the upstream emitter where\n\t\t\t\t\t// it would skip later messages in the same batch and leave\n\t\t\t\t\t// the solidify node un-terminated.\n\t\t\t\t\tlet pass: boolean;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpass = predicate(vr);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\temitTerminalError(err);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!pass) continue;\n\t\t\t\t\tlet artifact: T | null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tartifact = extract(vr);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\temitTerminalError(err);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (artifact == null) continue;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconfig.write(artifact, vr);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\temitTerminalError(err);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tactions.down([[DATA, artifact]] satisfies Messages);\n\t\t\t\t}\n\t\t\t});\n\t\t\t// If `subscribe` fired terminally during the call (push-on-subscribe\n\t\t\t// of an already-COMPLETE upstream), `tearDown()` ran inside the\n\t\t\t// callback before `unsub` was assigned, so the unsub is still\n\t\t\t// dangling. Drop it now if we're already terminated.\n\t\t\tif (terminated && unsub) {\n\t\t\t\tunsub();\n\t\t\t\tunsub = null;\n\t\t\t}\n\t\t\treturn () => {\n\t\t\t\ttearDown();\n\t\t\t};\n\t\t},\n\t\t{ name, describeKind: \"producer\" },\n\t);\n}\n","/**\n * Harness bridge factories (roadmap §9.0).\n *\n * Intake bridges, eval source wrapper, before/after comparison,\n * affected-task filter, code-change bridge, and notification effect.\n * All are compositions of existing primitives — no new abstractions.\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport type { TopicGraph } from \"../messaging/index.js\";\n\nimport type { IntakeItem, Severity, TriagedItem } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Generic intake bridge\n// ---------------------------------------------------------------------------\n\n/** Options for {@link createIntakeBridge}. */\nexport interface CreateIntakeBridgeOptions<T> {\n\t/** Graph to register the effect node on (B.1 narrow-waist visibility). */\n\tgraph: Graph;\n\t/** Reactive node emitting domain-specific data. */\n\tsource: Node<T>;\n\t/** TopicGraph to publish IntakeItem entries to. */\n\tintakeTopic: TopicGraph<IntakeItem>;\n\t/** Converts source data into IntakeItem[]. Return empty array to skip. */\n\tparser: (value: T) => IntakeItem[];\n\t/** Effect-node name (default `\"intake-bridge\"`). */\n\tname?: string;\n}\n\n/**\n * Generic source→intake bridge factory.\n *\n * Watches a source node for new values, passes each through a user-supplied\n * `parser` that produces zero or more `IntakeItem`s, and publishes them to\n * the given intake topic.\n *\n * This is the generalized pattern behind {@link evalIntakeBridge}. Use it for\n * CI results, test failures, Slack messages, monitoring alerts, or any domain\n * where structured results should flow into a harness loop.\n *\n * The effect node is registered on the supplied `graph` so it appears in\n * `describe()` and is owned by the graph's lifecycle.\n *\n * @returns The effect node (for lifecycle management).\n */\nexport function createIntakeBridge<T>(opts: CreateIntakeBridgeOptions<T>): Node<unknown> {\n\tconst { graph, source, intakeTopic, parser, name = \"intake-bridge\" } = opts;\n\tconst eff = node(\n\t\t[source as Node<unknown>],\n\t\t(batchData, _actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst value = data[0];\n\t\t\tif (value === undefined) return;\n\t\t\tconst items = parser(value as T);\n\t\t\tfor (const item of items) {\n\t\t\t\tintakeTopic.publish(item);\n\t\t\t}\n\t\t},\n\t\t{ describeKind: \"effect\" },\n\t);\n\tgraph.add(eff, { name });\n\treturn eff;\n}\n\n// ---------------------------------------------------------------------------\n// Generic eval result shape\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal eval result shape accepted by the bridge.\n *\n * TS eval runner uses `EvalRun` from `evals/lib/types.ts` which is a superset\n * of this shape. The bridge only reads what it needs.\n */\nexport interface EvalRunResult {\n\trun_id: string;\n\tmodel: string;\n\ttasks: EvalTaskResult[];\n}\n\nexport interface EvalTaskResult {\n\ttask_id: string;\n\tvalid: boolean;\n\tjudge_scores?: EvalJudgeScore[];\n}\n\nexport interface EvalJudgeScore {\n\tclaim: string;\n\tpass: boolean;\n\treasoning: string;\n}\n\n// ---------------------------------------------------------------------------\n// Bridge factory\n// ---------------------------------------------------------------------------\n\nexport interface EvalIntakeBridgeOptions {\n\t/** Graph to register the effect node on (B.1 narrow-waist visibility). */\n\tgraph: Graph;\n\t/** Node emitting EvalRunResult (or EvalRunResult[]). */\n\tsource: Node<EvalRunResult | EvalRunResult[]>;\n\t/** TopicGraph to publish IntakeItem entries to. */\n\tintakeTopic: TopicGraph<IntakeItem>;\n\t/** Effect-node name (default `\"eval-intake-bridge\"`). */\n\tname?: string;\n\t/** Minimum severity for eval-sourced items (default `\"medium\"`). */\n\tdefaultSeverity?: Severity;\n}\n\n/**\n * Create an effect node that watches an eval results source and publishes\n * per-criterion findings to an intake topic.\n *\n * Each failing judge criterion produces a separate IntakeItem — not one\n * item per task. This gives the triage stage granular findings to classify.\n *\n * The effect node is registered on the supplied `graph` so it appears in\n * `describe()` and is owned by the graph's lifecycle.\n *\n * @returns The effect node (for lifecycle management).\n */\nexport function evalIntakeBridge(opts: EvalIntakeBridgeOptions): Node<unknown> {\n\tconst {\n\t\tgraph,\n\t\tsource,\n\t\tintakeTopic,\n\t\tname = \"eval-intake-bridge\",\n\t\tdefaultSeverity = \"medium\",\n\t} = opts;\n\n\tconst eff = node(\n\t\t[source as Node<unknown>],\n\t\t(batchData, _actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst results = data[0];\n\t\t\tif (results === undefined) return;\n\t\t\tconst runs = Array.isArray(results)\n\t\t\t\t? (results as EvalRunResult[])\n\t\t\t\t: [results as EvalRunResult];\n\n\t\t\tfor (const run of runs) {\n\t\t\t\tfor (const task of run.tasks) {\n\t\t\t\t\t// Only process tasks with failures\n\t\t\t\t\tif (task.valid && task.judge_scores?.every((s) => s.pass)) continue;\n\n\t\t\t\t\t// Task-level validity failure (no judge scores or overall invalid)\n\t\t\t\t\tif (!task.valid && (!task.judge_scores || task.judge_scores.length === 0)) {\n\t\t\t\t\t\tintakeTopic.publish({\n\t\t\t\t\t\t\tsource: \"eval\",\n\t\t\t\t\t\t\tsummary: `Task ${task.task_id} invalid (model: ${run.model})`,\n\t\t\t\t\t\t\tevidence: `Run ${run.run_id}: task produced invalid output`,\n\t\t\t\t\t\t\taffectsAreas: [\"graphspec\"],\n\t\t\t\t\t\t\taffectsEvalTasks: [task.task_id],\n\t\t\t\t\t\t\tseverity: defaultSeverity,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Per-criterion findings\n\t\t\t\t\tif (task.judge_scores) {\n\t\t\t\t\t\tfor (const score of task.judge_scores) {\n\t\t\t\t\t\t\tif (score.pass) continue;\n\t\t\t\t\t\t\tintakeTopic.publish({\n\t\t\t\t\t\t\t\tsource: \"eval\",\n\t\t\t\t\t\t\t\tsummary: `${task.task_id}: ${score.claim} (model: ${run.model})`,\n\t\t\t\t\t\t\t\tevidence: score.reasoning,\n\t\t\t\t\t\t\t\taffectsAreas: [\"graphspec\"],\n\t\t\t\t\t\t\t\taffectsEvalTasks: [task.task_id],\n\t\t\t\t\t\t\t\tseverity: defaultSeverity,\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},\n\t\t{ describeKind: \"effect\" },\n\t);\n\tgraph.add(eff, { name });\n\treturn eff;\n}\n\n// ---------------------------------------------------------------------------\n// Composition A: Eval-driven improvement loop\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap any eval runner as a reactive producer node.\n *\n * When `trigger` emits, calls `runner()` and emits the result downstream.\n * Uses `switchMap` + `fromAny` — the async boundary stays in the source\n * layer (spec §5.10). A new trigger cancels any in-flight run.\n *\n * Pure transform via operator composition — does not construct an\n * effect/derived node, so no `graph` parameter is needed.\n *\n * ```ts\n * const trigger = state(0); // bump to trigger a new run\n * const results = evalSource(trigger, () => runEvals(config));\n * results.subscribe(msgs => { ... });\n * trigger.emit(1); // fires the runner\n * ```\n *\n * @param trigger - Any node; each new DATA emission fires the runner.\n * @param runner - Returns an EvalRunResult (or promise of one).\n */\nexport function evalSource<T extends EvalRunResult>(\n\ttrigger: Node<unknown>,\n\trunner: () => T | Promise<T>,\n): Node<T> {\n\treturn switchMap(trigger, () => fromAny(runner()) as Node<T>);\n}\n\n// ---------------------------------------------------------------------------\n\n/** Per-task delta produced by {@link beforeAfterCompare}. */\nexport interface EvalTaskDelta {\n\ttaskId: string;\n\tbefore: boolean;\n\tafter: boolean;\n\t/** Score-level diff (after − before), undefined if no scores present. */\n\tscoreDiff?: number;\n}\n\n/** Output of {@link beforeAfterCompare}. */\nexport interface EvalDelta {\n\t/** Task IDs that newly fail in `after` (were passing in `before`). */\n\tnewFailures: string[];\n\t/** Task IDs that now pass in `after` (were failing in `before`). */\n\tresolved: string[];\n\t/** Full per-task breakdown. */\n\ttaskDeltas: EvalTaskDelta[];\n\t/** True when net resolutions > net failures. */\n\toverallImproved: boolean;\n}\n\n/** Options for {@link beforeAfterCompare}. */\nexport interface BeforeAfterCompareOptions {\n\t/** Graph to register the derived node on (B.1 narrow-waist visibility). */\n\tgraph: Graph;\n\t/** Node holding the baseline eval result. */\n\tbefore: Node<EvalRunResult>;\n\t/** Node holding the new eval result. */\n\tafter: Node<EvalRunResult>;\n\t/** Derived-node name (default `\"eval-delta\"`). */\n\tname?: string;\n}\n\n/**\n * Derived node that computes before/after eval deltas.\n *\n * Pure computation: no LLM, no async. Compares per-task validity and\n * pass counts between two `EvalRunResult` snapshots.\n *\n * The derived node is registered on the supplied `graph` so it appears in\n * `describe()` and is owned by the graph's lifecycle.\n */\nexport function beforeAfterCompare(opts: BeforeAfterCompareOptions): Node<EvalDelta> {\n\tconst { graph, before, after, name = \"eval-delta\" } = opts;\n\tconst der = node<EvalDelta>(\n\t\t[before as Node<unknown>, after as Node<unknown>],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst bRes = data[0] as EvalRunResult;\n\t\t\tconst aRes = data[1] as EvalRunResult;\n\n\t\t\tconst beforeMap = new Map<string, EvalTaskResult>(bRes.tasks.map((t) => [t.task_id, t]));\n\t\t\tconst afterMap = new Map<string, EvalTaskResult>(aRes.tasks.map((t) => [t.task_id, t]));\n\n\t\t\tconst allIds = new Set([...beforeMap.keys(), ...afterMap.keys()]);\n\t\t\tconst taskDeltas: EvalTaskDelta[] = [];\n\t\t\tconst newFailures: string[] = [];\n\t\t\tconst resolved: string[] = [];\n\n\t\t\tfor (const id of allIds) {\n\t\t\t\tconst bt = beforeMap.get(id);\n\t\t\t\tconst at = afterMap.get(id);\n\t\t\t\tconst beforeValid = bt?.valid ?? false;\n\t\t\t\tconst afterValid = at?.valid ?? false;\n\n\t\t\t\tconst beforeScore = bt?.judge_scores\n\t\t\t\t\t? bt.judge_scores.filter((s) => s.pass).length\n\t\t\t\t\t: undefined;\n\t\t\t\tconst afterScore = at?.judge_scores\n\t\t\t\t\t? at.judge_scores.filter((s) => s.pass).length\n\t\t\t\t\t: undefined;\n\t\t\t\tconst scoreDiff =\n\t\t\t\t\tbeforeScore !== undefined && afterScore !== undefined\n\t\t\t\t\t\t? afterScore - beforeScore\n\t\t\t\t\t\t: undefined;\n\n\t\t\t\ttaskDeltas.push({ taskId: id, before: beforeValid, after: afterValid, scoreDiff });\n\t\t\t\tif (beforeValid && !afterValid) newFailures.push(id);\n\t\t\t\tif (!beforeValid && afterValid) resolved.push(id);\n\t\t\t}\n\n\t\t\tactions.emit({\n\t\t\t\tnewFailures,\n\t\t\t\tresolved,\n\t\t\t\ttaskDeltas,\n\t\t\t\toverallImproved: resolved.length > newFailures.length,\n\t\t\t});\n\t\t},\n\t\t{ describeKind: \"derived\" },\n\t);\n\tgraph.add(der as Node<unknown>, { name });\n\treturn der;\n}\n\n// ---------------------------------------------------------------------------\n\n/** Options for {@link affectedTaskFilter}. */\nexport interface AffectedTaskFilterOptions {\n\t/** Graph to register the derived node on (B.1 narrow-waist visibility). */\n\tgraph: Graph;\n\t/** Node holding the current list of triaged items. */\n\tissues: Node<readonly TriagedItem[]>;\n\t/**\n\t * Optional node (or plain array) of all known task IDs.\n\t * When provided, output is the intersection.\n\t */\n\tfullTaskSet?: Node<readonly string[]> | readonly string[];\n\t/** Derived-node name (default `\"affected-task-filter\"`). */\n\tname?: string;\n}\n\n/**\n * Derived node that selects which eval task IDs to re-run.\n *\n * Collects `affectsEvalTasks` from all triaged items, deduplicates, then\n * optionally intersects with `fullTaskSet`. Returns a sorted array of IDs.\n *\n * Use this to avoid re-running the full eval suite after each fix: only the\n * tasks that the triaged items claim to affect are returned.\n *\n * The derived node is registered on the supplied `graph` so it appears in\n * `describe()` and is owned by the graph's lifecycle.\n */\nexport function affectedTaskFilter(opts: AffectedTaskFilterOptions): Node<string[]> {\n\tconst { graph, issues, fullTaskSet, name = \"affected-task-filter\" } = opts;\n\n\tlet taskSetNode: Node<unknown> | null = null;\n\tif (fullTaskSet != null) {\n\t\tif (Array.isArray(fullTaskSet)) {\n\t\t\t// Static-array form: register the inline state node so it appears\n\t\t\t// in `describe()`/`explain()` walks (EC8 — qa 2026-04-30).\n\t\t\tconst inlineSet = node([], { initial: fullTaskSet as readonly string[] });\n\t\t\tgraph.add(inlineSet, { name: `${name}/fullTaskSet` });\n\t\t\ttaskSetNode = inlineSet as Node<unknown>;\n\t\t} else {\n\t\t\t// User-supplied Node — owned by the caller's graph; don't re-add.\n\t\t\ttaskSetNode = fullTaskSet as Node<unknown>;\n\t\t}\n\t}\n\n\tconst deps: Node<unknown>[] = [issues as Node<unknown>];\n\tif (taskSetNode) deps.push(taskSetNode);\n\n\tconst der = node<string[]>(\n\t\tdeps,\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst items = data[0] as readonly TriagedItem[];\n\t\t\tconst all = taskSetNode ? new Set(data[1] as readonly string[]) : null;\n\n\t\t\tconst affected = new Set<string>();\n\t\t\tfor (const item of items) {\n\t\t\t\tfor (const id of item.affectsEvalTasks ?? []) {\n\t\t\t\t\tif (all == null || all.has(id)) affected.add(id);\n\t\t\t\t}\n\t\t\t}\n\t\t\tactions.emit([...affected].sort());\n\t\t},\n\t\t{ describeKind: \"derived\" },\n\t);\n\tgraph.add(der as Node<unknown>, { name });\n\treturn der;\n}\n\n// ---------------------------------------------------------------------------\n// Composition D: Quality gate (CI/CD)\n// ---------------------------------------------------------------------------\n\n/** A single lint error emitted by a CI tool. */\nexport interface LintError {\n\tfile: string;\n\tline: number;\n\tcol: number;\n\trule: string;\n\tmessage: string;\n}\n\n/** A single test failure emitted by a test runner. */\nexport interface TestFailure {\n\ttestId: string;\n\tfile: string;\n\tmessage: string;\n}\n\n/** Structured code-change / CI event. */\nexport interface CodeChange {\n\t/** Files touched by the change. */\n\tfiles: string[];\n\tlintErrors?: LintError[];\n\ttestFailures?: TestFailure[];\n}\n\n/** Options for {@link codeChangeBridge}. */\nexport interface CodeChangeBridgeOptions {\n\t/** Graph to register the effect node on (B.1 narrow-waist visibility). */\n\tgraph: Graph;\n\t/** Node emitting CodeChange events. */\n\tsource: Node<CodeChange>;\n\t/** TopicGraph to publish IntakeItem entries to. */\n\tintakeTopic: TopicGraph<IntakeItem>;\n\t/** Optional custom parser (overrides default). */\n\tparser?: (change: CodeChange) => IntakeItem[];\n\t/** Effect-node name (default `\"code-change-bridge\"`). */\n\tname?: string;\n\t/** Default severity for generated IntakeItems (default `\"high\"`). */\n\tdefaultSeverity?: Severity;\n}\n\n/**\n * Intake bridge for code-change / CI events.\n *\n * Watches a source node for `CodeChange` events and publishes one\n * `IntakeItem` per lint error and per test failure to the intake topic.\n * Pass a custom `parser` to override the default mapping.\n *\n * The effect node is registered on the supplied `graph` so it appears in\n * `describe()` and is owned by the graph's lifecycle.\n */\nexport function codeChangeBridge(opts: CodeChangeBridgeOptions): Node<unknown> {\n\tconst {\n\t\tgraph,\n\t\tsource,\n\t\tintakeTopic,\n\t\tparser,\n\t\tname = \"code-change-bridge\",\n\t\tdefaultSeverity = \"high\",\n\t} = opts;\n\n\tfunction defaultParser(change: CodeChange): IntakeItem[] {\n\t\tconst items: IntakeItem[] = [];\n\t\tfor (const err of change.lintErrors ?? []) {\n\t\t\titems.push({\n\t\t\t\tsource: \"code-change\",\n\t\t\t\tsummary: `Lint: ${err.rule} in ${err.file}:${err.line}`,\n\t\t\t\tevidence: err.message,\n\t\t\t\taffectsAreas: [err.file],\n\t\t\t\tseverity: defaultSeverity,\n\t\t\t});\n\t\t}\n\t\tfor (const fail of change.testFailures ?? []) {\n\t\t\titems.push({\n\t\t\t\tsource: \"test\",\n\t\t\t\tsummary: `Test failure: ${fail.testId}`,\n\t\t\t\tevidence: fail.message,\n\t\t\t\taffectsAreas: [fail.file],\n\t\t\t\taffectsEvalTasks: [fail.testId],\n\t\t\t\tseverity: defaultSeverity,\n\t\t\t});\n\t\t}\n\t\treturn items;\n\t}\n\n\tconst resolve = parser ?? defaultParser;\n\n\tconst eff = node(\n\t\t[source as Node<unknown>],\n\t\t(batchData, _actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst change = data[0];\n\t\t\tif (change === undefined) return;\n\t\t\tfor (const item of resolve(change as CodeChange)) {\n\t\t\t\tintakeTopic.publish(item);\n\t\t\t}\n\t\t},\n\t\t{ describeKind: \"effect\" },\n\t);\n\tgraph.add(eff, { name });\n\treturn eff;\n}\n\n// ---------------------------------------------------------------------------\n\n/** Transport function for {@link notifyEffect}. Sync or async. */\nexport type NotifyTransport<T> = (item: T) => void | Promise<void>;\n\n/** Options for {@link notifyEffect}. */\nexport interface NotifyEffectOptions<T> {\n\t/** Graph to register the effect node on (B.1 narrow-waist visibility). */\n\tgraph: Graph;\n\t/** TopicGraph whose latest entry triggers the notification. */\n\ttopic: TopicGraph<T>;\n\t/** Called with each new item. May return a Promise. */\n\ttransport: NotifyTransport<T>;\n\t/** Effect-node name (default `\"notify-effect\"`). */\n\tname?: string;\n}\n\n/**\n * Effect node that sends each new topic entry to an external channel.\n *\n * The `transport` function is called for every item published to `topic`.\n * Async transports are bridged via `fromAny` (spec §5.10 compliant).\n *\n * Typical use: Slack webhook, GitHub PR comment, email notification, etc.\n * The factory provides reactive wiring; the transport supplies domain logic.\n *\n * The effect node is registered on the supplied `graph` so it appears in\n * `describe()` and is owned by the graph's lifecycle.\n *\n * ```ts\n * notifyEffect({ graph, topic: alertQueue, transport: async (item) => {\n * await fetch(SLACK_WEBHOOK, { method: 'POST', body: JSON.stringify({ text: item.summary }) });\n * }});\n * ```\n */\nexport function notifyEffect<T>(opts: NotifyEffectOptions<T>): Node<unknown> {\n\tconst { graph, topic, transport, name = \"notify-effect\" } = opts;\n\t// SENTINEL contract on `topic.latest` (COMPOSITION-GUIDE §1a + spec §5.12):\n\t// - `topic.publish(undefined)` is rejected at the publish boundary, so\n\t// `undefined` is exclusively the protocol SENTINEL on the read side.\n\t// - `topic.latest` stays SENTINEL on empty (no eager DATA emission), so\n\t// the partial-false first-run gate holds this fn until the first publish.\n\t// - Legit `null` DATA (when `T` includes `null`) reaches `transport`;\n\t// user transports must handle `null` themselves per v5.\n\t// The `=== undefined` guard below is defense-in-depth for any future\n\t// empty-batch wave where `prevData[0]` is still SENTINEL — in normal flow\n\t// the first-run gate has already filtered the empty case.\n\tconst eff = node(\n\t\t[topic.latest as Node<unknown>],\n\t\t(batchData, _actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst item = data[0];\n\t\t\tif (item === undefined) return;\n\t\t\t// transport is a side effect (webhook, Slack, email). Async transports\n\t\t\t// are fire-and-forget — the Promise result does not feed back into the\n\t\t\t// graph. Suppress unhandled-rejection noise by voiding the return.\n\t\t\tvoid transport(item as T);\n\t\t},\n\t\t{ describeKind: \"effect\" },\n\t);\n\tgraph.add(eff, { name });\n\treturn eff;\n}\n","/**\n * Harness runtime defaults (roadmap §9.0).\n *\n * Split out from `types.ts` in Wave B Unit 15 G so the type file holds\n * only type declarations and plug-in contracts. Runtime constants and\n * helpers live here; the harness barrel (`index.ts`) re-exports both so\n * external consumers see a single surface.\n *\n * @module\n */\n\nimport type {\n\tErrorClass,\n\tErrorClassifier,\n\tExecutionResult,\n\tIntervention,\n\tPresetId,\n\tQueueConfig,\n\tQueueRoute,\n\tRootCause,\n\tSeverity,\n\tStrategyKey,\n} from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Route / queue\n// ---------------------------------------------------------------------------\n\n/** Ordered queue route names for iteration. */\nexport const QUEUE_NAMES: readonly QueueRoute[] = [\n\t\"auto-fix\",\n\t\"needs-decision\",\n\t\"investigation\",\n\t\"backlog\",\n];\n\n/** Default queue configurations. */\nexport const DEFAULT_QUEUE_CONFIGS: Record<QueueRoute, QueueConfig> = {\n\t\"auto-fix\": { gated: false },\n\t\"needs-decision\": { gated: true },\n\tinvestigation: { gated: true },\n\t// `startOpen` intentionally omitted — backlog is not gated, so the flag\n\t// would be meaningless. Dropped in Unit 15 G trim pass.\n\tbacklog: { gated: false },\n};\n\n// ---------------------------------------------------------------------------\n// Priority scoring\n// ---------------------------------------------------------------------------\n\n/** Default severity weights. */\nexport const DEFAULT_SEVERITY_WEIGHTS: Record<Severity, number> = {\n\tcritical: 100,\n\thigh: 70,\n\tmedium: 40,\n\tlow: 10,\n};\n\n/** Default decay rate: ~7-day half-life. Re-exported from `base/utils/decay.ts`. */\nexport { DEFAULT_DECAY_RATE } from \"../../base/utils/decay.js\";\n\n// ---------------------------------------------------------------------------\n// Strategy model\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical 3-axis composite-key factory: `${presetId}|${rootCause}→${intervention}`.\n *\n * **Phase 13.I axis extension (DS-13.I, 2026-05-01).** Pre-multi-agent\n * callers without a preset registry pass {@link DEFAULT_PRESET_ID}\n * (`\"default\"`) for the first arg. Pre-1.0 breaking signature change;\n * persisted strategy-model snapshots from before this date are NOT portable.\n */\nexport function strategyKey(\n\tpresetId: PresetId,\n\trootCause: RootCause,\n\tintervention: Intervention,\n): StrategyKey {\n\treturn `${presetId}|${rootCause}→${intervention}`;\n}\n\n// ---------------------------------------------------------------------------\n// Error classifier\n// ---------------------------------------------------------------------------\n\n/**\n * Regex-word-boundary match over a closed keyword set. Callers needing\n * domain-specific failure modes should supply a custom\n * {@link ErrorClassifier}; this default exists so zero-config harness runs\n * still distinguish parse-class failures (fast-retry) from everything\n * else (full loop via reingestion).\n */\nconst SELF_CORRECTABLE_RE = /\\b(parse|json|config|validation|syntax)\\b/i;\n\n/** Default error classifier: parse/config errors are self-correctable. */\nexport const defaultErrorClassifier: ErrorClassifier = (result: ExecutionResult): ErrorClass =>\n\tSELF_CORRECTABLE_RE.test(result.detail) ? \"self-correctable\" : \"structural\";\n\n// ---------------------------------------------------------------------------\n// Default stage prompts\n// ---------------------------------------------------------------------------\n\n/** Default TRIAGE prompt — LLM classifies intake items into root-cause + intervention + route + priority. */\nexport const DEFAULT_TRIAGE_PROMPT = `You are a triage classifier for a reactive collaboration harness.\n\nGiven an intake item, classify it and output JSON:\n{\n \"rootCause\": \"composition\" | \"missing-fn\" | \"bad-docs\" | \"schema-gap\" | \"regression\" | \"unknown\",\n \"intervention\": \"template\" | \"catalog-fn\" | \"docs\" | \"wrapper\" | \"schema-change\" | \"investigate\",\n \"route\": \"auto-fix\" | \"needs-decision\" | \"investigation\" | \"backlog\",\n \"priority\": <number 0-100>,\n \"triageReasoning\": \"<one sentence>\"\n}\n\nStrategy model (past effectiveness):\n{{strategy}}\n\nIntake item:\n{{item}}`;\n\n/** Default EXECUTE prompt — LLM produces a fix given a triaged issue. */\nexport const DEFAULT_EXECUTE_PROMPT = `You are an implementation agent.\n\nGiven a triaged issue with root cause and intervention type, produce a fix.\n\nIssue:\n{{item}}\n\nOutput JSON:\n{\n \"outcome\": \"success\" | \"failure\" | \"partial\",\n \"detail\": \"<description of what was done or what failed>\"\n}`;\n\n/** Default VERIFY prompt — LLM reviews an execution result against the original issue. */\nexport const DEFAULT_VERIFY_PROMPT = `You are a QA reviewer.\n\nGiven an execution result, verify whether the fix is correct.\n\nExecution:\n{{execution}}\n\nOriginal issue:\n{{item}}\n\nOutput JSON:\n{\n \"verified\": true/false,\n \"findings\": [\"<finding1>\", ...],\n \"errorClass\": \"self-correctable\" | \"structural\" // only if verified=false\n}`;\n\n// ---------------------------------------------------------------------------\n// Prompt resolver helper\n// ---------------------------------------------------------------------------\n\n/**\n * Collapse the `string | ((input: In) => string) | undefined` prompt-template\n * pattern into a single `(input: In) => string`. A function `raw` is used as-is\n * (the caller opted into full control). Otherwise `raw ?? fallbackTemplate`\n * is fed through `substitute`, which does the placeholder replacement.\n *\n * Used by the three harness stages (TRIAGE / EXECUTE / VERIFY), which each\n * accept a `string | function` config but use different placeholder schemes\n * (`{{item}}`, `{{execution}}`, `{{strategy}}`). The helper absorbs only the\n * branch logic; the per-stage placeholder substitution lives at the call site.\n */\nexport function resolvePromptFn<In>(\n\traw: string | ((input: In) => string) | undefined,\n\tfallbackTemplate: string,\n\tsubstitute: (template: string, input: In) => string,\n): (input: In) => string {\n\tif (typeof raw === \"function\") return raw;\n\tconst template = raw ?? fallbackTemplate;\n\treturn (input) => substitute(template, input);\n}\n","/**\n * Strategy model and priority scoring (roadmap §9.0).\n *\n * `strategyModel` returns a typed alias of {@link AuditedSuccessTrackerGraph}\n * keyed by `StrategyKey` (the composite `rootCause→intervention` string).\n * The shared substrate (Class B audit Alt E collapse, 2026-04-30) replaces\n * the prior bespoke bundle shape; composite-key callers use {@link strategyKey}\n * to compute the key and pass `{ rootCause, intervention }` as record decoration.\n *\n * @module\n */\n\nimport { monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { decay } from \"../../base/utils/decay.js\";\nimport {\n\ttype AuditedSuccessTrackerGraph,\n\tauditedSuccessTracker,\n} from \"../orchestration/audited-success-tracker.js\";\n\nimport {\n\tDEFAULT_DECAY_RATE,\n\tDEFAULT_PRESET_ID,\n\tDEFAULT_SEVERITY_WEIGHTS,\n\ttype PrioritySignals,\n\ttype StrategyEntry,\n\ttype StrategyKey,\n\tstrategyKey,\n\ttype TriagedItem,\n} from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Strategy model\n// ---------------------------------------------------------------------------\n\n/** Snapshot shape for the strategy-model `entries` node. */\nexport type StrategySnapshot = ReadonlyMap<StrategyKey, StrategyEntry>;\n\n/** Strategy-model graph: a typed alias of {@link AuditedSuccessTrackerGraph}. */\nexport type StrategyModelGraph = AuditedSuccessTrackerGraph<StrategyKey, StrategyEntry>;\n\n/**\n * Create a strategy model that tracks\n * `presetId × rootCause × intervention → successRate` over completed\n * issues (presetId axis added in Phase 13.I, 2026-05-01). Returns an\n * {@link AuditedSuccessTrackerGraph} keyed by {@link StrategyKey}.\n *\n * The reactive `entries` field is a `Node<StrategySnapshot>` suitable for\n * `describe()` / `withLatestFrom` composition.\n *\n * Composite-key conversion happens at the call site:\n * ```ts\n * const strategy = strategyModel();\n * strategy.record(strategyKey(presetId, rootCause, intervention), success, {\n * presetId,\n * rootCause,\n * intervention,\n * });\n * strategy.lookup(strategyKey(presetId, rootCause, intervention));\n * ```\n *\n * Pass {@link DEFAULT_PRESET_ID} (`\"default\"`) for the presetId axis when\n * no preset registry is wired (single-agent harness).\n *\n * The model feeds back into TRIAGE for routing hints.\n */\nexport function strategyModel(): StrategyModelGraph {\n\treturn auditedSuccessTracker<StrategyKey, StrategyEntry>({ name: \"strategy\" });\n}\n\n// ---------------------------------------------------------------------------\n// Priority scoring\n// ---------------------------------------------------------------------------\n\n/**\n * Create a priority scoring derived node for a single triaged item.\n *\n * Combines severity weight, attention decay, strategy model effectiveness,\n * and an optional external urgency signal.\n *\n * **Age sampling caveat.** The `ageSeconds` term is computed as\n * `monotonicNs() - lastInteractionNs.cache` at *each reactive update*. If\n * nothing upstream settles, the score node does not recompute — so a\n * long-idle queue may show a stale score. Pass a `fromTimer(...)`-driven\n * node as a dep (or re-emit on `lastInteractionNs`) when live age decay\n * matters.\n *\n * **Not the same as `TriagedItem.priority`.** The LLM-emitted\n * `priority: 0..100` field on each triaged item is decorative today — the\n * queue consumption order ignores it (tracked in `docs/optimizations.md`\n * as a priority-ordered queue enhancement). This function computes an\n * orthogonal reactive score; it does NOT override the LLM's per-item\n * priority, nor does it drive queue ordering. Wire it to\n * `HarnessGraph.priorityScores` to surface per-route pressure.\n *\n * @param item - Node holding the triaged item.\n * @param strategy - Strategy model node.\n * @param lastInteractionNs - Node holding the monotonic timestamp (ns) of last human interaction.\n * @param urgency - Optional external urgency signal node (0–1 scale).\n * @param signals - Configurable scoring parameters.\n */\nexport function priorityScore(\n\titem: Node<TriagedItem>,\n\tstrategy: Node<StrategySnapshot>,\n\tlastInteractionNs: Node<number>,\n\turgency?: Node<number>,\n\tsignals?: PrioritySignals,\n): Node<number> {\n\tconst severityWeights = { ...DEFAULT_SEVERITY_WEIGHTS, ...signals?.severityWeights };\n\tconst decayRate = signals?.decayRate ?? DEFAULT_DECAY_RATE;\n\tconst effectivenessThreshold = signals?.effectivenessThreshold ?? 0.7;\n\tconst effectivenessBoost = signals?.effectivenessBoost ?? 15;\n\n\tconst deps: Node<unknown>[] = [item, strategy, lastInteractionNs];\n\tif (urgency) deps.push(urgency);\n\n\treturn node<number>(\n\t\tdeps,\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst values = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst itm = values[0] as TriagedItem;\n\t\t\tconst strat = values[1] as StrategySnapshot;\n\t\t\tconst lastNs = values[2] as number;\n\t\t\tconst urg = urgency ? (values[3] as number) : 0;\n\n\t\t\t// Base score from severity\n\t\t\tconst baseWeight = severityWeights[itm.severity ?? \"medium\"];\n\t\t\tconst ageSeconds = (monotonicNs() - lastNs) / 1e9;\n\t\t\tlet score = decay(baseWeight, ageSeconds, decayRate, 0);\n\n\t\t\t// Strategy model boost\n\t\t\tconst key = strategyKey(DEFAULT_PRESET_ID, itm.rootCause, itm.intervention);\n\t\t\tconst entry = strat.get(key);\n\t\t\tif (entry && entry.successRate >= effectivenessThreshold) {\n\t\t\t\tscore += effectivenessBoost;\n\t\t\t}\n\n\t\t\t// External urgency boost (0–1 scale → 0–20 points)\n\t\t\tscore += urg * 20;\n\n\t\t\tactions.emit(score);\n\t\t},\n\t\t{ name: \"priority-score\", describeKind: \"derived\" },\n\t);\n}\n","/**\n * `auditedSuccessTracker` — domain-agnostic per-key success-rate tracker.\n *\n * Reactive `key → { attempts, successes, successRate }` map mounted as a\n * Graph subclass. Reusable substrate for any domain that needs to track\n * outcomes per identifier (routing strategy effectiveness, A/B-test arms,\n * cache-policy tuning, retry-strategy selection, etc.).\n *\n * Replaces the prior `effectivenessTracker` and `strategyModel` factories\n * (Class B audit Alt E collapse, 2026-04-30). Composite-key callers (e.g.\n * `rootCause × intervention`) convert to a string key at the call site.\n *\n * @module\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport { keepalive, type ReactiveMapBundle, reactiveMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\n\n/** A single success-rate record for one key. */\nexport interface AuditedSuccessEntry<TKey extends string = string> {\n\treadonly key: TKey;\n\treadonly attempts: number;\n\treadonly successes: number;\n\treadonly successRate: number;\n}\n\n/** Snapshot shape — fresh `ReadonlyMap` on every mutation. */\nexport type AuditedSuccessSnapshot<\n\tTKey extends string = string,\n\tTEntry extends AuditedSuccessEntry<TKey> = AuditedSuccessEntry<TKey>,\n> = ReadonlyMap<TKey, TEntry>;\n\n/** Options for {@link auditedSuccessTracker}. */\nexport interface AuditedSuccessTrackerOptions {\n\t/** Optional graph identity (passed to the underlying Graph constructor). */\n\tgraph?: GraphOptions;\n\t/** Name of the tracker subgraph. Default `\"audited-success-tracker\"`. */\n\tname?: string;\n}\n\n/**\n * Reactive success-rate tracker mounted as a Graph subclass.\n *\n * `key → AuditedSuccessEntry` with `record(key, success, extra?)` /\n * `lookup(key)` methods. The {@link entries} field is a\n * `Node<ReadonlyMap<TKey, TEntry>>` suitable for graph composition —\n * exposed under name `\"entries\"` for `describe()` / `explain()`.\n *\n * Backed by the {@link reactiveMap} substrate; each successful `record(...)`\n * fires a DATA emission carrying the post-mutation map.\n *\n * **Field name.** This Graph subclass uses `entries` (not `snapshot`) for\n * the public-face Node because `Graph.prototype.snapshot()` is the\n * built-in persistence-snapshot method on the parent class — using\n * `snapshot` here would shadow it and break DTS generation.\n *\n * @typeParam TKey - String-typed key shape. Composite-key domains (e.g.\n * `rootCause × intervention`) convert to a string at the call site.\n * @typeParam TEntry - Entry shape; defaults to {@link AuditedSuccessEntry}.\n * Domains that need extra fields (e.g. `rootCause`/`intervention`) extend\n * this interface and pass the extra fields via `record(...)`'s `extra` arg.\n */\nexport class AuditedSuccessTrackerGraph<\n\tTKey extends string = string,\n\tTEntry extends AuditedSuccessEntry<TKey> = AuditedSuccessEntry<TKey>,\n> extends Graph {\n\t/** Reactive entries — `Node<ReadonlyMap<TKey, TEntry>>`, fresh map per mutation. */\n\treadonly entries: Node<AuditedSuccessSnapshot<TKey, TEntry>>;\n\n\tprivate readonly _map: ReactiveMapBundle<TKey, TEntry>;\n\n\tconstructor(opts?: AuditedSuccessTrackerOptions) {\n\t\tsuper(opts?.name ?? \"audited-success-tracker\", opts?.graph);\n\t\tthis._map = reactiveMap<TKey, TEntry>({ name: \"entries\" });\n\t\tthis.entries = this._map.entries;\n\t\tthis.add(this.entries, { name: \"entries\" });\n\n\t\t// Keep the entries node activated without external subscribers so\n\t\t// `tracker.entries.cache` is readable from sync code paths and\n\t\t// `lookup()` callers don't have to manage subscriptions. Released on\n\t\t// Graph dispose along with the underlying reactiveMap.\n\t\tthis.addDisposer(keepalive(this.entries));\n\t\tthis.addDisposer(() => this._map.dispose());\n\t}\n\n\t/**\n\t * Record a completed attempt. `extra` fields are merged into the stored\n\t * entry — use for domain-specific decoration (e.g. `{ rootCause,\n\t * intervention }` on the strategy-model collapse path).\n\t *\n\t * **Caller contract for typed `TEntry`.** When `TEntry` extends\n\t * {@link AuditedSuccessEntry} with required fields beyond\n\t * `key`/`attempts`/`successes`/`successRate`, the caller must supply\n\t * those required fields in `extra` on the **first** `record(key, ...)`\n\t * for that key. The internal `as TEntry` cast trusts this. Subsequent\n\t * `record(key, ...)` calls inherit the prior entry's fields, so `extra`\n\t * may be omitted or partial. Forgetting required fields on the first\n\t * record produces an entry whose typed-required fields are `undefined`\n\t * at runtime — TS won't catch it. Strategy callers always pass\n\t * `{ rootCause, intervention }`, so the StrategyEntry case is safe.\n\t */\n\trecord(\n\t\tkey: TKey,\n\t\tsuccess: boolean,\n\t\textra?: Partial<Omit<TEntry, \"key\" | \"attempts\" | \"successes\" | \"successRate\">>,\n\t): void {\n\t\tconst existing = this._map.get(key);\n\t\tconst attempts = (existing?.attempts ?? 0) + 1;\n\t\tconst successes = (existing?.successes ?? 0) + (success ? 1 : 0);\n\t\tthis._map.set(key, {\n\t\t\t...(existing ?? {}),\n\t\t\t...(extra ?? {}),\n\t\t\tkey,\n\t\t\tattempts,\n\t\t\tsuccesses,\n\t\t\tsuccessRate: successes / attempts,\n\t\t} as TEntry);\n\t}\n\n\t/**\n\t * Look up the entry for a key.\n\t *\n\t * Pure read: this tracker doesn't configure a TTL on the underlying\n\t * `reactiveMap`, so `_map.get(key)` never triggers TTL-expiry pruning\n\t * (which would otherwise be an observable side effect emitting a fresh\n\t * `entries` snapshot). If `AuditedSuccessTrackerOptions` ever gains a\n\t * `mapOptions` carve-out exposing TTL, revisit this contract.\n\t */\n\tlookup(key: TKey): TEntry | undefined {\n\t\treturn this._map.get(key);\n\t}\n}\n\n/**\n * Construct an {@link AuditedSuccessTrackerGraph}. Replaces the prior\n * `effectivenessTracker()` and `strategyModel()` factories.\n *\n * @example\n * ```ts\n * // Generic per-action tracker\n * const tracker = auditedSuccessTracker({ name: \"ab-test\" });\n * tracker.record(\"variant-a\", true);\n * tracker.record(\"variant-b\", false);\n * tracker.entries.subscribe(snap => console.log(snap.get(\"variant-a\")));\n *\n * // Composite-key (rootCause × intervention) tracker — caller computes the key\n * type StrategyEntry = AuditedSuccessEntry<StrategyKey> & {\n * rootCause: RootCause;\n * intervention: Intervention;\n * };\n * const strategy = auditedSuccessTracker<StrategyKey, StrategyEntry>({\n * name: \"strategy\",\n * });\n * strategy.record(\n * strategyKey(rootCause, intervention),\n * true,\n * { rootCause, intervention },\n * );\n * ```\n *\n * @category extra\n */\nexport function auditedSuccessTracker<\n\tTKey extends string = string,\n\tTEntry extends AuditedSuccessEntry<TKey> = AuditedSuccessEntry<TKey>,\n>(opts?: AuditedSuccessTrackerOptions): AuditedSuccessTrackerGraph<TKey, TEntry> {\n\treturn new AuditedSuccessTrackerGraph<TKey, TEntry>(opts);\n}\n","/**\n * Harness wiring types (roadmap §9.0).\n *\n * Shared types for the reactive collaboration loop: intake, triage, queue,\n * gate, execute, verify, reflect. These types are intentionally domain-agnostic\n * — the harness loop is not specific to eval workflows.\n *\n * Runtime constants and helpers live in `./defaults.ts`. The harness barrel\n * (`./index.ts`) re-exports both so external consumers see a single surface.\n *\n * @module\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport type { NodeInput } from \"@graphrefly/pure-ts/extra\";\n// Type-only import avoids a runtime cycle with `patterns/ai`.\nimport type { LLMAdapter } from \"../ai/index.js\";\nimport type { JobEnvelope } from \"../job-queue/index.js\";\n\n// ---------------------------------------------------------------------------\n// Intake\n// ---------------------------------------------------------------------------\n\n/** Known intake source tags. */\nexport type KnownIntakeSource = \"eval\" | \"test\" | \"human\" | \"code-change\" | \"hypothesis\" | \"parity\";\n\n/**\n * Sources that can produce intake items. Open union — the known tags\n * retain IDE autocomplete while user-supplied strings (e.g. `\"schema\"`,\n * `\"slack\"`) pass through without a type change.\n */\nexport type IntakeSource = KnownIntakeSource | (string & {});\n\n/** Severity levels for intake items. */\nexport type Severity = \"critical\" | \"high\" | \"medium\" | \"low\";\n\n/** Root cause categories for triage classification. */\nexport type RootCause =\n\t| \"composition\"\n\t| \"missing-fn\"\n\t| \"bad-docs\"\n\t| \"schema-gap\"\n\t| \"regression\"\n\t| \"unknown\";\n\n/** Intervention types that address root causes. */\nexport type Intervention =\n\t| \"template\"\n\t| \"catalog-fn\"\n\t| \"docs\"\n\t| \"wrapper\"\n\t| \"schema-change\"\n\t| \"investigate\";\n\n/** Routing destinations after triage. Closed union — iterated via `QUEUE_NAMES`. */\nexport type QueueRoute = \"auto-fix\" | \"needs-decision\" | \"investigation\" | \"backlog\";\n\n/**\n * An item entering the harness loop via the INTAKE stage.\n *\n * All intake sources produce this uniform shape — the intake topic\n * doesn't care where items came from.\n *\n * `$`-prefix keys (`$reingestions`, `$retries` on {@link TriagedItem}) are\n * framework-only — an LLM round-tripping the serialized item is far less\n * likely to echo back a `$`-prefixed key than an `_`-prefixed one, which\n * neutralizes the field-collision class that surfaced earlier in the\n * router's spread order.\n */\nexport interface IntakeItem {\n\tsource: IntakeSource;\n\tsummary: string;\n\tevidence: string;\n\taffectsAreas: string[];\n\taffectsEvalTasks?: string[];\n\tseverity?: Severity;\n\t/**\n\t * Identity-preservation key for retried / reingested items.\n\t *\n\t * `relatedTo[0]` MUST carry the original tracking key for retry /\n\t * reingest items so the harness's `routeJobIds` map preserves\n\t * identity across decorated retry summaries (per qa D1, 2026-04-29).\n\t * First-time publishes leave this `undefined`; the tracking key\n\t * falls back to `summary` via {@link trackingKey}.\n\t *\n\t * **Collision contract (DS-13.5.D.3, locked 2026-05-01).** Items\n\t * lacking `relatedTo[0]` and producing colliding `trackingKey()`\n\t * derivations overwrite the prior `routeJobIds` entry —\n\t * **last-write-wins**. Framework-enforced uniqueness was rejected\n\t * because it would break legitimate retry / reingest patterns where\n\t * an explicit `relatedTo[0]` carries the original key forward.\n\t *\n\t * **Single-threaded contract.** Ack runs before reingest publishes\n\t * (harness flow invariant) — under the standard single-threaded JS\n\t * pump this collapses the only practical race window. Multi-publisher\n\t * concurrency or batched intake of two first-time items with identical\n\t * `summary` can still race at boundaries; callers carrying their own\n\t * stable id should set `relatedTo[0]`.\n\t *\n\t * See {@link trackingKey} JSDoc in `patterns/_internal/index.ts` for\n\t * the uniqueness caller contract.\n\t *\n\t * Spec: docs/implementation-plan.md DS-13.5.D.3\n\t */\n\trelatedTo?: string[];\n\t/** Item-carried reingestion count. Incremented on each full-loop reingestion. */\n\t$reingestions?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Triage output\n// ---------------------------------------------------------------------------\n\n/** Output of the TRIAGE stage — enriched intake item with classification. */\nexport interface TriagedItem extends IntakeItem {\n\trootCause: RootCause;\n\tintervention: Intervention;\n\troute: QueueRoute;\n\tpriority: number;\n\ttriageReasoning?: string;\n\t/** Item-carried retry count. Incremented on each fast-retry pass. */\n\t$retries?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Strategy model\n// ---------------------------------------------------------------------------\n\n/**\n * Preset / persona / skill identifier. Open string set; conventionally\n * matches keys used in {@link presetRegistry} (Phase 13.H). Use\n * {@link DEFAULT_PRESET_ID} (\"default\") when no preset registry is wired.\n */\nexport type PresetId = string;\n\n/** Default presetId used when no preset registry is wired (back-compat for 2-axis callers). */\nexport const DEFAULT_PRESET_ID: PresetId = \"default\";\n\n/**\n * Key format: `${presetId}|${rootCause}→${intervention}`.\n *\n * **Phase 13.I axis extension (DS-13.I, 2026-05-01).** Widened from the\n * pre-multi-agent 2-axis `${rootCause}→${intervention}` to a 3-axis key\n * carrying the presetId of the agent that ran. Pre-1.0 breaking change;\n * existing callsites pass {@link DEFAULT_PRESET_ID} for the new axis when\n * they don't have a preset registry wired. The strategy-model storage\n * (`auditedSuccessTracker<StrategyKey, StrategyEntry>`) is unchanged\n * structurally — the key shape change cascades through the existing\n * tracker without surface refactor.\n */\nexport type StrategyKey = `${PresetId}|${RootCause}→${Intervention}`;\n\n/**\n * Effectiveness record for a `(presetId, rootCause, intervention)` triple.\n * Stored under `auditedSuccessTracker<StrategyKey, StrategyEntry>` (Class B\n * audit Alt E collapse, 2026-04-30; presetId axis added Phase 13.I,\n * 2026-05-01) — `key` is the composite `strategyKey(presetId, rc, intv)`\n * computed at the call site; `presetId` / `rootCause` / `intervention` are\n * decoration carried via `record(...)` so consumers can read them without\n * re-parsing the key.\n */\nexport interface StrategyEntry {\n\tkey: StrategyKey;\n\tpresetId: PresetId;\n\trootCause: RootCause;\n\tintervention: Intervention;\n\tattempts: number;\n\tsuccesses: number;\n\tsuccessRate: number;\n}\n\n// ---------------------------------------------------------------------------\n// Execution & verification\n// ---------------------------------------------------------------------------\n\n/**\n * LLM output shape from the EXECUTE stage (partial — lacks `item`).\n *\n * Generic over the artifact type `A` so typed executors like\n * `refineExecutor<T>` can flow `T` through to an `evalVerifier<T>` without\n * the caller casting `artifact` at the boundary. Defaults to `unknown`\n * for escape-hatch executors that carry opaque state.\n */\nexport type ExecuteOutput<A = unknown> = {\n\t/**\n\t * Execution outcome classification:\n\t *\n\t * - `\"success\"`: execution completed cleanly and the artifact (if any) is\n\t * ready for verification. The verifier should proceed with a full\n\t * evaluation pass.\n\t * - `\"failure\"`: execution did not produce a usable artifact — the actuator\n\t * threw, a prompt parse failed, or `shouldApply` skipped the item. The\n\t * verifier should treat this as a non-result and route accordingly.\n\t * - `\"partial\"`: execution produced a candidate that converged but did not\n\t * fully meet verification criteria. Used by `refineExecutor` when the\n\t * iteration cap is reached without full convergence; the artifact holds\n\t * the best candidate achieved.\n\t */\n\toutcome: \"success\" | \"failure\" | \"partial\";\n\tdetail: string;\n\t/**\n\t * Optional opaque artifact that a custom executor (e.g. `refineExecutor`)\n\t * may attach so downstream verifiers can re-run evaluation against the\n\t * thing that was produced. LLM-backed default executors never populate\n\t * this — it's an escape hatch for reactive executors carrying structured\n\t * output (a refined prompt, a patched spec, a generated template, ...).\n\t */\n\tartifact?: A;\n};\n\n/** Full execution result assembled downstream (LLM output + context). */\nexport interface ExecutionResult<A = unknown> {\n\titem: TriagedItem;\n\t/**\n\t * Execution outcome classification. Same semantics as\n\t * {@link ExecuteOutput.outcome}:\n\t *\n\t * - `\"success\"`: execution completed cleanly; artifact is ready for\n\t * verification.\n\t * - `\"failure\"`: no usable artifact was produced.\n\t * - `\"partial\"`: best candidate produced but convergence criteria not met\n\t * (iteration cap reached in `refineExecutor`).\n\t */\n\toutcome: \"success\" | \"failure\" | \"partial\";\n\tdetail: string;\n\t/**\n\t * Passthrough of {@link ExecuteOutput.artifact} when the executor emitted\n\t * one. Reactive executors like `refineExecutor` populate this; LLM-backed\n\t * default executors leave it undefined.\n\t */\n\tartifact?: A;\n}\n\n/** Whether an error is self-correctable (fast-retry) or structural (full loop). */\nexport type ErrorClass = \"self-correctable\" | \"structural\";\n\n/** Classifier for fast-retry path. */\nexport type ErrorClassifier = (result: ExecutionResult) => ErrorClass;\n\n// ---------------------------------------------------------------------------\n// Verification output\n// ---------------------------------------------------------------------------\n\n/** Result of the VERIFY stage. */\nexport interface VerifyResult<A = unknown> {\n\titem: TriagedItem;\n\texecution: ExecutionResult<A>;\n\tverified: boolean;\n\tfindings: string[];\n\terrorClass?: ErrorClass;\n}\n\n/**\n * Verifier output shape — what a custom verifier emits. The harness\n * assembles this into the full {@link VerifyResult} using the triaged\n * item + execute output sampled from `executeContextNode`.\n */\nexport interface VerifyOutput {\n\tverified: boolean;\n\tfindings: string[];\n\terrorClass?: ErrorClass;\n}\n\n// ---------------------------------------------------------------------------\n// Priority scoring\n// ---------------------------------------------------------------------------\n\n/** Configurable signals for priority scoring. */\nexport interface PrioritySignals {\n\t/** Per-severity base weight (default: critical=100, high=70, medium=40, low=10). */\n\tseverityWeights?: Partial<Record<Severity, number>>;\n\t/** Decay rate per second for attention decay (default ~1.15e-6 ≈ 7-day half-life). */\n\tdecayRate?: number;\n\t/** Strategy model effectiveness boost threshold (default 0.7). */\n\teffectivenessThreshold?: number;\n\t/** Strategy model effectiveness boost amount (default 15). */\n\teffectivenessBoost?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Harness loop configuration\n// ---------------------------------------------------------------------------\n\nimport type { StrategySnapshot } from \"./strategy.js\";\n\n/** Per-queue configuration in the harness loop. */\nexport interface QueueConfig {\n\t/** Whether this queue is gated (requires human approval). */\n\tgated: boolean;\n\t/** Maximum pending items in the gate (default Infinity). */\n\tmaxPending?: number;\n\t/** Start the gate in open (auto-approve) mode? Only meaningful when `gated: true`. */\n\tstartOpen?: boolean;\n}\n\n/**\n * Accumulating per-job payload threaded through the harness's\n * `executeFlow` ({@link harnessLoop} Tier 6.5 C2 lock). Each stage's work fn\n * receives the prior payload and returns a new one with its own field\n * filled in:\n *\n * - The `enqueueEffect` seeds with `{ item }` only.\n * - The execute work fn fills `execution`.\n * - The verify work fn fills `verify`.\n *\n * The post-completed dispatch effect reads `verify.verified` /\n * `verify.errorClass` to route the item to `verifyResults` /\n * `retryTopic.publish(...)` / `intake.publish(...)` (3-way verdict).\n *\n * Carrying `item` through stage payloads (rather than re-pairing via a\n * separate `withLatestFrom` node) is the C2 deviation from today's\n * `executeContextNode` design: each `JobEnvelope` is self-contained, so the\n * verify pump can run multiple in-flight jobs in parallel without an\n * external pairing node.\n */\nexport interface HarnessJobPayload<A = unknown> {\n\t/** The triaged item flowing through execute → verify → dispatch. */\n\titem: TriagedItem;\n\t/** Filled by the execute work fn. Verify reads this; dispatch routes. */\n\texecution?: ExecutionResult<A>;\n\t/** Filled by the verify work fn. Dispatch reads `verified` / `errorClass`. */\n\tverify?: VerifyOutput;\n}\n\n/**\n * Pluggable EXECUTE work fn — receives a {@link JobEnvelope} carrying a\n * {@link HarnessJobPayload} (with `item` set, `execution` / `verify`\n * unset), returns a {@link NodeInput} that emits the same payload with\n * `execution` filled.\n *\n * **C2 contract (Tier 6.5 lock, 2026-04-28):**\n * 1. Emit DATA exactly once per claimed job. The JobFlow pump subscribes\n * once, takes the first DATA, then unsubscribes. Subsequent emissions\n * are ignored.\n * 2. Errors must be caught and surfaced as a `failure` outcome inside the\n * payload — never throw / return ERROR. A pump nack would drop the\n * item from JobFlow before the dispatch effect could route it.\n * 3. The work fn runs once per claim — no internal `switchMap` needed.\n * Per-item subgraphs (e.g. a fresh `refineLoop` per claim) are\n * instantiated inside the work fn body.\n *\n * `defaultLlmExecutor` (in `defaults.ts`) is a thin `adapter.invoke()`\n * wrapper. `refineExecutor` builds a per-claim `refineLoop`.\n * `actuatorExecutor` runs a side-effecting `apply(item, signal)`.\n */\nexport type HarnessExecutor<A = unknown> = (\n\tjob: JobEnvelope<HarnessJobPayload<A>>,\n\topts?: { signal: AbortSignal },\n) => NodeInput<HarnessJobPayload<A>>;\n\n/**\n * Pluggable VERIFY work fn — receives a {@link JobEnvelope} whose payload\n * has `item` + `execution` populated, returns a {@link NodeInput} that\n * emits the same payload with `verify` filled.\n *\n * Same C2 contract rules 1–3 as {@link HarnessExecutor}. The dispatch\n * effect downstream reads `verify.verified` (success → ack +\n * verifyResults publish), `verify.errorClass === \"self-correctable\"`\n * (retry → republish to retry topic with `$retries` bumped), or anything\n * else (structural → reingest to intake if budget remains).\n *\n * Verify-LLM-call failures (parse error, adapter throw, timeout) MUST be\n * caught and surfaced as a structural-failure `verify` payload (`{\n * verified: false, findings: [...], errorClass: \"structural\" }`) so the\n * dispatch effect can route the item rather than silently drop it.\n */\nexport type HarnessVerifier<A = unknown> = (\n\tjob: JobEnvelope<HarnessJobPayload<A>>,\n\topts?: { signal: AbortSignal },\n) => NodeInput<HarnessJobPayload<A>>;\n\n/** Triage prompt callable shape — pair of `[intake item, strategy snapshot]`. */\nexport type TriagePromptFn = (pair: readonly [IntakeItem, StrategySnapshot]) => string;\n/** Execute prompt callable shape. */\nexport type ExecutePromptFn = (item: TriagedItem) => string;\n/** Verify prompt callable shape — pair of `[execute output, triaged item]`. */\nexport type VerifyPromptFn<A = unknown> = (\n\tpair: readonly [ExecuteOutput<A> | null, TriagedItem | null],\n) => string;\n\n/** Options for {@link harnessLoop}. */\nexport interface HarnessLoopOptions<A = unknown> {\n\t/** LLM adapter for promptNode-based stages (triage + any default executor/verifier). */\n\tadapter: LLMAdapter;\n\n\t/** Custom triage prompt (receives IntakeItem + strategy snapshot as a tuple). */\n\ttriagePrompt?: string | TriagePromptFn;\n\n\t/**\n\t * Execute prompt — sugar over the default LLM executor. Ignored when\n\t * `executor` is set.\n\t */\n\texecutePrompt?: string | ExecutePromptFn;\n\n\t/**\n\t * Verify prompt — sugar over the default LLM verifier. Ignored when\n\t * `verifier` is set.\n\t */\n\tverifyPrompt?: string | VerifyPromptFn<A>;\n\n\t/**\n\t * Pluggable EXECUTE slot. When omitted, the harness uses a `promptNode`\n\t * driven by `adapter` + `executePrompt`. Replace to plug in a\n\t * `refineExecutor`, tool-using agent, or any reactive execution pipeline.\n\t */\n\texecutor?: HarnessExecutor<A>;\n\n\t/**\n\t * Pluggable VERIFY slot. When omitted, the harness uses a `promptNode`\n\t * driven by `adapter` + `verifyPrompt`. Replace to plug in an\n\t * `evalVerifier` that re-runs affected eval tasks.\n\t */\n\tverifier?: HarnessVerifier<A>;\n\n\t/** Per-queue configuration overrides. */\n\tqueues?: Partial<Record<QueueRoute, QueueConfig>>;\n\n\t/** Priority scoring signals. */\n\tpriority?: PrioritySignals;\n\n\t/**\n\t * Reactive last-human-interaction timestamp (monotonic ns). Drives the\n\t * priority score age-decay term for `HarnessGraph.priorityScores`.\n\t *\n\t * **Required when `opts.priority` is set.** Priority score nodes only\n\t * re-derive when `topic.latest`, `strategy.snapshot`, or this tick settles —\n\t * an idle queue would freeze its age at construction time if we\n\t * auto-defaulted. Typical sources:\n\t * - `fromTimer(60_000)` — steady tick, uniform decay.\n\t * - `state(monotonicNs())` — bumped from a human-interaction handler.\n\t * - A reactive view over a DB column / external metrics source.\n\t */\n\tlastInteractionNs?: Node<number>;\n\n\t/** Error classifier for fast-retry path. */\n\terrorClassifier?: ErrorClassifier;\n\n\t/** Max fast-retries per item before routing to full intake (default 2). */\n\tmaxRetries?: number;\n\n\t/** Global retry cap across all items — circuit breaker (default maxRetries × 10). */\n\tmaxTotalRetries?: number;\n\n\t/** Max re-ingestions from verify→intake before giving up (default 1). */\n\tmaxReingestions?: number;\n\n\t/** Global reingestion cap across all items — circuit breaker (default maxReingestions × 10). */\n\tmaxTotalReingestions?: number;\n\n\t/** Retained limit for topic logs (default 1000). */\n\tretainedLimit?: number;\n\n\t/**\n\t * Per-pump-tick claim cap on the internal `executeFlow` JobFlow's `execute`\n\t * stage (Tier 6.5 C2). Default `Number.MAX_SAFE_INTEGER` — every pending\n\t * claim is processed in one tick (matches today's unbounded `merge()`\n\t * parallelism). Lower this to bound LLM cost spikes on bursty intake.\n\t *\n\t * **Caveat.** This caps **claims per pump tick**, not total concurrent\n\t * inflight. Bounded-inflight is a separate primitive concern — see\n\t * `docs/optimizations.md` \"Tier 6.5 follow-up — bounded concurrent inflight\n\t * on JobFlow stages\".\n\t */\n\texecuteMaxPerPump?: number;\n\n\t/**\n\t * Per-pump-tick claim cap on the internal `executeFlow` JobFlow's\n\t * `verify` stage. Default `Number.MAX_SAFE_INTEGER`. Same caveat as\n\t * {@link HarnessLoopOptions.executeMaxPerPump}. Honored independently\n\t * of the execute cap via `StageDef.maxPerPump` (Tier 6.5 D1).\n\t */\n\tverifyMaxPerPump?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Barrel re-exports from defaults.ts — preserves the pre-split import\n// surface (`import { QUEUE_NAMES, defaultErrorClassifier } from \".../types\"`).\n// ---------------------------------------------------------------------------\n\nexport {\n\tDEFAULT_DECAY_RATE,\n\tDEFAULT_QUEUE_CONFIGS,\n\tDEFAULT_SEVERITY_WEIGHTS,\n\tdefaultErrorClassifier,\n\tQUEUE_NAMES,\n\tstrategyKey,\n} from \"./defaults.js\";\n","/**\n * Audit, policy enforcement, and compliance export (roadmap §9.2).\n *\n * Three composed factories that wrap any {@link Graph} with the harness\n * accountability layer:\n *\n * - {@link auditTrail} — reactive mutation log with by-node/by-actor/by-time\n * queries.\n * - {@link policyGate} — reactive ABAC gate (Tier 2.3 rename of\n * `policyEnforcer`); in `\"audit\"` mode records would-be denials, in\n * `\"enforce\"` mode pushes guards onto target nodes so subsequent writes\n * throw {@link GuardDenied}.\n * - {@link complianceSnapshot} — point-in-time export of graph state +\n * audit trail + policies for regulatory archival.\n *\n * @module\n */\nimport type { Actor, GuardAction, NodeGuard, PolicyRuleData } from \"@graphrefly/pure-ts/core\";\nimport {\n\tbatch,\n\tDATA,\n\tdefaultHash,\n\tmonotonicNs,\n\ttype Node,\n\tNodeImpl,\n\tnode,\n\tplaceholderArgs,\n\tpolicyFromRules,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport { keepalive, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport {\n\tGraph,\n\ttype GraphOptions,\n\ttype GraphPersistSnapshot,\n\ttype TopologyEvent,\n\twatchTopologyTree,\n} from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport { TopicGraph } from \"../messaging/index.js\";\n\n// ---------------------------------------------------------------------------\n// Shared types\n// ---------------------------------------------------------------------------\n\n/** A single recorded mutation/event in an {@link AuditTrailGraph}. */\nexport interface AuditEntry {\n\tseq: number;\n\ttimestamp_ns: number;\n\twall_clock_ns: number;\n\tpath: string;\n\ttype:\n\t\t| \"data\"\n\t\t| \"dirty\"\n\t\t| \"resolved\"\n\t\t| \"invalidate\"\n\t\t| \"pause\"\n\t\t| \"resume\"\n\t\t| \"complete\"\n\t\t| \"error\"\n\t\t| \"teardown\";\n\tactor?: Actor;\n\tvalue?: unknown;\n\terror?: unknown;\n\tannotation?: string;\n}\n\nfunction auditMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"audit\", kind, extra);\n}\n\n// ---------------------------------------------------------------------------\n// auditTrail\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_INCLUDE_TYPES: ReadonlySet<AuditEntry[\"type\"]> = new Set([\n\t\"data\",\n\t\"error\",\n\t\"complete\",\n\t\"teardown\",\n]);\n\n/** Options for {@link auditTrail}. */\nexport interface AuditTrailOptions {\n\tname?: string;\n\tgraph?: GraphOptions;\n\t/** Ring-buffer cap for the underlying `reactiveLog`. Default: unbounded. */\n\tmaxSize?: number;\n\t/**\n\t * Which event types to record. Default: `[\"data\", \"error\", \"complete\",\n\t * \"teardown\"]` — the user-meaningful set. Opt in to mid-wave protocol\n\t * events (`\"dirty\"`, `\"resolved\"`, `\"invalidate\"`, `\"pause\"`, `\"resume\"`)\n\t * by listing them explicitly. Note: those tier-1/tier-2 events do not\n\t * carry an `actor` (no `lastMutation` populated) — record them only for\n\t * protocol-level diagnostics.\n\t */\n\tincludeTypes?: readonly AuditEntry[\"type\"][];\n\t/** Per-event filter; return false to skip. */\n\tfilter?: (entry: AuditEntry) => boolean;\n}\n\n/**\n * Mounted audit log — `entries` exposes the reactive `AuditEntry[]`; query\n * helpers are sync convenience wrappers over the cached snapshot.\n */\nexport class AuditTrailGraph extends Graph {\n\treadonly entries: Node<readonly AuditEntry[]>;\n\treadonly count: Node<number>;\n\t/**\n\t * Effective set of event types this trail records (EH-18). Reflects\n\t * either the caller-supplied `opts.includeTypes` or the default set\n\t * (`[\"data\", \"error\", \"complete\", \"teardown\"]`). Captured at construction\n\t * — each instance owns its own clone, so a default-using trail can never\n\t * leak mutations into the module-level default set.\n\t *\n\t * **Mutation contract.** Type-system read-only via `ReadonlySet`. Runtime\n\t * mutation through an unsafe cast (`(audit.includeTypes as Set<...>)\n\t * .add(...)`) is unsupported — it would desync the field from the\n\t * recording closure, which captured the original `Set` reference at\n\t * construction. The runtime does NOT enforce immutability beyond the\n\t * type contract; consumers must respect it.\n\t *\n\t * Use this to validate that a `complianceSnapshot.fingerprint` was\n\t * computed against the same recording surface — fingerprints are stable\n\t * only when the recording set is identical across snapshots.\n\t */\n\treadonly includeTypes: ReadonlySet<AuditEntry[\"type\"]>;\n\tprivate readonly _log;\n\tprivate readonly _target: Graph;\n\n\tconstructor(target: Graph, opts: AuditTrailOptions) {\n\t\tsuper(opts.name ?? `${target.name}_audit`, opts.graph);\n\t\tthis._target = target;\n\t\tthis._log = reactiveLog<AuditEntry>([], {\n\t\t\tname: \"entries\",\n\t\t\t...(opts.maxSize != null ? { maxSize: opts.maxSize } : {}),\n\t\t});\n\t\tthis.entries = this._log.entries;\n\t\tthis.add(this.entries, { name: \"entries\" });\n\n\t\tthis.count = this.derived<number>(\n\t\t\t\"count\",\n\t\t\t[\"entries\"],\n\t\t\t(batchData, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\treturn [(data[0] as readonly AuditEntry[]).length];\n\t\t\t},\n\t\t\t{ meta: auditMeta(\"count\") },\n\t\t);\n\t\tthis.addDisposer(keepalive(this.count));\n\n\t\t// Always clone — DEFAULT_INCLUDE_TYPES is a module-level singleton and\n\t\t// must not be shared across instances (a cast-and-mutate via\n\t\t// `audit.includeTypes` would otherwise corrupt every default audit\n\t\t// trail in the process).\n\t\tconst includeTypes: Set<AuditEntry[\"type\"]> =\n\t\t\topts.includeTypes != null ? new Set(opts.includeTypes) : new Set(DEFAULT_INCLUDE_TYPES);\n\t\tthis.includeTypes = includeTypes;\n\t\tconst filter = opts.filter;\n\n\t\t// Monotonic per-trail. **Stagnates** (does not wrap) past\n\t\t// `Number.MAX_SAFE_INTEGER` — IEEE-754 imprecision means `seq + 1 === seq`\n\t\t// once `seq` exceeds 2^53; subsequent records would carry the same\n\t\t// stagnant value and break uniqueness. At 100k events/sec that's\n\t\t// ~3000 years — not a practical concern.\n\t\tlet seq = 0;\n\t\tconst handle = target.observe({ timeline: true, structured: true });\n\t\tconst offEvent = handle.onEvent((event) => {\n\t\t\t// `event.type` includes \"derived\" (causal-trace recompute marker) which\n\t\t\t// isn't a recordable mutation — skip it. Cast through narrowed type\n\t\t\t// after the discriminator check.\n\t\t\tif (event.type === \"derived\") return;\n\t\t\tconst type = event.type as AuditEntry[\"type\"];\n\t\t\tif (!includeTypes.has(type)) return;\n\t\t\tconst path = event.path ?? \"\";\n\t\t\tconst entry: AuditEntry = {\n\t\t\t\tseq: seq++,\n\t\t\t\ttimestamp_ns: event.timestamp_ns ?? monotonicNs(),\n\t\t\t\twall_clock_ns: wallClockNs(),\n\t\t\t\tpath,\n\t\t\t\ttype,\n\t\t\t};\n\t\t\t// Attribution + value enrichment.\n\t\t\tconst node = path ? safeNode(target, path) : undefined;\n\t\t\tconst lastMutation = node?.lastMutation;\n\t\t\tif (lastMutation != null) entry.actor = lastMutation.actor;\n\t\t\tif (type === \"data\") entry.value = (event as { data: unknown }).data;\n\t\t\tif (type === \"error\") entry.error = (event as { data: unknown }).data;\n\t\t\tconst annotation = path ? safeAnnotation(target, path) : undefined;\n\t\t\tif (annotation != null) entry.annotation = annotation;\n\t\t\tif (filter != null && !filter(entry)) return;\n\t\t\tthis._log.append(entry);\n\t\t});\n\n\t\tthis.addDisposer(() => {\n\t\t\toffEvent();\n\t\t\thandle.dispose();\n\t\t});\n\t\tthis.addDisposer(() => this._log.disposeAllViews());\n\t}\n\n\t/** All entries currently in the ring (snapshot). */\n\tall(): readonly AuditEntry[] {\n\t\treturn (this.entries.cache as readonly AuditEntry[] | undefined) ?? [];\n\t}\n\n\t/** Entries matching `path`. Order preserved. */\n\tbyNode(path: string): readonly AuditEntry[] {\n\t\treturn this.all().filter((e) => e.path === path);\n\t}\n\n\t/** Entries whose `actor.id` matches. Use `byActorType` for type filtering. */\n\tbyActor(actorId: string): readonly AuditEntry[] {\n\t\treturn this.all().filter((e) => e.actor?.id === actorId);\n\t}\n\n\t/** Entries whose `actor.type` matches (e.g. `\"llm\"`, `\"human\"`). */\n\tbyActorType(type: string): readonly AuditEntry[] {\n\t\treturn this.all().filter((e) => e.actor?.type === type);\n\t}\n\n\t/**\n\t * Entries with `timestamp_ns` in `[start_ns, end_ns)` (end exclusive).\n\t * Omit `end_ns` to query open-ended.\n\t */\n\tbyTimeRange(start_ns: number, end_ns?: number): readonly AuditEntry[] {\n\t\treturn this.all().filter((e) => {\n\t\t\tif (e.timestamp_ns < start_ns) return false;\n\t\t\tif (end_ns != null && e.timestamp_ns >= end_ns) return false;\n\t\t\treturn true;\n\t\t});\n\t}\n\n\t/** Reference to the audited graph (escape hatch for tooling). */\n\tget target(): Graph {\n\t\treturn this._target;\n\t}\n}\n\n/**\n * Wraps any {@link Graph} with a reactive audit trail recording every event\n * matching `includeTypes` (default: data + error + complete + teardown).\n *\n * Each entry carries `seq`, `timestamp_ns` (monotonic), `wall_clock_ns`,\n * `path`, `type`, and — when available — `actor`, `value`, `error`, and the\n * `graph.trace()` reasoning annotation for the path.\n *\n * The returned graph mounts an `entries` node + `count` derived. Query\n * helpers (`byNode`, `byActor`, `byTimeRange`) operate on the cached\n * snapshot synchronously.\n */\nexport function auditTrail(target: Graph, opts: AuditTrailOptions = {}): AuditTrailGraph {\n\treturn new AuditTrailGraph(target, opts);\n}\n\n// ---------------------------------------------------------------------------\n// policyGate (renamed from `policyEnforcer` per Tier 2.3 — joins the\n// gate-family disambiguation: `valve` (boolean) / `budgetGate` (numeric) /\n// `approvalGate` (human judgment) / `policyGate` (ABAC rules))\n// ---------------------------------------------------------------------------\n\n/** A single policy denial recorded by {@link PolicyGateGraph}. */\nexport interface PolicyViolation {\n\ttimestamp_ns: number;\n\twall_clock_ns: number;\n\tpath: string;\n\tactor: Actor;\n\taction: GuardAction;\n\tmode: \"audit\" | \"enforce\";\n\t/** `\"observed\"` (audit mode after-the-fact) or `\"blocked\"` (enforce mode pre-write). */\n\tresult: \"observed\" | \"blocked\";\n}\n\n/** Options for {@link policyGate}. */\nexport interface PolicyGateOptions {\n\tname?: string;\n\tgraph?: GraphOptions;\n\t/**\n\t * `\"audit\"` (default) — observe events and record would-be denials;\n\t * does not block writes. Audit mode requires `lastMutation` attribution\n\t * on the audited node — anonymous/internal writes (no `actor` passed,\n\t * unguarded node) are skipped silently because the policy cannot be\n\t * evaluated without an actor.\n\t *\n\t * `\"enforce\"` — push guards onto target nodes so disallowed writes\n\t * throw {@link GuardDenied}. Reverted on dispose.\n\t */\n\tmode?: \"audit\" | \"enforce\";\n\t/**\n\t * Restrict enforcement to specific node paths (qualified). When omitted,\n\t * applies to every node visible in `target.describe()` at construction\n\t * time (subgraphs are walked transitively) AND subscribes to the full\n\t * topology tree via {@link watchTopologyTree}, so nodes added to\n\t * `target` OR any transitively-mounted subgraph after construction are\n\t * guarded automatically (enforce mode only).\n\t *\n\t * Accepts a static `readonly string[]` or a reactive\n\t * `Node<readonly string[]>` (Tier 3.4 — F.9 reactive primitive carve-out).\n\t * When a `Node` is passed, the enforcer rebinds the guarded path set on\n\t * every emission: paths added to the new set get wrapped, paths removed\n\t * from the new set get released, and the audit-mode allow-list filter\n\t * uses the latest cached value. Static-array callers retain the current\n\t * \"caller owns the path set\" semantics.\n\t *\n\t * **Cost:** unrestricted mode runs `describe({detail:\"minimal\"})` once\n\t * at construction (O(N) over the graph tree) plus one topology\n\t * subscription per graph instance in the mount tree. Restricted mode\n\t * (static or reactive) skips both and disables `watchTopologyTree`\n\t * dynamic coverage — for reactive callers, the path-set Node is the\n\t * single source of truth for which paths are guarded.\n\t */\n\tpaths?: readonly string[] | Node<readonly string[]>;\n\t/**\n\t * Ring-buffer cap for the violations topic. Default: 1000. Static\n\t * number only — reactive form is deferred pending TopicGraph reactive\n\t * `retainedLimit` support (see Tier 10.8 design follow-up in\n\t * `docs/optimizations.md`).\n\t */\n\tviolationsLimit?: number;\n}\n\n/**\n * Reactive ABAC enforcement layer. Policies are reactive — pass a\n * `Node<readonly PolicyRuleData[]>` to allow LLMs (or any reactive source)\n * to update them at runtime; the enforcer rebinds its internal\n * {@link NodeGuard} on every push.\n */\nexport class PolicyGateGraph extends Graph {\n\treadonly policies: Node<readonly PolicyRuleData[]>;\n\treadonly violations: TopicGraph<PolicyViolation>;\n\treadonly violationCount: Node<number>;\n\tprivate readonly _target: Graph;\n\tprivate readonly _mode: \"audit\" | \"enforce\";\n\tprivate _currentGuard: NodeGuard;\n\n\tconstructor(\n\t\ttarget: Graph,\n\t\tpolicies: readonly PolicyRuleData[] | Node<readonly PolicyRuleData[]>,\n\t\topts: PolicyGateOptions,\n\t) {\n\t\tsuper(opts.name ?? `${target.name}_policy`, opts.graph);\n\t\tthis._target = target;\n\t\tthis._mode = opts.mode ?? \"audit\";\n\n\t\tconst policiesNode = isNode(policies)\n\t\t\t? policies\n\t\t\t: node<readonly PolicyRuleData[]>([], { name: \"policies\", initial: policies });\n\t\tthis.policies = policiesNode;\n\t\tthis.add(this.policies, { name: \"policies\" });\n\n\t\tthis.violations = new TopicGraph<PolicyViolation>(\"violations\", {\n\t\t\tretainedLimit: opts.violationsLimit ?? 1000,\n\t\t});\n\t\tthis.mount(\"violations\", this.violations);\n\n\t\tthis.violationCount = this.derived<number>(\n\t\t\t\"violationCount\",\n\t\t\t[\"violations::events\"],\n\t\t\t(batchData, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\treturn [(data[0] as readonly PolicyViolation[]).length];\n\t\t\t},\n\t\t\t{\n\t\t\t\tmeta: auditMeta(\"policy_violation_count\"),\n\t\t\t},\n\t\t);\n\t\tthis.addDisposer(keepalive(this.violationCount));\n\n\t\t// Factory-time seed (COMPOSITION-GUIDE §28): cache the latest rules\n\t\t// inside a closure, refresh on each subscribe-pushed update, and read\n\t\t// closure inside the guard so policy updates take effect immediately.\n\t\tconst initialRules = (policiesNode.cache as readonly PolicyRuleData[] | undefined) ?? [];\n\t\tlet latestRules: readonly PolicyRuleData[] = initialRules;\n\t\tthis._currentGuard = policyFromRules(latestRules);\n\t\tconst offPolicies = policiesNode.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tlatestRules = (m[1] as readonly PolicyRuleData[] | undefined) ?? [];\n\t\t\t\t\tthis._currentGuard = policyFromRules(latestRules);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthis.addDisposer(offPolicies);\n\n\t\t// Resolve `paths` option to its three modes:\n\t\t// (a) undefined → dynamic coverage via watchTopologyTree\n\t\t// (b) static readonly string[] → caller owns the set\n\t\t// (c) Node<readonly string[]> → reactive set; rebind on each emission\n\t\t// `latestPaths` is the closure-mirror of the current path set (or\n\t\t// undefined for dynamic coverage). It is read by:\n\t\t// - the audit-mode observe callback (allow-list filter)\n\t\t// - the reactive-paths rebind subscription (diff against next set)\n\t\t// Mirrors the `latestRules` pattern used for `policiesNode` above\n\t\t// (COMPOSITION-GUIDE §28 factory-time seed).\n\t\tconst pathsOpt = opts.paths;\n\t\tconst pathsNode: Node<readonly string[]> | undefined = isNode(pathsOpt)\n\t\t\t? (pathsOpt as Node<readonly string[]>)\n\t\t\t: undefined;\n\t\t// `pathsExplicit` mirrors the legacy \"caller provided a path set\" branch\n\t\t// — true for both static-array and Node-of-array forms; false only when\n\t\t// `opts.paths` is omitted (dynamic-coverage mode).\n\t\tconst pathsExplicit = pathsOpt != null;\n\t\tconst initialPaths: readonly string[] | undefined =\n\t\t\tpathsNode != null\n\t\t\t\t? ((pathsNode.cache as readonly string[] | undefined) ?? [])\n\t\t\t\t: pathsExplicit\n\t\t\t\t\t? [...(pathsOpt as readonly string[])]\n\t\t\t\t\t: undefined;\n\t\t// `latestPaths` is undefined ONLY in dynamic-coverage mode.\n\t\tlet latestPaths: readonly string[] | undefined = initialPaths;\n\t\t// Initial sweep set for the enforce-mode wrap loop.\n\t\tconst paths = latestPaths ?? collectPaths(target);\n\n\t\t// Audit-mode reactive-paths subscription. Enforce mode handles its own\n\t\t// subscription (it also needs to diff old↔new to wrap/release guards);\n\t\t// audit mode just needs `latestPaths` to track the latest cache so the\n\t\t// allow-list filter stays current. Wired here, before the mode branch,\n\t\t// so it runs in audit mode only — enforce mode wires its own\n\t\t// rebinding subscription with diffing logic (DRY would require an\n\t\t// always-on tracker that enforce mode then ignores; the small\n\t\t// duplication keeps the enforce-mode branch self-contained).\n\t\tif (this._mode !== \"enforce\" && pathsNode != null) {\n\t\t\tconst offAuditPaths = pathsNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\t\tlatestPaths = (m[1] as readonly string[] | undefined) ?? [];\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.addDisposer(offAuditPaths);\n\t\t}\n\n\t\tif (this._mode === \"enforce\") {\n\t\t\t// Track which paths are currently guarded so dynamic adds don't\n\t\t\t// double-wrap and removed nodes release guard handles.\n\t\t\tconst restorers = new Map<string, () => void>();\n\t\t\tconst wrapAndPush = (path: string): void => {\n\t\t\t\tif (restorers.has(path)) return;\n\t\t\t\tconst node = safeNode(target, path);\n\t\t\t\tif (!(node instanceof NodeImpl)) return;\n\t\t\t\tconst pathGuard: NodeGuard = (actor, action) => {\n\t\t\t\t\tconst ok = this._currentGuard(actor, action);\n\t\t\t\t\tif (!ok) {\n\t\t\t\t\t\tthis._publishViolation(actor, action, path, \"blocked\");\n\t\t\t\t\t}\n\t\t\t\t\treturn ok;\n\t\t\t\t};\n\t\t\t\trestorers.set(path, node._pushGuard(pathGuard));\n\t\t\t};\n\t\t\t// Initial sweep: guard every path present at construction.\n\t\t\tfor (const path of paths) wrapAndPush(path);\n\n\t\t\t// Reactive paths rebind: when `paths` is a Node, every DATA emission\n\t\t\t// replaces `latestPaths` and diffs against the previous set —\n\t\t\t// added paths get wrapped, removed paths release their guard. No\n\t\t\t// imperative orchestration; the diff falls out of the closure-mirror\n\t\t\t// + subscribe pattern (mirrors `policiesNode` above).\n\t\t\tif (pathsNode != null) {\n\t\t\t\tconst offReactivePaths = pathsNode.subscribe((msgs) => {\n\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\t\t\tconst next = (m[1] as readonly string[] | undefined) ?? [];\n\t\t\t\t\t\tconst nextSet = new Set(next);\n\t\t\t\t\t\tconst prevSet = new Set(latestPaths ?? []);\n\t\t\t\t\t\t// Wrap rebind in `batch()` (qa D7) — guards are imperative\n\t\t\t\t\t\t// graph mutations; if `paths` and `policies` co-emit in an\n\t\t\t\t\t\t// outer batch (atomic config swap), each handler's mutations\n\t\t\t\t\t\t// would otherwise unwind in arbitrary order, letting an\n\t\t\t\t\t\t// in-flight write hit a half-rebound guard set. Batching\n\t\t\t\t\t\t// coalesces release + wrap into a single deferred drain.\n\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\t// Release paths that fell out of the new set.\n\t\t\t\t\t\t\tfor (const p of prevSet) {\n\t\t\t\t\t\t\t\tif (nextSet.has(p)) continue;\n\t\t\t\t\t\t\t\tconst r = restorers.get(p);\n\t\t\t\t\t\t\t\tif (r != null) {\n\t\t\t\t\t\t\t\t\tr();\n\t\t\t\t\t\t\t\t\trestorers.delete(p);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Wrap newly-added paths.\n\t\t\t\t\t\t\tfor (const p of nextSet) {\n\t\t\t\t\t\t\t\tif (prevSet.has(p)) continue;\n\t\t\t\t\t\t\t\twrapAndPush(p);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlatestPaths = next;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tthis.addDisposer(offReactivePaths);\n\t\t\t}\n\n\t\t\t// Dynamic coverage: when `paths` was NOT explicitly provided, follow\n\t\t\t// the full topology tree (target + every transitively-mounted\n\t\t\t// subgraph, including subgraphs mounted after construction) so late\n\t\t\t// adds at any depth get guarded. `prefix` carries the qualified\n\t\t\t// path-prefix from `target` to the emitter graph.\n\t\t\tif (!pathsExplicit) {\n\t\t\t\tconst offTopology = watchTopologyTree(target, (event, emitter, prefix) => {\n\t\t\t\t\tif (event.kind === \"added\") {\n\t\t\t\t\t\tif (event.nodeKind === \"node\") {\n\t\t\t\t\t\t\twrapAndPush(`${prefix}${event.name}`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Mount added. Walk just the newly-mounted subgraph's local\n\t\t\t\t\t\t\t// paths (scoped describe — O(M) in the mounted subtree)\n\t\t\t\t\t\t\t// rather than re-describing the entire target tree. The\n\t\t\t\t\t\t\t// emitter is the PARENT of the new mount; resolve the child\n\t\t\t\t\t\t\t// via its `_mounts` map.\n\t\t\t\t\t\t\tconst child = emitter._mounts.get(event.name);\n\t\t\t\t\t\t\tif (!(child instanceof Graph)) return;\n\t\t\t\t\t\t\tconst mountPrefix = `${prefix}${event.name}::`;\n\t\t\t\t\t\t\tconst localPaths = collectPaths(child);\n\t\t\t\t\t\t\tfor (const localPath of localPaths) {\n\t\t\t\t\t\t\t\t// `localPath` is relative to `child`; qualify with the\n\t\t\t\t\t\t\t\t// mount prefix so guard keys stay target-rooted.\n\t\t\t\t\t\t\t\twrapAndPush(\n\t\t\t\t\t\t\t\t\tlocalPath === \"\" ? `${prefix}${event.name}` : `${mountPrefix}${localPath}`,\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} else if (event.kind === \"removed\") {\n\t\t\t\t\t\t// TEARDOWN already unhooks the guard; release bookkeeping so\n\t\t\t\t\t\t// re-adds under the same qualified path re-wrap cleanly.\n\t\t\t\t\t\tif (event.nodeKind === \"node\") {\n\t\t\t\t\t\t\tconst qp = `${prefix}${event.name}`;\n\t\t\t\t\t\t\tconst r = restorers.get(qp);\n\t\t\t\t\t\t\tif (r != null) {\n\t\t\t\t\t\t\t\tr();\n\t\t\t\t\t\t\t\trestorers.delete(qp);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst mountQp = `${prefix}${event.name}`;\n\t\t\t\t\t\t\tconst mountPrefix = `${mountQp}::`;\n\t\t\t\t\t\t\tfor (const [p, r] of restorers) {\n\t\t\t\t\t\t\t\tif (p === mountQp || p.startsWith(mountPrefix)) {\n\t\t\t\t\t\t\t\t\tr();\n\t\t\t\t\t\t\t\t\trestorers.delete(p);\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});\n\t\t\t\tthis.addDisposer(offTopology);\n\t\t\t} else {\n\t\t\t\t// Restricted mode: subscribe to target.topology (own-graph only —\n\t\t\t\t// explicit `paths` means caller owns the path set) so node removals\n\t\t\t\t// release their restorers instead of leaking until enforcer dispose.\n\t\t\t\tconst offCleanup = target.topology.subscribe((msgs) => {\n\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\t\t\tconst event = m[1] as TopologyEvent;\n\t\t\t\t\t\tif (event.kind !== \"removed\" || event.nodeKind !== \"node\") continue;\n\t\t\t\t\t\tconst r = restorers.get(event.name);\n\t\t\t\t\t\tif (r != null) {\n\t\t\t\t\t\t\tr();\n\t\t\t\t\t\t\trestorers.delete(event.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tthis.addDisposer(offCleanup);\n\t\t\t}\n\t\t\tthis.addDisposer(() => {\n\t\t\t\tfor (const r of restorers.values()) r();\n\t\t\t\trestorers.clear();\n\t\t\t});\n\t\t} else {\n\t\t\t// Audit mode: observe writes, evaluate against current guard, record\n\t\t\t// violations without blocking. Use the structured observe stream so\n\t\t\t// `path` and `actor` attribution are supplied without per-node\n\t\t\t// subscription bookkeeping. B9: unattributed writes no longer skip\n\t\t\t// — the ObserveEvent always carries a well-formed `actor` (falling\n\t\t\t// back to `DEFAULT_ACTOR` for anonymous/internal writes), so the\n\t\t\t// policy is evaluated against every write.\n\t\t\tconst handle = target.observe({ timeline: true, structured: true });\n\t\t\tconst off = handle.onEvent((event) => {\n\t\t\t\tif (event.type !== \"data\" && event.type !== \"error\") return;\n\t\t\t\tconst path = event.path ?? \"\";\n\t\t\t\tif (!path) return;\n\t\t\t\t// `latestPaths` is the closure-mirror of the (possibly reactive)\n\t\t\t\t// path allow-list. Undefined = no restriction (dynamic-coverage\n\t\t\t\t// mode); reactive callers see the filter rebind on each emission\n\t\t\t\t// without re-creating the enforcer (Tier 3.4).\n\t\t\t\tif (latestPaths != null && !latestPaths.includes(path)) return;\n\t\t\t\t// Prefer the event-stamped actor (always populated for DATA/ERROR\n\t\t\t\t// post-B9). Fall back to lastMutation for back-compat with any\n\t\t\t\t// consumer stubbing observe events without the field.\n\t\t\t\tconst actor =\n\t\t\t\t\t(event as { actor?: Actor }).actor ?? safeNode(target, path)?.lastMutation?.actor;\n\t\t\t\tif (actor == null) return; // defensive — shouldn't happen post-B9\n\t\t\t\tconst action: GuardAction = \"write\";\n\t\t\t\tif (this._currentGuard(actor, action)) return;\n\t\t\t\tthis._publishViolation(actor, action, path, \"observed\");\n\t\t\t});\n\t\t\tthis.addDisposer(() => {\n\t\t\t\toff();\n\t\t\t\thandle.dispose();\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate _publishViolation(\n\t\tactor: Actor,\n\t\taction: GuardAction,\n\t\tpath: string,\n\t\tresult: \"observed\" | \"blocked\",\n\t): void {\n\t\tthis.violations.publish({\n\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\twall_clock_ns: wallClockNs(),\n\t\t\tpath,\n\t\t\tactor,\n\t\t\taction,\n\t\t\tmode: this._mode,\n\t\t\tresult,\n\t\t});\n\t}\n\n\t/** Snapshot of recorded violations. */\n\tall(): readonly PolicyViolation[] {\n\t\treturn this.violations.retained();\n\t}\n\n\tget mode(): \"audit\" | \"enforce\" {\n\t\treturn this._mode;\n\t}\n\n\tget target(): Graph {\n\t\treturn this._target;\n\t}\n}\n\n/**\n * Wraps a {@link Graph} with reactive policy enforcement. Pass either a\n * static rule list or a {@link Node} of rules (LLM-updatable). Records\n * `PolicyViolation` entries to `violations` topic; in `\"enforce\"` mode also\n * pushes guards onto target nodes so disallowed writes throw.\n *\n * Self-tags via `g.tagFactory(\"policyGate\", placeholderArgs(opts))` so\n * `graph.describe()` surfaces `factory: \"policyGate\"` provenance (Phase 2.5\n * DT5 ride-along, locked with the Tier 2.3 rename).\n */\nexport function policyGate(\n\ttarget: Graph,\n\tpolicies: readonly PolicyRuleData[] | Node<readonly PolicyRuleData[]>,\n\topts: PolicyGateOptions = {},\n): PolicyGateGraph {\n\tconst g = new PolicyGateGraph(target, policies, opts);\n\t// `placeholderArgs` walks `opts` for non-JSON fields (e.g. `policies` may\n\t// be a Node when the caller wants live-updatable rules; `opts.graph` is\n\t// `GraphOptions`). DT5 deferred tag; Tier 2.3 ride-along.\n\tg.tagFactory(\"policyGate\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\treturn g;\n}\n\n// ---------------------------------------------------------------------------\n// complianceSnapshot\n// ---------------------------------------------------------------------------\n\n/** Options for {@link complianceSnapshot}. */\nexport interface ComplianceSnapshotOptions {\n\taudit?: AuditTrailGraph;\n\tpolicies?: PolicyGateGraph;\n\t/** Actor recorded as the snapshot taker. */\n\tactor?: Actor;\n}\n\n/** Output of {@link complianceSnapshot}. JSON-serializable. */\nexport interface ComplianceSnapshotResult {\n\tformat_version: 1;\n\ttimestamp_ns: number;\n\twall_clock_ns: number;\n\tactor?: Actor;\n\tgraph: GraphPersistSnapshot;\n\taudit?: { count: number; entries: AuditEntry[] };\n\tpolicies?: {\n\t\tmode: \"audit\" | \"enforce\";\n\t\trules: readonly PolicyRuleData[];\n\t\tviolations: readonly PolicyViolation[];\n\t};\n\t/**\n\t * Truncated SHA-256 hex (16 chars / ~64 bits) over a canonical encoding\n\t * of every field above (excluding `fingerprint` itself). Deterministic\n\t * across runs given identical inputs. Suitable for casual tamper-evidence\n\t * and content-addressed dedup; for full cryptographic strength, hash the\n\t * canonical JSON externally with Web Crypto / Node `crypto`.\n\t */\n\tfingerprint: string;\n}\n\n/**\n * One-shot point-in-time export of a {@link Graph}'s state plus optional\n * audit + policy bundles. Returns a JSON-serializable object with a\n * deterministic truncated-SHA-256 {@link ComplianceSnapshotResult.fingerprint}\n * over the canonical payload for tamper-evidence in regulatory archival.\n *\n * **Cryptographic strength:** the fingerprint is truncated to 64 bits for\n * compact archival. Collision-resistant for casual integrity checks but NOT\n * sufficient for adversarial tamper-evidence — pair with a full SHA-256\n * (or stronger) over the canonical JSON when regulatory requirements demand\n * collision resistance.\n */\nexport function complianceSnapshot(\n\ttarget: Graph,\n\topts: ComplianceSnapshotOptions = {},\n): ComplianceSnapshotResult {\n\tconst result: Omit<ComplianceSnapshotResult, \"fingerprint\"> = {\n\t\tformat_version: 1,\n\t\ttimestamp_ns: monotonicNs(),\n\t\twall_clock_ns: wallClockNs(),\n\t\tgraph: target.snapshot() as GraphPersistSnapshot,\n\t};\n\tif (opts.actor != null) result.actor = opts.actor;\n\tif (opts.audit != null) {\n\t\tconst entries = [...opts.audit.all()];\n\t\tresult.audit = { count: entries.length, entries };\n\t}\n\tif (opts.policies != null) {\n\t\tconst rules = (opts.policies.policies.cache as readonly PolicyRuleData[] | undefined) ?? [];\n\t\tresult.policies = {\n\t\t\tmode: opts.policies.mode,\n\t\t\trules,\n\t\t\tviolations: [...opts.policies.all()],\n\t\t};\n\t}\n\tconst fingerprint = computeFingerprint(result);\n\treturn { ...result, fingerprint };\n}\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\nfunction isNode<T>(x: unknown): x is Node<T> {\n\treturn typeof x === \"object\" && x !== null && \"subscribe\" in (x as object);\n}\n\nfunction safeNode(target: Graph, path: string): Node | undefined {\n\ttry {\n\t\treturn target.node(path);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction safeAnnotation(target: Graph, path: string): string | undefined {\n\ttry {\n\t\treturn target.annotation(path);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Walks every locally-registered node path in `target`, descending through\n * mounted subgraphs. Returns qualified paths.\n */\nfunction collectPaths(target: Graph): string[] {\n\tconst described = target.describe({ detail: \"minimal\" });\n\treturn Object.keys(described.nodes);\n}\n\n/**\n * Stable canonical JSON → truncated SHA-256 hex fingerprint (16 hex chars,\n * ~64-bit). Uses the same vendored sync SHA-256 as `core/versioning.ts`\n * `defaultHash`, so cross-module fingerprints stay consistent.\n *\n * Canonicalization handles cycles (recursion-stack tracker), `undefined`,\n * `bigint`, `Map`, `Set`, `Date`, `RegExp`, and typed arrays via typed\n * markers — see {@link canonicalize}.\n *\n * **Note:** truncated to 16 hex chars (~64-bit) for compact archival. For\n * full 256-bit cryptographic strength, hash {@link complianceSnapshot} JSON\n * externally with Web Crypto / Node `crypto`.\n */\nfunction computeFingerprint(value: unknown): string {\n\t// Pre-stringify our canonical form so `defaultHash`'s\n\t// `canonicalizeForHash` (which rejects unsafe integers) only ever sees a\n\t// JSON string. Compliance payloads carry `timestamp_ns` values that\n\t// exceed `Number.MAX_SAFE_INTEGER` — JSON.stringify handles them fine,\n\t// the hash function only cares about deterministic input bytes.\n\treturn defaultHash(JSON.stringify(canonicalize(value)));\n}\n\n/**\n * Cycle-safe canonical encoding. Uses a recursion-stack `Set` (push on\n * descent, pop on return) so legitimate DAG re-references are encoded as\n * themselves; only true cycles produce a `__circular: true` marker. Typed\n * markers preserve `undefined` / `bigint` / `Map` / `Set` / `Date` / `RegExp`\n * / typed-array information that bare `JSON.stringify` would silently drop\n * or collide with strings.\n */\nfunction canonicalize(value: unknown): unknown {\n\tconst stack = new Set<object>();\n\tconst walk = (v: unknown): unknown => {\n\t\tif (v === undefined) return { __undefined: true };\n\t\tif (v === null) return null;\n\t\tconst t = typeof v;\n\t\tif (t === \"bigint\") return { __bigint: (v as bigint).toString() };\n\t\tif (t !== \"object\") return v;\n\t\tconst obj = v as object;\n\t\tif (stack.has(obj)) return { __circular: true };\n\t\tstack.add(obj);\n\t\ttry {\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\treturn (obj as unknown[]).map(walk);\n\t\t\t}\n\t\t\tif (obj instanceof Date) {\n\t\t\t\treturn { __date: obj.toISOString() };\n\t\t\t}\n\t\t\tif (obj instanceof RegExp) {\n\t\t\t\treturn { __regexp: { source: obj.source, flags: obj.flags } };\n\t\t\t}\n\t\t\tif (obj instanceof Map) {\n\t\t\t\tconst entries = [...(obj as Map<unknown, unknown>).entries()].map(([k, mv]) => [\n\t\t\t\t\twalk(k),\n\t\t\t\t\twalk(mv),\n\t\t\t\t]);\n\t\t\t\treturn { __map: entries };\n\t\t\t}\n\t\t\tif (obj instanceof Set) {\n\t\t\t\tconst items = [...(obj as Set<unknown>)].map(walk);\n\t\t\t\treturn { __set: items };\n\t\t\t}\n\t\t\tif (ArrayBuffer.isView(obj)) {\n\t\t\t\tconst ta = obj as unknown as { length: number; [i: number]: number };\n\t\t\t\tconst arr: number[] = new Array(ta.length);\n\t\t\t\tfor (let i = 0; i < ta.length; i++) arr[i] = ta[i] ?? 0;\n\t\t\t\treturn { __typed_array: { ctor: obj.constructor.name, data: arr } };\n\t\t\t}\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tfor (const k of Object.keys(obj as Record<string, unknown>).sort()) {\n\t\t\t\tout[k] = walk((obj as Record<string, unknown>)[k]);\n\t\t\t}\n\t\t\treturn out;\n\t\t} finally {\n\t\t\tstack.delete(obj);\n\t\t}\n\t};\n\treturn walk(value);\n}\n\n// `explainPath` / `CausalChain` / `CausalStep` are exported from `graph/`\n// at module root; do not re-export here to keep the namespace boundary clean\n// and avoid duplicate-identifier issues in bundled .d.ts.\n","/**\n * Reactive graph observability preset (Tier 5.3 reshape — Session A.4 lock).\n *\n * `graphLens(target)` is a thin compositor (~30 LOC of glue) over two\n * already-shipped reactive primitives:\n *\n * - `target.describe({ reactive: true })` — live topology snapshot.\n * - `target.observe({ reactive: true, tiers: [\"data\"] })` — coalesced data\n * changesets per outermost batch flush.\n *\n * It returns three Nodes plus a dispose function:\n *\n * - `topology: Node<GraphDescribeOutput>` — the live describe snapshot,\n * re-emitting on every settle of the target tree (structural change,\n * error/complete/teardown transition).\n * - `health: Node<HealthReport>` — `{ok, problems[]}` aggregated from the\n * live describe; `ok=false` when any node enters `\"errored\"` status,\n * with `upstreamCause` walked backward through deps.\n * - `flow: Node<ReadonlyMap<string, FlowEntry>>` — per-path DATA counters\n * accumulating as `target.observe({reactive: true, tiers: [\"data\"]})`\n * delivers changesets. The map is reconciled against `topology` on each\n * topology change so removed nodes drop their entries.\n *\n * Pre-Tier-5.3 shipped a `LensGraph` class with `stats` / `health` / `flow`\n * (as a `ReactiveMapBundle`) / `why(from, to)` / `flowEntryNode(...)`. The\n * surface collapsed because every concern was already a one-liner over\n * `describe({reactive:true})` + `observe({reactive:true, tiers})` once those\n * landed in Tier 1.5.1 / 1.5.2 — the class added no protocol-level concept,\n * just glue. Callers who need topology stats compose a derived over\n * `topology` directly; callers who need a causal chain call\n * `target.describe({ explain: { from, to }, reactive: true })`.\n *\n * The transitive topology-subscription helper {@link watchTopologyTree} is\n * re-exported here for downstream factories that need full-tree dynamic\n * coverage without taking a dep on `graph/`.\n *\n * @module\n */\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport {\n\ttype Graph,\n\ttype GraphDescribeOutput,\n\ttype ObserveChangeset,\n\ttype ObserveEvent,\n\treachable,\n} from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\n\nexport { watchTopologyTree } from \"@graphrefly/pure-ts/graph\";\n\n// ---------------------------------------------------------------------------\n// Payload types\n// ---------------------------------------------------------------------------\n\n/** A single health problem entry. */\nexport interface HealthProblem {\n\tpath: string;\n\t/** V1 only reports `\"errored\"`. Future versions may add `\"completed\"`, `\"disconnected\"`. */\n\tstatus: \"errored\";\n\t/** First errored upstream ancestor along the dep chain, when one exists and is distinct from `path`. */\n\tupstreamCause?: string;\n}\n\n/** Aggregate health snapshot. `ok=true` iff `problems.length === 0`. */\nexport interface HealthReport {\n\tok: boolean;\n\tproblems: readonly HealthProblem[];\n}\n\n/** Per-path flow entry stored in the {@link GraphLensView.flow} map. */\nexport interface FlowEntry {\n\tpath: string;\n\t/** Cumulative DATA emissions observed since the lens activated. */\n\tcount: number;\n\t/** Monotonic ns at the most recent DATA emission for this path, or `null` if none yet. */\n\tlastUpdate_ns: number | null;\n}\n\n/** Output of {@link graphLens}. */\nexport interface GraphLensView {\n\t/** Live describe snapshot. Re-emits on structural change AND status transitions. */\n\ttopology: Node<GraphDescribeOutput>;\n\t/** Live `{ok, problems[]}`. Aggregated from `topology`; equality-deduped. */\n\thealth: Node<HealthReport>;\n\t/** Per-path DATA counter map. Re-emits per outermost batch flush. */\n\tflow: Node<ReadonlyMap<string, FlowEntry>>;\n\t/**\n\t * Tear down the underlying `describe({reactive:true})` subscription.\n\t * The `flow` node activates lazily; subscribing-then-unsubscribing reclaims\n\t * its observe stream automatically. Call `dispose()` once when finished.\n\t */\n\tdispose(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Pure helpers (exported for testing / composition)\n// ---------------------------------------------------------------------------\n\n/** Build a `HealthReport` from a fresh `GraphDescribeOutput`. */\nexport function computeHealthReport(described: GraphDescribeOutput): HealthReport {\n\tconst problems: HealthProblem[] = [];\n\tfor (const [path, desc] of Object.entries(described.nodes)) {\n\t\tif (desc.status !== \"errored\") continue;\n\t\tconst entry: HealthProblem = { path, status: \"errored\" };\n\t\t// Walk upstream to find the first errored ancestor (if any) distinct from `path`.\n\t\t// Explicit empty options disambiguates the overload (otherwise both match\n\t\t// and TS picks the `withDetail:true` signature first).\n\t\tconst upstream = reachable(described, path, \"upstream\", {});\n\t\tfor (const p of upstream) {\n\t\t\tif (p === path) continue;\n\t\t\tif (described.nodes[p]?.status === \"errored\") {\n\t\t\t\tentry.upstreamCause = p;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tproblems.push(entry);\n\t}\n\tproblems.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));\n\treturn { ok: problems.length === 0, problems };\n}\n\n/** Structural equality for {@link HealthReport} — used as the `health` derived's `equals`. */\nexport function healthReportEqual(a: HealthReport, b: HealthReport): boolean {\n\tif (a.ok !== b.ok) return false;\n\tif (a.problems.length !== b.problems.length) return false;\n\tfor (let i = 0; i < a.problems.length; i++) {\n\t\tconst x = a.problems[i]!;\n\t\tconst y = b.problems[i]!;\n\t\tif (x.path !== y.path) return false;\n\t\tif (x.status !== y.status) return false;\n\t\tif (x.upstreamCause !== y.upstreamCause) return false;\n\t}\n\treturn true;\n}\n\n// ---------------------------------------------------------------------------\n// graphLens preset\n// ---------------------------------------------------------------------------\n\n/**\n * Reactive observability preset over a target {@link Graph}.\n *\n * @param target - The graph to observe.\n *\n * @example\n * ```ts\n * const g = new Graph(\"app\");\n * g.add(state(0, { name: \"counter\" }), { name: \"counter\" });\n *\n * const lens = graphLens(g);\n * lens.topology.subscribe((msgs) => console.log(\"topology:\", msgs));\n * lens.health.subscribe((msgs) => console.log(\"health:\", msgs));\n * lens.flow.subscribe((msgs) => {\n * for (const [type, payload] of msgs) {\n * if (type === DATA) console.log(\"flow map size:\", (payload as ReadonlyMap<string, FlowEntry>).size);\n * }\n * });\n *\n * // Causal chains: use the underlying primitive directly — `graphLens` no\n * // longer wraps it, since `graph.describe({ explain: {...}, reactive: true })`\n * // already provides everything the old `lens.why()` did.\n * const why = g.describe({\n * explain: { from: \"counter\", to: \"consumer\" },\n * reactive: true,\n * });\n *\n * // Tear down when done.\n * lens.dispose();\n * ```\n *\n * @category observability\n */\nexport function graphLens(target: Graph): GraphLensView {\n\tconst topologyHandle = target.describe({\n\t\treactive: true,\n\t\tdetail: \"standard\",\n\t\treactiveName: \"graphLens.topology\",\n\t});\n\tconst topology = topologyHandle.node;\n\n\tconst health = node<HealthReport>(\n\t\t[topology],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(computeHealthReport(data[0] as GraphDescribeOutput));\n\t\t},\n\t\t{\n\t\t\tname: \"graphLens.health\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tequals: healthReportEqual,\n\t\t\tmeta: domainMeta(\"lens\", \"health\"),\n\t\t},\n\t);\n\t// `topology` is already kept alive by `_describeReactive`'s internal\n\t// keepalive; `health` needs its own so the derived stays warm even if\n\t// the consumer subscribes lazily.\n\tconst stopHealthKeep = keepalive(health);\n\n\t// `flow` accumulates per-path counters across emissions. Closure-mirror\n\t// (COMPOSITION-GUIDE §28) holds the canonical map; the derived returns a\n\t// fresh ReadonlyMap projection per emit so consumers never observe an\n\t// in-place mutation. Topology drives reconciliation: paths that disappear\n\t// from the describe drop their counter entry.\n\t//\n\t// `lastAppliedFlush_ns` guards against double-applying the same changeset\n\t// when topology re-emits without a new dataFlow event (e.g. a node remove\n\t// re-fires `topology` while `dataFlow.cache` still holds the previous\n\t// changeset by reference). Using the monotonic `flushedAt_ns` cursor (qa\n\t// G2A — EC4 fix) is more robust than ref-comparison: an empty changeset\n\t// re-emitted with a fresh object identity but the same `flushedAt_ns`\n\t// won't trigger a stale-events replay, and a genuinely-new changeset\n\t// always advances the cursor.\n\tconst flowMap = new Map<string, FlowEntry>();\n\tlet lastAppliedFlush_ns = -1;\n\tconst dataFlow = target.observe({ reactive: true, tiers: [\"data\"] });\n\tconst flow = node<ReadonlyMap<string, FlowEntry>>(\n\t\t[dataFlow, topology],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst changeset = data[0];\n\t\t\tconst described = data[1];\n\t\t\tconst c = changeset as ObserveChangeset | undefined;\n\t\t\tconst desc = described as GraphDescribeOutput | undefined;\n\n\t\t\t// Apply NEW changeset events first so a freshly-emitted node-remove\n\t\t\t// observed below cleanly drops the entry. (If we reconciled first\n\t\t\t// then applied, an event referencing a path the topology had already\n\t\t\t// dropped would re-create the entry only to be wiped on the next\n\t\t\t// topology re-emit — order events-then-topology to avoid that.)\n\t\t\t//\n\t\t\t// Skip when `events.length === 0`: an empty changeset has no work\n\t\t\t// to do. The cursor advances anyway so a future identical-content\n\t\t\t// changeset (different ref, same flushedAt_ns) is also skipped.\n\t\t\tif (c != null && c.flushedAt_ns > lastAppliedFlush_ns) {\n\t\t\t\tlastAppliedFlush_ns = c.flushedAt_ns;\n\t\t\t\tfor (const event of c.events as readonly ObserveEvent[]) {\n\t\t\t\t\tif (event.type !== \"data\") continue;\n\t\t\t\t\tconst path = event.path;\n\t\t\t\t\tif (path == null || path === \"\") continue;\n\t\t\t\t\tconst prior = flowMap.get(path);\n\t\t\t\t\tflowMap.set(path, {\n\t\t\t\t\t\tpath,\n\t\t\t\t\t\tcount: (prior?.count ?? 0) + 1,\n\t\t\t\t\t\tlastUpdate_ns: c.flushedAt_ns,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Reconcile against current topology — drop entries whose paths\n\t\t\t// no longer exist in the describe.\n\t\t\tif (desc != null && flowMap.size > 0) {\n\t\t\t\tconst valid = new Set(Object.keys(desc.nodes));\n\t\t\t\tfor (const k of [...flowMap.keys()]) {\n\t\t\t\t\tif (!valid.has(k)) flowMap.delete(k);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Snapshot — consumers receive a frozen view.\n\t\t\tactions.emit(new Map(flowMap) as ReadonlyMap<string, FlowEntry>);\n\t\t},\n\t\t{\n\t\t\tname: \"graphLens.flow\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: domainMeta(\"lens\", \"flow\"),\n\t\t},\n\t);\n\tconst stopFlowKeep = keepalive(flow);\n\n\tlet disposed = false;\n\treturn {\n\t\ttopology,\n\t\thealth,\n\t\tflow,\n\t\tdispose() {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\t\t\tstopFlowKeep();\n\t\t\tstopHealthKeep();\n\t\t\ttopologyHandle.dispose();\n\t\t},\n\t};\n}\n","/**\n * Job queue patterns (roadmap §4.2).\n *\n * Queue / flow primitives modeled as graph factories:\n * - `jobQueue()` — claim/ack/nack workflow with reactive depth.\n * - `jobFlow()` — multi-stage queue chain.\n *\n * Topic / subscription / hub primitives live in `patterns/messaging`.\n */\n\nimport {\n\tbatch,\n\tDATA,\n\tERROR,\n\ttype Node,\n\tnode,\n\tplaceholderArgs,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport type { AppendLogStorageTier } from \"@graphrefly/pure-ts/extra\";\nimport {\n\tfromAny,\n\tkeepalive,\n\ttype NodeInput,\n\ttype ReactiveLogBundle,\n\treactiveList,\n\treactiveLog,\n\treactiveMap,\n} from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport {\n\ttype BaseAuditRecord,\n\tbumpCursor,\n\tcreateAuditLog,\n\tmutate,\n\tregisterCursor,\n} from \"../../base/mutation/index.js\";\n\nconst DEFAULT_MAX_PER_PUMP = 256;\nconst DEFAULT_COMPLETED_RETAINED_LIMIT = 1024;\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\nfunction jobQueueMeta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"job_queue\", kind, extra);\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\n/** Audit record for a job-queue mutation (Audit 2 cross-cutting). */\nexport type JobEventAction = \"enqueue\" | \"claim\" | \"ack\" | \"nack\" | \"remove\";\n\nexport interface JobEvent<T = unknown> extends BaseAuditRecord {\n\treadonly action: JobEventAction;\n\treadonly id: string;\n\treadonly attempts?: number;\n\treadonly payload?: T;\n}\n\n/** Recommended `keyOf` for keyed-storage adapters (Audit 2 #7). */\nexport const jobEventKeyOf = <T>(e: JobEvent<T>): string => e.action;\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 readonly _seqCursor: Node<number>;\n\treadonly pending: Node<readonly string[]>;\n\treadonly jobs: Node<ReadonlyMap<string, JobEnvelope<T>>>;\n\treadonly depth: Node<number>;\n\t/** Audit log of every queue mutation (Audit 2). */\n\treadonly events: ReactiveLogBundle<JobEvent<T>>;\n\t/** Alias for {@link JobQueueGraph.events} — Audit 2 `.audit` duplication. */\n\treadonly audit: ReactiveLogBundle<JobEvent<T>>;\n\n\t// Tier 8 / COMPOSITION-GUIDE §35: mutate wrappers for the four\n\t// single-record mutation methods. Assigned in the constructor (NOT via\n\t// class-field initializers) because field initializers run before the\n\t// constructor body — `this.events` and `this._seqCursor` aren't ready yet.\n\t// `claim` stays inline because it emits one record per claimed job.\n\tprivate readonly _enqueueImpl: (\n\t\tpayload: T,\n\t\topts: { id?: string; metadata?: Record<string, unknown> },\n\t) => string;\n\tprivate readonly _ackImpl: (id: string, job: JobEnvelope<T>) => void;\n\tprivate readonly _nackImpl: (id: string, job: JobEnvelope<T>, requeue: boolean) => void;\n\tprivate readonly _removeByIdImpl: (id: string, job: JobEnvelope<T>) => void;\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(this.pending, { name: \"pending\" });\n\t\tthis.add(this.jobs, { name: \"jobs\" });\n\t\tthis.depth = node(\n\t\t\t[this.pending],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tactions.emit((data[0] as readonly string[]).length);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"depth\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: jobQueueMeta(\"queue_depth\"),\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t);\n\t\tthis.add(this.depth, { name: \"depth\" });\n\t\tthis.addDisposer(keepalive(this.depth));\n\n\t\tthis.events = createAuditLog<JobEvent<T>>({\n\t\t\tname: \"events\",\n\t\t\tretainedLimit: 1024,\n\t\t\tgraph: this,\n\t\t});\n\t\tthis.audit = this.events;\n\t\tthis._seqCursor = registerCursor(this, \"seq\", 0);\n\n\t\t// `freeze: false` everywhere because the payload may be large and\n\t\t// per-mutation cost matters on hot paths. mutate bumps `seq` via\n\t\t// the registered cursor BEFORE the action runs, so action bodies that\n\t\t// need the just-bumped value (e.g. enqueue's auto-id) read\n\t\t// `this._seqCursor.cache`.\n\t\tthis._enqueueImpl = mutate<\n\t\t\t[T, { id?: string; metadata?: Record<string, unknown> }],\n\t\t\tstring,\n\t\t\tJobEvent<T>\n\t\t>(\n\t\t\t(payload, enqueueOpts): string => {\n\t\t\t\tconst seq = this._seqCursor.cache as number;\n\t\t\t\tconst id = enqueueOpts.id ?? `${this.name}-${seq}`;\n\t\t\t\tif (this._jobs.get(id) !== undefined) {\n\t\t\t\t\tthrow new Error(`jobQueue(\"${this.name}\"): duplicate job id \"${id}\"`);\n\t\t\t\t}\n\t\t\t\tconst job: JobEnvelope<T> = {\n\t\t\t\t\tid,\n\t\t\t\t\tpayload,\n\t\t\t\t\tattempts: 0,\n\t\t\t\t\tmetadata: Object.freeze({ ...(enqueueOpts.metadata ?? {}) }),\n\t\t\t\t\tstate: \"queued\",\n\t\t\t\t};\n\t\t\t\tthis._jobs.set(id, job);\n\t\t\t\tthis._pending.append(id);\n\t\t\t\treturn id;\n\t\t\t},\n\t\t\t{\n\t\t\t\tframe: \"inline\",\n\t\t\t\tlog: this.events,\n\t\t\t\tseq: this._seqCursor,\n\t\t\t\tfreeze: false,\n\t\t\t\tonSuccessRecord: ([payload], id, { t_ns, seq }) => ({\n\t\t\t\t\taction: \"enqueue\",\n\t\t\t\t\tid,\n\t\t\t\t\tpayload,\n\t\t\t\t\tt_ns,\n\t\t\t\t\tseq: seq ?? 0,\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tthis._ackImpl = mutate<[string, JobEnvelope<T>], void, JobEvent<T>>(\n\t\t\t(id, _job): void => {\n\t\t\t\tthis._jobs.delete(id);\n\t\t\t},\n\t\t\t{\n\t\t\t\tframe: \"inline\",\n\t\t\t\tlog: this.events,\n\t\t\t\tseq: this._seqCursor,\n\t\t\t\tfreeze: false,\n\t\t\t\tonSuccessRecord: ([id, job], _r, { t_ns, seq }) => ({\n\t\t\t\t\taction: \"ack\",\n\t\t\t\t\tid,\n\t\t\t\t\tattempts: job.attempts,\n\t\t\t\t\tt_ns,\n\t\t\t\t\tseq: seq ?? 0,\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tthis._nackImpl = mutate<[string, JobEnvelope<T>, boolean], void, JobEvent<T>>(\n\t\t\t(id, job, requeue): void => {\n\t\t\t\tif (requeue) {\n\t\t\t\t\tthis._jobs.set(id, { ...job, state: \"queued\" });\n\t\t\t\t\tthis._pending.append(id);\n\t\t\t\t} else {\n\t\t\t\t\tthis._jobs.delete(id);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tframe: \"inline\",\n\t\t\t\tlog: this.events,\n\t\t\t\tseq: this._seqCursor,\n\t\t\t\tfreeze: false,\n\t\t\t\tonSuccessRecord: ([id, job], _r, { t_ns, seq }) => ({\n\t\t\t\t\taction: \"nack\",\n\t\t\t\t\tid,\n\t\t\t\t\tattempts: job.attempts,\n\t\t\t\t\tt_ns,\n\t\t\t\t\tseq: seq ?? 0,\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tthis._removeByIdImpl = mutate<[string, JobEnvelope<T>], void, JobEvent<T>>(\n\t\t\t(id, job): void => {\n\t\t\t\tif (job.state === \"queued\") {\n\t\t\t\t\tconst pending = this.pending.cache as readonly string[];\n\t\t\t\t\tconst idx = pending.indexOf(id);\n\t\t\t\t\tif (idx >= 0) this._pending.pop(idx);\n\t\t\t\t}\n\t\t\t\tthis._jobs.delete(id);\n\t\t\t},\n\t\t\t{\n\t\t\t\tframe: \"inline\",\n\t\t\t\tlog: this.events,\n\t\t\t\tseq: this._seqCursor,\n\t\t\t\tfreeze: false,\n\t\t\t\tonSuccessRecord: ([id, job], _r, { t_ns, seq }) => ({\n\t\t\t\t\taction: \"remove\",\n\t\t\t\t\tid,\n\t\t\t\t\tattempts: job.attempts,\n\t\t\t\t\tt_ns,\n\t\t\t\t\tseq: seq ?? 0,\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Wire append-log storage tiers (Audit 4). Returns a disposer.\n\t *\n\t * Named `attachEventStorage` to avoid colliding with {@link Graph.attachSnapshotStorage}.\n\t */\n\tattachEventStorage(tiers: readonly AppendLogStorageTier<JobEvent<T>>[]): () => void {\n\t\treturn this.events.attachStorage(tiers);\n\t}\n\n\tenqueue(payload: T, opts: { id?: string; metadata?: Record<string, unknown> } = {}): string {\n\t\treturn this._enqueueImpl(payload, opts);\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\t// claim emits one audit record per claimed job; mutate wraps a\n\t\t\t// single call → single record, so claim stays inline and bumps the\n\t\t\t// cursor directly via the shared `bumpCursor` helper.\n\t\t\tthis.events.append({\n\t\t\t\taction: \"claim\",\n\t\t\t\tid,\n\t\t\t\tattempts: inflight.attempts,\n\t\t\t\tt_ns: wallClockNs(),\n\t\t\t\tseq: bumpCursor(this._seqCursor),\n\t\t\t});\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._ackImpl(id, job);\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\tthis._nackImpl(id, job, opts.requeue ?? true);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Remove a job by id regardless of its current state. Returns `true` if\n\t * the job existed and was removed, `false` if no job has this id.\n\t *\n\t * `ack` only works on inflight; `nack` only works on inflight.\n\t * `removeById` is the state-agnostic escape hatch — useful for\n\t * audit/observability layers that enqueue but never claim, and need to\n\t * finalize a job when an external decision (e.g. harness verify\n\t * outcome) resolves it. Distinct name from the inherited\n\t * {@link Graph.remove}, which removes a mounted child subgraph by path.\n\t *\n\t * When the job is in `queued` state, its id is also pulled from the\n\t * `pending` list — depth + pending snapshot stay consistent.\n\t */\n\tremoveById(id: string): boolean {\n\t\tconst job = this._jobs.get(id);\n\t\tif (!job) return false;\n\t\tthis._removeByIdImpl(id, job);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Subscribe to a Node and enqueue each DATA payload into this queue.\n\t * Returns a disposer that stops consuming when called.\n\t *\n\t * Used internally by {@link JobFlowGraph} for stage-to-stage wiring but\n\t * also useful for users wiring an external source into a job queue.\n\t *\n\t * @param source - Node whose DATA values are enqueued.\n\t * @param opts - Optional enqueue options (id generator, metadata prefix).\n\t */\n\tconsumeFrom(\n\t\tsource: Node<T>,\n\t\topts?: {\n\t\t\tmetadata?: Record<string, unknown>;\n\t\t},\n\t): () => void {\n\t\treturn source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tconst payload = m[1] as T;\n\t\t\t\tthis.enqueue(payload, opts ? { metadata: opts.metadata } : undefined);\n\t\t\t}\n\t\t});\n\t}\n}\n\n// ── StageDef ─────────────────────────────────────────────────────────────\n\n/**\n * Work function for a job flow stage. Receives the full job envelope and\n * an optional per-claim options object carrying an `AbortSignal`; returns\n * a `NodeInput<T>` — raw value (sync), Promise (async), or Node (composed\n * pipeline). `fromAny` coerces any of these shapes.\n *\n * On error / rejection: the stage nacks the job (no requeue by default).\n *\n * **Per-claim signal (Tier 6.5 2.5b, 2026-04-29).** The pump mints an\n * `AbortController` per claim and supplies its `signal` via `opts`. The\n * signal aborts when (a) the result node settles (first DATA / first\n * ERROR — auto-cleanup after the pump captures), OR (b) the pump itself\n * tears down (e.g. parent Graph `destroy()`). User-supplied work fns that\n * do long-running async (HTTP, LLM streams, evaluator subgraphs) can\n * forward this signal into `fetch({ signal })`, `adapter.invoke({ signal\n * })`, etc. for cooperative cancellation. Sync work fns ignore `opts` —\n * the second arg is optional, no behavior change for legacy callers.\n *\n * Mirrors the `LLMInvokeOptions.signal` / `apply(item, { signal })` /\n * tool-handler `(args, { signal })` precedents — same shape across the\n * library's user-callback boundaries.\n */\nexport type WorkFn<T> = (job: JobEnvelope<T>, opts?: { signal: AbortSignal }) => NodeInput<T>;\n\n/**\n * Stage definition for {@link JobFlowGraph}. Either a bare name string\n * (no work hook, pure pass-through) or a full definition object.\n */\nexport type StageDef<T> =\n\t| string\n\t| {\n\t\t\tname: string;\n\t\t\twork?: WorkFn<T>;\n\t\t\thandlerVersion?: { id: string; version: string | number };\n\t\t\t/**\n\t\t\t * Per-stage cap on `claim → work → ack` cycles per pump tick.\n\t\t\t * Overrides {@link JobFlowOptions.maxPerPump} for this stage. Useful\n\t\t\t * when stages have asymmetric cost (e.g. an LLM-execute stage capped\n\t\t\t * at 4 concurrent calls while a cheap verify stage runs unbounded).\n\t\t\t *\n\t\t\t * Falls back to the top-level `JobFlowOptions.maxPerPump`, which in\n\t\t\t * turn falls back to `DEFAULT_MAX_PER_PUMP` (256).\n\t\t\t */\n\t\t\tmaxPerPump?: number;\n\t\t\t/**\n\t\t\t * Per-stage cap on TOTAL concurrent inflight claims (Tier 6.5 3.1,\n\t\t\t * 2026-04-29). Distinct from {@link maxPerPump}: `maxPerPump` caps\n\t\t\t * claims per pump tick, while `maxInflight` caps the number of\n\t\t\t * unsettled in-flight claims at any moment across all ticks. Use\n\t\t\t * for rigorous LLM cost ceilings (e.g. \"no more than 4 concurrent\n\t\t\t * adapter.invoke calls regardless of pending depth\").\n\t\t\t *\n\t\t\t * When set, the stage mounts an internal `state(0)` counter as a\n\t\t\t * pump dep so the pump re-fires on each settle — pending items\n\t\t\t * resume claiming as soon as inflight drops below the cap.\n\t\t\t *\n\t\t\t * Unset (default): unbounded inflight, gated only by `maxPerPump`.\n\t\t\t */\n\t\t\tmaxInflight?: number;\n\t };\n\nexport type JobFlowOptions<T = unknown> = {\n\tgraph?: GraphOptions;\n\t/**\n\t * Stage definitions. Each stage is either a bare name string (pure\n\t * pass-through) or a `{ name, work?, handlerVersion?, maxPerPump? }` object.\n\t *\n\t * For back-compat, `string[]` values behave as stages with no work hook.\n\t */\n\tstages?: readonly StageDef<T>[];\n\t/**\n\t * Default cap on claims per pump tick across all stages. Per-stage\n\t * overrides can be set on each {@link StageDef.maxPerPump}; if neither is\n\t * set, falls back to `DEFAULT_MAX_PER_PUMP` (256).\n\t */\n\tmaxPerPump?: number;\n};\n\nexport class JobFlowGraph<T> extends Graph {\n\tprivate readonly _stageNames: readonly string[];\n\tprivate readonly _stageWorkFns: ReadonlyMap<string, WorkFn<T>>;\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<T> = {}) {\n\t\tsuper(name, opts.graph);\n\n\t\t// Normalise stage definitions.\n\t\tconst rawStages = opts.stages ?? ([\"incoming\", \"processing\", \"done\"] as readonly StageDef<T>[]);\n\t\tconst stageNames: string[] = [];\n\t\tconst stageWorkFns = new Map<string, WorkFn<T>>();\n\t\tconst stageMaxPerPump = new Map<string, number>();\n\t\tconst stageMaxInflight = new Map<string, number>();\n\n\t\tfor (const raw of rawStages) {\n\t\t\tconst stageName = typeof raw === \"string\" ? raw.trim() : raw.name.trim();\n\t\t\tif (typeof raw !== \"string\" && raw.work) {\n\t\t\t\tstageWorkFns.set(stageName, raw.work);\n\t\t\t}\n\t\t\tif (typeof raw !== \"string\" && raw.maxPerPump != null) {\n\t\t\t\tstageMaxPerPump.set(\n\t\t\t\t\tstageName,\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\t1,\n\t\t\t\t\t\trequireNonNegativeInt(raw.maxPerPump, `job flow stage \"${stageName}\" maxPerPump`),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (typeof raw !== \"string\" && raw.maxInflight != null) {\n\t\t\t\tstageMaxInflight.set(\n\t\t\t\t\tstageName,\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\t1,\n\t\t\t\t\t\trequireNonNegativeInt(raw.maxInflight, `job flow stage \"${stageName}\" maxInflight`),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tstageNames.push(stageName);\n\t\t}\n\n\t\tif (stageNames.length < 2) {\n\t\t\tthrow new Error(`jobFlow(\"${name}\"): requires at least 2 stages`);\n\t\t}\n\t\tconst unique = new Set(stageNames);\n\t\tif (unique.size !== stageNames.length) {\n\t\t\tthrow new Error(`jobFlow(\"${name}\"): stage names must be unique`);\n\t\t}\n\t\tthis._stageNames = Object.freeze([...stageNames]);\n\t\tthis._stageWorkFns = stageWorkFns;\n\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\n\t\tthis._completed = reactiveLog<JobEnvelope<T>>([], {\n\t\t\tname: \"completed\",\n\t\t\tmaxSize: DEFAULT_COMPLETED_RETAINED_LIMIT,\n\t\t});\n\t\tthis.completed = this._completed.entries;\n\t\tthis.add(this.completed, { name: \"completed\" });\n\t\tthis.completedCount = node(\n\t\t\t[this.completed],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tactions.emit((data[0] as readonly JobEnvelope<T>[]).length);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"completedCount\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: jobQueueMeta(\"job_flow_completed_count\"),\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t);\n\t\tthis.add(this.completedCount, { name: \"completedCount\" });\n\t\tthis.addDisposer(keepalive(this.completedCount));\n\n\t\tconst defaultMaxPerPump = Math.max(\n\t\t\t1,\n\t\t\trequireNonNegativeInt(opts.maxPerPump ?? DEFAULT_MAX_PER_PUMP, \"job flow maxPerPump\"),\n\t\t);\n\n\t\t// Wire up per-stage pumps.\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 workFn = this._stageWorkFns.get(stage);\n\t\t\t// Per-stage `maxPerPump` override falls back to the top-level cap.\n\t\t\t// Captured per stage so each pump's loop sees its own resolved limit.\n\t\t\tconst stagePerPump = stageMaxPerPump.get(stage) ?? defaultMaxPerPump;\n\t\t\tconst stageMaxInflightCap = stageMaxInflight.get(stage);\n\t\t\t// When `maxInflight` is set, mount a state(0) counter on the graph\n\t\t\t// and wire it as an extra pump dep — settles `inflightCounter.emit`\n\t\t\t// re-fire the pump so pending items resume claiming after each\n\t\t\t// settle (without a counter, the pump only fires on `pending`\n\t\t\t// changes, which `ack` does not affect → maxInflight at saturation\n\t\t\t// would deadlock the queue).\n\t\t\t// qa F-D (Tier 5 /qa pass, 2026-04-29): mount under `__inflight__/`\n\t\t\t// internal namespace so the counter cannot collide with a user-named\n\t\t\t// stage (e.g. `inflight_my-stage`). Matches the EH-16\n\t\t\t// `__processManagers__/<name>` convention (COMPOSITION-GUIDE §38 —\n\t\t\t// internal infrastructure paths use the `__` prefix).\n\t\t\tconst inflightCounter =\n\t\t\t\tstageMaxInflightCap !== undefined\n\t\t\t\t\t? node<number>([], { name: `__inflight__/${stage}`, initial: 0 })\n\t\t\t\t\t: null;\n\t\t\tif (inflightCounter) {\n\t\t\t\tthis.add(inflightCounter, { name: `__inflight__/${stage}` });\n\t\t\t}\n\n\t\t\t// `isTerminal` marks the last stage — completed jobs go into\n\t\t\t// `_completed` log instead of a next queue.\n\t\t\tconst isTerminal = next === null;\n\n\t\t\tif (workFn) {\n\t\t\t\t// ── Stage with work hook ──────────────────────────────────────\n\t\t\t\t// Pump effect: claim one job, run work(job), forward result on\n\t\t\t\t// success; nack on failure.\n\t\t\t\t// Per B.3 lock: effects ARE sanctioned for side-effects.\n\t\t\t\t// `fromAny` bridges sync value / Promise / Node → Node<T>.\n\t\t\t\t//\n\t\t\t\t// **Inflight teardown drain (Tier 6.5 2.5a, 2026-04-29).** Each\n\t\t\t\t// claim mints a per-claim `AbortController` and tracks the\n\t\t\t\t// `(unsub, ac)` pair in a `ctx.store.inflight` Set. The\n\t\t\t\t// per-claim signal is supplied to the work fn via the optional\n\t\t\t\t// second-arg `{ signal }` (mirrors `LLMInvokeOptions.signal` /\n\t\t\t\t// `apply(item, {signal})` / tool-handler precedents). On the\n\t\t\t\t// pump's `deactivate` hook (parent Graph TEARDOWN cascade —\n\t\t\t\t// e.g. `harness.destroy()`), every inflight entry is aborted +\n\t\t\t\t// unsubscribed so user-supplied async work (LLM streams, eval\n\t\t\t\t// HTTP calls, refineLoop iterations) gets cooperative\n\t\t\t\t// cancellation instead of leaking past the harness lifetime.\n\t\t\t\ttype InflightEntry = { unsub: () => void; ac: AbortController };\n\t\t\t\ttype InflightStore = { entries: Set<InflightEntry>; terminated: boolean };\n\t\t\t\tconst pumpDeps: Node[] =\n\t\t\t\t\tinflightCounter != null ? [current.pending, inflightCounter] : [current.pending];\n\t\t\t\tconst pump = node<unknown>(\n\t\t\t\t\tpumpDeps,\n\t\t\t\t\t(_data, _actions, ctx) => {\n\t\t\t\t\t\tif (!(\"inflight\" in ctx.store)) {\n\t\t\t\t\t\t\tctx.store.inflight = {\n\t\t\t\t\t\t\t\tentries: new Set<InflightEntry>(),\n\t\t\t\t\t\t\t\tterminated: false,\n\t\t\t\t\t\t\t} satisfies InflightStore;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst inflightStore = ctx.store.inflight as InflightStore;\n\t\t\t\t\t\tconst inflight = inflightStore.entries;\n\t\t\t\t\t\tlet processed = 0;\n\t\t\t\t\t\twhile (processed < stagePerPump) {\n\t\t\t\t\t\t\t// 3.1 maxInflight gate: cap concurrent inflight across pump\n\t\t\t\t\t\t\t// ticks. The inflightCounter (mounted as a pump dep) re-fires\n\t\t\t\t\t\t\t// the pump when a settle decrements it, so pending items\n\t\t\t\t\t\t\t// resume claiming when capacity frees up.\n\t\t\t\t\t\t\tif (stageMaxInflightCap !== undefined && inflight.size >= stageMaxInflightCap) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst claims = current.claim(1);\n\t\t\t\t\t\t\tif (claims.length === 0) break;\n\t\t\t\t\t\t\tconst job = claims[0] as JobEnvelope<T>;\n\t\t\t\t\t\t\tif (!job) break;\n\n\t\t\t\t\t\t\t// Build the updated path accumulator.\n\t\t\t\t\t\t\tconst prevPath = (job.metadata.job_flow_path as readonly string[] | undefined) ?? [];\n\t\t\t\t\t\t\tconst newPath = [...prevPath, stage];\n\n\t\t\t\t\t\t\tconst ac = new AbortController();\n\t\t\t\t\t\t\tconst entry: InflightEntry = { unsub: () => undefined, ac };\n\t\t\t\t\t\t\tinflight.add(entry);\n\t\t\t\t\t\t\tinflightCounter?.emit(inflight.size);\n\n\t\t\t\t\t\t\tlet result: NodeInput<T>;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tresult = workFn(job, { signal: ac.signal });\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Sync throw → nack no-requeue.\n\t\t\t\t\t\t\t\tinflight.delete(entry);\n\t\t\t\t\t\t\t\tinflightCounter?.emit(inflight.size);\n\t\t\t\t\t\t\t\tcurrent.nack(job.id, { requeue: false });\n\t\t\t\t\t\t\t\tprocessed += 1;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Coerce to Node<T> via fromAny.\n\t\t\t\t\t\t\tconst resultNode = fromAny<T>(result);\n\n\t\t\t\t\t\t\t// M8: Subscribe once to the result node; on DATA forward; on ERROR nack.\n\t\t\t\t\t\t\t// Use `let unsub` + TDZ guard (same pattern as toPromise) so sync\n\t\t\t\t\t\t\t// DATA delivery inside subscribe() doesn't hit TDZ on `unsub`.\n\t\t\t\t\t\t\tlet settled = false;\n\t\t\t\t\t\t\tlet unsub: (() => void) | undefined;\n\t\t\t\t\t\t\tconst cleanupSub = (): void => {\n\t\t\t\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\t\t\t\tunsub();\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tPromise.resolve().then(() => unsub?.());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tinflight.delete(entry);\n\t\t\t\t\t\t\t\t// qa F-F (Tier 5 /qa pass, 2026-04-29): skip the counter\n\t\t\t\t\t\t\t\t// emit after teardown — the counter Node is itself in the\n\t\t\t\t\t\t\t\t// cascade. Late ERROR/DATA arriving via the deferred\n\t\t\t\t\t\t\t\t// `Promise.resolve().then(unsub)` path could otherwise emit\n\t\t\t\t\t\t\t\t// on a torn-down node.\n\t\t\t\t\t\t\t\tif (!inflightStore.terminated) {\n\t\t\t\t\t\t\t\t\tinflightCounter?.emit(inflight.size);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tunsub = resultNode.subscribe((msgs) => {\n\t\t\t\t\t\t\t\tif (settled) return;\n\t\t\t\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\t\t\t\t\tcleanupSub();\n\t\t\t\t\t\t\t\t\t\tconst newPayload = m[1] as T;\n\t\t\t\t\t\t\t\t\t\tconst newMetadata = {\n\t\t\t\t\t\t\t\t\t\t\t...job.metadata,\n\t\t\t\t\t\t\t\t\t\t\tjob_flow_path: newPath,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\tif (isTerminal) {\n\t\t\t\t\t\t\t\t\t\t\tconst completedJob: JobEnvelope<T> = {\n\t\t\t\t\t\t\t\t\t\t\t\t...job,\n\t\t\t\t\t\t\t\t\t\t\t\tpayload: newPayload,\n\t\t\t\t\t\t\t\t\t\t\t\tmetadata: Object.freeze(newMetadata),\n\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\t\t\t\t\t\tcurrent.ack(job.id);\n\t\t\t\t\t\t\t\t\t\t\t\tthis._completed.append(completedJob);\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\t\t\t\t\t\tcurrent.ack(job.id);\n\t\t\t\t\t\t\t\t\t\t\t\t(next as JobQueueGraph<T>).enqueue(newPayload, {\n\t\t\t\t\t\t\t\t\t\t\t\t\tmetadata: newMetadata,\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t} else if (m[0] === ERROR) {\n\t\t\t\t\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\t\t\t\t\tcleanupSub();\n\t\t\t\t\t\t\t\t\t\tcurrent.nack(job.id, { requeue: false });\n\t\t\t\t\t\t\t\t\t\treturn;\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});\n\t\t\t\t\t\t\tentry.unsub = () => unsub?.();\n\n\t\t\t\t\t\t\tprocessed += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\t\t\t// qa F-F: set terminated BEFORE draining so any\n\t\t\t\t\t\t\t\t// `cleanupSub` racing via the deferred-microtask path\n\t\t\t\t\t\t\t\t// (`Promise.resolve().then(() => unsub?.())`) sees\n\t\t\t\t\t\t\t\t// `terminated === true` and skips its `inflightCounter.emit`.\n\t\t\t\t\t\t\t\tinflightStore.terminated = true;\n\t\t\t\t\t\t\t\tfor (const e of inflight) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\te.ac.abort();\n\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t// best-effort\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\te.unsub();\n\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t// best-effort\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\tinflight.clear();\n\t\t\t\t\t\t\t\t// Lock 6.D (Phase 13.6.B): drop the `inflight` key\n\t\t\t\t\t\t\t\t// so the next activation re-initializes a fresh\n\t\t\t\t\t\t\t\t// `InflightStore` with `terminated: false`. Without\n\t\t\t\t\t\t\t\t// this, post-flip preserve-by-default keeps the\n\t\t\t\t\t\t\t\t// stale `terminated: true` flag and silently\n\t\t\t\t\t\t\t\t// suppresses inflight-counter emits forever.\n\t\t\t\t\t\t\t\tdelete ctx.store.inflight;\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\t{\n\t\t\t\t\t\tmeta: jobQueueMeta(\"job_flow_pump\", { stage, has_work: true }),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthis.addDisposer(keepalive(pump));\n\t\t\t} else {\n\t\t\t\t// ── Stage without work hook (pass-through ferry) ──────────────\n\t\t\t\t// Claim, accumulate path, forward to next stage or completed.\n\t\t\t\tconst pump = this.effect(\n\t\t\t\t\t`pump_${stage}`,\n\t\t\t\t\t[`${stage}::pending`],\n\t\t\t\t\t() => {\n\t\t\t\t\t\tlet moved = 0;\n\t\t\t\t\t\twhile (moved < stagePerPump) {\n\t\t\t\t\t\t\tconst claim = current.claim(1);\n\t\t\t\t\t\t\tif (claim.length === 0) break;\n\t\t\t\t\t\t\tconst job = claim[0] as JobEnvelope<T>;\n\t\t\t\t\t\t\tif (!job) break;\n\n\t\t\t\t\t\t\tconst prevPath = (job.metadata.job_flow_path as readonly string[] | undefined) ?? [];\n\t\t\t\t\t\t\tconst newPath = [...prevPath, stage];\n\t\t\t\t\t\t\tconst newMetadata = { ...job.metadata, job_flow_path: newPath };\n\n\t\t\t\t\t\t\tif (isTerminal) {\n\t\t\t\t\t\t\t\tconst completedJob: JobEnvelope<T> = {\n\t\t\t\t\t\t\t\t\t...job,\n\t\t\t\t\t\t\t\t\tmetadata: Object.freeze(newMetadata),\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\t\t\tcurrent.ack(job.id);\n\t\t\t\t\t\t\t\t\tthis._completed.append(completedJob);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbatch(() => {\n\t\t\t\t\t\t\t\t\tcurrent.ack(job.id);\n\t\t\t\t\t\t\t\t\t(next as JobQueueGraph<T>).enqueue(job.payload, {\n\t\t\t\t\t\t\t\t\t\tmetadata: newMetadata,\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}\n\t\t\t\t\t\t\tmoved += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tmeta: jobQueueMeta(\"job_flow_pump\", { stage, has_work: false }),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthis.addDisposer(keepalive(pump));\n\t\t\t}\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\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<T>): JobFlowGraph<T> {\n\tconst g = new JobFlowGraph<T>(name, opts);\n\t// Tier 1.5.3 Phase 2.5 (DG1=B): tag the Graph with its constructing\n\t// factory so `describe()` surfaces provenance. Route through\n\t// `placeholderArgs` since `stages[].work` is a function and\n\t// `opts.graph` may carry non-JSON fields.\n\tconst { factory: _f, factoryArgs: _fa, ...tagArgs } = (opts ?? {}) as Record<string, unknown>;\n\tg.tagFactory(\"jobFlow\", placeholderArgs(tagArgs));\n\treturn g;\n}\n","/**\n * Process Manager pattern (Phase 7 — roadmap §4.6, Audit 3 — locked 2026-04-24).\n *\n * Reactive long-running workflow primitive over CQRS event nodes.\n * Correlates events across aggregates, tracks per-instance state, supports\n * retries with backoff, and runs compensation on failure or explicit cancel.\n *\n * ## Architecture\n *\n * - Per-instance state lives in a `Map<correlationId, TState>` closure (in-memory).\n * The `_process_<name>_started` synthetic event is dispatched per `start()`\n * for an event-sourced audit trail using `correlationId` as `aggregateId`.\n * Cross-restart state recovery is opt-in via\n * `opts.persistence.stateStorage` (kv-tier per-correlationId snapshot,\n * Tier 6.5 3.5) plus an explicit `restore()` call after construction.\n * - Watched-event subscriptions are imperative (coordinator role) — each\n * watched CQRS event type is subscribed to via `entries.subscribe(...)`.\n * These are NOT reactive node edges; the process manager is intentionally\n * a coordinator that bridges reactive CQRS events into imperative instance logic.\n * - Step execution uses `fromAny` to uniformly handle sync and async handlers.\n * - Retry delays use `setTimeout` (same sanctioned pattern as `extra/resilience.ts`\n * retry helper — this primitive is a coordinator, not a reactive pipeline stage).\n * - Timer scheduling uses `fromTimer` from `extra/sources.ts` per spec §5.8.\n * - Audit log uses `createAuditLog` per Audit 2.\n *\n * @module\n */\n\nimport {\n\tbatch,\n\tCOMPLETE,\n\tDATA,\n\tERROR,\n\ttype Messages,\n\ttype Node,\n\tnode,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport type {\n\tAppendLogStorageTier,\n\tKvStorageTier,\n\tReactiveLogBundle,\n} from \"@graphrefly/pure-ts/extra\";\nimport {\n\tfromAny,\n\tfromIter,\n\tfromTimer,\n\tmergeMap,\n\ttype NodeInput,\n\tvalve,\n} from \"@graphrefly/pure-ts/extra\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport {\n\ttype BaseAuditRecord,\n\tcreateAuditLog,\n\tmutate,\n\tregisterCursor,\n} from \"../../base/mutation/index.js\";\nimport type { StatusValue } from \"../../base/resilience/status.js\";\nimport { firstWhere } from \"../../base/sources/settled.js\";\nimport type { CqrsEvent, CqrsEventMap, CqrsGraph } from \"../cqrs/index.js\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Discriminated union returned by each step handler.\n *\n * - `\"success\"` — step ran cleanly; update state, optionally emit\n * side-effect events and schedule a future synthetic event. The process\n * instance stays `\"running\"`.\n * - `\"terminate\"` — workflow complete; instance moves to `\"completed\"`.\n * Process-specific extension to the canonical outcome enum.\n * - `\"failure\"` — triggers compensation; instance moves to `\"cancelled\"` /\n * `\"errored\"`.\n *\n * Field name is `outcome` (matching `cqrs.DispatchRecord.outcome` and the\n * canonical Tier 1.6.2 / 2.3 enum). `\"success\"` and `\"failure\"` are the\n * canonical values; `\"terminate\"` is the process-specific extension for\n * \"early-return success\".\n */\nexport type ProcessStepResult<TState> =\n\t| {\n\t\t\toutcome: \"success\";\n\t\t\tstate: TState;\n\t\t\temit?: readonly { type: string; payload: unknown }[];\n\t\t\tschedule?: ProcessSchedule;\n\t }\n\t| {\n\t\t\toutcome: \"terminate\";\n\t\t\tstate: TState;\n\t\t\temit?: readonly { type: string; payload: unknown }[];\n\t\t\treason?: string;\n\t }\n\t| { outcome: \"failure\"; error: unknown };\n\n/**\n * Schedule a synthetic timer event after `afterMs` milliseconds.\n * When the timer fires, the synthetic event of `eventType` is routed to the\n * matching step (if one is registered) for this correlationId.\n */\nexport type ProcessSchedule = { afterMs: number; eventType: string };\n\n/**\n * Step handler signature.\n *\n * Receives the current instance state and the triggering CQRS event.\n * Returns a {@link ProcessStepResult} — sync value, Promise, or any\n * {@link NodeInput} consumed via `fromAny`.\n */\nexport type ProcessStep<TState, EM extends CqrsEventMap, K extends keyof EM & string> = (\n\tstate: TState,\n\tevent: CqrsEvent<EM[K]>,\n) => NodeInput<ProcessStepResult<TState>>;\n\n/**\n * Compensation handler. Runs when a step returns `outcome: \"failure\"`, throws, or\n * when `cancel(correlationId)` is called on a running instance.\n *\n * Should undo any side effects performed by prior steps (refund, cancel\n * reservation, etc.). Errors thrown inside compensate are swallowed and\n * recorded in the audit log with `status: \"errored\"` to prevent cascading\n * failure loops.\n */\nexport type ProcessCompensate<TState> = (state: TState, error: unknown) => NodeInput<void>;\n\n/**\n * Audit record for a single process instance state transition.\n *\n * Every status change (start → running → completed / errored / cancelled)\n * appends one record. `correlationId` is the stable process key.\n *\n * Extends {@link BaseAuditRecord} so records carry `t_ns` / `seq` /\n * `handlerVersion` from the cross-cutting Audit 2 schema.\n */\nexport interface ProcessInstance<TState> extends BaseAuditRecord {\n\t/** Stable correlation key that identifies this process instance. */\n\treadonly correlationId: string;\n\t/** Most-recent instance state at this transition. */\n\treadonly state: TState;\n\t/** Current lifecycle status after this transition. */\n\treadonly status: \"running\" | \"completed\" | \"errored\" | \"cancelled\";\n\t/** Wall-clock nanoseconds when `start()` was called. */\n\treadonly startedAt: number;\n\t/** Wall-clock nanoseconds of this transition. */\n\treadonly updatedAt: number;\n\t/** Handler version stamped at transition time (Audit 5). */\n\treadonly handlerVersion?: { id: string; version: string | number };\n\t/** Optional human-readable reason for cancellation. Present only on `\"cancelled\"` records produced by `cancel()`. */\n\treadonly reason?: string;\n}\n\n/**\n * Recommended `keyOf` for storage tiers keyed by correlationId (Audit 2).\n */\nexport const processInstanceKeyOf = <TState>(i: ProcessInstance<TState>): string => i.correlationId;\n\n/**\n * Per-correlationId state snapshot persisted via\n * {@link ProcessManagerOpts.persistence.stateStorage} (Tier 6.5 3.5,\n * 2026-04-29). Captures the running instance's current state plus\n * lifecycle metadata so a fresh `processManager` can resume in-flight\n * workflows after restart via {@link ProcessManagerResult.restore}.\n *\n * Terminal records (`status` ∈ `\"completed\" | \"errored\" | \"cancelled\"`)\n * are deleted from the kv tier on transition — only running instances\n * persist between restarts.\n */\nexport interface ProcessStateSnapshot<TState> {\n\treadonly correlationId: string;\n\treadonly state: TState;\n\treadonly status: \"running\" | \"completed\" | \"errored\" | \"cancelled\";\n\treadonly startedAt: number;\n\treadonly updatedAt: number;\n\treadonly handlerVersion?: { id: string; version: string | number };\n}\n\n/** Recommended `keyOf` for `KvStorageTier<ProcessStateSnapshot<...>>`. */\nexport const processStateKeyOf = <TState>(s: ProcessStateSnapshot<TState>): string =>\n\ts.correlationId;\n\n/**\n * Options for {@link processManager}.\n */\nexport interface ProcessManagerOpts<TState, EM extends CqrsEventMap> {\n\t/** Initial state value for every new process instance. */\n\treadonly initial: TState;\n\t/** CQRS event types to watch for correlation routing. */\n\treadonly watching: readonly (keyof EM & string)[];\n\t/**\n\t * Per-event-type step handlers. A step is invoked when a watched event's\n\t * `correlationId` matches a running instance and the event type is in\n\t * `steps`. Events with no matching step are silently ignored.\n\t */\n\treadonly steps: { [K in keyof EM & string]?: ProcessStep<TState, EM, K> };\n\t/**\n\t * Optional compensation handler. Runs on step `outcome: \"failure\"` / step throw\n\t * and on explicit `cancel()`. If omitted, instances fail silently with\n\t * status `\"errored\"` instead of `\"cancelled\"`.\n\t */\n\treadonly compensate?: ProcessCompensate<TState>;\n\t/**\n\t * Optional predicate called after each `\"success\"` step. When it returns\n\t * `true`, the instance is moved to `\"completed\"` immediately without\n\t * waiting for a `\"terminate\"` step result.\n\t */\n\treadonly isTerminal?: (state: TState) => boolean;\n\t/**\n\t * Maximum number of retry attempts after a step throws (not counting the\n\t * first attempt). Default: `0` (no retry — fail immediately on throw).\n\t */\n\treadonly retryMax?: number;\n\t/**\n\t * Per-retry backoff delays in milliseconds. `backoffMs[i]` is the delay\n\t * before attempt `i + 1`. If fewer entries than `retryMax`, the last entry\n\t * is repeated. Default: `[0]` (no delay).\n\t *\n\t * **Implementation note:** retry delays are implemented with `setTimeout`\n\t * (same sanctioned exception as `extra/resilience.ts`). This is a\n\t * coordinator-layer primitive — `fromTimer` would require subscribing to\n\t * an additional node per attempt, which would leak timer nodes without a\n\t * clear disposal scope.\n\t */\n\treadonly backoffMs?: readonly number[];\n\t/** Handler version tag stamped onto audit records (Audit 5). */\n\treadonly handlerVersion?: { id: string; version: string | number };\n\t/**\n\t * When `true`, do NOT auto-restore on construction. The caller must invoke\n\t * {@link ProcessManagerResult.restore} explicitly to load persisted\n\t * snapshots and arm watch dispatch.\n\t *\n\t * **Default `false`:** the factory kicks off restoration immediately so\n\t * watch dispatch arms as soon as snapshots have loaded (or instantly when\n\t * no `stateStorage` tier is configured). Until restoration completes,\n\t * watched events accumulate at the source but are valve-blocked from\n\t * reaching the per-instance step pipeline (B5 — locked 2026-05-01).\n\t */\n\treadonly deferRestore?: boolean;\n\t/**\n\t * Maximum number of concurrent `tier.load(key)` calls during restore.\n\t *\n\t * The restore pipeline streams keys from `tier.list()` through\n\t * `mergeMap`, which by default subscribes to inner sources unbounded\n\t * (parallel up to the number of keys). For storage tiers with large\n\t * persisted-instance counts (10K+), unbounded concurrency can exhaust\n\t * file handles, connection pools, or the backend's concurrent-request\n\t * budget. This option caps the in-flight load count.\n\t *\n\t * **Default `8`** (D2 lock 2026-05-01). Set higher for backends with\n\t * generous concurrency budgets; set to `Number.POSITIVE_INFINITY` for\n\t * the prior unbounded behavior.\n\t */\n\treadonly restoreConcurrency?: number;\n\t/** Optional persistence wiring (Audit 4). */\n\treadonly persistence?: {\n\t\t/**\n\t\t * Wire the per-process synthetic state event stream to append-log tiers.\n\t\t * Reuses `CqrsGraph.attachEventStorage` so events persist across restarts.\n\t\t */\n\t\teventStorage?: readonly AppendLogStorageTier<CqrsEvent>[];\n\t\t/**\n\t\t * Wire per-correlationId state snapshots to kv tiers (Tier 6.5 3.5,\n\t\t * 2026-04-29). Each `start()` and step transition writes the running\n\t\t * instance's state under its `correlationId`; terminal transitions\n\t\t * (`completed` / `errored` / `cancelled`) `delete` the key. After\n\t\t * restart, callers invoke {@link ProcessManagerResult.restore} to\n\t\t * reload running instances from the first tier.\n\t\t *\n\t\t * Uses {@link KvStorageTier} (not snapshot tier) because per-instance\n\t\t * state is N records keyed by correlationId, not a single global\n\t\t * snapshot. {@link processStateKeyOf} is the recommended `keyOf`\n\t\t * (already aligned with the kv tier's `save(key, value)` shape).\n\t\t *\n\t\t * Terminal records are NOT preserved — historical lifecycle is the\n\t\t * audit log's job. State persistence covers crash-recovery only.\n\t\t */\n\t\tstateStorage?: readonly KvStorageTier<ProcessStateSnapshot<TState>>[];\n\t};\n}\n\n/**\n * Result handle returned by {@link processManager}.\n */\nexport interface ProcessManagerResult<TState> {\n\t/**\n\t * Reactive audit log of every process instance state transition.\n\t * Every `start()`, step result, retry, cancellation, and compensation\n\t * appends a {@link ProcessInstance} record.\n\t */\n\treadonly instances: ReactiveLogBundle<ProcessInstance<TState>>;\n\t/**\n\t * Alias for {@link instances} (Audit 2 `.audit` duplication convention).\n\t */\n\treadonly audit: ReactiveLogBundle<ProcessInstance<TState>>;\n\t/**\n\t * Start a new process instance identified by `correlationId`.\n\t *\n\t * Emits a synthetic `_process_<name>_started` event into the CQRS graph\n\t * with `correlationId` as `aggregateId` so per-aggregate streams record\n\t * the process lifecycle. If the correlationId already has an active\n\t * (running) instance, this call is a no-op (idempotent).\n\t *\n\t * @param correlationId - Stable key for this workflow instance.\n\t * @param initialPayload - Optional payload carried on the start event.\n\t */\n\tstart(correlationId: string, initialPayload?: unknown): void;\n\t/**\n\t * Cancel a running instance by correlationId.\n\t *\n\t * Triggers the `compensate` handler (if configured), then marks the\n\t * instance as `\"cancelled\"`. If the instance is not running, this is\n\t * a no-op.\n\t *\n\t * @param correlationId - Instance to cancel.\n\t * @param reason - Optional human-readable reason recorded in the audit log.\n\t */\n\tcancel(correlationId: string, reason?: string): void;\n\t/**\n\t * Synchronous read of the current in-memory state for a correlationId.\n\t * Returns `undefined` if the instance does not exist or has terminated.\n\t */\n\tgetState(correlationId: string): TState | undefined;\n\t/**\n\t * Reactive lifecycle of the restore pipeline. Typed as the central\n\t * {@link StatusValue} enum (`\"pending\" | \"running\" | \"completed\" | \"errored\"`);\n\t * the process-manager restore state machine currently emits the `\"pending\"`\n\t * and `\"completed\"` literals only — `\"running\"` / `\"errored\"` reserved\n\t * for future fine-grained restore observability. Starts at `\"pending\"`,\n\t * flips to `\"completed\"` once snapshot loads complete (or immediately when\n\t * no `stateStorage` is configured). On {@link dispose}, the node receives\n\t * TEARDOWN via the standard subgraph teardown cascade — there is no\n\t * `\"disposed\"` literal; consumers detect tear-down via subscription\n\t * COMPLETE on {@link dispose}. Watched events are valve-gated on this\n\t * node: dispatch is blocked while `restoreState !== \"completed\"`.\n\t *\n\t * Exposed for observability and tests. Subscribers can compose\n\t * `derived([restoreState], …)` to build their own gates / readouts.\n\t */\n\treadonly restoreState: Node<StatusValue>;\n\t/**\n\t * Trigger restoration of running instances from the first\n\t * {@link ProcessManagerOpts.persistence.stateStorage} tier (Tier 6.5\n\t * 3.5, 2026-04-29). Loads every record in the tier reactively and\n\t * re-hydrates `instanceStates` / `activeInstances` / `startedAt` for\n\t * any record whose `status === \"running\"`. Terminal records, if any\n\t * persisted before delete fired, are silently skipped.\n\t *\n\t * **Reactive composition (B5 — locked 2026-05-01):** internally,\n\t * `tier.list()` and `tier.load()` are wrapped in `fromAny` sources\n\t * (handles sync values, Promises, async iterables, and existing Nodes\n\t * uniformly per `~/src/graphrefly/COMPOSITION-GUIDE.md` §3 source\n\t * bridging); a `mergeMap` flattens per-key load results; an `effect`\n\t * populates closure state and flips {@link restoreState} to\n\t * `\"completed\"` on the `COMPLETE` boundary. No `await` inside the\n\t * reactive interior — the single async boundary is the returned\n\t * `Promise<void>`, which resolves when {@link restoreState} transitions\n\t * to `\"completed\"` OR when {@link dispose} tears down the restore node\n\t * (in which case `firstWhere`'s COMPLETE-rejection is swallowed and\n\t * the promise resolves to `undefined`).\n\t *\n\t * Idempotent — calling twice subscribes to the same restore pipeline\n\t * and resolves on the same gate flip. No-op when no `stateStorage`\n\t * tier is configured OR the first tier lacks a `list?` method:\n\t * `restoreState` flips to `\"completed\"` immediately so watches can arm.\n\t *\n\t * **Auto-restore default.** With `deferRestore: false` (the default),\n\t * the factory invokes `restore()` once at construction so callers do\n\t * not need to remember to wire it. Pass `deferRestore: true` to\n\t * suppress auto-restore and call `restore()` manually.\n\t */\n\trestore(): Promise<void>;\n\t/**\n\t * Release all watched-event subscriptions and stop processing new events.\n\t *\n\t * After `dispose()`, subsequent `start()` and `cancel()` calls are no-ops.\n\t * In-flight async steps complete naturally; no new steps are dispatched.\n\t *\n\t * Tears down the {@link restoreState} node via the standard subgraph\n\t * teardown cascade. Any pending `restore()` Promise resolves (the\n\t * COMPLETE-rejection from `firstWhere` is swallowed at the API edge);\n\t * the watch valve closes via TEARDOWN propagation; no further dispatch\n\t * even if a `fromAny(tier.load…)` would resolve later (the per-key\n\t * load source's cleanup sets `settled = true`, dropping the late DATA).\n\t */\n\tdispose(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Materialise a `NodeInput<T>` into a Promise.\n * Uses `fromAny` to normalise Node / Promise / iterable / scalar, then\n * collects the first DATA message.\n *\n * - If `input` is `null` or `undefined`, resolves immediately with `undefined`\n * (skips constructing a `fromAny` source).\n * - On COMPLETE without prior DATA, resolves with `undefined` (supports `void`\n * compensate handlers whose `NodeInput<void>` delivers COMPLETE only).\n *\n * Implementation note: `fromAny` over a scalar (e.g. `void` / `undefined`) or\n * sync iterable delivers DATA synchronously inside `n.subscribe()`, BEFORE the\n * `subscribe()` call returns. We therefore use `let unsub` (not `const`) and\n * avoid calling `unsub()` until after `subscribe()` has returned — deferring\n * the cleanup to a microtask via `Promise.resolve().then(unsub)` to sidestep\n * the Temporal Dead Zone.\n */\nfunction toPromise<T>(input: NodeInput<T>): Promise<T> {\n\t// Short-circuit: null/undefined input resolves immediately.\n\tif (input == null) return Promise.resolve(undefined as T);\n\n\tconst n = fromAny<T>(input);\n\treturn new Promise<T>((resolve, reject) => {\n\t\tlet settled = false;\n\t\t// `let` instead of `const` so that synchronous DATA delivery during\n\t\t// n.subscribe() (before the assignment completes) doesn't hit TDZ.\n\t\tlet unsub: (() => void) | undefined;\n\t\tconst cleanup = () => {\n\t\t\tif (unsub) {\n\t\t\t\tunsub();\n\t\t\t}\n\t\t};\n\t\tunsub = n.subscribe((msgs) => {\n\t\t\tif (settled) return;\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\t// Defer cleanup to after the subscribe() call returns (TDZ-safe).\n\t\t\t\t\tPromise.resolve().then(cleanup);\n\t\t\t\t\tresolve(m[1] as T);\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\tPromise.resolve().then(cleanup);\n\t\t\t\t\treject(m[1] as unknown);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\t// COMPLETE without prior DATA — resolve with undefined.\n\t\t\t\t\t// Supports void compensate handlers that return without emitting DATA.\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tPromise.resolve().then(cleanup);\n\t\t\t\t\tresolve(undefined as T);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/** Run `step(state, event)` with retry logic. Returns the step result. */\nasync function runWithRetry<TState>(\n\tstep: (state: TState, event: CqrsEvent) => NodeInput<ProcessStepResult<TState>>,\n\tstate: TState,\n\tevent: CqrsEvent,\n\tretryMax: number,\n\tbackoffMs: readonly number[],\n): Promise<ProcessStepResult<TState>> {\n\tlet lastError: unknown;\n\tfor (let attempt = 0; attempt <= retryMax; attempt++) {\n\t\tif (attempt > 0) {\n\t\t\t// Sanctioned setTimeout for retry backoff in coordinator primitives.\n\t\t\t// Same pattern as extra/resilience.ts retry implementation.\n\t\t\tconst delayMs = backoffMs[Math.min(attempt - 1, backoffMs.length - 1)] ?? 0;\n\t\t\tif (delayMs > 0) {\n\t\t\t\tawait new Promise<void>((r) => setTimeout(r, delayMs));\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tconst result = await toPromise(step(state, event));\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tlastError = err;\n\t\t\t// If we've exhausted retries, fall through to return a fail result.\n\t\t}\n\t}\n\treturn { outcome: \"failure\", error: lastError };\n}\n\n// ---------------------------------------------------------------------------\n// processManager factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a process manager that coordinates long-running reactive workflows\n * over a {@link CqrsGraph}.\n *\n * Process instances are identified by `correlationId`. Events from the watched\n * event types are routed to per-instance step handlers when the event's\n * `correlationId` matches a running instance.\n *\n * ```ts\n * const app = cqrs<{ orderPlaced: { orderId: string }; paymentReceived: { amount: number } }>(\"orders\");\n *\n * const pm = processManager(app, \"fulfillment\", {\n * initial: { step: \"awaiting-payment\", total: 0 },\n * watching: [\"orderPlaced\", \"paymentReceived\"],\n * steps: {\n * orderPlaced(state, event) {\n * return { outcome: \"success\", state: { ...state, orderId: event.payload.orderId } };\n * },\n * paymentReceived(state, event) {\n * return { outcome: \"terminate\", state: { ...state, total: event.payload.amount } };\n * },\n * },\n * compensate(state, _error) {\n * // undo reservation, issue refund, etc.\n * },\n * retryMax: 2,\n * backoffMs: [100, 500],\n * });\n *\n * pm.start(\"order-123\");\n * app.dispatch(\"orderPlaced\", { orderId: \"order-123\" }, { correlationId: \"order-123\" });\n * ```\n *\n * @param cqrsGraph - The CQRS graph whose event streams the manager watches.\n * @param name - Stable identifier for this process type; used for the\n * synthetic event-type prefix `_process_<name>_*`. Currently emits\n * `_process_<name>_started` per `start()`; the prefix is reserved for\n * future `_state` / `_timer` channels.\n * @param opts - Configuration: initial state, watched events, steps, retry,\n * compensation, and optional persistence.\n * @returns {@link ProcessManagerResult} with `instances` audit log and\n * `start`, `cancel`, `getState` imperative controls.\n *\n * @category patterns\n */\nexport function processManager<TState, EM extends CqrsEventMap = Record<string, unknown>>(\n\tcqrsGraph: CqrsGraph<EM>,\n\tname: string,\n\topts: ProcessManagerOpts<TState, EM>,\n): ProcessManagerResult<TState> {\n\tconst retryMax = opts.retryMax ?? 0;\n\tconst backoffMs: readonly number[] = opts.backoffMs ?? [0];\n\tconst retainedLimit = 1024;\n\n\t// ── Per-instance in-memory state ──────────────────────────────────────\n\t// Map from correlationId → current TState for running instances.\n\t// Imperative coordinator state — documented pattern for this primitive.\n\tconst instanceStates = new Map<string, TState>();\n\t// Track which instances are \"active\" (running) to prevent double-start\n\t// and to gate step delivery.\n\tconst activeInstances = new Set<string>();\n\t// Track startedAt per instance.\n\tconst startedAt = new Map<string, number>();\n\n\t// ── Audit log + seq cursor ────────────────────────────────────────────\n\t// EH-16 (Tier 6.5 3.3, 2026-04-29): the audit log + seq cursor are\n\t// mounted under a per-instance child Graph (`__processManagers__/<name>`)\n\t// rather than directly under `cqrsGraph._nodes`. `dispose()` then calls\n\t// `cqrsGraph.remove(...)` to unmount the subgraph cleanly via the\n\t// existing mount/removeMount lifecycle — no leaked nodes after repeated\n\t// create/dispose cycles. Pre-1.0 path-schema change: paths shift from\n\t// `${name}_process_instances` / `${name}_process_seq` (top-level) to\n\t// `__processManagers__/${name}::instances` / `::seq` (mounted).\n\tconst mountName = `__processManagers__/${name}`;\n\tconst subgraph = new Graph(name);\n\ttry {\n\t\tcqrsGraph.mount(mountName, subgraph);\n\t} catch (err) {\n\t\t// `Graph.mount` throws if the mount name is in use; surface a\n\t\t// processManager-specific message so callers see actionable context.\n\t\tconst detail = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(\n\t\t\t`processManager: name \"${name}\" is already in use on this CQRS graph ` +\n\t\t\t\t`(mount path \"${mountName}\" collides). Call .dispose() on the prior ` +\n\t\t\t\t`manager OR pick a different name before re-creating. (${detail})`,\n\t\t);\n\t}\n\n\tconst instances = createAuditLog<ProcessInstance<TState>>({\n\t\tname: \"instances\",\n\t\tretainedLimit,\n\t\tgraph: subgraph,\n\t});\n\n\t// Tier 8 γ-7-A (2026-04-28): seq cursor promoted from `let seq = 0` closure\n\t// to a `state(0)` node mounted on the per-process subgraph (visible in\n\t// `describe()` at `__processManagers__/<name>::seq`). The audit-record\n\t// stamping routes through `mutate` for centralized freeze + seq\n\t// advance + `handlerVersion` stamping + batch-frame rollback. The batch\n\t// frame closes EH-17 (re-entrancy hazard).\n\tconst seqCursor = registerCursor(subgraph, \"seq\", 0);\n\n\t// D4 (qa lock): `freeze: true` so step-handler-supplied state values\n\t// captured into audit records cannot be mutated post-record. Process\n\t// states are typically small workflow records (an order ID + a few\n\t// flags), so the `deepFreeze` tax is negligible — the safety vs. mutation\n\t// trade-off favors freeze. (The 768-dim-vector concern that motivates\n\t// `freeze: false` in memory primitives doesn't apply here.)\n\tconst appendRecord = mutate<\n\t\t[string, TState, ProcessInstance<TState>[\"status\"], string | undefined],\n\t\tvoid,\n\t\tProcessInstance<TState>\n\t>(\n\t\t// No closure-state mutation in the action — the audit-record append IS\n\t\t// the effect, performed by the framework via `onSuccessRecord`.\n\t\t() => undefined,\n\t\t{\n\t\t\tframe: \"transactional\",\n\t\t\tlog: instances,\n\t\t\tseq: seqCursor,\n\t\t\tfreeze: true,\n\t\t\t...(opts.handlerVersion !== undefined ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\tonSuccessRecord: ([correlationId, state, status, reason], _r, { t_ns, seq }) => ({\n\t\t\t\tcorrelationId,\n\t\t\t\tstate,\n\t\t\t\tstatus,\n\t\t\t\tstartedAt: startedAt.get(correlationId) ?? t_ns,\n\t\t\t\tupdatedAt: t_ns,\n\t\t\t\tt_ns,\n\t\t\t\tseq: seq ?? 0,\n\t\t\t\t...(reason !== undefined ? { reason } : {}),\n\t\t\t}),\n\t\t},\n\t);\n\n\t// ── State-snapshot persistence (Tier 6.5 3.5) ─────────────────────────\n\tconst stateStorageTiers = opts.persistence?.stateStorage ?? [];\n\n\t/**\n\t * Build the snapshot payload + iterate tiers. Returns the iterator over\n\t * tiers so the caller decides whether sync throws propagate (B4 — start\n\t * path inside mutate) or are swallowed (step path, fire-and-forget).\n\t */\n\tconst buildSnapshot = (\n\t\tcorrelationId: string,\n\t\tstatus: ProcessStateSnapshot<TState>[\"status\"],\n\t): ProcessStateSnapshot<TState> | undefined => {\n\t\tconst stateValue = instanceStates.get(correlationId);\n\t\tif (stateValue === undefined) return undefined;\n\t\treturn {\n\t\t\tcorrelationId,\n\t\t\tstate: stateValue,\n\t\t\tstatus,\n\t\t\tstartedAt: startedAt.get(correlationId) ?? wallClockNs(),\n\t\t\tupdatedAt: wallClockNs(),\n\t\t\t...(opts.handlerVersion !== undefined ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t};\n\t};\n\n\t/**\n\t * Best-effort persistence (used by step transitions). Sync throws are\n\t * swallowed so persistence failures do NOT poison reactive step dispatch.\n\t * Async rejections are caught at the Promise boundary.\n\t */\n\tconst persistState = (\n\t\tcorrelationId: string,\n\t\tstatus: ProcessStateSnapshot<TState>[\"status\"],\n\t): void => {\n\t\tif (stateStorageTiers.length === 0) return;\n\t\tconst snapshot = buildSnapshot(correlationId, status);\n\t\tif (snapshot === undefined) return;\n\t\tfor (const tier of stateStorageTiers) {\n\t\t\ttry {\n\t\t\t\tconst r = tier.save(correlationId, snapshot);\n\t\t\t\t// Tier may return Promise — fire-and-forget. Storage errors\n\t\t\t\t// surface via the tier's own onError plumbing (Tier 4 storage).\n\t\t\t\tif (r != null && typeof (r as Promise<void>).then === \"function\") {\n\t\t\t\t\t(r as Promise<void>).catch(() => undefined);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// best-effort; persistence failures don't block step execution\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Throwing variant (B4 — used inside `startInternal`'s mutate\n\t * action body so a sync-throwing tier rolls back the audit-log append +\n\t * seq cursor advance). Async rejections from `tier.save()` still cannot\n\t * unwind the synchronous batch frame — that's a known limitation of\n\t * Promise-returning storage; sync-throwing tiers (the actual D2 hazard)\n\t * are fully covered.\n\t */\n\tconst persistStateThrowing = (\n\t\tcorrelationId: string,\n\t\tstatus: ProcessStateSnapshot<TState>[\"status\"],\n\t): void => {\n\t\tif (stateStorageTiers.length === 0) return;\n\t\tconst snapshot = buildSnapshot(correlationId, status);\n\t\tif (snapshot === undefined) return;\n\t\tfor (const tier of stateStorageTiers) {\n\t\t\tconst r = tier.save(correlationId, snapshot);\n\t\t\tif (r != null && typeof (r as Promise<void>).then === \"function\") {\n\t\t\t\t(r as Promise<void>).catch(() => undefined);\n\t\t\t}\n\t\t}\n\t};\n\tconst removeState = (correlationId: string): void => {\n\t\tif (stateStorageTiers.length === 0) return;\n\t\tfor (const tier of stateStorageTiers) {\n\t\t\tif (!tier.delete) continue;\n\t\t\ttry {\n\t\t\t\tconst r = tier.delete(correlationId);\n\t\t\t\tif (r != null && typeof (r as Promise<void>).then === \"function\") {\n\t\t\t\t\t(r as Promise<void>).catch(() => undefined);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// best-effort\n\t\t\t}\n\t\t}\n\t};\n\n\t// ── Synthetic event helpers ───────────────────────────────────────────\n\tconst startedEventType = `_process_${name}_started`;\n\n\t// Pre-register the started event stream so it appears in describe().\n\t// Side-effect events (result.emit) dispatch using their own declared event type\n\t// via _appendEvent directly — no separate state event stream needed.\n\tcqrsGraph.event(startedEventType);\n\n\t// Wire persistence: event storage for synthetic state stream.\n\tif (opts.persistence?.eventStorage) {\n\t\tcqrsGraph.attachEventStorage(opts.persistence.eventStorage);\n\t}\n\n\t// ── Compensation helper ───────────────────────────────────────────────\n\tasync function runCompensate(\n\t\tcorrelationId: string,\n\t\tstate: TState,\n\t\terror: unknown,\n\t\treason?: string,\n\t): Promise<void> {\n\t\t// Eagerly remove from active state BEFORE any await so that concurrent\n\t\t// cancel() calls or in-flight step completions that arrive while we are\n\t\t// awaiting the compensate handler find the instance already gone and\n\t\t// exit early (C1 — double-compensation race fix).\n\t\tactiveInstances.delete(correlationId);\n\t\tinstanceStates.delete(correlationId);\n\t\tstartedAt.delete(correlationId);\n\n\t\tif (opts.compensate) {\n\t\t\ttry {\n\t\t\t\tawait toPromise(opts.compensate(state, error) as NodeInput<void>);\n\t\t\t\tappendRecord(correlationId, state, \"cancelled\", reason);\n\t\t\t\tremoveState(correlationId);\n\t\t\t} catch (_compErr) {\n\t\t\t\t// Compensation itself failed — still mark as errored so instance\n\t\t\t\t// doesn't stay in limbo. Swallow error to prevent cascading.\n\t\t\t\tappendRecord(correlationId, state, \"errored\", undefined);\n\t\t\t\tremoveState(correlationId);\n\t\t\t}\n\t\t} else {\n\t\t\tappendRecord(correlationId, state, \"errored\", undefined);\n\t\t\tremoveState(correlationId);\n\t\t}\n\t}\n\n\t// ── Step result handler ───────────────────────────────────────────────\n\tasync function handleStepResult(\n\t\tcorrelationId: string,\n\t\tresult: ProcessStepResult<TState>,\n\t): Promise<void> {\n\t\tif (!activeInstances.has(correlationId)) return; // cancelled during async step\n\n\t\tif (result.outcome === \"failure\") {\n\t\t\t// Capture state before eager delete (C1 — step-fail eager-delete).\n\t\t\tconst state = instanceStates.get(correlationId) ?? opts.initial;\n\t\t\t// runCompensate handles the eager delete; the early-exit guard above\n\t\t\t// ensures we won't double-compensate for an already-inactive instance.\n\t\t\tawait runCompensate(correlationId, state, result.error);\n\t\t\treturn;\n\t\t}\n\n\t\tif (result.outcome === \"success\") {\n\t\t\tinstanceStates.set(correlationId, result.state);\n\n\t\t\t// Emit side-effect CQRS events.\n\t\t\tif (result.emit) {\n\t\t\t\tfor (const ev of result.emit) {\n\t\t\t\t\t// Dispatch via _appendEvent is internal. Use a synthetic command\n\t\t\t\t\t// channel via the public `dispatch` API by pre-registering a\n\t\t\t\t\t// passthrough command, OR emit directly via an internal event.\n\t\t\t\t\t// Strategy: use event stream directly — the process manager is\n\t\t\t\t\t// an internal coordinator allowed to call internal CQRS APIs.\n\t\t\t\t\t// We use the synthetic stateEventType to carry side-effect events\n\t\t\t\t\t// so they appear in the aggregate stream.\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Emit side-effect events using the process state event stream with\n\t\t\t\t\t\t// the correlationId as aggregateId, but use the declared event type\n\t\t\t\t\t\t// as the type field for downstream sagas/projections to react to.\n\t\t\t\t\t\t// We do this by directly dispatching into the CQRS graph via the\n\t\t\t\t\t\t// dedicated per-process synthetic event channel.\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tcqrsGraph as unknown as {\n\t\t\t\t\t\t\t\t_appendEvent(\n\t\t\t\t\t\t\t\t\tname: string,\n\t\t\t\t\t\t\t\t\tpayload: unknown,\n\t\t\t\t\t\t\t\t\textra?: { correlationId?: string; aggregateId?: string },\n\t\t\t\t\t\t\t\t): void;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t)._appendEvent(ev.type, ev.payload, {\n\t\t\t\t\t\t\tcorrelationId,\n\t\t\t\t\t\t\taggregateId: correlationId,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (_emitErr) {\n\t\t\t\t\t\t// Non-fatal: side-effect event emission failures are not\n\t\t\t\t\t\t// step-fatal (they are fire-and-forget coordination signals).\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tappendRecord(correlationId, result.state, \"running\", undefined);\n\t\t\tpersistState(correlationId, \"running\");\n\n\t\t\t// Check isTerminal predicate.\n\t\t\tif (opts.isTerminal?.(result.state)) {\n\t\t\t\tactiveInstances.delete(correlationId);\n\t\t\t\tinstanceStates.delete(correlationId);\n\t\t\t\tstartedAt.delete(correlationId); // M3 — cleanup startedAt on isTerminal terminate\n\t\t\t\tappendRecord(correlationId, result.state, \"completed\", undefined);\n\t\t\t\tremoveState(correlationId);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Handle schedule: fire synthetic event after delay via fromTimer.\n\t\t\tif (result.schedule) {\n\t\t\t\tconst { afterMs, eventType } = result.schedule;\n\t\t\t\t// fromTimer per spec §5.8 — reactive timer source.\n\t\t\t\t// Subscribe to fire once and deliver the synthetic event.\n\t\t\t\t// M6: use `let timerUnsub` + TDZ guard to avoid referencing the\n\t\t\t\t// variable before its assignment if the callback fires synchronously.\n\t\t\t\tlet timerUnsub: (() => void) | undefined;\n\t\t\t\tconst timerNode = fromTimer(afterMs);\n\t\t\t\tconst timerCb: Parameters<typeof timerNode.subscribe>[0] = (msgs) => {\n\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\t\t// TDZ guard: if subscribe() hasn't returned yet, defer cleanup.\n\t\t\t\t\t\t\tif (timerUnsub) {\n\t\t\t\t\t\t\t\ttimerUnsub();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// fromTimer is async (setTimeout-backed) so this path is\n\t\t\t\t\t\t\t\t// never hit in practice, but guard for safety.\n\t\t\t\t\t\t\t\tqueueMicrotask(() => timerUnsub?.());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!activeInstances.has(correlationId)) return;\n\t\t\t\t\t\t\tconst currentState = instanceStates.get(correlationId);\n\t\t\t\t\t\t\tif (currentState === undefined) return;\n\t\t\t\t\t\t\tconst step = (\n\t\t\t\t\t\t\t\topts.steps as unknown as Record<string, ProcessStep<TState, EM, string>>\n\t\t\t\t\t\t\t)[eventType];\n\t\t\t\t\t\t\tif (!step) return;\n\t\t\t\t\t\t\tconst syntheticEvent: CqrsEvent = {\n\t\t\t\t\t\t\t\ttype: eventType,\n\t\t\t\t\t\t\t\t// m5: null payload (not undefined) to avoid soft §1.2 risk.\n\t\t\t\t\t\t\t\t// seq: Number.NaN — sentinel for synthetic events that do not\n\t\t\t\t\t\t\t\t// participate in cross-event ordering.\n\t\t\t\t\t\t\t\tpayload: null,\n\t\t\t\t\t\t\t\ttimestampNs: wallClockNs(),\n\t\t\t\t\t\t\t\tseq: Number.NaN,\n\t\t\t\t\t\t\t\tcorrelationId,\n\t\t\t\t\t\t\t\taggregateId: correlationId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tdispatchStep(correlationId, step, currentState, syntheticEvent);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\ttimerUnsub = timerNode.subscribe(timerCb);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (result.outcome === \"terminate\") {\n\t\t\tinstanceStates.set(correlationId, result.state);\n\t\t\t// Emit side-effect events.\n\t\t\tif (result.emit) {\n\t\t\t\tfor (const ev of result.emit) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tcqrsGraph as unknown as {\n\t\t\t\t\t\t\t\t_appendEvent(\n\t\t\t\t\t\t\t\t\tname: string,\n\t\t\t\t\t\t\t\t\tpayload: unknown,\n\t\t\t\t\t\t\t\t\textra?: { correlationId?: string; aggregateId?: string },\n\t\t\t\t\t\t\t\t): void;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t)._appendEvent(ev.type, ev.payload, {\n\t\t\t\t\t\t\tcorrelationId,\n\t\t\t\t\t\t\taggregateId: correlationId,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (_emitErr) {\n\t\t\t\t\t\t// non-fatal\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tactiveInstances.delete(correlationId);\n\t\t\tinstanceStates.delete(correlationId);\n\t\t\tstartedAt.delete(correlationId); // M3 — cleanup startedAt on terminate\n\t\t\tappendRecord(correlationId, result.state, \"completed\", undefined);\n\t\t\tremoveState(correlationId);\n\t\t}\n\t}\n\n\t// ── Step dispatch ─────────────────────────────────────────────────────\n\t// C2: Per-correlationId in-flight serialization map.\n\t// Multiple events for the same correlationId in one DATA wave both read the\n\t// same instanceStates snapshot if dispatched concurrently. Serializing via a\n\t// promise chain ensures the second step sees the first step's written state.\n\t// Cross-correlationId events still parallelize (separate map entries).\n\tconst inFlight = new Map<string, Promise<void>>();\n\n\tfunction dispatchStep(\n\t\tcorrelationId: string,\n\t\tstep: ProcessStep<TState, EM, string>,\n\t\t_state: TState, // C2: state is re-read inside the serialized closure; this param is kept for call-site clarity\n\t\tevent: CqrsEvent,\n\t): void {\n\t\tconst prior = inFlight.get(correlationId) ?? Promise.resolve();\n\t\tconst next = prior.then(async () => {\n\t\t\t// Re-read current state at execution time (prior steps may have updated it).\n\t\t\tconst currentState = instanceStates.get(correlationId);\n\t\t\tif (currentState === undefined) return; // instance was cancelled/terminated in prior step\n\t\t\tif (!activeInstances.has(correlationId)) return;\n\t\t\tlet result: ProcessStepResult<TState>;\n\t\t\ttry {\n\t\t\t\tresult = await runWithRetry(\n\t\t\t\t\tstep as (s: TState, e: CqrsEvent) => NodeInput<ProcessStepResult<TState>>,\n\t\t\t\t\tcurrentState,\n\t\t\t\t\tevent,\n\t\t\t\t\tretryMax,\n\t\t\t\t\tbackoffMs,\n\t\t\t\t);\n\t\t\t} catch (err) {\n\t\t\t\t// runWithRetry itself should not throw (it returns fail on exhaustion),\n\t\t\t\t// but guard against unexpected errors.\n\t\t\t\tawait runCompensate(correlationId, instanceStates.get(correlationId) ?? opts.initial, err);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait handleStepResult(correlationId, result);\n\t\t});\n\t\tinFlight.set(correlationId, next);\n\t\tnext.finally(() => {\n\t\t\tif (inFlight.get(correlationId) === next) inFlight.delete(correlationId);\n\t\t});\n\t}\n\n\t// C3: disposal flag — set true by dispose(); gates start() and cancel().\n\t// Synchronous liveness check used by start() / cancel() to avoid\n\t// reaching into the reactive layer (and to short-circuit before the\n\t// teardown cascade has propagated through restoreState).\n\tlet _disposed = false;\n\n\t// ── Restore lifecycle state (B5 — locked 2026-05-01; post-fix using\n\t// central StatusValue enum 2026-05-01) ───────────────────────────────\n\t// Reactive lifecycle node typed as the central StatusValue enum\n\t// (`\"pending\" | \"running\" | \"completed\" | \"errored\"`). Currently emits\n\t// the \"pending\" → \"completed\" subset only:\n\t// \"pending\" → constructed; restore not yet finished. Watched events\n\t// arrive at the source but are valve-blocked from\n\t// reaching step dispatch.\n\t// \"completed\" → restoration complete. Watch valve is open; events\n\t// accumulated during \"pending\" are delivered as the\n\t// latest cumulative cqrs log array; the per-watch\n\t// cursor catches up to that array in one step.\n\t// (\"running\" / \"errored\" reserved for future fine-grained restore\n\t// observability; not emitted today.)\n\t// Disposal: no \"disposed\" literal — dispose() unmounts the subgraph\n\t// which TEARDOWNs restoreState; the gateOpen valve closes via standard\n\t// cascade; pending restore() Promise resolves via the .catch at the\n\t// public API edge.\n\tconst restoreState = node<StatusValue>([], {\n\t\tinitial: \"pending\",\n\t\tname: \"restoreState\",\n\t\tdescribeKind: \"state\",\n\t});\n\tsubgraph.add(restoreState, { name: \"restoreState\" });\n\n\t// `gateOpen` is the valve control: true only while\n\t// restoreState === \"completed\". Lazy: activates when the first valve\n\t// subscribes.\n\tconst gateOpen = node<boolean>(\n\t\t[restoreState as Node],\n\t\t(data, a, ctx) => {\n\t\t\tconst batch0 = data[0];\n\t\t\tconst v = (batch0 != null && batch0.length > 0 ? batch0.at(-1) : ctx.prevData[0]) as\n\t\t\t\t| StatusValue\n\t\t\t\t| undefined;\n\t\t\ta.emit(v === \"completed\");\n\t\t},\n\t\t{ name: \"gateOpen\", describeKind: \"derived\" },\n\t);\n\tsubgraph.add(gateOpen, { name: \"gateOpen\" });\n\n\t// ── Watched event subscriptions (valve-gated) ────────────────────────\n\t// COMPOSITION-GUIDE §28 cursor pattern + valve(eventNode, gateOpen):\n\t// per watched event type, subscribe to a valve over the cqrs event\n\t// stream. While restoreState !== \"completed\", valve emits RESOLVED so\n\t// no DATA reaches the cursor — events are NOT lost; the cqrs event\n\t// log retains them. When the gate flips open, valve re-emits the\n\t// latest cumulative event array (control-only wave path inside\n\t// `valve`); the cursor processes everything from `lastCount` (still\n\t// 0 at that point) in one shot.\n\tconst watchDisposers: Array<() => void> = [];\n\n\tfor (const eventType of opts.watching) {\n\t\tconst eventNode = cqrsGraph.event(eventType as string);\n\t\tconst gated = valve(eventNode, gateOpen, { name: `gatedEvent:${eventType as string}` });\n\n\t\t// Cursor starts at 0 — pre-restore events are NOT pre-counted because\n\t\t// they may be pre-restart events that the persisted snapshot already\n\t\t// consumed. The restore pipeline's job is to seed instanceStates /\n\t\t// activeInstances; events for instances NOT in activeInstances after\n\t\t// restore drop on the floor (the per-event activeInstances.has guard).\n\t\tlet lastCount = 0;\n\n\t\tconst unsub = gated.subscribe((msgs: Messages) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tconst events = m[1] as readonly CqrsEvent[];\n\t\t\t\tif (events.length <= lastCount) continue;\n\t\t\t\tconst newEvents = events.slice(lastCount);\n\t\t\t\tlastCount = events.length;\n\n\t\t\t\tfor (const ev of newEvents) {\n\t\t\t\t\tconst corrId = ev.correlationId;\n\t\t\t\t\tif (corrId === undefined) continue;\n\t\t\t\t\tif (!activeInstances.has(corrId)) continue;\n\n\t\t\t\t\tconst step = (opts.steps as unknown as Record<string, ProcessStep<TState, EM, string>>)[\n\t\t\t\t\t\teventType as string\n\t\t\t\t\t];\n\t\t\t\t\tif (!step) continue;\n\n\t\t\t\t\tconst state = instanceStates.get(corrId);\n\t\t\t\t\tif (state === undefined) continue;\n\n\t\t\t\t\tdispatchStep(corrId, step, state, ev);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\twatchDisposers.push(unsub);\n\t}\n\n\t// ── Public API ────────────────────────────────────────────────────────\n\n\t// Tier 8 γ-7-A (2026-04-28): `start()` body is mutate-wrapped so the\n\t// synthetic-start-event emit + the running audit record commit in one\n\t// batch frame. If `_appendEvent` throws (e.g. event stream terminated),\n\t// mutate rolls back the in-band batch (audit append discarded, seq\n\t// cursor advance discarded) and re-throws to the caller. Pre-1.0 behavior\n\t// change vs. γ-7-B: the previous form silently swallowed `_appendEvent`\n\t// failures and still appended the running record. Per COMPOSITION-GUIDE\n\t// §35, closure mutations are NOT rolled back — so they are deferred to\n\t// after `_appendEvent` succeeds inside the action body.\n\t//\n\t// B4 (D2 — locked 2026-05-01): `persistState(...)` lives INSIDE the action\n\t// body (after the closure mutations that seed `instanceStates`) so a\n\t// sync-throwing `stateStorage` tier rolls back the in-band batch the same\n\t// way `_appendEvent` failures do — neither the audit log entry nor the\n\t// state snapshot ends up in the \"running\" record store. Per §35 the\n\t// closure mutations stay (instanceStates / activeInstances / startedAt\n\t// are already set), but the audit-log + persisted-snapshot are coherent\n\t// with each other: both absent on throw, both present on success.\n\tconst startInternal = mutate<[string, unknown], void, ProcessInstance<TState>>(\n\t\t(correlationId, initialPayload) => {\n\t\t\t// Synthetic start event first (potentially throws). Closure\n\t\t\t// mutations below only run if this call succeeds — per §35,\n\t\t\t// rollback does not undo them, so they must come after the\n\t\t\t// throwing work.\n\t\t\t(\n\t\t\t\tcqrsGraph as unknown as {\n\t\t\t\t\t_appendEvent(\n\t\t\t\t\t\tname: string,\n\t\t\t\t\t\tpayload: unknown,\n\t\t\t\t\t\textra?: { correlationId?: string; aggregateId?: string },\n\t\t\t\t\t): void;\n\t\t\t\t}\n\t\t\t)._appendEvent(startedEventType, initialPayload ?? null, {\n\t\t\t\tcorrelationId,\n\t\t\t\taggregateId: correlationId,\n\t\t\t});\n\t\t\tstartedAt.set(correlationId, wallClockNs());\n\t\t\tinstanceStates.set(correlationId, opts.initial);\n\t\t\tactiveInstances.add(correlationId);\n\t\t\t// B4: inside the rollback boundary so a sync-throwing tier\n\t\t\t// discards the audit-log append + seq cursor advance.\n\t\t\tpersistStateThrowing(correlationId, \"running\");\n\t\t},\n\t\t{\n\t\t\tframe: \"transactional\",\n\t\t\tlog: instances,\n\t\t\tseq: seqCursor,\n\t\t\tfreeze: true,\n\t\t\t...(opts.handlerVersion !== undefined ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\tonSuccessRecord: ([correlationId], _r, { t_ns, seq }) => ({\n\t\t\t\tcorrelationId,\n\t\t\t\tstate: opts.initial,\n\t\t\t\tstatus: \"running\",\n\t\t\t\tstartedAt: startedAt.get(correlationId) ?? t_ns,\n\t\t\t\tupdatedAt: t_ns,\n\t\t\t\tt_ns,\n\t\t\t\tseq: seq ?? 0,\n\t\t\t}),\n\t\t},\n\t);\n\n\t/**\n\t * Start a new process instance.\n\t *\n\t * Idempotent: if a running instance with the same `correlationId` already\n\t * exists, the call is a no-op. Also a no-op after `dispose()`.\n\t *\n\t * **Throws** if the synthetic `_process_<name>_started` event stream is\n\t * terminated (γ-7-A, 2026-04-28). The audit log is not appended in that\n\t * case — the in-band batch rolls back so the seq cursor and audit log\n\t * stay consistent with the pre-call state.\n\t */\n\tfunction start(correlationId: string, initialPayload?: unknown): void {\n\t\tif (_disposed) return;\n\t\tif (activeInstances.has(correlationId)) return;\n\t\t// B4 (D2): persistState now lives INSIDE `startInternal`'s mutate\n\t\t// action body so sync-throwing tiers roll back the audit-log entry too.\n\t\tstartInternal(correlationId, initialPayload);\n\t}\n\n\t/**\n\t * Cancel a running instance and trigger compensation.\n\t *\n\t * No-op if the instance is not currently running (or after `dispose()`).\n\t */\n\tfunction cancel(correlationId: string, reason?: string): void {\n\t\tif (_disposed) return;\n\t\tif (!activeInstances.has(correlationId)) return;\n\n\t\t// Capture state before the async compensate path.\n\t\tconst state = instanceStates.get(correlationId) ?? opts.initial;\n\t\t// Run compensation asynchronously (fire-and-forget from caller perspective).\n\t\t// C1: runCompensate does the eager activeInstances.delete before any await,\n\t\t// so concurrent calls or in-flight steps that complete concurrently find the\n\t\t// instance already removed and exit early.\n\t\t// M4: pass reason through so it lands on the audit record.\n\t\trunCompensate(\n\t\t\tcorrelationId,\n\t\t\tstate,\n\t\t\tnew Error(`cancelled: ${reason ?? \"no reason given\"}`),\n\t\t\treason,\n\t\t);\n\t}\n\n\t/**\n\t * Read the current in-memory state for a correlationId.\n\t *\n\t * Returns `undefined` if the instance does not exist or has terminated.\n\t */\n\tfunction getState(correlationId: string): TState | undefined {\n\t\treturn instanceStates.get(correlationId);\n\t}\n\n\t/**\n\t * Reactive restore pipeline (B5 — locked 2026-05-01; post-fix using\n\t * fromAny + StatusValue 2026-05-01).\n\t *\n\t * `restoreSubscription` is the single keepalive over the snapshot-load\n\t * effect. Set on first `restore()` call (or on construction when\n\t * `deferRestore !== true`). The effect:\n\t *\n\t * 1. Subscribes to `mergeMap(fromAny(tier.list()), keys =>\n\t * mergeMap(fromIter(keys), key => fromAny(tier.load(key))))` —\n\t * a fully reactive chain whose only async boundaries are the source\n\t * `fromAny` nodes (spec §5.10). `fromAny` accepts sync values,\n\t * Promises, async iterables, and existing Nodes — future-proof\n\t * against tier impls that decide to expose paginated/streaming\n\t * `list()` or batched `load()`.\n\t * 2. On each per-key load DATA, populates `instanceStates` /\n\t * `activeInstances` / `startedAt` for `status === \"running\"` records.\n\t * 3. On `COMPLETE` (all loads finished), flips `restoreState` to\n\t * `\"completed\"` — the watch valve opens, queued cqrs events become\n\t * deliverable, and any `firstWhere(restoreState …)` awaiter resolves.\n\t *\n\t * Idempotent: subsequent calls reuse the same subscription and resolve\n\t * on the same gate flip.\n\t */\n\tlet restoreSubscription: (() => void) | undefined;\n\n\tfunction startRestorePipeline(): void {\n\t\tif (restoreSubscription !== undefined) return;\n\t\tconst tier = stateStorageTiers[0];\n\t\tif (tier == null || tier.list == null || tier.load == null) {\n\t\t\t// No snapshot tier — flip immediately so watches can arm.\n\t\t\t// `restoreState` is a state node so write directly.\n\t\t\tif (!_disposed) restoreState.emit(\"completed\");\n\t\t\trestoreSubscription = () => undefined;\n\t\t\treturn;\n\t\t}\n\t\tconst tierLoad = tier.load.bind(tier);\n\t\tconst tierList = tier.list.bind(tier);\n\n\t\t// Reactive source chain. `tier.list()` and `tier.load(key)` are the\n\t\t// only async boundaries. Bridged via `fromAny`, which (post DS-13.5\n\t\t// follow-up, 2026-05-01) treats sync iterables as single DATA values\n\t\t// by default — `tier.list()`'s `readonly string[]` flows through as\n\t\t// ONE DATA carrying the whole list, not as a per-key stream. Sync\n\t\t// tier returns emit immediately at subscribe time; async tier\n\t\t// returns emit on resolve.\n\t\tconst listSource = fromAny<readonly string[]>(tierList());\n\t\tconst flattened = mergeMap(listSource, (keys: readonly string[]) => {\n\t\t\tif (keys.length === 0) {\n\t\t\t\t// fromIter([]) emits no DATA, only COMPLETE — which\n\t\t\t\t// propagates up through mergeMap so the effect sees its\n\t\t\t\t// own COMPLETE.\n\t\t\t\treturn fromIter<ProcessStateSnapshot<TState> | undefined>([]);\n\t\t\t}\n\t\t\t// Inner: per-key load via fromAny, flattened across keys.\n\t\t\t// Outer fromIter(keys) DOES want per-element emission here —\n\t\t\t// each key triggers a fresh load via mergeMap.\n\t\t\treturn mergeMap(\n\t\t\t\tfromIter(keys),\n\t\t\t\t(key: string) => fromAny(tierLoad(key)) as Node<ProcessStateSnapshot<TState> | undefined>,\n\t\t\t\t// Bound concurrent in-flight loads (D2, 2026-05-01) so a\n\t\t\t\t// large persisted-instance count doesn't exhaust file\n\t\t\t\t// handles / connection pools on the storage backend.\n\t\t\t\t{ concurrent: opts.restoreConcurrency ?? 8 },\n\t\t\t);\n\t\t});\n\n\t\t// Effect node: populate closure state on each load, flip the gate on\n\t\t// COMPLETE. Reactive — no awaits.\n\t\t//\n\t\t// Re-entrancy guard (A3, 2026-05-01): wrap the closure-mutation loop\n\t\t// + the gate flip in a single `batch()`. Without it, the synchronous\n\t\t// `restoreState.emit(\"completed\")` mid-fn-body would cascade through\n\t\t// gateOpen → valves → cqrs cursors → step dispatch BEFORE the\n\t\t// snapshot loop returns — external observers would see a half-\n\t\t// populated `instanceStates` map.\n\t\t//\n\t\t// Mid-iteration dispose hoisting (A4, 2026-05-01): the `_disposed`\n\t\t// check is hoisted to BEFORE the snapshot loop. The previous per-\n\t\t// snapshot check leaked state when `dispose()` fired between\n\t\t// snapshots N and N+1: snapshots 0..N populated `instanceStates`,\n\t\t// then dispose flipped `_disposed`, the terminalDeps branch\n\t\t// short-circuited the gate flip, and the cleanup path tore down the\n\t\t// watch valve — leaving orphan entries that subsequent `start()`\n\t\t// calls would treat as \"already active\" via `activeInstances.has`.\n\t\tconst restoreEffect = node(\n\t\t\t[flattened as Node],\n\t\t\t(data, _a, ctx) => {\n\t\t\t\tif (_disposed) return;\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tconst hasSnapshots = batch0 != null && batch0.length > 0;\n\t\t\t\tconst allDone = ctx.terminalDeps[0] === true;\n\t\t\t\tif (!hasSnapshots && !allDone) return;\n\t\t\t\tbatch(() => {\n\t\t\t\t\tif (hasSnapshots) {\n\t\t\t\t\t\tfor (const snap of batch0 as readonly (ProcessStateSnapshot<TState> | undefined)[]) {\n\t\t\t\t\t\t\tif (snap == null) continue;\n\t\t\t\t\t\t\tif (snap.status !== \"running\") continue;\n\t\t\t\t\t\t\tinstanceStates.set(snap.correlationId, snap.state);\n\t\t\t\t\t\t\tactiveInstances.add(snap.correlationId);\n\t\t\t\t\t\t\tstartedAt.set(snap.correlationId, snap.startedAt);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (allDone) restoreState.emit(\"completed\");\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"restoreEffect\", describeKind: \"effect\" },\n\t\t);\n\t\tsubgraph.add(restoreEffect, { name: \"restoreEffect\" });\n\t\trestoreSubscription = restoreEffect.subscribe(() => undefined);\n\t}\n\n\t/**\n\t * Trigger restoration (idempotent) and return a Promise that resolves\n\t * when `restoreState` transitions to `\"completed\"` OR when {@link dispose}\n\t * tears down the restore node (firstWhere's COMPLETE-rejection is\n\t * swallowed at the API edge so the caller's promise settles cleanly).\n\t */\n\tfunction restore(): Promise<void> {\n\t\tstartRestorePipeline();\n\t\tif (_disposed) return Promise.resolve();\n\t\tif (restoreState.cache === \"completed\") return Promise.resolve();\n\t\t// firstWhere is the canonical reactive→Promise bridge (spec §5.10);\n\t\t// async boundary lives at the public API edge, not in the graph.\n\t\t// .catch distinguishes the COMPLETE-without-match shape (which is\n\t\t// the dispose-tears-down case — swallow + resolve undefined) from\n\t\t// any other rejection (re-throw — caller sees a real failure).\n\t\treturn firstWhere(restoreState, (s) => s === \"completed\")\n\t\t\t.then(() => undefined)\n\t\t\t.catch((err: unknown) => {\n\t\t\t\tif (err instanceof Error && err.message === \"completed without matching value\") {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t});\n\t}\n\n\tfunction dispose(): void {\n\t\tif (_disposed) return;\n\t\t_disposed = true;\n\t\t// Pending `firstWhere(restoreState, ...)` awaiters (i.e. a `restore()`\n\t\t// Promise still waiting on the gate flip) settle via the framework's\n\t\t// DS-13.5.A Q16 auto-precede rule: TEARDOWN delivery on a non-terminal\n\t\t// node automatically prepends [COMPLETE] in `_frameBatch`, so sinks\n\t\t// see [[COMPLETE], [TEARDOWN]] in order. firstWhere rejects on\n\t\t// COMPLETE-without-match; the .catch in `restore()` swallows that\n\t\t// rejection and the public Promise resolves cleanly.\n\t\t// Tear down the restore pipeline keepalive. fromAny.cleanup sets\n\t\t// `settled = true`, so when the underlying tier.list/load promises\n\t\t// finally resolve, the DATA never propagates — the closure mutations\n\t\t// in `restoreEffect` are never invoked (D5 belt + suspenders).\n\t\tif (restoreSubscription) {\n\t\t\ttry {\n\t\t\t\trestoreSubscription();\n\t\t\t} catch {\n\t\t\t\t// non-fatal\n\t\t\t}\n\t\t\trestoreSubscription = undefined;\n\t\t}\n\t\t// Release all watched-event subscriptions (C3 — watchDisposers leak fix).\n\t\tfor (const unsub of watchDisposers) {\n\t\t\ttry {\n\t\t\t\tunsub();\n\t\t\t} catch (_err) {\n\t\t\t\t// non-fatal: best-effort teardown\n\t\t\t}\n\t\t}\n\t\twatchDisposers.length = 0;\n\t\t// EH-16 (Tier 6.5 3.3): unmount the per-instance subgraph so the\n\t\t// audit log + seq cursor nodes are removed from the CQRS graph and\n\t\t// don't leak across repeated create/dispose cycles. `Graph.remove`\n\t\t// fires TEARDOWN through the subtree.\n\t\ttry {\n\t\t\tcqrsGraph.remove(mountName);\n\t\t} catch (_err) {\n\t\t\t// non-fatal: best-effort teardown (e.g. cqrsGraph already destroyed)\n\t\t}\n\t}\n\n\t// Auto-restore on construction unless explicitly deferred (B5).\n\tif (opts.deferRestore !== true) {\n\t\tstartRestorePipeline();\n\t}\n\n\treturn {\n\t\tinstances,\n\t\taudit: instances,\n\t\trestoreState,\n\t\tstart,\n\t\tcancel,\n\t\tgetState,\n\t\trestore,\n\t\tdispose,\n\t};\n}\n","/**\n * MeasurementAdapter implementations (roadmap §7.1 — pluggable backends).\n *\n * All adapters implement {@link MeasurementAdapter} from `reactive-layout.ts`.\n * Sync constructors, sync `measureSegment()` — no async, no polling.\n */\n\nimport { countCells } from \"../../base/render/_ascii-width.js\";\nimport type { MeasurementAdapter } from \"./reactive-layout.js\";\n\n// ---------------------------------------------------------------------------\n// CliMeasureAdapter\n// ---------------------------------------------------------------------------\n\nexport type CliMeasureAdapterOptions = {\n\t/** Pixel width per terminal cell (default: 8). */\n\tcellPx?: number;\n};\n\n/**\n * Monospace terminal measurement adapter.\n *\n * Width = cell count × `cellPx`. CJK / fullwidth characters count as 2 cells.\n * No external dependencies. Works in any JS environment.\n */\nexport class CliMeasureAdapter implements MeasurementAdapter {\n\tprivate readonly cellPx: number;\n\n\tconstructor(opts?: CliMeasureAdapterOptions) {\n\t\tthis.cellPx = opts?.cellPx ?? 8;\n\t}\n\n\tmeasureSegment(text: string, _font: string): { width: number } {\n\t\treturn { width: countCells(text) * this.cellPx };\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// PrecomputedAdapter\n// ---------------------------------------------------------------------------\n\nexport type PrecomputedAdapterOptions = {\n\t/**\n\t * Pre-computed metrics: `{ font: { segment: widthPx } }`.\n\t * Outer key is the CSS font string; inner key is the text segment.\n\t */\n\tmetrics: Record<string, Record<string, number>>;\n\t/**\n\t * Fallback when a segment is not found in the metrics map.\n\t * - `\"per-char\"`: sum individual character widths from the same font map (default)\n\t * - `\"error\"`: throw an error for unknown segments\n\t */\n\tfallback?: \"per-char\" | \"error\";\n};\n\nclass PrecomputedAdapterKeyError extends Error {\n\tname = \"KeyError\";\n}\n\n/**\n * Pre-computed measurement adapter for SSR / snapshot replay.\n *\n * Reads from a static metrics object — zero measurement at runtime.\n * Ideal for server-side rendering or replaying snapshotted layouts.\n */\nexport class PrecomputedAdapter implements MeasurementAdapter {\n\tprivate readonly metrics: Record<string, Record<string, number>>;\n\tprivate readonly fallback: \"per-char\" | \"error\";\n\n\tconstructor(opts: PrecomputedAdapterOptions) {\n\t\tthis.metrics = opts.metrics;\n\t\tconst fb = opts.fallback ?? \"per-char\";\n\t\tif (fb !== \"per-char\" && fb !== \"error\") {\n\t\t\t// Keep parity with Python: validate at runtime.\n\t\t\tthrow new Error(\n\t\t\t\t`fallback must be 'per-char' or 'error', got ${JSON.stringify(opts.fallback)}`,\n\t\t\t);\n\t\t}\n\t\tthis.fallback = fb;\n\t}\n\n\tmeasureSegment(text: string, font: string): { width: number } {\n\t\tconst fontMap = this.metrics[font];\n\t\tif (fontMap) {\n\t\t\tconst w = fontMap[text];\n\t\t\tif (w !== undefined) return { width: w };\n\t\t}\n\n\t\tif (this.fallback === \"error\") {\n\t\t\tthrow new PrecomputedAdapterKeyError(\n\t\t\t\t`PrecomputedAdapter: no metrics for segment ${JSON.stringify(text)} in font ${JSON.stringify(font)}`,\n\t\t\t);\n\t\t}\n\n\t\t// per-char fallback: sum individual character widths\n\t\tlet total = 0;\n\t\tif (fontMap) {\n\t\t\tfor (const ch of text) {\n\t\t\t\tconst cw = fontMap[ch];\n\t\t\t\tif (cw !== undefined) {\n\t\t\t\t\ttotal += cw;\n\t\t\t\t}\n\t\t\t\t// unknown char contributes 0 (best-effort)\n\t\t\t}\n\t\t}\n\t\treturn { width: total };\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// CanvasMeasureAdapter (browser)\n// ---------------------------------------------------------------------------\n\nexport type CanvasMeasureAdapterOptions = {\n\t/** Emoji width correction factor (default: 1, no correction). */\n\temojiCorrection?: number;\n};\n\n/**\n * Browser measurement adapter using `OffscreenCanvas.measureText()`.\n *\n * Lazily creates an OffscreenCanvas and 2D context on first call.\n * Requires a browser environment with OffscreenCanvas support.\n */\nexport class CanvasMeasureAdapter implements MeasurementAdapter {\n\tprivate ctx: OffscreenCanvasRenderingContext2D | null = null;\n\tprivate currentFont = \"\";\n\tprivate readonly emojiCorrection: number;\n\n\tconstructor(opts?: CanvasMeasureAdapterOptions) {\n\t\tthis.emojiCorrection = opts?.emojiCorrection ?? 1;\n\t}\n\n\tprivate getContext(): OffscreenCanvasRenderingContext2D {\n\t\tif (!this.ctx) {\n\t\t\tif (typeof OffscreenCanvas === \"undefined\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"CanvasMeasureAdapter requires a browser environment with OffscreenCanvas support. \" +\n\t\t\t\t\t\t\"Use CliMeasureAdapter or NodeCanvasMeasureAdapter for Node.js.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst canvas = new OffscreenCanvas(0, 0);\n\t\t\tconst ctx = canvas.getContext(\"2d\");\n\t\t\tif (!ctx) throw new Error(\"CanvasMeasureAdapter: failed to get 2d context\");\n\t\t\tthis.ctx = ctx;\n\t\t}\n\t\treturn this.ctx;\n\t}\n\n\tmeasureSegment(text: string, font: string): { width: number } {\n\t\tconst ctx = this.getContext();\n\t\tif (font !== this.currentFont) {\n\t\t\tctx.font = font;\n\t\t\tthis.currentFont = font;\n\t\t}\n\t\tlet width = ctx.measureText(text).width;\n\t\t// Apply emoji correction if configured\n\t\tif (this.emojiCorrection !== 1 && /\\p{Emoji_Presentation}/u.test(text)) {\n\t\t\twidth *= this.emojiCorrection;\n\t\t}\n\t\treturn { width };\n\t}\n\n\tclearCache(): void {\n\t\t// No segment cache; context font is the only state.\n\t\tthis.currentFont = \"\";\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// NodeCanvasMeasureAdapter (Node.js / CLI with canvas package)\n// ---------------------------------------------------------------------------\n\n/**\n * Canvas API subset expected from `@napi-rs/canvas` or `skia-canvas`.\n * Passed via dependency injection — no dynamic import, no polling.\n */\nexport type CanvasModule = {\n\tcreateCanvas(\n\t\twidth: number,\n\t\theight: number,\n\t): {\n\t\tgetContext(type: \"2d\"): {\n\t\t\tfont: string;\n\t\t\tmeasureText(text: string): { width: number };\n\t\t};\n\t};\n};\n\n/**\n * Node.js measurement adapter using an injected canvas module.\n *\n * ```ts\n * import * as canvas from \"@napi-rs/canvas\";\n * const adapter = new NodeCanvasMeasureAdapter(canvas);\n * ```\n *\n * Works with `@napi-rs/canvas`, `skia-canvas`, or any module exposing\n * `createCanvas(w, h).getContext(\"2d\").measureText(text)`.\n */\nexport class NodeCanvasMeasureAdapter implements MeasurementAdapter {\n\tprivate ctx: { font: string; measureText(text: string): { width: number } } | null = null;\n\tprivate currentFont = \"\";\n\tprivate readonly canvasModule: CanvasModule;\n\n\tconstructor(canvasModule: CanvasModule) {\n\t\tthis.canvasModule = canvasModule;\n\t}\n\n\tprivate getContext(): { font: string; measureText(text: string): { width: number } } {\n\t\tif (!this.ctx) {\n\t\t\tconst canvas = this.canvasModule.createCanvas(0, 0);\n\t\t\tconst ctx = canvas.getContext(\"2d\");\n\t\t\tif (!ctx) throw new Error(\"NodeCanvasMeasureAdapter: failed to get 2d context\");\n\t\t\tthis.ctx = ctx;\n\t\t}\n\t\treturn this.ctx;\n\t}\n\n\tmeasureSegment(text: string, font: string): { width: number } {\n\t\tconst ctx = this.getContext();\n\t\tif (font !== this.currentFont) {\n\t\t\tctx.font = font;\n\t\t\tthis.currentFont = font;\n\t\t}\n\t\treturn { width: ctx.measureText(text).width };\n\t}\n\n\tclearCache(): void {\n\t\tthis.currentFont = \"\";\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// SvgBoundsAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * SVG measurement adapter — extracts dimensions from `viewBox` attribute\n * or explicit `width`/`height` attributes in the SVG string.\n *\n * Pure arithmetic: parses the SVG string for dimension attributes.\n * No DOM required. Works in any JS environment.\n *\n * Browser users who need `getBBox()` should pre-measure and pass explicit\n * `viewBox` on the content block instead.\n */\nexport class SvgBoundsAdapter {\n\tmeasureSvg(content: string): { width: number; height: number } {\n\t\t// Try viewBox first: viewBox=\"minX minY width height\"\n\t\tconst viewBoxMatch = content.match(/viewBox\\s*=\\s*[\"']([^\"']+)[\"']/);\n\t\tif (viewBoxMatch) {\n\t\t\tconst parts = viewBoxMatch[1]!.trim().split(/[\\s,]+/);\n\t\t\tif (parts.length >= 4) {\n\t\t\t\tconst w = Number.parseFloat(parts[2]!);\n\t\t\t\tconst h = Number.parseFloat(parts[3]!);\n\t\t\t\tif (Number.isFinite(w) && Number.isFinite(h) && w > 0 && h > 0) {\n\t\t\t\t\treturn { width: w, height: h };\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"SvgBoundsAdapter: viewBox width/height are missing, non-finite, or not positive\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to explicit width/height attributes\n\t\tconst widthMatch = content.match(/<svg[^>]*\\bwidth\\s*=\\s*[\"']?([\\d.]+)/);\n\t\tconst heightMatch = content.match(/<svg[^>]*\\bheight\\s*=\\s*[\"']?([\\d.]+)/);\n\t\tif (widthMatch && heightMatch) {\n\t\t\tconst w = Number.parseFloat(widthMatch[1]!);\n\t\t\tconst h = Number.parseFloat(heightMatch[1]!);\n\t\t\tif (Number.isFinite(w) && Number.isFinite(h) && w > 0 && h > 0) {\n\t\t\t\treturn { width: w, height: h };\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t\"SvgBoundsAdapter: svg width/height attributes are non-finite or not positive\",\n\t\t\t);\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t\"SvgBoundsAdapter: cannot determine dimensions — SVG has no viewBox or width/height attributes\",\n\t\t);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// ImageSizeAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * Image measurement adapter — returns pre-registered dimensions by src key.\n *\n * Sync-only: dimensions must be provided upfront via the `sizes` map.\n * No I/O, no polling, no async. For browser use, pre-measure via\n * `Image.onload` and pass natural dimensions on the content block directly,\n * or register them here.\n *\n * ```ts\n * const adapter = new ImageSizeAdapter({\n * \"hero.png\": { width: 1200, height: 630 },\n * \"logo.svg\": { width: 120, height: 40 },\n * });\n * ```\n */\nexport class ImageSizeAdapter {\n\tprivate readonly sizes: Map<string, { width: number; height: number }>;\n\n\tconstructor(sizes: Record<string, { width: number; height: number }>) {\n\t\tthis.sizes = new Map(Object.entries(sizes));\n\t}\n\n\tmeasureImage(src: string): { width: number; height: number } {\n\t\tconst dims = this.sizes.get(src);\n\t\tif (!dims) {\n\t\t\tthrow new Error(`ImageSizeAdapter: no dimensions registered for ${JSON.stringify(src)}`);\n\t\t}\n\t\treturn { width: dims.width, height: dims.height };\n\t}\n}\n","/**\n * Reactive multi-content block layout engine (roadmap §7.1 — mixed content).\n *\n * Extends the text-only `reactiveLayout` with support for image and SVG blocks.\n * Pure-arithmetic layout over measured child sizes — no DOM, no async.\n *\n * Graph shape:\n * ```\n * Graph(\"reactive-block-layout\")\n * ├── node([], { initial: \"blocks\" }) — ContentBlock[] input\n * ├── node([], { initial: \"max-width\" }) — container constraint\n * ├── node([], { initial: \"gap\" }) — vertical gap between blocks (px)\n * ├── derived(\"measured-blocks\") — blocks → MeasuredBlock[] (per-type measurement)\n * ├── derived(\"block-flow\") — measured-blocks + max-width + gap → PositionedBlock[]\n * ├── derived(\"total-height\") — block-flow → total height\n * └── meta: { block-count, layout-time-ns }\n * ```\n */\nimport { monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\n\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { emitToMeta } from \"../../base/meta/emit-to-meta.js\";\nimport {\n\tanalyzeAndMeasure,\n\ttype CharPosition,\n\tcomputeCharPositions,\n\tcomputeLineBreaks,\n\ttype LineBreaksResult,\n\ttype MeasurementAdapter,\n\ttype PreparedSegment,\n} from \"./reactive-layout.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Pluggable measurement backend for SVG content. */\nexport interface SvgMeasurer {\n\tmeasureSvg(content: string): { width: number; height: number };\n}\n\n/** Pluggable measurement backend for image content. */\nexport interface ImageMeasurer {\n\tmeasureImage(src: string): { width: number; height: number };\n}\n\n/** Adapters map for `reactiveBlockLayout`. */\nexport type BlockAdapters = {\n\t/** Text measurement adapter (required — delegates to `reactiveLayout` internals). */\n\ttext: MeasurementAdapter;\n\t/** SVG measurement (optional — required only if SVG blocks are present). */\n\tsvg?: SvgMeasurer;\n\t/** Image measurement (optional — required only if image blocks without explicit dimensions are present). */\n\timage?: ImageMeasurer;\n};\n\n/** A content block — text, image, or SVG. */\nexport type ContentBlock =\n\t| {\n\t\t\ttype: \"text\";\n\t\t\ttext: string;\n\t\t\tfont?: string;\n\t\t\tlineHeight?: number;\n\t }\n\t| {\n\t\t\ttype: \"image\";\n\t\t\tsrc: string;\n\t\t\t/** Natural width in px. Required if no ImageMeasurer adapter is provided. */\n\t\t\tnaturalWidth?: number;\n\t\t\t/** Natural height in px. Required if no ImageMeasurer adapter is provided. */\n\t\t\tnaturalHeight?: number;\n\t }\n\t| {\n\t\t\ttype: \"svg\";\n\t\t\tcontent: string;\n\t\t\t/** Explicit viewBox dimensions. Required if no SvgMeasurer adapter is provided. */\n\t\t\tviewBox?: { width: number; height: number };\n\t };\n\n/**\n * A block after measurement — knows its natural dimensions.\n *\n * **Equality note:** The reactive `measured-blocks` node uses dimension-only equality\n * (`type`, `width`, `height`, `index`). Inner text layout data (`textSegments`,\n * `textLineBreaks`, `textCharPositions`) is NOT compared for change detection.\n * If you need text-level reactivity, use `reactiveLayout()` directly per text block.\n */\nexport type MeasuredBlock = {\n\tindex: number;\n\ttype: \"text\" | \"image\" | \"svg\";\n\twidth: number;\n\theight: number;\n\t/** For text blocks: the inner layout results. */\n\ttextSegments?: PreparedSegment[];\n\ttextLineBreaks?: LineBreaksResult;\n\ttextCharPositions?: CharPosition[];\n};\n\n/** A block after flow — positioned in the container. */\nexport type PositionedBlock = MeasuredBlock & {\n\tx: number;\n\ty: number;\n};\n\n/** Options for `reactiveBlockLayout`. */\nexport type ReactiveBlockLayoutOptions = {\n\tadapters: BlockAdapters;\n\tname?: string;\n\tblocks?: ContentBlock[];\n\t/** Container max width in px (clamped to ≥ 0 on init and `setMaxWidth`). */\n\tmaxWidth?: number;\n\t/** Vertical gap between blocks in px (default 0). */\n\tgap?: number;\n\t/** Default font for text blocks that don't specify one. */\n\tdefaultFont?: string;\n\t/** Default line height for text blocks that don't specify one. */\n\tdefaultLineHeight?: number;\n};\n\n/** Result bundle from `reactiveBlockLayout`. */\nexport type ReactiveBlockLayoutBundle = {\n\tgraph: Graph;\n\tsetBlocks: (blocks: ContentBlock[]) => void;\n\tsetMaxWidth: (maxWidth: number) => void;\n\tsetGap: (gap: number) => void;\n\tmeasuredBlocks: Node<MeasuredBlock[]>;\n\tblockFlow: Node<PositionedBlock[]>;\n\ttotalHeight: Node<number>;\n};\n\n// ---------------------------------------------------------------------------\n// Block measurement (pure functions)\n// ---------------------------------------------------------------------------\n\n/**\n * Measure a single content block, returning natural (unconstrained) dimensions.\n * Text blocks use the text layout pipeline; image/SVG use adapters or explicit dims.\n */\nexport function measureBlock(\n\tblock: ContentBlock,\n\tmaxWidth: number,\n\tadapters: BlockAdapters,\n\tmeasureCache: Map<string, Map<string, number>>,\n\tdefaultFont: string,\n\tdefaultLineHeight: number,\n\tindex: number,\n): MeasuredBlock {\n\tswitch (block.type) {\n\t\tcase \"text\": {\n\t\t\tconst font = block.font ?? defaultFont;\n\t\t\tconst lineHeight = block.lineHeight ?? defaultLineHeight;\n\t\t\tconst segments = analyzeAndMeasure(block.text, font, adapters.text, measureCache);\n\t\t\tconst lineBreaks = computeLineBreaks(segments, maxWidth, adapters.text, font, measureCache);\n\t\t\tconst charPositions = computeCharPositions(lineBreaks, segments, lineHeight);\n\t\t\tconst height = lineBreaks.lineCount * lineHeight;\n\t\t\t// Width is the max line width (clamped to maxWidth)\n\t\t\tlet width = 0;\n\t\t\tfor (const line of lineBreaks.lines) {\n\t\t\t\tif (line.width > width) width = line.width;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tindex,\n\t\t\t\ttype: \"text\",\n\t\t\t\twidth: Math.min(width, maxWidth),\n\t\t\t\theight,\n\t\t\t\ttextSegments: segments,\n\t\t\t\ttextLineBreaks: lineBreaks,\n\t\t\t\ttextCharPositions: charPositions,\n\t\t\t};\n\t\t}\n\t\tcase \"image\": {\n\t\t\tlet w: number;\n\t\t\tlet h: number;\n\t\t\tif (block.naturalWidth != null && block.naturalHeight != null) {\n\t\t\t\tw = block.naturalWidth;\n\t\t\t\th = block.naturalHeight;\n\t\t\t} else if (adapters.image) {\n\t\t\t\tconst dims = adapters.image.measureImage(block.src);\n\t\t\t\tw = dims.width;\n\t\t\t\th = dims.height;\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Image block at index ${index} has no naturalWidth/naturalHeight and no ImageMeasurer adapter`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Scale proportionally to fit maxWidth\n\t\t\tif (w > maxWidth) {\n\t\t\t\th = (h * maxWidth) / w;\n\t\t\t\tw = maxWidth;\n\t\t\t}\n\t\t\treturn { index, type: \"image\", width: w, height: h };\n\t\t}\n\t\tcase \"svg\": {\n\t\t\tlet w: number;\n\t\t\tlet h: number;\n\t\t\tif (block.viewBox) {\n\t\t\t\tw = block.viewBox.width;\n\t\t\t\th = block.viewBox.height;\n\t\t\t} else if (adapters.svg) {\n\t\t\t\tconst dims = adapters.svg.measureSvg(block.content);\n\t\t\t\tw = dims.width;\n\t\t\t\th = dims.height;\n\t\t\t} else {\n\t\t\t\tthrow new Error(`SVG block at index ${index} has no viewBox and no SvgMeasurer adapter`);\n\t\t\t}\n\t\t\t// Scale proportionally to fit maxWidth\n\t\t\tif (w > maxWidth) {\n\t\t\t\th = (h * maxWidth) / w;\n\t\t\t\tw = maxWidth;\n\t\t\t}\n\t\t\treturn { index, type: \"svg\", width: w, height: h };\n\t\t}\n\t}\n}\n\n/**\n * Measure all blocks in a content array.\n */\nexport function measureBlocks(\n\tblocks: ContentBlock[],\n\tmaxWidth: number,\n\tadapters: BlockAdapters,\n\tmeasureCache: Map<string, Map<string, number>>,\n\tdefaultFont: string,\n\tdefaultLineHeight: number,\n): MeasuredBlock[] {\n\treturn blocks.map((block, i) =>\n\t\tmeasureBlock(block, maxWidth, adapters, measureCache, defaultFont, defaultLineHeight, i),\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Block flow (pure function)\n// ---------------------------------------------------------------------------\n\n/**\n * Vertical stacking flow: blocks are placed top-to-bottom, left-aligned,\n * separated by `gap` pixels. Pure arithmetic over measured sizes.\n */\nexport function computeBlockFlow(measured: MeasuredBlock[], gap: number): PositionedBlock[] {\n\tconst result: PositionedBlock[] = [];\n\tlet y = 0;\n\tfor (let i = 0; i < measured.length; i++) {\n\t\tconst m = measured[i]!;\n\t\tresult.push({ ...m, x: 0, y });\n\t\ty += m.height + (i < measured.length - 1 ? gap : 0);\n\t}\n\treturn result;\n}\n\n/**\n * Compute total height from positioned blocks.\n */\nexport function computeTotalHeight(flow: PositionedBlock[]): number {\n\tif (flow.length === 0) return 0;\n\tconst last = flow[flow.length - 1]!;\n\treturn last.y + last.height;\n}\n\n// ---------------------------------------------------------------------------\n// Reactive graph factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive block layout graph for mixed content (text + image + SVG).\n *\n * ```\n * Graph(\"reactive-block-layout\")\n * ├── node([], { initial: \"blocks\" }) — ContentBlock[] input\n * ├── node([], { initial: \"max-width\" }) — container constraint\n * ├── node([], { initial: \"gap\" }) — vertical gap (px)\n * ├── derived(\"measured-blocks\") — blocks + max-width → MeasuredBlock[]\n * ├── derived(\"block-flow\") — measured-blocks + gap → PositionedBlock[]\n * ├── derived(\"total-height\") — block-flow → number\n * └── meta: { block-count, layout-time-ns }\n * ```\n */\nexport function reactiveBlockLayout(opts: ReactiveBlockLayoutOptions): ReactiveBlockLayoutBundle {\n\tconst {\n\t\tadapters,\n\t\tname = \"reactive-block-layout\",\n\t\tdefaultFont = \"16px sans-serif\",\n\t\tdefaultLineHeight = 20,\n\t} = opts;\n\tconst g = new Graph(name);\n\n\t// Shared text measurement cache (same structure as reactiveLayout)\n\tconst measureCache = new Map<string, Map<string, number>>();\n\n\t// --- State nodes ---\n\tconst blocksNode = node<ContentBlock[]>([], { name: \"blocks\", initial: opts.blocks ?? [] });\n\tconst maxWidthNode = node<number>([], {\n\t\tname: \"max-width\",\n\t\tinitial: Math.max(0, opts.maxWidth ?? 800),\n\t});\n\tconst gapNode = node<number>([], { name: \"gap\", initial: opts.gap ?? 0 });\n\n\t// --- Derived: measured-blocks ---\n\t// Raw `node(...)` instead of `derived(...)` so the fn can return a\n\t// cleanup function. Core fires function-form cleanup on INVALIDATE (see\n\t// `node.ts:_updateState` INVALIDATE branch), which lets us flush the\n\t// measure cache and the downstream adapter cache reactively — replaces\n\t// the old v4 per-node `onMessage` hook that watched for INVALIDATE.\n\tconst measuredBlocksNode: Node<MeasuredBlock[]> = node<MeasuredBlock[]>(\n\t\t[blocksNode, maxWidthNode],\n\t\t(data, actions, ctx) => {\n\t\t\tconst blocksVal = data[0] != null && data[0].length > 0 ? data[0].at(-1) : ctx.prevData[0];\n\t\t\tconst mwVal = data[1] != null && data[1].length > 0 ? data[1].at(-1) : ctx.prevData[1];\n\t\t\tconst t0 = monotonicNs();\n\t\t\tconst result = measureBlocks(\n\t\t\t\tblocksVal as ContentBlock[],\n\t\t\t\tmwVal as number,\n\t\t\t\tadapters,\n\t\t\t\tmeasureCache,\n\t\t\t\tdefaultFont,\n\t\t\t\tdefaultLineHeight,\n\t\t\t);\n\t\t\tconst elapsed = monotonicNs() - t0;\n\n\t\t\t// Phase-3 meta deferral (parity with reactiveLayout)\n\t\t\tconst meta = measuredBlocksNode.meta;\n\t\t\tif (meta) {\n\t\t\t\temitToMeta(meta[\"block-count\"], result.length);\n\t\t\t\temitToMeta(meta[\"layout-time-ns\"], elapsed);\n\t\t\t}\n\n\t\t\tactions.emit(result);\n\n\t\t\t// Object-form cleanup: flush on deactivation + INVALIDATE only,\n\t\t\t// NOT before fn re-runs. Preserves cached measurements across\n\t\t\t// block edits so a single-block change doesn't wipe entries from\n\t\t\t// the other blocks. Image/SVG measurers don't expose a cache hook.\n\t\t\tconst flush = (): void => {\n\t\t\t\tmeasureCache.clear();\n\t\t\t\tadapters.text.clearCache?.();\n\t\t\t};\n\t\t\treturn { onDeactivation: flush, onInvalidate: flush };\n\t\t},\n\t\t{\n\t\t\tname: \"measured-blocks\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: { \"block-count\": 0, \"layout-time-ns\": 0 },\n\t\t\tequals: (a, b) => {\n\t\t\t\tconst ma = a as MeasuredBlock[] | null;\n\t\t\t\tconst mb = b as MeasuredBlock[] | null;\n\t\t\t\tif (ma == null || mb == null) return ma === mb;\n\t\t\t\tif (ma.length !== mb.length) return false;\n\t\t\t\tfor (let i = 0; i < ma.length; i++) {\n\t\t\t\t\tconst ba = ma[i]!;\n\t\t\t\t\tconst bb = mb[i]!;\n\t\t\t\t\tif (\n\t\t\t\t\t\tba.type !== bb.type ||\n\t\t\t\t\t\tba.width !== bb.width ||\n\t\t\t\t\t\tba.height !== bb.height ||\n\t\t\t\t\t\tba.index !== bb.index\n\t\t\t\t\t)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n\n\t// --- Derived: block-flow ---\n\tconst blockFlowNode = node<PositionedBlock[]>(\n\t\t[measuredBlocksNode, gapNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(computeBlockFlow(data[0] as MeasuredBlock[], data[1] as number));\n\t\t},\n\t\t{\n\t\t\tname: \"block-flow\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tequals: (a, b) => {\n\t\t\t\tconst fa = a as PositionedBlock[] | null;\n\t\t\t\tconst fb = b as PositionedBlock[] | null;\n\t\t\t\tif (fa == null || fb == null) return fa === fb;\n\t\t\t\tif (fa.length !== fb.length) return false;\n\t\t\t\tfor (let i = 0; i < fa.length; i++) {\n\t\t\t\t\tconst pa = fa[i]!;\n\t\t\t\t\tconst pb = fb[i]!;\n\t\t\t\t\tif (pa.x !== pb.x || pa.y !== pb.y || pa.width !== pb.width || pa.height !== pb.height)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n\n\t// --- Derived: total-height ---\n\tconst totalHeightNode = node<number>(\n\t\t[blockFlowNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tactions.emit(computeTotalHeight(data[0] as PositionedBlock[]));\n\t\t},\n\t\t{ describeKind: \"derived\", name: \"total-height\" },\n\t);\n\n\t// --- Register in graph ---\n\tg.add(blocksNode, { name: \"blocks\" });\n\tg.add(maxWidthNode, { name: \"max-width\" });\n\tg.add(gapNode, { name: \"gap\" });\n\tg.add(measuredBlocksNode, { name: \"measured-blocks\" });\n\tg.add(blockFlowNode, { name: \"block-flow\" });\n\tg.add(totalHeightNode, { name: \"total-height\" });\n\n\t// --- Edges (for describe() visibility) ---\n\n\treturn {\n\t\tgraph: g,\n\t\tsetBlocks: (blocks: ContentBlock[]) => g.set(\"blocks\", blocks),\n\t\tsetMaxWidth: (mw: number) => g.set(\"max-width\", Math.max(0, mw)),\n\t\tsetGap: (gap: number) => g.set(\"gap\", gap),\n\t\tmeasuredBlocks: measuredBlocksNode,\n\t\tblockFlow: blockFlowNode,\n\t\ttotalHeight: totalHeightNode,\n\t};\n}\n","/**\n * Reactive flow layout — multi-column text flowing around shape obstacles\n * (roadmap §7.1, extends `reactiveLayout`).\n *\n * Unlike `reactiveLayout` (single-column, one `maxWidth`) and\n * `reactiveBlockLayout` (vertical stack of heterogeneous blocks), this engine\n * lays out a single stream of text across **N columns** while wrapping around\n * arbitrary **shape obstacles** (circles, rectangles). Each line's available\n * width can differ from every other line's, enabling magazine-style editorial\n * layouts — and the cursor carries seamlessly from column to column so text\n * never duplicates or gaps at boundaries.\n *\n * ```\n * Graph(\"reactive-flow-layout\")\n * ├── node([], { initial: \"text\" })\n * ├── node([], { initial: \"font\" })\n * ├── node([], { initial: \"line-height\" })\n * ├── node([], { initial: \"container\" }) — { width, height, paddingX, paddingY }\n * ├── node([], { initial: \"columns\" }) — { count, gap }\n * ├── node([], { initial: \"obstacles\" }) — Obstacle[] (moves reactively — rAF-friendly)\n * ├── derived(\"segments\") — text + font → PreparedSegment[] (from reactiveLayout)\n * ├── derived(\"flow-lines\") — segments + container + columns + obstacles + line-height\n * │ → PositionedLine[]\n * └── meta: { line-count, layout-time-ns, overflow-segments }\n * ```\n *\n * Obstacle positions change every frame; `flow-lines` re-runs per change, but\n * `segments` stays cached (text hasn't changed). Callers drive obstacles via a\n * reactive source like `fromRaf()` piped into a state node.\n */\nimport { monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\n\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { emitToMeta } from \"../../base/meta/emit-to-meta.js\";\nimport {\n\tanalyzeAndMeasure,\n\tcarveTextLineSlots,\n\ttype Interval,\n\ttype LayoutCursor,\n\tlayoutNextLine,\n\ttype MeasurementAdapter,\n\ttype PreparedSegment,\n} from \"./reactive-layout.js\";\n\n// ---------------------------------------------------------------------------\n// Obstacle types\n// ---------------------------------------------------------------------------\n\n/** A circle obstacle. Center `(cx, cy)`, radius `r`; text keeps `padding` distance. */\nexport type CircleObstacle = {\n\tkind: \"circle\";\n\tcx: number;\n\tcy: number;\n\tr: number;\n\t/** Horizontal padding between obstacle and wrapped text (default 0). */\n\thPad?: number;\n\t/** Vertical padding — band overlap tolerance (default 0). */\n\tvPad?: number;\n};\n\n/** A rectangle obstacle. Top-left `(x, y)`, size `(w, h)`. */\nexport type RectObstacle = {\n\tkind: \"rect\";\n\tx: number;\n\ty: number;\n\tw: number;\n\th: number;\n\thPad?: number;\n\tvPad?: number;\n};\n\n/** Union of built-in obstacle shapes. */\nexport type Obstacle = CircleObstacle | RectObstacle;\n\n/**\n * Compute the horizontal interval occluded by a circle at vertical band\n * `[bandTop, bandBottom]`, or `null` if no occlusion.\n *\n * Exported so consumers that render obstacle outlines in sync with the flow\n * can reuse the same geometry the flow engine uses — no divergence.\n */\nexport function circleIntervalForBand(\n\to: CircleObstacle,\n\tbandTop: number,\n\tbandBottom: number,\n): Interval | null {\n\tconst hPad = o.hPad ?? 0;\n\tconst vPad = o.vPad ?? 0;\n\tconst top = bandTop - vPad;\n\tconst bottom = bandBottom + vPad;\n\tif (top >= o.cy + o.r || bottom <= o.cy - o.r) return null;\n\tconst minDy = o.cy >= top && o.cy <= bottom ? 0 : o.cy < top ? top - o.cy : o.cy - bottom;\n\tif (minDy >= o.r) return null;\n\tconst maxDx = Math.sqrt(o.r * o.r - minDy * minDy);\n\treturn { left: o.cx - maxDx - hPad, right: o.cx + maxDx + hPad };\n}\n\n/** Same as `circleIntervalForBand` for rectangles. */\nexport function rectIntervalForBand(\n\to: RectObstacle,\n\tbandTop: number,\n\tbandBottom: number,\n): Interval | null {\n\tconst hPad = o.hPad ?? 0;\n\tconst vPad = o.vPad ?? 0;\n\tif (bandBottom <= o.y - vPad) return null;\n\tif (bandTop >= o.y + o.h + vPad) return null;\n\treturn { left: o.x - hPad, right: o.x + o.w + hPad };\n}\n\nfunction obstacleIntervalForBand(\n\to: Obstacle,\n\tbandTop: number,\n\tbandBottom: number,\n): Interval | null {\n\treturn o.kind === \"circle\"\n\t\t? circleIntervalForBand(o, bandTop, bandBottom)\n\t\t: rectIntervalForBand(o, bandTop, bandBottom);\n}\n\n// ---------------------------------------------------------------------------\n// Flow layout types\n// ---------------------------------------------------------------------------\n\nexport type FlowContainer = {\n\twidth: number;\n\theight: number;\n\tpaddingX?: number;\n\tpaddingY?: number;\n};\n\nexport type FlowColumns = {\n\tcount: number;\n\tgap: number;\n};\n\n/** A single positioned line after flow layout. */\nexport type PositionedLine = {\n\tx: number;\n\ty: number;\n\t/** Natural measured width of the text content. */\n\twidth: number;\n\t/** Width of the slot this line was placed in — use this as the DOM element's\n\t * `width` when applying `text-align: justify` so the line stretches to the\n\t * obstacle edge on both sides. */\n\tslotWidth: number;\n\ttext: string;\n\t/** Which column index this line belongs to (0-based). */\n\tcolumnIndex: number;\n\t/** `true` iff the slot's right edge was carved short by an obstacle (the\n\t * slot sits to the LEFT of an obstacle). Renderers can right-align text\n\t * in these slots so single-word lines still hug the obstacle — CSS\n\t * `text-align: justify` can't stretch single-word lines, which otherwise\n\t * produces a visible asymmetry vs. the slot on the other side of the\n\t * obstacle (which is flush by default). */\n\tflushToRight: boolean;\n};\n\n/** Options for `reactiveFlowLayout`. */\nexport type ReactiveFlowLayoutOptions = {\n\tadapter: MeasurementAdapter;\n\tname?: string;\n\ttext?: string;\n\tfont?: string;\n\tlineHeight?: number;\n\tcontainer?: FlowContainer;\n\tcolumns?: FlowColumns;\n\tobstacles?: Obstacle[];\n\t/** Minimum slot width (px) below which a slot is discarded rather than squeezed. Default `20`. */\n\tminSlotWidth?: number;\n\t/**\n\t * Vertical gap (px) inserted after a hard-break segment (the spacing\n\t * between paragraphs). When unset (or explicitly set to `null`), tracks\n\t * the current `lineHeight` reactively — one line-height of visible\n\t * paragraph gap, matching dense editorial layouts. Set to `0` for\n\t * paragraph-preserving layout that reclaims the break line; set larger\n\t * (e.g. `2 * lineHeight`) for looser manuscript settings. Reactive —\n\t * update via `setParagraphSpacing(n)` or restore to track-lineHeight\n\t * mode via `setParagraphSpacing(null)`.\n\t */\n\tparagraphSpacing?: number | null;\n};\n\n/** Result bundle from `reactiveFlowLayout`. */\nexport type ReactiveFlowLayoutBundle = {\n\tgraph: Graph;\n\tsetText: (text: string) => void;\n\tsetFont: (font: string) => void;\n\tsetLineHeight: (lh: number) => void;\n\tsetContainer: (c: FlowContainer) => void;\n\tsetColumns: (c: FlowColumns) => void;\n\tsetObstacles: (o: Obstacle[]) => void;\n\tsetParagraphSpacing: (ps: number | null) => void;\n\tsegments: Node<PreparedSegment[]>;\n\tflowLines: Node<PositionedLine[]>;\n};\n\n// ---------------------------------------------------------------------------\n// Pure flow-layout compute\n// ---------------------------------------------------------------------------\n\n/** Result of `computeFlowLines`. */\nexport type FlowLinesResult = {\n\t/** Positioned lines in render order (columns inner-ordered top-to-bottom). */\n\tlines: PositionedLine[];\n\t/** Cursor position after the last line was placed. If\n\t * `cursor.segmentIndex < segments.length`, the layout **truncated** — the\n\t * container couldn't fit all text. */\n\tcursor: LayoutCursor;\n};\n\n/** Optional tuning knobs for {@link computeFlowLines}. */\nexport type ComputeFlowLinesOptions = {\n\t/**\n\t * Vertical gap (px) inserted after a hard-break segment (the spacing\n\t * between paragraphs). Defaults to `lineHeight` — one line-height of\n\t * visible paragraph gap, which matches dense editorial layouts. Set to\n\t * `0` for paragraph-preserving layout that reclaims the break line;\n\t * set larger (e.g. `2 * lineHeight`) for looser manuscript settings.\n\t */\n\tparagraphSpacing?: number;\n};\n\n/**\n * Lay out `segments` across N columns, wrapping each line around `obstacles`.\n * Pure function — no reactive wiring. Exported for testing and for consumers\n * who want to run flow layout outside a Graph.\n *\n * `carveTextLineSlots` guarantees left-to-right-ordered, non-overlapping slots,\n * so this function does not sort them.\n */\nexport function computeFlowLines(\n\tsegments: PreparedSegment[],\n\tcontainer: FlowContainer,\n\tcolumns: FlowColumns,\n\tobstacles: Obstacle[],\n\tlineHeight: number,\n\tminSlotWidth: number,\n\topts?: ComputeFlowLinesOptions,\n): FlowLinesResult {\n\tconst paragraphSpacing = opts?.paragraphSpacing ?? lineHeight;\n\tconst lines: PositionedLine[] = [];\n\tlet cursor: LayoutCursor = { segmentIndex: 0, graphemeIndex: 0 };\n\tif (segments.length === 0 || columns.count <= 0 || lineHeight <= 0) {\n\t\treturn { lines, cursor };\n\t}\n\n\tconst padX = container.paddingX ?? 0;\n\tconst padY = container.paddingY ?? 0;\n\tconst availWidth = Math.max(0, container.width - padX * 2);\n\tconst availHeight = Math.max(0, container.height - padY * 2);\n\tconst gapTotal = columns.gap * Math.max(0, columns.count - 1);\n\tconst colWidth = Math.max(0, (availWidth - gapTotal) / columns.count);\n\tif (colWidth <= 0) return { lines, cursor };\n\n\touterCol: for (let col = 0; col < columns.count; col++) {\n\t\tconst colLeft = padX + col * (colWidth + columns.gap);\n\t\tconst colRight = colLeft + colWidth;\n\t\tlet bandTop = padY;\n\n\t\twhile (bandTop + lineHeight <= padY + availHeight) {\n\t\t\tconst bandBottom = bandTop + lineHeight;\n\t\t\tconst blocked: Interval[] = [];\n\t\t\tfor (let oi = 0; oi < obstacles.length; oi++) {\n\t\t\t\tconst iv = obstacleIntervalForBand(obstacles[oi]!, bandTop, bandBottom);\n\t\t\t\tif (iv !== null) blocked.push(iv);\n\t\t\t}\n\t\t\tconst slots = carveTextLineSlots({ left: colLeft, right: colRight }, blocked, minSlotWidth);\n\n\t\t\tif (slots.length === 0) {\n\t\t\t\tbandTop += lineHeight;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet hardBreakThisBand = false;\n\t\t\tfor (let si = 0; si < slots.length; si++) {\n\t\t\t\tconst slot = slots[si]!;\n\t\t\t\tconst slotW = slot.right - slot.left;\n\t\t\t\tconst line = layoutNextLine(segments, cursor, slotW);\n\t\t\t\tif (line === null) {\n\t\t\t\t\treturn { lines, cursor };\n\t\t\t\t}\n\t\t\t\tif (line.text.length === 0 && line.width === 0) {\n\t\t\t\t\t// Hard-break — advance cursor past the break segment and end\n\t\t\t\t\t// THIS band so the break produces a visible paragraph gap\n\t\t\t\t\t// rather than being silently absorbed across remaining slots.\n\t\t\t\t\tcursor = line.end;\n\t\t\t\t\thardBreakThisBand = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlines.push({\n\t\t\t\t\tx: slot.left,\n\t\t\t\t\ty: bandTop,\n\t\t\t\t\twidth: line.width,\n\t\t\t\t\tslotWidth: slotW,\n\t\t\t\t\ttext: line.text,\n\t\t\t\t\tcolumnIndex: col,\n\t\t\t\t\tflushToRight: slot.right < colRight - 0.5,\n\t\t\t\t});\n\t\t\t\tcursor = line.end;\n\t\t\t}\n\n\t\t\tif (hardBreakThisBand) {\n\t\t\t\t// Paragraph gap: `paragraphSpacing` (default lineHeight) of\n\t\t\t\t// vertical space after the break. `0` reclaims the break line;\n\t\t\t\t// larger values space paragraphs further apart.\n\t\t\t\tbandTop += paragraphSpacing;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbandTop += lineHeight;\n\t\t\tif (cursor.segmentIndex >= segments.length) break outerCol;\n\t\t}\n\n\t\tif (cursor.segmentIndex >= segments.length) break;\n\t}\n\n\treturn { lines, cursor };\n}\n\n// ---------------------------------------------------------------------------\n// Reactive graph factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive flow-layout graph: N columns of text wrapping around\n * shape obstacles. Re-runs only the dependent derived nodes on any input\n * change. Obstacle movement (e.g. rAF-driven) invalidates `flow-lines` only;\n * `segments` stays cached as long as `text`/`font` don't change.\n *\n * @example\n * ```ts\n * import { fromRaf, reactiveFlowLayout } from \"@graphrefly/graphrefly-ts\";\n *\n * const flow = reactiveFlowLayout({\n * adapter: new CanvasMeasureAdapter(),\n * text: longEssay,\n * font: \"18px serif\",\n * lineHeight: 26,\n * container: { width: 900, height: 600, paddingX: 40, paddingY: 40 },\n * columns: { count: 2, gap: 32 },\n * obstacles: [{ kind: \"circle\", cx: 450, cy: 300, r: 80 }],\n * });\n *\n * // Animate the obstacle via rAF:\n * fromRaf().subscribe(([[, t]]) => {\n * const x = 450 + 120 * Math.sin((t as number) * 0.001);\n * flow.setObstacles([{ kind: \"circle\", cx: x, cy: 300, r: 80 }]);\n * });\n * ```\n */\nexport function reactiveFlowLayout(opts: ReactiveFlowLayoutOptions): ReactiveFlowLayoutBundle {\n\tconst { adapter, name = \"reactive-flow-layout\", minSlotWidth = 20 } = opts;\n\tconst g = new Graph(name);\n\n\tconst measureCache = new Map<string, Map<string, number>>();\n\n\tconst textNode = node<string>([], { name: \"text\", initial: opts.text ?? \"\" });\n\tconst fontNode = node<string>([], { name: \"font\", initial: opts.font ?? \"16px sans-serif\" });\n\tconst lineHeightNode = node<number>([], { name: \"line-height\", initial: opts.lineHeight ?? 20 });\n\tconst containerNode = node<FlowContainer>([], {\n\t\tname: \"container\",\n\t\tinitial: opts.container ?? { width: 800, height: 600, paddingX: 0, paddingY: 0 },\n\t});\n\tconst columnsNode = node<FlowColumns>([], {\n\t\tname: \"columns\",\n\t\tinitial: opts.columns ?? { count: 1, gap: 0 },\n\t});\n\tconst obstaclesNode = node<Obstacle[]>([], { name: \"obstacles\", initial: opts.obstacles ?? [] });\n\t// `paragraphSpacing` is reactive with a \"track lineHeight\" default. The\n\t// state node holds `number | null` — when `null`, `flow-lines` substitutes\n\t// the CURRENT `lineHeight` value, so the default stays truly reactive\n\t// as lineHeight updates. A caller who wants a fixed independent gap sets\n\t// an explicit number via the constructor or `setParagraphSpacing`; passing\n\t// `null` back restores the track-lineHeight behavior.\n\tconst paragraphSpacingNode = node<number | null>([], {\n\t\tname: \"paragraph-spacing\",\n\t\tinitial: opts.paragraphSpacing ?? null,\n\t});\n\n\tconst segmentsNode: Node<PreparedSegment[]> = node<PreparedSegment[]>(\n\t\t[textNode, fontNode],\n\t\t(data, actions, ctx) => {\n\t\t\tconst b0 = data[0];\n\t\t\tconst textVal = (b0 != null && b0.length > 0 ? b0.at(-1) : ctx.prevData[0]) as string;\n\t\t\tconst b1 = data[1];\n\t\t\tconst fontVal = (b1 != null && b1.length > 0 ? b1.at(-1) : ctx.prevData[1]) as string;\n\t\t\tconst result = analyzeAndMeasure(textVal, fontVal, adapter, measureCache);\n\t\t\tactions.emit(result);\n\t\t\t// Flush on deactivation + INVALIDATE only — preserve cache across\n\t\t\t// fn re-runs so text/font edits don't wipe per-segment entries that\n\t\t\t// still match the new text.\n\t\t\tconst flush = (): void => {\n\t\t\t\tmeasureCache.clear();\n\t\t\t\tadapter.clearCache?.();\n\t\t\t};\n\t\t\treturn { onDeactivation: flush, onInvalidate: flush };\n\t\t},\n\t\t{ name: \"segments\", describeKind: \"derived\" },\n\t);\n\n\tconst flowLinesNode = node<PositionedLine[]>(\n\t\t[segmentsNode, containerNode, columnsNode, obstaclesNode, lineHeightNode, paragraphSpacingNode],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst segments = data[0] as PreparedSegment[];\n\t\t\tconst t0 = monotonicNs();\n\t\t\t// `ps === null` → track current lineHeight. Any explicit number\n\t\t\t// (0, 60, …) overrides; passing `null` via `setParagraphSpacing`\n\t\t\t// restores tracking.\n\t\t\tconst effectiveSpacing = (data[5] as number | null) ?? (data[4] as number);\n\t\t\tconst { lines: result, cursor } = computeFlowLines(\n\t\t\t\tsegments,\n\t\t\t\tdata[1] as FlowContainer,\n\t\t\t\tdata[2] as FlowColumns,\n\t\t\t\tdata[3] as Obstacle[],\n\t\t\t\tdata[4] as number,\n\t\t\t\tminSlotWidth,\n\t\t\t\t{ paragraphSpacing: effectiveSpacing },\n\t\t\t);\n\t\t\tconst elapsed = monotonicNs() - t0;\n\t\t\t// Overflow signal: segments left unlaid-out after the container is\n\t\t\t// exhausted. `0` means all text fit; `N > 0` means the container\n\t\t\t// occluded/overflowed N segments — consumers can surface a \"…more\"\n\t\t\t// indicator, grow the container, or discard obstacles.\n\t\t\tconst overflow = Math.max(0, segments.length - cursor.segmentIndex);\n\t\t\tconst meta = flowLinesNode.meta;\n\t\t\tif (meta) {\n\t\t\t\temitToMeta(meta[\"line-count\"], result.length);\n\t\t\t\temitToMeta(meta[\"layout-time-ns\"], elapsed);\n\t\t\t\temitToMeta(meta[\"overflow-segments\"], overflow);\n\t\t\t}\n\t\t\tactions.emit(result);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tname: \"flow-lines\",\n\t\t\tmeta: {\n\t\t\t\t\"line-count\": 0,\n\t\t\t\t\"layout-time-ns\": 0,\n\t\t\t\t\"overflow-segments\": 0,\n\t\t\t},\n\t\t\tequals: (a, b) => {\n\t\t\t\tconst la = a as PositionedLine[];\n\t\t\t\tconst lb = b as PositionedLine[];\n\t\t\t\tif (la.length !== lb.length) return false;\n\t\t\t\tfor (let i = 0; i < la.length; i++) {\n\t\t\t\t\tconst pa = la[i]!;\n\t\t\t\t\tconst pb = lb[i]!;\n\t\t\t\t\tif (\n\t\t\t\t\t\tpa.x !== pb.x ||\n\t\t\t\t\t\tpa.y !== pb.y ||\n\t\t\t\t\t\tpa.width !== pb.width ||\n\t\t\t\t\t\tpa.slotWidth !== pb.slotWidth ||\n\t\t\t\t\t\tpa.text !== pb.text ||\n\t\t\t\t\t\tpa.columnIndex !== pb.columnIndex ||\n\t\t\t\t\t\tpa.flushToRight !== pb.flushToRight\n\t\t\t\t\t)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n\n\tg.add(textNode, { name: \"text\" });\n\tg.add(fontNode, { name: \"font\" });\n\tg.add(lineHeightNode, { name: \"line-height\" });\n\tg.add(containerNode, { name: \"container\" });\n\tg.add(columnsNode, { name: \"columns\" });\n\tg.add(obstaclesNode, { name: \"obstacles\" });\n\tg.add(paragraphSpacingNode, { name: \"paragraph-spacing\" });\n\tg.add(segmentsNode, { name: \"segments\" });\n\tg.add(flowLinesNode, { name: \"flow-lines\" });\n\n\treturn {\n\t\tgraph: g,\n\t\tsetText: (t: string) => g.set(\"text\", t),\n\t\tsetFont: (f: string) => g.set(\"font\", f),\n\t\tsetLineHeight: (lh: number) => g.set(\"line-height\", lh),\n\t\tsetContainer: (c: FlowContainer) => g.set(\"container\", c),\n\t\tsetColumns: (c: FlowColumns) => g.set(\"columns\", c),\n\t\tsetObstacles: (o: Obstacle[]) => g.set(\"obstacles\", o),\n\t\tsetParagraphSpacing: (ps: number | null) => g.set(\"paragraph-spacing\", ps),\n\t\tsegments: segmentsNode,\n\t\tflowLines: flowLinesNode,\n\t};\n}\n","/**\n * Typed errors for the surface layer (§9.3-core).\n *\n * The surface layer is consumed by `@graphrefly/mcp-server` and\n * `@graphrefly/cli`. Both have native error channels (MCP's `isError` flag,\n * CLI's exit codes), so surface functions throw a {@link SurfaceError}\n * carrying a structured code + details payload that wrappers can map to\n * their native shape. No `Result` envelope — keep the callsite idiom\n * `try/catch` and let each wrapper surface the error its own way.\n *\n * @module\n */\n\n/** Structured error codes emitted by the surface layer. JSON-safe. */\nexport type SurfaceErrorCode =\n\t| \"invalid-spec\"\n\t| \"graph-not-found\"\n\t| \"graph-exists\"\n\t| \"snapshot-not-found\"\n\t| \"node-not-found\"\n\t| \"reduce-timeout\"\n\t| \"catalog-error\"\n\t| \"restore-failed\"\n\t| \"snapshot-failed\"\n\t| \"tier-no-list\"\n\t| \"compose-not-configured\"\n\t| \"compose-failed\"\n\t| \"internal-error\";\n\n/** JSON-safe shape surfaces should echo back through the wrapper. */\nexport interface SurfaceErrorPayload {\n\tcode: SurfaceErrorCode;\n\tmessage: string;\n\t/** Optional structured detail; must be JSON-safe. */\n\tdetails?: Readonly<Record<string, unknown>>;\n}\n\n/**\n * Thrown by surface layer functions on failure. `code` is the stable\n * machine-readable identifier; `details` carries structured context\n * (e.g. `validateSpec` errors, missing path name). Both fields round-trip\n * through `toJSON()` for wrappers that serialize errors over the wire.\n */\nexport class SurfaceError extends Error {\n\treadonly code: SurfaceErrorCode;\n\treadonly details?: Readonly<Record<string, unknown>>;\n\n\tconstructor(\n\t\tcode: SurfaceErrorCode,\n\t\tmessage: string,\n\t\tdetails?: Readonly<Record<string, unknown>>,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"SurfaceError\";\n\t\tthis.code = code;\n\t\tif (details !== undefined) this.details = details;\n\t}\n\n\t/**\n\t * JSON-safe payload for wire serialization. Defensively validates\n\t * `details` — if it can't be round-tripped through `JSON.stringify`\n\t * (cyclic refs, `BigInt`, `Error` instance not pre-toJSON'd), the\n\t * payload falls back to `{code, message}` only rather than crashing\n\t * the MCP/CLI wrapper when it serializes this error onto the wire.\n\t */\n\ttoJSON(): SurfaceErrorPayload {\n\t\tconst out: SurfaceErrorPayload = { code: this.code, message: this.message };\n\t\tif (this.details !== undefined) {\n\t\t\tconst safe = safeDetails(this.details);\n\t\t\tif (safe !== undefined) out.details = safe;\n\t\t}\n\t\treturn out;\n\t}\n}\n\nfunction safeDetails(\n\tdetails: Readonly<Record<string, unknown>>,\n): Readonly<Record<string, unknown>> | undefined {\n\ttry {\n\t\t// Round-trip through JSON to strip non-serializable values (functions,\n\t\t// undefined) and reject cyclic structures with a thrown TypeError. The\n\t\t// round-trip result is the canonical wire shape.\n\t\treturn JSON.parse(JSON.stringify(details)) as Readonly<Record<string, unknown>>;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Wrap any thrown value as a SurfaceError. Idempotent on existing SurfaceError. */\nexport function asSurfaceError(\n\terr: unknown,\n\tfallbackCode: SurfaceErrorCode = \"internal-error\",\n): SurfaceError {\n\tif (err instanceof SurfaceError) return err;\n\tconst message = err instanceof Error ? err.message : String(err);\n\treturn new SurfaceError(fallbackCode, message);\n}\n","/**\n * Surface: create a graph from a {@link GraphSpec} (§9.3-core).\n *\n * Thin wrapper over {@link compileSpec} that converts the two failure modes\n * ({@link validateSpec} structural errors, and catalog-aware validation\n * errors) into typed {@link SurfaceError} throws. Consumers are MCP/CLI\n * wrappers, not end-user graph code — those should import `compileSpec`\n * directly.\n *\n * @module\n */\n\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport type { CompileSpecOptions, GraphSpec } from \"../graphspec/index.js\";\nimport { compileSpec, validateSpec, validateSpecAgainstCatalog } from \"../graphspec/index.js\";\nimport { SurfaceError } from \"./errors.js\";\n\n/** Options for {@link createGraph}. Same shape as {@link CompileSpecOptions}. */\nexport type CreateGraphOptions = CompileSpecOptions;\n\n/**\n * Build a {@link Graph} from a parsed {@link GraphSpec} with surface-layer\n * error typing.\n *\n * @throws {SurfaceError} `invalid-spec` for structural errors;\n * `catalog-error` when fn/source names or config don't match the catalog.\n */\nexport function createGraph(spec: GraphSpec, opts?: CreateGraphOptions): Graph {\n\tconst structural = validateSpec(spec);\n\tif (!structural.valid) {\n\t\tthrow new SurfaceError(\n\t\t\t\"invalid-spec\",\n\t\t\t`GraphSpec validation failed:\\n${structural.errors.join(\"\\n\")}`,\n\t\t\t{ errors: structural.errors },\n\t\t);\n\t}\n\tconst catalog = opts?.catalog ?? {};\n\tconst catalogValidation = validateSpecAgainstCatalog(spec, catalog);\n\tif (!catalogValidation.valid) {\n\t\tthrow new SurfaceError(\n\t\t\t\"catalog-error\",\n\t\t\t`Catalog validation failed:\\n${catalogValidation.errors.join(\"\\n\")}`,\n\t\t\t{ errors: catalogValidation.errors },\n\t\t);\n\t}\n\ttry {\n\t\treturn compileSpec(spec, opts);\n\t} catch (err) {\n\t\t// compileSpec re-throws validation errors plus may throw on missing\n\t\t// catalog entries for template-inner deferred nodes. Surface as\n\t\t// catalog-error; callers can inspect the wrapped message.\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new SurfaceError(\"catalog-error\", message);\n\t}\n}\n","/**\n * Surface: one-shot `input → pipeline → output` (§9.3-core).\n *\n * `runReduction` compiles a {@link GraphSpec}, pushes an input value to a\n * named state node, awaits the first post-push DATA emission on a named\n * output, then disposes the graph. Stateless per call — no graphId, no\n * registry.\n *\n * Named `runReduction` (not `reduce`) to avoid collision with the\n * reactive {@link reduce} operator in `extra/operators.ts`. The MCP tool\n * name (`graphrefly_reduce`) and CLI subcommand (`graphrefly reduce`) use\n * the short form; the library export carries the verb.\n *\n * The subscribe-before-push ordering is deliberate. `graph.set` propagates\n * synchronously for sync derived/operator chains; for async sources\n * (`fromPromise`, `fromAsyncIter`, LLM adapters) the first post-push DATA\n * arrives on a later tick. Subscribing before the push catches both, and\n * skipping the priming push-on-subscribe emission avoids resolving with the\n * stale pre-push cache (spec §2.2).\n *\n * @module\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport { COMPLETE, DATA, ERROR, RESOLVED } from \"@graphrefly/pure-ts/core\";\nimport type { GraphSpec, GraphSpecCatalog } from \"../graphspec/index.js\";\nimport { createGraph } from \"./create.js\";\nimport { SurfaceError } from \"./errors.js\";\n\n/** Options for {@link reduce}. */\nexport interface ReduceOptions {\n\t/** Fn/source catalog for {@link createGraph}. */\n\tcatalog?: GraphSpecCatalog;\n\t/** Path of the state node that receives the input. Default `\"input\"`. */\n\tinputPath?: string;\n\t/** Path of the node whose first post-push DATA is the result. Default `\"output\"`. */\n\toutputPath?: string;\n\t/** Hard deadline in milliseconds. Default `30_000`. */\n\ttimeoutMs?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/**\n * Run a spec as a one-shot reduction: `input → graph → output`.\n *\n * Resolves on the first `[DATA, v]` **or** `[RESOLVED]` emitted by\n * `outputPath` after the input push. The RESOLVED path handles spec\n * §1.3.3 equals-substitution (output recomputed to a value equal to its\n * cache, so the graph skips the DATA push) by returning `outputNode.cache`\n * — the caller always gets the settled value, never hangs on idempotent\n * inputs.\n *\n * @throws {SurfaceError} `invalid-spec` / `catalog-error` (propagated from\n * {@link createGraph}), `node-not-found` when `inputPath`/`outputPath`\n * can't be resolved, `reduce-timeout` when `timeoutMs` elapses without\n * a post-push emission, or the ERROR payload from the graph re-thrown\n * as `internal-error`.\n */\nexport async function runReduction(\n\tspec: GraphSpec,\n\tinput: unknown,\n\topts?: ReduceOptions,\n): Promise<unknown> {\n\tconst inputPath = opts?.inputPath ?? \"input\";\n\tconst outputPath = opts?.outputPath ?? \"output\";\n\tconst timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n\tconst graph = createGraph(spec, { catalog: opts?.catalog });\n\tlet outputNode: Node<unknown>;\n\ttry {\n\t\toutputNode = graph.resolve(outputPath);\n\t} catch {\n\t\tgraph.destroy();\n\t\tthrow new SurfaceError(\n\t\t\t\"node-not-found\",\n\t\t\t`reduce: output path \"${outputPath}\" is not registered`,\n\t\t\t{ path: outputPath },\n\t\t);\n\t}\n\t// Verify input path exists before we subscribe and push.\n\ttry {\n\t\tgraph.resolve(inputPath);\n\t} catch {\n\t\tgraph.destroy();\n\t\tthrow new SurfaceError(\n\t\t\t\"node-not-found\",\n\t\t\t`reduce: input path \"${inputPath}\" is not registered`,\n\t\t\t{ path: inputPath },\n\t\t);\n\t}\n\n\ttry {\n\t\treturn await new Promise<unknown>((resolve, reject) => {\n\t\t\tlet primed = false;\n\t\t\tlet settled = false;\n\t\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\t\tlet unsub: (() => void) | undefined;\n\t\t\t// Sync-settle deferred-unsubscribe invariant (C24-4):\n\t\t\t// `outputNode.subscribe(cb)` may invoke `cb` synchronously during\n\t\t\t// the call (push-on-subscribe per spec §2.2). If `cb` reaches\n\t\t\t// `finish()` BEFORE `subscribe()` returns, `unsub` is still\n\t\t\t// `undefined` and we'd leak the subscription if we tried `unsub?.()`\n\t\t\t// immediately. The contract: `finish()` toggles `shouldUnsub = true`;\n\t\t\t// the post-subscribe block (after `unsub` is assigned) checks that\n\t\t\t// flag and tears down. Two-phase ensures exactly one unsubscribe\n\t\t\t// regardless of whether settlement happened during or after the\n\t\t\t// subscribe call.\n\t\t\tlet shouldUnsub = false;\n\n\t\t\tconst finish = (action: () => void): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\t\tif (unsub !== undefined) {\n\t\t\t\t\tunsub();\n\t\t\t\t\tunsub = undefined;\n\t\t\t\t} else {\n\t\t\t\t\tshouldUnsub = true;\n\t\t\t\t}\n\t\t\t\taction();\n\t\t\t};\n\n\t\t\tunsub = outputNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\t// Skip push-on-subscribe emissions that land before we\n\t\t\t\t\t// trigger the input push — those carry pre-push state.\n\t\t\t\t\tif (!primed) continue;\n\t\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\t\tfinish(() => resolve(m[1]));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m[0] === RESOLVED) {\n\t\t\t\t\t\t// Spec §1.3.3 equals-substitution: the output recomputed to\n\t\t\t\t\t\t// a value equal to its cached value, so the graph emits\n\t\t\t\t\t\t// RESOLVED instead of DATA. For a one-shot reduce the\n\t\t\t\t\t\t// caller wants the output value — read the cache **before**\n\t\t\t\t\t\t// finish() runs unsub (which can trigger lazy deactivation\n\t\t\t\t\t\t// and clear the cache per the RAM-cache rule).\n\t\t\t\t\t\tconst cached = outputNode.cache;\n\t\t\t\t\t\tfinish(() => resolve(cached));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m[0] === ERROR) {\n\t\t\t\t\t\tconst payload = m[1];\n\t\t\t\t\t\tconst message = payload instanceof Error ? payload.message : String(payload);\n\t\t\t\t\t\tconst cause = payload instanceof Error ? payload : undefined;\n\t\t\t\t\t\tfinish(() =>\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew SurfaceError(\n\t\t\t\t\t\t\t\t\t\"internal-error\",\n\t\t\t\t\t\t\t\t\t`reduce: output emitted ERROR: ${message}`,\n\t\t\t\t\t\t\t\t\tcause != null ? { cause } : undefined,\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\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\t\tfinish(() =>\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew SurfaceError(\n\t\t\t\t\t\t\t\t\t\"internal-error\",\n\t\t\t\t\t\t\t\t\t`reduce: output COMPLETEd without a post-push DATA`,\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\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (shouldUnsub) {\n\t\t\t\tunsub?.();\n\t\t\t\tunsub = undefined;\n\t\t\t}\n\n\t\t\tprimed = true;\n\t\t\ttry {\n\t\t\t\tgraph.set(inputPath, input);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\tconst cause = err instanceof Error ? err : undefined;\n\t\t\t\tfinish(() =>\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew SurfaceError(\n\t\t\t\t\t\t\t\"internal-error\",\n\t\t\t\t\t\t\t`reduce: failed to set input on \"${inputPath}\": ${message}`,\n\t\t\t\t\t\t\tcause != null ? { path: inputPath, cause } : { path: inputPath },\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Synchronous wave may have already settled the promise via the\n\t\t\t// subscribe callback above; skip the timer in that case so we\n\t\t\t// don't leak an orphan setTimeout into the event loop (A1, E4).\n\t\t\tif (!settled && Number.isFinite(timeoutMs) && timeoutMs > 0) {\n\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\tfinish(() =>\n\t\t\t\t\t\treject(\n\t\t\t\t\t\t\tnew SurfaceError(\n\t\t\t\t\t\t\t\t\"reduce-timeout\",\n\t\t\t\t\t\t\t\t`reduce: no output emitted within ${timeoutMs}ms`,\n\t\t\t\t\t\t\t\t{ timeoutMs, outputPath },\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}, timeoutMs);\n\t\t\t\t// Belt-and-suspenders: if the caller drops the returned promise\n\t\t\t\t// we shouldn't keep the process alive.\n\t\t\t\ttimer.unref?.();\n\t\t\t}\n\t\t});\n\t} finally {\n\t\tgraph.destroy();\n\t}\n}\n","/**\n * Surface: snapshot save/restore/diff/list over {@link KvStorageTier} (§9.3-core).\n *\n * One-shot snapshot management for stateless callers (MCP tools, CLI\n * commands) layered on the existing multi-tier auto-checkpoint substrate.\n * A saved snapshot is a `mode: \"full\"` {@link GraphCheckpointRecord} with\n * `seq: 0` — byte-identical to the baseline anchor\n * {@link Graph.attachSnapshotStorage} writes on its first flush. An\n * auto-checkpointed graph can therefore be restored through this surface,\n * and a surface-saved snapshot can be picked up by `attachSnapshotStorage({\n * autoRestore: true })`.\n *\n * The wire envelope stays at {@link SNAPSHOT_WIRE_VERSION}; no new format.\n *\n * @module\n */\n\nimport { wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport type { KvStorageTier } from \"@graphrefly/pure-ts/extra\";\nimport type {\n\tGraphCheckpointRecord,\n\tGraphDiffResult,\n\tGraphNodeFactory,\n\tGraphPersistSnapshot,\n} from \"@graphrefly/pure-ts/graph\";\nimport { Graph, SNAPSHOT_VERSION } from \"@graphrefly/pure-ts/graph\";\nimport { SurfaceError } from \"./errors.js\";\n\n/**\n * Current envelope version. Re-exported from `graph.ts` so the one-shot\n * surface path and `Graph.attachSnapshotStorage` write byte-identical\n * `format_version` fields — no silent wire drift.\n */\nexport const SNAPSHOT_WIRE_VERSION = SNAPSHOT_VERSION;\n\n/** Shape returned by {@link saveSnapshot}. */\nexport interface SaveSnapshotResult {\n\tsnapshotId: string;\n\ttimestamp_ns: number;\n}\n\n/** Options for {@link restoreSnapshot}. */\nexport interface RestoreSnapshotOptions {\n\t/** Passthrough to `Graph.fromSnapshot`. First matching pattern wins. */\n\tfactories?: Record<string, GraphNodeFactory>;\n}\n\n/**\n * Key prefix applied to every surface-written snapshot record. Isolates\n * surface-saved snapshots from other keys on the same tier (notably\n * `attachSnapshotStorage` baseline/WAL keys written under `graph.name`).\n */\nexport const SNAPSHOT_KEY_PREFIX = \"snapshot:\";\n\n/**\n * Reject caller-supplied ids that start with {@link SNAPSHOT_KEY_PREFIX}.\n *\n * Surface ids are keyed in the caller's external namespace; the `\"snapshot:\"`\n * prefix is an implementation detail of tier layout. Allowing `\"snapshot:foo\"`\n * through would produce surprising round-trips — `deleteSnapshot(\"foo\")` and\n * `deleteSnapshot(\"snapshot:foo\")` would both target the same tier key, while\n * `listSnapshots()` decodes to `\"foo\"` — so we enforce disjointness at the API\n * boundary (pre-1.0, no back-compat).\n */\nfunction assertExternalId(snapshotId: string): void {\n\tif (snapshotId.startsWith(SNAPSHOT_KEY_PREFIX)) {\n\t\tthrow new SurfaceError(\n\t\t\t\"snapshot-failed\",\n\t\t\t`snapshot id must not start with \"${SNAPSHOT_KEY_PREFIX}\" (reserved); got \"${snapshotId}\"`,\n\t\t\t{ snapshotId },\n\t\t);\n\t}\n}\n\nfunction encodeKey(snapshotId: string): string {\n\treturn `${SNAPSHOT_KEY_PREFIX}${snapshotId}`;\n}\n\nfunction decodeKey(key: string): string | undefined {\n\treturn key.startsWith(SNAPSHOT_KEY_PREFIX) ? key.slice(SNAPSHOT_KEY_PREFIX.length) : undefined;\n}\n\nfunction unwrapCheckpoint(raw: unknown, snapshotId: string): GraphPersistSnapshot {\n\tif (raw == null || typeof raw !== \"object\") {\n\t\tthrow new SurfaceError(\"snapshot-not-found\", `snapshot \"${snapshotId}\" not found in tier`, {\n\t\t\tsnapshotId,\n\t\t});\n\t}\n\t// Accept both wrapped (GraphCheckpointRecord) and bare\n\t// (GraphPersistSnapshot) payloads — attachSnapshotStorage writes wrapped, a user\n\t// may also hand us a bare one via dictKv for tests.\n\tconst record = raw as Record<string, unknown>;\n\tif (\"mode\" in record) {\n\t\tif (record.mode === \"full\" && \"snapshot\" in record) {\n\t\t\treturn record.snapshot as GraphPersistSnapshot;\n\t\t}\n\t\tif (record.mode === \"diff\") {\n\t\t\tthrow new SurfaceError(\n\t\t\t\t\"restore-failed\",\n\t\t\t\t`snapshot \"${snapshotId}\" is a diff record (legacy/non-paired tier write); under the Phase 14.6 paired-tier shape snapshot tiers hold only baselines. For WAL replay use Graph.restoreSnapshot({ mode: \"diff\", source: { tier, walTier } }).`,\n\t\t\t\t{ snapshotId, mode: \"diff\" },\n\t\t\t);\n\t\t}\n\t\tthrow new SurfaceError(\n\t\t\t\"restore-failed\",\n\t\t\t`snapshot \"${snapshotId}\" has unknown mode \"${String(record.mode)}\"`,\n\t\t\t{ snapshotId, mode: String(record.mode) },\n\t\t);\n\t}\n\tif (\"nodes\" in record && \"edges\" in record && \"subgraphs\" in record && \"name\" in record) {\n\t\treturn record as unknown as GraphPersistSnapshot;\n\t}\n\tthrow new SurfaceError(\n\t\t\"restore-failed\",\n\t\t`snapshot \"${snapshotId}\" payload is not a GraphCheckpointRecord or GraphPersistSnapshot`,\n\t\t{ snapshotId },\n\t);\n}\n\n/**\n * Write a graph's current state as a one-shot `mode: \"full\"` record.\n *\n * Uses the same {@link GraphCheckpointRecord} envelope as\n * {@link Graph.attachSnapshotStorage} so the two persistence paths interoperate.\n *\n * @throws {SurfaceError} `snapshot-failed` when the tier's `save` throws.\n */\nexport async function saveSnapshot(\n\tgraph: Graph,\n\tsnapshotId: string,\n\ttier: KvStorageTier,\n): Promise<SaveSnapshotResult> {\n\tassertExternalId(snapshotId);\n\tlet snapshot: GraphPersistSnapshot;\n\ttry {\n\t\tsnapshot = graph.snapshot();\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new SurfaceError(\n\t\t\t\"snapshot-failed\",\n\t\t\t`snapshot \"${snapshotId}\" serialization failed: ${message}`,\n\t\t\t{ snapshotId },\n\t\t);\n\t}\n\tconst record: GraphCheckpointRecord = {\n\t\tname: graph.name,\n\t\tmode: \"full\",\n\t\tseq: 0,\n\t\ttimestamp_ns: wallClockNs(),\n\t\tformat_version: SNAPSHOT_WIRE_VERSION,\n\t\tsnapshot,\n\t};\n\ttry {\n\t\tawait tier.save(encodeKey(snapshotId), record);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new SurfaceError(\"snapshot-failed\", `snapshot \"${snapshotId}\" save failed: ${message}`, {\n\t\t\tsnapshotId,\n\t\t});\n\t}\n\treturn { snapshotId, timestamp_ns: record.timestamp_ns };\n}\n\n/**\n * Load a snapshot from a tier and materialize it as a new {@link Graph}.\n *\n * Uses {@link Graph.fromSnapshot} to reconstruct topology; pass\n * `factories` when the graph includes non-state nodes that the default\n * hydrator can't rebuild on its own.\n *\n * **Requires a `mode: \"full\"` record.** Surface-written snapshots from\n * {@link saveSnapshot} always qualify. Records written by\n * {@link Graph.attachSnapshotStorage} with `compactEvery > 1` may be\n * `mode: \"diff\"` between compacts — those throw `restore-failed` until\n * the tier's next compact flush (or until Phase 8.7 WAL replay lands).\n * If you need interop during development, either call\n * {@link saveSnapshot} explicitly (always full) or configure\n * `attachSnapshotStorage({compactEvery: 1})`.\n *\n * @throws {SurfaceError} `snapshot-not-found` on miss; `restore-failed`\n * when the payload shape doesn't match, when the record is\n * `mode: \"diff\"`, or when `Graph.fromSnapshot` rejects.\n */\nexport async function restoreSnapshot(\n\tsnapshotId: string,\n\ttier: KvStorageTier,\n\topts?: RestoreSnapshotOptions,\n): Promise<Graph> {\n\tassertExternalId(snapshotId);\n\t// Try namespaced key first (surface-written records), fall back to raw key\n\t// so callers restoring snapshots that predate the namespacing change (or\n\t// bare `GraphPersistSnapshot` payloads written by user test fixtures)\n\t// still resolve. Once all writers are on encodeKey, the fallback can go.\n\tconst key = encodeKey(snapshotId);\n\tlet raw = await tier.load(key);\n\tif (raw === undefined) {\n\t\traw = await tier.load(snapshotId);\n\t}\n\tconst snapshot = unwrapCheckpoint(raw, snapshotId);\n\ttry {\n\t\treturn Graph.fromSnapshot(\n\t\t\tsnapshot,\n\t\t\topts?.factories ? { factories: opts.factories } : undefined,\n\t\t);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new SurfaceError(\n\t\t\t\"restore-failed\",\n\t\t\t`snapshot \"${snapshotId}\" restore failed: ${message}`,\n\t\t\t{\n\t\t\t\tsnapshotId,\n\t\t\t},\n\t\t);\n\t}\n}\n\n/**\n * Load two snapshots and compute a {@link GraphDiffResult} via static\n * {@link Graph.diff}. Returns the audit shape (structural + value diff,\n * no payload); use {@link diffForWAL} directly for WAL-oriented diffs.\n *\n * @throws {SurfaceError} `snapshot-not-found` on either miss.\n */\nexport async function diffSnapshots(\n\tsnapshotIdA: string,\n\tsnapshotIdB: string,\n\ttier: KvStorageTier,\n): Promise<GraphDiffResult> {\n\tassertExternalId(snapshotIdA);\n\tassertExternalId(snapshotIdB);\n\tconst loadWithFallback = async (id: string): Promise<unknown> => {\n\t\tconst key = encodeKey(id);\n\t\tlet raw = await tier.load(key);\n\t\tif (raw === undefined) raw = await tier.load(id);\n\t\treturn raw;\n\t};\n\tconst [rawA, rawB] = await Promise.all([\n\t\tloadWithFallback(snapshotIdA),\n\t\tloadWithFallback(snapshotIdB),\n\t]);\n\tconst snapshotA = unwrapCheckpoint(rawA, snapshotIdA);\n\tconst snapshotB = unwrapCheckpoint(rawB, snapshotIdB);\n\treturn Graph.diff(snapshotA, snapshotB);\n}\n\n/**\n * Enumerate snapshot ids on a tier.\n *\n * Only keys written by {@link saveSnapshot} are returned. Surface-written\n * records are stored under the `\"snapshot:\"` key prefix and decoded back to\n * the caller-visible id before being returned — other keys on the same tier\n * (notably `attachSnapshotStorage` baseline/WAL keys written under `graph.name`) are\n * filtered out automatically. This lets a single tier back both the surface\n * and `attachSnapshotStorage` without leaking graph names through `listSnapshots`.\n *\n * @param tier — the storage tier to enumerate.\n * @param opts.includeUnprefixed — when `true`, also return keys that are\n * NOT under the namespacing prefix. Off by default; set this when reading\n * pre-namespacing snapshot sets.\n *\n * **Caveat:** when a tier is shared with {@link Graph.attachSnapshotStorage}, its\n * auto-checkpoint baseline + WAL keys (written under `graph.name`) are\n * unprefixed. Calling with `includeUnprefixed: true` returns those keys\n * alongside surface snapshots — and subsequent `restoreSnapshot` /\n * `deleteSnapshot` will operate on them via the fallback-lookup path,\n * potentially overwriting or deleting live auto-checkpoint state. Use\n * `includeUnprefixed` only against tiers you know are NOT shared with\n * `attachSnapshotStorage`, or follow up with a predicate filter to separate\n * ids you own from ones owned by other subsystems.\n *\n * @throws {SurfaceError} `tier-no-list` when the tier does not implement\n * the optional `list()` method. Check `typeof tier.list === \"function\"`\n * before calling if you want to branch on capability.\n */\nexport async function listSnapshots(\n\ttier: KvStorageTier,\n\topts?: { includeUnprefixed?: boolean },\n): Promise<readonly string[]> {\n\tif (typeof tier.list !== \"function\") {\n\t\tthrow new SurfaceError(\n\t\t\t\"tier-no-list\",\n\t\t\t\"KvStorageTier does not implement list(); wrap the tier with an enumerator or use a different backend\",\n\t\t);\n\t}\n\tconst keys = await tier.list();\n\tconst result: string[] = [];\n\tconst includeUnprefixed = opts?.includeUnprefixed === true;\n\tfor (const k of keys) {\n\t\tconst decoded = decodeKey(k);\n\t\tif (decoded !== undefined) result.push(decoded);\n\t\telse if (includeUnprefixed) result.push(k);\n\t}\n\treturn result;\n}\n\n/**\n * Delete a snapshot from a tier.\n *\n * Silent on miss (clear semantics). `tier.clear` is optional — throws\n * `snapshot-failed` when the tier is append-only.\n *\n * @throws {SurfaceError} `snapshot-failed` when `clear` is unsupported\n * or throws.\n */\nexport async function deleteSnapshot(snapshotId: string, tier: KvStorageTier): Promise<void> {\n\tassertExternalId(snapshotId);\n\tif (typeof tier.delete !== \"function\") {\n\t\tthrow new SurfaceError(\n\t\t\t\"snapshot-failed\",\n\t\t\t`KvStorageTier is append-only (no delete()); cannot delete \"${snapshotId}\"`,\n\t\t\t{ snapshotId },\n\t\t);\n\t}\n\ttry {\n\t\tawait tier.delete(encodeKey(snapshotId));\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new SurfaceError(\n\t\t\t\"snapshot-failed\",\n\t\t\t`snapshot \"${snapshotId}\" delete failed: ${message}`,\n\t\t\t{\n\t\t\t\tsnapshotId,\n\t\t\t},\n\t\t);\n\t}\n}\n","/**\n * `topologyView({ graph, layout? }): TopologyViewGraph` — D3 of the\n * three-layer view (`docs/optimizations.md` line \"D — Three-layer view\").\n *\n * Composes a target {@link Graph} with a pluggable layered-DAG layout into a\n * live {@link LayoutFrame} stream:\n *\n * ```text\n * target graph\n * └─ observe({ changeset: true }) → Node<GraphChange>\n * └─ filter(topology) → recompute layout\n * └─ each change → merge into a LayoutFrame\n * ```\n *\n * **Initial frame** is delivered on subscribe (push-on-subscribe per spec\n * §2.2) — the layout is seeded from `graph.describe()` at construction. A\n * consumer that wants deltas only can `pipe(skip(1))` from the output node.\n *\n * **Pluggable layout** — pass `opts.layout` to swap in `dagre`, `elk`, or\n * any layered-DAG library. The default is a minimal Sugiyama in\n * `_internal.ts` (matches the library's \"no deps, browser-safe\" ethos).\n *\n * **No timers** — animation is driven by the changeset's batch boundaries.\n * Each batch IS a frame; CSS transitions handle visual fade.\n *\n * @module\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport { Graph, type GraphChange, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { defaultLayout } from \"./_internal.js\";\nimport type { LayoutFn, LayoutFrame } from \"./types.js\";\n\nexport type {\n\tLayoutBox,\n\tLayoutEdge,\n\tLayoutFn,\n\tLayoutFrame,\n} from \"./types.js\";\n\n/** Topology variants from {@link GraphChange} that invalidate layout. */\nconst TOPOLOGY_TYPES = new Set<GraphChange[\"type\"]>([\n\t\"node-added\",\n\t\"node-removed\",\n\t\"mount\",\n\t\"unmount\",\n]);\n\nfunction isTopologyChange(c: GraphChange): boolean {\n\treturn TOPOLOGY_TYPES.has(c.type);\n}\n\n/** Options for {@link topologyView}. */\nexport interface TopologyViewOptions {\n\t/** The target graph to observe. */\n\treadonly graph: Graph;\n\t/**\n\t * Pluggable layout function. Defaults to the bundled Sugiyama layout.\n\t * Adapt `dagre` / `elk` / etc. by wrapping their output in the\n\t * {@link LayoutFn} shape.\n\t */\n\treadonly layout?: LayoutFn;\n\t/** Optional name for the {@link TopologyViewGraph}. Defaults to `\"topology-view\"`. */\n\treadonly name?: string;\n\t/**\n\t * Forward extra options to the underlying {@link Graph} constructor\n\t * (e.g. `versioning`, `traceCapacity`).\n\t */\n\treadonly graphOptions?: GraphOptions;\n}\n\n/**\n * Live topology view — a {@link Graph} subclass that exposes a single\n * output node {@link TopologyViewGraph.frame} emitting {@link LayoutFrame}s.\n */\nexport class TopologyViewGraph extends Graph {\n\treadonly target: Graph;\n\treadonly layout: LayoutFn;\n\treadonly frame: Node<LayoutFrame>;\n\n\tconstructor(opts: TopologyViewOptions) {\n\t\tconst name = opts.name ?? \"topology-view\";\n\t\tsuper(name, opts.graphOptions);\n\t\tthis.target = opts.graph;\n\t\tthis.layout = opts.layout ?? ((spec) => defaultLayout(spec, \"LR\"));\n\n\t\t// 1. Source node — discrete GraphChange events from the target graph.\n\t\t// Every change (data + topology + batch boundaries) flows here.\n\t\tconst changeset = this.target.observe({\n\t\t\tchangeset: true,\n\t\t\tchangesetName: \"target-changeset\",\n\t\t});\n\t\tthis.add(changeset, { name: \"changeset\" });\n\n\t\t// 2. Layout — recomputes only on topology changes. Reads\n\t\t// `target.describe()` inside the fn body — this is a method call on\n\t\t// the stored Graph reference, NOT a `.cache` read of another\n\t\t// reactive node, so it does not violate spec §5.12. Initial value\n\t\t// is seeded from the construction-time describe so the first\n\t\t// push-on-subscribe delivers a valid frame before any change\n\t\t// arrives. `partial: true` opts out of the first-run gate (§2.7) —\n\t\t// the seeded `initial` is correct from construction; we don't need\n\t\t// to wait for the upstream changeset to deliver its first DATA.\n\t\tconst seedLayout = this._computeLayout();\n\t\tconst layoutNode = this.derived<Pick<LayoutFrame, \"boxes\" | \"edges\">>(\n\t\t\t\"layout\",\n\t\t\t[\"changeset\"],\n\t\t\t(data, _ctx) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\t\t// No changeset DATA this wave (or this is the seed activation\n\t\t\t\t\t// before changeset has fired). Settle as RESOLVED — caller\n\t\t\t\t\t// will read `prevData[0]` if it needs the current layout.\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\tlet topologyHit = false;\n\t\t\t\tfor (const c of batch0 as readonly GraphChange[]) {\n\t\t\t\t\tif (isTopologyChange(c)) {\n\t\t\t\t\t\ttopologyHit = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!topologyHit) {\n\t\t\t\t\t// Data-only wave: keep layout unchanged. The cached layout\n\t\t\t\t\t// (from `initial` or a prior emit) is still valid.\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\treturn [this._computeLayout()];\n\t\t\t},\n\t\t\t{ initial: seedLayout, partial: true },\n\t\t);\n\t\tvoid layoutNode;\n\n\t\t// 3. Frame — merges latest layout with the per-wave changes from the\n\t\t// changeset. Two deps: layout (slow-moving — re-emits only on\n\t\t// topology) and changeset (fast-moving — re-emits per change event).\n\t\t// The fn collapses each wave into one LayoutFrame.\n\t\t//\n\t\t// `partial: true` opts out of the first-run gate so that a\n\t\t// data-only wave (where the layout dep settles RESOLVED but\n\t\t// changeset emits DATA) still triggers fn — without it, frame\n\t\t// would never run for data events because layout settled RESOLVED\n\t\t// and `_depSettledAsResolved` does NOT exit the sentinel state on\n\t\t// a dep, leaving the gate closed indefinitely.\n\t\tthis.frame = this.derived<LayoutFrame>(\n\t\t\t\"frame\",\n\t\t\t[\"layout\", \"changeset\"],\n\t\t\t(data, ctx) => {\n\t\t\t\tconst layoutBatch = data[0];\n\t\t\t\tconst changesetBatch = data[1];\n\t\t\t\tconst layout =\n\t\t\t\t\tlayoutBatch != null && layoutBatch.length > 0\n\t\t\t\t\t\t? (layoutBatch.at(-1) as Pick<LayoutFrame, \"boxes\" | \"edges\">)\n\t\t\t\t\t\t: (ctx.prevData[0] as Pick<LayoutFrame, \"boxes\" | \"edges\"> | undefined);\n\t\t\t\tif (layout == null) {\n\t\t\t\t\t// No layout yet — defer (skip emit). With `initial:` on\n\t\t\t\t\t// `layout`, this should never happen on the activation\n\t\t\t\t\t// wave, but guard for the edge case.\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\tconst changes: GraphChange[] = [];\n\t\t\t\tif (changesetBatch != null) {\n\t\t\t\t\tfor (const c of changesetBatch) changes.push(c as GraphChange);\n\t\t\t\t}\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tboxes: layout.boxes,\n\t\t\t\t\t\tedges: layout.edges,\n\t\t\t\t\t\tchanges,\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t},\n\t\t\t{\n\t\t\t\tinitial: { boxes: seedLayout.boxes, edges: seedLayout.edges, changes: [] },\n\t\t\t\tpartial: true,\n\t\t\t},\n\t\t);\n\n\t\t// No external keepalive — the chain `frame → layout → changeset` is\n\t\t// activated by external subscribers on `frame`. When the last consumer\n\t\t// unsubscribes, the chain tears down and releases the target observe\n\t\t// handle. Producer-bound lifecycle, no leaks.\n\t}\n\n\tprivate _computeLayout(): Pick<LayoutFrame, \"boxes\" | \"edges\"> {\n\t\t// /qa F-5: short-circuit if the target was destroyed. `target.describe()`\n\t\t// on a destroyed graph returns empty topology silently — without this\n\t\t// guard, frame consumers would see a degraded layout (empty boxes /\n\t\t// edges) with no signal that the underlying graph is gone. The COMPLETE\n\t\t// propagation is handled by the changeset stream's teardown variant\n\t\t// flowing through `frame`.\n\t\tif (this.target.destroyed) {\n\t\t\treturn { boxes: [], edges: [] };\n\t\t}\n\t\tconst spec = this.target.describe();\n\t\treturn this.layout(spec);\n\t}\n}\n\n/**\n * Factory wrapper — `topologyView({ graph, layout? })`.\n */\nexport function topologyView(opts: TopologyViewOptions): TopologyViewGraph {\n\tconst view = new TopologyViewGraph(opts);\n\tview.tagFactory(\"topologyView\");\n\treturn view;\n}\n","/**\n * Default layout for `topologyView` — wraps the bundled Sugiyama-style layered\n * DAG layout from `extra/render/_layout-sugiyama.ts`.\n *\n * The library ships zero deps and is browser-safe by default; the bundled\n * layout matches that ethos. Users wanting production-quality layout can swap\n * in `dagre`, `elk`, etc. by passing `opts.layout` to {@link topologyView}.\n *\n * Direction-agnostic (defaults to `\"LR\"`). Per-node label sizing is\n * conservative: 1 cell tall, label-length-derived width capped at 24 cells.\n *\n * @module\n */\n\nimport type { GraphDescribeOutput } from \"@graphrefly/pure-ts/graph\";\nimport {\n\ttype LayoutDirection,\n\ttype LayoutEdgePoint,\n\tsugiyamaLayout,\n} from \"../../base/render/_layout-sugiyama.js\";\nimport type { LayoutFn, LayoutFrame } from \"./types.js\";\n\nconst MIN_W = 3;\nconst MAX_W = 24;\nconst NODE_H = 1;\nconst LAYER_GAP = 4;\nconst NODE_GAP = 1;\n\n/**\n * Best-effort label-width estimate (cells). Caller can override by providing\n * its own {@link LayoutFn}; this default treats every visible character as\n * one cell. Local-segment is preferred over qualified path so the label\n * stays compact on cells with deep mounts.\n */\nfunction widthOf(id: string): number {\n\tconst local = id.includes(\"::\") ? (id.split(\"::\").pop() ?? id) : id;\n\treturn Math.max(MIN_W, Math.min(MAX_W, local.length + 2));\n}\n\nfunction heightOf(_id: string): number {\n\treturn NODE_H;\n}\n\n/**\n * Default layered-DAG layout for `topologyView`. Pure fn over a describe\n * snapshot; deterministic for a given input ordering.\n */\nexport function defaultLayout(\n\tspec: GraphDescribeOutput,\n\tdirection: LayoutDirection = \"LR\",\n): Pick<LayoutFrame, \"boxes\" | \"edges\"> {\n\tconst ids = Object.keys(spec.nodes).sort();\n\tconst edges = spec.edges.map((e) => ({ from: e.from, to: e.to }));\n\tif (ids.length === 0) {\n\t\treturn { boxes: [], edges: [] };\n\t}\n\tconst result = sugiyamaLayout({\n\t\tnodes: ids,\n\t\tedges,\n\t\twidthCells: widthOf,\n\t\theightCells: heightOf,\n\t\tlayerGap: LAYER_GAP,\n\t\tnodeGap: NODE_GAP,\n\t\tdirection,\n\t});\n\n\t// Map back to the public LayoutFrame shape, attaching per-node meta from\n\t// the describe snapshot for downstream renderers (kind/factory/domain).\n\tconst boxes = result.boxes.map((b) => ({\n\t\tid: b.id,\n\t\tx: b.x,\n\t\ty: b.y,\n\t\tw: b.w,\n\t\th: b.h,\n\t\tmeta: spec.nodes[b.id]?.meta,\n\t}));\n\n\t// Build a quick \"to → ordered deps\" lookup for `depIndex` attribution. The\n\t// describe snapshot's `nodes[id].deps` is the positional dep array; the\n\t// edge's depIndex is the position of `from` in `to`'s deps.\n\t//\n\t// /qa F-22: when the same upstream appears multiple times in `to.deps`\n\t// (diamond / duplicate-dep patterns), each (from, to) edge gets a distinct\n\t// depIndex via a per-`to` running cursor over occurrences in `toDeps`.\n\tconst seenPerTo = new Map<string, number>();\n\tconst edgeOut = result.edges.map((e) => {\n\t\tconst toDeps = spec.nodes[e.to]?.deps ?? [];\n\t\tconst cursorKey = `${e.to}::${e.from}`;\n\t\tconst startFrom = seenPerTo.get(cursorKey) ?? 0;\n\t\tconst depIndex = toDeps.indexOf(e.from, startFrom);\n\t\tseenPerTo.set(cursorKey, depIndex >= 0 ? depIndex + 1 : startFrom);\n\t\tconst points = e.points.map((p: LayoutEdgePoint) => [p.x, p.y] as const);\n\t\treturn {\n\t\t\tfrom: e.from,\n\t\t\tto: e.to,\n\t\t\tdepIndex: depIndex >= 0 ? depIndex : -1,\n\t\t\tpoints: points as ReadonlyArray<readonly [number, number]>,\n\t\t};\n\t});\n\n\treturn { boxes, edges: edgeOut };\n}\n\n/** Adapter — narrows `defaultLayout` to the {@link LayoutFn} signature. */\nexport const defaultLayoutFn: LayoutFn = (spec) => defaultLayout(spec, \"LR\");\n"],"mappings":"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","names":["node","import_core","clampNonNegative","import_core","batch","import_core","import_core","import_core","import_core","import_extra","import_core","import_extra","import_core","import_extra","import_core","import_extra","raw","import_core","import_extra","batch","tier","import_core","mapUsage","toLLMResponse","import_core","mapUsage","toLLMResponse","import_core","import_extra","batch","tier","import_extra","import_core","import_core","import_core","import_core","import_core","import_extra","import_core","import_core","import_extra","makeAbortError","batch","import_core","import_extra","batch","meta","import_extra","import_extra","import_extra","import_core","import_extra","makeAbortError","sleep","import_core","import_extra","import_core","import_extra","import_core","import_extra","nodeFactory","import_core","import_core","import_extra","batch","import_core","import_extra","import_core","import_extra","import_graph","import_core","import_extra","meta","batch","import_core","import_extra","promptNode","import_core","import_graph","batch","store","batch","import_core","import_extra","batch","import_core","store","batch","import_core","batch","import_core","batch","import_core","batch","i","import_core","batch","import_core","batch","import_core","import_extra","import_graph","batch","import_core","import_extra","batch","import_core","import_extra","batch","import_core","import_extra","import_graph","batch","import_core","import_extra","batch","import_core","import_extra","import_graph","import_core","import_extra","import_core","import_extra","isNodeLike","keepalive","node","batch","ageSeconds","import_core","import_extra","import_graph","import_core","import_extra","import_graph","batch","out","filter","policy","NS_PER_SEC","batch","out","meta","reindex","ageSeconds","node","meta","import_core","import_extra","import_core","import_graph","import_core","import_extra","import_graph","meta","batch","i","node","_","meta","batch","stripFences","feedback","meta","node","import_core","import_extra","VALID_NODE_TYPES","node","import_core","import_extra","import_graph","import_extra","deepFreeze","batch","tier","import_core","import_graph","import_core","import_graph","import_core","graphemeSegmenter","w","canBreakAfter","text","endsAtSoftHyphen","meta","batch","batch","import_core","import_extra","import_graph","import_extra","baseMeta","batch","policy","import_core","import_extra","batch","import_core","batch","import_core","import_extra","batch","topic","import_core","import_extra","import_graph","batch","ageSeconds","import_core","import_extra","import_graph","batch","filter","node","isNode","import_core","import_extra","import_graph","import_graph","batch","import_core","import_extra","import_graph","DEFAULT_MAX_PER_PUMP","requireNonNegativeInt","batch","import_core","import_extra","import_graph","tier","import_core","import_graph","meta","batch","import_core","import_graph","batch","meta","import_core","DEFAULT_TIMEOUT_MS","import_core","import_graph","tier","import_graph"]}
|