@graphrefly/graphrefly 0.47.0 → 0.47.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/dist/base/composition/index.cjs +24 -16
  2. package/dist/base/composition/index.cjs.map +1 -1
  3. package/dist/base/composition/index.js +6 -6
  4. package/dist/base/index.cjs +142 -86
  5. package/dist/base/index.cjs.map +1 -1
  6. package/dist/base/index.js +11 -11
  7. package/dist/base/io/index.cjs +114 -68
  8. package/dist/base/io/index.cjs.map +1 -1
  9. package/dist/base/io/index.js +5 -5
  10. package/dist/base/sources/browser/index.cjs +13 -9
  11. package/dist/base/sources/browser/index.cjs.map +1 -1
  12. package/dist/base/sources/browser/index.js +13 -9
  13. package/dist/base/sources/browser/index.js.map +1 -1
  14. package/dist/base/sources/event/index.cjs +1 -1
  15. package/dist/base/sources/event/index.cjs.map +1 -1
  16. package/dist/base/sources/event/index.js +1 -1
  17. package/dist/base/sources/index.cjs +21 -13
  18. package/dist/base/sources/index.cjs.map +1 -1
  19. package/dist/base/sources/index.js +3 -3
  20. package/dist/base/sources/node/index.cjs +43 -37
  21. package/dist/base/sources/node/index.cjs.map +1 -1
  22. package/dist/base/sources/node/index.js +43 -37
  23. package/dist/base/sources/node/index.js.map +1 -1
  24. package/dist/{chunk-VLAGJZSL.js → chunk-3O3NKZJW.js} +2 -2
  25. package/dist/{chunk-YJ4U2D2C.js → chunk-446I4EGD.js} +9 -7
  26. package/dist/chunk-446I4EGD.js.map +1 -0
  27. package/dist/{chunk-DKNHAICT.js → chunk-5GVURVIG.js} +14 -8
  28. package/dist/chunk-5GVURVIG.js.map +1 -0
  29. package/dist/{chunk-2OB3CEJS.js → chunk-6MRSX3YK.js} +2 -2
  30. package/dist/{chunk-EVYY4X5A.js → chunk-6ZLCPUXS.js} +2 -2
  31. package/dist/{chunk-ZVXXDWIB.js → chunk-7AVQIGF6.js} +514 -33
  32. package/dist/chunk-7AVQIGF6.js.map +1 -0
  33. package/dist/{chunk-7EGRP2VX.js → chunk-7BULJTL6.js} +2 -2
  34. package/dist/{chunk-7EGRP2VX.js.map → chunk-7BULJTL6.js.map} +1 -1
  35. package/dist/{chunk-FW23JYNQ.js → chunk-CEVNQ74M.js} +2 -2
  36. package/dist/{chunk-CGHORL6G.js → chunk-DDTS7F5O.js} +7 -5
  37. package/dist/chunk-DDTS7F5O.js.map +1 -0
  38. package/dist/{chunk-OCUDSN63.js → chunk-EL5VHUGK.js} +79 -47
  39. package/dist/chunk-EL5VHUGK.js.map +1 -0
  40. package/dist/{chunk-4GYMCUDZ.js → chunk-EP4WVQLX.js} +5 -5
  41. package/dist/{chunk-SOOKUYVM.js → chunk-F7EKHR32.js} +13 -9
  42. package/dist/chunk-F7EKHR32.js.map +1 -0
  43. package/dist/{chunk-JKTC747G.js → chunk-FQSQONOU.js} +4 -4
  44. package/dist/{chunk-JGFRAFDL.js → chunk-FVINAAKA.js} +3 -3
  45. package/dist/{chunk-RAGGHLCV.js → chunk-GUNIRPEJ.js} +8 -6
  46. package/dist/{chunk-RAGGHLCV.js.map → chunk-GUNIRPEJ.js.map} +1 -1
  47. package/dist/{chunk-BU3SEFA5.js → chunk-IOJDYUA7.js} +2 -2
  48. package/dist/{chunk-Y52CS6YA.js → chunk-JA67ZQG2.js} +2 -2
  49. package/dist/{chunk-Y52CS6YA.js.map → chunk-JA67ZQG2.js.map} +1 -1
  50. package/dist/{chunk-DM4OMPWK.js → chunk-KNU73RZW.js} +2 -2
  51. package/dist/{chunk-GWRNLJNW.js → chunk-KRFGO5QH.js} +19 -15
  52. package/dist/{chunk-GWRNLJNW.js.map → chunk-KRFGO5QH.js.map} +1 -1
  53. package/dist/{chunk-Z4YXAUDN.js → chunk-KUFXLAEY.js} +11 -7
  54. package/dist/{chunk-Z4YXAUDN.js.map → chunk-KUFXLAEY.js.map} +1 -1
  55. package/dist/{chunk-Z6EGP5D7.js → chunk-LDCSZ72P.js} +2 -2
  56. package/dist/{chunk-5IMMNARC.js → chunk-MS3WPRJR.js} +37 -25
  57. package/dist/chunk-MS3WPRJR.js.map +1 -0
  58. package/dist/{chunk-CXANAIZU.js → chunk-N65E26UL.js} +3 -3
  59. package/dist/{chunk-O3MT7DYI.js → chunk-N6MNJNHB.js} +2 -2
  60. package/dist/{chunk-Q3EYOCZB.js → chunk-NPRP3MCV.js} +111 -2
  61. package/dist/chunk-NPRP3MCV.js.map +1 -0
  62. package/dist/{chunk-A7KV5UK4.js → chunk-OXD5LFQP.js} +2 -2
  63. package/dist/{chunk-ZT4WMQW4.js → chunk-PTWADEH3.js} +9 -7
  64. package/dist/chunk-PTWADEH3.js.map +1 -0
  65. package/dist/{chunk-IHTWQEDR.js → chunk-QFE5BQH7.js} +2 -2
  66. package/dist/{chunk-IHTWQEDR.js.map → chunk-QFE5BQH7.js.map} +1 -1
  67. package/dist/{chunk-22SG74BD.js → chunk-R6ZCSXKX.js} +3 -3
  68. package/dist/{chunk-PZWISPIQ.js → chunk-S7HN5FHL.js} +17 -11
  69. package/dist/chunk-S7HN5FHL.js.map +1 -0
  70. package/dist/{chunk-RJOG4IJU.js → chunk-T7SP3EYR.js} +18 -12
  71. package/dist/chunk-T7SP3EYR.js.map +1 -0
  72. package/dist/{chunk-4S53H2KR.js → chunk-VAZXUK6G.js} +2 -2
  73. package/dist/{chunk-IJRR6YAI.js → chunk-VLDRAMP7.js} +18 -12
  74. package/dist/chunk-VLDRAMP7.js.map +1 -0
  75. package/dist/{chunk-TNX5ZGDJ.js → chunk-VNXAF2KE.js} +4 -4
  76. package/dist/{chunk-EHRRQ4IC.js → chunk-VP3TIUDF.js} +2 -2
  77. package/dist/{chunk-6XZYT4SW.js → chunk-WGDEBIP4.js} +5 -5
  78. package/dist/{chunk-E5OZPDIW.js → chunk-X7BA5PWG.js} +7 -5
  79. package/dist/chunk-X7BA5PWG.js.map +1 -0
  80. package/dist/compat/index.cjs +1 -1
  81. package/dist/compat/index.cjs.map +1 -1
  82. package/dist/compat/index.js +2 -2
  83. package/dist/compat/nestjs/index.cjs +1 -1
  84. package/dist/compat/nestjs/index.cjs.map +1 -1
  85. package/dist/compat/nestjs/index.js +2 -2
  86. package/dist/index.cjs +1657 -982
  87. package/dist/index.cjs.map +1 -1
  88. package/dist/index.d.cts +2 -2
  89. package/dist/index.d.ts +2 -2
  90. package/dist/index.js +58 -36
  91. package/dist/index.js.map +1 -1
  92. package/dist/presets/ai/index.cjs +42 -26
  93. package/dist/presets/ai/index.cjs.map +1 -1
  94. package/dist/presets/ai/index.js +11 -11
  95. package/dist/presets/harness/index.cjs +53 -33
  96. package/dist/presets/harness/index.cjs.map +1 -1
  97. package/dist/presets/harness/index.js +22 -22
  98. package/dist/presets/index.cjs +76 -48
  99. package/dist/presets/index.cjs.map +1 -1
  100. package/dist/presets/index.js +28 -28
  101. package/dist/presets/inspect/index.cjs.map +1 -1
  102. package/dist/presets/inspect/index.js +4 -4
  103. package/dist/presets/resilience/index.cjs +35 -23
  104. package/dist/presets/resilience/index.cjs.map +1 -1
  105. package/dist/presets/resilience/index.js +5 -5
  106. package/dist/solutions/index.cjs +71 -45
  107. package/dist/solutions/index.cjs.map +1 -1
  108. package/dist/solutions/index.js +24 -24
  109. package/dist/{timeout-U5O4ESK3.js → timeout-BEABACRP.js} +2 -2
  110. package/dist/utils/ai/browser.cjs.map +1 -1
  111. package/dist/utils/ai/browser.js +9 -9
  112. package/dist/utils/ai/index.cjs +41 -25
  113. package/dist/utils/ai/index.cjs.map +1 -1
  114. package/dist/utils/ai/index.js +18 -18
  115. package/dist/utils/ai/node.js +3 -3
  116. package/dist/utils/domain-templates/index.cjs +1 -1
  117. package/dist/utils/domain-templates/index.cjs.map +1 -1
  118. package/dist/utils/domain-templates/index.js +2 -2
  119. package/dist/utils/graphspec/index.cjs +1 -1
  120. package/dist/utils/graphspec/index.cjs.map +1 -1
  121. package/dist/utils/graphspec/index.js +2 -2
  122. package/dist/utils/harness/index.cjs +16 -10
  123. package/dist/utils/harness/index.cjs.map +1 -1
  124. package/dist/utils/harness/index.js +1 -1
  125. package/dist/utils/index.cjs +1069 -452
  126. package/dist/utils/index.cjs.map +1 -1
  127. package/dist/utils/index.d.cts +2 -2
  128. package/dist/utils/index.d.ts +2 -2
  129. package/dist/utils/index.js +45 -23
  130. package/dist/utils/inspect/index.cjs.map +1 -1
  131. package/dist/utils/inspect/index.js +2 -2
  132. package/dist/utils/memory/index.cjs +513 -37
  133. package/dist/utils/memory/index.cjs.map +1 -1
  134. package/dist/utils/memory/index.d.cts +641 -3
  135. package/dist/utils/memory/index.d.ts +641 -3
  136. package/dist/utils/memory/index.js +19 -1
  137. package/dist/utils/messaging/index.cjs +109 -0
  138. package/dist/utils/messaging/index.cjs.map +1 -1
  139. package/dist/utils/messaging/index.d.cts +115 -2
  140. package/dist/utils/messaging/index.d.ts +115 -2
  141. package/dist/utils/messaging/index.js +5 -1
  142. package/dist/utils/orchestration/index.cjs +5 -3
  143. package/dist/utils/orchestration/index.cjs.map +1 -1
  144. package/dist/utils/orchestration/index.js +2 -2
  145. package/dist/utils/process/index.js +2 -2
  146. package/dist/utils/reduction/index.cjs +1 -1
  147. package/dist/utils/reduction/index.cjs.map +1 -1
  148. package/dist/utils/reduction/index.js +1 -1
  149. package/dist/utils/resilience/index.cjs +35 -23
  150. package/dist/utils/resilience/index.cjs.map +1 -1
  151. package/dist/utils/resilience/index.js +4 -4
  152. package/dist/utils/surface/index.cjs +1 -1
  153. package/dist/utils/surface/index.cjs.map +1 -1
  154. package/dist/utils/surface/index.js +3 -3
  155. package/package.json +1 -1
  156. package/dist/chunk-5IMMNARC.js.map +0 -1
  157. package/dist/chunk-CGHORL6G.js.map +0 -1
  158. package/dist/chunk-DKNHAICT.js.map +0 -1
  159. package/dist/chunk-E5OZPDIW.js.map +0 -1
  160. package/dist/chunk-IJRR6YAI.js.map +0 -1
  161. package/dist/chunk-OCUDSN63.js.map +0 -1
  162. package/dist/chunk-PZWISPIQ.js.map +0 -1
  163. package/dist/chunk-Q3EYOCZB.js.map +0 -1
  164. package/dist/chunk-RJOG4IJU.js.map +0 -1
  165. package/dist/chunk-SOOKUYVM.js.map +0 -1
  166. package/dist/chunk-YJ4U2D2C.js.map +0 -1
  167. package/dist/chunk-ZT4WMQW4.js.map +0 -1
  168. package/dist/chunk-ZVXXDWIB.js.map +0 -1
  169. /package/dist/{chunk-VLAGJZSL.js.map → chunk-3O3NKZJW.js.map} +0 -0
  170. /package/dist/{chunk-2OB3CEJS.js.map → chunk-6MRSX3YK.js.map} +0 -0
  171. /package/dist/{chunk-EVYY4X5A.js.map → chunk-6ZLCPUXS.js.map} +0 -0
  172. /package/dist/{chunk-FW23JYNQ.js.map → chunk-CEVNQ74M.js.map} +0 -0
  173. /package/dist/{chunk-4GYMCUDZ.js.map → chunk-EP4WVQLX.js.map} +0 -0
  174. /package/dist/{chunk-JKTC747G.js.map → chunk-FQSQONOU.js.map} +0 -0
  175. /package/dist/{chunk-JGFRAFDL.js.map → chunk-FVINAAKA.js.map} +0 -0
  176. /package/dist/{chunk-BU3SEFA5.js.map → chunk-IOJDYUA7.js.map} +0 -0
  177. /package/dist/{chunk-DM4OMPWK.js.map → chunk-KNU73RZW.js.map} +0 -0
  178. /package/dist/{chunk-Z6EGP5D7.js.map → chunk-LDCSZ72P.js.map} +0 -0
  179. /package/dist/{chunk-CXANAIZU.js.map → chunk-N65E26UL.js.map} +0 -0
  180. /package/dist/{chunk-O3MT7DYI.js.map → chunk-N6MNJNHB.js.map} +0 -0
  181. /package/dist/{chunk-A7KV5UK4.js.map → chunk-OXD5LFQP.js.map} +0 -0
  182. /package/dist/{chunk-22SG74BD.js.map → chunk-R6ZCSXKX.js.map} +0 -0
  183. /package/dist/{chunk-4S53H2KR.js.map → chunk-VAZXUK6G.js.map} +0 -0
  184. /package/dist/{chunk-TNX5ZGDJ.js.map → chunk-VNXAF2KE.js.map} +0 -0
  185. /package/dist/{chunk-EHRRQ4IC.js.map → chunk-VP3TIUDF.js.map} +0 -0
  186. /package/dist/{chunk-6XZYT4SW.js.map → chunk-WGDEBIP4.js.map} +0 -0
  187. /package/dist/{timeout-U5O4ESK3.js.map → timeout-BEABACRP.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/base/resilience/_internal.ts","../../src/base/resilience/backoff.ts","../../src/base/resilience/timeout.ts","../../src/solutions/index.ts","../../src/presets/ai/agent-loop.ts","../../src/base/sources/settled.ts","../../src/utils/ai/_internal.ts","../../src/base/meta/domain-meta.ts","../../src/utils/ai/agents/chat-stream.ts","../../src/utils/ai/agents/tool-execution.ts","../../src/base/resilience/retry.ts","../../src/utils/ai/agents/tool-registry.ts","../../src/presets/ai/agent-memory.ts","../../src/base/composition/distill.ts","../../src/base/sources/async.ts","../../src/utils/ai/memory/memory-composers.ts","../../src/base/utils/decay.ts","../../src/utils/memory/index.ts","../../src/base/mutation/index.ts","../../src/utils/ai/prompts/prompt-call.ts","../../src/utils/ai/prompts/prompt-node.ts","../../src/presets/harness/harness-loop.ts","../../src/base/resilience/status.ts","../../src/utils/resilience/index.ts","../../src/utils/resilience/breaker.ts","../../src/utils/resilience/budget-gate.ts","../../src/utils/resilience/fallback.ts","../../src/utils/resilience/rate-limiter.ts","../../src/utils/messaging/message.ts","../../src/utils/messaging/index.ts","../../src/utils/orchestration/pipeline-graph.ts","../../src/utils/harness/_internal.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/job-queue/index.ts","../../src/presets/harness/refine-loop.ts","../../src/presets/harness/spawnable.ts","../../src/presets/ai/agents.ts","../../src/presets/ai/agent.ts","../../src/presets/inspect/guarded-execution.ts","../../src/utils/inspect/audit.ts","../../src/presets/resilience/resilient-pipeline.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 * Solutions — curated headline-product barrel.\n *\n * The front door for \"I want a recipe.\" Re-exports headline factories from\n * presets so consumers can import from one place without knowing which preset\n * sub-domain each factory lives in.\n *\n * Verticals (solutions/<vertical>/) are deferred per D202 — added when\n * consumer pressure justifies a bundled vertical starter kit.\n *\n * @module\n */\n\nexport { agentLoop } from \"../presets/ai/agent-loop.js\";\nexport { agentMemory } from \"../presets/ai/agent-memory.js\";\nexport { harnessLoop } from \"../presets/harness/harness-loop.js\";\nexport { refineLoop } from \"../presets/harness/refine-loop.js\";\nexport { spawnable } from \"../presets/harness/spawnable.js\";\nexport { guardedExecution } from \"../presets/inspect/guarded-execution.js\";\nexport { resilientPipeline } from \"../presets/resilience/resilient-pipeline.js\";\n","/**\n * Reactive agent loop — autonomous multi-turn LLM agent with tool execution.\n */\n\nexport type AgentLoopStatus = \"idle\" | \"thinking\" | \"acting\" | \"done\" | \"error\";\n\nimport {\n\tbatch,\n\tDATA,\n\tERROR,\n\tINVALIDATE,\n\ttype Node,\n\tnode,\n\tnode as nodeFactory,\n\tplaceholderArgs,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport { fromAny, keepalive, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { awaitSettled } from \"../../base/sources/settled.js\";\nimport { aiMeta } from \"../../utils/ai/_internal.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMResponse,\n\tToolCall,\n\tToolDefinition,\n} from \"../../utils/ai/adapters/core/types.js\";\nimport { type ChatStreamGraph, chatStream } from \"../../utils/ai/agents/chat-stream.js\";\nimport { type ToolResult, toolExecution } from \"../../utils/ai/agents/tool-execution.js\";\nimport { type ToolRegistryGraph, toolRegistry } from \"../../utils/ai/agents/tool-registry.js\";\n\nexport type { ToolResult } from \"../../utils/ai/agents/tool-execution.js\";\n\n// ---------------------------------------------------------------------------\n// agentLoop\n// ---------------------------------------------------------------------------\n\nexport type AgentLoopOptions = {\n\tgraph?: GraphOptions;\n\tadapter: LLMAdapter;\n\ttools?: readonly ToolDefinition[];\n\tsystemPrompt?: string;\n\tmaxTurns?: number;\n\tstopWhen?: (response: LLMResponse) => boolean;\n\tonToolCall?: (call: ToolCall) => void;\n\tmaxMessages?: number;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/**\n\t * Reactive tool-call splice (COMPOSITION-GUIDE §31 \"interception is security\").\n\t * When set, the raw `toolCalls` node is piped through this transform before\n\t * reaching the executor. The transform is a pure reactive composition —\n\t * `(calls: Node<readonly ToolCall[]>) => Node<readonly ToolCall[]>` — so the\n\t * gate is visible in `describe()` / `explain()` as a real edge (no hidden\n\t * imperative wraps; §24).\n\t *\n\t * Typical uses:\n\t * - **Filter / block** — `derived([calls, policy], ([raw, p]) => raw.filter(p))`\n\t * - **Throttle / debounce** — `throttle(calls, windowMs)`\n\t * - **Human-in-the-loop approval** — pipe through a `gate` controller so\n\t * calls wait for human approval before reaching the executor.\n\t *\n\t * The public `agent.toolCalls` node surfaces the POST-intercept stream, so\n\t * audit / telemetry consumers see what the executor actually runs. The raw\n\t * pre-intercept stream is not exposed — tests that need it should run\n\t * without `interceptToolCalls` set (the identity case).\n\t */\n\tinterceptToolCalls?: (calls: Node<readonly ToolCall[]>) => Node<readonly ToolCall[]>;\n};\n\n/**\n * Reactive agent loop.\n *\n * The loop is a reactive state machine wired entirely from graph primitives:\n * `chat.messages` + `tools.schemas` + gating state feed a `promptInput`\n * derived; `switchMap` turns non-null inputs into an LLM invocation via\n * `fromAny(adapter.invoke(...))`. The LLM response drives chat writes and\n * status transitions via effects. Tool calls flow through a reactive\n * executor (`retrySource` + `rescue`) that retries once on error and\n * surfaces terminal errors as JSON-shaped `ToolResult` payloads for the\n * LLM to react to.\n *\n * **No imperative control flow inside the reactive layer** (spec §5.8-5.12):\n * no `while` loops, no manual `await adapter.invoke`, no polling.\n * `agent.run()` is a thin `awaitSettled` bridge so callers can still `await`\n * the loop if they want a Promise.\n *\n * Public surface:\n * - `chat` / `tools` — subgraphs (imperative `append` at boundary, reactive `executeReactive` for tool invocation)\n * - `status` / `turn` / `aborted` — state nodes with explicit initials\n * - `lastResponse` / `toolCalls` / `toolResults` — reactive outputs (SENTINEL until first emission; callers use `awaitSettled` / `subscribe`)\n * - `run(userMessage?, signal?)` — optional user append + Promise bridge\n * - `abort()` — imperative abort shim; flips `aborted` state\n *\n * **Lifecycle: single-mount.** `AgentLoopGraph` instances expect to be\n * constructed once and used until `destroy()`. The internal closure mirrors\n * (`latestTurn` / `latestAborted` / `latestStatus`) are wired by\n * subscribe-and-capture at construction time; their `addDisposer`-registered\n * subscriptions are torn down on subgraph unmount or `destroy()`. After\n * teardown the mirrors freeze at their last value, so re-using a destroyed\n * instance — calling `run()` again, or remounting under a new parent —\n * would silently feed stale mirror data into reactive fn bodies. If you\n * need to \"reset\" an agent, build a fresh `AgentLoopGraph` instance instead\n * of recycling.\n */\nexport class AgentLoopGraph extends Graph {\n\treadonly chat: ChatStreamGraph;\n\treadonly tools: ToolRegistryGraph;\n\n\t/** Current agent status. `initial: \"idle\"` — always has a real value. */\n\treadonly status: Node<AgentLoopStatus>;\n\t/** Turn count (completed LLM invocations this run). `initial: 0`. */\n\treadonly turn: Node<number>;\n\t/** Aborted flag; flipped by `abort()` or external `AbortSignal`. `initial: false`. */\n\treadonly aborted: Node<boolean>;\n\n\t/**\n\t * Most recent LLM response. State-backed mirror driven by the response\n\t * effect. **Stays SENTINEL** (`cache === undefined`, no DATA emitted)\n\t * until the first real response — bridge subscribers see no spurious\n\t * push-on-subscribe DATA. After a real response, holds the latest\n\t * `LLMResponse`. Reset between `run()` calls via `[[INVALIDATE]]` (clears\n\t * cache back to SENTINEL) so a second run with a pre-aborted signal\n\t * cannot leak the prior run's response. Bridge with\n\t * `awaitSettled(lastResponse)` for the first DATA as a Promise; consumers\n\t * inside reactive fns gate on `ctx.prevData[i] === undefined`.\n\t */\n\treadonly lastResponse: Node<LLMResponse>;\n\t/** Tool-call batch emitted by the most recent LLM response. SENTINEL. */\n\treadonly toolCalls: Node<readonly ToolCall[]>;\n\t/** Tool-result batch (one entry per call) after reactive execution. SENTINEL. */\n\treadonly toolResults: Node<readonly ToolResult[]>;\n\n\tprivate readonly _terminalResult: Node<LLMResponse>;\n\tprivate readonly _disposeRunWiring: () => void;\n\t/** Guards against overlapping `run()` calls. */\n\tprivate _running = false;\n\t/**\n\t * Abort controller for the currently-running `adapter.invoke`. Minted per\n\t * switchMap project; aborted when the reactive `aborted` node flips true\n\t * OR when the caller's external `AbortSignal` fires. Threaded into\n\t * `adapter.invoke({ signal })` AND `fromAny(promise, { signal })`, so the\n\t * reactive layer sees ERROR when the wire call is cancelled.\n\t */\n\tprivate _currentAbortController: AbortController | null = null;\n\n\tconstructor(name: string, opts: AgentLoopOptions) {\n\t\tsuper(name, opts.graph);\n\n\t\t// Mount chat subgraph\n\t\tthis.chat = chatStream(`${name}-chat`, { maxMessages: opts.maxMessages });\n\t\tthis.mount(\"chat\", this.chat);\n\n\t\t// Mount tool registry subgraph\n\t\tthis.tools = toolRegistry(`${name}-tools`);\n\t\tthis.mount(\"tools\", this.tools);\n\n\t\tif (opts.tools) {\n\t\t\tfor (const tool of opts.tools) {\n\t\t\t\tthis.tools.register(tool);\n\t\t\t}\n\t\t}\n\n\t\t// --- State nodes (always have a real value; explicit initials) ---\n\t\tthis.status = node<AgentLoopStatus>([], {\n\t\t\t...{\n\t\t\t\tname: \"status\",\n\t\t\t\tdescribeKind: \"state\",\n\t\t\t\tmeta: aiMeta(\"agent_status\"),\n\t\t\t},\n\t\t\tinitial: \"idle\",\n\t\t});\n\t\tthis.add(this.status, { name: \"status\" });\n\n\t\tthis.turn = node<number>([], {\n\t\t\t...{\n\t\t\t\tname: \"turn\",\n\t\t\t\tdescribeKind: \"state\",\n\t\t\t\tmeta: aiMeta(\"agent_turn_count\"),\n\t\t\t},\n\t\t\tinitial: 0,\n\t\t});\n\t\tthis.add(this.turn, { name: \"turn\" });\n\n\t\tthis.aborted = node<boolean>([], {\n\t\t\t...{\n\t\t\t\tname: \"aborted\",\n\t\t\t\tdescribeKind: \"state\",\n\t\t\t\tmeta: aiMeta(\"agent_aborted\"),\n\t\t\t},\n\t\t\tinitial: false,\n\t\t});\n\t\tthis.add(this.aborted, { name: \"aborted\" });\n\n\t\t// --- Reactive pipeline ---\n\t\t//\n\t\t// **Read pattern (Phase 12 D1 lock + F2 fix 2026-05-01).** State\n\t\t// scratchpad held on this `AgentLoopGraph` (turn / aborted / chat /\n\t\t// tools) is read inside reactive fn bodies via either:\n\t\t// (a) `data[i]` / `ctx.prevData[i]` for declared deps, OR\n\t\t// (b) sole-owner `.cache` reads on subgraph-mounted state Nodes\n\t\t// (chat / tools mounted as subgraphs of this Graph; the agent\n\t\t// is the sole owner; promptInput / effResponse / effResults\n\t\t// live in the same enclosing constructor scope — sanctioned\n\t\t// form per Phase 12 D1 read-pattern lock).\n\t\t//\n\t\t// Closure mirrors (`latestTurn` / `latestAborted` / `latestStatus`)\n\t\t// are kept ONLY for fields where (b) doesn't simplify the call site\n\t\t// — turn / aborted / status are state Nodes registered on `this`\n\t\t// directly (not subgraphs), and the closure form keeps\n\t\t// effResponse's batch logic readable. They are CORRECT but are NOT\n\t\t// safe under nested drains (the subscribe handler may not have run\n\t\t// yet when a downstream fn reads the closure). For nested-drain-\n\t\t// reachable reads (promptInput, called via `agentLoop.run` from\n\t\t// inside another graph's reactive subscribe handler), prefer (a) or\n\t\t// (b) over the closure mirror. F2 root cause: chat.messages.cache\n\t\t// is updated DURING the DATA-settle phase (before subscribers\n\t\t// run), so `.cache` reads are always at least as fresh as closure\n\t\t// mirrors. See `optimizations.md` \"Phase 13 design-session inputs\n\t\t// from §13.M lock-test\" F2.\n\t\t//\n\t\t// **Pattern note on `latestTurn` staleness under in-batch reads.**\n\t\t// Effect 1 emits `turnNode.emit(next)` inside its batch; Effect 2\n\t\t// reads `latestTurn` on the following wave (after toolResults\n\t\t// settle). Because batch drain is FIFO, `turnSub`'s handler runs\n\t\t// before Effect 2's next wave fires, so `latestTurn` is up-to-date\n\t\t// by the time Effect 2 reads it. This invariant is stable as long\n\t\t// as `turnNode.emit` remains inside Effect 1's batch — a future\n\t\t// refactor that un-batches the emit would regress silently.\n\t\tlet latestTurn = 0;\n\t\tconst turnSub = this.turn.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) if (m[0] === DATA) latestTurn = m[1] as number;\n\t\t});\n\t\tlet latestAborted = false;\n\t\tconst abortedSub = this.aborted.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) if (m[0] === DATA) latestAborted = m[1] as boolean;\n\t\t});\n\n\t\tconst adapter = opts.adapter;\n\t\tconst systemPrompt = opts.systemPrompt;\n\t\tconst model = opts.model;\n\t\tconst temperature = opts.temperature;\n\t\tconst maxTokens = opts.maxTokens;\n\t\tconst maxTurns = opts.maxTurns ?? 10;\n\t\tconst stopWhen = opts.stopWhen;\n\n\t\t// Capture `this` for closures that don't bind `this`.\n\t\tconst chat = this.chat;\n\t\tconst tools = this.tools;\n\t\tconst statusNode = this.status;\n\t\tconst turnNode = this.turn;\n\t\tconst abortedNode = this.aborted;\n\n\t\t// promptInput: STATUS is the only reactive trigger — chat.messages,\n\t\t// tools.schemas, turn, aborted are sampled via closure-held mirrors\n\t\t// (all populated by subscribe-and-capture above). This prevents the\n\t\t// classic feedback cycle (COMPOSITION-GUIDE §7): if chat.messageCount\n\t\t// were a reactive dep here, effect 1's `chat.append` would trigger a\n\t\t// promptInput wave, which under effect-1's batch would see status\n\t\t// STILL \"thinking\" (pre-drain) and fire a spurious LLM invocation.\n\t\t// By gating only on status, chat writes don't re-trigger — only\n\t\t// explicit status transitions do.\n\t\tconst promptInput: Node<InvokeInput> = nodeFactory<InvokeInput>(\n\t\t\t[statusNode],\n\t\t\t(data, actions, ctx) => {\n\t\t\t\tconst stat = readLatest<AgentLoopStatus>(data, ctx.prevData, 0, \"idle\");\n\t\t\t\tif (stat !== \"thinking\" || latestAborted || latestTurn >= maxTurns) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// F2 fix (2026-05-01): under nested drains, the closure mirrors\n\t\t\t\t// `latestMessages` / `latestSchemas` lag the actual node state —\n\t\t\t\t// messagesSub / schemasSub subscribers may not have run yet when\n\t\t\t\t// promptInput fires (the drain processes status's downstream\n\t\t\t\t// before chat.messages's subscribers fire, even though\n\t\t\t\t// chat.messages.cache is already settled). Read `.cache`\n\t\t\t\t// directly per Phase 12 D1 read-pattern lock: chat / tools are\n\t\t\t\t// mounted as subgraphs of this AgentLoopGraph (sole owner) and\n\t\t\t\t// promptInput is a reactive reader in the same enclosing\n\t\t\t\t// constructor scope — sanctioned `.cache` form. See\n\t\t\t\t// `optimizations.md` \"Phase 13 design-session inputs from §13.M\n\t\t\t\t// lock-test\" F2.\n\t\t\t\tconst messages = (this.chat.messages.cache as readonly ChatMessage[] | undefined) ?? [];\n\t\t\t\tif (messages.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\tconst schemas = (this.tools.schemas.cache as readonly ToolDefinition[] | undefined) ?? [];\n\t\t\t\tactions.emit({ messages, tools: schemas });\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"promptInput\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"agent_prompt_input\", {\n\t\t\t\t\t// State this fn body samples beyond its declared `statusNode`\n\t\t\t\t\t// dep. `aborted` / `turn` come from §28 closure mirrors\n\t\t\t\t\t// (`latestAborted` / `latestTurn`); `chat.messages` /\n\t\t\t\t\t// `tools.schemas` come from sole-owner `.cache` reads\n\t\t\t\t\t// (Phase 12 D1 lock + F2 fix; see comment block above).\n\t\t\t\t\t// Listed here so inspection tooling can surface fold-in\n\t\t\t\t\t// state without grepping source.\n\t\t\t\t\tclosureReads: [\"aborted\", \"turn\", \"chat.messages\", \"tools.schemas\"],\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tconst llmResponse: Node<LLMResponse> = switchMap(\n\t\t\tpromptInput,\n\t\t\t(input) => {\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tthis._currentAbortController = controller;\n\t\t\t\tif (latestAborted) {\n\t\t\t\t\tcontroller.abort(new Error(\"agentLoop: aborted\"));\n\t\t\t\t}\n\t\t\t\t// Wave A Unit B-CC fix: drop the `Promise.resolve(adapter.invoke(...))`\n\t\t\t\t// wrapper. `adapter.invoke` returns a `NodeInput<LLMResponse>`\n\t\t\t\t// (Promise | Node | raw). `fromAny` already handles all three\n\t\t\t\t// shapes; the manual `Promise.resolve` wrapper would force a\n\t\t\t\t// Node-returning adapter into an extra microtask hop and lose\n\t\t\t\t// reactivity (see Unit 11 + Unit 1 for the parallel cleanup).\n\t\t\t\treturn fromAny(\n\t\t\t\t\tadapter.invoke(input.messages, {\n\t\t\t\t\t\ttools: input.tools.length > 0 ? input.tools : undefined,\n\t\t\t\t\t\tsystemPrompt,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttemperature,\n\t\t\t\t\t\tmaxTokens,\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t}),\n\t\t\t\t\t{ signal: controller.signal },\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ equals: () => false },\n\t\t);\n\n\t\t// State mirror for `lastResponse` — exists for **cross-run reset\n\t\t// semantics**, NOT the §32 mid-wave hazard.\n\t\t//\n\t\t// Why: `llmResponse` is a switchMap output; its cache persists across\n\t\t// `run()` calls (switchMap's output node has no built-in reset path —\n\t\t// the cache stays at the last DATA the inner emitted). A second\n\t\t// `run()` with a pre-aborted signal would otherwise have\n\t\t// `_terminalResult` evaluate `stat=done` (driven by `effAbort`) +\n\t\t// `resp=<prior run's response>` (cached on `llmResponse`) and resolve\n\t\t// the Promise with stale data instead of rejecting with AbortError.\n\t\t// The mirror is **reset via `[[INVALIDATE]]`** in `run()`'s reset\n\t\t// batch — INVALIDATE clears `_cached` back to `undefined` (SENTINEL)\n\t\t// AND clears the `prevData` slot on every dependent (`_terminalResult`,\n\t\t// `toolCallsRaw`), so the abort path correctly emits\n\t\t// `[[ERROR, AbortError]]` from terminalResult's `stat=\"done\" &&\n\t\t// prevData[lastResponse] === undefined → ERROR` guard.\n\t\t//\n\t\t// **No `T | null` placeholder.** Per `feedback_use_prevdata_for_sentinel`\n\t\t// + COMPOSITION-GUIDE §1a, the SENTINEL state IS the \"never sent\n\t\t// real DATA yet\" signal. An eager `initial: null` would push `[null]`\n\t\t// to every fresh subscriber — a footgun for bridge subscribers that\n\t\t// would otherwise need `if (resp == null) continue` guards. Stay\n\t\t// SENTINEL; consumers detect \"no response yet\" via\n\t\t// `ctx.prevData[i] === undefined` (or `cache === undefined` outside\n\t\t// reactive fns). F9 lock-test (`multi-agent-example.test.ts` test 5)\n\t\t// pins this invariant.\n\t\t//\n\t\t// What this does NOT solve: the §32 mid-wave \"stale peer-read\"\n\t\t// hazard. Investigation (2026-04-25) confirmed `_dirtyDepCount`\n\t\t// gating in `_maybeRunFnOnSettlement` already prevents that — when\n\t\t// `effResponse`'s nested batch fires `status=\"done\"` mid-iteration,\n\t\t// terminal's status dep settles but its `llmResponse` (or mirror)\n\t\t// dep is still DIRTY from Phase 1, so the fn does not run until\n\t\t// Phase 2 visits both deps. Verified by fast-check invariant `#12b\n\t\t// nested-drain-peer-consistency-compound` and by the multi-turn\n\t\t// `executes tool calls and loops` test passing under either dep\n\t\t// shape (`[statusNode, llmResponse]` or `[statusNode, lastResponseState]`).\n\t\t//\n\t\t// Verified by: QA C3 regression tests (`run() with pre-aborted\n\t\t// signal rejects AbortError` and `second run() with pre-aborted\n\t\t// signal rejects AbortError (no stale response leak)`) — both\n\t\t// fail when `_terminalResult` is rewired to depend on `llmResponse`\n\t\t// directly. See COMPOSITION-GUIDE §32 (cross-wave reset reframe).\n\t\tconst lastResponseState = node<LLMResponse>([], {\n\t\t\tname: \"lastResponse\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_last_response\"),\n\t\t});\n\t\tthis.lastResponse = lastResponseState;\n\n\t\t// toolCalls: raw node that emits DATA only when status === \"acting\" and\n\t\t// the current response has tool calls. Otherwise emits RESOLVED. Using\n\t\t// DATA([]) for the idle case would cause switchMap(toolCalls) to\n\t\t// re-dispatch its inner (creating a fresh node([], { initial: [] }) source whose\n\t\t// emissions re-trigger effects downstream). RESOLVED keeps the inner\n\t\t// alive and lets upstream waves pass through without re-dispatch.\n\t\t// Inner raw tool-call stream — name `toolCallsRaw` so the post-intercept\n\t\t// public surface (`this.toolCalls`) is unambiguous in `describe()`.\n\t\t// QA-fix: previously the inner was named `\"toolCalls\"`, which collided\n\t\t// with `this.toolCalls` if the user-supplied interceptor returned a\n\t\t// wrapper that internally retained a reference to this raw node —\n\t\t// `describe()` would render two distinct nodes both labeled `\"toolCalls\"`.\n\t\tconst toolCallsRaw = nodeFactory<readonly ToolCall[]>(\n\t\t\t[lastResponseState, statusNode],\n\t\t\t(data, actions, ctx) => {\n\t\t\t\t// SENTINEL guard: `lastResponseState` stays `undefined` (cache\n\t\t\t\t// + prevData) until the first real response. `readLatest`'s\n\t\t\t\t// fallback returns `undefined` here so the no-DATA branch is\n\t\t\t\t// indistinguishable from the protocol SENTINEL — both gate to\n\t\t\t\t// RESOLVED. Per `feedback_use_prevdata_for_sentinel`.\n\t\t\t\tconst resp = readLatest<LLMResponse | undefined>(data, ctx.prevData, 0, undefined);\n\t\t\t\tconst stat = readLatest<AgentLoopStatus>(data, ctx.prevData, 1, \"idle\");\n\t\t\t\tif (stat !== \"acting\") {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst calls = resp?.toolCalls;\n\t\t\t\tif (calls == null || calls.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(calls);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"toolCallsRaw\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"agent_tool_calls_raw\"),\n\t\t\t},\n\t\t);\n\t\t// Reactive splice (D9 / COMPOSITION-GUIDE §31). When `interceptToolCalls`\n\t\t// is set, the raw tool-call stream is transformed in the graph — the\n\t\t// executor sees the gated stream, and `agent.toolCalls` surfaces the\n\t\t// post-intercept view so audit / telemetry match reality.\n\t\tconst gatedToolCallsNode = opts.interceptToolCalls\n\t\t\t? opts.interceptToolCalls(toolCallsRaw)\n\t\t\t: toolCallsRaw;\n\t\tthis.toolCalls = gatedToolCallsNode;\n\n\t\t// Delegate per-call fan-out + retry + rescue to the `toolExecution`\n\t\t// primitive. `toolCallsRaw` already gates empty batches to RESOLVED,\n\t\t// so `toolExecution`'s \"non-empty batch only\" contract is satisfied\n\t\t// upstream. `retryCount: 1` matches the pre-extraction behaviour\n\t\t// (one retry after first failure = 2 attempts total).\n\t\tconst toolResultsNode: Node<readonly ToolResult[]> = toolExecution({\n\t\t\ttoolCalls: gatedToolCallsNode,\n\t\t\ttools,\n\t\t\tretryCount: 1,\n\t\t});\n\t\tthis.toolResults = toolResultsNode;\n\n\t\t// --- State-machine effects ---\n\t\t// Effect 1: LLM response landed → write lastResponse mirror + chat,\n\t\t// transition status, increment turn. Emission ORDER inside the batch\n\t\t// matters (drain is FIFO under any outer-batch depth):\n\t\t// 1. `lastResponseState.emit(response)` FIRST — so when the drain\n\t\t// fires the status=done wave later in the queue, `_terminalResult`'s\n\t\t// dep on `lastResponseState` has already been updated.\n\t\t// 2. `statusNode.emit(nextStatus)` — drives state machine.\n\t\t// 3. `turnNode.emit(next)` — counter.\n\t\t// 4. `chat.append(...)` LAST — chat.messageCount wave now sees the\n\t\t// new status (so `promptInput` gates correctly).\n\t\t// Without (1) first, `_terminalResult` reads stale `prevData` for\n\t\t// lastResponse when status transitions synchronously during drain.\n\t\t//\n\t\t// **Invariant independence from outer batch depth.** `downWithBatch`\n\t\t// preserves FIFO drain order regardless of nesting — whether the\n\t\t// outer batch is at depth 0 (common: Promise microtask) or depth >0\n\t\t// (user-composed `batch()` scope around `agent.run()`), the emissions\n\t\t// above drain in the order they were enqueued. The state-mirror\n\t\t// pattern holds in both cases.\n\t\t//\n\t\t// **Abort guard (C2 defense-in-depth).** If the `aborted` state has\n\t\t// flipped true between `adapter.invoke`'s Promise resolution and this\n\t\t// effect firing (micro-race), bail out so we don't append to chat or\n\t\t// execute tool calls for an abandoned run. The controller.abort() in\n\t\t// effAbort also fires the signal, which causes `fromAny` to emit\n\t\t// ERROR — but that ERROR propagation arrives in a separate wave, so\n\t\t// this guard covers the \"Promise already resolved before abort hit\n\t\t// the controller\" case.\n\t\tconst effResponse = node(\n\t\t\t[llmResponse],\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\tif (latestAborted) return;\n\t\t\t\tconst response = data[0] as LLMResponse;\n\t\t\t\tconst next = latestTurn + 1;\n\t\t\t\tconst hasToolCalls = response.toolCalls != null && response.toolCalls.length > 0;\n\t\t\t\tconst naturalStop =\n\t\t\t\t\tresponse.finishReason === \"end_turn\" &&\n\t\t\t\t\t(!response.toolCalls || response.toolCalls.length === 0);\n\t\t\t\tconst customStop = stopWhen?.(response) === true;\n\t\t\t\tconst capReached = next >= maxTurns;\n\t\t\t\tconst nextStatus: AgentLoopStatus =\n\t\t\t\t\tcustomStop || naturalStop || !hasToolCalls || capReached ? \"done\" : \"acting\";\n\t\t\t\tbatch(() => {\n\t\t\t\t\tlastResponseState.emit(response);\n\t\t\t\t\tstatusNode.emit(nextStatus);\n\t\t\t\t\tturnNode.emit(next);\n\t\t\t\t\tchat.append(\"assistant\", response.content, {\n\t\t\t\t\t\ttoolCalls: response.toolCalls,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\n\t\t// Effect 2: Tool results landed → append to chat, transition to\n\t\t// thinking (or done if turn cap reached). Same ordering discipline —\n\t\t// status emits before chat mutations. Abort guard mirrors effResponse.\n\t\tconst effResults = node(\n\t\t\t[toolResultsNode],\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\tif (latestAborted) return;\n\t\t\t\tconst arr = data[0] as readonly ToolResult[];\n\t\t\t\tif (arr.length === 0) return;\n\t\t\t\tconst nextStatus: AgentLoopStatus = latestTurn >= maxTurns ? \"done\" : \"thinking\";\n\t\t\t\tbatch(() => {\n\t\t\t\t\tstatusNode.emit(nextStatus);\n\t\t\t\t\tfor (const r of arr) chat.appendToolResult(r.id, r.content);\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\n\t\t// Effect 3: external abort → cancel in-flight wire call + terminal status.\n\t\t// Aborting the controller causes the switchMap inner's `fromAny` to\n\t\t// emit ERROR (signal-bound), which tears down the subscription. The\n\t\t// `status=\"done\"` emit drives `_terminalResult` to resolve `run()`'s\n\t\t// Promise (via AbortError when `resp == null`, see C3).\n\t\t//\n\t\t// Unit 4 Q5: status guard — if status is already \"done\" (the natural-\n\t\t// completion path raced the abort), skip the redundant emit so the\n\t\t// status-node event log isn't polluted with a trailing duplicate.\n\t\t// Closure-mirror `latestStatus` keeps the comparison synchronous and\n\t\t// P3-compliant (closure read, not `.cache` read — see §28). Seeded\n\t\t// from `statusNode.cache` to match the §28 factory-time-seed pattern\n\t\t// that `latestTurn` / `latestAborted` use — the literal `\"idle\"` would\n\t\t// silently drift if the constructor initial value ever changed.\n\t\tlet latestStatus: AgentLoopStatus = (statusNode.cache as AgentLoopStatus | undefined) ?? \"idle\";\n\t\tconst statusSub = statusNode.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) if (m[0] === DATA) latestStatus = m[1] as AgentLoopStatus;\n\t\t});\n\t\tconst effAbort = node(\n\t\t\t[abortedNode],\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\tif (data[0] === true) {\n\t\t\t\t\tthis._currentAbortController?.abort(new Error(\"agentLoop: aborted\"));\n\t\t\t\t\tif (latestStatus !== \"done\") statusNode.emit(\"done\");\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\n\t\t// Keepalive so the pipeline stays activated even without external\n\t\t// subscribers. Callers don't need to subscribe to `llmResponse` /\n\t\t// `toolResults` for the loop to run.\n\t\tconst kaResponse = keepalive(effResponse);\n\t\tconst kaResults = keepalive(effResults);\n\t\tconst kaAbort = keepalive(effAbort);\n\n\t\t// terminalResult emits the final `LLMResponse` on each \"done\"\n\t\t// transition. The old compound `{response, runVersion}` shape existed\n\t\t// to let a re-entrant caller's `awaitSettled` predicate filter out\n\t\t// the PREVIOUS run's cached DATA; that job now belongs to\n\t\t// `awaitSettled({skipCurrent: true})` (extra/sources.ts) which\n\t\t// ignores the initial push-on-subscribe DATA and resolves only on\n\t\t// fresh post-subscribe emissions. Retiring the stamp removes a\n\t\t// closure-held counter and a per-emission object allocation from\n\t\t// the hot path.\n\t\t//\n\t\t// C3 (abort-before-response) post-SENTINEL: when `stat === \"done\"` but\n\t\t// `lastResponseState` is SENTINEL (no DATA ever delivered for this\n\t\t// run — `prevData[1] === undefined`, equivalently `resp === undefined`\n\t\t// after `readLatest`'s fallback), emit `ERROR(AbortError)` so the\n\t\t// awaiting Promise rejects instead of hanging on a RESOLVED. The\n\t\t// SENTINEL state is restored at every `run()` boundary by\n\t\t// `lastResponse.down([[INVALIDATE]])` (clears `_cached` AND clears\n\t\t// each dependent's `prevData` slot for this dep), so a second run\n\t\t// after a successful first run still detects the abort cleanly —\n\t\t// no stale `prevData` leak.\n\t\tthis._terminalResult = nodeFactory<LLMResponse>(\n\t\t\t[statusNode, lastResponseState],\n\t\t\t(data, actions, ctx) => {\n\t\t\t\tconst stat = readLatest<AgentLoopStatus>(data, ctx.prevData, 0, \"idle\");\n\t\t\t\tconst resp = readLatest<LLMResponse | undefined>(data, ctx.prevData, 1, undefined);\n\t\t\t\tif (stat === \"done\") {\n\t\t\t\t\tif (resp !== undefined) {\n\t\t\t\t\t\tactions.emit(resp);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst err = new Error(\"agentLoop: aborted\") as Error & { name: string };\n\t\t\t\t\terr.name = \"AbortError\";\n\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (stat === \"error\") {\n\t\t\t\t\tactions.down([[ERROR, new Error(\"agentLoop: errored\")]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"terminalResult\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"agent_terminal_result\"),\n\t\t\t\t// `lastResponseState` is SENTINEL until the first real response\n\t\t\t\t// arrives — without `partial: true`, the spec §2.7 first-run\n\t\t\t\t// gate would block this fn from ever firing on the abort-\n\t\t\t\t// before-response path (`status → \"done\"` while `lastResponse`\n\t\t\t\t// has never delivered DATA). The fn explicitly handles the\n\t\t\t\t// SENTINEL case (`resp === undefined → ERROR(AbortError)`),\n\t\t\t\t// so partial-fire is safe by design.\n\t\t\t\tpartial: true,\n\t\t\t},\n\t\t);\n\t\t// Wave B-CC Q2/C: register intermediate pipeline nodes so consumers\n\t\t// can `observe(path)` them by name (e.g. `agent.observe(\"promptInput\")`).\n\t\t// They were already visible in `describe()` via dep traversal, but not\n\t\t// path-addressable. Tools using the `observe`-by-path API now work.\n\t\t//\n\t\t// QA-fix (#5 stability): registrations live AFTER ALL dependent nodes\n\t\t// are constructed (`promptInput → llmResponse → effResponse →\n\t\t// lastResponseState → toolCallsRaw → toolResultsNode → effResults →\n\t\t// effAbort → _terminalResult`). Topology event-stream consumers\n\t\t// subscribed at construction time now see registrations in an order\n\t\t// where every edge between two registered nodes is already valid —\n\t\t// no transient partial graph slipping through to live mermaid / d2\n\t\t// renderers.\n\t\tthis.add(promptInput as Node<unknown>, { name: \"promptInput\" });\n\t\tthis.add(llmResponse as Node<unknown>, { name: \"llmResponse\" });\n\t\tthis.add(this.lastResponse as Node<unknown>, { name: \"lastResponse\" });\n\t\t// When no interceptor is configured, `this.toolCalls === toolCallsRaw` —\n\t\t// registering the same instance under two names trips the per-graph\n\t\t// `_nodeToName` collision check. Register the raw under `toolCalls`\n\t\t// directly in that case; otherwise register both (raw + post-intercept).\n\t\tif (this.toolCalls === toolCallsRaw) {\n\t\t\tthis.add(this.toolCalls as Node<unknown>, { name: \"toolCalls\" });\n\t\t} else {\n\t\t\tthis.add(toolCallsRaw as Node<unknown>, { name: \"toolCallsRaw\" });\n\t\t\tthis.add(this.toolCalls as Node<unknown>, { name: \"toolCalls\" });\n\t\t}\n\t\tthis.add(toolResultsNode as Node<unknown>, { name: \"toolResults\" });\n\t\tthis.add(this._terminalResult as Node<unknown>, { name: \"terminalResult\" });\n\n\t\t// Register subscriptions via `addDisposer` so they tear down on\n\t\t// subgraph unmount (not just explicit `destroy()`). A caller that\n\t\t// unmounts the AgentLoopGraph from its parent via `graph.remove(...)`\n\t\t// would otherwise keep `turnSub` / `abortedSub` live against dead state.\n\t\tthis.addDisposer(turnSub);\n\t\tthis.addDisposer(abortedSub);\n\t\tthis.addDisposer(statusSub);\n\t\tthis.addDisposer(kaResponse);\n\t\tthis.addDisposer(kaResults);\n\t\tthis.addDisposer(kaAbort);\n\t\tthis._disposeRunWiring = (): void => {\n\t\t\t// addDisposer takes care of teardown; this shim stays for the\n\t\t\t// `destroy()` override's idempotency contract (safe no-op if the\n\t\t\t// disposers already fired).\n\t\t};\n\t}\n\n\t/**\n\t * Bridge to `Promise<LLMResponse>` over the reactive pipeline.\n\t *\n\t * - If `userMessage` is provided, appends it as a user message and\n\t * transitions status to `\"thinking\"` to kick the loop.\n\t * - If `signal` is provided, binds it to the reactive `aborted` node\n\t * AND threads into `adapter.invoke({ signal })` so the wire call can\n\t * cancel mid-flight. The reactive `aborted` state + effect 3 guarantee\n\t * that even an adapter that ignores `signal` will stop emitting into\n\t * the agent graph.\n\t * - Resolves when `status === \"done\"` with the final LLM response.\n\t * Rejects with `AbortError` when the abort signal fires pre-response.\n\t * Rejects with the stage error when `status === \"error\"`.\n\t *\n\t * **Concurrency:** `run()` refuses to overlap with a pending call on the\n\t * same agent. Attempting to call `run()` while a previous `run()` is\n\t * still in-flight throws a `RangeError` immediately. Stale-resolution\n\t * safety is provided by `awaitSettled({skipCurrent: true})`, which\n\t * ignores the cached initial DATA from any previous run and resolves\n\t * only on a fresh post-subscribe emission of `_terminalResult`.\n\t */\n\tasync run(userMessage?: string, signal?: AbortSignal): Promise<LLMResponse | null> {\n\t\tif (this._running) {\n\t\t\tthrow new RangeError(\n\t\t\t\t`agentLoop \"${this.name}\": run() called while a previous run() is still pending — await the previous run before starting another, or call abort() first`,\n\t\t\t);\n\t\t}\n\t\tthis._running = true;\n\n\t\tlet offAbort: (() => void) | undefined;\n\t\ttry {\n\t\t\t// Reset per-run state. `lastResponse` MUST be cleared here —\n\t\t\t// without it, `_terminalResult` would read the prior run's\n\t\t\t// cached response during a second `run()` with a pre-aborted\n\t\t\t// signal: `effAbort` drives `status → \"done\"`, `_terminalResult`\n\t\t\t// evaluates `stat=\"done\"` + `resp=<prior respA>` and emits DATA\n\t\t\t// as a fresh post-subscribe signal → `awaitSettled` resolves\n\t\t\t// with the stale response instead of rejecting with AbortError.\n\t\t\t// The C3 `stat=done && resp===undefined → ERROR` guard in\n\t\t\t// `_terminalResult` is only correct once the reset clears the\n\t\t\t// cache.\n\t\t\t//\n\t\t\t// **SENTINEL reset via plain `[[INVALIDATE]]`** (DS-13.5.A,\n\t\t\t// 2026-05-01). Pre-DS-13.5.A this required a paired\n\t\t\t// `[[INVALIDATE], [RESOLVED]]` because INVALIDATE alone left\n\t\t\t// dependents wedged in DIRTY. With INVALIDATE settling the wave\n\t\t\t// (decrementing `_dirtyDepCount` like RESOLVED) and clearing\n\t\t\t// `_cached` + each dependent's `prevData[lastResponse]` slot\n\t\t\t// back to `undefined`, a single emission restores SENTINEL state\n\t\t\t// AND lets dependents fire on the next status transition.\n\t\t\t// `lastResponse` is a `Node<LLMResponse>` with no `initial` —\n\t\t\t// it stays SENTINEL until the first real response; resetting\n\t\t\t// via `emit(null)` would push a `null` DATA placeholder (the\n\t\t\t// F9 trap), which is why INVALIDATE rather than emit is used.\n\t\t\tbatch(() => {\n\t\t\t\tthis.lastResponse.down([[INVALIDATE]]);\n\t\t\t\tthis.turn.emit(0);\n\t\t\t\tthis.aborted.emit(false);\n\t\t\t\tthis.status.emit(\"idle\");\n\t\t\t});\n\t\t\tif (userMessage != null) this.chat.append(\"user\", userMessage);\n\n\t\t\t// Subscribe to `_terminalResult` BEFORE transitioning to\n\t\t\t// \"thinking\" — otherwise a synchronous adapter (mock tests,\n\t\t\t// offline stubs) would drain status → done → DATA on\n\t\t\t// `_terminalResult` before `awaitSettled` had a chance to\n\t\t\t// subscribe, and `skipCurrent: true` would swallow the only\n\t\t\t// DATA this run will produce. `awaitSettled` / `firstWhere`\n\t\t\t// subscribes synchronously during the `async` function's\n\t\t\t// initial execution slice, so calling it before the kick\n\t\t\t// guarantees the subscription is in place when the pipeline\n\t\t\t// starts draining.\n\t\t\t//\n\t\t\t// `skipCurrent: true` still matters: on the second `run()`\n\t\t\t// call `_terminalResult` holds cached DATA from the prior run,\n\t\t\t// and push-on-subscribe would resolve immediately with that\n\t\t\t// stale value without the skip.\n\t\t\tconst resultPromise = awaitSettled(this._terminalResult, { skipCurrent: true });\n\n\t\t\tif (signal != null) {\n\t\t\t\tif (signal.aborted) {\n\t\t\t\t\tthis.aborted.emit(true);\n\t\t\t\t} else {\n\t\t\t\t\tconst listener = (): void => this.aborted.emit(true);\n\t\t\t\t\tsignal.addEventListener(\"abort\", listener, { once: true });\n\t\t\t\t\toffAbort = (): void => signal.removeEventListener(\"abort\", listener);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Kick — transition to \"thinking\" fires promptInput → llmResponse.\n\t\t\t// Skip the kick when the signal was already aborted: `effAbort`\n\t\t\t// has driven `status → \"done\"` above, and a trailing\n\t\t\t// `thinking` emit would produce a non-monotonic `idle → done →\n\t\t\t// thinking` sequence in the status-event log for no reactive\n\t\t\t// benefit (promptInput gates on `!latestAborted` anyway).\n\t\t\tif (signal?.aborted !== true) {\n\t\t\t\tthis.status.emit(\"thinking\");\n\t\t\t}\n\n\t\t\treturn await resultPromise;\n\t\t} finally {\n\t\t\toffAbort?.();\n\t\t\tthis._running = false;\n\t\t\tthis._currentAbortController = null;\n\t\t}\n\t}\n\n\t/**\n\t * Flip the reactive `aborted` state. Equivalent to setting an external\n\t * `AbortSignal` — the pipeline observes and transitions to `\"done\"`.\n\t */\n\tabort(): void {\n\t\tthis.aborted.emit(true);\n\t}\n\n\toverride destroy(): void {\n\t\ttry {\n\t\t\tthis._disposeRunWiring();\n\t\t} catch {\n\t\t\t/* best-effort: disposing keepalives shouldn't block destroy */\n\t\t}\n\t\tsuper.destroy();\n\t}\n}\n\n/**\n * Read the latest value for dep `i` inside a raw-`node()` fn body.\n *\n * Checks `batchData[i]` first (this-wave DATA from the dep), falls back to\n * `ctx.prevData[i]` (last DATA from prior waves), and finally to `fallback`\n * when the dep has never emitted (SENTINEL). Matches the unwrap semantics\n * `derived`'s sugar applies, so raw nodes can read deps uniformly.\n *\n * @internal\n */\nfunction readLatest<T>(\n\tbatchData: readonly (readonly unknown[] | undefined)[],\n\tprevData: readonly unknown[],\n\tindex: number,\n\tfallback: T,\n): T {\n\tconst batch = batchData[index];\n\tif (batch != null && batch.length > 0) return batch[batch.length - 1] as T;\n\tconst prev = prevData[index];\n\treturn (prev !== undefined ? prev : fallback) as T;\n}\n\n/** @internal Shape of the LLM invocation input — constructed inside `promptInput`. */\ninterface InvokeInput {\n\treadonly messages: readonly ChatMessage[];\n\treadonly tools: readonly ToolDefinition[];\n}\n\nexport function agentLoop(name: string, opts: AgentLoopOptions): AgentLoopGraph {\n\tconst g = new AgentLoopGraph(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. Opts include non-JSON\n\t// fields (`adapter`, `tools`, `stopWhen`, `onToolCall`,\n\t// `interceptToolCalls`, etc.) so route through `placeholderArgs`\n\t// (DG2=ii).\n\tg.tagFactory(\"agentLoop\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\treturn g;\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 * @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 * 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","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","/**\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","/**\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","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","// ---------------------------------------------------------------------------\n// agentMemory — sugar over the memoryWith* composers (Unit 7 B).\n//\n// Thin wiring: distill() builds the core store (when no tiers configured);\n// optional capabilities delegate to the composer Graph subclasses in\n// `memory-composers.ts`. Each composer is a self-contained\n// `MemoryWithXxxGraph` that AgentMemoryGraph mounts on itself (Class B\n// audit, 2026-04-30) — teardown cascades via `Graph.destroy()`.\n//\n// **Phase 12.D (2026-04-30):** Migrated from the `Object.assign(graph, ...)`\n// factory pattern to `class extends Graph` (mirrors the\n// `MemoryWith*Graph` precedent). Required by Phase 13.G `agent(spec)` —\n// `AgentBundle.graph: AgentGraph<TIn, TOut>` consumers want `instanceof`\n// narrowing on agent-memory subgraphs.\n// ---------------------------------------------------------------------------\n\nimport { DATA, type Node, node, placeholderArgs, RESOLVED } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, fromTimer, type NodeInput, switchMap } 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 type { LLMAdapter } from \"../../utils/ai/adapters/core/types.js\";\nimport {\n\ttype MemoryWithTiersGraph,\n\tmemoryRetrieval,\n\tmemoryWithKG,\n\tmemoryWithTiers,\n\tmemoryWithVectors,\n} from \"../../utils/ai/memory/memory-composers.js\";\nimport type { RetrievalEntry, RetrievalQuery } from \"../../utils/ai/memory/retrieval.js\";\nimport type { MemoryTiersBundle, MemoryTiersOptions } from \"../../utils/ai/memory/tiers.js\";\nimport { llmConsolidator, llmExtractor } from \"../../utils/ai/prompts/prompt-call.js\";\nimport type { KnowledgeGraph, VectorIndexGraph } from \"../../utils/memory/index.js\";\n\nexport type AgentMemoryOptions<TMem = unknown> = {\n\tgraph?: GraphOptions;\n\t/** LLM adapter for extraction and consolidation. */\n\tadapter?: LLMAdapter;\n\t/** System prompt for the extractor LLM. */\n\textractPrompt?: string;\n\t/** Custom extractFn (overrides adapter + extractPrompt). */\n\textractFn?: (raw: unknown, existing: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>;\n\t/** System prompt for the consolidation LLM. */\n\tconsolidatePrompt?: string;\n\t/** Custom consolidateFn (overrides adapter + consolidatePrompt). */\n\tconsolidateFn?: (entries: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>;\n\t/** Reactive trigger for consolidation (caller supplies e.g. `fromTimer`). */\n\tconsolidateTrigger?: NodeInput<unknown>;\n\t/** Score function for budget packing (required). */\n\tscore: (mem: TMem, context: unknown) => number;\n\t/** Cost function for budget packing (required). */\n\tcost: (mem: TMem) => number;\n\t/** Token budget for compact view (default 2000). */\n\tbudget?: number;\n\t/** Context node for scoring. */\n\tcontext?: NodeInput<unknown>;\n\t/** Admission filter (default: admit all). */\n\tadmissionFilter?: (candidate: unknown) => boolean;\n\t/** Vector index dimensions (> 0 enables vector index for retrieval). */\n\tvectorDimensions?: number;\n\t/**\n\t * B12: optional accessor for an entry's hierarchical context breadcrumb\n\t * (e.g. `[\"projects\", \"auth\", \"tokens\"]`). When supplied alongside\n\t * `contextWeight > 0`, retrieval applies a score boost for entries whose\n\t * context shares a prefix with the query's `context`. Entries without\n\t * a breadcrumb are scored flatly.\n\t */\n\tcontextOf?: (mem: TMem) => readonly string[] | undefined;\n\t/**\n\t * B12: hierarchical context boost multiplier. Score is scaled by\n\t * `(1 + contextWeight * sharedDepth / queryDepth)` when both the query\n\t * and entry supply a `context`. Default: 0.\n\t */\n\tcontextWeight?: number;\n\n\t// --- In-factory composition (new) ---\n\n\t/** Extract embedding vector from a memory entry (enables vector index). */\n\tembedFn?: (mem: TMem) => readonly number[] | undefined;\n\t/** Enable knowledge graph for entity/relation tracking. */\n\tenableKnowledgeGraph?: boolean;\n\t/** Extract entities and relations from a memory entry. */\n\tentityFn?: (\n\t\tkey: string,\n\t\tmem: TMem,\n\t) =>\n\t\t| {\n\t\t\t\tentities?: Array<{ id: string; value: unknown }>;\n\t\t\t\trelations?: Array<{ from: string; to: string; relation: string; weight?: number }>;\n\t\t }\n\t\t| undefined;\n\n\t/** 3-tier storage configuration. Omit to use single-tier (existing behavior). */\n\ttiers?: MemoryTiersOptions<TMem>;\n\n\t/** Retrieval pipeline configuration. Requires vector index or knowledge graph. */\n\tretrieval?: {\n\t\t/** Max candidates from vector search (default 20). */\n\t\ttopK?: number;\n\t\t/** KG expansion depth in hops (default 1). */\n\t\tgraphDepth?: number;\n\t};\n\n\t/** Periodic reflection/consolidation configuration. */\n\treflection?: {\n\t\t/** Interval in ms between consolidation runs (default 300_000 = 5 min). */\n\t\tinterval?: number;\n\t\t/** Enable/disable periodic reflection (default true when consolidateFn is available). */\n\t\tenabled?: boolean;\n\t};\n};\n\n/**\n * Pre-wired agentic memory graph. Sugar over `distill` plus the\n * `memoryWithVectors` / `memoryWithKG` / `memoryWithTiers` / `memoryRetrieval`\n * composers. Power users who want a subset of capabilities can call those\n * composers directly; this class bundles them into one ergonomic Graph subclass.\n *\n * Mounts:\n * - `tiers/*` — present when `opts.tiers` configured (replaces the\n * default distill bundle).\n * - `vectors/*` — present when `opts.vectorDimensions > 0 && opts.embedFn`.\n * - `knowledge/*` — present when `opts.enableKnowledgeGraph`.\n * - `retrieval/*` — present when vectors or kg configured.\n *\n * When `opts.tiers` is omitted, `store` / `compact` / `size` are added as\n * top-level nodes on this graph (visible in `describe()` / `explain()`).\n */\nexport class AgentMemoryGraph<TMem = unknown> extends Graph {\n\treadonly distillBundle: DistillBundle<TMem>;\n\treadonly compact: Node<Array<{ key: string; value: TMem; score: number }>>;\n\treadonly size: Node<number>;\n\t/** Vector index bundle (null if not enabled). */\n\treadonly vectors: VectorIndexGraph<TMem> | null;\n\t/** Knowledge graph (null if not enabled). */\n\treadonly kg: KnowledgeGraph<unknown, string> | null;\n\t/** Memory tiers bundle (null if not configured). */\n\treadonly memoryTiers: MemoryTiersBundle<TMem> | null;\n\t/**\n\t * The mounted `MemoryWithTiersGraph` subgraph (null when `opts.tiers` was\n\t * omitted). Surfaces the inner graph for `describe()` / `explain()` walks\n\t * and for callers that need direct access to the tiers subgraph (e.g.\n\t * to register additional disposers or attach storage). Companion to\n\t * `memoryTiers`, which carries only the bundle's reactive surface (B5e).\n\t */\n\treadonly tiers: MemoryWithTiersGraph<unknown, TMem> | null;\n\t/**\n\t * Reactive consumer API. Given a reactive `RetrievalQuery | null` source,\n\t * returns a `Node` emitting the packed retrieval results. Composable with\n\t * graph topology — subscribe it, chain it into `promptNode`, or switchMap\n\t * over a user-input node.\n\t *\n\t * Each call mounts its own per-input subgraph at\n\t * `retrieval::retrieve_${id}` (via `MemoryRetrievalGraph`); concurrent\n\t * calls don't share state mirrors. One-shot consumers wrap with\n\t * `awaitSettled(retrieveReactive(query))`.\n\t *\n\t * Null when no retrieval pipeline is configured.\n\t *\n\t * **QA F-9 (2026-04-30):** the prior `retrieval` / `retrievalTrace`\n\t * shared state-node mirrors have been dropped. Use `retrieveReactive`\n\t * for per-call reactive results; one-shot trace consumers should\n\t * subscribe to the projection's upstream `result` derived directly\n\t * via `view.target.resolve(\"retrieval::retrieve_${id}::result\")`.\n\t */\n\treadonly retrieveReactive:\n\t\t| ((queryInput: NodeInput<RetrievalQuery | null>) => Node<ReadonlyArray<RetrievalEntry<TMem>>>)\n\t\t| null;\n\n\tconstructor(name: string, source: NodeInput<unknown>, opts: AgentMemoryOptions<TMem>) {\n\t\tsuper(name, opts.graph);\n\n\t\t// --- Extract function resolution ---\n\t\t// /qa A3 (2026-04-30): validate BEFORE tagFactory so an invalid-opts\n\t\t// throw doesn't leave a tagged-but-empty Graph instance behind.\n\t\tlet rawExtractFn: (\n\t\t\traw: unknown,\n\t\t\texisting: ReadonlyMap<string, TMem>,\n\t\t) => NodeInput<Extraction<TMem>>;\n\t\tif (opts.extractFn) {\n\t\t\trawExtractFn = opts.extractFn;\n\t\t} else if (opts.adapter && opts.extractPrompt) {\n\t\t\trawExtractFn = llmExtractor<unknown, TMem>(opts.extractPrompt, { adapter: opts.adapter });\n\t\t} else {\n\t\t\tthrow new Error(\"agentMemory: provide either extractFn or adapter + extractPrompt\");\n\t\t}\n\n\t\t// Tier 1.5.3 Phase 2.5 (DG1=B): tag the Graph with its constructing\n\t\t// factory so `describe()` exposes provenance. Opts contain non-JSON\n\t\t// fields (`adapter`, `extractFn`, `embedFn`, `score`, `cost`, `evict`,\n\t\t// callbacks, etc.) so route through `placeholderArgs` (DG2=ii).\n\t\tthis.tagFactory(\"agentMemory\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\t\t// Tier 1.5.4 — distill's `extractFn` is now reactive (called once with\n\t\t// nodes). Adapt the AgentMemoryOptions callback shape via switchMap +\n\t\t// closure-mirror for `existing` (COMPOSITION-GUIDE §40 recipe).\n\t\t// QA F9: register the closure-mirror's unsub with the host graph so\n\t\t// `graph.destroy()` reclaims it — was previously leaked.\n\t\t//\n\t\t// **Phase 16 attempt (2026-04-29) reverted.** Tried `withLatestFrom(\n\t\t// rawNode, existingNode) + switchMap`; this is the WRONG migration per\n\t\t// COMPOSITION-GUIDE §28. **Phase 10.5 (same-day partial-flag flip on\n\t\t// `withLatestFrom`)** removes the initial-pair drop, but this site stays\n\t\t// on closure-mirror form pending Phase 11 restricted signatures. See\n\t\t// `archive/docs/SESSION-graph-narrow-waist.md` § \"Status of existing\n\t\t// modifications\" + § \"Phase 10.5\".\n\t\tconst extractFn = (\n\t\t\trawNode: Node<unknown>,\n\t\t\texistingNode: Node<ReadonlyMap<string, TMem>>,\n\t\t): NodeInput<Extraction<TMem>> => {\n\t\t\tlet latestExisting: ReadonlyMap<string, TMem> =\n\t\t\t\t(existingNode.cache as ReadonlyMap<string, TMem> | undefined) ?? new Map();\n\t\t\tconst unsubExisting = existingNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === DATA) latestExisting = m[1] as ReadonlyMap<string, TMem>;\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.addDisposer(unsubExisting);\n\t\t\treturn switchMap(rawNode, (raw) => {\n\t\t\t\tif (raw == null) return { upsert: [] };\n\t\t\t\treturn rawExtractFn(raw, latestExisting);\n\t\t\t});\n\t\t};\n\n\t\t// --- Admission filter ---\n\t\tlet filteredSource = source;\n\t\tif (opts.admissionFilter) {\n\t\t\tconst srcNode = fromAny(source);\n\t\t\tconst filter = opts.admissionFilter;\n\t\t\tfilteredSource = node(\n\t\t\t\t[srcNode],\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 raw = data[0];\n\t\t\t\t\tif (filter(raw)) {\n\t\t\t\t\t\tactions.emit(raw);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// EC1 (qa 2026-04-30): emitting `undefined` would violate spec §5.12\n\t\t\t\t\t\t// (undefined is the protocol SENTINEL — TopicGraph.publish even\n\t\t\t\t\t\t// throws on it). Downstream `batch.at(-1) : ctx.prevData[i]`\n\t\t\t\t\t\t// would also resolve `undefined` back to the prior accepted\n\t\t\t\t\t\t// value, leaking past-the-filter. Emit a tier-3 RESOLVED so the\n\t\t\t\t\t\t// wave settles cleanly without surfacing a stale DATA.\n\t\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{ name: \"admissionFilter\", describeKind: \"derived\" },\n\t\t\t);\n\t\t}\n\n\t\t// --- Consolidation ---\n\t\tlet consolidateFn:\n\t\t\t| ((entries: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>)\n\t\t\t| undefined;\n\t\tif (opts.consolidateFn) {\n\t\t\tconsolidateFn = opts.consolidateFn;\n\t\t} else if (opts.adapter && opts.consolidatePrompt) {\n\t\t\tconsolidateFn = llmConsolidator<TMem>(opts.consolidatePrompt, { adapter: opts.adapter });\n\t\t}\n\n\t\t// --- Reflection: default consolidateTrigger from fromTimer ---\n\t\tlet consolidateTrigger = opts.consolidateTrigger;\n\t\tif (!consolidateTrigger && consolidateFn && opts.reflection?.enabled !== false) {\n\t\t\tconst interval = opts.reflection?.interval ?? 300_000;\n\t\t\tconsolidateTrigger = fromTimer(interval, { period: interval });\n\t\t}\n\n\t\t// --- Build distill bundle (the core) ---\n\t\t// Tier 4.1 B (2026-04-29): when tiers are configured, `memoryWithTiers`\n\t\t// is the construction site for the distill bundle so it can wire\n\t\t// `reactiveMap.retention` into the store at construction (no §7 cycle).\n\t\t// When tiers are NOT configured, agentMemory calls `distill` directly.\n\t\tconst distillOpts: DistillOptions<TMem> = {\n\t\t\tscore: opts.score,\n\t\t\tcost: opts.cost,\n\t\t\tbudget: opts.budget ?? 2000,\n\t\t\tcontext: opts.context,\n\t\t\tconsolidate: consolidateFn,\n\t\t\tconsolidateTrigger,\n\t\t};\n\n\t\tlet distillBundle: DistillBundle<TMem>;\n\t\tlet memoryTiersBundle: MemoryTiersBundle<TMem> | null = null;\n\t\tlet tiersSubgraph: MemoryWithTiersGraph<unknown, TMem> | null = null;\n\t\tif (opts.tiers) {\n\t\t\tconst tiersGraph = memoryWithTiers<unknown, TMem>({\n\t\t\t\t// User customization first; canonical agent-memory-level overrides\n\t\t\t\t// last so they always win even if `MemoryTiersOptions` later adds\n\t\t\t\t// any of the same keys.\n\t\t\t\t...opts.tiers,\n\t\t\t\tname: \"tiers\",\n\t\t\t\tsource: filteredSource,\n\t\t\t\textractFn,\n\t\t\t\tscore: opts.score,\n\t\t\t\tcost: opts.cost,\n\t\t\t\t...(opts.budget !== undefined ? { budget: opts.budget } : { budget: 2000 }),\n\t\t\t\t...(opts.context !== undefined ? { context: opts.context } : {}),\n\t\t\t\t...(consolidateFn !== undefined ? { consolidate: consolidateFn } : {}),\n\t\t\t\t...(consolidateTrigger !== undefined ? { consolidateTrigger } : {}),\n\t\t\t});\n\t\t\tthis.mount(\"tiers\", tiersGraph);\n\t\t\tdistillBundle = tiersGraph.store;\n\t\t\tmemoryTiersBundle = tiersGraph.tiers;\n\t\t\ttiersSubgraph = tiersGraph;\n\t\t} else {\n\t\t\tdistillBundle = distill<unknown, TMem>(filteredSource, extractFn, distillOpts);\n\t\t\tthis.add(distillBundle.store.entries, { name: \"store\" });\n\t\t\tthis.add(distillBundle.compact, { name: \"compact\" });\n\t\t\tthis.add(distillBundle.size, { name: \"size\" });\n\t\t}\n\n\t\t// --- Vector index (composer) ---\n\t\tlet vectors: VectorIndexGraph<TMem> | null = null;\n\t\tif (opts.vectorDimensions && opts.vectorDimensions > 0 && opts.embedFn) {\n\t\t\tconst vectorsGraph = memoryWithVectors<TMem>({\n\t\t\t\tname: \"vectors\",\n\t\t\t\tstore: distillBundle,\n\t\t\t\tdimension: opts.vectorDimensions,\n\t\t\t\tembedFn: opts.embedFn,\n\t\t\t});\n\t\t\tthis.mount(\"vectors\", vectorsGraph);\n\t\t\tvectors = vectorsGraph.vectors;\n\t\t}\n\n\t\t// --- Knowledge graph (composer) ---\n\t\tlet kg: KnowledgeGraph<unknown, string> | null = null;\n\t\tif (opts.enableKnowledgeGraph) {\n\t\t\tconst kgGraph = memoryWithKG<TMem>({\n\t\t\t\tname: \"knowledge\",\n\t\t\t\tstore: distillBundle,\n\t\t\t\tkgName: `${name}-kg`,\n\t\t\t\tmountPath: \"knowledge-kg\",\n\t\t\t\t...(opts.entityFn !== undefined ? { entityFn: opts.entityFn } : {}),\n\t\t\t});\n\t\t\tthis.mount(\"knowledge\", kgGraph);\n\t\t\tkg = kgGraph.kg;\n\t\t}\n\n\t\t// --- Retrieval pipeline (composer) ---\n\t\tlet retrieveReactive:\n\t\t\t| ((\n\t\t\t\t\tqueryInput: NodeInput<RetrievalQuery | null>,\n\t\t\t ) => Node<ReadonlyArray<RetrievalEntry<TMem>>>)\n\t\t\t| null = null;\n\n\t\tif (vectors || kg) {\n\t\t\tconst retrievalGraph = memoryRetrieval<TMem>({\n\t\t\t\tname: \"retrieval\",\n\t\t\t\tstore: distillBundle,\n\t\t\t\tvectors,\n\t\t\t\tkg,\n\t\t\t\tscore: opts.score,\n\t\t\t\tcost: opts.cost,\n\t\t\t\t...(opts.budget !== undefined ? { budget: opts.budget } : {}),\n\t\t\t\t...(opts.retrieval?.topK !== undefined ? { topK: opts.retrieval.topK } : {}),\n\t\t\t\t...(opts.retrieval?.graphDepth !== undefined\n\t\t\t\t\t? { graphDepth: opts.retrieval.graphDepth }\n\t\t\t\t\t: {}),\n\t\t\t\t...(opts.contextOf !== undefined ? { contextOf: opts.contextOf } : {}),\n\t\t\t\t...(opts.contextWeight !== undefined ? { contextWeight: opts.contextWeight } : {}),\n\t\t\t\t...(opts.context !== undefined ? { context: opts.context } : {}),\n\t\t\t});\n\t\t\tthis.mount(\"retrieval\", retrievalGraph);\n\t\t\tretrieveReactive = retrievalGraph.retrieveReactive.bind(retrievalGraph);\n\t\t}\n\n\t\tthis.distillBundle = distillBundle;\n\t\tthis.compact = distillBundle.compact;\n\t\tthis.size = distillBundle.size;\n\t\tthis.vectors = vectors;\n\t\tthis.kg = kg;\n\t\tthis.memoryTiers = memoryTiersBundle;\n\t\tthis.tiers = tiersSubgraph;\n\t\tthis.retrieveReactive = retrieveReactive;\n\t}\n}\n\n/**\n * Pre-wired agentic memory graph. Sugar over `distill` plus the\n * `memoryWithVectors` / `memoryWithKG` / `memoryWithTiers` / `memoryRetrieval`\n * composers. Power users who want a subset of capabilities can call those\n * composers directly; this factory bundles them into one ergonomic call.\n *\n * Returns an {@link AgentMemoryGraph} subclass instance — `instanceof\n * AgentMemoryGraph` narrows in callers (e.g. Phase 13.G `agent(spec)`).\n */\nexport function agentMemory<TMem = unknown>(\n\tname: string,\n\tsource: NodeInput<unknown>,\n\topts: AgentMemoryOptions<TMem>,\n): AgentMemoryGraph<TMem> {\n\treturn new AgentMemoryGraph<TMem>(name, source, 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// 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 * 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 * 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// 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 * harnessLoop() factory (roadmap §9.0).\n *\n * Wires the static 7-stage topology: INTAKE → TRIAGE → QUEUE → GATE →\n * EXECUTE → VERIFY → REFLECT. Static topology, flowing data — the Kafka\n * insight applied to human+LLM collaboration.\n *\n * **Hub model (Wave B Unit 20 C + Q1).** All reactive-wire-crossing topics\n * live in one `MessagingHubGraph` exposed as `HarnessGraph.queues`: the\n * four per-route queues, an `__unrouted` dead-letter, plus `intake`,\n * `retry`, `verify-results`, and the `triage-output` fan-in topic. The\n * router is a single derived/effect pair that publishes to `triage-output`;\n * per-route `topicBridge`s fan out by `map:` predicate. Routing is data\n * (topic name), not code — every routing decision is a visible edge in\n * `describe()` / `explain()`.\n *\n * **EXECUTE/VERIFY via JobFlow (Tier 6.5 C2 lock, 2026-04-28).** The\n * stages 5–6 EXECUTE → VERIFY pair runs through an internal `executeFlow`\n * JobFlow with two stages (`execute`, `verify`). Each stage's pump owns\n * `claim → work → ack` for one claim; the verify stage's payload contains\n * `{ item, execution, verify }` so the post-completed dispatch effect can\n * route the 3-way verdict (verified / self-correctable retry / structural\n * + reingest) without any cross-wave `withLatestFrom` pairing. Items\n * arriving from per-route topics + retry feedback enter via a single\n * `enqueueEffect` that pushes to `executeFlow.queue(\"execute\")`.\n *\n * @module\n */\n\nimport { monotonicNs, type Node, node, placeholderArgs } from \"@graphrefly/pure-ts/core\";\nimport { merge, withLatestFrom } from \"@graphrefly/pure-ts/extra\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { tryIncrementBounded } from \"../../base/mutation/index.js\";\nimport { _oneShotLlmCall, stripFences } from \"../../utils/ai/_internal.js\";\nimport type { ChatMessage, LLMAdapter } from \"../../utils/ai/index.js\";\nimport { promptNode } from \"../../utils/ai/index.js\";\nimport { trackingKey } from \"../../utils/harness/_internal.js\";\nimport {\n\tDEFAULT_DECAY_RATE,\n\tDEFAULT_EXECUTE_PROMPT,\n\tDEFAULT_QUEUE_CONFIGS,\n\tDEFAULT_SEVERITY_WEIGHTS,\n\tDEFAULT_TRIAGE_PROMPT,\n\tDEFAULT_VERIFY_PROMPT,\n\tdefaultErrorClassifier,\n\tQUEUE_NAMES,\n\tresolvePromptFn,\n} from \"../../utils/harness/defaults.js\";\nimport {\n\ttype StrategyModelGraph,\n\ttype StrategySnapshot,\n\tstrategyModel,\n} from \"../../utils/harness/strategy.js\";\nimport type {\n\tErrorClassifier,\n\tExecuteOutput,\n\tExecutePromptFn,\n\tExecutionResult,\n\tHarnessExecutor,\n\tHarnessJobPayload,\n\tHarnessLoopOptions,\n\tHarnessVerifier,\n\tIntakeItem,\n\tQueueConfig,\n\tQueueRoute,\n\tTriagedItem,\n\tVerifyOutput,\n\tVerifyPromptFn,\n\tVerifyResult,\n} from \"../../utils/harness/types.js\";\nimport { DEFAULT_PRESET_ID, strategyKey } from \"../../utils/harness/types.js\";\nimport {\n\ttype JobEnvelope,\n\ttype JobFlowGraph,\n\ttype JobQueueGraph,\n\tjobFlow,\n\tjobQueue,\n} from \"../../utils/job-queue/index.js\";\nimport {\n\ttype MessagingHubGraph,\n\tmessagingHub,\n\ttype TopicGraph,\n\ttopicBridge,\n} from \"../../utils/messaging/index.js\";\nimport { type GateController, pipelineGraph } from \"../../utils/orchestration/index.js\";\n\n// ---------------------------------------------------------------------------\n// Hub topic names (internal constants — strings are the routing API)\n// ---------------------------------------------------------------------------\n\nconst TOPIC_INTAKE = \"intake\";\nconst TOPIC_TRIAGE_OUTPUT = \"triage-output\";\nconst TOPIC_RETRY = \"retry\";\nconst TOPIC_VERIFY_RESULTS = \"verify-results\";\nconst TOPIC_UNROUTED = \"__unrouted\";\n\n// ---------------------------------------------------------------------------\n// Default LLM executor / verifier work fns (Tier 6.5 C2)\n// ---------------------------------------------------------------------------\n\n/**\n * Build the default EXECUTE work fn — calls `adapter.invoke()` once per\n * claimed job, parses the JSON response into an `ExecuteOutput<A>`, and\n * returns a {@link HarnessJobPayload} with `execution` filled in.\n *\n * Errors (parse failure, adapter throw, malformed JSON) are caught and\n * surfaced as a `failure`-outcome payload — the dispatch effect routes\n * the item rather than dropping it via pump nack (see C2 contract on\n * {@link HarnessExecutor}).\n *\n * Subsumes the pre-Tier-6.5 `promptNode`-based default: per-claim LLM\n * calls don't benefit from `promptNode`'s cross-wave switchMap, and a\n * fresh per-claim subgraph would be wasteful. Direct `adapter.invoke`\n * is the right shape inside JobFlow pumps.\n *\n * @param adapter - LLMAdapter for the execute call.\n * @param prompt - Prompt template (string or `(item) => string`). Defaults\n * to the harness's built-in execute prompt.\n */\nexport function defaultLlmExecutor<A = unknown>(\n\tadapter: LLMAdapter,\n\tprompt?: string | ExecutePromptFn,\n): HarnessExecutor<A> {\n\tconst promptFn = resolvePromptFn<TriagedItem>(prompt, DEFAULT_EXECUTE_PROMPT, (tpl, item) =>\n\t\ttpl.replace(\"{{item}}\", JSON.stringify(item)),\n\t);\n\treturn (job, opts) => {\n\t\tconst item = job.payload.item;\n\t\tconst messages: readonly ChatMessage[] = [{ role: \"user\", content: promptFn(item) }];\n\t\t// Bridge-layer flakes get `outcome: \"failure\"` with no `errorClass`.\n\t\t// The dispatch effect's `errorClassifier` runs over `detail` and the\n\t\t// default classifier matches `parse|json|config|validation|syntax`,\n\t\t// so parse-error flakes route to retry. Adapter HTTP/network failures\n\t\t// without a keyword fall through to structural per the existing\n\t\t// asymmetry (executor side relies on classifier; verifier side sets\n\t\t// errorClass directly per qa F3).\n\t\tconst failurePayload = (detail: string): HarnessJobPayload<A> => ({\n\t\t\t...job.payload,\n\t\t\texecution: { item, outcome: \"failure\", detail },\n\t\t});\n\t\tconst formatErr = (err: unknown): string => (err instanceof Error ? err.message : String(err));\n\t\t// One-shot bridge via `_oneShotLlmCall` (patterns/ai/_internal.ts).\n\t\t// Helper owns subscription / abort / first-DATA capture / COMPLETE\n\t\t// arm; this site owns parse + validate + payload mapping. Pump-\n\t\t// supplied `opts.signal` (Tier 6.5 2.5b) cascades into adapter +\n\t\t// fromAny via `parentSignal`.\n\t\treturn _oneShotLlmCall<HarnessJobPayload<A>>(adapter, messages, {\n\t\t\tparentSignal: opts?.signal,\n\t\t\tonSuccess: (resp) => {\n\t\t\t\tlet parsed: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(stripFences(String(resp.content)));\n\t\t\t\t} catch (err) {\n\t\t\t\t\treturn failurePayload(`execute parse error: ${formatErr(err)}`);\n\t\t\t\t}\n\t\t\t\t// Validate plain object before field access — non-object JSON\n\t\t\t\t// (`null` / number / array / string) silently masks malformed\n\t\t\t\t// responses unless caught here. Surfaced via parse-error keyword\n\t\t\t\t// for classifier routing.\n\t\t\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t\t\treturn failurePayload(\n\t\t\t\t\t\t`execute parse error: non-object response: ${JSON.stringify(parsed)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst obj = parsed as Partial<ExecuteOutput<A>>;\n\t\t\t\treturn {\n\t\t\t\t\t...job.payload,\n\t\t\t\t\texecution: {\n\t\t\t\t\t\titem,\n\t\t\t\t\t\toutcome: obj.outcome ?? \"failure\",\n\t\t\t\t\t\tdetail: obj.detail ?? \"unknown\",\n\t\t\t\t\t\tartifact: obj.artifact,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t\tonFailure: (kind, err) => {\n\t\t\t\tif (kind === \"complete\") {\n\t\t\t\t\treturn failurePayload(\"adapter completed without emitting DATA\");\n\t\t\t\t}\n\t\t\t\treturn failurePayload(`executor failed: ${formatErr(err)}`);\n\t\t\t},\n\t\t});\n\t};\n}\n\n/**\n * Build the default VERIFY work fn — calls `adapter.invoke()` once per\n * claimed job to review the prior-stage execution, parses the JSON\n * response into a `VerifyOutput`, and returns a {@link HarnessJobPayload}\n * with `verify` filled in.\n *\n * Same C2 error semantics as {@link defaultLlmExecutor}: parse / adapter\n * failures are surfaced as a structural-failure verify payload so the\n * dispatch effect routes the item.\n */\nexport function defaultLlmVerifier<A = unknown>(\n\tadapter: LLMAdapter,\n\tprompt?: string | VerifyPromptFn<A>,\n): HarnessVerifier<A> {\n\tconst promptFn = resolvePromptFn<readonly [ExecuteOutput<A> | null, TriagedItem | null]>(\n\t\tprompt,\n\t\tDEFAULT_VERIFY_PROMPT,\n\t\t(tpl, pair) => {\n\t\t\tconst [execution, item] = pair;\n\t\t\treturn tpl\n\t\t\t\t.replace(\"{{execution}}\", JSON.stringify(execution))\n\t\t\t\t.replace(\"{{item}}\", JSON.stringify(item));\n\t\t},\n\t);\n\treturn (job, opts) => {\n\t\tconst { item, execution } = job.payload;\n\t\tif (execution == null) {\n\t\t\t// Defensive — verify stage runs after execute; if execution is\n\t\t\t// missing, surface as STRUCTURAL failure rather than throw. This is\n\t\t\t// the only structural-classified path here: it indicates a topology\n\t\t\t// bug (verify ran without execute), not an LLM-bridge flake. Bridge\n\t\t\t// flakes (parse / adapter throw / ERROR / COMPLETE-without-DATA) get\n\t\t\t// `errorClass: \"self-correctable\"` below so the dispatch effect's\n\t\t\t// retry budget absorbs them before reingest fires (qa F3).\n\t\t\treturn {\n\t\t\t\t...job.payload,\n\t\t\t\tverify: {\n\t\t\t\t\tverified: false,\n\t\t\t\t\tfindings: [\"verifier: prior execute stage produced no execution\"],\n\t\t\t\t\terrorClass: \"structural\",\n\t\t\t\t},\n\t\t\t} satisfies HarnessJobPayload<A>;\n\t\t}\n\t\tconst messages: readonly ChatMessage[] = [\n\t\t\t{ role: \"user\", content: promptFn([execution, item]) },\n\t\t];\n\t\t// Bridge-layer flakes: classify as self-correctable so the dispatch\n\t\t// effect routes via the retry budget first. Persistent flakes still\n\t\t// fall through to structural after `maxRetries` exhaustion (qa F3).\n\t\tconst failurePayload = (finding: string): HarnessJobPayload<A> => ({\n\t\t\t...job.payload,\n\t\t\tverify: {\n\t\t\t\tverified: false,\n\t\t\t\tfindings: [finding],\n\t\t\t\terrorClass: \"self-correctable\",\n\t\t\t},\n\t\t});\n\t\tconst formatErr = (err: unknown): string => (err instanceof Error ? err.message : String(err));\n\t\t// One-shot bridge — see `_oneShotLlmCall` JSDoc. Helper owns the\n\t\t// subscribe + capture + abort + COMPLETE arm; this site owns parse +\n\t\t// validate + verify-payload mapping. Pump-supplied `opts.signal`\n\t\t// (Tier 6.5 2.5b) cascades into adapter + fromAny via `parentSignal`.\n\t\treturn _oneShotLlmCall<HarnessJobPayload<A>>(adapter, messages, {\n\t\t\tparentSignal: opts?.signal,\n\t\t\tonSuccess: (resp) => {\n\t\t\t\tlet parsed: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(stripFences(String(resp.content)));\n\t\t\t\t} catch (err) {\n\t\t\t\t\treturn failurePayload(`verify parse error: ${formatErr(err)}`);\n\t\t\t\t}\n\t\t\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t\t\treturn failurePayload(\n\t\t\t\t\t\t`verify parse error: non-object response: ${JSON.stringify(parsed)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst obj = parsed as Partial<VerifyOutput>;\n\t\t\t\treturn {\n\t\t\t\t\t...job.payload,\n\t\t\t\t\tverify: {\n\t\t\t\t\t\tverified: obj.verified === true,\n\t\t\t\t\t\tfindings: obj.findings ?? [],\n\t\t\t\t\t\terrorClass: obj.errorClass,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t\tonFailure: (kind, err) => {\n\t\t\t\tif (kind === \"complete\") {\n\t\t\t\t\treturn failurePayload(\"verifier completed without emitting DATA\");\n\t\t\t\t}\n\t\t\t\treturn failurePayload(`verifier failed: ${formatErr(err)}`);\n\t\t\t},\n\t\t});\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// HarnessGraph\n// ---------------------------------------------------------------------------\n\n/**\n * The graph returned by {@link harnessLoop}. Wraps a single\n * {@link MessagingHubGraph} that owns all reactive-wire-crossing topics\n * (intake, per-route queues, `__unrouted`, retry, verify-results,\n * triage-output), plus an `executeFlow` JobFlow that owns the\n * EXECUTE → VERIFY pipeline (Tier 6.5 C2). Sugar getters expose the\n * canonical topics so the surface stays ergonomic.\n */\nexport class HarnessGraph<A = unknown> extends Graph {\n\t/** Messaging hub — the routing-data plane. Queue topics live here. */\n\treadonly queues: MessagingHubGraph;\n\n\t/**\n\t * EXECUTE → VERIFY JobFlow (Tier 6.5 C2). Pumps own claim/ack/nack\n\t * lifecycle for each stage. Inspect via:\n\t * - `harness.executeFlow.queue(\"execute\").pending` — pending depth.\n\t * - `harness.executeFlow.queue(\"verify\").pending` — items mid-execute.\n\t * - `harness.executeFlow.completed` — verified items waiting for the\n\t * dispatch effect's 3-way routing.\n\t * - `harness.executeFlow.completedCount` — total terminal completions.\n\t */\n\treadonly executeFlow: JobFlowGraph<HarnessJobPayload<A>>;\n\n\t/**\n\t * Per-route JobQueueGraph audit mirrors. Each triaged item that reaches\n\t * a queue is also enqueued here, giving reactive `depth` + `pending` +\n\t * `jobs` observables per route. The dispatch effect ack/removeBy-id's\n\t * the matching job on terminal verdict. The executeFlow JobFlow handles\n\t * the EXECUTE → VERIFY data flow; this is a parallel audit-side ledger\n\t * for per-route depth metrics. Inspect via\n\t * `harness.jobs.get(route).depth.cache` for backpressure metrics.\n\t */\n\treadonly jobs: ReadonlyMap<QueueRoute, JobQueueGraph<TriagedItem>>;\n\n\t/** Per-route gate controllers (only for gated queues). */\n\treadonly gates: ReadonlyMap<QueueRoute, GateController<TriagedItem>>;\n\n\t/**\n\t * Per-route queue topics — typed accessor for the four\n\t * {@link QUEUE_NAMES} entries (`auto-fix`, `needs-decision`,\n\t * `investigation`, `backlog`). Mirrors the `gates` / `jobs` map\n\t * shape so callers can iterate `[route, topic]` pairs without\n\t * hand-rolling `harness.queues.topicNames()` + meta-topic exclusion.\n\t *\n\t * Excludes the meta topics that share the hub:\n\t * `intake` (use {@link intake}), `verify-results` (use\n\t * {@link verifyResults}), `retry` (use {@link retry}), `__unrouted`\n\t * (use {@link unrouted}), and the internal `triage-output` fan-in.\n\t */\n\treadonly queueTopics: ReadonlyMap<QueueRoute, TopicGraph<TriagedItem>>;\n\n\t/** Strategy model — `auditedSuccessTracker` keyed by `StrategyKey`. */\n\treadonly strategy: StrategyModelGraph;\n\n\t/** Global retry count across all items (circuit breaker). Reactive — subscribable. */\n\treadonly totalRetries: Node<number>;\n\n\t/** Global reingestion count across all items (circuit breaker). Reactive — subscribable. */\n\treadonly totalReingestions: Node<number>;\n\n\t/**\n\t * Per-route priority score nodes, populated only when `opts.priority` is\n\t * set on {@link harnessLoop}. Each node emits a score combining severity,\n\t * attention decay, and strategy-model effectiveness for the route's\n\t * current head-of-queue item. `undefined` means the caller did not opt\n\t * in to priority scoring.\n\t */\n\treadonly priorityScores?: ReadonlyMap<QueueRoute, Node<number>>;\n\n\t/**\n\t * REFLECT-stage tick marker — emits one DATA per terminal verdict observed\n\t * on `executeFlow.completed`. `equals: () => false` so each completion\n\t * produces an observable tick (no Object.is collapse on identical\n\t * `null` payloads). Inspection tools (`harnessTrace`, dashboards) can\n\t * subscribe directly here instead of resolving by string path\n\t * (`harness.node(\"reflect\")`) — the field is the lock against rename\n\t * drift.\n\t */\n\treadonly reflect: Node<null>;\n\n\tconstructor(\n\t\tname: string,\n\t\tqueues: MessagingHubGraph,\n\t\texecuteFlow: JobFlowGraph<HarnessJobPayload<A>>,\n\t\tqueueTopics: Map<QueueRoute, TopicGraph<TriagedItem>>,\n\t\tjobs: Map<QueueRoute, JobQueueGraph<TriagedItem>>,\n\t\tgates: Map<QueueRoute, GateController<TriagedItem>>,\n\t\tstrategy: StrategyModelGraph,\n\t\ttotalRetries: Node<number>,\n\t\ttotalReingestions: Node<number>,\n\t\treflect: Node<null>,\n\t\tpriorityScores?: Map<QueueRoute, Node<number>>,\n\t) {\n\t\tsuper(name);\n\t\tthis.queues = queues;\n\t\tthis.executeFlow = executeFlow;\n\t\tthis.queueTopics = queueTopics;\n\t\tthis.jobs = jobs;\n\t\tthis.gates = gates;\n\t\tthis.strategy = strategy;\n\t\tthis.totalRetries = totalRetries;\n\t\tthis.totalReingestions = totalReingestions;\n\t\tthis.reflect = reflect;\n\t\tthis.priorityScores = priorityScores;\n\t}\n\n\t/** Intake topic — publish items here to enter the loop. */\n\tget intake(): TopicGraph<IntakeItem> {\n\t\treturn this.queues.topic<IntakeItem>(TOPIC_INTAKE);\n\t}\n\n\t/** Verify results topic — subscribe to see verification outcomes. */\n\tget verifyResults(): TopicGraph<VerifyResult<A>> {\n\t\treturn this.queues.topic<VerifyResult<A>>(TOPIC_VERIFY_RESULTS);\n\t}\n\n\t/** Retry feedback topic — fast-retry re-entry point. */\n\tget retry(): TopicGraph<TriagedItem> {\n\t\treturn this.queues.topic<TriagedItem>(TOPIC_RETRY);\n\t}\n\n\t/** Dead-letter topic for items whose LLM-chosen route is unknown. */\n\tget unrouted(): TopicGraph<TriagedItem> {\n\t\treturn this.queues.topic<TriagedItem>(TOPIC_UNROUTED);\n\t}\n\n\t/**\n\t * Stage-label → observe-path map for the 7 pipeline stages.\n\t *\n\t * Decouples inspection tools (`harnessTrace`, `harnessProfile`, custom\n\t * dashboards) from mount-structure churn: hub migration, future stage\n\t * splits, gate remounting, or the Tier 6.5 C2 JobFlow rewire shouldn't\n\t * require edits to `trace.ts` as long as this method stays accurate.\n\t *\n\t * Each stage yields `{ label, paths }`; consumers iterate paths per\n\t * stage and attach observers. Tier 6.5: EXECUTE / VERIFY paths now\n\t * resolve to the `executeFlow` stage queues + the `verify-dispatch`\n\t * effect node.\n\t */\n\tstageNodes(): ReadonlyArray<{ label: string; paths: readonly string[] }> {\n\t\tconst hub = this.queues;\n\t\tconst resolveHubPath = (name: string): string | null =>\n\t\t\thub.has(name) ? `queues::${name}::latest` : null;\n\t\tconst includeIf = <T>(value: T | null | undefined): readonly T[] =>\n\t\t\tvalue == null ? [] : [value];\n\n\t\tconst queuePaths = QUEUE_NAMES.flatMap((r) => includeIf(resolveHubPath(r)));\n\t\tconst gatePaths: string[] = [];\n\t\tfor (const [route] of this.gates) {\n\t\t\tgatePaths.push(`gates::${route}/gate`);\n\t\t}\n\t\treturn [\n\t\t\t{ label: \"INTAKE\", paths: includeIf(resolveHubPath(\"intake\")) },\n\t\t\t{ label: \"TRIAGE\", paths: [\"triage\"] },\n\t\t\t{ label: \"QUEUE\", paths: queuePaths },\n\t\t\t{ label: \"GATE\", paths: gatePaths },\n\t\t\t{ label: \"EXECUTE\", paths: [\"executeFlow::execute::events\"] },\n\t\t\t{ label: \"VERIFY\", paths: [\"executeFlow::verify::events\"] },\n\t\t\t{ label: \"REFLECT\", paths: [\"reflect\"] },\n\t\t\t{ label: \"STRATEGY\", paths: [\"strategy::entries\"] },\n\t\t];\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// harnessLoop factory\n// ---------------------------------------------------------------------------\n\n/**\n * Wire the reactive collaboration loop as a static-topology graph.\n *\n * The loop has 7 stages:\n * 1. **INTAKE** — items arrive from multiple sources via `intake.publish()`\n * 2. **TRIAGE** — promptNode classifies, routes, and prioritizes\n * 3. **QUEUE** — 4 priority-ordered TopicGraphs (auto-fix, needs-decision, investigation, backlog)\n * 4. **GATE** — human approval on configurable queues\n * 5. **EXECUTE** — JobFlow `execute` stage; user-supplied or default work fn\n * 6. **VERIFY** — JobFlow `verify` stage; verifies the executed artifact\n * 7. **REFLECT** — strategy model records outcomes; dispatch effect routes 3-way\n *\n * @param name - Graph name.\n * @param opts - Configuration.\n * @returns HarnessGraph with controller accessors.\n */\nexport function harnessLoop<A = unknown>(\n\tname: string,\n\topts: HarnessLoopOptions<A>,\n): HarnessGraph<A> {\n\tconst adapter = opts.adapter;\n\tconst maxRetries = opts.maxRetries ?? 2;\n\tconst retainedLimit = opts.retainedLimit ?? 1000;\n\tconst errorClassifier: ErrorClassifier = opts.errorClassifier ?? defaultErrorClassifier;\n\n\tconst queueConfigs = new Map<QueueRoute, QueueConfig>();\n\tfor (const route of QUEUE_NAMES) {\n\t\tqueueConfigs.set(route, {\n\t\t\t...DEFAULT_QUEUE_CONFIGS[route],\n\t\t\t...opts.queues?.[route],\n\t\t});\n\t}\n\n\t// --- Messaging hub (Wave B Q1 Option A) ---\n\tconst queuesHub = messagingHub(`${name}/queues`, {\n\t\tdefaultTopicOptions: { retainedLimit },\n\t});\n\n\t// Eagerly create canonical topics so they appear in `describe()` from\n\t// construction time and `harness.queues.has(route)` answers `true`\n\t// before any publish.\n\tconst intake = queuesHub.topic<IntakeItem>(TOPIC_INTAKE);\n\tconst triageOutput = queuesHub.topic<TriagedItem>(TOPIC_TRIAGE_OUTPUT);\n\tconst retryTopic = queuesHub.topic<TriagedItem>(TOPIC_RETRY);\n\tconst verifyResults = queuesHub.topic<VerifyResult<A>>(TOPIC_VERIFY_RESULTS);\n\tconst queueTopics = new Map<QueueRoute, TopicGraph<TriagedItem>>();\n\tfor (const route of QUEUE_NAMES) {\n\t\tqueueTopics.set(route, queuesHub.topic<TriagedItem>(route));\n\t}\n\tconst unroutedTopic = queuesHub.topic<TriagedItem>(TOPIC_UNROUTED);\n\n\t// --- Strategy model (used by triage + dispatch) ---\n\tconst strategy = strategyModel();\n\n\t// --- Stage 2: TRIAGE ---\n\t// triageInput pairs intake.latest (trigger) with strategy.entries\n\t// (advisory, sampled via withLatestFrom). Breaks the feedback cycle\n\t// (verify → strategy.record → strategy.entries would otherwise re-fire\n\t// triage on every recorded outcome).\n\tconst triageInput = withLatestFrom(\n\t\tintake.latest as Node<unknown>,\n\t\tstrategy.entries as Node<unknown>,\n\t);\n\n\tconst triagePromptFn = resolvePromptFn<readonly [IntakeItem, StrategySnapshot]>(\n\t\topts.triagePrompt,\n\t\tDEFAULT_TRIAGE_PROMPT,\n\t\t(tpl, pair) => {\n\t\t\tconst [item, strat] = pair;\n\t\t\treturn tpl\n\t\t\t\t.replace(\"{{strategy}}\", JSON.stringify(Array.from(strat.entries())))\n\t\t\t\t.replace(\"{{item}}\", JSON.stringify(item));\n\t\t},\n\t);\n\n\tconst triageNode = promptNode<TriagedItem>(\n\t\tadapter as LLMAdapter,\n\t\t[triageInput as Node<unknown>],\n\t\t(pair: unknown) => {\n\t\t\t// `intake.latest` is now SENTINEL on empty (COMPOSITION-GUIDE §1a),\n\t\t\t// so the `withLatestFrom partial:false` gate holds the fn until both\n\t\t\t// deps deliver real DATA. The `=== undefined` guard catches the\n\t\t\t// edge where the pair itself is unset (defensive — shouldn't fire\n\t\t\t// in normal flow).\n\t\t\tconst asPair = pair as readonly [IntakeItem, StrategySnapshot] | undefined;\n\t\t\tif (asPair === undefined) return \"\";\n\t\t\treturn triagePromptFn(asPair);\n\t\t},\n\t\t{\n\t\t\tname: \"triage\",\n\t\t\tformat: \"json\",\n\t\t},\n\t);\n\n\t// --- Stage 3: QUEUE (hub routing) ---\n\t//\n\t// Router is a thin effect that publishes the merged TriagedItem to\n\t// `triage-output`. `topicBridge`s fan it out to per-route queues by\n\t// filtering on `item.route`. Unknown routes flow into `__unrouted` so\n\t// misclassified items become a subscribable dead-letter signal.\n\tconst routerInput = withLatestFrom(triageNode as Node<unknown>, triageInput as Node<unknown>);\n\tconst router = node(\n\t\t[routerInput 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 pair = data[0];\n\t\t\tif (pair == null) return;\n\t\t\tconst [classification, triagePair] = pair as [\n\t\t\t\tTriagedItem | null,\n\t\t\t\t[IntakeItem | null, StrategySnapshot] | null,\n\t\t\t];\n\t\t\tif (!classification?.route) return;\n\t\t\tconst intakeItem = triagePair?.[0];\n\t\t\t// Intake fields win over classification: the LLM only owns the five\n\t\t\t// triage-classification fields (rootCause, intervention, route,\n\t\t\t// priority, triageReasoning); any intake state it accidentally\n\t\t\t// returns is overwritten by the real intake value via the trailing\n\t\t\t// spread.\n\t\t\tconst merged: TriagedItem = { ...classification, ...intakeItem } as TriagedItem;\n\t\t\ttriageOutput.publish(merged);\n\t\t},\n\t\t{ describeKind: \"effect\" },\n\t);\n\tconst routerUnsub = router.subscribe(() => {});\n\n\t// TopicBridges fan triage-output into per-route queues (visible edges).\n\tconst knownRoutes = new Set<string>(QUEUE_NAMES);\n\tfor (const route of QUEUE_NAMES) {\n\t\ttopicBridge<TriagedItem>(`bridge/${route}`, triageOutput, queueTopics.get(route)!, {\n\t\t\tmap: (item) => (item.route === route ? item : undefined),\n\t\t});\n\t}\n\ttopicBridge<TriagedItem>(\"bridge/__unrouted\", triageOutput, unroutedTopic, {\n\t\tmap: (item) => (knownRoutes.has(item.route) ? undefined : item),\n\t});\n\n\t// --- Per-route audit JobQueueGraphs (parallel ledger) ---\n\t//\n\t// One jobQueue per route mirrors the route topic's publishes so\n\t// dashboards get a subscribable `depth` / `pending` / `jobs` view of\n\t// in-progress items. Identity is established at enqueue time (the\n\t// returned `id` is paired with `trackingKey(item)`); the dispatch\n\t// effect calls `JobQueueGraph.removeById(id)` on terminal verdict.\n\t//\n\t// This audit ledger runs in parallel with the `executeFlow` JobFlow\n\t// (Tier 6.5 C2). The two are complementary:\n\t// - This ledger gives **per-route** depth/pending observables\n\t// (\"how backed up is auto-fix?\").\n\t// - executeFlow gives **per-stage** depth/pending observables\n\t// (\"how many items are mid-execute?\").\n\t//\n\t// **Retry handling.** Retry items republished to `retryTopic` flow\n\t// into executeFlow (via the enqueue effect) but NOT into per-route\n\t// audit jq's (retryTopic isn't mirrored). The audit job stays alive\n\t// across retries — only terminal (verified / structural) decisions\n\t// remove it. `depth` reflects \"items still being worked on\".\n\t//\n\t// **Ring-buffer safety.** WeakSet keyed on item identity; once the\n\t// topic's ring buffer trims the head, dropped entries become\n\t// unreachable and the WeakSet auto-prunes.\n\tconst jobQueues = new Map<QueueRoute, JobQueueGraph<TriagedItem>>();\n\tconst routeJobIds = new Map<string, { route: QueueRoute; id: string }>();\n\tfor (const route of QUEUE_NAMES) {\n\t\tjobQueues.set(route, jobQueue<TriagedItem>(`jobs/${route}`));\n\t}\n\tconst jobMirrorUnsubs: Array<() => void> = [];\n\tfor (const route of QUEUE_NAMES) {\n\t\tconst topic = queueTopics.get(route)!;\n\t\tconst jq = jobQueues.get(route)!;\n\t\tconst seen = new WeakSet<object>();\n\t\tconst mirror = node(\n\t\t\t[topic.events as Node<unknown>],\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 events = data[0];\n\t\t\t\tconst arr = (events ?? []) as readonly TriagedItem[];\n\t\t\t\tfor (const item of arr) {\n\t\t\t\t\tif (seen.has(item as unknown as object)) continue;\n\t\t\t\t\tseen.add(item as unknown as object);\n\t\t\t\t\tconst id = jq.enqueue(item);\n\t\t\t\t\trouteJobIds.set(trackingKey(item), { route, id });\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ name: `jobs/${route}-mirror`, describeKind: \"effect\" },\n\t\t);\n\t\tjobMirrorUnsubs.push(mirror.subscribe(() => {}));\n\t}\n\n\tfunction ackJob(item: TriagedItem): void {\n\t\tconst key = trackingKey(item);\n\t\tconst entry = routeJobIds.get(key);\n\t\tif (!entry) return;\n\t\tjobQueues.get(entry.route)?.removeById(entry.id);\n\t\trouteJobIds.delete(key);\n\t}\n\n\t// --- Stage 4: GATE ---\n\t//\n\t// Per-route gates between `topic.latest` and the executeFlow enqueue.\n\t// Foreign-node-accept (Session B.1): pass `topic.latest` directly; the\n\t// gate factory auto-adds the source under `${name}/source` inside its\n\t// own graph if not already registered.\n\tconst gateGraph = pipelineGraph(\"gates\");\n\tconst gateControllers = new Map<QueueRoute, GateController<TriagedItem>>();\n\tfor (const route of QUEUE_NAMES) {\n\t\tconst config = queueConfigs.get(route)!;\n\t\tif (!config.gated) continue;\n\t\tconst topic = queueTopics.get(route)!;\n\t\tconst ctrl = gateGraph.approvalGate<TriagedItem>(\n\t\t\t`${route}/gate`,\n\t\t\ttopic.latest as Node<unknown>,\n\t\t\t{\n\t\t\t\tmaxPending: config.maxPending,\n\t\t\t\tstartOpen: config.startOpen,\n\t\t\t},\n\t\t);\n\t\tgateControllers.set(route, ctrl);\n\t}\n\n\t// --- executeInput: merge of post-gate route latests + retry feedback ---\n\t// All inputs are SENTINEL until first DATA (COMPOSITION-GUIDE §1a): topic\n\t// `latest` returns `[]` on empty, gate `output` doesn't push pre-DATA.\n\tconst queueOutputs: Node<TriagedItem>[] = [];\n\tfor (const route of QUEUE_NAMES) {\n\t\tconst config = queueConfigs.get(route)!;\n\t\tif (config.gated && gateControllers.has(route)) {\n\t\t\tqueueOutputs.push(gateControllers.get(route)!.output as Node<TriagedItem>);\n\t\t} else {\n\t\t\tqueueOutputs.push(queueTopics.get(route)!.latest);\n\t\t}\n\t}\n\tqueueOutputs.push(retryTopic.latest);\n\n\tconst executeInput = merge<TriagedItem>(...queueOutputs);\n\n\t// --- Stages 5+6: EXECUTE → VERIFY via JobFlow (Tier 6.5 C2) ---\n\tconst executor: HarnessExecutor<A> =\n\t\topts.executor ?? defaultLlmExecutor<A>(adapter as LLMAdapter, opts.executePrompt);\n\tconst verifier: HarnessVerifier<A> =\n\t\topts.verifier ?? defaultLlmVerifier<A>(adapter as LLMAdapter, opts.verifyPrompt);\n\n\t// Per-stage `maxPerPump` caps via the JobFlow `StageDef.maxPerPump`\n\t// extension (Tier 6.5 D1 follow-up). Each stage gets its own cap;\n\t// callers can pin execute at a low concurrency for cost control while\n\t// leaving verify unbounded (or vice versa). Defaults to\n\t// `Number.MAX_SAFE_INTEGER` per stage — matches today's unbounded\n\t// `merge()` parallelism.\n\tconst executeMaxPerPump = opts.executeMaxPerPump ?? Number.MAX_SAFE_INTEGER;\n\tconst verifyMaxPerPump = opts.verifyMaxPerPump ?? Number.MAX_SAFE_INTEGER;\n\n\tconst executeFlow = jobFlow<HarnessJobPayload<A>>(`${name}/executeFlow`, {\n\t\tstages: [\n\t\t\t{ name: \"execute\", work: (job) => executor(job), maxPerPump: executeMaxPerPump },\n\t\t\t{ name: \"verify\", work: (job) => verifier(job), maxPerPump: verifyMaxPerPump },\n\t\t],\n\t});\n\n\t// Enqueue effect: per-item bridge from the reactive `executeInput`\n\t// stream into the JobFlow. Each non-null item becomes one JobEnvelope\n\t// at the execute stage. Retry items (via `retryTopic`) re-enter the\n\t// flow as fresh enqueues with their `$retries` counter bumped.\n\tconst enqueueEffect = node(\n\t\t[executeInput 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\texecuteFlow.enqueue({ item: item as TriagedItem });\n\t\t},\n\t\t{ name: \"execute-enqueue\", describeKind: \"effect\" },\n\t);\n\tconst enqueueUnsub = enqueueEffect.subscribe(() => {});\n\n\t// --- Stage 7: dispatch effect (REFLECT + retry/structural routing) ---\n\t//\n\t// Replaces the pre-Tier-6.5 `fastRetry` effect. Reads completed\n\t// JobEnvelopes from `executeFlow.completed`, identifies new ones via\n\t// WeakSet, and dispatches the 3-way verdict:\n\t//\n\t// 1. **Verified** → record success, publish VerifyResult, ack audit job.\n\t// 2. **Self-correctable + retries available** → republish to retryTopic\n\t// with $retries bumped (no audit ack — retry stays in the audit ledger).\n\t// 3. **Structural / retries exhausted** → record failure, publish\n\t// VerifyResult, ack audit job, reingest if reingestion budget remains.\n\t//\n\t// Imperative cross-graph publish from inside an effect is sanctioned\n\t// per COMPOSITION-GUIDE §32 / §35 for terminal side-effects with audit\n\t// trails (here: verifyResults / retry / intake topics).\n\tconst maxReingestions = opts.maxReingestions ?? 1;\n\tconst maxTotalRetries = Math.min(opts.maxTotalRetries ?? maxRetries * 10, 100);\n\tconst maxTotalReingestions = Math.min(opts.maxTotalReingestions ?? maxReingestions * 10, 100);\n\tconst totalRetries = node([], { initial: 0 });\n\tconst totalReingestions = node([], { initial: 0 });\n\n\tfunction assembleResult(\n\t\texecution: ExecutionResult<A>,\n\t\tverify: VerifyOutput,\n\t\titem: TriagedItem,\n\t): VerifyResult<A> {\n\t\treturn {\n\t\t\titem,\n\t\t\texecution,\n\t\t\tverified: verify.verified,\n\t\t\tfindings: verify.findings ?? [],\n\t\t\terrorClass: verify.errorClass,\n\t\t};\n\t}\n\n\tfunction handleVerified(vr: VerifyResult<A>, item: TriagedItem): void {\n\t\tstrategy.record(strategyKey(DEFAULT_PRESET_ID, item.rootCause, item.intervention), true, {\n\t\t\tpresetId: DEFAULT_PRESET_ID,\n\t\t\trootCause: item.rootCause,\n\t\t\tintervention: item.intervention,\n\t\t});\n\t\tverifyResults.publish(vr);\n\t\tackJob(item);\n\t}\n\n\tfunction handleRetry(vr: VerifyResult<A>, item: TriagedItem): void {\n\t\tconst key = trackingKey(item);\n\t\tconst itemRetries = item.$retries ?? 0;\n\t\tconst retryItem: TriagedItem = {\n\t\t\t...item,\n\t\t\t$retries: itemRetries + 1,\n\t\t\tsummary: `[RETRY ${itemRetries + 1}/${maxRetries}] ${key} — Previous attempt failed: ${vr.findings.join(\"; \")}`,\n\t\t\trelatedTo: [key],\n\t\t};\n\t\tretryTopic.publish(retryItem);\n\t\t// Audit job stays alive across retries — only terminal (verified /\n\t\t// structural) decisions remove it.\n\t}\n\n\tfunction handleStructural(vr: VerifyResult<A>, item: TriagedItem): void {\n\t\tstrategy.record(strategyKey(DEFAULT_PRESET_ID, item.rootCause, item.intervention), false, {\n\t\t\tpresetId: DEFAULT_PRESET_ID,\n\t\t\trootCause: item.rootCause,\n\t\t\tintervention: item.intervention,\n\t\t});\n\t\tverifyResults.publish(vr);\n\t\tackJob(item);\n\t\tconst key = trackingKey(item);\n\t\tconst itemReingestions = item.$reingestions ?? 0;\n\t\tif (\n\t\t\titemReingestions < maxReingestions &&\n\t\t\ttryIncrementBounded(totalReingestions, maxTotalReingestions)\n\t\t) {\n\t\t\tintake.publish({\n\t\t\t\tsource: item.source,\n\t\t\t\tsummary: `Verification failed for: ${key}`,\n\t\t\t\tevidence: vr.findings.join(\"\\n\"),\n\t\t\t\taffectsAreas: item.affectsAreas,\n\t\t\t\taffectsEvalTasks: item.affectsEvalTasks,\n\t\t\t\tseverity: item.severity ?? \"high\",\n\t\t\t\trelatedTo: [key],\n\t\t\t\t$reingestions: itemReingestions + 1,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Monotonic length cursor (qa F4) — `executeFlow.completed` retains up to\n\t// `DEFAULT_COMPLETED_RETAINED_LIMIT` (1024) entries; each new completion\n\t// emits a fresh snapshot containing every retained job. A naive\n\t// `WeakSet.has` walk is O(retainedLimit) per emit. Track the last-seen\n\t// length and only iterate the new tail. The cursor is capped at the\n\t// snapshot length to handle ring-buffer trims (when the retained log\n\t// drops oldest entries past the limit, `arr.length` shrinks and the\n\t// cursor catches up automatically).\n\tlet dispatchCursor = 0;\n\tconst dispatchEffect = node(\n\t\t[executeFlow.completed 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 log = data[0];\n\t\t\tconst arr = (log ?? []) as readonly JobEnvelope<HarnessJobPayload<A>>[];\n\t\t\t// Trim handling: if the retained log shrunk below our cursor, the\n\t\t\t// missing entries are gone (we already processed them or the trim\n\t\t\t// happened mid-flight); just clamp.\n\t\t\tif (dispatchCursor > arr.length) dispatchCursor = arr.length;\n\t\t\tconst start = dispatchCursor;\n\t\t\tdispatchCursor = arr.length;\n\t\t\tfor (let i = start; i < arr.length; i++) {\n\t\t\t\tconst job = arr[i] as JobEnvelope<HarnessJobPayload<A>>;\n\t\t\t\tconst { item, execution, verify } = job.payload;\n\t\t\t\t// Defensive — both should always be present in a verify-stage\n\t\t\t\t// completion. If either is missing, log via verifyResults so the\n\t\t\t\t// failure is observable but don't block the dispatch effect.\n\t\t\t\tif (execution == null || verify == null) {\n\t\t\t\t\tackJob(item);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst vr = assembleResult(execution, verify, item);\n\t\t\t\tif (vr.verified) {\n\t\t\t\t\thandleVerified(vr, item);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst errClass =\n\t\t\t\t\tvr.errorClass ??\n\t\t\t\t\terrorClassifier({\n\t\t\t\t\t\titem,\n\t\t\t\t\t\toutcome: execution.outcome,\n\t\t\t\t\t\tdetail: vr.findings.join(\"; \"),\n\t\t\t\t\t});\n\t\t\t\tconst itemRetries = item.$retries ?? 0;\n\t\t\t\tif (\n\t\t\t\t\terrClass === \"self-correctable\" &&\n\t\t\t\t\titemRetries < maxRetries &&\n\t\t\t\t\ttryIncrementBounded(totalRetries, maxTotalRetries)\n\t\t\t\t) {\n\t\t\t\t\thandleRetry(vr, item);\n\t\t\t\t} else {\n\t\t\t\t\thandleStructural(vr, item);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{ name: \"verify-dispatch\", describeKind: \"effect\" },\n\t);\n\tconst dispatchUnsub = dispatchEffect.subscribe(() => {});\n\n\t// REFLECT — topology marker derived from completed-log emissions.\n\t// `equals: () => false` disables Object.is absorption so each\n\t// completion produces an observable REFLECT tick (one per verify\n\t// wave). Without this, `null === null` would collapse every emit\n\t// after the first into RESOLVED and the trace would show a single\n\t// REFLECT event over the whole run.\n\tconst reflectNode = node(\n\t\t[executeFlow.completed as Node<unknown>],\n\t\t(_batchData, actions) => {\n\t\t\tactions.emit(null);\n\t\t},\n\t\t{\n\t\t\tname: \"reflect\",\n\t\t\tequals: () => false,\n\t\t},\n\t);\n\n\t// --- Optional priority scoring (Unit 19) ---\n\tlet priorityScores: Map<QueueRoute, Node<number>> | undefined;\n\tif (opts.priority) {\n\t\tpriorityScores = buildPriorityScores(queueTopics, strategy, opts);\n\t}\n\n\t// --- Assemble HarnessGraph ---\n\tconst harness = new HarnessGraph<A>(\n\t\tname,\n\t\tqueuesHub,\n\t\texecuteFlow,\n\t\tqueueTopics,\n\t\tjobQueues,\n\t\tgateControllers,\n\t\tstrategy,\n\t\ttotalRetries,\n\t\ttotalReingestions,\n\t\treflectNode as Node<null>,\n\t\tpriorityScores,\n\t);\n\n\t// Register disposers for unregistered internal nodes.\n\tharness.addDisposer(routerUnsub);\n\tharness.addDisposer(enqueueUnsub);\n\tharness.addDisposer(dispatchUnsub);\n\t// Strategy is mounted as a child subgraph below; its disposal cascades\n\t// via the mount lifecycle (no separate `addDisposer(strategy.dispose)`\n\t// needed post Class B audit Alt E migration).\n\tfor (const unsub of jobMirrorUnsubs) harness.addDisposer(unsub);\n\n\t// Register stage nodes for introspection (harnessTrace, describe,\n\t// observe). Tier 6.3: triage-input + router-input named so\n\t// `explain(intake.latest, reflect)` walks named nodes end-to-end with\n\t// no `<anonymous>` entries.\n\tharness.add(triageInput as Node<unknown>, { name: \"triage-input\" });\n\tharness.add(triageNode as Node<unknown>, { name: \"triage\" });\n\tharness.add(routerInput as Node<unknown>, { name: \"router-input\" });\n\tharness.add(executeInput as Node<unknown>, { name: \"execute-input\" });\n\tharness.add(enqueueEffect as Node<unknown>, { name: \"execute-enqueue\" });\n\tharness.add(dispatchEffect as Node<unknown>, { name: \"verify-dispatch\" });\n\tharness.add(reflectNode as Node<unknown>, { name: \"reflect\" });\n\t// Reflect is a topology marker — subscribe so its fn registers as a\n\t// reactive edge visible in `describe()` / `explain()` immediately on\n\t// harness construction.\n\tharness.addDisposer(reflectNode.subscribe(() => undefined));\n\tif (priorityScores) {\n\t\tfor (const [route, score] of priorityScores) {\n\t\t\tharness.add(score as Node<unknown>, { name: `priority/${route}` });\n\t\t\tharness.addDisposer(score.subscribe(() => {}));\n\t\t}\n\t}\n\n\t// Mount subgraphs\n\tharness.mount(\"queues\", queuesHub);\n\tharness.mount(\"gates\", gateGraph);\n\tharness.mount(\"executeFlow\", executeFlow);\n\tharness.mount(\"strategy\", strategy);\n\tfor (const [route, jq] of jobQueues) {\n\t\tharness.mount(`jobs/${route}`, jq);\n\t}\n\n\t// Tier 1.5.3 Phase 2.5 (DG1=B): tag the Graph with its constructing\n\t// factory so `describe()` exposes provenance.\n\tharness.tagFactory(\"harnessLoop\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\n\treturn harness;\n}\n\n// ---------------------------------------------------------------------------\n// Priority scoring wiring (Unit 19 decision 2)\n// ---------------------------------------------------------------------------\n\nfunction buildPriorityScores<A>(\n\tqueueTopics: Map<QueueRoute, TopicGraph<TriagedItem>>,\n\tstrategy: StrategyModelGraph,\n\topts: HarnessLoopOptions<A>,\n): Map<QueueRoute, Node<number>> {\n\tif (!opts.lastInteractionNs) {\n\t\tthrow new Error(\n\t\t\t\"harnessLoop: `opts.priority` requires `opts.lastInteractionNs` — pass a Node<number> (e.g. `fromTimer(60_000)` or a `state(monotonicNs())` you bump on human interaction). Priority scores only decay when this node settles; an internal default would freeze age at construction time.\",\n\t\t);\n\t}\n\tconst lastInteractionNs = opts.lastInteractionNs;\n\tconst signals = opts.priority ?? {};\n\tconst severityWeights = {\n\t\t...DEFAULT_SEVERITY_WEIGHTS,\n\t\t...signals.severityWeights,\n\t} as Record<string, number>;\n\tconst decayRate = signals.decayRate ?? DEFAULT_DECAY_RATE;\n\tconst effectivenessThreshold = signals.effectivenessThreshold ?? 0.7;\n\tconst effectivenessBoost = signals.effectivenessBoost ?? 15;\n\n\tconst scores = new Map<QueueRoute, Node<number>>();\n\tfor (const [route, topic] of queueTopics) {\n\t\tconst score = node<number>(\n\t\t\t[\n\t\t\t\ttopic.latest as Node<unknown>,\n\t\t\t\tstrategy.entries as Node<unknown>,\n\t\t\t\tlastInteractionNs as Node<unknown>,\n\t\t\t],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst vals = 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 item = vals[0] as TriagedItem | undefined;\n\t\t\t\tif (item === undefined) {\n\t\t\t\t\tactions.emit(0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst baseWeight = severityWeights[item.severity ?? \"medium\"] ?? 40;\n\t\t\t\tconst ageSeconds = (monotonicNs() - (vals[2] as number)) / 1e9;\n\t\t\t\tlet s = baseWeight * Math.exp(-decayRate * Math.max(0, ageSeconds));\n\t\t\t\tconst key = strategyKey(DEFAULT_PRESET_ID, item.rootCause, item.intervention);\n\t\t\t\tconst strat = vals[1] as ReadonlyMap<string, { successRate: number }>;\n\t\t\t\tconst entry = strat?.get(key);\n\t\t\t\tif (entry && entry.successRate >= effectivenessThreshold) {\n\t\t\t\t\ts += effectivenessBoost;\n\t\t\t\t}\n\t\t\t\tactions.emit(s);\n\t\t\t},\n\t\t\t{ name: `priority/${route}`, describeKind: \"derived\" },\n\t\t);\n\t\tscores.set(route, score);\n\t}\n\treturn scores;\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 * 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 * 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 * 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 * Harness-domain internal helpers.\n *\n * trackingKey extracted from patterns/_internal/index.ts during cleave A2.\n * Destination decided per STOP #1 resolution: harness-domain shape,\n * used only by utils/harness/types.ts and presets/harness/harness-loop.ts.\n */\n\n// trackingKey\n// ---------------------------------------------------------------------------\n\n/**\n * Stable tracking key for an item with retry/reingestion decoration.\n *\n * Uses `relatedTo[0]` if present (carries the original key forward through\n * retries and reingestions). Falls back to `summary` for first-time items.\n *\n * This avoids deriving keys from mutated summary strings — retries decorate\n * the summary with `[RETRY N/M]` and failure context, so regex-stripping\n * would be fragile and any new decoration pattern would risk infinite loops\n * by generating novel keys.\n *\n * **Caller contract — uniqueness (qa D1, 2026-04-29).** Two distinct intake\n * items sharing the same `summary` (and neither carrying `relatedTo`)\n * produce the SAME tracking key. The harness's `routeJobIds` map is keyed\n * by this value: a duplicate-key publish overwrites the prior mapping, and\n * a later `ackJob` for the original publish acks the wrong audit job.\n * Single-threaded JS makes the typical structural-failure path safe (the\n * ack runs before reingest publishes), but multi-publisher concurrency or\n * batched intake of two items with identical summaries can race.\n *\n * **Caller responsibility:** ensure `summary` uniqueness OR carry an\n * explicit stable id via `relatedTo[0]` for items that may collide. For\n * retry/reingestion paths the `relatedTo` array MUST start with the\n * original tracking key — `[originalKey, ...]` — so the carried-forward\n * identity matches the audit log entry created at first publish.\n *\n * @internal\n */\nexport function trackingKey(item: { summary: string; relatedTo?: string[] }): string {\n\treturn item.relatedTo?.[0] ?? item.summary;\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 * 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 * refineLoop — universal prompt/artifact optimization loop as a reactive Graph.\n *\n * Roadmap §9.8 (Wave 2.5). The loop is a 4-topic reactive pipeline:\n *\n * iterationTrigger ──▶ GENERATE ──▶ EVALUATE ──▶ ANALYZE ──▶ DECIDE\n * │ │\n * └─────── feedback + trigger ◀─────┘\n *\n * Each stage is a `TopicGraph` so dispatches stay O(1) per subscriber (cursor-\n * based) and every iteration is observable, replayable, and checkpointable.\n *\n * Composition invariants (from COMPOSITION-GUIDE):\n * - §7 feedback cycle: only `iterationTrigger` drives re-generation. Strategy\n * + feedback + dataset are read via closure updaters (§28 factory-time seed)\n * so mid-run swaps apply to the NEXT iteration, never retrigger the current.\n * - §28 factory-time seed: strategy, lastFeedback, prevCandidates, dataset\n * closures captured at wiring time + updated via subscribe handlers so the\n * first activation doesn't drop the initial pair.\n * - §32 nested-drain state-mirror: the decide-effect writes `lastFeedback`\n * BEFORE bumping `iterationTrigger` inside its `batch()`, guaranteeing the\n * mirror is current when the next-iteration wave reaches the generate fn.\n * - §19 terminal-emission: history / best emit once per iteration (settled),\n * not on every intermediate wave.\n * - §27 attachSnapshotStorage: the whole graph is checkpointable — pause overnight,\n * resume tomorrow from the exact iteration count, candidate set, strategy.\n *\n * Scope clamp (v1): core factory + `RefineStrategy<T>` + `blindVariation` and\n * `errorCritique` built-ins + budget gating + checkpoint/resume.\n * `mutateAndRefine` / registry / `autoSelectStrategy` / `optimizeCatalog` /\n * `refineExecutor` are deferred.\n *\n * @module\n */\n\n// `createNode` is the local alias for `node` so calls don't shadow\n// `Graph.prototype.node` when the file's body inadvertently references the\n// graph's `.node()` method. B5f keeps protocol-primitive construction visually\n// distinct from graph-instance method dispatch.\nimport {\n\tbatch,\n\tnode as createNode,\n\tDATA,\n\tERROR,\n\tmonotonicNs,\n\ttype Node,\n\tplaceholderArgs,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport type { NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { switchMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { tryIncrementBounded } from \"../../base/mutation/index.js\";\nimport { messagingHub, type TopicGraph } from \"../../utils/messaging/index.js\";\n\n// ---------------------------------------------------------------------------\n// Core types\n// ---------------------------------------------------------------------------\n\n/** A single task row — the unit the evaluator scores one candidate against. */\nexport interface DatasetItem {\n\treadonly id: string;\n\treadonly [k: string]: unknown;\n}\n\n/**\n * One candidate's score on one task. Higher is better by convention.\n *\n * Set `candidateIndex` when the evaluator fans out scores across multiple\n * candidates (e.g. `candidates × tasks`). `pickBest` aggregates mean scores\n * per `candidateIndex` when present; when absent, falls back to positional\n * alignment (`scores[i]` ↔ `candidates[i]`).\n */\nexport interface EvalResult {\n\treadonly taskId: string;\n\treadonly score: number;\n\treadonly error?: string;\n\treadonly detail?: unknown;\n\t/** 0-based index into the `candidates` batch this score belongs to. */\n\treadonly candidateIndex?: number;\n}\n\n/** Aggregated feedback the strategy produces from a scores batch. */\nexport interface Feedback {\n\treadonly summary: string;\n\treadonly critique?: unknown;\n\treadonly weakTasks?: readonly string[];\n\treadonly score: number;\n}\n\n/**\n * Strategy interface — plain object, no base class. Strategies implement three\n * pure hooks; the loop infrastructure wraps them in reactive nodes so every\n * decision is visible in `describe()`.\n *\n * `generate` may be sync or async. Async generates yield a microtask per\n * iteration — that's what gives `pause()` / `setStrategy()` a window to\n * interleave. **A fully synchronous `generate` will drain the entire loop\n * during factory activation** (all iterations run before `refineLoop()`\n * returns), which is usually not what you want for observable, steerable\n * loops. Real strategies that call LLMs / evals are async and Just Work;\n * custom sync strategies for tests are fine but should be marked `async`\n * to match real cadence.\n */\nexport interface RefineStrategy<T> {\n\treadonly name: string;\n\t/** Produce initial candidates from the seed. Called at iteration 0. */\n\tseed(seed: T): readonly T[];\n\t/** Reduce scores to feedback. Pure function. */\n\tanalyze(scores: readonly EvalResult[], candidates: readonly T[]): Feedback;\n\t/**\n\t * Generate next-iteration candidates from feedback + prior candidates.\n\t * Async allowed — the loop awaits via `fromAny`.\n\t */\n\tgenerate(feedback: Feedback, candidates: readonly T[]): Promise<readonly T[]> | readonly T[];\n}\n\n/**\n * Evaluator shape — Shape 4 (2026-04-22): both `candidates` and `dataset` are\n * reactive nodes; the evaluator's returned node IS the EVALUATE topic's source\n * (no glue). Implementers can batch-eval (e.g. `funnel` with concurrency) or\n * map per-candidate — user's code.\n *\n * **Cancel-on-input contract (load-bearing).** Evaluators with async work\n * (LLM calls, network requests, etc.) MUST cancel any in-flight work when\n * `candidates` emits a new batch. The canonical pattern is `switchMap` over\n * `candidates`. If an evaluator does NOT cancel — e.g. naively kicks a\n * `Promise.all` per-batch and emits whatever resolves — late scores from a\n * prior iteration can arrive after the loop has already moved to the next\n * iteration (especially after `pause()` / `resume()`). Such stale scores\n * trip {@link refineLoop}'s `feedbackEnvelopeNode` with mismatched\n * `iter`/`scores`/`items`, producing an incorrect `DecideEvent` and (worse)\n * marking the iter as decided so the real iter's scores get skipped by\n * de-dup, stalling the loop. See `optimizations.md` \"refineLoop async-\n * evaluator stale-scores follow-up\" for the proposed `wrapEvaluator()`\n * helper that would enforce cancellation.\n *\n * **`EvalResult.candidateIndex` semantics.** Optional per-result field.\n * When present, multi-candidate aggregators ({@link errorCritique}'s\n * `pickBest`) score per index, picking the candidate with the highest\n * mean score. When absent across all results, those aggregators fall back\n * to positional matching against `candidates[0]` — meaning a strategy that\n * generates >1 candidate but emits unindexed scores effectively only ever\n * critiques the first candidate. Set `candidateIndex` whenever the\n * evaluator's score corresponds to a specific candidate in the batch.\n */\nexport type Evaluator<T> = (\n\tcandidates: Node<readonly T[]>,\n\tdataset: Node<readonly DatasetItem[]>,\n) => Node<readonly EvalResult[]>;\n\n// ---------------------------------------------------------------------------\n// Convergence\n// ---------------------------------------------------------------------------\n\n/**\n * Early-stop controls. Each field fans into its own derived node; the four\n * combine via `||` into `converged: Node<boolean>`. Callers see exactly\n * which rule tripped via `status` / the DECIDE topic's `reason`.\n */\nexport interface ConvergenceOptions {\n\t/** Stop when aggregate score has not improved for N iterations. */\n\tpatience?: number;\n\t/** Stop when aggregate score reaches or exceeds this. */\n\tminScore?: number;\n\t/** Stop when absolute delta between consecutive scores falls below this. */\n\tminDelta?: number;\n\t/** Stop after N total evaluations (iteration count × per-iter candidates). */\n\tmaxEvaluations?: number;\n\t/** Stop after N iterations. Always set a finite bound in production. */\n\tmaxIterations?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Topic payloads (one per stage)\n// ---------------------------------------------------------------------------\n\n/** Emitted to the GENERATE topic each time the strategy produces a batch. */\nexport interface GenerateEvent<T> {\n\treadonly iteration: number;\n\treadonly candidates: readonly T[];\n\treadonly timestamp_ns: number;\n}\n\n/** Emitted to the EVALUATE topic when scores settle for an iteration. */\nexport interface EvaluateEvent<T> {\n\treadonly iteration: number;\n\treadonly candidates: readonly T[];\n\treadonly scores: readonly EvalResult[];\n\treadonly timestamp_ns: number;\n}\n\n/** Emitted to the ANALYZE topic — strategy's reduction over scores. */\nexport interface AnalyzeEvent<T> {\n\treadonly iteration: number;\n\treadonly candidates: readonly T[];\n\treadonly feedback: Feedback;\n\treadonly timestamp_ns: number;\n}\n\n/** Emitted to the DECIDE topic — branch taken this iteration. */\nexport interface DecideEvent {\n\treadonly iteration: number;\n\treadonly decision: \"continue\" | \"converged\" | \"budget\" | \"paused\";\n\treadonly reason?: string;\n\treadonly timestamp_ns: number;\n}\n\n// ---------------------------------------------------------------------------\n// Status + history\n// ---------------------------------------------------------------------------\n\nexport type RefineStatus = \"running\" | \"converged\" | \"budget\" | \"paused\" | \"errored\";\n\n/**\n * **Internal envelope** — carries the iteration number alongside the\n * candidates batch so `iter` rides the data wave through the pipeline. Lets\n * downstream stages read iter from a real reactive edge instead of from\n * `iterationTrigger.cache` (P3 violation; see /qa D1, 2026-05-01).\n *\n * Sidecar `candidatesItemsNode = derived([candidatesNode], ([env]) => env.items)`\n * preserves the user-facing `Evaluator<T>` API (which sees `Node<readonly T[]>`).\n */\ninterface CandidatesEnvelope<T> {\n\treadonly iter: number;\n\treadonly items: readonly T[];\n}\n\n/**\n * **Internal envelope** — assembled by `feedbackEnvelopeNode` from\n * `userScoresNode` + `candidatesNode`. Carries iter + items + scores +\n * feedback together as the trigger payload for `decideEffect` (`§16` nested\n * `withLatestFrom` advisory-samples history / budget / pause). Lets\n * `decideEffect` read iter from the envelope (no `iterationTrigger.cache` read)\n * AND ensures decideEffect only fires when the user evaluator has actually\n * emitted fresh scores (gate via `batchData[scores]` length, eliminating\n * spurious decides on candidates-only fan-out waves).\n */\ninterface FeedbackEnvelope<T> {\n\treadonly iter: number;\n\treadonly items: readonly T[];\n\treadonly scores: readonly EvalResult[];\n\treadonly feedback: Feedback;\n}\n\nexport interface Iteration<T> {\n\treadonly n: number;\n\treadonly candidates: readonly T[];\n\treadonly scores: readonly EvalResult[];\n\treadonly feedback: Feedback;\n\t/** `null` iff the candidate batch for this iteration was empty. */\n\treadonly best: T | null;\n\treadonly bestScore: number;\n\treadonly timestamp_ns: number;\n}\n\n// ---------------------------------------------------------------------------\n// Factory + returned graph\n// ---------------------------------------------------------------------------\n\nexport interface RefineLoopOptions extends ConvergenceOptions {\n\t/** Reactive dataset OR a plain array (auto-wrapped into `state`). */\n\tdataset: NodeInput<readonly DatasetItem[]> | readonly DatasetItem[];\n\t/** Total teacher calls cap across iterations. Default: unlimited. */\n\tbudget?: number;\n\t/** Graph name. Default: `\"refine-loop\"`. */\n\tname?: string;\n\t/** Extra graph options forwarded to the underlying `Graph`. */\n\tgraph?: GraphOptions;\n}\n\n/**\n * `class RefineLoopGraph<T> extends Graph` — the universal prompt/artifact\n * optimization loop as a reactive Graph subclass.\n *\n * Constructed via the {@link refineLoop} factory in normal use; exported as a\n * class so consumers can `instanceof`-narrow on returned values (Phase 13.G\n * `agent(spec)` is the consumer that motivated the migration). All\n * observability tools (`describe`, `explain`, `observe`, `attachSnapshotStorage`,\n * `snapshot`) Just Work since this `extends Graph`.\n *\n * **Phase 12.D (2026-04-30):** Migrated from `Object.assign(graph, ...)` factory\n * pattern to `class extends Graph` (Tier R5.1 deferral lifted; mirrors the\n * `MemoryWith*Graph` precedent). `setStrategy` / `pause` / `resume` are now\n * instance methods that read `this.strategy` / `this._pauseState` / `this.status`\n * / `this._iteration` instead of factory-local closures.\n */\nexport class RefineLoopGraph<T> extends Graph {\n\treadonly best: Node<T | null>;\n\t/**\n\t * Best score so far. Pseudo-private (`_score`) to avoid colliding with any\n\t * future `Graph.prototype.score` method (B5d forward-compat hazard\n\t * prevention). Typed-public — read via `loop._score.cache` /\n\t * `loop._score.subscribe(...)` from external code.\n\t */\n\treadonly _score: Node<number>;\n\treadonly status: Node<RefineStatus>;\n\treadonly history: Node<readonly Iteration<T>[]>;\n\treadonly strategy: Node<RefineStrategy<T>>;\n\t/**\n\t * Monotonic iteration counter. Pseudo-private (`_iteration`) to avoid\n\t * colliding with any future `Graph.prototype.iteration` method (B5d\n\t * forward-compat hazard prevention). Typed-public — read via\n\t * `loop._iteration.cache` / `loop._iteration.subscribe(...)`.\n\t */\n\treadonly _iteration: Node<number>;\n\t/** Stage topic — subscribe for per-stage streaming / cursor consumers. */\n\treadonly generate: TopicGraph<GenerateEvent<T>>;\n\t/** Stage topic — subscribe for per-stage streaming / cursor consumers. */\n\treadonly evaluate: TopicGraph<EvaluateEvent<T>>;\n\t/** Stage topic — subscribe for per-stage streaming / cursor consumers. */\n\treadonly analyze: TopicGraph<AnalyzeEvent<T>>;\n\t/** Stage topic — subscribe for per-stage streaming / cursor consumers. */\n\treadonly decide: TopicGraph<DecideEvent>;\n\n\t/** Internal: paused-flag node. Mounted as \"paused\" in describe(). */\n\tprivate readonly _pauseState: Node<boolean>;\n\n\tconstructor(\n\t\tseed: T,\n\t\tevaluator: Evaluator<T>,\n\t\tinitialStrategy: RefineStrategy<T>,\n\t\topts: RefineLoopOptions,\n\t) {\n\t\tconst name = opts.name ?? \"refine-loop\";\n\t\tsuper(name, opts.graph);\n\n\t\t// /qa A2 (2026-04-30): tag the Graph with its constructing factory so\n\t\t// `describe()` / `compileSpec` round-trip surfaces provenance — mirrors\n\t\t// the `agentMemory` pattern. `seed` / `evaluator` / `initialStrategy`\n\t\t// and option fields are non-JSON (functions, strategies); route through\n\t\t// `placeholderArgs` (DG2=ii) which substitutes `\"<function>\"` /\n\t\t// `\"<Node>\"` / `\"<unserializable>\"` for non-JSON values.\n\t\tthis.tagFactory(\n\t\t\t\"refineLoop\",\n\t\t\tplaceholderArgs({ seed, evaluator, initialStrategy, ...opts } as unknown as Record<\n\t\t\t\tstring,\n\t\t\t\tunknown\n\t\t\t>),\n\t\t);\n\n\t\t// --- Dataset: auto-wrap arrays into a state node ------------------------\n\t\tconst datasetNode: Node<readonly DatasetItem[]> = isNode<readonly DatasetItem[]>(opts.dataset)\n\t\t\t? opts.dataset\n\t\t\t: createNode<readonly DatasetItem[]>([], {\n\t\t\t\t\tname: \"dataset\",\n\t\t\t\t\tinitial: opts.dataset as readonly DatasetItem[],\n\t\t\t\t});\n\t\tthis.add(datasetNode, { name: \"dataset\" });\n\n\t\t// --- State nodes --------------------------------------------------------\n\t\tconst iterationTrigger = createNode<number>([], { name: \"iteration\", initial: 0 });\n\t\tthis.add(iterationTrigger, { name: \"iteration\" });\n\n\t\tconst strategyNode = createNode<RefineStrategy<T>>([], {\n\t\t\tname: \"strategy\",\n\t\t\tinitial: initialStrategy,\n\t\t\tequals: () => false, // always propagate strategy swaps\n\t\t});\n\t\tthis.add(strategyNode, { name: \"strategy\" });\n\n\t\tconst lastFeedbackState = createNode<Feedback | null>([], {\n\t\t\tname: \"lastFeedback\",\n\t\t\tinitial: null,\n\t\t});\n\t\tthis.add(lastFeedbackState, { name: \"lastFeedback\" });\n\n\t\tconst prevCandidatesState = createNode<readonly T[]>([], {\n\t\t\tname: \"prevCandidates\",\n\t\t\tinitial: [],\n\t\t});\n\t\tthis.add(prevCandidatesState, { name: \"prevCandidates\" });\n\n\t\tconst pauseState = createNode<boolean>([], { name: \"paused\", initial: false });\n\t\tthis.add(pauseState, { name: \"paused\" });\n\n\t\tconst statusState = createNode<RefineStatus>([], { name: \"status\", initial: \"running\" });\n\t\tthis.add(statusState, { name: \"status\" });\n\n\t\tconst historyState = createNode<readonly Iteration<T>[]>([], {\n\t\t\tname: \"history\",\n\t\t\tinitial: [],\n\t\t\tequals: () => false, // append-style; reactive consumers want every push\n\t\t});\n\t\tthis.add(historyState, { name: \"history\" });\n\n\t\tconst bestState = createNode<T | null>([], { name: \"best\", initial: null });\n\t\tthis.add(bestState, { name: \"best\" });\n\n\t\tconst scoreState = createNode<number>([], { name: \"score\", initial: Number.NEGATIVE_INFINITY });\n\t\tthis.add(scoreState, { name: \"score\" });\n\n\t\t// --- Budget counter -----------------------------------------------------\n\t\tconst budgetState = createNode<number>([], { name: \"budget-used\", initial: 0 });\n\t\tthis.add(budgetState, { name: \"budget-used\" });\n\n\t\t// --- Stage hub (Shape B + C-aspects) ------------------------------------\n\t\t// One messagingHub instead of four standalone TopicGraphs. Topics are\n\t\t// eagerly created so the public accessors (loop.generate etc.) are\n\t\t// available immediately without waiting for the first event to fire.\n\t\t// The hub is mounted in this so all stage topics appear under \"stages::\"\n\t\t// in describe()/explain() — visible edges, not closure-held singletons.\n\t\tconst hub = messagingHub(\"stages\");\n\t\tthis.mount(\"stages\", hub);\n\t\tconst hubGenerateTopic = hub.topic<GenerateEvent<T>>(\"generate\");\n\t\tconst hubEvaluateTopic = hub.topic<EvaluateEvent<T>>(\"evaluate\");\n\t\tconst hubAnalyzeTopic = hub.topic<AnalyzeEvent<T>>(\"analyze\");\n\t\tconst hubDecideTopic = hub.topic<DecideEvent>(\"decide\");\n\n\t\t// /qa A1 (2026-04-30): assign the public field surface BEFORE wiring\n\t\t// any effect / subscribe activation below. A synchronous strategy can\n\t\t// drain the entire GENERATE → EVALUATE → ANALYZE → DECIDE cascade\n\t\t// during the constructor body (see strategy doc above); fields must be\n\t\t// reachable in case any future subscribe handler dereferences `this.X`\n\t\t// during that synchronous drain. Defensive — no current handler reads\n\t\t// `this.<field>`, but keeping construction-order safe avoids future\n\t\t// undefined-field crashes.\n\t\tthis.best = bestState as Node<T | null>;\n\t\tthis._score = scoreState;\n\t\tthis.status = statusState;\n\t\tthis.history = historyState;\n\t\tthis.strategy = strategyNode;\n\t\tthis._iteration = iterationTrigger;\n\t\tthis.generate = hubGenerateTopic;\n\t\tthis.evaluate = hubEvaluateTopic;\n\t\tthis.analyze = hubAnalyzeTopic;\n\t\tthis.decide = hubDecideTopic;\n\t\tthis._pauseState = pauseState;\n\n\t\t// --- Factory-time seed closures (§28) -----------------------------------\n\t\t// These mirror the reactive dep values so the generate fn can read them\n\t\t// without the multi-dep push-on-subscribe initial-pair drop. Per\n\t\t// COMPOSITION-GUIDE-PROTOCOL.md §28: \"The closure reads inside the\n\t\t// reactive fn are NOT P3 violations — they read a closure variable,\n\t\t// not a `.cache`.\" Subscribe handlers run synchronously on dep DATA,\n\t\t// so the closure mirrors are always current by the time the generate\n\t\t// fn fires for the next iter.\n\t\tlet latestStrategy: RefineStrategy<T> = initialStrategy;\n\t\tlet latestFeedback: Feedback | null = null;\n\t\tlet latestPrevCandidates: readonly T[] = [];\n\t\tthis.addDisposer(\n\t\t\tstrategyNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) if (m[0] === DATA) latestStrategy = m[1] as RefineStrategy<T>;\n\t\t\t}),\n\t\t);\n\t\tthis.addDisposer(\n\t\t\tlastFeedbackState.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) if (m[0] === DATA) latestFeedback = m[1] as Feedback | null;\n\t\t\t}),\n\t\t);\n\t\tthis.addDisposer(\n\t\t\tprevCandidatesState.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) if (m[0] === DATA) latestPrevCandidates = m[1] as readonly T[];\n\t\t\t}),\n\t\t);\n\n\t\t// --- GENERATE: iterationTrigger → candidates ----------------------------\n\t\t// switchMap cancels any in-flight generate when a new iteration fires.\n\t\t// At iteration 0, strategy.seed(seed). At iteration > 0, strategy.generate.\n\t\t//\n\t\t// Sync strategies emit in the same wave as `iterationTrigger` — no microtask\n\t\t// bridge. This eliminates the per-topic iteration race (Edge #5): all four\n\t\t// stage effects drain under one wave, so iteration numbers across\n\t\t// GENERATE / EVALUATE / ANALYZE / DECIDE are guaranteed identical.\n\t\t//\n\t\t// Async strategies still cross a Promise boundary — that's the strategy's\n\t\t// async-source contract (spec §5.10: async boundaries belong in sources).\n\t\t// Cancellation on strategy swap / pause / new iteration uses switchMap's\n\t\t// inner-node unsubscribe + a `cancelled` flag so late Promise resolutions\n\t\t// don't emit into a torn-down switchMap slot.\n\t\t//\n\t\t// **/qa D1 (2026-05-01) — envelope shape:** the inner producer emits\n\t\t// `{iter, items}` so `iter` rides the data wave through every downstream\n\t\t// stage. Eliminates the cross-node `iterationTrigger.cache` P3 violation\n\t\t// in `decideEffect` (and the resume-stall failure mode it caused). User-\n\t\t// facing evaluator API stays `Node<readonly T[]>` via the\n\t\t// `candidatesItemsNode` sidecar derived below.\n\t\tconst candidatesNode = switchMap<number, CandidatesEnvelope<T>>(\n\t\t\titerationTrigger,\n\t\t\t(iter) => {\n\t\t\t\tconst strat = latestStrategy;\n\t\t\t\tconst isSeed = iter === 0 || latestFeedback == null;\n\t\t\t\treturn createNode<CandidatesEnvelope<T>>(\n\t\t\t\t\t[],\n\t\t\t\t\t(_data, actions) => {\n\t\t\t\t\t\tlet cancelled = false;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = isSeed\n\t\t\t\t\t\t\t\t? strat.seed(seed)\n\t\t\t\t\t\t\t\t: strat.generate(latestFeedback as Feedback, latestPrevCandidates);\n\t\t\t\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\t\t\t\tresult.then(\n\t\t\t\t\t\t\t\t\t(v) => {\n\t\t\t\t\t\t\t\t\t\tif (!cancelled) actions.emit({ iter, items: v });\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t(err) => {\n\t\t\t\t\t\t\t\t\t\tif (!cancelled) actions.down([[ERROR, err]]);\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\treturn () => {\n\t\t\t\t\t\t\t\t\tcancelled = true;\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tactions.emit({ iter, items: result });\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tcancelled = true;\n\t\t\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t},\n\t\t\t\t\t{ describeKind: \"producer\" },\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ name: \"candidates\" },\n\t\t);\n\t\tthis.add(candidatesNode, { name: \"candidates\" });\n\n\t\t// User-facing items sidecar: preserves the `Evaluator<T>` API\n\t\t// (`(candidates: Node<readonly T[]>, dataset: Node<readonly DatasetItem[]>) => ...`)\n\t\t// while the internal pipeline reads iter from the envelope.\n\t\tconst candidatesItemsNode = createNode<readonly T[]>(\n\t\t\t[candidatesNode],\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 env = data[0] as CandidatesEnvelope<T> | undefined;\n\t\t\t\tif (env === undefined) {\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(env.items);\n\t\t\t},\n\t\t\t{ name: \"candidates-items\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(candidatesItemsNode, { name: \"candidates-items\" });\n\n\t\t// Error watcher — strategy throws surface as ERROR on `candidatesNode`.\n\t\t// Promote to `status = \"errored\"` so callers don't have to subscribe to\n\t\t// the error channel directly.\n\t\tconst errorWatcher = createNode(\n\t\t\t[candidatesNode],\n\t\t\t(_batchData, _actions, ctx) => {\n\t\t\t\tconst terminal = ctx.terminalDeps[0];\n\t\t\t\tif (terminal !== undefined && terminal !== true) {\n\t\t\t\t\tstatusState.emit(\"errored\");\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ name: \"error-watcher\", describeKind: \"effect\", errorWhenDepsError: false },\n\t\t);\n\t\tthis.add(errorWatcher, { name: \"error-watcher\" });\n\t\tthis.addDisposer(errorWatcher.subscribe(() => undefined));\n\n\t\t// GENERATE stage: three nodes replace one monolithic effect.\n\t\t// (1) derived computes the event payload — reactive edge visible in explain().\n\t\t// (2) publish effect routes the derived event to the hub topic.\n\t\t// (3) mirror effect keeps prevCandidatesState in sync for §28 closure reads.\n\t\t// Budget accounting stays in decideEffect (single authority).\n\t\t// /qa D1: iter + items both come from the candidates envelope — no\n\t\t// separate `iterationTrigger` dep, no cross-node cache reads.\n\t\tconst generateEventNode = createNode<GenerateEvent<T>>(\n\t\t\t[candidatesNode],\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 env = data[0] as CandidatesEnvelope<T>;\n\t\t\t\tactions.emit({\n\t\t\t\t\titeration: env.iter,\n\t\t\t\t\tcandidates: env.items,\n\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"generate-event\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(generateEventNode, { name: \"generate-event\" });\n\t\tthis.addDisposer(generateEventNode.subscribe(() => undefined));\n\n\t\tconst generatePublishEffect = createNode(\n\t\t\t[generateEventNode],\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\thubGenerateTopic.publish(data[0] as GenerateEvent<T>);\n\t\t\t},\n\t\t\t{ name: \"generate-publish\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(generatePublishEffect, { name: \"generate-publish\" });\n\t\tthis.addDisposer(generatePublishEffect.subscribe(() => undefined));\n\n\t\tconst generateMirrorEffect = createNode(\n\t\t\t[candidatesNode],\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 env = data[0] as CandidatesEnvelope<T>;\n\t\t\t\tprevCandidatesState.emit(env.items);\n\t\t\t},\n\t\t\t{ name: \"generate-mirror\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(generateMirrorEffect, { name: \"generate-mirror\" });\n\t\tthis.addDisposer(generateMirrorEffect.subscribe(() => undefined));\n\n\t\t// --- EVALUATE: candidates × dataset → scores ----------------------------\n\t\t// User evaluator sees the items sidecar (preserves `Evaluator<T>` API).\n\t\tconst scoresNode = evaluator(candidatesItemsNode, datasetNode);\n\t\tthis.add(scoresNode, { name: \"scores\" });\n\n\t\t// EVALUATE stage: derived event node + publish effect.\n\t\t// /qa D1: iter from candidates envelope; gate on `scoresFired` so a\n\t\t// candidates-only fan-out wave (e.g. async eval still in flight) does\n\t\t// NOT publish a stale evaluate event.\n\t\tconst evaluateEventNode = createNode<EvaluateEvent<T>>(\n\t\t\t[scoresNode, candidatesNode],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst scoresFired = batchData[0] != null && batchData[0].length > 0;\n\t\t\t\tif (!scoresFired) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\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 scores = data[0] as readonly EvalResult[];\n\t\t\t\tconst env = data[1] as CandidatesEnvelope<T>;\n\t\t\t\tactions.emit({\n\t\t\t\t\titeration: env.iter,\n\t\t\t\t\tcandidates: env.items,\n\t\t\t\t\tscores,\n\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"evaluate-event\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(evaluateEventNode, { name: \"evaluate-event\" });\n\t\tthis.addDisposer(evaluateEventNode.subscribe(() => undefined));\n\n\t\tconst evaluatePublishEffect = createNode(\n\t\t\t[evaluateEventNode],\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\thubEvaluateTopic.publish(data[0] as EvaluateEvent<T>);\n\t\t\t},\n\t\t\t{ name: \"evaluate-publish\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(evaluatePublishEffect, { name: \"evaluate-publish\" });\n\t\tthis.addDisposer(evaluatePublishEffect.subscribe(() => undefined));\n\n\t\t// --- ANALYZE: strategy.analyze(scores, candidates) → feedbackEnvelope ---\n\t\t// /qa D1: feedbackEnvelope is the canonical iter-tagged trigger payload\n\t\t// for the DECIDE stage. Gates on `scoresFired` so a candidates-only\n\t\t// wave (async eval not settled yet) does NOT emit stale feedback into\n\t\t// `decideEffect`. When the user evaluator emits, both deps' caches are\n\t\t// consistent (candidates envelope carries iter that matches the scores\n\t\t// the user just produced — *assuming the user evaluator cancels async\n\t\t// work on candidates change; see Evaluator<T> JSDoc contract*).\n\t\tconst feedbackEnvelopeNode = createNode<FeedbackEnvelope<T>>(\n\t\t\t[scoresNode, candidatesNode],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst scoresFired = batchData[0] != null && batchData[0].length > 0;\n\t\t\t\tif (!scoresFired) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\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 scores = data[0] as readonly EvalResult[];\n\t\t\t\tconst env = data[1] as CandidatesEnvelope<T>;\n\t\t\t\tactions.emit({\n\t\t\t\t\titer: env.iter,\n\t\t\t\t\titems: env.items,\n\t\t\t\t\tscores,\n\t\t\t\t\tfeedback: latestStrategy.analyze(scores, env.items),\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"feedback-envelope\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(feedbackEnvelopeNode, { name: \"feedback-envelope\" });\n\n\t\t// User-facing feedback projection sidecar — preserves `feedback` path\n\t\t// for observers that consume the bare `Feedback` shape via\n\t\t// `loop.observe(\"feedback\")` etc.\n\t\tconst feedbackNode = createNode<Feedback>(\n\t\t\t[feedbackEnvelopeNode],\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 fbEnv = data[0] as FeedbackEnvelope<T>;\n\t\t\t\tactions.emit(fbEnv.feedback);\n\t\t\t},\n\t\t\t{ name: \"feedback\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(feedbackNode, { name: \"feedback\" });\n\n\t\t// ANALYZE stage: derived event node + publish effect.\n\t\t// /qa D1: pull iter + items from feedbackEnvelopeNode (single source of\n\t\t// truth for the analyze beat). No cross-node cache reads.\n\t\tconst analyzeEventNode = createNode<AnalyzeEvent<T>>(\n\t\t\t[feedbackEnvelopeNode],\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 fbEnv = data[0] as FeedbackEnvelope<T>;\n\t\t\t\tactions.emit({\n\t\t\t\t\titeration: fbEnv.iter,\n\t\t\t\t\tcandidates: fbEnv.items,\n\t\t\t\t\tfeedback: fbEnv.feedback,\n\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"analyze-event\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(analyzeEventNode, { name: \"analyze-event\" });\n\t\tthis.addDisposer(analyzeEventNode.subscribe(() => undefined));\n\n\t\tconst analyzePublishEffect = createNode(\n\t\t\t[analyzeEventNode],\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\thubAnalyzeTopic.publish(data[0] as AnalyzeEvent<T>);\n\t\t\t},\n\t\t\t{ name: \"analyze-publish\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(analyzePublishEffect, { name: \"analyze-publish\" });\n\t\tthis.addDisposer(analyzePublishEffect.subscribe(() => undefined));\n\n\t\t// --- Convergence: four derived nodes fanning into one boolean -----------\n\t\tconst patienceNode = createNode<boolean>(\n\t\t\t[historyState],\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 h = data[0] as readonly Iteration<T>[];\n\t\t\t\tif (opts.patience == null || h.length <= opts.patience) {\n\t\t\t\t\tactions.emit(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// No improvement over the last `patience` iterations.\n\t\t\t\tconst lookback = h.slice(-(opts.patience + 1));\n\t\t\t\tconst baseline = lookback[0]!.bestScore;\n\t\t\t\tactions.emit(lookback.slice(1).every((i) => i.bestScore <= baseline));\n\t\t\t},\n\t\t\t{ name: \"patience-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(patienceNode, { name: \"patience-check\" });\n\n\t\tconst minScoreNode = createNode<boolean>(\n\t\t\t[scoreState],\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(opts.minScore != null && (data[0] as number) >= opts.minScore);\n\t\t\t},\n\t\t\t{ name: \"min-score-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(minScoreNode, { name: \"min-score-check\" });\n\n\t\tconst minDeltaNode = createNode<boolean>(\n\t\t\t[historyState],\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 h = data[0] as readonly Iteration<T>[];\n\t\t\t\tif (opts.minDelta == null || h.length < 2) {\n\t\t\t\t\tactions.emit(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst prev = h[h.length - 2]!.bestScore;\n\t\t\t\tconst curr = h[h.length - 1]!.bestScore;\n\t\t\t\tactions.emit(Math.abs(curr - prev) < opts.minDelta);\n\t\t\t},\n\t\t\t{ name: \"min-delta-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(minDeltaNode, { name: \"min-delta-check\" });\n\n\t\tconst maxEvalsNode = createNode<boolean>(\n\t\t\t[budgetState],\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(opts.maxEvaluations != null && (data[0] as number) >= opts.maxEvaluations);\n\t\t\t},\n\t\t\t{ name: \"max-evaluations-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(maxEvalsNode, { name: \"max-evaluations-check\" });\n\n\t\tconst maxIterNode = createNode<boolean>(\n\t\t\t[iterationTrigger],\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(opts.maxIterations != null && (data[0] as number) >= opts.maxIterations);\n\t\t\t},\n\t\t\t{ name: \"max-iterations-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(maxIterNode, { name: \"max-iterations-check\" });\n\n\t\tconst budgetExhaustedNode = createNode<boolean>(\n\t\t\t[budgetState],\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(opts.budget != null && (data[0] as number) >= opts.budget);\n\t\t\t},\n\t\t\t{ name: \"budget-exhausted-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(budgetExhaustedNode, { name: \"budget-exhausted-check\" });\n\n\t\t// Activate convergence derivations so their cache stays current — decideEffect\n\t\t// reads their cache via external-boundary reads (§28). They must NOT be direct\n\t\t// deps: that would create a feedback cycle (decideEffect writes history/score,\n\t\t// convergence derives from those, cycle).\n\t\tthis.addDisposer(patienceNode.subscribe(() => undefined));\n\t\tthis.addDisposer(minScoreNode.subscribe(() => undefined));\n\t\tthis.addDisposer(minDeltaNode.subscribe(() => undefined));\n\t\tthis.addDisposer(maxEvalsNode.subscribe(() => undefined));\n\t\tthis.addDisposer(maxIterNode.subscribe(() => undefined));\n\t\tthis.addDisposer(budgetExhaustedNode.subscribe(() => undefined));\n\n\t\tconst convergedNode = createNode<{ converged: boolean; reason?: string }>(\n\t\t\t[patienceNode, minScoreNode, minDeltaNode, maxEvalsNode, maxIterNode],\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 [p, ms, md, me, mi] = data;\n\t\t\t\tif (p) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"patience\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (ms) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"min-score\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (md) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"min-delta\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (me) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"max-evaluations\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (mi) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"max-iterations\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tactions.emit({ converged: false });\n\t\t\t},\n\t\t\t{ name: \"converged\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(convergedNode, { name: \"converged\" });\n\t\tthis.addDisposer(convergedNode.subscribe(() => undefined));\n\n\t\t// --- DECIDE: feedbackEnvelope settles → fire next iteration OR terminate ---\n\t\t// **/qa D1 (2026-05-01) — reactive form via §32 envelope + sole-owner\n\t\t// `.cache` reads + reactive `pauseState` dep.** Two patterns at play:\n\t\t//\n\t\t// - **`iter` rides with the feedbackEnvelope payload** (§32 envelope).\n\t\t// Eliminates the original `iterationTrigger.cache` cross-node read\n\t\t// that caused the resume-stall (where iter.cache was bumped past\n\t\t// the candidates batch we're processing).\n\t\t//\n\t\t// - **`historyState` / `budgetState` are read via `.cache`** as a\n\t\t// sole-owner pattern: decideEffect is the SOLE WRITER + sole\n\t\t// reactive READER, both declared in the same enclosing constructor\n\t\t// scope. Reading their `.cache` here is \"read your own scratchpad\"\n\t\t// semantically, even though they're sibling Node objects. Adding\n\t\t// them as direct deps would create the §7 self-feedback cycle\n\t\t// (decideEffect writes them, would re-trigger itself); closure\n\t\t// mirrors would just duplicate state already held in the nodes\n\t\t// themselves. The comment block belongs to /qa D1 follow-up\n\t\t// (2026-05-01) — explicit user lock that sole-owner-and-reader\n\t\t// nodes in the same enclosing scope are a sanctioned `.cache` read\n\t\t// form.\n\t\t//\n\t\t// - **`pauseState` is a direct dep** because it's an EXTERNAL CONTROL\n\t\t// INPUT — written by `pause()` / `resume()` imperative methods at\n\t\t// the user-call boundary, NOT by decideEffect. Making it a real\n\t\t// declared edge surfaces \"this decision considers pause state\" in\n\t\t// `describe()` / `explain()` topology. The `feedbackFired` gate\n\t\t// below skips fn body execution when only pauseState fired (no new\n\t\t// iteration to decide).\n\t\t//\n\t\t// Trigger semantics: feedbackEnvelopeNode itself only fires when the\n\t\t// user evaluator emits fresh scores (gate via `batchData[scoresIdx]`\n\t\t// in feedbackEnvelopeNode), so a candidates-only fan-out wave (async\n\t\t// eval still in flight after `resume()`) does NOT spuriously trigger\n\t\t// decideEffect.\n\t\t//\n\t\t// **Score-staleness contract:** if the user's `Evaluator<T>` does NOT\n\t\t// cancel its async work when `candidates` changes, late scores from a\n\t\t// prior iter can emit to scoresNode and trip feedbackEnvelopeNode +\n\t\t// decideEffect with the new candidates' iter tag but stale scores\n\t\t// data. See `Evaluator<T>` JSDoc (cancel-on-input contract) and\n\t\t// `optimizations.md` \"refineLoop async-evaluator stale-scores\n\t\t// follow-up\" for the wrapper proposal.\n\t\t//\n\t\t// Track last-decided iteration to avoid re-deciding when feedbackEnv\n\t\t// re-fires within one wave (e.g. async evaluator emits multiple\n\t\t// scores per candidates change).\n\t\tlet lastDecidedIteration = -1;\n\t\tconst decideEffect = createNode(\n\t\t\t[feedbackEnvelopeNode, pauseState],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\t// `pauseState` is declared dep #1 — gate skips fn body when\n\t\t\t\t// only pauseState fired (no new iteration to decide; we just\n\t\t\t\t// want pauseState's prevData to advance for the next feedback\n\t\t\t\t// fire).\n\t\t\t\tconst feedbackFired = batchData[0] != null && batchData[0].length > 0;\n\t\t\t\tif (!feedbackFired) return;\n\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 fbEnv = data[0] as FeedbackEnvelope<T>;\n\t\t\t\tconst paused = data[1] as boolean;\n\n\t\t\t\tconst i = fbEnv.iter;\n\t\t\t\tconst fb = fbEnv.feedback;\n\t\t\t\tconst cs = fbEnv.items;\n\t\t\t\tconst scores = fbEnv.scores;\n\n\t\t\t\t// De-dup: only run once per iteration. fn may fire multiple\n\t\t\t\t// times per wave as feedbackEnvelopeNode settles.\n\t\t\t\tif (i <= lastDecidedIteration) return;\n\t\t\t\tlastDecidedIteration = i;\n\n\t\t\t\t// Sole-owner `.cache` reads — decideEffect is the SOLE\n\t\t\t\t// writer and sole reactive reader of these state nodes.\n\t\t\t\tconst currentHistory = historyState.cache as readonly Iteration<T>[];\n\t\t\t\tconst currentBudget = budgetState.cache as number;\n\n\t\t\t\t// Compute next history / score.\n\t\t\t\tconst { best, bestScore } = pickBest(cs, scores);\n\t\t\t\tconst iteration: Iteration<T> = {\n\t\t\t\t\tn: i,\n\t\t\t\t\tcandidates: cs,\n\t\t\t\t\tscores,\n\t\t\t\t\tfeedback: fb,\n\t\t\t\t\tbest,\n\t\t\t\t\tbestScore,\n\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t};\n\t\t\t\tconst nextHistory = [...currentHistory, iteration];\n\t\t\t\t// Budget accounting — decideEffect is the single authority.\n\t\t\t\tconst nextBudget = currentBudget + cs.length;\n\n\t\t\t\t// Inline convergence checks — single source of truth. The derived\n\t\t\t\t// `convergedNode` + friends exist for describe()/observe() surface;\n\t\t\t\t// inlining here avoids a drain-round-trip deadlock where decideEffect\n\t\t\t\t// would need convergedNode.cache to update before running, but\n\t\t\t\t// convergedNode needs historyState.emit from inside decideEffect.\n\t\t\t\tlet decision: DecideEvent[\"decision\"] = \"continue\";\n\t\t\t\tlet reason: string | undefined;\n\t\t\t\tconst budgetOut = opts.budget != null && nextBudget >= opts.budget;\n\t\t\t\tif (budgetOut) {\n\t\t\t\t\tdecision = \"budget\";\n\t\t\t\t\treason = \"budget\";\n\t\t\t\t} else if (opts.minScore != null && fb.score >= opts.minScore) {\n\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\treason = \"min-score\";\n\t\t\t\t} else if (opts.maxIterations != null && i >= opts.maxIterations) {\n\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\treason = \"max-iterations\";\n\t\t\t\t} else if (opts.maxEvaluations != null && nextBudget >= opts.maxEvaluations) {\n\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\treason = \"max-evaluations\";\n\t\t\t\t} else if (opts.minDelta != null && nextHistory.length >= 2) {\n\t\t\t\t\tconst prev = nextHistory[nextHistory.length - 2]!.bestScore;\n\t\t\t\t\tconst curr = nextHistory[nextHistory.length - 1]!.bestScore;\n\t\t\t\t\tif (Math.abs(curr - prev) < opts.minDelta) {\n\t\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\t\treason = \"min-delta\";\n\t\t\t\t\t}\n\t\t\t\t} else if (opts.patience != null && nextHistory.length > opts.patience) {\n\t\t\t\t\tconst lookback = nextHistory.slice(-(opts.patience + 1));\n\t\t\t\t\tconst baseline = lookback[0]!.bestScore;\n\t\t\t\t\tif (lookback.slice(1).every((it) => it.bestScore <= baseline)) {\n\t\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\t\treason = \"patience\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// paused takes precedence over continue — if paused AND no convergence,\n\t\t\t\t// we pause. Otherwise if converged we stop for real.\n\t\t\t\tif (decision === \"continue\" && paused) {\n\t\t\t\t\tdecision = \"paused\";\n\t\t\t\t}\n\n\t\t\t\t// All emissions in one batch — drain order is feedback mirror first\n\t\t\t\t// (§32), then iterationTrigger, so the next generate sees fresh fb.\n\t\t\t\t// `lastFeedbackState` is always mirrored (regardless of decision) so\n\t\t\t\t// resume-after-pause gets current feedback; only `iterationTrigger`\n\t\t\t\t// is gated on `continue`.\n\t\t\t\tbatch(() => {\n\t\t\t\t\tbestState.emit(best);\n\t\t\t\t\tscoreState.emit(fb.score);\n\t\t\t\t\thistoryState.emit(nextHistory);\n\t\t\t\t\tbudgetState.emit(nextBudget);\n\t\t\t\t\tlastFeedbackState.emit(fb);\n\t\t\t\t\thubDecideTopic.publish({\n\t\t\t\t\t\titeration: i,\n\t\t\t\t\t\tdecision,\n\t\t\t\t\t\treason,\n\t\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t\t});\n\n\t\t\t\t\tif (decision === \"continue\") {\n\t\t\t\t\t\titerationTrigger.emit(i + 1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstatusState.emit(\n\t\t\t\t\t\t\tdecision === \"converged\" ? \"converged\" : decision === \"budget\" ? \"budget\" : \"paused\",\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: \"decide-bridge\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(decideEffect, { name: \"decide-bridge\" });\n\t\tthis.addDisposer(decideEffect.subscribe(() => undefined));\n\n\t\t// /qa A1 (2026-04-30): public field surface (best / score / status /\n\t\t// history / strategy / iteration / generate / evaluate / analyze /\n\t\t// decide / _pauseState) is assigned EARLIER, immediately after the\n\t\t// stage hub is mounted (search \"qa A1\" above). Doing the assignment\n\t\t// before any subscribe activation keeps `this.<field>` reachable\n\t\t// during a synchronous strategy drain.\n\t}\n\n\t/** Swap the active strategy mid-run (human-in-the-loop handoff). */\n\tsetStrategy(next: RefineStrategy<T>): void {\n\t\tthis.strategy.emit(next);\n\t}\n\n\t/** Pause after the current iteration completes. */\n\tpause(): void {\n\t\tthis._pauseState.emit(true);\n\t}\n\n\t/**\n\t * Resume a paused loop. Idempotent: only un-pauses from the \"paused\"\n\t * terminal state. Converged / budget / errored are permanent — a user\n\t * wanting to start over should construct a fresh refineLoop.\n\t */\n\tresume(): void {\n\t\tif (this.status.cache !== \"paused\") return;\n\t\tbatch(() => {\n\t\t\tthis._pauseState.emit(false);\n\t\t\tthis.status.emit(\"running\" as RefineStatus);\n\t\t\tthis._iteration.emit((this._iteration.cache as number) + 1);\n\t\t});\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Structural type-guard for `Node<T>`. Checks the three core Node methods\n * (`subscribe`, `down`, `emit`) as callable properties — rejects plain objects\n * with a single `subscribe` field that happen to look like a Node but aren't.\n */\nfunction isNode<T>(x: unknown): x is Node<T> {\n\tif (typeof x !== \"object\" || x === null) return false;\n\tconst obj = x as Record<string, unknown>;\n\treturn (\n\t\ttypeof obj.subscribe === \"function\" &&\n\t\ttypeof obj.down === \"function\" &&\n\t\ttypeof obj.emit === \"function\"\n\t);\n}\n\nfunction pickBest<T>(\n\tcandidates: readonly T[],\n\tscores: readonly EvalResult[],\n): { best: T | null; bestScore: number } {\n\t// Empty batch → no best. Use `null` per COMPOSITION-GUIDE §3: `undefined`\n\t// is the protocol SENTINEL, `null` is the domain sentinel for \"no value\".\n\tif (candidates.length === 0) {\n\t\treturn { best: null, bestScore: Number.NEGATIVE_INFINITY };\n\t}\n\tif (candidates.length === 1) {\n\t\tconst mean = meanScore(scores);\n\t\treturn { best: candidates[0]!, bestScore: mean };\n\t}\n\t// Fan-out aware: when any score carries `candidateIndex`, aggregate mean\n\t// score per candidate. When absent, fall back to positional `scores[i]` ↔\n\t// `candidates[i]` alignment (one-score-per-candidate convention).\n\tconst hasFanOut = scores.some((s) => typeof s.candidateIndex === \"number\");\n\tif (hasFanOut) {\n\t\tconst sums = new Array<{ sum: number; count: number }>(candidates.length);\n\t\tfor (let i = 0; i < candidates.length; i++) sums[i] = { sum: 0, count: 0 };\n\t\tfor (const s of scores) {\n\t\t\tconst idx = s.candidateIndex;\n\t\t\tif (typeof idx === \"number\" && idx >= 0 && idx < candidates.length) {\n\t\t\t\tsums[idx]!.sum += s.score;\n\t\t\t\tsums[idx]!.count += 1;\n\t\t\t}\n\t\t}\n\t\tlet best = candidates[0]!;\n\t\tlet bestScore = sums[0]!.count > 0 ? sums[0]!.sum / sums[0]!.count : Number.NEGATIVE_INFINITY;\n\t\tfor (let i = 1; i < candidates.length; i++) {\n\t\t\tconst avg = sums[i]!.count > 0 ? sums[i]!.sum / sums[i]!.count : Number.NEGATIVE_INFINITY;\n\t\t\tif (avg > bestScore) {\n\t\t\t\tbestScore = avg;\n\t\t\t\tbest = candidates[i]!;\n\t\t\t}\n\t\t}\n\t\treturn { best, bestScore };\n\t}\n\tlet best = candidates[0]!;\n\tlet bestScore = scores[0]?.score ?? Number.NEGATIVE_INFINITY;\n\tfor (let i = 1; i < candidates.length; i++) {\n\t\tconst s = scores[i]?.score ?? Number.NEGATIVE_INFINITY;\n\t\tif (s > bestScore) {\n\t\t\tbestScore = s;\n\t\t\tbest = candidates[i]!;\n\t\t}\n\t}\n\treturn { best, bestScore };\n}\n\nfunction meanScore(scores: readonly EvalResult[]): number {\n\tif (scores.length === 0) return Number.NEGATIVE_INFINITY;\n\tlet sum = 0;\n\tfor (const s of scores) sum += s.score;\n\treturn sum / scores.length;\n}\n\n// ---------------------------------------------------------------------------\n// refineLoop factory\n// ---------------------------------------------------------------------------\n\n/**\n * Construct a {@link RefineLoopGraph} — the universal prompt/artifact\n * optimization loop. Thin wrapper over `new RefineLoopGraph(...)` for\n * call-site ergonomics.\n */\nexport function refineLoop<T>(\n\tseed: T,\n\tevaluator: Evaluator<T>,\n\tinitialStrategy: RefineStrategy<T>,\n\topts: RefineLoopOptions,\n): RefineLoopGraph<T> {\n\treturn new RefineLoopGraph<T>(seed, evaluator, initialStrategy, opts);\n}\n\n// ---------------------------------------------------------------------------\n// Built-in strategy: blindVariation\n// ---------------------------------------------------------------------------\n\n/**\n * Context passed to a `blindVariation` teacher per call. `reportCost` is a\n * per-call hook — see `BlindVariationOptions.tokens`.\n */\nexport interface BlindVariationContext<T> {\n\treadonly prior: T;\n\t/**\n\t * Report tokens consumed by this teacher call. Aggregated per iteration\n\t * and flushed to `opts.tokens` in the strategy's `finally` block so\n\t * partial spend is preserved when the teacher throws mid-batch.\n\t */\n\treadonly reportCost: (tokens: number) => void;\n}\n\nexport interface BlindVariationOptions<T> {\n\t/** Name — default: `\"blindVariation\"`. */\n\tname?: string;\n\t/** Number of candidates generated per iteration. Default: 4. */\n\twidth?: number;\n\t/**\n\t * Run teacher calls in parallel via `Promise.all`. Default `true` — the\n\t * common case (independent LLM calls). Set `false` to run sequentially\n\t * via `for/await` when teachers share stateful resources (rate limiters,\n\t * rolling context, serial API ordering) that don't tolerate concurrency.\n\t */\n\tparallel?: boolean;\n\t/**\n\t * Optional cost counter node. Running total tokens reported via\n\t * `ctx.reportCost` during each iteration is added to this node in the\n\t * strategy's `finally` block — fires on success AND on teacher throw so\n\t * partial spend is never lost. User owns the node; wire to `budgetGate`,\n\t * `attachSnapshotStorage`, telemetry, etc.\n\t */\n\ttokens?: Node<number>;\n\t/**\n\t * Teacher — given `{prior, reportCost}`, produce one variant. Async\n\t * allowed. Called `width` times per iteration. Call `ctx.reportCost(n)`\n\t * to track tokens consumed per call (optional, no-op if `opts.tokens`\n\t * is not set).\n\t */\n\tteacher: (ctx: BlindVariationContext<T>) => Promise<T> | T;\n}\n\n/**\n * Simplest built-in strategy: generate N variants per iteration via the\n * supplied `teacher`; no feedback-informed steering (equivalent to Random\n * Search). Validates the loop infrastructure end-to-end and is the baseline\n * every other strategy should outperform.\n *\n * `analyze` records the mean score and flags the worst task — strategies that\n * care about per-task critique layer on top.\n */\nexport function blindVariation<T>(opts: BlindVariationOptions<T>): RefineStrategy<T> {\n\tconst width = opts.width ?? 4;\n\tconst name = opts.name ?? \"blindVariation\";\n\treturn {\n\t\tname,\n\t\tseed(seed) {\n\t\t\t// Iteration 0 emits just the seed — strategy.seed is synchronous by\n\t\t\t// contract, so we can't call an async teacher here. `width`-many\n\t\t\t// teacher-produced variants begin at iteration 1 via `generate`.\n\t\t\treturn [seed];\n\t\t},\n\t\tanalyze(scores, _candidates) {\n\t\t\tconst score = meanScore(scores);\n\t\t\tlet worst: EvalResult | null = null;\n\t\t\tfor (const s of scores) {\n\t\t\t\tif (!worst || s.score < worst.score) worst = s;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsummary: `blindVariation iteration: mean=${score.toFixed(3)}, n=${scores.length}`,\n\t\t\t\tscore,\n\t\t\t\tweakTasks: worst ? [worst.taskId] : [],\n\t\t\t};\n\t\t},\n\t\tasync generate(_feedback, candidates) {\n\t\t\tif (candidates.length === 0) {\n\t\t\t\t// Empty candidate batch is a contract violation — either the\n\t\t\t\t// seed was empty or a previous generate returned nothing. Surface\n\t\t\t\t// as an error rather than silently returning [] (which would\n\t\t\t\t// stall the loop in an infinite zero-candidate cycle).\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"blindVariation.generate: empty candidate batch — cannot derive prior for teacher\",\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Pick the current \"recent best\" — `null` IS a valid domain value\n\t\t\t// per COMPOSITION-GUIDE §3; the length guard above has already\n\t\t\t// filtered the `undefined` protocol sentinel.\n\t\t\tconst prior = candidates[candidates.length - 1] as T;\n\t\t\tlet iterCost = 0;\n\t\t\tconst reportCost = (n: number) => {\n\t\t\t\titerCost += n;\n\t\t\t};\n\t\t\tconst ctx: BlindVariationContext<T> = { prior, reportCost };\n\t\t\ttry {\n\t\t\t\tif (opts.parallel !== false) {\n\t\t\t\t\treturn await Promise.all(Array.from({ length: width }, () => opts.teacher(ctx)));\n\t\t\t\t}\n\t\t\t\tconst out: T[] = [];\n\t\t\t\tfor (let i = 0; i < width; i++) {\n\t\t\t\t\tout.push(await opts.teacher(ctx));\n\t\t\t\t}\n\t\t\t\treturn out;\n\t\t\t} finally {\n\t\t\t\tif (opts.tokens != null && iterCost > 0) {\n\t\t\t\t\t// /qa D1 follow-up (2026-05-01): replaced direct `.cache` read\n\t\t\t\t\t// + emit with `tryIncrementBounded`, which encapsulates the\n\t\t\t\t\t// self-owned-counter `.cache` access in the canonical helper\n\t\t\t\t\t// (sole sanctioned site per its JSDoc). Cap is unbounded for\n\t\t\t\t\t// the token meter.\n\t\t\t\t\ttryIncrementBounded(opts.tokens, Number.MAX_SAFE_INTEGER, iterCost);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Built-in strategy: errorCritique\n// ---------------------------------------------------------------------------\n\n/**\n * Context passed to an `errorCritique` teacher. `critique` is the pre-formatted\n * summary a prompt template can drop in verbatim; `failures` carries the\n * structured evidence (per-task error / score / detail) for richer prompts.\n */\nexport interface ErrorCritiqueContext<T> {\n\treadonly prior: T;\n\treadonly critique: string;\n\treadonly failures: readonly EvalResult[];\n\t/**\n\t * Report tokens consumed by this teacher call. Aggregated per iteration\n\t * and flushed to `opts.tokens` in the strategy's `finally` block so\n\t * partial spend is preserved when the teacher throws mid-batch.\n\t */\n\treadonly reportCost: (tokens: number) => void;\n}\n\nexport interface ErrorCritiqueOptions<T> {\n\t/** Name — default: `\"errorCritique\"`. */\n\tname?: string;\n\t/** Number of candidates generated per iteration. Default: 4. */\n\twidth?: number;\n\t/**\n\t * Cut-off below which a task is classified as a failure and fed into the\n\t * critique. Default: the batch mean — any task scoring below the batch\n\t * mean is a failure. Pass a number for an absolute cut-off, or a function\n\t * for per-batch computation (e.g. a percentile). When the default mean\n\t * is non-finite (NaN / ±Infinity from a degenerate evaluator), ALL scores\n\t * are treated as failures so the critique loop continues to steer.\n\t */\n\tfailureThreshold?: number | ((scores: readonly EvalResult[]) => number);\n\t/** Cap on failure samples packed into the critique. Default: 5. */\n\tmaxFailureSamples?: number;\n\t/**\n\t * Format failures into the `critique` string passed to the teacher. Default\n\t * joins `- taskId (score=N) | error: …` lines. Override to shape LLM prompts.\n\t *\n\t * **Note:** the `feedback` argument is a shell with `{score, weakTasks}`\n\t * populated; `summary` is empty because `analyze` computes the final summary\n\t * AFTER `formatCritique` runs (the summary embeds the formatted count).\n\t * Rely on `failures` and `feedback.score` — do not read `feedback.summary`\n\t * here.\n\t */\n\tformatCritique?: (failures: readonly EvalResult[], feedback: Feedback) => string;\n\t/**\n\t * Run teacher calls in parallel via `Promise.all`. Default `true` — the\n\t * common case (independent LLM calls). Set `false` to run sequentially\n\t * via `for/await` when teachers share stateful resources (rate limiters,\n\t * rolling context, serial API ordering) that don't tolerate concurrency.\n\t */\n\tparallel?: boolean;\n\t/**\n\t * Optional cost counter node. Running total tokens reported via\n\t * `ctx.reportCost` during each iteration is added to this node in the\n\t * strategy's `finally` block — fires on success AND on teacher throw so\n\t * partial spend is never lost. User owns the node; wire to `budgetGate`,\n\t * `attachSnapshotStorage`, telemetry, etc.\n\t */\n\ttokens?: Node<number>;\n\t/**\n\t * Teacher — given `{prior, critique, failures, reportCost}`, produce one\n\t * refined variant. Called `width` times per iteration. Async allowed.\n\t * Call `ctx.reportCost(n)` to track tokens consumed per call (optional,\n\t * no-op if `opts.tokens` is not set).\n\t */\n\tteacher: (ctx: ErrorCritiqueContext<T>) => Promise<T> | T;\n}\n\n/**\n * Private payload stashed inside `Feedback.critique` so `generate` can recover\n * the analyze-time prior + failure set without another pass over scores.\n */\ninterface ErrorCritiquePrivate<T> {\n\treadonly kind: \"errorCritique\";\n\treadonly best: T | null;\n\treadonly failures: readonly EvalResult[];\n\treadonly critiqueText: string;\n}\n\nfunction isErrorCritiquePrivate<T>(v: unknown): v is ErrorCritiquePrivate<T> {\n\treturn typeof v === \"object\" && v !== null && (v as { kind?: unknown }).kind === \"errorCritique\";\n}\n\nfunction defaultFormatCritique(failures: readonly EvalResult[], feedback: Feedback): string {\n\tif (failures.length === 0) {\n\t\treturn `No task scored below the batch mean (${feedback.score.toFixed(3)}). Reinforce the current direction.`;\n\t}\n\tconst lines = failures.map((f) => {\n\t\tconst err = f.error != null ? ` | error: ${f.error}` : \"\";\n\t\treturn `- ${f.taskId} (score=${f.score.toFixed(3)})${err}`;\n\t});\n\treturn `Failures below threshold:\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Critique-driven strategy (ProTeGi-style \"textual gradient\"). Each iteration:\n * 1. `analyze` classifies tasks scoring below a threshold as failures, picks\n * the best candidate from the batch, and packs both plus a formatted\n * critique string into `feedback.critique` as a private payload.\n * 2. `generate` unpacks that payload and calls the teacher with\n * `{prior, critique, failures, reportCost}` `width` times, returning the\n * refined batch.\n *\n * The teacher receives a pre-formatted string (drop into an LLM prompt) AND\n * the structured failure list (for richer prompts that want per-task detail).\n * Throws on empty candidate batches — matches `blindVariation`'s contract\n * (no silent zero-candidate cycles).\n *\n * When `setStrategy()` swaps this strategy in mid-run, the first `generate`\n * may receive a `Feedback` produced by the prior strategy (no private payload);\n * the fallback path uses `candidates[last]` as the prior and the feedback\n * summary as the critique, so the loop keeps running without a stall. When a\n * private payload IS present, `priv.critiqueText` takes precedence over any\n * edits a caller made to `feedback.summary` — treat `critique` as the\n * strategy-owned channel.\n */\nexport function errorCritique<T>(opts: ErrorCritiqueOptions<T>): RefineStrategy<T> {\n\tconst width = opts.width ?? 4;\n\tconst name = opts.name ?? \"errorCritique\";\n\tconst maxFailureSamples = opts.maxFailureSamples ?? 5;\n\tconst format = opts.formatCritique ?? defaultFormatCritique;\n\n\treturn {\n\t\tname,\n\t\tseed(seed) {\n\t\t\t// Iteration 0 emits just the seed. The critique loop begins at\n\t\t\t// iteration 1, once real scores exist to derive failures from.\n\t\t\treturn [seed];\n\t\t},\n\t\tanalyze(scores, candidates) {\n\t\t\tconst score = meanScore(scores);\n\t\t\tconst userThreshold =\n\t\t\t\ttypeof opts.failureThreshold === \"function\"\n\t\t\t\t\t? opts.failureThreshold(scores)\n\t\t\t\t\t: opts.failureThreshold;\n\t\t\t// A1: when the user didn't supply a threshold AND the batch-mean\n\t\t\t// default is non-finite (e.g. evaluator produced NaN / ±Infinity),\n\t\t\t// treat every score as a failure instead of filtering with `< NaN`\n\t\t\t// (which would be false for every score → silent no-op).\n\t\t\tconst thresholdUnresolvable = userThreshold === undefined && !Number.isFinite(score);\n\t\t\tconst threshold = userThreshold ?? score;\n\t\t\tconst allFailures = thresholdUnresolvable\n\t\t\t\t? [...scores].sort((a, b) => a.score - b.score)\n\t\t\t\t: scores\n\t\t\t\t\t\t.filter((s) => s.score < threshold)\n\t\t\t\t\t\t.slice()\n\t\t\t\t\t\t.sort((a, b) => a.score - b.score);\n\t\t\tconst failures = allFailures.slice(0, maxFailureSamples);\n\n\t\t\tconst { best, bestScore } = pickBest(candidates, scores);\n\t\t\tconst feedbackShell: Feedback = {\n\t\t\t\tsummary: \"\",\n\t\t\t\tscore,\n\t\t\t\tweakTasks: failures.map((f) => f.taskId),\n\t\t\t};\n\t\t\tconst critiqueText = format(failures, feedbackShell);\n\n\t\t\tconst priv: ErrorCritiquePrivate<T> = {\n\t\t\t\tkind: \"errorCritique\",\n\t\t\t\tbest,\n\t\t\t\tfailures,\n\t\t\t\tcritiqueText,\n\t\t\t};\n\t\t\tconst retainedSuffix =\n\t\t\t\tallFailures.length > failures.length ? ` (top ${failures.length} retained)` : \"\";\n\t\t\treturn {\n\t\t\t\tsummary: `errorCritique iteration: mean=${score.toFixed(3)}, failures=${allFailures.length}${retainedSuffix}/${scores.length}, bestScore=${bestScore.toFixed(3)}`,\n\t\t\t\tcritique: priv,\n\t\t\t\tweakTasks: failures.map((f) => f.taskId),\n\t\t\t\tscore,\n\t\t\t};\n\t\t},\n\t\tasync generate(feedback, candidates) {\n\t\t\t// N1: Length guard FIRST. The only protocol-sentinel risk is\n\t\t\t// `undefined` sneaking in via an empty candidates array; after\n\t\t\t// this check, `null` values (including `priv.best === null` when\n\t\t\t// T admits null) flow through as domain-valid per\n\t\t\t// COMPOSITION-GUIDE §3 / spec §1.\n\t\t\tif (candidates.length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"errorCritique.generate: empty candidate batch — cannot derive prior for teacher\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst priv = isErrorCritiquePrivate<T>(feedback.critique) ? feedback.critique : undefined;\n\t\t\tconst prior: T =\n\t\t\t\tpriv !== undefined ? (priv.best as T) : (candidates[candidates.length - 1] as T);\n\t\t\tconst critique = priv?.critiqueText ?? feedback.summary;\n\t\t\tconst failures = priv?.failures ?? [];\n\t\t\tlet iterCost = 0;\n\t\t\tconst reportCost = (n: number) => {\n\t\t\t\titerCost += n;\n\t\t\t};\n\t\t\tconst ctx: ErrorCritiqueContext<T> = { prior, critique, failures, reportCost };\n\t\t\ttry {\n\t\t\t\tif (opts.parallel !== false) {\n\t\t\t\t\treturn await Promise.all(Array.from({ length: width }, () => opts.teacher(ctx)));\n\t\t\t\t}\n\t\t\t\tconst out: T[] = [];\n\t\t\t\tfor (let i = 0; i < width; i++) {\n\t\t\t\t\tout.push(await opts.teacher(ctx));\n\t\t\t\t}\n\t\t\t\treturn out;\n\t\t\t} finally {\n\t\t\t\tif (opts.tokens != null && iterCost > 0) {\n\t\t\t\t\t// /qa D1 follow-up (2026-05-01): replaced direct `.cache` read\n\t\t\t\t\t// + emit with `tryIncrementBounded`, which encapsulates the\n\t\t\t\t\t// self-owned-counter `.cache` access in the canonical helper.\n\t\t\t\t\ttryIncrementBounded(opts.tokens, Number.MAX_SAFE_INTEGER, iterCost);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * Phase 13.I — `spawnable()` harness preset.\n *\n * Source: `archive/docs/SESSION-multi-agent-gap-analysis.md` G3 lock B + G5\n * reframe.\n *\n * Wraps a {@link MessagingHubGraph} + {@link presetRegistry} +\n * (per-request) {@link agent} mounting + depth-cap + termination contract.\n * Consumers emit a `TopicMessage<SpawnPayload>` to the well-known\n * {@link SPAWNS_TOPIC}; `spawnable()` mints a fresh agent from the\n * matching preset, mounts it, and tracks it in `activeSlot` until the\n * agent settles or expires. Out-of-policy requests (depth-cap exceeded,\n * unknown presetId, schema-invalid, expired) flow to the `rejected`\n * topic.\n *\n * **Cross-cut #1 lock (no `agent.run()`):** spawnable kicks each agent\n * via `bundle.in.emit(taskInput)`; status transitions are observed via\n * the agent's reactive `status` Node.\n *\n * **Termination contract:**\n * - `done` / `error` from the agent's `status` → unmount + remove from\n * `activeSlot`.\n * - `expiresAt` (set on the request envelope, ISO 8601) — when the wall\n * clock passes the deadline AND the agent is still active, the agent is\n * aborted (via `loop.abort()`) and reported on `rejected` with\n * `reason: \"expired\"`. (Per-spawn timeout via the `timeout` operator\n * recipe is documented in COMPOSITION-GUIDE-PATTERNS.)\n *\n * **Depth-cap:** locked recipe (DS-13.I) is `valve(spawnTopic, derived(\n * [depthCounter], n => n < cap))`, but the practical pattern in\n * `spawnable()` checks depth per-request inside the request handler so\n * over-cap requests can be reported on `rejected`. Callers who want hard\n * cuts (no rejection signal) can wrap their own publish path with\n * `valve` per the recipe.\n */\n\nimport { batch, DATA, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { aiMeta } from \"../../utils/ai/_internal.js\";\nimport type { LLMResponse } from \"../../utils/ai/adapters/core/types.js\";\nimport {\n\ttype MessagingHubGraph,\n\tSPAWNS_TOPIC,\n\ttype SubscriptionGraph,\n\tsubscription,\n\ttype TopicGraph,\n\ttype TopicMessage,\n\ttopic,\n} from \"../../utils/messaging/index.js\";\nimport type { AgentBundle, AgentSpec, AgentStatus } from \"../ai/agent.js\";\nimport type { PresetRegistryBundle } from \"../ai/agents.js\";\nimport { agent } from \"../ai/agents.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Payload of a spawn request envelope. Wraps in a {@link Message}<...>:\n * the request body sets `presetId` (the preset registry key) and\n * `taskInput` (the typed input passed to the spawned agent's `bundle.in`).\n */\nexport interface SpawnPayload<TIn> {\n\treadonly presetId: string;\n\treadonly taskInput: TIn;\n}\n\n/**\n * Rejection record published to the `rejected` topic when a spawn request\n * is denied. `reason` is a short human-readable code.\n */\nexport interface SpawnRejection<TIn> {\n\treadonly request: TopicMessage<SpawnPayload<TIn>>;\n\treadonly reason: string;\n}\n\n/**\n * Options for {@link spawnable}.\n */\nexport interface SpawnableOpts<TIn, TOut> {\n\t/** Existing messaging hub. {@link SPAWNS_TOPIC} is created lazily on it. */\n\treadonly hub: MessagingHubGraph;\n\t/** Preset registry — keys must match `request.payload.presetId`. */\n\treadonly registry: PresetRegistryBundle<AgentSpec<TIn, TOut>>;\n\t/**\n\t * Local mount name on the hub for this spawnable's subgraph. Multiple\n\t * spawnable instances on the same hub must use distinct names. Default\n\t * `\"spawnable\"`.\n\t */\n\treadonly name?: string;\n\t/** Maximum concurrently-active agents. Default unbounded. */\n\treadonly depthCap?: number;\n\t/**\n\t * Initial cursor for the spawn-topic subscription. Default `\"now\"` —\n\t * pre-existing retained spawn requests are NOT replayed at construction.\n\t * Pass `\"retained\"` to replay or a number for explicit cursor offset.\n\t */\n\treadonly from?: \"now\" | \"retained\" | number;\n\t/**\n\t * Optional caller-supplied validator. Returns `true` to accept the\n\t * request, `false` to reject. Reject reason on the `rejected` topic is\n\t * `\"schema validation failed\"`. Pair with the `Message.schema` field carried\n\t * in the envelope when full JSON-Schema validation is needed (consumer\n\t * supplies the validator — ajv / zod / valibot — and reads the schema\n\t * from the envelope to gate). The substrate itself does NOT ship a\n\t * JSON-Schema validator; the `Message.schema` field is wire convention.\n\t */\n\treadonly validate?: (request: TopicMessage<SpawnPayload<TIn>>) => boolean;\n}\n\n/**\n * The bundle returned by {@link spawnable}.\n */\nexport interface SpawnableBundle<TIn, TOut> {\n\t/** The well-known spawn topic — emit `TopicMessage<SpawnPayload<TIn>>` here. */\n\treadonly spawnTopic: TopicGraph<TopicMessage<SpawnPayload<TIn>>>;\n\t/** Reactive map of currently-active agent bundles, keyed by request id. */\n\treadonly activeSlot: Node<ReadonlyMap<string, AgentBundle<TIn, TOut>>>;\n\t/** Topic of rejected requests with reason. */\n\treadonly rejected: TopicGraph<SpawnRejection<TIn>>;\n\t/** The internal SpawnableGraph subgraph (mounted under the hub). */\n\treadonly graph: SpawnableGraph<TIn, TOut>;\n}\n\n// ---------------------------------------------------------------------------\n// SpawnableGraph\n// ---------------------------------------------------------------------------\n\n/**\n * Graph subclass implementing {@link SpawnableBundle}'s topology.\n * Mounted under the hub at `opts.name` (default `\"spawnable\"`).\n *\n * Topology:\n * ```\n * <hub>\n * ├── spawns (TopicGraph; well-known well-named spawn topic)\n * └── <name> (SpawnableGraph)\n * ├── spawn-sub (SubscriptionGraph over hub::spawns::events)\n * ├── rejected (TopicGraph<SpawnRejection>)\n * ├── active-slot (Node<ReadonlyMap<id, AgentBundle>>)\n * └── spawn-{req.id}/ (mounted AgentGraph per active spawn)\n * ```\n */\nexport class SpawnableGraph<TIn, TOut> extends Graph {\n\treadonly spawnTopic: TopicGraph<TopicMessage<SpawnPayload<TIn>>>;\n\treadonly rejected: TopicGraph<SpawnRejection<TIn>>;\n\treadonly activeSlot: Node<ReadonlyMap<string, AgentBundle<TIn, TOut>>>;\n\tprivate readonly _spawnSub: SubscriptionGraph<TopicMessage<SpawnPayload<TIn>>>;\n\tprivate readonly _registry: PresetRegistryBundle<AgentSpec<TIn, TOut>>;\n\tprivate readonly _depthCap: number | undefined;\n\tprivate readonly _validate: ((req: TopicMessage<SpawnPayload<TIn>>) => boolean) | undefined;\n\tprivate _disposed = false;\n\n\tconstructor(opts: SpawnableOpts<TIn, TOut>) {\n\t\tconst name = opts.name ?? \"spawnable\";\n\t\tsuper(name);\n\n\t\tthis._registry = opts.registry;\n\t\tthis._depthCap = opts.depthCap;\n\t\tthis._validate = opts.validate;\n\n\t\t// Spawn topic on the hub (well-known name; lazy-created if absent).\n\t\tthis.spawnTopic = opts.hub.topic<TopicMessage<SpawnPayload<TIn>>>(SPAWNS_TOPIC);\n\n\t\t// Rejected topic is private to this spawnable subgraph.\n\t\tthis.rejected = topic<SpawnRejection<TIn>>(\"rejected\");\n\t\tthis.mount(\"rejected\", this.rejected);\n\n\t\t// Active-slot map. `equals: () => false` so each mutation emits a\n\t\t// fresh snapshot even when callers pass an identity-equal Map ref.\n\t\tconst activeSlotNode = node<ReadonlyMap<string, AgentBundle<TIn, TOut>>>([], {\n\t\t\tname: \"active-slot\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"spawnable_active_slot\"),\n\t\t\tinitial: new Map(),\n\t\t\tequals: () => false,\n\t\t});\n\t\tthis.add(activeSlotNode, { name: \"active-slot\" });\n\t\tthis.activeSlot = activeSlotNode;\n\n\t\t// Cursor-based subscription over hub.spawnTopic.events. Lives under\n\t\t// this spawnable subgraph (NOT the hub), so multiple spawnable\n\t\t// instances on the same hub get independent cursors.\n\t\t// Default `from: \"now\"` skips pre-construction retained requests —\n\t\t// older requests are NOT replayed unless the caller opts in.\n\t\tthis._spawnSub = subscription<TopicMessage<SpawnPayload<TIn>>>(\"spawn-sub\", this.spawnTopic, {\n\t\t\tfrom: opts.from ?? \"now\",\n\t\t});\n\t\tthis.mount(\"spawn-sub\", this._spawnSub);\n\n\t\t// Subscribe to `available` to process new requests; ack as we go.\n\t\tconst subRef = this._spawnSub;\n\t\tconst unsub = subRef.available.subscribe((msgs) => {\n\t\t\tif (this._disposed) return;\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tconst items = m[1] as readonly TopicMessage<SpawnPayload<TIn>>[];\n\t\t\t\tif (items.length === 0) continue;\n\t\t\t\tfor (const req of items) {\n\t\t\t\t\tif (this._disposed) return;\n\t\t\t\t\tthis._processRequest(req);\n\t\t\t\t}\n\t\t\t\tsubRef.ack(items.length);\n\t\t\t}\n\t\t});\n\t\tthis.addDisposer(unsub);\n\t\tthis.addDisposer(() => {\n\t\t\tthis._disposed = true;\n\t\t});\n\t\t// Keepalive on the active-slot Node so external `cache` reads stay\n\t\t// current even when no one is subscribed.\n\t\tthis.addDisposer(keepalive(activeSlotNode));\n\t}\n\n\tprivate _processRequest(req: TopicMessage<SpawnPayload<TIn>>): void {\n\t\tif (this._disposed) return;\n\n\t\t// Custom validation.\n\t\tif (this._validate && !this._validate(req)) {\n\t\t\tthis.rejected.publish({ request: req, reason: \"schema validation failed\" });\n\t\t\treturn;\n\t\t}\n\n\t\t// Expiry check (only on entry — per-agent timeouts during run are a\n\t\t// future iteration; recipe-style composition with `timeout` covers\n\t\t// the in-flight case until then). Use `wallClockNs()` so test\n\t\t// suites that monkey-patch the central clock can pin expiry decisions.\n\t\tif (req.expiresAt != null) {\n\t\t\tconst expiry = Date.parse(req.expiresAt);\n\t\t\tif (!Number.isFinite(expiry)) {\n\t\t\t\tthis.rejected.publish({ request: req, reason: \"invalid expiresAt\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nowMs = wallClockNs() / 1_000_000;\n\t\t\tif (nowMs >= expiry) {\n\t\t\t\tthis.rejected.publish({ request: req, reason: \"expired\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Depth-cap check.\n\t\tconst currentMap =\n\t\t\t(this.activeSlot.cache as ReadonlyMap<string, AgentBundle<TIn, TOut>> | undefined) ??\n\t\t\tnew Map();\n\t\tif (this._depthCap != null && currentMap.size >= this._depthCap) {\n\t\t\tthis.rejected.publish({\n\t\t\t\trequest: req,\n\t\t\t\treason: `depth-cap exceeded (${currentMap.size}/${this._depthCap})`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Look up preset.\n\t\tconst spec = this._registry.registry.get(req.payload.presetId);\n\t\tif (!spec) {\n\t\t\tthis.rejected.publish({\n\t\t\t\trequest: req,\n\t\t\t\treason: `unknown presetId: ${req.payload.presetId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Mint and mount the agent. Slot name is derived from the request id\n\t\t// so it's traceable in describe / explain output.\n\t\tconst slotName = `spawn-${req.id}`;\n\t\tlet bundle: AgentBundle<TIn, TOut>;\n\t\ttry {\n\t\t\tbundle = agent<TIn, TOut>(this, { ...spec, name: slotName });\n\t\t} catch (e) {\n\t\t\tthis.rejected.publish({\n\t\t\t\trequest: req,\n\t\t\t\treason: `agent mint failed: ${(e as Error).message ?? \"unknown\"}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Update active-slot.\n\t\tconst updated = new Map(currentMap);\n\t\tupdated.set(req.id, bundle);\n\t\tthis.activeSlot.emit(updated);\n\n\t\t// Watch for completion BEFORE kicking, so a synchronous adapter that\n\t\t// drives status straight to \"done\" inside the kick still triggers\n\t\t// cleanup. Subscribe to status; on terminal, unmount + remove. Each\n\t\t// per-spawn statusUnsub releases inside `onTerminal` so we don't\n\t\t// accumulate dead disposers per-spawn over the spawnable's lifetime.\n\t\tlet statusUnsub: (() => void) | undefined;\n\t\tconst onTerminal = (stat: AgentStatus): void => {\n\t\t\tif (stat !== \"done\" && stat !== \"error\") return;\n\t\t\t// Idempotent — guard against double-fire.\n\t\t\tconst live =\n\t\t\t\t(this.activeSlot.cache as ReadonlyMap<string, AgentBundle<TIn, TOut>> | undefined) ??\n\t\t\t\tnew Map();\n\t\t\tif (!live.has(req.id)) return;\n\t\t\tbatch(() => {\n\t\t\t\ttry {\n\t\t\t\t\tthis.remove(slotName);\n\t\t\t\t} catch {\n\t\t\t\t\t// Already removed (e.g., parent destroyed mid-flight).\n\t\t\t\t}\n\t\t\t\tconst next = new Map(live);\n\t\t\t\tnext.delete(req.id);\n\t\t\t\tthis.activeSlot.emit(next);\n\t\t\t});\n\t\t\t// Release the per-spawn status subscription now that the spawn\n\t\t\t// is finished — prevents disposer accumulation over many spawns.\n\t\t\tstatusUnsub?.();\n\t\t\tstatusUnsub = undefined;\n\t\t};\n\t\tstatusUnsub = bundle.status.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) onTerminal(m[1] as AgentStatus);\n\t\t\t}\n\t\t});\n\t\t// Defensive disposer — fires on SpawnableGraph.destroy() if the\n\t\t// spawn is still in-flight. `onTerminal` clears `statusUnsub` so\n\t\t// double-call is a no-op.\n\t\tthis.addDisposer(() => statusUnsub?.());\n\n\t\t// Kick the agent reactively.\n\t\tbundle.in.emit(req.payload.taskInput);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// spawnable() factory\n// ---------------------------------------------------------------------------\n\n/**\n * Constructs a {@link SpawnableGraph}, mounts it under `opts.hub` at\n * `opts.name` (default `\"spawnable\"`), and returns the\n * {@link SpawnableBundle} contract.\n *\n * **Composition with Phase 13 substrate:**\n * - Builds on **13.B** ({@link Message} envelope, {@link SPAWNS_TOPIC}).\n * - Builds on **13.G/H** ({@link agent}, {@link AgentBundle}).\n * - Builds on **13.H** ({@link presetRegistry}).\n * - The depth-cap gate is documented as a **13.D recipe**\n * (`valve(spawnTopic, derived([depthCounter], n => n < cap))`); inside\n * `spawnable()` the depth check is per-request so over-cap requests\n * surface on `rejected`. Callers wanting a hard cut (no rejection\n * signal) can wrap their publish path with `valve`.\n *\n * **Strategy-key axis (DS-13.I):** when `harnessLoop` is wired to a\n * spawnable, downstream `strategy.record(...)` calls should pass the\n * spawning agent's `presetId` for the {@link strategyKey} first axis.\n * Single-agent harness keeps using {@link DEFAULT_PRESET_ID} as before.\n *\n * @example\n * ```ts\n * const hub = messagingHub(\"hub\");\n * const presets = presetRegistry<AgentSpec<string, LLMResponse>>();\n * presets.put(\"researcher\", { name: \"researcher\", adapter: openai, systemPrompt: \"...\" });\n * presets.put(\"coder\", { name: \"coder\", adapter: anthropic, systemPrompt: \"...\" });\n *\n * const sp = spawnable({ hub, registry: presets, depthCap: 5 });\n *\n * // Trigger a spawn:\n * sp.spawnTopic.publish({\n * id: \"req-42\",\n * payload: { presetId: \"researcher\", taskInput: \"what is reactive graph composition?\" },\n * });\n *\n * // Observe active agents:\n * sp.activeSlot.subscribe((msgs) => { ... });\n *\n * // Observe rejections:\n * sp.rejected.events.subscribe((msgs) => { ... });\n * ```\n *\n * @category patterns\n */\nexport function spawnable<TIn = string, TOut = LLMResponse>(\n\topts: SpawnableOpts<TIn, TOut>,\n): SpawnableBundle<TIn, TOut> {\n\tconst graph = new SpawnableGraph<TIn, TOut>(opts);\n\topts.hub.mount(opts.name ?? \"spawnable\", graph);\n\treturn {\n\t\tspawnTopic: graph.spawnTopic,\n\t\tactiveSlot: graph.activeSlot,\n\t\trejected: graph.rejected,\n\t\tgraph,\n\t};\n}\n","/**\n * Phase 13.H — `agent(spec)` preset + `presetRegistry` sugar.\n *\n * Source: `archive/docs/SESSION-multi-agent-gap-analysis.md` G1 + G2.\n *\n * `agent()` is the ergonomic factory — given a parent Graph and an\n * `AgentSpec`, mints an `AgentGraph`, mounts it under the parent at\n * `spec.name`, and returns the `AgentBundle` contract.\n *\n * `presetRegistry()` is thin sugar over `reactiveMap` — a typed reactive\n * map of `<id, preset>`. Pairs with `materialize` (Phase 13.C) for\n * dynamic preset selection: callers store specs / factories / configs in\n * the registry and `materialize` mounts the matching one based on a\n * routing key.\n *\n * **Cross-cut #1 lock:** no `agent.run()` imperative sugar — caller-side\n * runtime is `bundle.in.emit(input)` + `awaitSettled(bundle.out)`.\n */\n\nimport { type ReactiveMapBundle, reactiveMap } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport type { LLMResponse } from \"../../utils/ai/adapters/core/types.js\";\nimport { type AgentBundle, AgentGraph, type AgentSpec } from \"./agent.js\";\n\n// ---------------------------------------------------------------------------\n// agent() factory\n// ---------------------------------------------------------------------------\n\n/**\n * Mints an {@link AgentGraph} from `spec`, mounts it under `parent` at\n * `spec.name`, and returns the {@link AgentBundle} contract.\n *\n * **Default type parameters.** When called without explicit type params,\n * `TIn` defaults to `string` and `TOut` to `LLMResponse` — the common\n * case where the caller writes a user message and reads the raw response.\n * Custom types require both `inMapper` and `outMapper` in the spec; the\n * default mappers throw at runtime if `TIn` / `TOut` aren't string /\n * LLMResponse.\n *\n * **Memory partition default.** Each `agent()` call mints its own\n * `AgentMemoryGraph` if `spec.memory` is omitted (private memory; the\n * common case). Pass an explicit shared instance — e.g.\n * `agent(parent, { ..., memory: sharedMemory })` for two agents — to\n * implement §29 handoff context transfer.\n *\n * **Reactive entry / exit:**\n * - `bundle.in.emit(input)` kicks the loop reactively (no imperative\n * `.run()` per cross-cut #1 lock).\n * - `awaitSettled(bundle.out, { skipCurrent: true })` resolves on the\n * first response after the kick. `skipCurrent` matters for the second\n * call onward — `out` caches the prior response.\n *\n * **Mounting.** The factory mounts under `parent.mount(spec.name, ...)`.\n * The slot name must be free on `parent` at construction time. To keep\n * the agent unmounted, construct `new AgentGraph(spec)` directly.\n *\n * @example\n * ```ts\n * import { agent, awaitSettled, Graph } from \"@graphrefly/graphrefly-ts\";\n *\n * const parent = new Graph(\"parent\");\n * const a = agent(parent, {\n * name: \"researcher\",\n * adapter: openaiAdapter,\n * systemPrompt: \"Research the user's question carefully.\",\n * });\n * a.in.emit(\"What's the capital of France?\");\n * const resp = await awaitSettled(a.out, { skipCurrent: true });\n * ```\n *\n * @category patterns\n */\nexport function agent<TIn = string, TOut = LLMResponse>(\n\tparent: Graph,\n\tspec: AgentSpec<TIn, TOut>,\n): AgentBundle<TIn, TOut> {\n\tconst graph = new AgentGraph<TIn, TOut>(spec);\n\tparent.mount(spec.name, graph);\n\treturn {\n\t\tin: graph.in,\n\t\tout: graph.out,\n\t\tstatus: graph.status,\n\t\tcost: graph.cost,\n\t\tgraph,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// presetRegistry()\n// ---------------------------------------------------------------------------\n\n/**\n * The bundle returned by {@link presetRegistry}. Wraps a `reactiveMap`\n * with imperative `put` / `remove` shortcuts and exposes the underlying\n * `registry` for direct reactive consumption (`.entries` is a\n * `Node<ReadonlyMap<string, TPreset>>`).\n *\n * Use the `registry.entries` Node directly with {@link materialize} (Phase\n * 13.C) — pass it as the `factories` argument when `TPreset` is itself\n * a `() => Graph` factory thunk, or transform via `derived` when\n * `TPreset` is a richer spec type that needs a `spec → factory` adapter.\n */\nexport interface PresetRegistryBundle<TPreset> {\n\t/**\n\t * The underlying reactive map. `registry.entries` is the\n\t * `Node<ReadonlyMap<string, TPreset>>` — pass directly to\n\t * {@link materialize} when preset shape matches the factories arg.\n\t */\n\treadonly registry: ReactiveMapBundle<string, TPreset>;\n\t/** Imperative add / replace. Always emits a fresh snapshot. */\n\tput(id: string, preset: TPreset): void;\n\t/** Imperative remove. Returns `true` if the id was present. */\n\tremove(id: string): boolean;\n}\n\n/**\n * Thin sugar over `reactiveMap` — a typed registry of `<id, preset>` for\n * agent / strategy / persona / skill catalogs.\n *\n * **Generic over preset shape.** `TPreset` is open — could be an\n * {@link AgentSpec}, a `() => Graph` factory thunk, a static config\n * object, or anything else. Decoupled from `agent()` so the same primitive\n * powers harnessLoop strategy registries, pipelineGraph stage catalogs,\n * etc.\n *\n * **Composes with `materialize`.** When `TPreset` is a `() => Graph`\n * factory, pass `registry.entries` directly to\n * {@link materialize} as the `factories` argument. When `TPreset` is a\n * spec, transform via `derived` to build a `Map<id, () => Graph>` adapter:\n *\n * ```ts\n * const presets = presetRegistry<AgentSpec<string, LLMResponse>>();\n * presets.put(\"researcher\", { name: \"researcher\", adapter, systemPrompt: \"...\" });\n *\n * // Adapter: spec → factory.\n * const factories = derived(\n * [presets.registry.entries],\n * ([m]) => new Map(\n * [...m].map(([id, spec]) => [id, () => new AgentGraph(spec)]),\n * ),\n * );\n * const slot = materialize(activeKey, factories, parent);\n * ```\n *\n * @param initial - Optional initial entries.\n * @returns {@link PresetRegistryBundle}.\n *\n * @category patterns\n */\nexport function presetRegistry<TPreset>(\n\tinitial?: ReadonlyMap<string, TPreset>,\n): PresetRegistryBundle<TPreset> {\n\tconst registry = reactiveMap<string, TPreset>({ name: \"presetRegistry\" });\n\tif (initial != null) {\n\t\tfor (const [id, preset] of initial) {\n\t\t\tregistry.set(id, preset);\n\t\t}\n\t}\n\treturn {\n\t\tregistry,\n\t\tput(id, preset) {\n\t\t\tregistry.set(id, preset);\n\t\t},\n\t\tremove(id) {\n\t\t\tif (!registry.has(id)) return false;\n\t\t\tregistry.delete(id);\n\t\t\treturn true;\n\t\t},\n\t};\n}\n","/**\n * Phase 13.G — `AgentBundle<TIn, TOut>` interface + `class AgentGraph extends Graph`.\n *\n * Source: `archive/docs/SESSION-multi-agent-gap-analysis.md` G1 lock B.\n *\n * Composes the existing substrate (`agentLoop`, `toolRegistry`,\n * `agentMemory`) into a typed inbox/outbox subgraph that other parts of a\n * multi-agent system can wire to. Sibling preset `agent()` (in\n * `./agents.ts`) is the ergonomic factory; this file is the contract.\n *\n * **Cross-cut #1 lock (no `agent.run()`):** caller-side runtime entry is\n * `bundle.in.emit(input)` + `awaitSettled(bundle.out)`. The legacy\n * `agentLoop.run()` is still available on `bundle.graph.loop` for\n * single-shot Promise-bridge use cases, but `agent()` does NOT expose a\n * `run()` method on the bundle.\n *\n * **Memory partition default:** private memory per agent (each `agent(...)`\n * call creates its own `AgentMemoryGraph` if none passed). Pass an explicit\n * shared instance for §29 handoff context-transfer.\n */\n\nimport { batch, DATA, INVALIDATE, type Node, node, RESOLVED } from \"@graphrefly/pure-ts/core\";\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { aiMeta } from \"../../utils/ai/_internal.js\";\nimport type {\n\tInputTokens,\n\tLLMAdapter,\n\tLLMResponse,\n\tOutputTokens,\n\tTokenUsage,\n\tToolDefinition,\n} from \"../../utils/ai/adapters/core/types.js\";\nimport {\n\ttype SubscriptionGraph,\n\tsubscription,\n\ttype TopicGraph,\n\ttopic,\n} from \"../../utils/messaging/index.js\";\nimport { type AgentLoopGraph, agentLoop } from \"./agent-loop.js\";\nimport type { AgentMemoryGraph } from \"./agent-memory.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Lifecycle status of an {@link AgentGraph}.\n *\n * - `idle` — no input has been received since construction or last reset.\n * - `running` — inputs are flowing through the underlying agentLoop\n * (collapses the loop's `thinking` + `acting` substates so consumers\n * don't have to model the tool-call inner loop).\n * - `verifying` — verifier subgraph is in flight (reserved; lights up when\n * the verifier slot is added in a future wave per G7 recipe).\n * - `done` — the most recent input has settled with a verified response.\n * - `error` — the loop or verifier produced a terminal error.\n *\n * **Note (Phase 13.G, 2026-05-01):** v1 of `agent()` has no built-in\n * verifier slot — `verifying` is reserved but never produced. When a\n * verifier consumer surfaces, this enum widens (non-breaking type\n * widening; existing consumers see the same `idle | running | done | error`\n * subset).\n */\nexport type AgentStatus = \"idle\" | \"running\" | \"verifying\" | \"done\" | \"error\";\n\n/**\n * Aggregated cost for an agent's run, surfaced as a `Node<CostState>` on\n * the bundle. **Wraps the canonical {@link TokenUsage}** so consumers get\n * the full provider-disaggregated token classes (cache-read /\n * cache-write-5m / cache-write-1h / audio / image / video / tool-use /\n * reasoning / prediction-accepted / prediction-rejected / extensions /\n * auxiliary non-token costs / raw escape-hatch) without losing fidelity\n * for downstream pricing. USD conversion is a downstream `derived` over\n * `usage`.\n *\n * - `usage` — accumulated {@link TokenUsage} across all turns of the\n * current input.\n * - `turns` — number of completed agentLoop iterations (LLM invocations).\n *\n * **Counter scope:** resets to {@link ZERO_COST} on each new `bundle.in`\n * emit (per-input cost rather than per-agent-lifetime). Sum across multiple\n * inputs by snapshotting `cost` at `done` and accumulating externally —\n * a per-lifetime cost is a downstream `scan` over this.\n *\n * **Helpers.** Use `sumInputTokens(usage)` / `sumOutputTokens(usage)` from\n * `@graphrefly/graphrefly-ts` to flatten to scalars when the caller wants\n * a single number.\n */\nexport interface CostState {\n\treadonly usage: TokenUsage;\n\treadonly turns: number;\n}\n\nconst EMPTY_INPUT: InputTokens = Object.freeze({ regular: 0 });\nconst EMPTY_OUTPUT: OutputTokens = Object.freeze({ regular: 0 });\nconst EMPTY_USAGE: TokenUsage = Object.freeze({ input: EMPTY_INPUT, output: EMPTY_OUTPUT });\n\n/** Empty cost. Used as the initial value and the per-input reset baseline. */\nexport const ZERO_COST: CostState = Object.freeze({ usage: EMPTY_USAGE, turns: 0 });\n\n// ---------------------------------------------------------------------------\n// TokenUsage accumulator\n// ---------------------------------------------------------------------------\n\nfunction addOptional(a: number | undefined, b: number | undefined): number | undefined {\n\tif (a == null && b == null) return undefined;\n\treturn (a ?? 0) + (b ?? 0);\n}\n\nfunction addExtensions(\n\ta: Record<string, number> | undefined,\n\tb: Record<string, number> | undefined,\n): Record<string, number> | undefined {\n\tif (a == null && b == null) return undefined;\n\tconst out: Record<string, number> = { ...(a ?? {}) };\n\tfor (const [k, v] of Object.entries(b ?? {})) {\n\t\tout[k] = (out[k] ?? 0) + v;\n\t}\n\treturn out;\n}\n\n/**\n * Accumulates two {@link TokenUsage} snapshots. All field classes are\n * summed; optional fields propagate as `undefined` when absent from both\n * sides, otherwise treated as 0 for the missing side. `auxiliary` and\n * `extensions` merge by key. `raw` is dropped — it's a per-call escape\n * hatch, not summable.\n *\n * @category extra\n */\nexport function addUsage(a: TokenUsage, b: TokenUsage): TokenUsage {\n\tconst out: TokenUsage = {\n\t\tinput: {\n\t\t\tregular: a.input.regular + b.input.regular,\n\t\t\t...(addOptional(a.input.cacheRead, b.input.cacheRead) !== undefined && {\n\t\t\t\tcacheRead: addOptional(a.input.cacheRead, b.input.cacheRead) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.cacheWrite5m, b.input.cacheWrite5m) !== undefined && {\n\t\t\t\tcacheWrite5m: addOptional(a.input.cacheWrite5m, b.input.cacheWrite5m) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.cacheWrite1h, b.input.cacheWrite1h) !== undefined && {\n\t\t\t\tcacheWrite1h: addOptional(a.input.cacheWrite1h, b.input.cacheWrite1h) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.cacheWriteOther, b.input.cacheWriteOther) !== undefined && {\n\t\t\t\tcacheWriteOther: addOptional(a.input.cacheWriteOther, b.input.cacheWriteOther) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.audio, b.input.audio) !== undefined && {\n\t\t\t\taudio: addOptional(a.input.audio, b.input.audio) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.image, b.input.image) !== undefined && {\n\t\t\t\timage: addOptional(a.input.image, b.input.image) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.video, b.input.video) !== undefined && {\n\t\t\t\tvideo: addOptional(a.input.video, b.input.video) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.toolUse, b.input.toolUse) !== undefined && {\n\t\t\t\ttoolUse: addOptional(a.input.toolUse, b.input.toolUse) as number,\n\t\t\t}),\n\t\t\t...(addExtensions(a.input.extensions, b.input.extensions) !== undefined && {\n\t\t\t\textensions: addExtensions(a.input.extensions, b.input.extensions) as Record<string, number>,\n\t\t\t}),\n\t\t},\n\t\toutput: {\n\t\t\tregular: a.output.regular + b.output.regular,\n\t\t\t...(addOptional(a.output.reasoning, b.output.reasoning) !== undefined && {\n\t\t\t\treasoning: addOptional(a.output.reasoning, b.output.reasoning) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.output.audio, b.output.audio) !== undefined && {\n\t\t\t\taudio: addOptional(a.output.audio, b.output.audio) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.output.predictionAccepted, b.output.predictionAccepted) !== undefined && {\n\t\t\t\tpredictionAccepted: addOptional(\n\t\t\t\t\ta.output.predictionAccepted,\n\t\t\t\t\tb.output.predictionAccepted,\n\t\t\t\t) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.output.predictionRejected, b.output.predictionRejected) !== undefined && {\n\t\t\t\tpredictionRejected: addOptional(\n\t\t\t\t\ta.output.predictionRejected,\n\t\t\t\t\tb.output.predictionRejected,\n\t\t\t\t) as number,\n\t\t\t}),\n\t\t\t...(addExtensions(a.output.extensions, b.output.extensions) !== undefined && {\n\t\t\t\textensions: addExtensions(a.output.extensions, b.output.extensions) as Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tnumber\n\t\t\t\t>,\n\t\t\t}),\n\t\t},\n\t\t...(addExtensions(a.auxiliary, b.auxiliary) !== undefined && {\n\t\t\tauxiliary: addExtensions(a.auxiliary, b.auxiliary) as Record<string, number>,\n\t\t}),\n\t};\n\treturn out;\n}\n\n/**\n * Spec for {@link agent} (in `./agents.ts`). Required fields are minimal —\n * `name` and `adapter` cover the common case where the input is a string\n * and the output is the raw `LLMResponse`. Optional fields shape the\n * agent's behavior:\n *\n * - **Mappers** (`inMapper` / `outMapper`) translate between caller-typed\n * `TIn` / `TOut` and the loop's internal `string` / `LLMResponse`. Default\n * identity mappers are wired automatically when `TIn` extends `string`\n * and `TOut` extends `LLMResponse`.\n * - **`tools`** is a reactive `NodeInput<readonly ToolDefinition[]>` —\n * `agent()` subscribes and reconciles the underlying `toolRegistry`'s\n * registrations on each emit. Static-array form is also accepted.\n * - **`memory`** is an explicit `AgentMemoryGraph` instance for shared\n * memory across agents (§29 handoff context transfer). Default: private\n * memory per agent (each `agent()` call mints its own).\n * - **`maxIterations`** caps the underlying agentLoop's tool-call inner\n * loop. Default 10 (matches `agentLoop`).\n * - **Verifier slot** is intentionally not in v1 — G7 reframe locks it as\n * a caller-composed recipe. When a real consumer surfaces, a\n * `verifier?: (out: Node<TOut>) => NodeInput<VerifierResult>` field\n * lands here additively.\n */\nexport interface AgentSpec<TIn, TOut> {\n\t/** Local mount name when wired to a parent graph. Required. */\n\treadonly name: string;\n\t/** LLM adapter for the underlying agentLoop. Required. */\n\treadonly adapter: LLMAdapter;\n\t/** Optional system prompt. Static today; reactive widening pending. */\n\treadonly systemPrompt?: string;\n\t/**\n\t * Optional reactive tool list. When a Node, the agent subscribes and\n\t * reconciles the underlying `toolRegistry` registrations on each emit\n\t * (additions registered, removals unregistered). When a static array,\n\t * tools are registered once at construction.\n\t */\n\treadonly tools?: Node<readonly ToolDefinition[]> | readonly ToolDefinition[];\n\t/**\n\t * Optional shared memory. Default: private (agent mints its own\n\t * `AgentMemoryGraph` if needed; not yet wired into the loop's chat —\n\t * that wiring is a separate follow-up). Pass an explicit instance to\n\t * share memory across agents for §29 handoff context transfer.\n\t */\n\treadonly memory?: AgentMemoryGraph<unknown>;\n\t/**\n\t * Maps caller-typed input → string for the underlying chat. Defaults to\n\t * identity when `TIn extends string`; required otherwise.\n\t */\n\treadonly inMapper?: (input: TIn) => string;\n\t/**\n\t * Maps the agentLoop's `LLMResponse` → caller-typed output. Defaults to\n\t * identity when `TOut extends LLMResponse`; required otherwise.\n\t */\n\treadonly outMapper?: (response: LLMResponse) => TOut;\n\t/** Caps tool-call inner-loop iterations. Default 10. */\n\treadonly maxIterations?: number;\n\t/** Escape hatch for non-core fields. Surfaced in `describe()` via meta. */\n\treadonly meta?: Record<string, unknown>;\n}\n\n/**\n * Public contract for an agent — typed inbox/outbox + lifecycle / cost\n * observables + the underlying graph for inspection / mounting.\n *\n * **Reactive entry:** caller writes to `in` (e.g. `bundle.in.emit(input)`).\n * The agent reactively kicks the underlying loop and produces `out`.\n *\n * **Reactive exit:** caller reads `out` via `subscribe` (continuous) or\n * `awaitSettled(out)` (single-shot). Both `in` and `out` stay SENTINEL\n * (`cache === undefined`) until the first real emission — no `null`\n * push-on-subscribe trap (per `feedback_use_prevdata_for_sentinel`).\n *\n * **Cross-graph wiring:** the bundle's `graph` is mountable under any\n * parent via `parent.mount(name, bundle.graph)`. After mount, the bundle's\n * Nodes are reachable through both the bundle reference (direct) and via\n * `parent.node(\"<name>::out\")` etc. (qualified path).\n */\nexport interface AgentBundle<TIn, TOut> {\n\treadonly in: Node<TIn>;\n\treadonly out: Node<TOut>;\n\treadonly status: Node<AgentStatus>;\n\treadonly cost: Node<CostState>;\n\treadonly graph: AgentGraph<TIn, TOut>;\n}\n\n// ---------------------------------------------------------------------------\n// AgentGraph\n// ---------------------------------------------------------------------------\n\nconst TERMINAL_STATUSES = new Set<AgentStatus>([\"done\", \"error\"]);\n\n/**\n * Graph subclass implementing {@link AgentBundle}. Mounts an inner\n * {@link AgentLoopGraph} at `loop/`; `in` / `out` / `status` / `cost`\n * surface the bundle contract as top-level nodes.\n *\n * Construction is internal — use the {@link agent} factory in\n * `./agents.ts` for normal use. Direct `new AgentGraph(name, spec)` is\n * supported for callers that want full control over mount order.\n *\n * **Topology:**\n * ```\n * <name>\n * ├── loop (AgentLoopGraph subgraph)\n * │ ├── chat\n * │ ├── tools\n * │ ├── status / turn / aborted / lastResponse / ...\n * ├── in (Node<TIn>, SENTINEL until first emit)\n * ├── out (Node<TOut>, SENTINEL until first response)\n * ├── status (Node<AgentStatus>, mirror of loop.status)\n * └── cost (Node<CostState>)\n * ```\n *\n * **Lifecycle:**\n * - On `in` emit: `inMapper` projects to `string`; appended to\n * `loop.chat`; loop status reset (`turn=0`, `aborted=false`,\n * `status=\"thinking\"`); per-input cost counters reset to zero.\n * - On `loop.lastResponse` emit: cost rolls forward; `out` emits\n * `outMapper(response)`.\n * - On `loop.status=\"done\"`: agent's status emits `\"done\"`.\n * - On `loop.status=\"error\"` (or any ERROR propagation): agent's status\n * emits `\"error\"`.\n */\nexport class AgentGraph<TIn, TOut> extends Graph {\n\t/** The agent's typed inbox. Writable; `in.emit(value)` kicks the loop. */\n\treadonly in: Node<TIn>;\n\t/** The agent's typed outbox. SENTINEL until first response. */\n\treadonly out: Node<TOut>;\n\t/** Lifecycle status (translated from the underlying loop's substates). */\n\treadonly status: Node<AgentStatus>;\n\t/** Cumulative cost for the current / most-recent input. */\n\treadonly cost: Node<CostState>;\n\t/** The underlying agentLoop — exposed for inspection / advanced wiring. */\n\treadonly loop: AgentLoopGraph;\n\t/** Optional shared memory subgraph (mounted at `memory/` if provided). */\n\treadonly memory: AgentMemoryGraph<unknown> | null;\n\n\tconstructor(spec: AgentSpec<TIn, TOut>, opts?: GraphOptions) {\n\t\tsuper(spec.name, opts);\n\n\t\t// --- 1. Mount the agentLoop subgraph. ------------------------------\n\t\tconst initialTools = Array.isArray(spec.tools)\n\t\t\t? (spec.tools as readonly ToolDefinition[])\n\t\t\t: undefined;\n\t\tthis.loop = agentLoop(`${spec.name}-loop`, {\n\t\t\tadapter: spec.adapter,\n\t\t\t...(spec.systemPrompt != null ? { systemPrompt: spec.systemPrompt } : {}),\n\t\t\t...(initialTools != null ? { tools: initialTools } : {}),\n\t\t\t...(spec.maxIterations != null ? { maxTurns: spec.maxIterations } : {}),\n\t\t});\n\t\tthis.mount(\"loop\", this.loop);\n\n\t\t// --- 2. Reactive tools subscription (if Node-form). ----------------\n\t\t// agentLoop's tools are static-array at construction; we reconcile\n\t\t// dynamically by subscribing to the user's reactive Node and\n\t\t// register/unregister against the inner toolRegistry.\n\t\tif (spec.tools != null && !Array.isArray(spec.tools)) {\n\t\t\tconst toolsNode = spec.tools as Node<readonly ToolDefinition[]>;\n\t\t\tconst registered = new Set<string>();\n\t\t\tconst unsubTools = toolsNode.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 next = m[1] as readonly ToolDefinition[];\n\t\t\t\t\tconst nextNames = new Set(next.map((t) => t.name));\n\t\t\t\t\t// Unregister missing.\n\t\t\t\t\tfor (const name of registered) {\n\t\t\t\t\t\tif (!nextNames.has(name)) {\n\t\t\t\t\t\t\tthis.loop.tools.unregister(name);\n\t\t\t\t\t\t\tregistered.delete(name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Register new (idempotent guard via local tracking).\n\t\t\t\t\tfor (const tool of next) {\n\t\t\t\t\t\tif (!registered.has(tool.name)) {\n\t\t\t\t\t\t\tthis.loop.tools.register(tool);\n\t\t\t\t\t\t\tregistered.add(tool.name);\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(unsubTools);\n\t\t}\n\n\t\t// --- 3. Optional shared memory subgraph (passed through). ----------\n\t\t// v1: memory is mounted but NOT yet wired into the loop's chat — the\n\t\t// chat-context-from-memory glue is a separate follow-up. Mounting it\n\t\t// here gives the bundle a stable surface for §29 handoff (callers\n\t\t// can pass the SAME instance to multiple agents for shared memory).\n\t\tthis.memory = spec.memory ?? null;\n\t\tif (this.memory != null) {\n\t\t\tthis.mount(\"memory\", this.memory);\n\t\t}\n\n\t\t// --- 4. `in` — the typed inbox. ------------------------------------\n\t\t// SENTINEL until first emit; `equals: () => false` so re-emitting the\n\t\t// same value still kicks (no spurious dedup of repeat inputs).\n\t\tthis.in = node<TIn>([], {\n\t\t\tname: \"in\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_in\"),\n\t\t\tequals: () => false,\n\t\t});\n\t\tthis.add(this.in, { name: \"in\" });\n\n\t\t// --- 5. `cost` — per-input token counters. -------------------------\n\t\tconst costNode = node<CostState>([], {\n\t\t\tname: \"cost\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_cost\"),\n\t\t\tinitial: ZERO_COST,\n\t\t});\n\t\tthis.add(costNode, { name: \"cost\" });\n\t\tthis.cost = costNode;\n\n\t\t// --- 6. `out` — the typed outbox. ----------------------------------\n\t\t// Derived from `loop.lastResponse`. SENTINEL while `loop.lastResponse`\n\t\t// has never emitted a real response (F9 fix: the loop now stays\n\t\t// SENTINEL too — no more eager `null` placeholder), so the SENTINEL\n\t\t// detector inside the fn is `prevData[0] === undefined`. Between\n\t\t// runs, `loop.lastResponse.down([[INVALIDATE]])` clears that\n\t\t// `prevData` slot back to undefined, so this derived correctly gates\n\t\t// to RESOLVED on the next status=\"idle\" wave.\n\t\tconst outMapper = spec.outMapper ?? defaultOutMapper<TOut>();\n\t\tconst outNode = node<TOut>(\n\t\t\t[this.loop.lastResponse],\n\t\t\t(data, a, ctx) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tconst resp =\n\t\t\t\t\tbatch0 != null && batch0.length > 0\n\t\t\t\t\t\t? (batch0.at(-1) as LLMResponse | undefined)\n\t\t\t\t\t\t: (ctx.prevData[0] as LLMResponse | undefined);\n\t\t\t\tif (resp === undefined) {\n\t\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ta.emit(outMapper(resp));\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"out\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"agent_out\"),\n\t\t\t\t// Each in.emit may produce a structurally-equal response (e.g.\n\t\t\t\t// from a deterministic adapter) — disable framework dedup so\n\t\t\t\t// repeat emits propagate and `awaitSettled({skipCurrent:true})`\n\t\t\t\t// sees them. Callers can wrap with `distinctUntilChanged` if\n\t\t\t\t// they want change-only semantics.\n\t\t\t\tequals: () => false,\n\t\t\t},\n\t\t);\n\t\tthis.add(outNode, { name: \"out\" });\n\t\tthis.out = outNode;\n\n\t\t// --- 7. `status` — translated from loop.status. --------------------\n\t\t// Mirror via §32 pattern: a state node downstream consumers depend on,\n\t\t// reset and updated by an effect listening to loop.status.\n\t\tconst statusNode = node<AgentStatus>([], {\n\t\t\tname: \"status\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_status\"),\n\t\t\tinitial: \"idle\",\n\t\t});\n\t\tthis.add(statusNode, { name: \"status\" });\n\t\tthis.status = statusNode;\n\n\t\tconst statusMirrorEff = node(\n\t\t\t[this.loop.status],\n\t\t\t(data, _a, ctx) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tconst loopStatus =\n\t\t\t\t\tbatch0 != null && batch0.length > 0\n\t\t\t\t\t\t? (batch0.at(-1) as string)\n\t\t\t\t\t\t: ((ctx.prevData[0] as string | undefined) ?? \"idle\");\n\t\t\t\tconst next: AgentStatus =\n\t\t\t\t\tloopStatus === \"idle\"\n\t\t\t\t\t\t? \"idle\"\n\t\t\t\t\t\t: loopStatus === \"thinking\" || loopStatus === \"acting\"\n\t\t\t\t\t\t\t? \"running\"\n\t\t\t\t\t\t\t: loopStatus === \"done\"\n\t\t\t\t\t\t\t\t? \"done\"\n\t\t\t\t\t\t\t\t: loopStatus === \"error\"\n\t\t\t\t\t\t\t\t\t? \"error\"\n\t\t\t\t\t\t\t\t\t: \"idle\";\n\t\t\t\tif (statusNode.cache !== next) statusNode.emit(next);\n\t\t\t},\n\t\t\t{ describeKind: \"effect\", meta: aiMeta(\"agent_status_mirror\") },\n\t\t);\n\t\tthis.addDisposer(keepalive(statusMirrorEff));\n\n\t\t// --- 8. Cost-rollup effect. ---------------------------------------\n\t\t// Rolls forward on each loop.lastResponse emission. Reads\n\t\t// loop.turn.cache for the iteration count (sole-owner-reactive-reader\n\t\t// per Phase 12 D1 lock — loop is mounted as a subgraph of this Graph).\n\t\t// SENTINEL gate: `prevData[0] === undefined` means no response has\n\t\t// ever been delivered for this run (post-INVALIDATE reset between\n\t\t// runs), so the rollup short-circuits.\n\t\tconst costEff = node(\n\t\t\t[this.loop.lastResponse],\n\t\t\t(data, _a, ctx) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tconst resp =\n\t\t\t\t\tbatch0 != null && batch0.length > 0\n\t\t\t\t\t\t? (batch0.at(-1) as LLMResponse | undefined)\n\t\t\t\t\t\t: (ctx.prevData[0] as LLMResponse | undefined);\n\t\t\t\tif (resp === undefined) return;\n\t\t\t\tconst prev = (costNode.cache as CostState | undefined) ?? ZERO_COST;\n\t\t\t\tconst turns = (this.loop.turn.cache as number | undefined) ?? prev.turns;\n\t\t\t\tconst next: CostState = {\n\t\t\t\t\tusage: resp.usage != null ? addUsage(prev.usage, resp.usage) : prev.usage,\n\t\t\t\t\tturns,\n\t\t\t\t};\n\t\t\t\tcostNode.emit(next);\n\t\t\t},\n\t\t\t{ describeKind: \"effect\", meta: aiMeta(\"agent_cost_rollup\") },\n\t\t);\n\t\tthis.addDisposer(keepalive(costEff));\n\n\t\t// --- 9. `in` → input queue → drain → kick the loop. ----------------\n\t\t// Phase 13.G/H + /qa N1(b) lock (2026-05-01): bundle.in is a\n\t\t// writable surface, but kicks are queued through an internal\n\t\t// hub-style topic + cursor subscription. Out-of-the-box queueing —\n\t\t// caller fires `in.emit(x)` while the agent is mid-run; the input\n\t\t// is parked on the queue and picked up when the loop returns to\n\t\t// `idle` / `done` / `error`. No mid-run reset / cost-leak hazard\n\t\t// (which the prior raw `in.subscribe → kick` path had).\n\t\t//\n\t\t// Topology:\n\t\t// `in` (state Node, writable) → `inputBridge` (subscribe →\n\t\t// publish) → `inputTopic` (TopicGraph<TIn>) → `inputSub`\n\t\t// (SubscriptionGraph<TIn>) → `drainEffect` (effect on\n\t\t// [inputSub.available, loop.status]) → loop kick.\n\t\tconst inMapper = spec.inMapper ?? defaultInMapper<TIn>();\n\t\tconst inputTopic: TopicGraph<TIn> = topic<TIn>(\"input-topic\");\n\t\tthis.mount(\"input-topic\", inputTopic);\n\t\tconst inputSub: SubscriptionGraph<TIn> = subscription<TIn>(\"input-sub\", inputTopic, {\n\t\t\tfrom: \"now\",\n\t\t});\n\t\tthis.mount(\"input-sub\", inputSub);\n\n\t\t// Bridge: `in.emit(x)` publishes to the topic. Validates the\n\t\t// caller-supplied input via `inMapper` at the boundary so the\n\t\t// type error surfaces in the caller's stack frame (not later\n\t\t// during drain). Per the F9 SENTINEL trap, `in` cache is\n\t\t// `undefined` until the first emit; push-on-subscribe delivers\n\t\t// nothing.\n\t\tconst inputBridge = this.in.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tconst input = m[1] as TIn;\n\t\t\t\t// Boundary type-check: throws if TIn is not string and no\n\t\t\t\t// inMapper supplied. Better here than at drain time so the\n\t\t\t\t// caller's `in.emit(...)` raises synchronously.\n\t\t\t\tinMapper(input);\n\t\t\t\tinputTopic.publish(input);\n\t\t\t}\n\t\t});\n\t\tthis.addDisposer(inputBridge);\n\n\t\t// Drain effect: when an input is pending AND the loop is ready\n\t\t// (`idle` / `done` / `error`), pull one and kick. Re-entrancy\n\t\t// guard via `loop.status` — `thinking` / `acting` skip.\n\t\tconst drainEffect = node(\n\t\t\t[inputSub.available, this.loop.status],\n\t\t\t(data, _a, ctx) => {\n\t\t\t\tconst availBatch = data[0];\n\t\t\t\tconst statusBatch = data[1];\n\t\t\t\tconst avail =\n\t\t\t\t\t(availBatch != null && availBatch.length > 0\n\t\t\t\t\t\t? (availBatch.at(-1) as readonly TIn[])\n\t\t\t\t\t\t: ((ctx.prevData[0] as readonly TIn[] | undefined) ?? [])) ?? [];\n\t\t\t\tconst stat =\n\t\t\t\t\t(statusBatch != null && statusBatch.length > 0\n\t\t\t\t\t\t? (statusBatch.at(-1) as string)\n\t\t\t\t\t\t: ((ctx.prevData[1] as string | undefined) ?? \"idle\")) ?? \"idle\";\n\t\t\t\tif (avail.length === 0) return;\n\t\t\t\tif (stat === \"thinking\" || stat === \"acting\") return;\n\t\t\t\tconst result = inputSub.pullAndAck(1);\n\t\t\t\tif (result.items.length === 0) return;\n\t\t\t\tconst input = result.items[0] as TIn;\n\t\t\t\tconst userMsg = inMapper(input);\n\t\t\t\tbatch(() => {\n\t\t\t\t\t// Reset per-input accumulators so cost/turns don't include\n\t\t\t\t\t// the previous input. `lastResponse` is reset via plain\n\t\t\t\t\t// `[[INVALIDATE]]` — under DS-13.5.A INVALIDATE both clears\n\t\t\t\t\t// `_cached` AND settles the consuming wave (decrements\n\t\t\t\t\t// `_dirtyDepCount` like RESOLVED), so dependents like\n\t\t\t\t\t// `out` / `costEff` fire on the next status transition\n\t\t\t\t\t// without staying wedged in DIRTY. Pre-DS-13.5.A this used\n\t\t\t\t\t// the `[[INVALIDATE], [RESOLVED]]` paired-reset workaround.\n\t\t\t\t\tthis.loop.lastResponse.down([[INVALIDATE]]);\n\t\t\t\t\tthis.loop.turn.emit(0);\n\t\t\t\t\tthis.loop.aborted.emit(false);\n\t\t\t\t\tcostNode.emit(ZERO_COST);\n\t\t\t\t\tthis.loop.chat.append(\"user\", userMsg);\n\t\t\t\t\tthis.loop.status.emit(\"thinking\");\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ describeKind: \"effect\", meta: aiMeta(\"agent_input_drain\") },\n\t\t);\n\t\tthis.addDisposer(keepalive(drainEffect));\n\n\t\t// `out` and `status` keepalives are unnecessary because the cost /\n\t\t// status effects above already activate `loop.lastResponse` and\n\t\t// `loop.status` — the derived `out` reads from a kept-alive source.\n\t\t// We do keep `out` alive explicitly so `awaitSettled(bundle.out,\n\t\t// { skipCurrent: true })` works even when no other consumer\n\t\t// subscribes between input and response.\n\t\tthis.addDisposer(keepalive(this.out));\n\n\t\t// Surface in describe.\n\t\tvoid TERMINAL_STATUSES;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Default mappers\n// ---------------------------------------------------------------------------\n\n/**\n * Default `inMapper` for `TIn extends string`. Asserts the runtime type at\n * the boundary so callers who omit `inMapper` for a non-string `TIn` get a\n * clear error rather than a silent passthrough.\n */\nfunction defaultInMapper<TIn>(): (input: TIn) => string {\n\treturn (input) => {\n\t\tif (typeof input !== \"string\") {\n\t\t\tthrow new TypeError(\n\t\t\t\t`agent: inMapper is required when TIn is not a string (got ${typeof input}). Pass spec.inMapper.`,\n\t\t\t);\n\t\t}\n\t\treturn input;\n\t};\n}\n\n/**\n * Default `outMapper` for `TOut extends LLMResponse`. Asserts the response\n * shape at the boundary; callers with a non-LLMResponse `TOut` must\n * provide `outMapper`.\n */\nfunction defaultOutMapper<TOut>(): (response: LLMResponse) => TOut {\n\treturn (response) => response as unknown as TOut;\n}\n","/**\n * Composable safety layer (roadmap §9.0b — Tier 5.1 Wave-B rebuild).\n *\n * {@link guardedExecution} wraps any {@link Graph} with:\n *\n * - {@link policyGate} — reactive ABAC (Tier 2.3 rename of `policyEnforcer`),\n * policies stored as a `Node` so LLMs / humans can update them at runtime.\n * Full transitive dynamic coverage via `watchTopologyTree`.\n * - Reactive {@link GuardedExecutionGraph.scopedDescribeNode} — a thin\n * delegate over `target.describe({ reactive: true, actor })` that re-derives\n * on every settle (topology change, error transition, actor swap).\n * - The enforcer's `violations` topic is republished as `violations` on\n * the wrapper, composable with {@link graphLens}'s `health`.\n * - The wrapper-level `lints` topic surfaces non-policy diagnostic warnings\n * (`empty-policies` / `audit-no-effect` / `no-actor`) so misconfigurations\n * are caught reactively rather than via thrown errors at scattered call sites.\n * - The `scope` derived publishes the current configuration tuple\n * (`{actor, mode, policiesCount}`) for dashboards.\n *\n * V1 scope: policies + actor + reactive scoped describe + lints + scope.\n * Budget-as-option is NOT in V1 — it requires a cost-tracking design that\n * hasn't landed yet. Callers who need a budget limit today append a\n * budget-aware {@link PolicyRuleData} to the policies list (check current\n * cost and `deny` when exhausted).\n *\n * @module\n */\nimport type { Actor, PolicyRuleData } from \"@graphrefly/pure-ts/core\";\nimport { DATA, monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport {\n\ttype DescribeFilter,\n\tGraph,\n\ttype GraphDescribeOptions,\n\ttype GraphDescribeOutput,\n\ttype GraphOptions,\n} from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport {\n\ttype PolicyGateGraph,\n\ttype PolicyViolation,\n\tpolicyGate,\n} from \"../../utils/inspect/audit.js\";\nimport { TopicGraph } from \"../../utils/messaging/index.js\";\n\nfunction isNode<T>(x: unknown): x is Node<T> {\n\treturn (\n\t\ttypeof x === \"object\" && x !== null && \"subscribe\" in (x as object) && \"down\" in (x as object)\n\t);\n}\n\nfunction guardedMeta(kind: string): Record<string, unknown> {\n\treturn domainMeta(\"guarded\", kind);\n}\n\n/** Diagnostic warning published on {@link GuardedExecutionGraph.lints}. */\nexport interface GuardedExecutionLint {\n\t/**\n\t * - `\"empty-policies\"` — `policies` Node emitted an empty array in\n\t * `mode: \"enforce\"`. Static empty arrays throw at construction; this\n\t * covers the reactive case.\n\t * - `\"audit-no-effect\"` — `mode: \"audit\"` plus the target has no per-node\n\t * guards, so `scopedDescribeNode` filters by per-node guards only and\n\t * policies will never gate visibility (they still populate `violations`\n\t * on writes).\n\t * - `\"no-actor\"` — neither a wrapper-configured nor per-call actor was\n\t * supplied. `scopedDescribeNode` falls back to \"describe everything\"\n\t * for the corresponding subscription.\n\t */\n\tkind: \"empty-policies\" | \"audit-no-effect\" | \"no-actor\";\n\tmessage: string;\n\ttimestamp_ns: number;\n}\n\n/** Configuration tuple published on {@link GuardedExecutionGraph.scope}. */\nexport interface GuardedScope {\n\t/** The wrapper-configured default actor, or `null` when none configured. */\n\tactor: Actor | null;\n\tmode: \"audit\" | \"enforce\";\n\t/** Current policy count (reactive — re-emits on `policies` Node updates). */\n\tpoliciesCount: number;\n}\n\n/** Options for {@link guardedExecution}. */\nexport interface GuardedExecutionOptions {\n\t/**\n\t * Policies enforced against every guarded write. Static list or a live\n\t * `Node<readonly PolicyRuleData[]>` (LLM-updatable).\n\t *\n\t * **Empty-policies handling:**\n\t * - Static empty array + `mode: \"enforce\"` throws `RangeError` at\n\t * construction (deny-by-default is almost certainly a misconfiguration).\n\t * - Node-supplied empty array + `mode: \"enforce\"` emits a one-time\n\t * `\"empty-policies\"` lint on first such emission (the wrapper can't\n\t * throw mid-run — surface the warning reactively).\n\t * - `mode: \"audit\"` tolerates empty policies (no guards stacked; policies\n\t * only feed the `violations` channel on writes).\n\t */\n\tpolicies: readonly PolicyRuleData[] | Node<readonly PolicyRuleData[]>;\n\t/**\n\t * Default actor used when the caller invokes\n\t * {@link GuardedExecutionGraph.scopedDescribeNode} without an override.\n\t * Accepts a static {@link Actor} or a `Node<Actor>` — when a Node is\n\t * supplied, the reactive describe re-derives on every actor emission so\n\t * harnesses binding a per-turn actor get a single live describe Node\n\t * instead of re-creating one per turn.\n\t *\n\t * Omit to scope per-call only. A `\"no-actor\"` lint fires once per instance\n\t * if neither a configured nor per-call actor is ever supplied (the\n\t * resulting describe is unscoped — full visibility).\n\t */\n\tactor?: Actor | Node<Actor>;\n\t/**\n\t * `\"enforce\"` (default) — push guards onto target nodes so disallowed\n\t * writes throw {@link GuardDenied}.\n\t * `\"audit\"` — record would-be denials to the `violations` topic without\n\t * blocking writes.\n\t */\n\tmode?: \"audit\" | \"enforce\";\n\t/** Ring-buffer cap for the `violations` topic. Default 1000 (inherited from policyGate). */\n\tviolationsLimit?: number;\n\t/** Ring-buffer cap for the `lints` topic. Default 64 — each lint kind fires at most once per instance. */\n\tlintsLimit?: number;\n\t/** Wrapper graph name. Default `${target.name}_guarded`. */\n\tname?: string;\n\t/** Wrapper graph options. */\n\tgraph?: GraphOptions;\n}\n\n/**\n * Wrapper over a target {@link Graph} providing reactive ABAC + reactive\n * scoped describe + diagnostic lints. Mounts a {@link PolicyGateGraph} under\n * `enforcer`, a {@link TopicGraph} of {@link GuardedExecutionLint} under\n * `lints`, and a `scope` derived publishing `{actor, mode, policiesCount}`.\n *\n * @category patterns\n */\nexport class GuardedExecutionGraph extends Graph {\n\treadonly enforcer: PolicyGateGraph;\n\treadonly violations: TopicGraph<PolicyViolation>;\n\treadonly lints: TopicGraph<GuardedExecutionLint>;\n\treadonly scope: Node<GuardedScope>;\n\t/**\n\t * Canonical reactive describe scoped to the wrapper's configured `actor`.\n\t * Subscribes ONCE at construction; lifecycle owned by the wrapper (disposed\n\t * on `wrapper.destroy()`). Use this property for the common case\n\t * (long-lived consumer wanting \"describe scoped to my actor\"); use\n\t * {@link scopedDescribeNode} only when a per-call actor override or\n\t * different `detail`/`fields` is required.\n\t *\n\t * Re-derives on every settle of the target graph: structural changes,\n\t * status transitions (errors flip nodes into `\"errored\"`), and actor\n\t * emissions (when a `Node<Actor>` is bound, including the SENTINEL bridge\n\t * applied internally — see qa G1B).\n\t */\n\treadonly scopedDescribe: Node<GraphDescribeOutput>;\n\tprivate readonly _target: Graph;\n\tprivate readonly _actorNode: Node<Actor | null>;\n\tprivate readonly _mode: \"audit\" | \"enforce\";\n\tprivate readonly _firedLintKinds = new Set<GuardedExecutionLint[\"kind\"]>();\n\n\tconstructor(target: Graph, opts: GuardedExecutionOptions) {\n\t\tsuper(opts.name ?? `${target.name}_guarded`, opts.graph);\n\t\tthis._target = target;\n\t\tthis._mode = opts.mode ?? \"enforce\";\n\n\t\tconst policiesOpt = opts.policies;\n\t\tconst policiesIsNode = isNode<readonly PolicyRuleData[]>(policiesOpt);\n\t\t// Static empty + enforce → throw (deny-by-default = misconfig).\n\t\tif (\n\t\t\t!policiesIsNode &&\n\t\t\tthis._mode === \"enforce\" &&\n\t\t\t(policiesOpt as readonly PolicyRuleData[]).length === 0\n\t\t) {\n\t\t\tthrow new RangeError(\n\t\t\t\t'guardedExecution: empty `policies` in `mode: \"enforce\"` denies every action. ' +\n\t\t\t\t\t'Pass at least `{ effect: \"allow\", action: \"*\" }` and layer deny rules on top.',\n\t\t\t);\n\t\t}\n\n\t\t// Lints topic — mounted before any potential first-DATA emission.\n\t\tthis.lints = new TopicGraph<GuardedExecutionLint>(\"lints\", {\n\t\t\tretainedLimit: opts.lintsLimit ?? 64,\n\t\t});\n\t\tthis.mount(\"lints\", this.lints);\n\n\t\t// Normalize `actor` to a Node<Actor | null>. `null` (a valid DATA in\n\t\t// the v5 sentinel-as-undefined model) means \"no actor configured\" —\n\t\t// `target.describe({ reactive: true })`'s `resolveActorOption` treats\n\t\t// `null` cache as \"no scoping\" (full visibility), and the `scope`\n\t\t// derived can publish `actor: null` cleanly. Using `node([], { initial: undefined })`\n\t\t// here would leave the actor node in sentinel state, which never fires\n\t\t// DATA on subscribe and would block the `scope` derived's first-run\n\t\t// gate from completing.\n\t\t//\n\t\t// qa G1B (EC2 fix): when the caller passes a `Node<Actor>`, that node's\n\t\t// cache may itself be SENTINEL at construction (e.g. a `producer`\n\t\t// awaiting first emission, or a deferred `derived`). Forwarding the raw\n\t\t// Node would re-introduce the same sentinel-stall on `scope`. Bridge\n\t\t// through a node bridge with a `null` initial so the\n\t\t// internal `_actorNode` always carries non-sentinel cache; the bridge\n\t\t// re-emits whenever the caller's Node emits, and forwards `null`\n\t\t// through unchanged.\n\t\tconst actorOpt = opts.actor;\n\t\tif (actorOpt == null) {\n\t\t\tthis._actorNode = node<Actor | null>([], { name: \"actor\", initial: null });\n\t\t} else if (isNode<Actor>(actorOpt)) {\n\t\t\tthis._actorNode = node<Actor | null>(\n\t\t\t\t[actorOpt],\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] as Actor | null | undefined) ?? null);\n\t\t\t\t},\n\t\t\t\t{ describeKind: \"derived\", name: \"actor\", initial: null },\n\t\t\t);\n\t\t} else {\n\t\t\tthis._actorNode = node<Actor | null>([], { name: \"actor\", initial: actorOpt });\n\t\t}\n\n\t\t// Mount the enforcer.\n\t\tconst enforcerOpts: { mode: \"audit\" | \"enforce\"; name: string; violationsLimit?: number } = {\n\t\t\tmode: this._mode,\n\t\t\tname: \"enforcer\",\n\t\t};\n\t\tif (opts.violationsLimit != null) enforcerOpts.violationsLimit = opts.violationsLimit;\n\t\tthis.enforcer = policyGate(target, opts.policies, enforcerOpts);\n\t\tthis.violations = this.enforcer.violations;\n\t\tthis.mount(\"enforcer\", this.enforcer);\n\n\t\t// Empty-policies one-time lint (Node form, enforce mode only).\n\t\tif (policiesIsNode && this._mode === \"enforce\") {\n\t\t\tconst policiesNode = policiesOpt as Node<readonly PolicyRuleData[]>;\n\t\t\t// Two paths here intentionally:\n\t\t\t// (1) Synchronous cache seed — fires immediately if the Node was\n\t\t\t// constructed with an empty array as its current cache. This\n\t\t\t// covers `node<…[]>([], { initial: [] })` and any pre-emitted derived.\n\t\t\t// (2) Subscribe path — catches subsequent empty emissions AND\n\t\t\t// handles the SENTINEL case (cache=undefined at construction)\n\t\t\t// where the Node fires its first DATA after the wrapper is\n\t\t\t// built. The `_firedLintKinds` Set keeps the lint one-shot\n\t\t\t// across both paths.\n\t\t\t// qa F6 (deferred): if a Node's initial cache is SENTINEL (undefined)\n\t\t\t// AND it never emits an empty array (only ever non-empty), the lint\n\t\t\t// never fires — that's correct behavior, the configuration is\n\t\t\t// effectively non-empty for the wrapper's lifetime.\n\t\t\tconst cached = policiesNode.cache as readonly PolicyRuleData[] | undefined;\n\t\t\tif (cached != null && cached.length === 0) {\n\t\t\t\tthis._fireLint(\n\t\t\t\t\t\"empty-policies\",\n\t\t\t\t\t'`policies` Node cached an empty array in `mode: \"enforce\"` — every action will be denied. Add at least one allow rule.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst offEmpty = policiesNode.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 v = m[1] as readonly PolicyRuleData[] | undefined;\n\t\t\t\t\tif (v == null || v.length === 0) {\n\t\t\t\t\t\tthis._fireLint(\n\t\t\t\t\t\t\t\"empty-policies\",\n\t\t\t\t\t\t\t'`policies` Node emitted an empty array in `mode: \"enforce\"` — every action will be denied. Add at least one allow rule.',\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(offEmpty);\n\t\t}\n\n\t\t// Audit-mode + no per-node guards on the target → fire once.\n\t\t// qa EC5 (deferred): the check is one-shot at construction. If the\n\t\t// caller later mounts a guarded node into the target, the lint stays\n\t\t// retained even though the configuration is now effective. Recommended\n\t\t// pattern: mount per-node guards on the target BEFORE wrapping.\n\t\t// Reactive recompute (subscribe to target.topology, clear lint when a\n\t\t// guard appears) is filed in `docs/optimizations.md` as a follow-up.\n\t\tif (this._mode === \"audit\") {\n\t\t\tconst described = target.describe({ detail: \"full\" });\n\t\t\tconst anyGuard = Object.values(described.nodes).some((n) => n.guard != null);\n\t\t\tif (!anyGuard) {\n\t\t\t\tthis._fireLint(\n\t\t\t\t\t\"audit-no-effect\",\n\t\t\t\t\t'`mode: \"audit\"` + target has no per-node guards — `scopedDescribeNode` filters by per-node guards only, so policy rules will not affect describe() visibility. Policies still populate the `violations` topic on writes.',\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// No-actor lint: fires at construction when neither configured nor\n\t\t// implicitly carried via a Node-cache. Per-call overrides on\n\t\t// `scopedDescribeNode` cannot retroactively suppress this — the\n\t\t// configured-default branch is what callers most often miss.\n\t\tif (actorOpt == null) {\n\t\t\tthis._fireLint(\n\t\t\t\t\"no-actor\",\n\t\t\t\t\"no actor configured — `wrapper.scopedDescribe` and `scopedDescribeNode()` will return an unscoped describe (full visibility) unless a per-call actor is supplied.\",\n\t\t\t);\n\t\t}\n\n\t\t// Scope derived: live tuple of {actor, mode, policiesCount}.\n\t\tthis.scope = node<GuardedScope>(\n\t\t\t[this._actorNode, this.enforcer.policies],\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({\n\t\t\t\t\tactor: (data[0] as Actor | null | undefined) ?? null,\n\t\t\t\t\tmode: this._mode,\n\t\t\t\t\tpoliciesCount: (data[1] as readonly PolicyRuleData[]).length,\n\t\t\t\t});\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"scope\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: guardedMeta(\"scope\"),\n\t\t\t},\n\t\t);\n\t\tthis.add(this.scope, { name: \"scope\" });\n\t\tthis.addDisposer(keepalive(this.scope));\n\n\t\t// qa G1A \"same concept\": single canonical reactive describe bound to\n\t\t// the configured actor, mounted once at construction. Removes the\n\t\t// per-call handle proliferation from the prior `scopedDescribeNode`\n\t\t// pattern (the method is retained as the per-call escape hatch). The\n\t\t// reactive describe re-derives on actor swap / topology change /\n\t\t// status transition; lifecycle owned by the wrapper.\n\t\tconst scopedHandle = target.describe({\n\t\t\treactive: true,\n\t\t\t// F8 (Tier 5.2): `_actorNode` is `Node<Actor | null>`. The cast is\n\t\t\t// safe at runtime per the `resolveActorOption` null-tolerance\n\t\t\t// contract — `null` / `undefined` cache is treated as \"no scoping\"\n\t\t\t// (full visibility). See `scopedDescribeNode` for the matching\n\t\t\t// per-call site and graph.ts § \"Cache-undefined semantics\".\n\t\t\tactor: this._actorNode as Node<Actor>,\n\t\t\treactiveName: \"scopedDescribe\",\n\t\t});\n\t\tthis.scopedDescribe = scopedHandle.node;\n\t\tthis.add(this.scopedDescribe, { name: \"scopedDescribe\" });\n\t\tthis.addDisposer(scopedHandle.dispose);\n\t}\n\n\tprivate _fireLint(kind: GuardedExecutionLint[\"kind\"], message: string): void {\n\t\tif (this._firedLintKinds.has(kind)) return;\n\t\tthis._firedLintKinds.add(kind);\n\t\tthis.lints.publish({ kind, message, timestamp_ns: monotonicNs() });\n\t}\n\n\t/**\n\t * **Per-call escape hatch.** Prefer {@link scopedDescribe} (the mounted\n\t * property) for the common case of \"describe scoped to my actor.\" Use\n\t * this method ONLY when you need a per-call actor override or different\n\t * `detail`/`fields`/`filter`.\n\t *\n\t * Returns a live `Node<GraphDescribeOutput>` scoped to the supplied (or\n\t * configured) actor, plus an explicit `dispose` for caller-controlled\n\t * lifecycle. Re-derives on every settle of the target graph: structural\n\t * changes, status transitions, and actor emissions (when a `Node<Actor>`\n\t * is bound).\n\t *\n\t * **Lifecycle (qa G1A — EC1 fix).** Each call instantiates a fresh\n\t * `target.describe({reactive: true})` handle (with its own version state,\n\t * observe handle, transitive topology subscriptions, derived + keepalive).\n\t * The caller MUST invoke the returned `dispose()` when finished to release\n\t * these resources. Disposers ARE also tracked on the wrapper graph so\n\t * `wrapper.destroy()` cleans up any handles the caller forgot — but a\n\t * long-lived wrapper with heavy per-call usage will leak until destroy\n\t * unless `dispose()` is called explicitly.\n\t *\n\t * @param actorOverride - Optional per-call override. Static {@link Actor}\n\t * or `Node<Actor>`. Omit to use the wrapper-configured default.\n\t * @param opts - Standard {@link GraphDescribeOptions} fields (`detail`,\n\t * `fields`, `filter`). `actor` / `reactive` / `reactiveName` are\n\t * controlled by the wrapper.\n\t * @returns `{node, dispose}` — `node` is the live describe Node; `dispose`\n\t * tears down the underlying reactive describe subscription idempotently.\n\t */\n\tscopedDescribeNode(\n\t\tactorOverride?: Actor | Node<Actor>,\n\t\topts?: Omit<GraphDescribeOptions, \"actor\" | \"reactive\" | \"reactiveName\">,\n\t): { node: Node<GraphDescribeOutput>; dispose: () => void } {\n\t\tconst actorNode =\n\t\t\tactorOverride == null\n\t\t\t\t? this._actorNode\n\t\t\t\t: isNode<Actor>(actorOverride)\n\t\t\t\t\t? actorOverride\n\t\t\t\t\t: node<Actor>([], { name: \"actor_override\", initial: actorOverride });\n\t\tconst handle = this._target.describe({\n\t\t\treactive: true,\n\t\t\t// `_actorNode` is `Node<Actor | null>`. The `as Node<Actor>` cast is\n\t\t\t// safe at runtime: `_describeReactive` resolves the actor via\n\t\t\t// `resolveActorOption`, which treats `null`/`undefined` cache as\n\t\t\t// \"no scoping\" (full visibility). Documented in graph.ts §\n\t\t\t// \"Cache-undefined semantics.\"\n\t\t\tactor: actorNode as Node<Actor>,\n\t\t\t...(opts ?? {}),\n\t\t});\n\t\t// Track on the wrapper as a safety net for callers who forget to\n\t\t// dispose; explicit `dispose()` is still the canonical lifecycle path.\n\t\tthis.addDisposer(handle.dispose);\n\t\treturn { node: handle.node, dispose: handle.dispose };\n\t}\n\n\t/** The wrapped graph (escape hatch for tooling). */\n\tget target(): Graph {\n\t\treturn this._target;\n\t}\n}\n\n/**\n * Wrap a {@link Graph} with {@link policyGate} plus a reactive scoped describe\n * lens. Returns a {@link GuardedExecutionGraph} that can be mounted, diffed,\n * or composed with {@link graphLens}.\n *\n * @param target - The graph to guard.\n * @param opts - See {@link GuardedExecutionOptions}.\n *\n * @example\n * ```ts\n * const guarded = guardedExecution(app, {\n * actor: node<Actor>([], { initial: { type: \"human\", id: \"alice\" } }), // reactive — re-derive on swap\n * policies: [\n * { effect: \"allow\", action: \"read\", actorType: \"human\" },\n * { effect: \"deny\", action: \"write\", pathPattern: \"system::*\" },\n * ],\n * mode: \"enforce\",\n * });\n *\n * // Canonical: subscribe to the mounted reactive describe (no per-call leak).\n * guarded.scopedDescribe.subscribe((msgs) => { /* live describe per actor / topology change *\\/ });\n * // Per-call escape hatch (different actor / detail) — caller manages dispose.\n * const detailed = guarded.scopedDescribeNode(undefined, { detail: \"standard\" });\n * try { detailed.node.subscribe(/* … *\\/); } finally { detailed.dispose(); }\n * guarded.violations.events.subscribe(msgs => console.log(\"violations:\", msgs));\n * guarded.lints.events.subscribe(msgs => console.warn(\"lints:\", msgs));\n * guarded.scope.subscribe(msgs => console.log(\"scope:\", msgs));\n * ```\n *\n * @category patterns\n */\nexport function guardedExecution(\n\ttarget: Graph,\n\topts: GuardedExecutionOptions,\n): GuardedExecutionGraph {\n\treturn new GuardedExecutionGraph(target, opts);\n}\n\n// Re-export types useful for call sites.\nexport type { DescribeFilter };\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 * Resilience composition with correct nesting order (roadmap §9.0b — Tier 5.2 Wave-B rebuild).\n *\n * {@link resilientPipeline} composes the resilience primitives from\n * `extra/resilience/` in the canonical nesting order:\n *\n * ```text\n * rateLimit → budget → breaker → timeout → retry → fallback → status\n * ```\n *\n * Returns a {@link ResilientPipelineGraph} (Graph subclass) with mounted\n * intermediate nodes and per-layer status companions, replacing the prior\n * bundle return. Each intermediate is mounted under a stable name so\n * `pipeline.describe()` shows the resilience chain in topology snapshots,\n * mermaid renders, and `lens.health` aggregations.\n *\n * **Per-attempt timeout vs. retry ordering.** `timeout` is applied BEFORE\n * `retry` so each retry attempt resubscribes to a fresh deadline (per-attempt\n * semantics). If `timeout` wrapped `retry`, a single deadline would apply to\n * the entire retry chain — not what callers expect.\n *\n * **`breakerOnOpen` + `retry` interaction.** With `breakerOnOpen: \"error\"` AND\n * `retry`, retry sees `CircuitOpenError` and resubscribes; the next attempt\n * very likely also breaker-open → another error → retry burns its budget\n * against an open circuit. Either set retry's `backoff` long enough for the\n * breaker reset window OR keep the default `breakerOnOpen: \"skip\"` (emits\n * RESOLVED when open; downstream drops the beat without retry firing).\n *\n * **Reactive options (switchMap rebuild).** Every primitive option accepts a\n * `T | Node<T>` (precedent-aligned with `FallbackInput<T>`). When the caller\n * supplies a static value, the layer is built once at construction. When the\n * caller supplies a `Node<T>`, the pipeline subscribes via `switchMap` and\n * **rebuilds the layer on every option emission** — the chain stalls until\n * the option Node emits its first DATA. Each rebuild creates a fresh\n * primitive instance, so internal state is lost (rate-limiter pending buffer,\n * breaker failure count, retry attempt count, in-flight timeout). Per-layer\n * **companion Nodes** (`droppedCount`, `rateLimitState`, `breakerState`) are\n * therefore exposed ONLY for the static-options path. Primitive-side widening\n * (filed in `docs/optimizations.md` under \"Tier 5.2 follow-up — primitive-side\n * reactive-options widening\") will preserve internal state once it lands and\n * the pipeline will trivially forward Node-form options to the primitive.\n *\n * @module\n */\nimport { ERROR, type Node, node, placeholderArgs } from \"@graphrefly/pure-ts/core\";\nimport { switchMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport { NS_PER_MS } from \"../../base/resilience/backoff.js\";\nimport {\n\ttype BreakerState,\n\ttype BudgetConstraint,\n\tbudgetGate,\n\ttype CircuitBreakerOptions,\n\tcircuitBreaker,\n\ttype FallbackInput,\n\tfallback,\n\ttype NodeOrValue,\n\ttype RateLimiterOptions,\n\ttype RateLimiterState,\n\ttype RetryOptions,\n\ttype RetryState,\n\trateLimiter,\n\tretry,\n\ttype StatusValue,\n\ttype TimeoutOptions,\n\ttype TimeoutState,\n\twithBreaker,\n\twithStatus,\n\twithTimeout,\n} from \"../../utils/resilience/index.js\";\n\n// ---------------------------------------------------------------------------\n// Reactive-option helpers\n// ---------------------------------------------------------------------------\n\n/**\n * `T | Node<T>` for primitive options — precedent-aligned with\n * {@link FallbackInput} and `policyGate.policies`. When the caller supplies a\n * static value, the layer is built once at construction. When the caller\n * supplies a `Node<T>`, the pipeline subscribes via {@link switchMap}: the\n * layer is rebuilt on every option emission. **State-loss caveat:** each\n * rebuild creates a fresh primitive instance — `rateLimiter` loses its pending\n * buffer, `circuitBreaker` resets failure count, `retry` resets attempt\n * count, `timeout` cancels in-flight deadline. This is the documented\n * switchMap-pattern semantics; primitive-side widening (filed in\n * `docs/optimizations.md`) will preserve internal state once it lands and the\n * pipeline can forward Node-form options directly.\n *\n * Per-layer **companion Nodes** (`droppedCount`, `rateLimitState`,\n * `breakerState`) are exposed only for the static-options path — Node-form\n * leaves them as `undefined` because each rebuild creates new companion\n * instances and a switchMap-mirrored companion would track only the latest\n * bundle. Callers needing both reactive options AND companions wait for\n * primitive-side widening.\n */\n// NodeOrValue re-imported from utils/resilience (same type, avoid barrel duplicate).\n\nfunction isNode<T>(x: unknown): x is Node<T> {\n\treturn (\n\t\ttypeof x === \"object\" && x !== null && \"subscribe\" in (x as object) && \"down\" in (x as object)\n\t);\n}\n\n/**\n * Validation shared by the static and reactive timeout paths. The reactive\n * path runs this inside the `switchMap` projection so an emitted bad value\n * surfaces as a thrown error at projection time (the consuming subscribe\n * routes it through the reactive ERROR channel rather than crashing\n * construction).\n */\nfunction assertTimeoutMsValid(ms: number): void {\n\tif (ms <= 0) throw new RangeError(\"timeoutMs must be > 0\");\n\t// Guard against `timeoutMs * NS_PER_MS` overflowing\n\t// `Number.MAX_SAFE_INTEGER` (~9.007e15). 9_000_000 ms ≈ 2.5 hours is a\n\t// sane upper bound; callers needing longer deadlines should express them\n\t// at the primitive level.\n\tif (ms > 9_000_000) {\n\t\tthrow new RangeError(\n\t\t\t\"timeoutMs must be <= 9_000_000 (≈2.5h) to stay within safe ns arithmetic\",\n\t\t);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link resilientPipeline}. Every layer is optional — omit a\n * field and that layer is skipped.\n *\n * Reactive (`Node<T>`) forms are accepted everywhere a primitive value would\n * fit; the pipeline subscribes via `switchMap` and rebuilds the layer on each\n * emission. See module JSDoc for the rebuild semantics + state-loss caveat.\n */\nexport interface ResilientPipelineOptions<T> {\n\t/**\n\t * Admission control — at most `maxEvents` `DATA` per `windowNs`. See\n\t * {@link rateLimiter}.\n\t *\n\t * `maxBuffer` is optional at the pipeline layer (defaults to `Infinity`,\n\t * preserving the historical unbounded behavior). Pass an explicit positive\n\t * integer to opt in to a bounded queue.\n\t */\n\trateLimit?: NodeOrValue<Omit<RateLimiterOptions, \"maxBuffer\"> & { maxBuffer?: number }>;\n\t/** Cost/constraint gate. See {@link budgetGate}. */\n\tbudget?: NodeOrValue<ReadonlyArray<BudgetConstraint>>;\n\t/** Circuit breaker — fail-fast when the downstream resource is unhealthy. See {@link circuitBreaker}. */\n\tbreaker?: NodeOrValue<CircuitBreakerOptions>;\n\t/**\n\t * Behavior when the breaker is open:\n\t * - `\"skip\"` (default) — emit `RESOLVED` (lets downstream drop the beat).\n\t * - `\"error\"` — emit a `CircuitOpenError` so `retry` / `fallback` can react.\n\t * See module JSDoc for the retry-budget burn caveat.\n\t *\n\t * Static (configuration-only — no reactive form).\n\t */\n\tbreakerOnOpen?: \"skip\" | \"error\";\n\t/** Retry policy on terminal `ERROR`. See {@link retry}. */\n\tretry?: NodeOrValue<RetryOptions>;\n\t/**\n\t * Per-attempt deadline in milliseconds. Converted to ns internally. Omit\n\t * to skip the timeout wrap.\n\t *\n\t * Specified in ms (not ns) because callers consistently think in\n\t * millisecond deadlines; the underlying {@link timeout} primitive takes ns\n\t * internally.\n\t */\n\ttimeoutMs?: NodeOrValue<number>;\n\t/** Final fallback value emitted on terminal `ERROR` after retry exhausts. See {@link fallback}. */\n\tfallback?: FallbackInput<T>;\n\t/**\n\t * Initial status reported by the status node. Default `\"pending\"`. Static.\n\t */\n\tinitialStatus?: StatusValue;\n\t/** Wrapper graph name. Default `\"resilient_pipeline\"`. */\n\tname?: string;\n\t/** Wrapper graph options. */\n\tgraph?: GraphOptions;\n}\n\n// ---------------------------------------------------------------------------\n// ResilientPipelineGraph\n// ---------------------------------------------------------------------------\n\n/**\n * Graph subclass returned by {@link resilientPipeline}. Mounts each\n * configured intermediate under a stable name and exposes per-layer status\n * companions.\n *\n * @category patterns\n */\nexport class ResilientPipelineGraph<T> extends Graph {\n\t/**\n\t * Final resilient node — subscribe to this for `DATA` emissions.\n\t *\n\t * Named `output` (not `node`) because `Graph.node(name)` already names the\n\t * path-resolution method on the base class; a `readonly node` field would\n\t * shadow it.\n\t */\n\treadonly output: Node<T>;\n\t/** Live status: `\"pending\" | \"running\" | \"completed\" | \"errored\"`. */\n\treadonly status: Node<StatusValue>;\n\t/**\n\t * Last error payload, or `null` when not errored.\n\t *\n\t * Named `lastError` (not `error`) because `Graph.error(name, err)` already\n\t * names a method on the base class.\n\t */\n\treadonly lastError: Node<unknown | null>;\n\t/** Breaker state when `opts.breaker` is provided; `undefined` otherwise. */\n\treadonly breakerState: Node<BreakerState> | undefined;\n\t/**\n\t * Timeout state companion when `opts.timeoutMs` is supplied as a\n\t * `Node<Partial<TimeoutOptions>>`-like form; `undefined` otherwise\n\t * (DS-13.5.B forwarding contract — Node-form opts skip the switchMap\n\t * rebuild and lift the primitive's lifecycle companion onto the\n\t * pipeline bundle).\n\t */\n\treadonly timeoutState: Node<TimeoutState> | undefined;\n\t/**\n\t * Retry state companion when `opts.retry` is supplied as a\n\t * `Node<RetryOptions>`-like form; `undefined` otherwise\n\t * (DS-13.5.B forwarding contract).\n\t */\n\treadonly retryState: Node<RetryState> | undefined;\n\t/**\n\t * Drop-counter when `opts.rateLimit` is provided; `undefined` otherwise.\n\t *\n\t * **Lifetime note:** `droppedCount` retains its final value through\n\t * terminal (`COMPLETE` / `ERROR` / `TEARDOWN`); the underlying counter\n\t * resets to `0` only at the next subscription cycle.\n\t */\n\treadonly droppedCount: Node<number> | undefined;\n\t/**\n\t * Combined rate-limit state when `opts.rateLimit` is provided; `undefined`\n\t * otherwise. Same lifecycle as {@link droppedCount} but exposes\n\t * `pendingCount` and `paused` alongside the drop counter for richer\n\t * backpressure observability (Tier 5.2 D7).\n\t */\n\treadonly rateLimitState: Node<RateLimiterState> | undefined;\n\n\tconstructor(source: Node<T>, opts: ResilientPipelineOptions<T> = {}) {\n\t\tsuper(opts.name ?? \"resilient_pipeline\", opts.graph);\n\n\t\tlet current: Node<T> = source;\n\t\tlet droppedCount: Node<number> | undefined;\n\t\tlet rateLimitState: Node<RateLimiterState> | undefined;\n\t\tlet breakerState: Node<BreakerState> | undefined;\n\t\tlet timeoutState: Node<TimeoutState> | undefined;\n\t\tlet retryState: Node<RetryState> | undefined;\n\n\t\t// 1. Admission control — cheapest to drop / queue before any other work.\n\t\tif (opts.rateLimit != null) {\n\t\t\tif (isNode<Omit<RateLimiterOptions, \"maxBuffer\"> & { maxBuffer?: number }>(opts.rateLimit)) {\n\t\t\t\t// DS-13.5.B forwarding: rateLimiter primitive is widened to\n\t\t\t\t// accept `NodeOrValue<RateLimiterOptions>` directly. Forward\n\t\t\t\t// the Node form to preserve internal state (pending buffer,\n\t\t\t\t// dropped counter) across opts swaps. Companion nodes\n\t\t\t\t// (droppedCount / rateLimitState) lift onto the pipeline\n\t\t\t\t// bundle. The pre-DS-13.5.B switchMap-rebuild path is gone.\n\t\t\t\tconst bundle = rateLimiter(current, opts.rateLimit as NodeOrValue<RateLimiterOptions>);\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\tdroppedCount = bundle.droppedCount;\n\t\t\t\trateLimitState = bundle.rateLimitState;\n\t\t\t\tthis.add(current, { name: \"rateLimited\" });\n\t\t\t\tthis.add(droppedCount, { name: \"droppedCount\" });\n\t\t\t\tthis.add(rateLimitState, { name: \"rateLimitState\" });\n\t\t\t} else {\n\t\t\t\tconst rateOpts: RateLimiterOptions = {\n\t\t\t\t\t...opts.rateLimit,\n\t\t\t\t\tmaxBuffer: opts.rateLimit.maxBuffer ?? Infinity,\n\t\t\t\t\tmeta: domainMeta(\"resilient\", \"rate-limit\"),\n\t\t\t\t};\n\t\t\t\tconst bundle = rateLimiter(current, rateOpts);\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\tdroppedCount = bundle.droppedCount;\n\t\t\t\trateLimitState = bundle.rateLimitState;\n\t\t\t\tthis.add(current, { name: \"rateLimited\" });\n\t\t\t\tthis.add(droppedCount, { name: \"droppedCount\" });\n\t\t\t\tthis.add(rateLimitState, { name: \"rateLimitState\" });\n\t\t\t}\n\t\t}\n\n\t\t// 2. Budget — block when constraints are exhausted. Also cheap (no I/O).\n\t\tif (opts.budget != null) {\n\t\t\tif (isNode<ReadonlyArray<BudgetConstraint>>(opts.budget)) {\n\t\t\t\tconst inputForLayer = current;\n\t\t\t\tconst reactiveBudget = opts.budget;\n\t\t\t\tcurrent = switchMap(reactiveBudget, (constraints) =>\n\t\t\t\t\tconstraints.length > 0\n\t\t\t\t\t\t? budgetGate(inputForLayer, constraints, {\n\t\t\t\t\t\t\t\tmeta: domainMeta(\"resilient\", \"budget\"),\n\t\t\t\t\t\t\t}).node\n\t\t\t\t\t\t: inputForLayer,\n\t\t\t\t);\n\t\t\t\tthis.add(current, { name: \"budgetGated\" });\n\t\t\t} else if (opts.budget.length > 0) {\n\t\t\t\tcurrent = budgetGate(current, opts.budget, {\n\t\t\t\t\tmeta: domainMeta(\"resilient\", \"budget\"),\n\t\t\t\t}).node;\n\t\t\t\tthis.add(current, { name: \"budgetGated\" });\n\t\t\t}\n\t\t}\n\n\t\t// 3. Breaker — skip the resource when unhealthy (fail-fast before retry wastes time).\n\t\tif (opts.breaker != null) {\n\t\t\t// DS-13.5.B forwarding: circuitBreaker primitive accepts\n\t\t\t// `NodeOrValue<CircuitBreakerOptions>` directly. Pass the Node\n\t\t\t// form straight through so internal state (`_state`,\n\t\t\t// `_failureCount`, `_openCycle`, …) is preserved across opts\n\t\t\t// swaps. Companion `breakerState` lifts onto the pipeline\n\t\t\t// bundle in both static and Node-form paths.\n\t\t\tconst breaker = circuitBreaker(opts.breaker as NodeOrValue<CircuitBreakerOptions>);\n\t\t\tconst onOpen = opts.breakerOnOpen ?? \"skip\";\n\t\t\tconst wrapped = withBreaker<T>(breaker, {\n\t\t\t\tonOpen,\n\t\t\t\tmeta: domainMeta(\"resilient\", \"breaker\"),\n\t\t\t})(current);\n\t\t\tcurrent = wrapped.node;\n\t\t\tbreakerState = wrapped.breakerState;\n\t\t\tthis.add(current, { name: \"breakerWrapped\" });\n\t\t\tthis.add(breakerState, { name: \"breakerState\" });\n\t\t}\n\n\t\t// 4. Timeout — per-attempt deadline. Applied BEFORE retry so each retry\n\t\t// resubscribes to a fresh timeout. Swapping the order (timeout\n\t\t// OUTSIDE retry) would apply one global deadline to the entire\n\t\t// retry chain — not what callers expect for \"per-attempt timeout.\"\n\t\tif (opts.timeoutMs != null) {\n\t\t\tif (isNode<number>(opts.timeoutMs)) {\n\t\t\t\t// DS-13.5.B forwarding: build a derived `Node<{ns}>` from\n\t\t\t\t// the caller's `Node<number>` (ms) and pass directly to the\n\t\t\t\t// widened timeout primitive. State preservation (in-flight\n\t\t\t\t// deadline) is handled inside timeout's reactive opts path.\n\t\t\t\t// Companion `timeoutState` lifts onto the pipeline bundle.\n\t\t\t\tconst reactiveTimeoutMs = opts.timeoutMs;\n\t\t\t\tconst initialMs = reactiveTimeoutMs.cache as number | undefined;\n\t\t\t\t// QA A5 (2026-05-03): assert validity of the cached initial\n\t\t\t\t// value at construction so a bad cache fails loud at wire\n\t\t\t\t// time, not silently at first emit. Reactive emits with\n\t\t\t\t// invalid values flow through the producer body's ERROR\n\t\t\t\t// channel rather than throwing into the host scheduler.\n\t\t\t\tif (initialMs !== undefined) assertTimeoutMsValid(initialMs);\n\t\t\t\tconst optsBridge = node<Partial<TimeoutOptions>>(\n\t\t\t\t\t[reactiveTimeoutMs as Node<unknown>],\n\t\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst ms = data[0] as number | undefined;\n\t\t\t\t\t\tif (ms === undefined) return;\n\t\t\t\t\t\t// QA A5: route validation failures through the\n\t\t\t\t\t\t// reactive ERROR channel — sync `throw` inside a\n\t\t\t\t\t\t// producer body corrupts the host scheduler's\n\t\t\t\t\t\t// wave dispatch (mirrors timeout primitive's\n\t\t\t\t\t\t// \"sync throw would corrupt the host scheduler\"\n\t\t\t\t\t\t// rationale).\n\t\t\t\t\t\tif (typeof ms !== \"number\" || !Number.isFinite(ms) || ms <= 0 || ms > 9_000_000) {\n\t\t\t\t\t\t\tactions.down([\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\tERROR,\n\t\t\t\t\t\t\t\t\tnew RangeError(\n\t\t\t\t\t\t\t\t\t\t`resilientPipeline: timeoutMs reactive emit invalid (${ms}); must be > 0 and <= 9_000_000.`,\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\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactions.emit({ ns: ms * NS_PER_MS });\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\t\tname: \"timeoutOptsBridge\",\n\t\t\t\t\t\t...(initialMs !== undefined\n\t\t\t\t\t\t\t? { initial: { ns: initialMs * NS_PER_MS } as Partial<TimeoutOptions> }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\t// QA A5: register the bridge on the pipeline graph so\n\t\t\t\t// describe() walks see the full topology (dry-run /\n\t\t\t\t// real-run equivalence per CLAUDE.md).\n\t\t\t\tthis.add(optsBridge, { name: \"timeoutOptsBridge\" });\n\t\t\t\tconst bundle = withTimeout(current, optsBridge, {\n\t\t\t\t\tmeta: domainMeta(\"resilient\", \"timeout\"),\n\t\t\t\t});\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\ttimeoutState = bundle.timeoutState;\n\t\t\t\tthis.add(current, { name: \"timeoutWrapped\" });\n\t\t\t\tthis.add(timeoutState, { name: \"timeoutState\" });\n\t\t\t} else {\n\t\t\t\tassertTimeoutMsValid(opts.timeoutMs);\n\t\t\t\tconst bundle = withTimeout(\n\t\t\t\t\tcurrent,\n\t\t\t\t\t{ ns: opts.timeoutMs * NS_PER_MS },\n\t\t\t\t\t{\n\t\t\t\t\t\tmeta: domainMeta(\"resilient\", \"timeout\"),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\ttimeoutState = bundle.timeoutState;\n\t\t\t\tthis.add(current, { name: \"timeoutWrapped\" });\n\t\t\t\tthis.add(timeoutState, { name: \"timeoutState\" });\n\t\t\t}\n\t\t}\n\n\t\t// 5. Retry — resubscribe on `ERROR` up to `count` times. Wraps timeout\n\t\t// so each retry gets its own fresh deadline.\n\t\tif (opts.retry != null) {\n\t\t\t// DS-13.5.B forwarding: retry primitive accepts\n\t\t\t// `NodeOrValue<RetryOptions>` directly. Forward Node form so\n\t\t\t// `attempt` / `prevDelay` / in-flight timer survive opts swaps.\n\t\t\t// Companion `retryState` lifts onto the pipeline bundle.\n\t\t\tif (isNode<RetryOptions>(opts.retry)) {\n\t\t\t\tconst bundle = retry(current, opts.retry as NodeOrValue<RetryOptions>);\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\tretryState = bundle.retryState;\n\t\t\t\tthis.add(current, { name: \"retryWrapped\" });\n\t\t\t\tthis.add(retryState, { name: \"retryState\" });\n\t\t\t} else {\n\t\t\t\tconst bundle = retry(current, {\n\t\t\t\t\t...opts.retry,\n\t\t\t\t\tmeta: domainMeta(\"resilient\", \"retry\"),\n\t\t\t\t});\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\tretryState = bundle.retryState;\n\t\t\t\tthis.add(current, { name: \"retryWrapped\" });\n\t\t\t\tthis.add(retryState, { name: \"retryState\" });\n\t\t\t}\n\t\t}\n\n\t\t// 6. Fallback — last resort after retry+timeout exhaust. Guard\n\t\t// `opts.fallback !== undefined` so `null` is a valid fallback.\n\t\tif (opts.fallback !== undefined) {\n\t\t\tcurrent = fallback(current, opts.fallback, {\n\t\t\t\tmeta: domainMeta(\"resilient\", \"fallback\"),\n\t\t\t});\n\t\t\tthis.add(current, { name: \"fallbackWrapped\" });\n\t\t}\n\n\t\t// 7. Status wrapping — observability. Always last so it sees the final shape.\n\t\tconst statusBundle = withStatus(current, {\n\t\t\tinitialStatus: opts.initialStatus ?? \"pending\",\n\t\t\tmeta: domainMeta(\"resilient\", \"status\"),\n\t\t});\n\n\t\tthis.output = statusBundle.node;\n\t\tthis.status = statusBundle.status;\n\t\tthis.lastError = statusBundle.error;\n\t\tthis.breakerState = breakerState;\n\t\tthis.droppedCount = droppedCount;\n\t\tthis.rateLimitState = rateLimitState;\n\t\tthis.timeoutState = timeoutState;\n\t\tthis.retryState = retryState;\n\n\t\t// Mount the externally-visible top-level entries by name. Each carries\n\t\t// its own factoryTag meta from the underlying primitive (`withStatus`\n\t\t// for `output`/`status`/`lastError`); domain-level provenance lives on\n\t\t// the Graph itself via the `tagFactory(\"resilientPipeline\", ...)` call\n\t\t// in the public factory below. The mount names use `output` /\n\t\t// `lastError` to match the property names — the previous `node` /\n\t\t// `error` clashed with `Graph.node(name)` / `Graph.error(name, err)`.\n\t\tthis.add(this.output, { name: \"output\" });\n\t\tthis.add(this.status, { name: \"status\" });\n\t\tthis.add(this.lastError, { name: \"lastError\" });\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Compose a resilient pipeline around `source` in the canonical nesting\n * order — `rateLimit → budget → breaker → timeout → retry → fallback → status`.\n * Omit any option to skip that layer.\n *\n * Returns a {@link ResilientPipelineGraph} (Graph subclass) —\n * `pipeline.output` is the externally visible final node; `pipeline.status`\n * / `pipeline.lastError` / `pipeline.breakerState` / `pipeline.droppedCount`\n * are the per-layer companions. Call `pipeline.describe()` to see the\n * mounted intermediates; compose with {@link graphLens}'s `health` for\n * aggregate status.\n *\n * **Naming note:** `output` and `lastError` (not `node` / `error`) avoid\n * clashes with `Graph.node(name)` and `Graph.error(name, err)` on the base\n * class.\n *\n * @param source - Upstream node to wrap.\n * @param opts - See {@link ResilientPipelineOptions}. All fields optional.\n *\n * @example\n * ```ts\n * const safeFetch = resilientPipeline(fetchNode, {\n * rateLimit: { maxEvents: 10, windowNs: NS_PER_SEC },\n * breaker: { failureThreshold: 5 },\n * retry: { count: 3, backoff: \"exponential\" },\n * timeoutMs: 10_000,\n * fallback: null,\n * });\n * safeFetch.output.subscribe(msgs => console.log(msgs));\n * safeFetch.status.subscribe(msgs => console.log(msgs));\n * graphSpecToAscii(safeFetch.describe()); // visualize the chain\n * ```\n *\n * @category patterns\n */\nexport function resilientPipeline<T>(\n\tsource: Node<T>,\n\topts: ResilientPipelineOptions<T> = {},\n): ResilientPipelineGraph<T> {\n\tconst g = new ResilientPipelineGraph<T>(source, opts);\n\t// Self-tag for `graph.describe()` factory provenance (Phase 2.5 DG1=B).\n\t// `placeholderArgs` substitutes Node-typed and function-typed fields with\n\t// `\"<Node>\"` / `\"<function>\"` so `factoryArgs` stays JSON-serializable.\n\tg.tagFactory(\"resilientPipeline\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\treturn g;\n}\n\n// Tag the underlying status / error / breaker / dropped companions with a\n// best-effort factoryTag too via the wrapper class's meta — already covered\n// by `domainMeta(\"resilient\", kind)` on the mounted nodes.\n\n// Tier 9.1 γ-form: this module now lives inside `extra/resilience/`, so the\n// underlying primitive option types are already exported from the same barrel\n// (`./index.js`). The previous re-exports of `factoryTag` / `placeholderArgs` /\n// `NS_PER_MS` / `NS_PER_SEC` / option types were a workaround for the prior\n// `patterns/resilient-pipeline/` folder location and are now redundant.\n"],"mappings":"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","names":["node","clampNonNegative","import_core","import_core","import_extra","import_graph","import_core","import_core","batch","import_core","import_extra","batch","import_core","import_extra","import_core","batch","import_core","import_extra","import_graph","batch","nodeFactory","batch","fallback","import_core","import_extra","import_graph","import_core","import_extra","import_core","import_extra","isNodeLike","keepalive","node","batch","import_core","import_extra","import_graph","ageSeconds","import_core","import_extra","import_graph","import_core","import_extra","import_graph","meta","NS_PER_SEC","batch","out","meta","ageSeconds","import_core","import_core","import_extra","batch","batch","import_core","import_extra","import_graph","import_core","import_core","import_core","import_core","import_extra","import_core","import_core","import_extra","import_graph","batch","import_core","import_graph","batch","import_core","import_extra","import_graph","import_core","import_extra","import_graph","DEFAULT_MAX_PER_PUMP","requireNonNegativeInt","batch","requireNonNegativeInt","DEFAULT_MAX_PER_PUMP","batch","topic","ageSeconds","import_core","import_extra","import_graph","isNode","createNode","batch","i","best","bestScore","import_core","import_extra","import_graph","import_extra","import_core","import_extra","import_graph","import_core","import_extra","import_graph","import_core","import_extra","import_graph","isNode","batch","node","isNode","isNode","batch","import_core","import_extra","import_graph","isNode"]}
1
+ {"version":3,"sources":["../../src/base/resilience/_internal.ts","../../src/base/resilience/backoff.ts","../../src/base/resilience/timeout.ts","../../src/solutions/index.ts","../../src/presets/ai/agent-loop.ts","../../src/base/sources/settled.ts","../../src/utils/ai/_internal.ts","../../src/base/meta/domain-meta.ts","../../src/utils/ai/agents/chat-stream.ts","../../src/utils/ai/agents/tool-execution.ts","../../src/base/resilience/retry.ts","../../src/utils/ai/agents/tool-registry.ts","../../src/presets/ai/agent-memory.ts","../../src/base/composition/distill.ts","../../src/base/sources/async.ts","../../src/utils/ai/memory/memory-composers.ts","../../src/base/utils/decay.ts","../../src/utils/memory/index.ts","../../src/base/mutation/index.ts","../../src/utils/ai/prompts/prompt-call.ts","../../src/utils/ai/prompts/prompt-node.ts","../../src/presets/harness/harness-loop.ts","../../src/base/resilience/status.ts","../../src/utils/resilience/index.ts","../../src/utils/resilience/breaker.ts","../../src/utils/resilience/budget-gate.ts","../../src/utils/resilience/fallback.ts","../../src/utils/resilience/rate-limiter.ts","../../src/utils/messaging/message.ts","../../src/utils/messaging/index.ts","../../src/utils/orchestration/pipeline-graph.ts","../../src/utils/harness/_internal.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/job-queue/index.ts","../../src/presets/harness/refine-loop.ts","../../src/presets/harness/spawnable.ts","../../src/presets/ai/agents.ts","../../src/presets/ai/agent.ts","../../src/presets/inspect/guarded-execution.ts","../../src/utils/inspect/audit.ts","../../src/presets/resilience/resilient-pipeline.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\tonDeactivation: () => {\n\t\t\t\t\tstopped = true;\n\t\t\t\t\ttimer.cancel();\n\t\t\t\t\tif (srcUnsub) srcUnsub();\n\t\t\t\t\tif (optsUnsub) optsUnsub();\n\t\t\t\t},\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 * Solutions — curated headline-product barrel.\n *\n * The front door for \"I want a recipe.\" Re-exports headline factories from\n * presets so consumers can import from one place without knowing which preset\n * sub-domain each factory lives in.\n *\n * Verticals (solutions/<vertical>/) are deferred per D202 — added when\n * consumer pressure justifies a bundled vertical starter kit.\n *\n * @module\n */\n\nexport { agentLoop } from \"../presets/ai/agent-loop.js\";\nexport { agentMemory } from \"../presets/ai/agent-memory.js\";\nexport { harnessLoop } from \"../presets/harness/harness-loop.js\";\nexport { refineLoop } from \"../presets/harness/refine-loop.js\";\nexport { spawnable } from \"../presets/harness/spawnable.js\";\nexport { guardedExecution } from \"../presets/inspect/guarded-execution.js\";\nexport { resilientPipeline } from \"../presets/resilience/resilient-pipeline.js\";\n","/**\n * Reactive agent loop — autonomous multi-turn LLM agent with tool execution.\n */\n\nexport type AgentLoopStatus = \"idle\" | \"thinking\" | \"acting\" | \"done\" | \"error\";\n\nimport {\n\tbatch,\n\tDATA,\n\tERROR,\n\tINVALIDATE,\n\ttype Node,\n\tnode,\n\tnode as nodeFactory,\n\tplaceholderArgs,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport { fromAny, keepalive, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { awaitSettled } from \"../../base/sources/settled.js\";\nimport { aiMeta } from \"../../utils/ai/_internal.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMResponse,\n\tToolCall,\n\tToolDefinition,\n} from \"../../utils/ai/adapters/core/types.js\";\nimport { type ChatStreamGraph, chatStream } from \"../../utils/ai/agents/chat-stream.js\";\nimport { type ToolResult, toolExecution } from \"../../utils/ai/agents/tool-execution.js\";\nimport { type ToolRegistryGraph, toolRegistry } from \"../../utils/ai/agents/tool-registry.js\";\n\nexport type { ToolResult } from \"../../utils/ai/agents/tool-execution.js\";\n\n// ---------------------------------------------------------------------------\n// agentLoop\n// ---------------------------------------------------------------------------\n\nexport type AgentLoopOptions = {\n\tgraph?: GraphOptions;\n\tadapter: LLMAdapter;\n\ttools?: readonly ToolDefinition[];\n\tsystemPrompt?: string;\n\tmaxTurns?: number;\n\tstopWhen?: (response: LLMResponse) => boolean;\n\tonToolCall?: (call: ToolCall) => void;\n\tmaxMessages?: number;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/**\n\t * Reactive tool-call splice (COMPOSITION-GUIDE §31 \"interception is security\").\n\t * When set, the raw `toolCalls` node is piped through this transform before\n\t * reaching the executor. The transform is a pure reactive composition —\n\t * `(calls: Node<readonly ToolCall[]>) => Node<readonly ToolCall[]>` — so the\n\t * gate is visible in `describe()` / `explain()` as a real edge (no hidden\n\t * imperative wraps; §24).\n\t *\n\t * Typical uses:\n\t * - **Filter / block** — `derived([calls, policy], ([raw, p]) => raw.filter(p))`\n\t * - **Throttle / debounce** — `throttle(calls, windowMs)`\n\t * - **Human-in-the-loop approval** — pipe through a `gate` controller so\n\t * calls wait for human approval before reaching the executor.\n\t *\n\t * The public `agent.toolCalls` node surfaces the POST-intercept stream, so\n\t * audit / telemetry consumers see what the executor actually runs. The raw\n\t * pre-intercept stream is not exposed — tests that need it should run\n\t * without `interceptToolCalls` set (the identity case).\n\t */\n\tinterceptToolCalls?: (calls: Node<readonly ToolCall[]>) => Node<readonly ToolCall[]>;\n};\n\n/**\n * Reactive agent loop.\n *\n * The loop is a reactive state machine wired entirely from graph primitives:\n * `chat.messages` + `tools.schemas` + gating state feed a `promptInput`\n * derived; `switchMap` turns non-null inputs into an LLM invocation via\n * `fromAny(adapter.invoke(...))`. The LLM response drives chat writes and\n * status transitions via effects. Tool calls flow through a reactive\n * executor (`retrySource` + `rescue`) that retries once on error and\n * surfaces terminal errors as JSON-shaped `ToolResult` payloads for the\n * LLM to react to.\n *\n * **No imperative control flow inside the reactive layer** (spec §5.8-5.12):\n * no `while` loops, no manual `await adapter.invoke`, no polling.\n * `agent.run()` is a thin `awaitSettled` bridge so callers can still `await`\n * the loop if they want a Promise.\n *\n * Public surface:\n * - `chat` / `tools` — subgraphs (imperative `append` at boundary, reactive `executeReactive` for tool invocation)\n * - `status` / `turn` / `aborted` — state nodes with explicit initials\n * - `lastResponse` / `toolCalls` / `toolResults` — reactive outputs (SENTINEL until first emission; callers use `awaitSettled` / `subscribe`)\n * - `run(userMessage?, signal?)` — optional user append + Promise bridge\n * - `abort()` — imperative abort shim; flips `aborted` state\n *\n * **Lifecycle: single-mount.** `AgentLoopGraph` instances expect to be\n * constructed once and used until `destroy()`. The internal closure mirrors\n * (`latestTurn` / `latestAborted` / `latestStatus`) are wired by\n * subscribe-and-capture at construction time; their `addDisposer`-registered\n * subscriptions are torn down on subgraph unmount or `destroy()`. After\n * teardown the mirrors freeze at their last value, so re-using a destroyed\n * instance — calling `run()` again, or remounting under a new parent —\n * would silently feed stale mirror data into reactive fn bodies. If you\n * need to \"reset\" an agent, build a fresh `AgentLoopGraph` instance instead\n * of recycling.\n */\nexport class AgentLoopGraph extends Graph {\n\treadonly chat: ChatStreamGraph;\n\treadonly tools: ToolRegistryGraph;\n\n\t/** Current agent status. `initial: \"idle\"` — always has a real value. */\n\treadonly status: Node<AgentLoopStatus>;\n\t/** Turn count (completed LLM invocations this run). `initial: 0`. */\n\treadonly turn: Node<number>;\n\t/** Aborted flag; flipped by `abort()` or external `AbortSignal`. `initial: false`. */\n\treadonly aborted: Node<boolean>;\n\n\t/**\n\t * Most recent LLM response. State-backed mirror driven by the response\n\t * effect. **Stays SENTINEL** (`cache === undefined`, no DATA emitted)\n\t * until the first real response — bridge subscribers see no spurious\n\t * push-on-subscribe DATA. After a real response, holds the latest\n\t * `LLMResponse`. Reset between `run()` calls via `[[INVALIDATE]]` (clears\n\t * cache back to SENTINEL) so a second run with a pre-aborted signal\n\t * cannot leak the prior run's response. Bridge with\n\t * `awaitSettled(lastResponse)` for the first DATA as a Promise; consumers\n\t * inside reactive fns gate on `ctx.prevData[i] === undefined`.\n\t */\n\treadonly lastResponse: Node<LLMResponse>;\n\t/** Tool-call batch emitted by the most recent LLM response. SENTINEL. */\n\treadonly toolCalls: Node<readonly ToolCall[]>;\n\t/** Tool-result batch (one entry per call) after reactive execution. SENTINEL. */\n\treadonly toolResults: Node<readonly ToolResult[]>;\n\n\tprivate readonly _terminalResult: Node<LLMResponse>;\n\tprivate readonly _disposeRunWiring: () => void;\n\t/** Guards against overlapping `run()` calls. */\n\tprivate _running = false;\n\t/**\n\t * Abort controller for the currently-running `adapter.invoke`. Minted per\n\t * switchMap project; aborted when the reactive `aborted` node flips true\n\t * OR when the caller's external `AbortSignal` fires. Threaded into\n\t * `adapter.invoke({ signal })` AND `fromAny(promise, { signal })`, so the\n\t * reactive layer sees ERROR when the wire call is cancelled.\n\t */\n\tprivate _currentAbortController: AbortController | null = null;\n\n\tconstructor(name: string, opts: AgentLoopOptions) {\n\t\tsuper(name, opts.graph);\n\n\t\t// Mount chat subgraph\n\t\tthis.chat = chatStream(`${name}-chat`, { maxMessages: opts.maxMessages });\n\t\tthis.mount(\"chat\", this.chat);\n\n\t\t// Mount tool registry subgraph\n\t\tthis.tools = toolRegistry(`${name}-tools`);\n\t\tthis.mount(\"tools\", this.tools);\n\n\t\tif (opts.tools) {\n\t\t\tfor (const tool of opts.tools) {\n\t\t\t\tthis.tools.register(tool);\n\t\t\t}\n\t\t}\n\n\t\t// --- State nodes (always have a real value; explicit initials) ---\n\t\tthis.status = node<AgentLoopStatus>([], {\n\t\t\t...{\n\t\t\t\tname: \"status\",\n\t\t\t\tdescribeKind: \"state\",\n\t\t\t\tmeta: aiMeta(\"agent_status\"),\n\t\t\t},\n\t\t\tinitial: \"idle\",\n\t\t});\n\t\tthis.add(this.status, { name: \"status\" });\n\n\t\tthis.turn = node<number>([], {\n\t\t\t...{\n\t\t\t\tname: \"turn\",\n\t\t\t\tdescribeKind: \"state\",\n\t\t\t\tmeta: aiMeta(\"agent_turn_count\"),\n\t\t\t},\n\t\t\tinitial: 0,\n\t\t});\n\t\tthis.add(this.turn, { name: \"turn\" });\n\n\t\tthis.aborted = node<boolean>([], {\n\t\t\t...{\n\t\t\t\tname: \"aborted\",\n\t\t\t\tdescribeKind: \"state\",\n\t\t\t\tmeta: aiMeta(\"agent_aborted\"),\n\t\t\t},\n\t\t\tinitial: false,\n\t\t});\n\t\tthis.add(this.aborted, { name: \"aborted\" });\n\n\t\t// --- Reactive pipeline ---\n\t\t//\n\t\t// **Read pattern (Phase 12 D1 lock + F2 fix 2026-05-01).** State\n\t\t// scratchpad held on this `AgentLoopGraph` (turn / aborted / chat /\n\t\t// tools) is read inside reactive fn bodies via either:\n\t\t// (a) `data[i]` / `ctx.prevData[i]` for declared deps, OR\n\t\t// (b) sole-owner `.cache` reads on subgraph-mounted state Nodes\n\t\t// (chat / tools mounted as subgraphs of this Graph; the agent\n\t\t// is the sole owner; promptInput / effResponse / effResults\n\t\t// live in the same enclosing constructor scope — sanctioned\n\t\t// form per Phase 12 D1 read-pattern lock).\n\t\t//\n\t\t// Closure mirrors (`latestTurn` / `latestAborted` / `latestStatus`)\n\t\t// are kept ONLY for fields where (b) doesn't simplify the call site\n\t\t// — turn / aborted / status are state Nodes registered on `this`\n\t\t// directly (not subgraphs), and the closure form keeps\n\t\t// effResponse's batch logic readable. They are CORRECT but are NOT\n\t\t// safe under nested drains (the subscribe handler may not have run\n\t\t// yet when a downstream fn reads the closure). For nested-drain-\n\t\t// reachable reads (promptInput, called via `agentLoop.run` from\n\t\t// inside another graph's reactive subscribe handler), prefer (a) or\n\t\t// (b) over the closure mirror. F2 root cause: chat.messages.cache\n\t\t// is updated DURING the DATA-settle phase (before subscribers\n\t\t// run), so `.cache` reads are always at least as fresh as closure\n\t\t// mirrors. See `optimizations.md` \"Phase 13 design-session inputs\n\t\t// from §13.M lock-test\" F2.\n\t\t//\n\t\t// **Pattern note on `latestTurn` staleness under in-batch reads.**\n\t\t// Effect 1 emits `turnNode.emit(next)` inside its batch; Effect 2\n\t\t// reads `latestTurn` on the following wave (after toolResults\n\t\t// settle). Because batch drain is FIFO, `turnSub`'s handler runs\n\t\t// before Effect 2's next wave fires, so `latestTurn` is up-to-date\n\t\t// by the time Effect 2 reads it. This invariant is stable as long\n\t\t// as `turnNode.emit` remains inside Effect 1's batch — a future\n\t\t// refactor that un-batches the emit would regress silently.\n\t\tlet latestTurn = 0;\n\t\tconst turnSub = this.turn.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) if (m[0] === DATA) latestTurn = m[1] as number;\n\t\t});\n\t\tlet latestAborted = false;\n\t\tconst abortedSub = this.aborted.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) if (m[0] === DATA) latestAborted = m[1] as boolean;\n\t\t});\n\n\t\tconst adapter = opts.adapter;\n\t\tconst systemPrompt = opts.systemPrompt;\n\t\tconst model = opts.model;\n\t\tconst temperature = opts.temperature;\n\t\tconst maxTokens = opts.maxTokens;\n\t\tconst maxTurns = opts.maxTurns ?? 10;\n\t\tconst stopWhen = opts.stopWhen;\n\n\t\t// Capture `this` for closures that don't bind `this`.\n\t\tconst chat = this.chat;\n\t\tconst tools = this.tools;\n\t\tconst statusNode = this.status;\n\t\tconst turnNode = this.turn;\n\t\tconst abortedNode = this.aborted;\n\n\t\t// promptInput: STATUS is the only reactive trigger — chat.messages,\n\t\t// tools.schemas, turn, aborted are sampled via closure-held mirrors\n\t\t// (all populated by subscribe-and-capture above). This prevents the\n\t\t// classic feedback cycle (COMPOSITION-GUIDE §7): if chat.messageCount\n\t\t// were a reactive dep here, effect 1's `chat.append` would trigger a\n\t\t// promptInput wave, which under effect-1's batch would see status\n\t\t// STILL \"thinking\" (pre-drain) and fire a spurious LLM invocation.\n\t\t// By gating only on status, chat writes don't re-trigger — only\n\t\t// explicit status transitions do.\n\t\tconst promptInput: Node<InvokeInput> = nodeFactory<InvokeInput>(\n\t\t\t[statusNode],\n\t\t\t(data, actions, ctx) => {\n\t\t\t\tconst stat = readLatest<AgentLoopStatus>(data, ctx.prevData, 0, \"idle\");\n\t\t\t\tif (stat !== \"thinking\" || latestAborted || latestTurn >= maxTurns) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// F2 fix (2026-05-01): under nested drains, the closure mirrors\n\t\t\t\t// `latestMessages` / `latestSchemas` lag the actual node state —\n\t\t\t\t// messagesSub / schemasSub subscribers may not have run yet when\n\t\t\t\t// promptInput fires (the drain processes status's downstream\n\t\t\t\t// before chat.messages's subscribers fire, even though\n\t\t\t\t// chat.messages.cache is already settled). Read `.cache`\n\t\t\t\t// directly per Phase 12 D1 read-pattern lock: chat / tools are\n\t\t\t\t// mounted as subgraphs of this AgentLoopGraph (sole owner) and\n\t\t\t\t// promptInput is a reactive reader in the same enclosing\n\t\t\t\t// constructor scope — sanctioned `.cache` form. See\n\t\t\t\t// `optimizations.md` \"Phase 13 design-session inputs from §13.M\n\t\t\t\t// lock-test\" F2.\n\t\t\t\tconst messages = (this.chat.messages.cache as readonly ChatMessage[] | undefined) ?? [];\n\t\t\t\tif (messages.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\tconst schemas = (this.tools.schemas.cache as readonly ToolDefinition[] | undefined) ?? [];\n\t\t\t\tactions.emit({ messages, tools: schemas });\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"promptInput\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"agent_prompt_input\", {\n\t\t\t\t\t// State this fn body samples beyond its declared `statusNode`\n\t\t\t\t\t// dep. `aborted` / `turn` come from §28 closure mirrors\n\t\t\t\t\t// (`latestAborted` / `latestTurn`); `chat.messages` /\n\t\t\t\t\t// `tools.schemas` come from sole-owner `.cache` reads\n\t\t\t\t\t// (Phase 12 D1 lock + F2 fix; see comment block above).\n\t\t\t\t\t// Listed here so inspection tooling can surface fold-in\n\t\t\t\t\t// state without grepping source.\n\t\t\t\t\tclosureReads: [\"aborted\", \"turn\", \"chat.messages\", \"tools.schemas\"],\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tconst llmResponse: Node<LLMResponse> = switchMap(\n\t\t\tpromptInput,\n\t\t\t(input) => {\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tthis._currentAbortController = controller;\n\t\t\t\tif (latestAborted) {\n\t\t\t\t\tcontroller.abort(new Error(\"agentLoop: aborted\"));\n\t\t\t\t}\n\t\t\t\t// Wave A Unit B-CC fix: drop the `Promise.resolve(adapter.invoke(...))`\n\t\t\t\t// wrapper. `adapter.invoke` returns a `NodeInput<LLMResponse>`\n\t\t\t\t// (Promise | Node | raw). `fromAny` already handles all three\n\t\t\t\t// shapes; the manual `Promise.resolve` wrapper would force a\n\t\t\t\t// Node-returning adapter into an extra microtask hop and lose\n\t\t\t\t// reactivity (see Unit 11 + Unit 1 for the parallel cleanup).\n\t\t\t\treturn fromAny(\n\t\t\t\t\tadapter.invoke(input.messages, {\n\t\t\t\t\t\ttools: input.tools.length > 0 ? input.tools : undefined,\n\t\t\t\t\t\tsystemPrompt,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttemperature,\n\t\t\t\t\t\tmaxTokens,\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t}),\n\t\t\t\t\t{ signal: controller.signal },\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ equals: () => false },\n\t\t);\n\n\t\t// State mirror for `lastResponse` — exists for **cross-run reset\n\t\t// semantics**, NOT the §32 mid-wave hazard.\n\t\t//\n\t\t// Why: `llmResponse` is a switchMap output; its cache persists across\n\t\t// `run()` calls (switchMap's output node has no built-in reset path —\n\t\t// the cache stays at the last DATA the inner emitted). A second\n\t\t// `run()` with a pre-aborted signal would otherwise have\n\t\t// `_terminalResult` evaluate `stat=done` (driven by `effAbort`) +\n\t\t// `resp=<prior run's response>` (cached on `llmResponse`) and resolve\n\t\t// the Promise with stale data instead of rejecting with AbortError.\n\t\t// The mirror is **reset via `[[INVALIDATE]]`** in `run()`'s reset\n\t\t// batch — INVALIDATE clears `_cached` back to `undefined` (SENTINEL)\n\t\t// AND clears the `prevData` slot on every dependent (`_terminalResult`,\n\t\t// `toolCallsRaw`), so the abort path correctly emits\n\t\t// `[[ERROR, AbortError]]` from terminalResult's `stat=\"done\" &&\n\t\t// prevData[lastResponse] === undefined → ERROR` guard.\n\t\t//\n\t\t// **No `T | null` placeholder.** Per `feedback_use_prevdata_for_sentinel`\n\t\t// + COMPOSITION-GUIDE §1a, the SENTINEL state IS the \"never sent\n\t\t// real DATA yet\" signal. An eager `initial: null` would push `[null]`\n\t\t// to every fresh subscriber — a footgun for bridge subscribers that\n\t\t// would otherwise need `if (resp == null) continue` guards. Stay\n\t\t// SENTINEL; consumers detect \"no response yet\" via\n\t\t// `ctx.prevData[i] === undefined` (or `cache === undefined` outside\n\t\t// reactive fns). F9 lock-test (`multi-agent-example.test.ts` test 5)\n\t\t// pins this invariant.\n\t\t//\n\t\t// What this does NOT solve: the §32 mid-wave \"stale peer-read\"\n\t\t// hazard. Investigation (2026-04-25) confirmed `_dirtyDepCount`\n\t\t// gating in `_maybeRunFnOnSettlement` already prevents that — when\n\t\t// `effResponse`'s nested batch fires `status=\"done\"` mid-iteration,\n\t\t// terminal's status dep settles but its `llmResponse` (or mirror)\n\t\t// dep is still DIRTY from Phase 1, so the fn does not run until\n\t\t// Phase 2 visits both deps. Verified by fast-check invariant `#12b\n\t\t// nested-drain-peer-consistency-compound` and by the multi-turn\n\t\t// `executes tool calls and loops` test passing under either dep\n\t\t// shape (`[statusNode, llmResponse]` or `[statusNode, lastResponseState]`).\n\t\t//\n\t\t// Verified by: QA C3 regression tests (`run() with pre-aborted\n\t\t// signal rejects AbortError` and `second run() with pre-aborted\n\t\t// signal rejects AbortError (no stale response leak)`) — both\n\t\t// fail when `_terminalResult` is rewired to depend on `llmResponse`\n\t\t// directly. See COMPOSITION-GUIDE §32 (cross-wave reset reframe).\n\t\tconst lastResponseState = node<LLMResponse>([], {\n\t\t\tname: \"lastResponse\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_last_response\"),\n\t\t});\n\t\tthis.lastResponse = lastResponseState;\n\n\t\t// toolCalls: raw node that emits DATA only when status === \"acting\" and\n\t\t// the current response has tool calls. Otherwise emits RESOLVED. Using\n\t\t// DATA([]) for the idle case would cause switchMap(toolCalls) to\n\t\t// re-dispatch its inner (creating a fresh node([], { initial: [] }) source whose\n\t\t// emissions re-trigger effects downstream). RESOLVED keeps the inner\n\t\t// alive and lets upstream waves pass through without re-dispatch.\n\t\t// Inner raw tool-call stream — name `toolCallsRaw` so the post-intercept\n\t\t// public surface (`this.toolCalls`) is unambiguous in `describe()`.\n\t\t// QA-fix: previously the inner was named `\"toolCalls\"`, which collided\n\t\t// with `this.toolCalls` if the user-supplied interceptor returned a\n\t\t// wrapper that internally retained a reference to this raw node —\n\t\t// `describe()` would render two distinct nodes both labeled `\"toolCalls\"`.\n\t\tconst toolCallsRaw = nodeFactory<readonly ToolCall[]>(\n\t\t\t[lastResponseState, statusNode],\n\t\t\t(data, actions, ctx) => {\n\t\t\t\t// SENTINEL guard: `lastResponseState` stays `undefined` (cache\n\t\t\t\t// + prevData) until the first real response. `readLatest`'s\n\t\t\t\t// fallback returns `undefined` here so the no-DATA branch is\n\t\t\t\t// indistinguishable from the protocol SENTINEL — both gate to\n\t\t\t\t// RESOLVED. Per `feedback_use_prevdata_for_sentinel`.\n\t\t\t\tconst resp = readLatest<LLMResponse | undefined>(data, ctx.prevData, 0, undefined);\n\t\t\t\tconst stat = readLatest<AgentLoopStatus>(data, ctx.prevData, 1, \"idle\");\n\t\t\t\tif (stat !== \"acting\") {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst calls = resp?.toolCalls;\n\t\t\t\tif (calls == null || calls.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(calls);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"toolCallsRaw\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"agent_tool_calls_raw\"),\n\t\t\t},\n\t\t);\n\t\t// Reactive splice (D9 / COMPOSITION-GUIDE §31). When `interceptToolCalls`\n\t\t// is set, the raw tool-call stream is transformed in the graph — the\n\t\t// executor sees the gated stream, and `agent.toolCalls` surfaces the\n\t\t// post-intercept view so audit / telemetry match reality.\n\t\tconst gatedToolCallsNode = opts.interceptToolCalls\n\t\t\t? opts.interceptToolCalls(toolCallsRaw)\n\t\t\t: toolCallsRaw;\n\t\tthis.toolCalls = gatedToolCallsNode;\n\n\t\t// Delegate per-call fan-out + retry + rescue to the `toolExecution`\n\t\t// primitive. `toolCallsRaw` already gates empty batches to RESOLVED,\n\t\t// so `toolExecution`'s \"non-empty batch only\" contract is satisfied\n\t\t// upstream. `retryCount: 1` matches the pre-extraction behaviour\n\t\t// (one retry after first failure = 2 attempts total).\n\t\tconst toolResultsNode: Node<readonly ToolResult[]> = toolExecution({\n\t\t\ttoolCalls: gatedToolCallsNode,\n\t\t\ttools,\n\t\t\tretryCount: 1,\n\t\t});\n\t\tthis.toolResults = toolResultsNode;\n\n\t\t// --- State-machine effects ---\n\t\t// Effect 1: LLM response landed → write lastResponse mirror + chat,\n\t\t// transition status, increment turn. Emission ORDER inside the batch\n\t\t// matters (drain is FIFO under any outer-batch depth):\n\t\t// 1. `lastResponseState.emit(response)` FIRST — so when the drain\n\t\t// fires the status=done wave later in the queue, `_terminalResult`'s\n\t\t// dep on `lastResponseState` has already been updated.\n\t\t// 2. `statusNode.emit(nextStatus)` — drives state machine.\n\t\t// 3. `turnNode.emit(next)` — counter.\n\t\t// 4. `chat.append(...)` LAST — chat.messageCount wave now sees the\n\t\t// new status (so `promptInput` gates correctly).\n\t\t// Without (1) first, `_terminalResult` reads stale `prevData` for\n\t\t// lastResponse when status transitions synchronously during drain.\n\t\t//\n\t\t// **Invariant independence from outer batch depth.** `downWithBatch`\n\t\t// preserves FIFO drain order regardless of nesting — whether the\n\t\t// outer batch is at depth 0 (common: Promise microtask) or depth >0\n\t\t// (user-composed `batch()` scope around `agent.run()`), the emissions\n\t\t// above drain in the order they were enqueued. The state-mirror\n\t\t// pattern holds in both cases.\n\t\t//\n\t\t// **Abort guard (C2 defense-in-depth).** If the `aborted` state has\n\t\t// flipped true between `adapter.invoke`'s Promise resolution and this\n\t\t// effect firing (micro-race), bail out so we don't append to chat or\n\t\t// execute tool calls for an abandoned run. The controller.abort() in\n\t\t// effAbort also fires the signal, which causes `fromAny` to emit\n\t\t// ERROR — but that ERROR propagation arrives in a separate wave, so\n\t\t// this guard covers the \"Promise already resolved before abort hit\n\t\t// the controller\" case.\n\t\tconst effResponse = node(\n\t\t\t[llmResponse],\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\tif (latestAborted) return;\n\t\t\t\tconst response = data[0] as LLMResponse;\n\t\t\t\tconst next = latestTurn + 1;\n\t\t\t\tconst hasToolCalls = response.toolCalls != null && response.toolCalls.length > 0;\n\t\t\t\tconst naturalStop =\n\t\t\t\t\tresponse.finishReason === \"end_turn\" &&\n\t\t\t\t\t(!response.toolCalls || response.toolCalls.length === 0);\n\t\t\t\tconst customStop = stopWhen?.(response) === true;\n\t\t\t\tconst capReached = next >= maxTurns;\n\t\t\t\tconst nextStatus: AgentLoopStatus =\n\t\t\t\t\tcustomStop || naturalStop || !hasToolCalls || capReached ? \"done\" : \"acting\";\n\t\t\t\tbatch(() => {\n\t\t\t\t\tlastResponseState.emit(response);\n\t\t\t\t\tstatusNode.emit(nextStatus);\n\t\t\t\t\tturnNode.emit(next);\n\t\t\t\t\tchat.append(\"assistant\", response.content, {\n\t\t\t\t\t\ttoolCalls: response.toolCalls,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\n\t\t// Effect 2: Tool results landed → append to chat, transition to\n\t\t// thinking (or done if turn cap reached). Same ordering discipline —\n\t\t// status emits before chat mutations. Abort guard mirrors effResponse.\n\t\tconst effResults = node(\n\t\t\t[toolResultsNode],\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\tif (latestAborted) return;\n\t\t\t\tconst arr = data[0] as readonly ToolResult[];\n\t\t\t\tif (arr.length === 0) return;\n\t\t\t\tconst nextStatus: AgentLoopStatus = latestTurn >= maxTurns ? \"done\" : \"thinking\";\n\t\t\t\tbatch(() => {\n\t\t\t\t\tstatusNode.emit(nextStatus);\n\t\t\t\t\tfor (const r of arr) chat.appendToolResult(r.id, r.content);\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\n\t\t// Effect 3: external abort → cancel in-flight wire call + terminal status.\n\t\t// Aborting the controller causes the switchMap inner's `fromAny` to\n\t\t// emit ERROR (signal-bound), which tears down the subscription. The\n\t\t// `status=\"done\"` emit drives `_terminalResult` to resolve `run()`'s\n\t\t// Promise (via AbortError when `resp == null`, see C3).\n\t\t//\n\t\t// Unit 4 Q5: status guard — if status is already \"done\" (the natural-\n\t\t// completion path raced the abort), skip the redundant emit so the\n\t\t// status-node event log isn't polluted with a trailing duplicate.\n\t\t// Closure-mirror `latestStatus` keeps the comparison synchronous and\n\t\t// P3-compliant (closure read, not `.cache` read — see §28). Seeded\n\t\t// from `statusNode.cache` to match the §28 factory-time-seed pattern\n\t\t// that `latestTurn` / `latestAborted` use — the literal `\"idle\"` would\n\t\t// silently drift if the constructor initial value ever changed.\n\t\tlet latestStatus: AgentLoopStatus = (statusNode.cache as AgentLoopStatus | undefined) ?? \"idle\";\n\t\tconst statusSub = statusNode.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) if (m[0] === DATA) latestStatus = m[1] as AgentLoopStatus;\n\t\t});\n\t\tconst effAbort = node(\n\t\t\t[abortedNode],\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\tif (data[0] === true) {\n\t\t\t\t\tthis._currentAbortController?.abort(new Error(\"agentLoop: aborted\"));\n\t\t\t\t\tif (latestStatus !== \"done\") statusNode.emit(\"done\");\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ describeKind: \"effect\" },\n\t\t);\n\n\t\t// Keepalive so the pipeline stays activated even without external\n\t\t// subscribers. Callers don't need to subscribe to `llmResponse` /\n\t\t// `toolResults` for the loop to run.\n\t\tconst kaResponse = keepalive(effResponse);\n\t\tconst kaResults = keepalive(effResults);\n\t\tconst kaAbort = keepalive(effAbort);\n\n\t\t// terminalResult emits the final `LLMResponse` on each \"done\"\n\t\t// transition. The old compound `{response, runVersion}` shape existed\n\t\t// to let a re-entrant caller's `awaitSettled` predicate filter out\n\t\t// the PREVIOUS run's cached DATA; that job now belongs to\n\t\t// `awaitSettled({skipCurrent: true})` (extra/sources.ts) which\n\t\t// ignores the initial push-on-subscribe DATA and resolves only on\n\t\t// fresh post-subscribe emissions. Retiring the stamp removes a\n\t\t// closure-held counter and a per-emission object allocation from\n\t\t// the hot path.\n\t\t//\n\t\t// C3 (abort-before-response) post-SENTINEL: when `stat === \"done\"` but\n\t\t// `lastResponseState` is SENTINEL (no DATA ever delivered for this\n\t\t// run — `prevData[1] === undefined`, equivalently `resp === undefined`\n\t\t// after `readLatest`'s fallback), emit `ERROR(AbortError)` so the\n\t\t// awaiting Promise rejects instead of hanging on a RESOLVED. The\n\t\t// SENTINEL state is restored at every `run()` boundary by\n\t\t// `lastResponse.down([[INVALIDATE]])` (clears `_cached` AND clears\n\t\t// each dependent's `prevData` slot for this dep), so a second run\n\t\t// after a successful first run still detects the abort cleanly —\n\t\t// no stale `prevData` leak.\n\t\tthis._terminalResult = nodeFactory<LLMResponse>(\n\t\t\t[statusNode, lastResponseState],\n\t\t\t(data, actions, ctx) => {\n\t\t\t\tconst stat = readLatest<AgentLoopStatus>(data, ctx.prevData, 0, \"idle\");\n\t\t\t\tconst resp = readLatest<LLMResponse | undefined>(data, ctx.prevData, 1, undefined);\n\t\t\t\tif (stat === \"done\") {\n\t\t\t\t\tif (resp !== undefined) {\n\t\t\t\t\t\tactions.emit(resp);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst err = new Error(\"agentLoop: aborted\") as Error & { name: string };\n\t\t\t\t\terr.name = \"AbortError\";\n\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (stat === \"error\") {\n\t\t\t\t\tactions.down([[ERROR, new Error(\"agentLoop: errored\")]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"terminalResult\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"agent_terminal_result\"),\n\t\t\t\t// `lastResponseState` is SENTINEL until the first real response\n\t\t\t\t// arrives — without `partial: true`, the spec §2.7 first-run\n\t\t\t\t// gate would block this fn from ever firing on the abort-\n\t\t\t\t// before-response path (`status → \"done\"` while `lastResponse`\n\t\t\t\t// has never delivered DATA). The fn explicitly handles the\n\t\t\t\t// SENTINEL case (`resp === undefined → ERROR(AbortError)`),\n\t\t\t\t// so partial-fire is safe by design.\n\t\t\t\tpartial: true,\n\t\t\t},\n\t\t);\n\t\t// Wave B-CC Q2/C: register intermediate pipeline nodes so consumers\n\t\t// can `observe(path)` them by name (e.g. `agent.observe(\"promptInput\")`).\n\t\t// They were already visible in `describe()` via dep traversal, but not\n\t\t// path-addressable. Tools using the `observe`-by-path API now work.\n\t\t//\n\t\t// QA-fix (#5 stability): registrations live AFTER ALL dependent nodes\n\t\t// are constructed (`promptInput → llmResponse → effResponse →\n\t\t// lastResponseState → toolCallsRaw → toolResultsNode → effResults →\n\t\t// effAbort → _terminalResult`). Topology event-stream consumers\n\t\t// subscribed at construction time now see registrations in an order\n\t\t// where every edge between two registered nodes is already valid —\n\t\t// no transient partial graph slipping through to live mermaid / d2\n\t\t// renderers.\n\t\tthis.add(promptInput as Node<unknown>, { name: \"promptInput\" });\n\t\tthis.add(llmResponse as Node<unknown>, { name: \"llmResponse\" });\n\t\tthis.add(this.lastResponse as Node<unknown>, { name: \"lastResponse\" });\n\t\t// When no interceptor is configured, `this.toolCalls === toolCallsRaw` —\n\t\t// registering the same instance under two names trips the per-graph\n\t\t// `_nodeToName` collision check. Register the raw under `toolCalls`\n\t\t// directly in that case; otherwise register both (raw + post-intercept).\n\t\tif (this.toolCalls === toolCallsRaw) {\n\t\t\tthis.add(this.toolCalls as Node<unknown>, { name: \"toolCalls\" });\n\t\t} else {\n\t\t\tthis.add(toolCallsRaw as Node<unknown>, { name: \"toolCallsRaw\" });\n\t\t\tthis.add(this.toolCalls as Node<unknown>, { name: \"toolCalls\" });\n\t\t}\n\t\tthis.add(toolResultsNode as Node<unknown>, { name: \"toolResults\" });\n\t\tthis.add(this._terminalResult as Node<unknown>, { name: \"terminalResult\" });\n\n\t\t// Register subscriptions via `addDisposer` so they tear down on\n\t\t// subgraph unmount (not just explicit `destroy()`). A caller that\n\t\t// unmounts the AgentLoopGraph from its parent via `graph.remove(...)`\n\t\t// would otherwise keep `turnSub` / `abortedSub` live against dead state.\n\t\tthis.addDisposer(turnSub);\n\t\tthis.addDisposer(abortedSub);\n\t\tthis.addDisposer(statusSub);\n\t\tthis.addDisposer(kaResponse);\n\t\tthis.addDisposer(kaResults);\n\t\tthis.addDisposer(kaAbort);\n\t\tthis._disposeRunWiring = (): void => {\n\t\t\t// addDisposer takes care of teardown; this shim stays for the\n\t\t\t// `destroy()` override's idempotency contract (safe no-op if the\n\t\t\t// disposers already fired).\n\t\t};\n\t}\n\n\t/**\n\t * Bridge to `Promise<LLMResponse>` over the reactive pipeline.\n\t *\n\t * - If `userMessage` is provided, appends it as a user message and\n\t * transitions status to `\"thinking\"` to kick the loop.\n\t * - If `signal` is provided, binds it to the reactive `aborted` node\n\t * AND threads into `adapter.invoke({ signal })` so the wire call can\n\t * cancel mid-flight. The reactive `aborted` state + effect 3 guarantee\n\t * that even an adapter that ignores `signal` will stop emitting into\n\t * the agent graph.\n\t * - Resolves when `status === \"done\"` with the final LLM response.\n\t * Rejects with `AbortError` when the abort signal fires pre-response.\n\t * Rejects with the stage error when `status === \"error\"`.\n\t *\n\t * **Concurrency:** `run()` refuses to overlap with a pending call on the\n\t * same agent. Attempting to call `run()` while a previous `run()` is\n\t * still in-flight throws a `RangeError` immediately. Stale-resolution\n\t * safety is provided by `awaitSettled({skipCurrent: true})`, which\n\t * ignores the cached initial DATA from any previous run and resolves\n\t * only on a fresh post-subscribe emission of `_terminalResult`.\n\t */\n\tasync run(userMessage?: string, signal?: AbortSignal): Promise<LLMResponse | null> {\n\t\tif (this._running) {\n\t\t\tthrow new RangeError(\n\t\t\t\t`agentLoop \"${this.name}\": run() called while a previous run() is still pending — await the previous run before starting another, or call abort() first`,\n\t\t\t);\n\t\t}\n\t\tthis._running = true;\n\n\t\tlet offAbort: (() => void) | undefined;\n\t\ttry {\n\t\t\t// Reset per-run state. `lastResponse` MUST be cleared here —\n\t\t\t// without it, `_terminalResult` would read the prior run's\n\t\t\t// cached response during a second `run()` with a pre-aborted\n\t\t\t// signal: `effAbort` drives `status → \"done\"`, `_terminalResult`\n\t\t\t// evaluates `stat=\"done\"` + `resp=<prior respA>` and emits DATA\n\t\t\t// as a fresh post-subscribe signal → `awaitSettled` resolves\n\t\t\t// with the stale response instead of rejecting with AbortError.\n\t\t\t// The C3 `stat=done && resp===undefined → ERROR` guard in\n\t\t\t// `_terminalResult` is only correct once the reset clears the\n\t\t\t// cache.\n\t\t\t//\n\t\t\t// **SENTINEL reset via plain `[[INVALIDATE]]`** (DS-13.5.A,\n\t\t\t// 2026-05-01). Pre-DS-13.5.A this required a paired\n\t\t\t// `[[INVALIDATE], [RESOLVED]]` because INVALIDATE alone left\n\t\t\t// dependents wedged in DIRTY. With INVALIDATE settling the wave\n\t\t\t// (decrementing `_dirtyDepCount` like RESOLVED) and clearing\n\t\t\t// `_cached` + each dependent's `prevData[lastResponse]` slot\n\t\t\t// back to `undefined`, a single emission restores SENTINEL state\n\t\t\t// AND lets dependents fire on the next status transition.\n\t\t\t// `lastResponse` is a `Node<LLMResponse>` with no `initial` —\n\t\t\t// it stays SENTINEL until the first real response; resetting\n\t\t\t// via `emit(null)` would push a `null` DATA placeholder (the\n\t\t\t// F9 trap), which is why INVALIDATE rather than emit is used.\n\t\t\tbatch(() => {\n\t\t\t\tthis.lastResponse.down([[INVALIDATE]]);\n\t\t\t\tthis.turn.emit(0);\n\t\t\t\tthis.aborted.emit(false);\n\t\t\t\tthis.status.emit(\"idle\");\n\t\t\t});\n\t\t\tif (userMessage != null) this.chat.append(\"user\", userMessage);\n\n\t\t\t// Subscribe to `_terminalResult` BEFORE transitioning to\n\t\t\t// \"thinking\" — otherwise a synchronous adapter (mock tests,\n\t\t\t// offline stubs) would drain status → done → DATA on\n\t\t\t// `_terminalResult` before `awaitSettled` had a chance to\n\t\t\t// subscribe, and `skipCurrent: true` would swallow the only\n\t\t\t// DATA this run will produce. `awaitSettled` / `firstWhere`\n\t\t\t// subscribes synchronously during the `async` function's\n\t\t\t// initial execution slice, so calling it before the kick\n\t\t\t// guarantees the subscription is in place when the pipeline\n\t\t\t// starts draining.\n\t\t\t//\n\t\t\t// `skipCurrent: true` still matters: on the second `run()`\n\t\t\t// call `_terminalResult` holds cached DATA from the prior run,\n\t\t\t// and push-on-subscribe would resolve immediately with that\n\t\t\t// stale value without the skip.\n\t\t\tconst resultPromise = awaitSettled(this._terminalResult, { skipCurrent: true });\n\n\t\t\tif (signal != null) {\n\t\t\t\tif (signal.aborted) {\n\t\t\t\t\tthis.aborted.emit(true);\n\t\t\t\t} else {\n\t\t\t\t\tconst listener = (): void => this.aborted.emit(true);\n\t\t\t\t\tsignal.addEventListener(\"abort\", listener, { once: true });\n\t\t\t\t\toffAbort = (): void => signal.removeEventListener(\"abort\", listener);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Kick — transition to \"thinking\" fires promptInput → llmResponse.\n\t\t\t// Skip the kick when the signal was already aborted: `effAbort`\n\t\t\t// has driven `status → \"done\"` above, and a trailing\n\t\t\t// `thinking` emit would produce a non-monotonic `idle → done →\n\t\t\t// thinking` sequence in the status-event log for no reactive\n\t\t\t// benefit (promptInput gates on `!latestAborted` anyway).\n\t\t\tif (signal?.aborted !== true) {\n\t\t\t\tthis.status.emit(\"thinking\");\n\t\t\t}\n\n\t\t\treturn await resultPromise;\n\t\t} finally {\n\t\t\toffAbort?.();\n\t\t\tthis._running = false;\n\t\t\tthis._currentAbortController = null;\n\t\t}\n\t}\n\n\t/**\n\t * Flip the reactive `aborted` state. Equivalent to setting an external\n\t * `AbortSignal` — the pipeline observes and transitions to `\"done\"`.\n\t */\n\tabort(): void {\n\t\tthis.aborted.emit(true);\n\t}\n\n\toverride destroy(): void {\n\t\ttry {\n\t\t\tthis._disposeRunWiring();\n\t\t} catch {\n\t\t\t/* best-effort: disposing keepalives shouldn't block destroy */\n\t\t}\n\t\tsuper.destroy();\n\t}\n}\n\n/**\n * Read the latest value for dep `i` inside a raw-`node()` fn body.\n *\n * Checks `batchData[i]` first (this-wave DATA from the dep), falls back to\n * `ctx.prevData[i]` (last DATA from prior waves), and finally to `fallback`\n * when the dep has never emitted (SENTINEL). Matches the unwrap semantics\n * `derived`'s sugar applies, so raw nodes can read deps uniformly.\n *\n * @internal\n */\nfunction readLatest<T>(\n\tbatchData: readonly (readonly unknown[] | undefined)[],\n\tprevData: readonly unknown[],\n\tindex: number,\n\tfallback: T,\n): T {\n\tconst batch = batchData[index];\n\tif (batch != null && batch.length > 0) return batch[batch.length - 1] as T;\n\tconst prev = prevData[index];\n\treturn (prev !== undefined ? prev : fallback) as T;\n}\n\n/** @internal Shape of the LLM invocation input — constructed inside `promptInput`. */\ninterface InvokeInput {\n\treadonly messages: readonly ChatMessage[];\n\treadonly tools: readonly ToolDefinition[];\n}\n\nexport function agentLoop(name: string, opts: AgentLoopOptions): AgentLoopGraph {\n\tconst g = new AgentLoopGraph(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. Opts include non-JSON\n\t// fields (`adapter`, `tools`, `stopWhen`, `onToolCall`,\n\t// `interceptToolCalls`, etc.) so route through `placeholderArgs`\n\t// (DG2=ii).\n\tg.tagFactory(\"agentLoop\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\treturn g;\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 * @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\tonDeactivation: () => {\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}\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\tonDeactivation: () => {\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},\n\t\t{ describeKind: \"producer\" },\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","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","/**\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","/**\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\tonDeactivation: () => {\n\t\t\t\t\tinner();\n\t\t\t\t\tmerged.unsub();\n\t\t\t\t},\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\tonDeactivation: () => {\n\t\t\t\t\tinner();\n\t\t\t\t\tmerged.unsub();\n\t\t\t\t},\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","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\tonDeactivation: () => {\n\t\t\t\t\t\t\tac.abort();\n\t\t\t\t\t\t},\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\tonDeactivation: () => {\n\t\t\t\t\t\tac.abort();\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t},\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","// ---------------------------------------------------------------------------\n// agentMemory — sugar over the memoryWith* composers (Unit 7 B).\n//\n// Thin wiring: distill() builds the core store (when no tiers configured);\n// optional capabilities delegate to the composer Graph subclasses in\n// `memory-composers.ts`. Each composer is a self-contained\n// `MemoryWithXxxGraph` that AgentMemoryGraph mounts on itself (Class B\n// audit, 2026-04-30) — teardown cascades via `Graph.destroy()`.\n//\n// **Phase 12.D (2026-04-30):** Migrated from the `Object.assign(graph, ...)`\n// factory pattern to `class extends Graph` (mirrors the\n// `MemoryWith*Graph` precedent). Required by Phase 13.G `agent(spec)` —\n// `AgentBundle.graph: AgentGraph<TIn, TOut>` consumers want `instanceof`\n// narrowing on agent-memory subgraphs.\n// ---------------------------------------------------------------------------\n\nimport { DATA, type Node, node, placeholderArgs, RESOLVED } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, fromTimer, type NodeInput, switchMap } 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 type { LLMAdapter } from \"../../utils/ai/adapters/core/types.js\";\nimport {\n\ttype MemoryWithTiersGraph,\n\tmemoryRetrieval,\n\tmemoryWithKG,\n\tmemoryWithTiers,\n\tmemoryWithVectors,\n} from \"../../utils/ai/memory/memory-composers.js\";\nimport type { RetrievalEntry, RetrievalQuery } from \"../../utils/ai/memory/retrieval.js\";\nimport type { MemoryTiersBundle, MemoryTiersOptions } from \"../../utils/ai/memory/tiers.js\";\nimport { llmConsolidator, llmExtractor } from \"../../utils/ai/prompts/prompt-call.js\";\nimport type { KnowledgeGraph, VectorIndexGraph } from \"../../utils/memory/index.js\";\n\nexport type AgentMemoryOptions<TMem = unknown> = {\n\tgraph?: GraphOptions;\n\t/** LLM adapter for extraction and consolidation. */\n\tadapter?: LLMAdapter;\n\t/** System prompt for the extractor LLM. */\n\textractPrompt?: string;\n\t/** Custom extractFn (overrides adapter + extractPrompt). */\n\textractFn?: (raw: unknown, existing: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>;\n\t/** System prompt for the consolidation LLM. */\n\tconsolidatePrompt?: string;\n\t/** Custom consolidateFn (overrides adapter + consolidatePrompt). */\n\tconsolidateFn?: (entries: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>;\n\t/** Reactive trigger for consolidation (caller supplies e.g. `fromTimer`). */\n\tconsolidateTrigger?: NodeInput<unknown>;\n\t/** Score function for budget packing (required). */\n\tscore: (mem: TMem, context: unknown) => number;\n\t/** Cost function for budget packing (required). */\n\tcost: (mem: TMem) => number;\n\t/** Token budget for compact view (default 2000). */\n\tbudget?: number;\n\t/** Context node for scoring. */\n\tcontext?: NodeInput<unknown>;\n\t/** Admission filter (default: admit all). */\n\tadmissionFilter?: (candidate: unknown) => boolean;\n\t/** Vector index dimensions (> 0 enables vector index for retrieval). */\n\tvectorDimensions?: number;\n\t/**\n\t * B12: optional accessor for an entry's hierarchical context breadcrumb\n\t * (e.g. `[\"projects\", \"auth\", \"tokens\"]`). When supplied alongside\n\t * `contextWeight > 0`, retrieval applies a score boost for entries whose\n\t * context shares a prefix with the query's `context`. Entries without\n\t * a breadcrumb are scored flatly.\n\t */\n\tcontextOf?: (mem: TMem) => readonly string[] | undefined;\n\t/**\n\t * B12: hierarchical context boost multiplier. Score is scaled by\n\t * `(1 + contextWeight * sharedDepth / queryDepth)` when both the query\n\t * and entry supply a `context`. Default: 0.\n\t */\n\tcontextWeight?: number;\n\n\t// --- In-factory composition (new) ---\n\n\t/** Extract embedding vector from a memory entry (enables vector index). */\n\tembedFn?: (mem: TMem) => readonly number[] | undefined;\n\t/** Enable knowledge graph for entity/relation tracking. */\n\tenableKnowledgeGraph?: boolean;\n\t/** Extract entities and relations from a memory entry. */\n\tentityFn?: (\n\t\tkey: string,\n\t\tmem: TMem,\n\t) =>\n\t\t| {\n\t\t\t\tentities?: Array<{ id: string; value: unknown }>;\n\t\t\t\trelations?: Array<{ from: string; to: string; relation: string; weight?: number }>;\n\t\t }\n\t\t| undefined;\n\n\t/** 3-tier storage configuration. Omit to use single-tier (existing behavior). */\n\ttiers?: MemoryTiersOptions<TMem>;\n\n\t/** Retrieval pipeline configuration. Requires vector index or knowledge graph. */\n\tretrieval?: {\n\t\t/** Max candidates from vector search (default 20). */\n\t\ttopK?: number;\n\t\t/** KG expansion depth in hops (default 1). */\n\t\tgraphDepth?: number;\n\t};\n\n\t/** Periodic reflection/consolidation configuration. */\n\treflection?: {\n\t\t/** Interval in ms between consolidation runs (default 300_000 = 5 min). */\n\t\tinterval?: number;\n\t\t/** Enable/disable periodic reflection (default true when consolidateFn is available). */\n\t\tenabled?: boolean;\n\t};\n};\n\n/**\n * Pre-wired agentic memory graph. Sugar over `distill` plus the\n * `memoryWithVectors` / `memoryWithKG` / `memoryWithTiers` / `memoryRetrieval`\n * composers. Power users who want a subset of capabilities can call those\n * composers directly; this class bundles them into one ergonomic Graph subclass.\n *\n * Mounts:\n * - `tiers/*` — present when `opts.tiers` configured (replaces the\n * default distill bundle).\n * - `vectors/*` — present when `opts.vectorDimensions > 0 && opts.embedFn`.\n * - `knowledge/*` — present when `opts.enableKnowledgeGraph`.\n * - `retrieval/*` — present when vectors or kg configured.\n *\n * When `opts.tiers` is omitted, `store` / `compact` / `size` are added as\n * top-level nodes on this graph (visible in `describe()` / `explain()`).\n */\nexport class AgentMemoryGraph<TMem = unknown> extends Graph {\n\treadonly distillBundle: DistillBundle<TMem>;\n\treadonly compact: Node<Array<{ key: string; value: TMem; score: number }>>;\n\treadonly size: Node<number>;\n\t/** Vector index bundle (null if not enabled). */\n\treadonly vectors: VectorIndexGraph<TMem> | null;\n\t/** Knowledge graph (null if not enabled). */\n\treadonly kg: KnowledgeGraph<unknown, string> | null;\n\t/** Memory tiers bundle (null if not configured). */\n\treadonly memoryTiers: MemoryTiersBundle<TMem> | null;\n\t/**\n\t * The mounted `MemoryWithTiersGraph` subgraph (null when `opts.tiers` was\n\t * omitted). Surfaces the inner graph for `describe()` / `explain()` walks\n\t * and for callers that need direct access to the tiers subgraph (e.g.\n\t * to register additional disposers or attach storage). Companion to\n\t * `memoryTiers`, which carries only the bundle's reactive surface (B5e).\n\t */\n\treadonly tiers: MemoryWithTiersGraph<unknown, TMem> | null;\n\t/**\n\t * Reactive consumer API. Given a reactive `RetrievalQuery | null` source,\n\t * returns a `Node` emitting the packed retrieval results. Composable with\n\t * graph topology — subscribe it, chain it into `promptNode`, or switchMap\n\t * over a user-input node.\n\t *\n\t * Each call mounts its own per-input subgraph at\n\t * `retrieval::retrieve_${id}` (via `MemoryRetrievalGraph`); concurrent\n\t * calls don't share state mirrors. One-shot consumers wrap with\n\t * `awaitSettled(retrieveReactive(query))`.\n\t *\n\t * Null when no retrieval pipeline is configured.\n\t *\n\t * **QA F-9 (2026-04-30):** the prior `retrieval` / `retrievalTrace`\n\t * shared state-node mirrors have been dropped. Use `retrieveReactive`\n\t * for per-call reactive results; one-shot trace consumers should\n\t * subscribe to the projection's upstream `result` derived directly\n\t * via `view.target.resolve(\"retrieval::retrieve_${id}::result\")`.\n\t */\n\treadonly retrieveReactive:\n\t\t| ((queryInput: NodeInput<RetrievalQuery | null>) => Node<ReadonlyArray<RetrievalEntry<TMem>>>)\n\t\t| null;\n\n\tconstructor(name: string, source: NodeInput<unknown>, opts: AgentMemoryOptions<TMem>) {\n\t\tsuper(name, opts.graph);\n\n\t\t// --- Extract function resolution ---\n\t\t// /qa A3 (2026-04-30): validate BEFORE tagFactory so an invalid-opts\n\t\t// throw doesn't leave a tagged-but-empty Graph instance behind.\n\t\tlet rawExtractFn: (\n\t\t\traw: unknown,\n\t\t\texisting: ReadonlyMap<string, TMem>,\n\t\t) => NodeInput<Extraction<TMem>>;\n\t\tif (opts.extractFn) {\n\t\t\trawExtractFn = opts.extractFn;\n\t\t} else if (opts.adapter && opts.extractPrompt) {\n\t\t\trawExtractFn = llmExtractor<unknown, TMem>(opts.extractPrompt, { adapter: opts.adapter });\n\t\t} else {\n\t\t\tthrow new Error(\"agentMemory: provide either extractFn or adapter + extractPrompt\");\n\t\t}\n\n\t\t// Tier 1.5.3 Phase 2.5 (DG1=B): tag the Graph with its constructing\n\t\t// factory so `describe()` exposes provenance. Opts contain non-JSON\n\t\t// fields (`adapter`, `extractFn`, `embedFn`, `score`, `cost`, `evict`,\n\t\t// callbacks, etc.) so route through `placeholderArgs` (DG2=ii).\n\t\tthis.tagFactory(\"agentMemory\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\t\t// Tier 1.5.4 — distill's `extractFn` is now reactive (called once with\n\t\t// nodes). Adapt the AgentMemoryOptions callback shape via switchMap +\n\t\t// closure-mirror for `existing` (COMPOSITION-GUIDE §40 recipe).\n\t\t// QA F9: register the closure-mirror's unsub with the host graph so\n\t\t// `graph.destroy()` reclaims it — was previously leaked.\n\t\t//\n\t\t// **Phase 16 attempt (2026-04-29) reverted.** Tried `withLatestFrom(\n\t\t// rawNode, existingNode) + switchMap`; this is the WRONG migration per\n\t\t// COMPOSITION-GUIDE §28. **Phase 10.5 (same-day partial-flag flip on\n\t\t// `withLatestFrom`)** removes the initial-pair drop, but this site stays\n\t\t// on closure-mirror form pending Phase 11 restricted signatures. See\n\t\t// `archive/docs/SESSION-graph-narrow-waist.md` § \"Status of existing\n\t\t// modifications\" + § \"Phase 10.5\".\n\t\tconst extractFn = (\n\t\t\trawNode: Node<unknown>,\n\t\t\texistingNode: Node<ReadonlyMap<string, TMem>>,\n\t\t): NodeInput<Extraction<TMem>> => {\n\t\t\tlet latestExisting: ReadonlyMap<string, TMem> =\n\t\t\t\t(existingNode.cache as ReadonlyMap<string, TMem> | undefined) ?? new Map();\n\t\t\tconst unsubExisting = existingNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === DATA) latestExisting = m[1] as ReadonlyMap<string, TMem>;\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.addDisposer(unsubExisting);\n\t\t\treturn switchMap(rawNode, (raw) => {\n\t\t\t\tif (raw == null) return { upsert: [] };\n\t\t\t\treturn rawExtractFn(raw, latestExisting);\n\t\t\t});\n\t\t};\n\n\t\t// --- Admission filter ---\n\t\tlet filteredSource = source;\n\t\tif (opts.admissionFilter) {\n\t\t\tconst srcNode = fromAny(source);\n\t\t\tconst filter = opts.admissionFilter;\n\t\t\tfilteredSource = node(\n\t\t\t\t[srcNode],\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 raw = data[0];\n\t\t\t\t\tif (filter(raw)) {\n\t\t\t\t\t\tactions.emit(raw);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// EC1 (qa 2026-04-30): emitting `undefined` would violate spec §5.12\n\t\t\t\t\t\t// (undefined is the protocol SENTINEL — TopicGraph.publish even\n\t\t\t\t\t\t// throws on it). Downstream `batch.at(-1) : ctx.prevData[i]`\n\t\t\t\t\t\t// would also resolve `undefined` back to the prior accepted\n\t\t\t\t\t\t// value, leaking past-the-filter. Emit a tier-3 RESOLVED so the\n\t\t\t\t\t\t// wave settles cleanly without surfacing a stale DATA.\n\t\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{ name: \"admissionFilter\", describeKind: \"derived\" },\n\t\t\t);\n\t\t}\n\n\t\t// --- Consolidation ---\n\t\tlet consolidateFn:\n\t\t\t| ((entries: ReadonlyMap<string, TMem>) => NodeInput<Extraction<TMem>>)\n\t\t\t| undefined;\n\t\tif (opts.consolidateFn) {\n\t\t\tconsolidateFn = opts.consolidateFn;\n\t\t} else if (opts.adapter && opts.consolidatePrompt) {\n\t\t\tconsolidateFn = llmConsolidator<TMem>(opts.consolidatePrompt, { adapter: opts.adapter });\n\t\t}\n\n\t\t// --- Reflection: default consolidateTrigger from fromTimer ---\n\t\tlet consolidateTrigger = opts.consolidateTrigger;\n\t\tif (!consolidateTrigger && consolidateFn && opts.reflection?.enabled !== false) {\n\t\t\tconst interval = opts.reflection?.interval ?? 300_000;\n\t\t\tconsolidateTrigger = fromTimer(interval, { period: interval });\n\t\t}\n\n\t\t// --- Build distill bundle (the core) ---\n\t\t// Tier 4.1 B (2026-04-29): when tiers are configured, `memoryWithTiers`\n\t\t// is the construction site for the distill bundle so it can wire\n\t\t// `reactiveMap.retention` into the store at construction (no §7 cycle).\n\t\t// When tiers are NOT configured, agentMemory calls `distill` directly.\n\t\tconst distillOpts: DistillOptions<TMem> = {\n\t\t\tscore: opts.score,\n\t\t\tcost: opts.cost,\n\t\t\tbudget: opts.budget ?? 2000,\n\t\t\tcontext: opts.context,\n\t\t\tconsolidate: consolidateFn,\n\t\t\tconsolidateTrigger,\n\t\t};\n\n\t\tlet distillBundle: DistillBundle<TMem>;\n\t\tlet memoryTiersBundle: MemoryTiersBundle<TMem> | null = null;\n\t\tlet tiersSubgraph: MemoryWithTiersGraph<unknown, TMem> | null = null;\n\t\tif (opts.tiers) {\n\t\t\tconst tiersGraph = memoryWithTiers<unknown, TMem>({\n\t\t\t\t// User customization first; canonical agent-memory-level overrides\n\t\t\t\t// last so they always win even if `MemoryTiersOptions` later adds\n\t\t\t\t// any of the same keys.\n\t\t\t\t...opts.tiers,\n\t\t\t\tname: \"tiers\",\n\t\t\t\tsource: filteredSource,\n\t\t\t\textractFn,\n\t\t\t\tscore: opts.score,\n\t\t\t\tcost: opts.cost,\n\t\t\t\t...(opts.budget !== undefined ? { budget: opts.budget } : { budget: 2000 }),\n\t\t\t\t...(opts.context !== undefined ? { context: opts.context } : {}),\n\t\t\t\t...(consolidateFn !== undefined ? { consolidate: consolidateFn } : {}),\n\t\t\t\t...(consolidateTrigger !== undefined ? { consolidateTrigger } : {}),\n\t\t\t});\n\t\t\tthis.mount(\"tiers\", tiersGraph);\n\t\t\tdistillBundle = tiersGraph.store;\n\t\t\tmemoryTiersBundle = tiersGraph.tiers;\n\t\t\ttiersSubgraph = tiersGraph;\n\t\t} else {\n\t\t\tdistillBundle = distill<unknown, TMem>(filteredSource, extractFn, distillOpts);\n\t\t\tthis.add(distillBundle.store.entries, { name: \"store\" });\n\t\t\tthis.add(distillBundle.compact, { name: \"compact\" });\n\t\t\tthis.add(distillBundle.size, { name: \"size\" });\n\t\t}\n\n\t\t// --- Vector index (composer) ---\n\t\tlet vectors: VectorIndexGraph<TMem> | null = null;\n\t\tif (opts.vectorDimensions && opts.vectorDimensions > 0 && opts.embedFn) {\n\t\t\tconst vectorsGraph = memoryWithVectors<TMem>({\n\t\t\t\tname: \"vectors\",\n\t\t\t\tstore: distillBundle,\n\t\t\t\tdimension: opts.vectorDimensions,\n\t\t\t\tembedFn: opts.embedFn,\n\t\t\t});\n\t\t\tthis.mount(\"vectors\", vectorsGraph);\n\t\t\tvectors = vectorsGraph.vectors;\n\t\t}\n\n\t\t// --- Knowledge graph (composer) ---\n\t\tlet kg: KnowledgeGraph<unknown, string> | null = null;\n\t\tif (opts.enableKnowledgeGraph) {\n\t\t\tconst kgGraph = memoryWithKG<TMem>({\n\t\t\t\tname: \"knowledge\",\n\t\t\t\tstore: distillBundle,\n\t\t\t\tkgName: `${name}-kg`,\n\t\t\t\tmountPath: \"knowledge-kg\",\n\t\t\t\t...(opts.entityFn !== undefined ? { entityFn: opts.entityFn } : {}),\n\t\t\t});\n\t\t\tthis.mount(\"knowledge\", kgGraph);\n\t\t\tkg = kgGraph.kg;\n\t\t}\n\n\t\t// --- Retrieval pipeline (composer) ---\n\t\tlet retrieveReactive:\n\t\t\t| ((\n\t\t\t\t\tqueryInput: NodeInput<RetrievalQuery | null>,\n\t\t\t ) => Node<ReadonlyArray<RetrievalEntry<TMem>>>)\n\t\t\t| null = null;\n\n\t\tif (vectors || kg) {\n\t\t\tconst retrievalGraph = memoryRetrieval<TMem>({\n\t\t\t\tname: \"retrieval\",\n\t\t\t\tstore: distillBundle,\n\t\t\t\tvectors,\n\t\t\t\tkg,\n\t\t\t\tscore: opts.score,\n\t\t\t\tcost: opts.cost,\n\t\t\t\t...(opts.budget !== undefined ? { budget: opts.budget } : {}),\n\t\t\t\t...(opts.retrieval?.topK !== undefined ? { topK: opts.retrieval.topK } : {}),\n\t\t\t\t...(opts.retrieval?.graphDepth !== undefined\n\t\t\t\t\t? { graphDepth: opts.retrieval.graphDepth }\n\t\t\t\t\t: {}),\n\t\t\t\t...(opts.contextOf !== undefined ? { contextOf: opts.contextOf } : {}),\n\t\t\t\t...(opts.contextWeight !== undefined ? { contextWeight: opts.contextWeight } : {}),\n\t\t\t\t...(opts.context !== undefined ? { context: opts.context } : {}),\n\t\t\t});\n\t\t\tthis.mount(\"retrieval\", retrievalGraph);\n\t\t\tretrieveReactive = retrievalGraph.retrieveReactive.bind(retrievalGraph);\n\t\t}\n\n\t\tthis.distillBundle = distillBundle;\n\t\tthis.compact = distillBundle.compact;\n\t\tthis.size = distillBundle.size;\n\t\tthis.vectors = vectors;\n\t\tthis.kg = kg;\n\t\tthis.memoryTiers = memoryTiersBundle;\n\t\tthis.tiers = tiersSubgraph;\n\t\tthis.retrieveReactive = retrieveReactive;\n\t}\n}\n\n/**\n * Pre-wired agentic memory graph. Sugar over `distill` plus the\n * `memoryWithVectors` / `memoryWithKG` / `memoryWithTiers` / `memoryRetrieval`\n * composers. Power users who want a subset of capabilities can call those\n * composers directly; this factory bundles them into one ergonomic call.\n *\n * Returns an {@link AgentMemoryGraph} subclass instance — `instanceof\n * AgentMemoryGraph` narrows in callers (e.g. Phase 13.G `agent(spec)`).\n */\nexport function agentMemory<TMem = unknown>(\n\tname: string,\n\tsource: NodeInput<unknown>,\n\topts: AgentMemoryOptions<TMem>,\n): AgentMemoryGraph<TMem> {\n\treturn new AgentMemoryGraph<TMem>(name, source, 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\tonDeactivation: () => {\n\t\t\t\tstopped = true;\n\t\t\t\tunsub?.();\n\t\t\t},\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\tonDeactivation: source.subscribe((msgs) => {\n\t\t\t\ta.down(msgs);\n\t\t\t}),\n\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\tonDeactivation: source.subscribe((msgs) => {\n\t\t\t\ta.down(msgs);\n\t\t\t}),\n\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// 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 * 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// DS-14.7 follow-up #2 (persistence half) — durable, event-sourced fact store\n// with substrate-owned replay/dedup (memo:Re Story 6.4 back-derivation).\nexport {\n\ttype PersistentReactiveFactStoreConfig,\n\ttype PersistentReactiveFactStoreGraph,\n\tpersistentReactiveFactStore,\n} from \"./persistent-fact-store.js\";\n// DS-14.7 follow-up #1: recipe library — 8 shipped compositions over the\n// four extension faces. Re-exported here so `utils/memory` stays the single\n// import surface.\nexport * from \"./recipes/index.js\";\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// 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\tonDeactivation: () => {\n\t\t\t\t\t\t\t\tabortDispose?.();\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\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\tonDeactivation: () => {\n\t\t\t\t\t\t\tcancelled = true;\n\t\t\t\t\t\t\tsub();\n\t\t\t\t\t\t\t// F-7: cleanup callback's abortDispose call is idempotent —\n\t\t\t\t\t\t\t// the terminal-branch dispose above sets `abortDispose =\n\t\t\t\t\t\t\t// undefined` so this is a no-op when terminal-fired.\n\t\t\t\t\t\t\tabortDispose?.();\n\t\t\t\t\t\t\tabortDispose = undefined;\n\t\t\t\t\t\t},\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 * harnessLoop() factory (roadmap §9.0).\n *\n * Wires the static 7-stage topology: INTAKE → TRIAGE → QUEUE → GATE →\n * EXECUTE → VERIFY → REFLECT. Static topology, flowing data — the Kafka\n * insight applied to human+LLM collaboration.\n *\n * **Hub model (Wave B Unit 20 C + Q1).** All reactive-wire-crossing topics\n * live in one `MessagingHubGraph` exposed as `HarnessGraph.queues`: the\n * four per-route queues, an `__unrouted` dead-letter, plus `intake`,\n * `retry`, `verify-results`, and the `triage-output` fan-in topic. The\n * router is a single derived/effect pair that publishes to `triage-output`;\n * per-route `topicBridge`s fan out by `map:` predicate. Routing is data\n * (topic name), not code — every routing decision is a visible edge in\n * `describe()` / `explain()`.\n *\n * **EXECUTE/VERIFY via JobFlow (Tier 6.5 C2 lock, 2026-04-28).** The\n * stages 5–6 EXECUTE → VERIFY pair runs through an internal `executeFlow`\n * JobFlow with two stages (`execute`, `verify`). Each stage's pump owns\n * `claim → work → ack` for one claim; the verify stage's payload contains\n * `{ item, execution, verify }` so the post-completed dispatch effect can\n * route the 3-way verdict (verified / self-correctable retry / structural\n * + reingest) without any cross-wave `withLatestFrom` pairing. Items\n * arriving from per-route topics + retry feedback enter via a single\n * `enqueueEffect` that pushes to `executeFlow.queue(\"execute\")`.\n *\n * @module\n */\n\nimport { monotonicNs, type Node, node, placeholderArgs } from \"@graphrefly/pure-ts/core\";\nimport { merge, withLatestFrom } from \"@graphrefly/pure-ts/extra\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { tryIncrementBounded } from \"../../base/mutation/index.js\";\nimport { _oneShotLlmCall, stripFences } from \"../../utils/ai/_internal.js\";\nimport type { ChatMessage, LLMAdapter } from \"../../utils/ai/index.js\";\nimport { promptNode } from \"../../utils/ai/index.js\";\nimport { trackingKey } from \"../../utils/harness/_internal.js\";\nimport {\n\tDEFAULT_DECAY_RATE,\n\tDEFAULT_EXECUTE_PROMPT,\n\tDEFAULT_QUEUE_CONFIGS,\n\tDEFAULT_SEVERITY_WEIGHTS,\n\tDEFAULT_TRIAGE_PROMPT,\n\tDEFAULT_VERIFY_PROMPT,\n\tdefaultErrorClassifier,\n\tQUEUE_NAMES,\n\tresolvePromptFn,\n} from \"../../utils/harness/defaults.js\";\nimport {\n\ttype StrategyModelGraph,\n\ttype StrategySnapshot,\n\tstrategyModel,\n} from \"../../utils/harness/strategy.js\";\nimport type {\n\tErrorClassifier,\n\tExecuteOutput,\n\tExecutePromptFn,\n\tExecutionResult,\n\tHarnessExecutor,\n\tHarnessJobPayload,\n\tHarnessLoopOptions,\n\tHarnessVerifier,\n\tIntakeItem,\n\tQueueConfig,\n\tQueueRoute,\n\tTriagedItem,\n\tVerifyOutput,\n\tVerifyPromptFn,\n\tVerifyResult,\n} from \"../../utils/harness/types.js\";\nimport { DEFAULT_PRESET_ID, strategyKey } from \"../../utils/harness/types.js\";\nimport {\n\ttype JobEnvelope,\n\ttype JobFlowGraph,\n\ttype JobQueueGraph,\n\tjobFlow,\n\tjobQueue,\n} from \"../../utils/job-queue/index.js\";\nimport {\n\ttype MessagingHubGraph,\n\tmessagingHub,\n\ttype TopicGraph,\n\ttopicBridge,\n} from \"../../utils/messaging/index.js\";\nimport { type GateController, pipelineGraph } from \"../../utils/orchestration/index.js\";\n\n// ---------------------------------------------------------------------------\n// Hub topic names (internal constants — strings are the routing API)\n// ---------------------------------------------------------------------------\n\nconst TOPIC_INTAKE = \"intake\";\nconst TOPIC_TRIAGE_OUTPUT = \"triage-output\";\nconst TOPIC_RETRY = \"retry\";\nconst TOPIC_VERIFY_RESULTS = \"verify-results\";\nconst TOPIC_UNROUTED = \"__unrouted\";\n\n// ---------------------------------------------------------------------------\n// Default LLM executor / verifier work fns (Tier 6.5 C2)\n// ---------------------------------------------------------------------------\n\n/**\n * Build the default EXECUTE work fn — calls `adapter.invoke()` once per\n * claimed job, parses the JSON response into an `ExecuteOutput<A>`, and\n * returns a {@link HarnessJobPayload} with `execution` filled in.\n *\n * Errors (parse failure, adapter throw, malformed JSON) are caught and\n * surfaced as a `failure`-outcome payload — the dispatch effect routes\n * the item rather than dropping it via pump nack (see C2 contract on\n * {@link HarnessExecutor}).\n *\n * Subsumes the pre-Tier-6.5 `promptNode`-based default: per-claim LLM\n * calls don't benefit from `promptNode`'s cross-wave switchMap, and a\n * fresh per-claim subgraph would be wasteful. Direct `adapter.invoke`\n * is the right shape inside JobFlow pumps.\n *\n * @param adapter - LLMAdapter for the execute call.\n * @param prompt - Prompt template (string or `(item) => string`). Defaults\n * to the harness's built-in execute prompt.\n */\nexport function defaultLlmExecutor<A = unknown>(\n\tadapter: LLMAdapter,\n\tprompt?: string | ExecutePromptFn,\n): HarnessExecutor<A> {\n\tconst promptFn = resolvePromptFn<TriagedItem>(prompt, DEFAULT_EXECUTE_PROMPT, (tpl, item) =>\n\t\ttpl.replace(\"{{item}}\", JSON.stringify(item)),\n\t);\n\treturn (job, opts) => {\n\t\tconst item = job.payload.item;\n\t\tconst messages: readonly ChatMessage[] = [{ role: \"user\", content: promptFn(item) }];\n\t\t// Bridge-layer flakes get `outcome: \"failure\"` with no `errorClass`.\n\t\t// The dispatch effect's `errorClassifier` runs over `detail` and the\n\t\t// default classifier matches `parse|json|config|validation|syntax`,\n\t\t// so parse-error flakes route to retry. Adapter HTTP/network failures\n\t\t// without a keyword fall through to structural per the existing\n\t\t// asymmetry (executor side relies on classifier; verifier side sets\n\t\t// errorClass directly per qa F3).\n\t\tconst failurePayload = (detail: string): HarnessJobPayload<A> => ({\n\t\t\t...job.payload,\n\t\t\texecution: { item, outcome: \"failure\", detail },\n\t\t});\n\t\tconst formatErr = (err: unknown): string => (err instanceof Error ? err.message : String(err));\n\t\t// One-shot bridge via `_oneShotLlmCall` (patterns/ai/_internal.ts).\n\t\t// Helper owns subscription / abort / first-DATA capture / COMPLETE\n\t\t// arm; this site owns parse + validate + payload mapping. Pump-\n\t\t// supplied `opts.signal` (Tier 6.5 2.5b) cascades into adapter +\n\t\t// fromAny via `parentSignal`.\n\t\treturn _oneShotLlmCall<HarnessJobPayload<A>>(adapter, messages, {\n\t\t\tparentSignal: opts?.signal,\n\t\t\tonSuccess: (resp) => {\n\t\t\t\tlet parsed: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(stripFences(String(resp.content)));\n\t\t\t\t} catch (err) {\n\t\t\t\t\treturn failurePayload(`execute parse error: ${formatErr(err)}`);\n\t\t\t\t}\n\t\t\t\t// Validate plain object before field access — non-object JSON\n\t\t\t\t// (`null` / number / array / string) silently masks malformed\n\t\t\t\t// responses unless caught here. Surfaced via parse-error keyword\n\t\t\t\t// for classifier routing.\n\t\t\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t\t\treturn failurePayload(\n\t\t\t\t\t\t`execute parse error: non-object response: ${JSON.stringify(parsed)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst obj = parsed as Partial<ExecuteOutput<A>>;\n\t\t\t\treturn {\n\t\t\t\t\t...job.payload,\n\t\t\t\t\texecution: {\n\t\t\t\t\t\titem,\n\t\t\t\t\t\toutcome: obj.outcome ?? \"failure\",\n\t\t\t\t\t\tdetail: obj.detail ?? \"unknown\",\n\t\t\t\t\t\tartifact: obj.artifact,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t\tonFailure: (kind, err) => {\n\t\t\t\tif (kind === \"complete\") {\n\t\t\t\t\treturn failurePayload(\"adapter completed without emitting DATA\");\n\t\t\t\t}\n\t\t\t\treturn failurePayload(`executor failed: ${formatErr(err)}`);\n\t\t\t},\n\t\t});\n\t};\n}\n\n/**\n * Build the default VERIFY work fn — calls `adapter.invoke()` once per\n * claimed job to review the prior-stage execution, parses the JSON\n * response into a `VerifyOutput`, and returns a {@link HarnessJobPayload}\n * with `verify` filled in.\n *\n * Same C2 error semantics as {@link defaultLlmExecutor}: parse / adapter\n * failures are surfaced as a structural-failure verify payload so the\n * dispatch effect routes the item.\n */\nexport function defaultLlmVerifier<A = unknown>(\n\tadapter: LLMAdapter,\n\tprompt?: string | VerifyPromptFn<A>,\n): HarnessVerifier<A> {\n\tconst promptFn = resolvePromptFn<readonly [ExecuteOutput<A> | null, TriagedItem | null]>(\n\t\tprompt,\n\t\tDEFAULT_VERIFY_PROMPT,\n\t\t(tpl, pair) => {\n\t\t\tconst [execution, item] = pair;\n\t\t\treturn tpl\n\t\t\t\t.replace(\"{{execution}}\", JSON.stringify(execution))\n\t\t\t\t.replace(\"{{item}}\", JSON.stringify(item));\n\t\t},\n\t);\n\treturn (job, opts) => {\n\t\tconst { item, execution } = job.payload;\n\t\tif (execution == null) {\n\t\t\t// Defensive — verify stage runs after execute; if execution is\n\t\t\t// missing, surface as STRUCTURAL failure rather than throw. This is\n\t\t\t// the only structural-classified path here: it indicates a topology\n\t\t\t// bug (verify ran without execute), not an LLM-bridge flake. Bridge\n\t\t\t// flakes (parse / adapter throw / ERROR / COMPLETE-without-DATA) get\n\t\t\t// `errorClass: \"self-correctable\"` below so the dispatch effect's\n\t\t\t// retry budget absorbs them before reingest fires (qa F3).\n\t\t\treturn {\n\t\t\t\t...job.payload,\n\t\t\t\tverify: {\n\t\t\t\t\tverified: false,\n\t\t\t\t\tfindings: [\"verifier: prior execute stage produced no execution\"],\n\t\t\t\t\terrorClass: \"structural\",\n\t\t\t\t},\n\t\t\t} satisfies HarnessJobPayload<A>;\n\t\t}\n\t\tconst messages: readonly ChatMessage[] = [\n\t\t\t{ role: \"user\", content: promptFn([execution, item]) },\n\t\t];\n\t\t// Bridge-layer flakes: classify as self-correctable so the dispatch\n\t\t// effect routes via the retry budget first. Persistent flakes still\n\t\t// fall through to structural after `maxRetries` exhaustion (qa F3).\n\t\tconst failurePayload = (finding: string): HarnessJobPayload<A> => ({\n\t\t\t...job.payload,\n\t\t\tverify: {\n\t\t\t\tverified: false,\n\t\t\t\tfindings: [finding],\n\t\t\t\terrorClass: \"self-correctable\",\n\t\t\t},\n\t\t});\n\t\tconst formatErr = (err: unknown): string => (err instanceof Error ? err.message : String(err));\n\t\t// One-shot bridge — see `_oneShotLlmCall` JSDoc. Helper owns the\n\t\t// subscribe + capture + abort + COMPLETE arm; this site owns parse +\n\t\t// validate + verify-payload mapping. Pump-supplied `opts.signal`\n\t\t// (Tier 6.5 2.5b) cascades into adapter + fromAny via `parentSignal`.\n\t\treturn _oneShotLlmCall<HarnessJobPayload<A>>(adapter, messages, {\n\t\t\tparentSignal: opts?.signal,\n\t\t\tonSuccess: (resp) => {\n\t\t\t\tlet parsed: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(stripFences(String(resp.content)));\n\t\t\t\t} catch (err) {\n\t\t\t\t\treturn failurePayload(`verify parse error: ${formatErr(err)}`);\n\t\t\t\t}\n\t\t\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t\t\treturn failurePayload(\n\t\t\t\t\t\t`verify parse error: non-object response: ${JSON.stringify(parsed)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst obj = parsed as Partial<VerifyOutput>;\n\t\t\t\treturn {\n\t\t\t\t\t...job.payload,\n\t\t\t\t\tverify: {\n\t\t\t\t\t\tverified: obj.verified === true,\n\t\t\t\t\t\tfindings: obj.findings ?? [],\n\t\t\t\t\t\terrorClass: obj.errorClass,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t\tonFailure: (kind, err) => {\n\t\t\t\tif (kind === \"complete\") {\n\t\t\t\t\treturn failurePayload(\"verifier completed without emitting DATA\");\n\t\t\t\t}\n\t\t\t\treturn failurePayload(`verifier failed: ${formatErr(err)}`);\n\t\t\t},\n\t\t});\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// HarnessGraph\n// ---------------------------------------------------------------------------\n\n/**\n * The graph returned by {@link harnessLoop}. Wraps a single\n * {@link MessagingHubGraph} that owns all reactive-wire-crossing topics\n * (intake, per-route queues, `__unrouted`, retry, verify-results,\n * triage-output), plus an `executeFlow` JobFlow that owns the\n * EXECUTE → VERIFY pipeline (Tier 6.5 C2). Sugar getters expose the\n * canonical topics so the surface stays ergonomic.\n */\nexport class HarnessGraph<A = unknown> extends Graph {\n\t/** Messaging hub — the routing-data plane. Queue topics live here. */\n\treadonly queues: MessagingHubGraph;\n\n\t/**\n\t * EXECUTE → VERIFY JobFlow (Tier 6.5 C2). Pumps own claim/ack/nack\n\t * lifecycle for each stage. Inspect via:\n\t * - `harness.executeFlow.queue(\"execute\").pending` — pending depth.\n\t * - `harness.executeFlow.queue(\"verify\").pending` — items mid-execute.\n\t * - `harness.executeFlow.completed` — verified items waiting for the\n\t * dispatch effect's 3-way routing.\n\t * - `harness.executeFlow.completedCount` — total terminal completions.\n\t */\n\treadonly executeFlow: JobFlowGraph<HarnessJobPayload<A>>;\n\n\t/**\n\t * Per-route JobQueueGraph audit mirrors. Each triaged item that reaches\n\t * a queue is also enqueued here, giving reactive `depth` + `pending` +\n\t * `jobs` observables per route. The dispatch effect ack/removeBy-id's\n\t * the matching job on terminal verdict. The executeFlow JobFlow handles\n\t * the EXECUTE → VERIFY data flow; this is a parallel audit-side ledger\n\t * for per-route depth metrics. Inspect via\n\t * `harness.jobs.get(route).depth.cache` for backpressure metrics.\n\t */\n\treadonly jobs: ReadonlyMap<QueueRoute, JobQueueGraph<TriagedItem>>;\n\n\t/** Per-route gate controllers (only for gated queues). */\n\treadonly gates: ReadonlyMap<QueueRoute, GateController<TriagedItem>>;\n\n\t/**\n\t * Per-route queue topics — typed accessor for the four\n\t * {@link QUEUE_NAMES} entries (`auto-fix`, `needs-decision`,\n\t * `investigation`, `backlog`). Mirrors the `gates` / `jobs` map\n\t * shape so callers can iterate `[route, topic]` pairs without\n\t * hand-rolling `harness.queues.topicNames()` + meta-topic exclusion.\n\t *\n\t * Excludes the meta topics that share the hub:\n\t * `intake` (use {@link intake}), `verify-results` (use\n\t * {@link verifyResults}), `retry` (use {@link retry}), `__unrouted`\n\t * (use {@link unrouted}), and the internal `triage-output` fan-in.\n\t */\n\treadonly queueTopics: ReadonlyMap<QueueRoute, TopicGraph<TriagedItem>>;\n\n\t/** Strategy model — `auditedSuccessTracker` keyed by `StrategyKey`. */\n\treadonly strategy: StrategyModelGraph;\n\n\t/** Global retry count across all items (circuit breaker). Reactive — subscribable. */\n\treadonly totalRetries: Node<number>;\n\n\t/** Global reingestion count across all items (circuit breaker). Reactive — subscribable. */\n\treadonly totalReingestions: Node<number>;\n\n\t/**\n\t * Per-route priority score nodes, populated only when `opts.priority` is\n\t * set on {@link harnessLoop}. Each node emits a score combining severity,\n\t * attention decay, and strategy-model effectiveness for the route's\n\t * current head-of-queue item. `undefined` means the caller did not opt\n\t * in to priority scoring.\n\t */\n\treadonly priorityScores?: ReadonlyMap<QueueRoute, Node<number>>;\n\n\t/**\n\t * REFLECT-stage tick marker — emits one DATA per terminal verdict observed\n\t * on `executeFlow.completed`. `equals: () => false` so each completion\n\t * produces an observable tick (no Object.is collapse on identical\n\t * `null` payloads). Inspection tools (`harnessTrace`, dashboards) can\n\t * subscribe directly here instead of resolving by string path\n\t * (`harness.node(\"reflect\")`) — the field is the lock against rename\n\t * drift.\n\t */\n\treadonly reflect: Node<null>;\n\n\tconstructor(\n\t\tname: string,\n\t\tqueues: MessagingHubGraph,\n\t\texecuteFlow: JobFlowGraph<HarnessJobPayload<A>>,\n\t\tqueueTopics: Map<QueueRoute, TopicGraph<TriagedItem>>,\n\t\tjobs: Map<QueueRoute, JobQueueGraph<TriagedItem>>,\n\t\tgates: Map<QueueRoute, GateController<TriagedItem>>,\n\t\tstrategy: StrategyModelGraph,\n\t\ttotalRetries: Node<number>,\n\t\ttotalReingestions: Node<number>,\n\t\treflect: Node<null>,\n\t\tpriorityScores?: Map<QueueRoute, Node<number>>,\n\t) {\n\t\tsuper(name);\n\t\tthis.queues = queues;\n\t\tthis.executeFlow = executeFlow;\n\t\tthis.queueTopics = queueTopics;\n\t\tthis.jobs = jobs;\n\t\tthis.gates = gates;\n\t\tthis.strategy = strategy;\n\t\tthis.totalRetries = totalRetries;\n\t\tthis.totalReingestions = totalReingestions;\n\t\tthis.reflect = reflect;\n\t\tthis.priorityScores = priorityScores;\n\t}\n\n\t/** Intake topic — publish items here to enter the loop. */\n\tget intake(): TopicGraph<IntakeItem> {\n\t\treturn this.queues.topic<IntakeItem>(TOPIC_INTAKE);\n\t}\n\n\t/** Verify results topic — subscribe to see verification outcomes. */\n\tget verifyResults(): TopicGraph<VerifyResult<A>> {\n\t\treturn this.queues.topic<VerifyResult<A>>(TOPIC_VERIFY_RESULTS);\n\t}\n\n\t/** Retry feedback topic — fast-retry re-entry point. */\n\tget retry(): TopicGraph<TriagedItem> {\n\t\treturn this.queues.topic<TriagedItem>(TOPIC_RETRY);\n\t}\n\n\t/** Dead-letter topic for items whose LLM-chosen route is unknown. */\n\tget unrouted(): TopicGraph<TriagedItem> {\n\t\treturn this.queues.topic<TriagedItem>(TOPIC_UNROUTED);\n\t}\n\n\t/**\n\t * Stage-label → observe-path map for the 7 pipeline stages.\n\t *\n\t * Decouples inspection tools (`harnessTrace`, `harnessProfile`, custom\n\t * dashboards) from mount-structure churn: hub migration, future stage\n\t * splits, gate remounting, or the Tier 6.5 C2 JobFlow rewire shouldn't\n\t * require edits to `trace.ts` as long as this method stays accurate.\n\t *\n\t * Each stage yields `{ label, paths }`; consumers iterate paths per\n\t * stage and attach observers. Tier 6.5: EXECUTE / VERIFY paths now\n\t * resolve to the `executeFlow` stage queues + the `verify-dispatch`\n\t * effect node.\n\t */\n\tstageNodes(): ReadonlyArray<{ label: string; paths: readonly string[] }> {\n\t\tconst hub = this.queues;\n\t\tconst resolveHubPath = (name: string): string | null =>\n\t\t\thub.has(name) ? `queues::${name}::latest` : null;\n\t\tconst includeIf = <T>(value: T | null | undefined): readonly T[] =>\n\t\t\tvalue == null ? [] : [value];\n\n\t\tconst queuePaths = QUEUE_NAMES.flatMap((r) => includeIf(resolveHubPath(r)));\n\t\tconst gatePaths: string[] = [];\n\t\tfor (const [route] of this.gates) {\n\t\t\tgatePaths.push(`gates::${route}/gate`);\n\t\t}\n\t\treturn [\n\t\t\t{ label: \"INTAKE\", paths: includeIf(resolveHubPath(\"intake\")) },\n\t\t\t{ label: \"TRIAGE\", paths: [\"triage\"] },\n\t\t\t{ label: \"QUEUE\", paths: queuePaths },\n\t\t\t{ label: \"GATE\", paths: gatePaths },\n\t\t\t{ label: \"EXECUTE\", paths: [\"executeFlow::execute::events\"] },\n\t\t\t{ label: \"VERIFY\", paths: [\"executeFlow::verify::events\"] },\n\t\t\t{ label: \"REFLECT\", paths: [\"reflect\"] },\n\t\t\t{ label: \"STRATEGY\", paths: [\"strategy::entries\"] },\n\t\t];\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// harnessLoop factory\n// ---------------------------------------------------------------------------\n\n/**\n * Wire the reactive collaboration loop as a static-topology graph.\n *\n * The loop has 7 stages:\n * 1. **INTAKE** — items arrive from multiple sources via `intake.publish()`\n * 2. **TRIAGE** — promptNode classifies, routes, and prioritizes\n * 3. **QUEUE** — 4 priority-ordered TopicGraphs (auto-fix, needs-decision, investigation, backlog)\n * 4. **GATE** — human approval on configurable queues\n * 5. **EXECUTE** — JobFlow `execute` stage; user-supplied or default work fn\n * 6. **VERIFY** — JobFlow `verify` stage; verifies the executed artifact\n * 7. **REFLECT** — strategy model records outcomes; dispatch effect routes 3-way\n *\n * @param name - Graph name.\n * @param opts - Configuration.\n * @returns HarnessGraph with controller accessors.\n */\nexport function harnessLoop<A = unknown>(\n\tname: string,\n\topts: HarnessLoopOptions<A>,\n): HarnessGraph<A> {\n\tconst adapter = opts.adapter;\n\tconst maxRetries = opts.maxRetries ?? 2;\n\tconst retainedLimit = opts.retainedLimit ?? 1000;\n\tconst errorClassifier: ErrorClassifier = opts.errorClassifier ?? defaultErrorClassifier;\n\n\tconst queueConfigs = new Map<QueueRoute, QueueConfig>();\n\tfor (const route of QUEUE_NAMES) {\n\t\tqueueConfigs.set(route, {\n\t\t\t...DEFAULT_QUEUE_CONFIGS[route],\n\t\t\t...opts.queues?.[route],\n\t\t});\n\t}\n\n\t// --- Messaging hub (Wave B Q1 Option A) ---\n\tconst queuesHub = messagingHub(`${name}/queues`, {\n\t\tdefaultTopicOptions: { retainedLimit },\n\t});\n\n\t// Eagerly create canonical topics so they appear in `describe()` from\n\t// construction time and `harness.queues.has(route)` answers `true`\n\t// before any publish.\n\tconst intake = queuesHub.topic<IntakeItem>(TOPIC_INTAKE);\n\tconst triageOutput = queuesHub.topic<TriagedItem>(TOPIC_TRIAGE_OUTPUT);\n\tconst retryTopic = queuesHub.topic<TriagedItem>(TOPIC_RETRY);\n\tconst verifyResults = queuesHub.topic<VerifyResult<A>>(TOPIC_VERIFY_RESULTS);\n\tconst queueTopics = new Map<QueueRoute, TopicGraph<TriagedItem>>();\n\tfor (const route of QUEUE_NAMES) {\n\t\tqueueTopics.set(route, queuesHub.topic<TriagedItem>(route));\n\t}\n\tconst unroutedTopic = queuesHub.topic<TriagedItem>(TOPIC_UNROUTED);\n\n\t// --- Strategy model (used by triage + dispatch) ---\n\tconst strategy = strategyModel();\n\n\t// --- Stage 2: TRIAGE ---\n\t// triageInput pairs intake.latest (trigger) with strategy.entries\n\t// (advisory, sampled via withLatestFrom). Breaks the feedback cycle\n\t// (verify → strategy.record → strategy.entries would otherwise re-fire\n\t// triage on every recorded outcome).\n\tconst triageInput = withLatestFrom(\n\t\tintake.latest as Node<unknown>,\n\t\tstrategy.entries as Node<unknown>,\n\t);\n\n\tconst triagePromptFn = resolvePromptFn<readonly [IntakeItem, StrategySnapshot]>(\n\t\topts.triagePrompt,\n\t\tDEFAULT_TRIAGE_PROMPT,\n\t\t(tpl, pair) => {\n\t\t\tconst [item, strat] = pair;\n\t\t\treturn tpl\n\t\t\t\t.replace(\"{{strategy}}\", JSON.stringify(Array.from(strat.entries())))\n\t\t\t\t.replace(\"{{item}}\", JSON.stringify(item));\n\t\t},\n\t);\n\n\tconst triageNode = promptNode<TriagedItem>(\n\t\tadapter as LLMAdapter,\n\t\t[triageInput as Node<unknown>],\n\t\t(pair: unknown) => {\n\t\t\t// `intake.latest` is now SENTINEL on empty (COMPOSITION-GUIDE §1a),\n\t\t\t// so the `withLatestFrom partial:false` gate holds the fn until both\n\t\t\t// deps deliver real DATA. The `=== undefined` guard catches the\n\t\t\t// edge where the pair itself is unset (defensive — shouldn't fire\n\t\t\t// in normal flow).\n\t\t\tconst asPair = pair as readonly [IntakeItem, StrategySnapshot] | undefined;\n\t\t\tif (asPair === undefined) return \"\";\n\t\t\treturn triagePromptFn(asPair);\n\t\t},\n\t\t{\n\t\t\tname: \"triage\",\n\t\t\tformat: \"json\",\n\t\t},\n\t);\n\n\t// --- Stage 3: QUEUE (hub routing) ---\n\t//\n\t// Router is a thin effect that publishes the merged TriagedItem to\n\t// `triage-output`. `topicBridge`s fan it out to per-route queues by\n\t// filtering on `item.route`. Unknown routes flow into `__unrouted` so\n\t// misclassified items become a subscribable dead-letter signal.\n\tconst routerInput = withLatestFrom(triageNode as Node<unknown>, triageInput as Node<unknown>);\n\tconst router = node(\n\t\t[routerInput 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 pair = data[0];\n\t\t\tif (pair == null) return;\n\t\t\tconst [classification, triagePair] = pair as [\n\t\t\t\tTriagedItem | null,\n\t\t\t\t[IntakeItem | null, StrategySnapshot] | null,\n\t\t\t];\n\t\t\tif (!classification?.route) return;\n\t\t\tconst intakeItem = triagePair?.[0];\n\t\t\t// Intake fields win over classification: the LLM only owns the five\n\t\t\t// triage-classification fields (rootCause, intervention, route,\n\t\t\t// priority, triageReasoning); any intake state it accidentally\n\t\t\t// returns is overwritten by the real intake value via the trailing\n\t\t\t// spread.\n\t\t\tconst merged: TriagedItem = { ...classification, ...intakeItem } as TriagedItem;\n\t\t\ttriageOutput.publish(merged);\n\t\t},\n\t\t{ describeKind: \"effect\" },\n\t);\n\tconst routerUnsub = router.subscribe(() => {});\n\n\t// TopicBridges fan triage-output into per-route queues (visible edges).\n\tconst knownRoutes = new Set<string>(QUEUE_NAMES);\n\tfor (const route of QUEUE_NAMES) {\n\t\ttopicBridge<TriagedItem>(`bridge/${route}`, triageOutput, queueTopics.get(route)!, {\n\t\t\tmap: (item) => (item.route === route ? item : undefined),\n\t\t});\n\t}\n\ttopicBridge<TriagedItem>(\"bridge/__unrouted\", triageOutput, unroutedTopic, {\n\t\tmap: (item) => (knownRoutes.has(item.route) ? undefined : item),\n\t});\n\n\t// --- Per-route audit JobQueueGraphs (parallel ledger) ---\n\t//\n\t// One jobQueue per route mirrors the route topic's publishes so\n\t// dashboards get a subscribable `depth` / `pending` / `jobs` view of\n\t// in-progress items. Identity is established at enqueue time (the\n\t// returned `id` is paired with `trackingKey(item)`); the dispatch\n\t// effect calls `JobQueueGraph.removeById(id)` on terminal verdict.\n\t//\n\t// This audit ledger runs in parallel with the `executeFlow` JobFlow\n\t// (Tier 6.5 C2). The two are complementary:\n\t// - This ledger gives **per-route** depth/pending observables\n\t// (\"how backed up is auto-fix?\").\n\t// - executeFlow gives **per-stage** depth/pending observables\n\t// (\"how many items are mid-execute?\").\n\t//\n\t// **Retry handling.** Retry items republished to `retryTopic` flow\n\t// into executeFlow (via the enqueue effect) but NOT into per-route\n\t// audit jq's (retryTopic isn't mirrored). The audit job stays alive\n\t// across retries — only terminal (verified / structural) decisions\n\t// remove it. `depth` reflects \"items still being worked on\".\n\t//\n\t// **Ring-buffer safety.** WeakSet keyed on item identity; once the\n\t// topic's ring buffer trims the head, dropped entries become\n\t// unreachable and the WeakSet auto-prunes.\n\tconst jobQueues = new Map<QueueRoute, JobQueueGraph<TriagedItem>>();\n\tconst routeJobIds = new Map<string, { route: QueueRoute; id: string }>();\n\tfor (const route of QUEUE_NAMES) {\n\t\tjobQueues.set(route, jobQueue<TriagedItem>(`jobs/${route}`));\n\t}\n\tconst jobMirrorUnsubs: Array<() => void> = [];\n\tfor (const route of QUEUE_NAMES) {\n\t\tconst topic = queueTopics.get(route)!;\n\t\tconst jq = jobQueues.get(route)!;\n\t\tconst seen = new WeakSet<object>();\n\t\tconst mirror = node(\n\t\t\t[topic.events as Node<unknown>],\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 events = data[0];\n\t\t\t\tconst arr = (events ?? []) as readonly TriagedItem[];\n\t\t\t\tfor (const item of arr) {\n\t\t\t\t\tif (seen.has(item as unknown as object)) continue;\n\t\t\t\t\tseen.add(item as unknown as object);\n\t\t\t\t\tconst id = jq.enqueue(item);\n\t\t\t\t\trouteJobIds.set(trackingKey(item), { route, id });\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ name: `jobs/${route}-mirror`, describeKind: \"effect\" },\n\t\t);\n\t\tjobMirrorUnsubs.push(mirror.subscribe(() => {}));\n\t}\n\n\tfunction ackJob(item: TriagedItem): void {\n\t\tconst key = trackingKey(item);\n\t\tconst entry = routeJobIds.get(key);\n\t\tif (!entry) return;\n\t\tjobQueues.get(entry.route)?.removeById(entry.id);\n\t\trouteJobIds.delete(key);\n\t}\n\n\t// --- Stage 4: GATE ---\n\t//\n\t// Per-route gates between `topic.latest` and the executeFlow enqueue.\n\t// Foreign-node-accept (Session B.1): pass `topic.latest` directly; the\n\t// gate factory auto-adds the source under `${name}/source` inside its\n\t// own graph if not already registered.\n\tconst gateGraph = pipelineGraph(\"gates\");\n\tconst gateControllers = new Map<QueueRoute, GateController<TriagedItem>>();\n\tfor (const route of QUEUE_NAMES) {\n\t\tconst config = queueConfigs.get(route)!;\n\t\tif (!config.gated) continue;\n\t\tconst topic = queueTopics.get(route)!;\n\t\tconst ctrl = gateGraph.approvalGate<TriagedItem>(\n\t\t\t`${route}/gate`,\n\t\t\ttopic.latest as Node<unknown>,\n\t\t\t{\n\t\t\t\tmaxPending: config.maxPending,\n\t\t\t\tstartOpen: config.startOpen,\n\t\t\t},\n\t\t);\n\t\tgateControllers.set(route, ctrl);\n\t}\n\n\t// --- executeInput: merge of post-gate route latests + retry feedback ---\n\t// All inputs are SENTINEL until first DATA (COMPOSITION-GUIDE §1a): topic\n\t// `latest` returns `[]` on empty, gate `output` doesn't push pre-DATA.\n\tconst queueOutputs: Node<TriagedItem>[] = [];\n\tfor (const route of QUEUE_NAMES) {\n\t\tconst config = queueConfigs.get(route)!;\n\t\tif (config.gated && gateControllers.has(route)) {\n\t\t\tqueueOutputs.push(gateControllers.get(route)!.output as Node<TriagedItem>);\n\t\t} else {\n\t\t\tqueueOutputs.push(queueTopics.get(route)!.latest);\n\t\t}\n\t}\n\tqueueOutputs.push(retryTopic.latest);\n\n\tconst executeInput = merge<TriagedItem>(...queueOutputs);\n\n\t// --- Stages 5+6: EXECUTE → VERIFY via JobFlow (Tier 6.5 C2) ---\n\tconst executor: HarnessExecutor<A> =\n\t\topts.executor ?? defaultLlmExecutor<A>(adapter as LLMAdapter, opts.executePrompt);\n\tconst verifier: HarnessVerifier<A> =\n\t\topts.verifier ?? defaultLlmVerifier<A>(adapter as LLMAdapter, opts.verifyPrompt);\n\n\t// Per-stage `maxPerPump` caps via the JobFlow `StageDef.maxPerPump`\n\t// extension (Tier 6.5 D1 follow-up). Each stage gets its own cap;\n\t// callers can pin execute at a low concurrency for cost control while\n\t// leaving verify unbounded (or vice versa). Defaults to\n\t// `Number.MAX_SAFE_INTEGER` per stage — matches today's unbounded\n\t// `merge()` parallelism.\n\tconst executeMaxPerPump = opts.executeMaxPerPump ?? Number.MAX_SAFE_INTEGER;\n\tconst verifyMaxPerPump = opts.verifyMaxPerPump ?? Number.MAX_SAFE_INTEGER;\n\n\tconst executeFlow = jobFlow<HarnessJobPayload<A>>(`${name}/executeFlow`, {\n\t\tstages: [\n\t\t\t{ name: \"execute\", work: (job) => executor(job), maxPerPump: executeMaxPerPump },\n\t\t\t{ name: \"verify\", work: (job) => verifier(job), maxPerPump: verifyMaxPerPump },\n\t\t],\n\t});\n\n\t// Enqueue effect: per-item bridge from the reactive `executeInput`\n\t// stream into the JobFlow. Each non-null item becomes one JobEnvelope\n\t// at the execute stage. Retry items (via `retryTopic`) re-enter the\n\t// flow as fresh enqueues with their `$retries` counter bumped.\n\tconst enqueueEffect = node(\n\t\t[executeInput 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\texecuteFlow.enqueue({ item: item as TriagedItem });\n\t\t},\n\t\t{ name: \"execute-enqueue\", describeKind: \"effect\" },\n\t);\n\tconst enqueueUnsub = enqueueEffect.subscribe(() => {});\n\n\t// --- Stage 7: dispatch effect (REFLECT + retry/structural routing) ---\n\t//\n\t// Replaces the pre-Tier-6.5 `fastRetry` effect. Reads completed\n\t// JobEnvelopes from `executeFlow.completed`, identifies new ones via\n\t// WeakSet, and dispatches the 3-way verdict:\n\t//\n\t// 1. **Verified** → record success, publish VerifyResult, ack audit job.\n\t// 2. **Self-correctable + retries available** → republish to retryTopic\n\t// with $retries bumped (no audit ack — retry stays in the audit ledger).\n\t// 3. **Structural / retries exhausted** → record failure, publish\n\t// VerifyResult, ack audit job, reingest if reingestion budget remains.\n\t//\n\t// Imperative cross-graph publish from inside an effect is sanctioned\n\t// per COMPOSITION-GUIDE §32 / §35 for terminal side-effects with audit\n\t// trails (here: verifyResults / retry / intake topics).\n\tconst maxReingestions = opts.maxReingestions ?? 1;\n\tconst maxTotalRetries = Math.min(opts.maxTotalRetries ?? maxRetries * 10, 100);\n\tconst maxTotalReingestions = Math.min(opts.maxTotalReingestions ?? maxReingestions * 10, 100);\n\tconst totalRetries = node([], { initial: 0 });\n\tconst totalReingestions = node([], { initial: 0 });\n\n\tfunction assembleResult(\n\t\texecution: ExecutionResult<A>,\n\t\tverify: VerifyOutput,\n\t\titem: TriagedItem,\n\t): VerifyResult<A> {\n\t\treturn {\n\t\t\titem,\n\t\t\texecution,\n\t\t\tverified: verify.verified,\n\t\t\tfindings: verify.findings ?? [],\n\t\t\terrorClass: verify.errorClass,\n\t\t};\n\t}\n\n\tfunction handleVerified(vr: VerifyResult<A>, item: TriagedItem): void {\n\t\tstrategy.record(strategyKey(DEFAULT_PRESET_ID, item.rootCause, item.intervention), true, {\n\t\t\tpresetId: DEFAULT_PRESET_ID,\n\t\t\trootCause: item.rootCause,\n\t\t\tintervention: item.intervention,\n\t\t});\n\t\tverifyResults.publish(vr);\n\t\tackJob(item);\n\t}\n\n\tfunction handleRetry(vr: VerifyResult<A>, item: TriagedItem): void {\n\t\tconst key = trackingKey(item);\n\t\tconst itemRetries = item.$retries ?? 0;\n\t\tconst retryItem: TriagedItem = {\n\t\t\t...item,\n\t\t\t$retries: itemRetries + 1,\n\t\t\tsummary: `[RETRY ${itemRetries + 1}/${maxRetries}] ${key} — Previous attempt failed: ${vr.findings.join(\"; \")}`,\n\t\t\trelatedTo: [key],\n\t\t};\n\t\tretryTopic.publish(retryItem);\n\t\t// Audit job stays alive across retries — only terminal (verified /\n\t\t// structural) decisions remove it.\n\t}\n\n\tfunction handleStructural(vr: VerifyResult<A>, item: TriagedItem): void {\n\t\tstrategy.record(strategyKey(DEFAULT_PRESET_ID, item.rootCause, item.intervention), false, {\n\t\t\tpresetId: DEFAULT_PRESET_ID,\n\t\t\trootCause: item.rootCause,\n\t\t\tintervention: item.intervention,\n\t\t});\n\t\tverifyResults.publish(vr);\n\t\tackJob(item);\n\t\tconst key = trackingKey(item);\n\t\tconst itemReingestions = item.$reingestions ?? 0;\n\t\tif (\n\t\t\titemReingestions < maxReingestions &&\n\t\t\ttryIncrementBounded(totalReingestions, maxTotalReingestions)\n\t\t) {\n\t\t\tintake.publish({\n\t\t\t\tsource: item.source,\n\t\t\t\tsummary: `Verification failed for: ${key}`,\n\t\t\t\tevidence: vr.findings.join(\"\\n\"),\n\t\t\t\taffectsAreas: item.affectsAreas,\n\t\t\t\taffectsEvalTasks: item.affectsEvalTasks,\n\t\t\t\tseverity: item.severity ?? \"high\",\n\t\t\t\trelatedTo: [key],\n\t\t\t\t$reingestions: itemReingestions + 1,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Monotonic length cursor (qa F4) — `executeFlow.completed` retains up to\n\t// `DEFAULT_COMPLETED_RETAINED_LIMIT` (1024) entries; each new completion\n\t// emits a fresh snapshot containing every retained job. A naive\n\t// `WeakSet.has` walk is O(retainedLimit) per emit. Track the last-seen\n\t// length and only iterate the new tail. The cursor is capped at the\n\t// snapshot length to handle ring-buffer trims (when the retained log\n\t// drops oldest entries past the limit, `arr.length` shrinks and the\n\t// cursor catches up automatically).\n\tlet dispatchCursor = 0;\n\tconst dispatchEffect = node(\n\t\t[executeFlow.completed 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 log = data[0];\n\t\t\tconst arr = (log ?? []) as readonly JobEnvelope<HarnessJobPayload<A>>[];\n\t\t\t// Trim handling: if the retained log shrunk below our cursor, the\n\t\t\t// missing entries are gone (we already processed them or the trim\n\t\t\t// happened mid-flight); just clamp.\n\t\t\tif (dispatchCursor > arr.length) dispatchCursor = arr.length;\n\t\t\tconst start = dispatchCursor;\n\t\t\tdispatchCursor = arr.length;\n\t\t\tfor (let i = start; i < arr.length; i++) {\n\t\t\t\tconst job = arr[i] as JobEnvelope<HarnessJobPayload<A>>;\n\t\t\t\tconst { item, execution, verify } = job.payload;\n\t\t\t\t// Defensive — both should always be present in a verify-stage\n\t\t\t\t// completion. If either is missing, log via verifyResults so the\n\t\t\t\t// failure is observable but don't block the dispatch effect.\n\t\t\t\tif (execution == null || verify == null) {\n\t\t\t\t\tackJob(item);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst vr = assembleResult(execution, verify, item);\n\t\t\t\tif (vr.verified) {\n\t\t\t\t\thandleVerified(vr, item);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst errClass =\n\t\t\t\t\tvr.errorClass ??\n\t\t\t\t\terrorClassifier({\n\t\t\t\t\t\titem,\n\t\t\t\t\t\toutcome: execution.outcome,\n\t\t\t\t\t\tdetail: vr.findings.join(\"; \"),\n\t\t\t\t\t});\n\t\t\t\tconst itemRetries = item.$retries ?? 0;\n\t\t\t\tif (\n\t\t\t\t\terrClass === \"self-correctable\" &&\n\t\t\t\t\titemRetries < maxRetries &&\n\t\t\t\t\ttryIncrementBounded(totalRetries, maxTotalRetries)\n\t\t\t\t) {\n\t\t\t\t\thandleRetry(vr, item);\n\t\t\t\t} else {\n\t\t\t\t\thandleStructural(vr, item);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{ name: \"verify-dispatch\", describeKind: \"effect\" },\n\t);\n\tconst dispatchUnsub = dispatchEffect.subscribe(() => {});\n\n\t// REFLECT — topology marker derived from completed-log emissions.\n\t// `equals: () => false` disables Object.is absorption so each\n\t// completion produces an observable REFLECT tick (one per verify\n\t// wave). Without this, `null === null` would collapse every emit\n\t// after the first into RESOLVED and the trace would show a single\n\t// REFLECT event over the whole run.\n\tconst reflectNode = node(\n\t\t[executeFlow.completed as Node<unknown>],\n\t\t(_batchData, actions) => {\n\t\t\tactions.emit(null);\n\t\t},\n\t\t{\n\t\t\tname: \"reflect\",\n\t\t\tequals: () => false,\n\t\t},\n\t);\n\n\t// --- Optional priority scoring (Unit 19) ---\n\tlet priorityScores: Map<QueueRoute, Node<number>> | undefined;\n\tif (opts.priority) {\n\t\tpriorityScores = buildPriorityScores(queueTopics, strategy, opts);\n\t}\n\n\t// --- Assemble HarnessGraph ---\n\tconst harness = new HarnessGraph<A>(\n\t\tname,\n\t\tqueuesHub,\n\t\texecuteFlow,\n\t\tqueueTopics,\n\t\tjobQueues,\n\t\tgateControllers,\n\t\tstrategy,\n\t\ttotalRetries,\n\t\ttotalReingestions,\n\t\treflectNode as Node<null>,\n\t\tpriorityScores,\n\t);\n\n\t// Register disposers for unregistered internal nodes.\n\tharness.addDisposer(routerUnsub);\n\tharness.addDisposer(enqueueUnsub);\n\tharness.addDisposer(dispatchUnsub);\n\t// Strategy is mounted as a child subgraph below; its disposal cascades\n\t// via the mount lifecycle (no separate `addDisposer(strategy.dispose)`\n\t// needed post Class B audit Alt E migration).\n\tfor (const unsub of jobMirrorUnsubs) harness.addDisposer(unsub);\n\n\t// Register stage nodes for introspection (harnessTrace, describe,\n\t// observe). Tier 6.3: triage-input + router-input named so\n\t// `explain(intake.latest, reflect)` walks named nodes end-to-end with\n\t// no `<anonymous>` entries.\n\tharness.add(triageInput as Node<unknown>, { name: \"triage-input\" });\n\tharness.add(triageNode as Node<unknown>, { name: \"triage\" });\n\tharness.add(routerInput as Node<unknown>, { name: \"router-input\" });\n\tharness.add(executeInput as Node<unknown>, { name: \"execute-input\" });\n\tharness.add(enqueueEffect as Node<unknown>, { name: \"execute-enqueue\" });\n\tharness.add(dispatchEffect as Node<unknown>, { name: \"verify-dispatch\" });\n\tharness.add(reflectNode as Node<unknown>, { name: \"reflect\" });\n\t// Reflect is a topology marker — subscribe so its fn registers as a\n\t// reactive edge visible in `describe()` / `explain()` immediately on\n\t// harness construction.\n\tharness.addDisposer(reflectNode.subscribe(() => undefined));\n\tif (priorityScores) {\n\t\tfor (const [route, score] of priorityScores) {\n\t\t\tharness.add(score as Node<unknown>, { name: `priority/${route}` });\n\t\t\tharness.addDisposer(score.subscribe(() => {}));\n\t\t}\n\t}\n\n\t// Mount subgraphs\n\tharness.mount(\"queues\", queuesHub);\n\tharness.mount(\"gates\", gateGraph);\n\tharness.mount(\"executeFlow\", executeFlow);\n\tharness.mount(\"strategy\", strategy);\n\tfor (const [route, jq] of jobQueues) {\n\t\tharness.mount(`jobs/${route}`, jq);\n\t}\n\n\t// Tier 1.5.3 Phase 2.5 (DG1=B): tag the Graph with its constructing\n\t// factory so `describe()` exposes provenance.\n\tharness.tagFactory(\"harnessLoop\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\n\treturn harness;\n}\n\n// ---------------------------------------------------------------------------\n// Priority scoring wiring (Unit 19 decision 2)\n// ---------------------------------------------------------------------------\n\nfunction buildPriorityScores<A>(\n\tqueueTopics: Map<QueueRoute, TopicGraph<TriagedItem>>,\n\tstrategy: StrategyModelGraph,\n\topts: HarnessLoopOptions<A>,\n): Map<QueueRoute, Node<number>> {\n\tif (!opts.lastInteractionNs) {\n\t\tthrow new Error(\n\t\t\t\"harnessLoop: `opts.priority` requires `opts.lastInteractionNs` — pass a Node<number> (e.g. `fromTimer(60_000)` or a `state(monotonicNs())` you bump on human interaction). Priority scores only decay when this node settles; an internal default would freeze age at construction time.\",\n\t\t);\n\t}\n\tconst lastInteractionNs = opts.lastInteractionNs;\n\tconst signals = opts.priority ?? {};\n\tconst severityWeights = {\n\t\t...DEFAULT_SEVERITY_WEIGHTS,\n\t\t...signals.severityWeights,\n\t} as Record<string, number>;\n\tconst decayRate = signals.decayRate ?? DEFAULT_DECAY_RATE;\n\tconst effectivenessThreshold = signals.effectivenessThreshold ?? 0.7;\n\tconst effectivenessBoost = signals.effectivenessBoost ?? 15;\n\n\tconst scores = new Map<QueueRoute, Node<number>>();\n\tfor (const [route, topic] of queueTopics) {\n\t\tconst score = node<number>(\n\t\t\t[\n\t\t\t\ttopic.latest as Node<unknown>,\n\t\t\t\tstrategy.entries as Node<unknown>,\n\t\t\t\tlastInteractionNs as Node<unknown>,\n\t\t\t],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst vals = 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 item = vals[0] as TriagedItem | undefined;\n\t\t\t\tif (item === undefined) {\n\t\t\t\t\tactions.emit(0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst baseWeight = severityWeights[item.severity ?? \"medium\"] ?? 40;\n\t\t\t\tconst ageSeconds = (monotonicNs() - (vals[2] as number)) / 1e9;\n\t\t\t\tlet s = baseWeight * Math.exp(-decayRate * Math.max(0, ageSeconds));\n\t\t\t\tconst key = strategyKey(DEFAULT_PRESET_ID, item.rootCause, item.intervention);\n\t\t\t\tconst strat = vals[1] as ReadonlyMap<string, { successRate: number }>;\n\t\t\t\tconst entry = strat?.get(key);\n\t\t\t\tif (entry && entry.successRate >= effectivenessThreshold) {\n\t\t\t\t\ts += effectivenessBoost;\n\t\t\t\t}\n\t\t\t\tactions.emit(s);\n\t\t\t},\n\t\t\t{ name: `priority/${route}`, describeKind: \"derived\" },\n\t\t);\n\t\tscores.set(route, score);\n\t}\n\treturn scores;\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 { onDeactivation: 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 { onDeactivation: 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\tonDeactivation: () => {\n\t\t\t\t\tfor (const u of unsubs) u();\n\t\t\t\t},\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 * 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\tonDeactivation: () => {\n\t\t\t\t\tsourceUnsub?.();\n\t\t\t\t\tfallbackUnsub?.();\n\t\t\t\t},\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\tonDeactivation: () => {\n\t\t\t\t\tterminated = true;\n\t\t\t\t\ttimer.cancel();\n\t\t\t\t\tunsub();\n\t\t\t\t\toptMirror.unsub();\n\t\t\t\t},\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 * 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, type ReactiveLogBundle, 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// ── LogProjector ──────────────────────────────────────────────────────────\n//\n// Promotion 2 (memo:Re Story 6.4 back-derivation, design-review-locked\n// 2026-05-16). A cursor-driven projector over a log/topic where a per-item\n// sink can poison-fail. memo:Re hand-rolled `createProjectorCursor` and got\n// the failure mode wrong: a bare `catch { break; }` conflated a *transient*\n// condition (a native feature not yet available → retry later) with a\n// *poison* entry (will never project) → a permanent head-of-line block of\n// every newer entry. The fix is a real, observable, subscribable dead-letter\n// topic + a typed failure policy.\n//\n// Built ON `subscription()` (TopicGraph source) / the bundle's `fromCursor`\n// view (ReactiveLogBundle source) — the same hardened cursor machinery\n// `SubscriptionGraph` itself uses — so the consumer never hand-rolls cursor\n// persistence/durability (the Med \"durability skew\" + parse-leniency findings\n// dissolve). Scope is deliberately bounded: `halt | deadLetter` only, NO\n// programmatic retry/backoff (compose a downstream subscription on\n// `deadLetter` for that — avoids the §44 wrap-imperative-as-primitive trap).\n\nexport type ProjectorPoisonPolicy = \"halt\" | \"deadLetter\";\n\n/** A poison entry routed to {@link LogProjectorGraph.deadLetter}. */\nexport type DeadLetterEntry<T> = {\n\treadonly item: T;\n\t/** `Error.message` (or `String(thrown)`) from the failing `sink`. */\n\treadonly error: string;\n\t/** Absolute 0-based log position of the poisoned item. */\n\treadonly cursorPos: number;\n};\n\nexport type LogProjectorOptions<T> = {\n\tgraph?: GraphOptions;\n\t/**\n\t * Per-item side-effecting projection.\n\t *\n\t * **Transient-vs-poison contract (read this).** The projector cannot tell\n\t * \"this will project later\" from \"this will never project\" — only the sink\n\t * knows. So the contract is:\n\t * - **Return normally** (sync return, or a resolved Promise) → the item is\n\t * *handled*; the cursor advances. Use this for the success path AND for\n\t * any transient/skip condition the sink wants to no-op (e.g. an optional\n\t * native feature not yet available — return without throwing; the entry\n\t * is simply considered done for this projector).\n\t * - **Throw / reject** → the item is *poison*; the {@link onPoison} policy\n\t * applies. Do NOT throw for transient conditions or the item is\n\t * dead-lettered (or halts the stream).\n\t */\n\treadonly sink: (item: T) => void | Promise<void>;\n\t/**\n\t * Behaviour when `sink` throws/rejects on an item (poison):\n\t * - `\"halt\"` (default) — stop projecting at the poison item; the cursor\n\t * does NOT advance past it (head-of-line stop). `position` stalls — that\n\t * is the observable signal. No retry/backoff is built in.\n\t * - `\"deadLetter\"` — publish `{ item, error, cursorPos }` to the\n\t * {@link LogProjectorGraph.deadLetter} topic and advance past it, so\n\t * newer entries still project.\n\t */\n\treadonly onPoison?: ProjectorPoisonPolicy;\n\t/**\n\t * Initial cursor position. `\"retained\"` (default) projects all history;\n\t * `\"now\"` skips existing entries (project only future appends); a number\n\t * starts at that absolute index.\n\t */\n\treadonly from?: \"retained\" | \"now\" | number;\n\t/** Retained window for the `deadLetter` topic. Default 1024. */\n\treadonly deadLetterRetainedLimit?: number;\n};\n\n/**\n * Cursor-driven projector over a {@link TopicGraph} or {@link ReactiveLogBundle}.\n *\n * Topology (mounted on the returned graph):\n * - `subscription` (TopicGraph source only) — the hardened\n * {@link SubscriptionGraph} cursor; or a local `cursor` state + the\n * bundle's `fromCursor` view (ReactiveLogBundle source).\n * - `drain` — an `effect` that, on every not-yet-projected wave, schedules a\n * serialized async pass that calls `sink` per item (mirrors the\n * `SubscriptionGraph.ackPump` / `TopicBridge.ackPump` effect precedent +\n * memo:Re's `inFlight` chain — one wave processed at a time).\n * - `deadLetter` — a real {@link TopicGraph} (NOT a callback): poison entries\n * are observable in `describe()` and subscribable, instead of memo:Re's\n * silent `break`.\n *\n * **No imperative reads.** Observe `position` (cursor) / subscribe to\n * `deadLetter`. `idle()` is a test-only await convenience.\n *\n * @category patterns\n */\nexport class LogProjectorGraph<T> extends Graph {\n\t/** Reactive count of fully-projected entries (the cursor; read-only). */\n\treadonly position: Node<number>;\n\t/**\n\t * Poison entries (populated when `onPoison: \"deadLetter\"`). A real topic —\n\t * subscribable + visible in `describe()`.\n\t */\n\treadonly deadLetter: TopicGraph<DeadLetterEntry<T>>;\n\tprivate _inFlight: Promise<void> = Promise.resolve();\n\n\tconstructor(\n\t\tname: string,\n\t\tsource: TopicGraph<T> | ReactiveLogBundle<T>,\n\t\topts: LogProjectorOptions<T>,\n\t) {\n\t\tsuper(name, opts.graph);\n\t\tconst onPoison: ProjectorPoisonPolicy = opts.onPoison ?? \"halt\";\n\t\tconst sink = opts.sink;\n\n\t\tconst dl = new TopicGraph<DeadLetterEntry<T>>(`${name}_dead_letter`, {\n\t\t\tretainedLimit: opts.deadLetterRetainedLimit ?? DEFAULT_TOPIC_RETAINED_LIMIT,\n\t\t});\n\t\tthis.mount(\"deadLetter\", dl);\n\t\tthis.deadLetter = dl;\n\n\t\t// Uniform cursor surface over either source kind. A TopicGraph reuses\n\t\t// the hardened SubscriptionGraph cursor; a ReactiveLogBundle uses a\n\t\t// local state cursor + the bundle's `fromCursor` view — the very\n\t\t// machinery SubscriptionGraph is itself built on.\n\t\tlet available: Node<readonly T[]>;\n\t\tlet cursorBase: () => number;\n\t\tlet advance: (n: number) => void;\n\n\t\tif (source instanceof TopicGraph) {\n\t\t\tconst sub = new SubscriptionGraph<T>(`${name}_subscription`, source, {\n\t\t\t\tfrom: opts.from ?? \"retained\",\n\t\t\t});\n\t\t\tthis.mount(\"subscription\", sub);\n\t\t\tavailable = sub.available;\n\t\t\tthis.position = sub.cursor;\n\t\t\tcursorBase = () => sub.cursor.cache as number;\n\t\t\tadvance = (n) => {\n\t\t\t\tif (n > 0) sub.ack(n);\n\t\t\t};\n\t\t} else {\n\t\t\tconst log = source;\n\t\t\tlet initialCursor: number;\n\t\t\tif (opts.from === \"now\") {\n\t\t\t\tinitialCursor = log.size;\n\t\t\t} else if (typeof opts.from === \"number\") {\n\t\t\t\tinitialCursor = requireNonNegativeInt(opts.from, \"logProjector from\");\n\t\t\t} else {\n\t\t\t\tinitialCursor = 0; // \"retained\"\n\t\t\t}\n\t\t\tconst cursor = this.state<number>(\"cursor\", initialCursor, {\n\t\t\t\tmeta: messagingMeta(\"log_projector_cursor\"),\n\t\t\t});\n\t\t\tthis.position = cursor;\n\t\t\tcursorBase = () => cursor.cache as number;\n\t\t\tavailable = log.view({ kind: \"fromCursor\", cursor });\n\t\t\tadvance = (n) => {\n\t\t\t\tif (n > 0) cursor.emit((cursor.cache as number) + n);\n\t\t\t};\n\t\t}\n\n\t\t// `halt` is a HARD LATCH (QA-C): on the first poison under `onPoison:\n\t\t// \"halt\"`, `sink` has been invoked exactly once on the poison item;\n\t\t// the projector then freezes — no further `sink` calls, no rescheduled\n\t\t// drains — so a later unrelated append cannot re-invoke the (possibly\n\t\t// side-effecting, non-idempotent) sink on the poison. The stalled\n\t\t// `position` + frozen stream IS the observable signal. v1 has no retry\n\t\t// (compose downstream of `deadLetter` if you need that).\n\t\tlet halted = false;\n\n\t\t// Serialized async drain. One wave processed at a time (the inFlight\n\t\t// chain) so an async `sink` cannot interleave; the cursor is advanced\n\t\t// ONCE per pass after the captured snapshot is processed (mirrors\n\t\t// memo:Re's `runPump` + the ackPump effect precedent).\n\t\tconst runDrain = async (): Promise<void> => {\n\t\t\tif (halted) return;\n\t\t\tconst snapshot = (available.cache as readonly T[] | undefined) ?? [];\n\t\t\tif (snapshot.length === 0) return;\n\t\t\tlet consumed = 0;\n\t\t\tfor (let i = 0; i < snapshot.length; i += 1) {\n\t\t\t\tconst item = snapshot[i] as T;\n\t\t\t\ttry {\n\t\t\t\t\tawait sink(item);\n\t\t\t\t\tconsumed += 1;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst error = e instanceof Error ? e.message : String(e);\n\t\t\t\t\tif (onPoison === \"deadLetter\") {\n\t\t\t\t\t\tdl.publish({ item, error, cursorPos: cursorBase() + consumed });\n\t\t\t\t\t\tconsumed += 1; // advance past the poison\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// \"halt\" — latch and stop here; do NOT advance past the\n\t\t\t\t\t// poison, do NOT re-invoke `sink` on any later wave.\n\t\t\t\t\thalted = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (consumed > 0) advance(consumed);\n\t\t};\n\t\tconst schedule = (): void => {\n\t\t\tif (halted) return; // latched — no further drains\n\t\t\tthis._inFlight = this._inFlight.then(runDrain, runDrain);\n\t\t};\n\n\t\t// Effect: every wave that exposes not-yet-projected entries schedules a\n\t\t// drain. Side-effecting (sink / cursor advance / dead-letter publish) →\n\t\t// an `effect` node, not a pure derived (COMPOSITION-GUIDE §35; exact\n\t\t// `SubscriptionGraph.advancePump` precedent — never calls `emit` on its\n\t\t// own node, kept warm via `keepalive`).\n\t\tconst drain = node<unknown>(\n\t\t\t[available],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\tconst b = batchData[0];\n\t\t\t\tconst snap = (b != null && b.length > 0 ? b.at(-1) : ctx.prevData[0]) as\n\t\t\t\t\t| readonly T[]\n\t\t\t\t\t| undefined;\n\t\t\t\tif (snap && snap.length > 0) schedule();\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"drain\",\n\t\t\t\tdescribeKind: \"effect\",\n\t\t\t\tmeta: messagingMeta(\"log_projector_drain\"),\n\t\t\t},\n\t\t);\n\t\tthis.add(drain, { name: \"drain\" });\n\t\tthis.addDisposer(keepalive(drain));\n\t}\n\n\t/**\n\t * Await any in-flight drain pass. **Test convenience only** — the canonical\n\t * reactive observable is {@link LogProjectorGraph.position}.\n\t */\n\tidle(): Promise<void> {\n\t\treturn this._inFlight;\n\t}\n}\n\n/**\n * Creates a cursor-driven log/topic projector with a typed poison-failure\n * policy and an observable dead-letter topic.\n *\n * @example\n * ```ts\n * import { logProjector, topic } from \"@graphrefly/graphrefly\";\n *\n * const events = topic<Doc>(\"docs\");\n * const proj = logProjector(\"indexer\", events, {\n * sink: async (doc) => { await index(doc); }, // throw ⇒ poison\n * onPoison: \"deadLetter\",\n * });\n * proj.deadLetter.events.subscribe(/* observe poison *​/);\n * ```\n *\n * @remarks\n * **Use an UNBOUNDED source for durable / long-lived projection.** The cursor\n * is an absolute index; the underlying `fromCursor` view slices the source's\n * *current* entries array. A `TopicGraph` with a `retainedLimit` (or a\n * `ReactiveLogBundle` with `maxSize`) trims its head, so an absolute cursor\n * past the retained window reads the wrong offset (skips entries or stalls).\n * This is inherited `subscription()` / `fromCursor` behaviour, not specific to\n * `logProjector` — but it matters here because projection is typically\n * long-lived. For unbounded projection pass a source with NO `retainedLimit` /\n * `maxSize` (memo:Re's `changesetLog` is unbounded ✓).\n *\n * @category patterns\n */\nexport function logProjector<T>(\n\tname: string,\n\tsource: TopicGraph<T> | ReactiveLogBundle<T>,\n\topts: LogProjectorOptions<T>,\n): LogProjectorGraph<T> {\n\treturn new LogProjectorGraph<T>(name, source, opts);\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 * Harness-domain internal helpers.\n *\n * trackingKey extracted from patterns/_internal/index.ts during cleave A2.\n * Destination decided per STOP #1 resolution: harness-domain shape,\n * used only by utils/harness/types.ts and presets/harness/harness-loop.ts.\n */\n\n// trackingKey\n// ---------------------------------------------------------------------------\n\n/**\n * Stable tracking key for an item with retry/reingestion decoration.\n *\n * Uses `relatedTo[0]` if present (carries the original key forward through\n * retries and reingestions). Falls back to `summary` for first-time items.\n *\n * This avoids deriving keys from mutated summary strings — retries decorate\n * the summary with `[RETRY N/M]` and failure context, so regex-stripping\n * would be fragile and any new decoration pattern would risk infinite loops\n * by generating novel keys.\n *\n * **Caller contract — uniqueness (qa D1, 2026-04-29).** Two distinct intake\n * items sharing the same `summary` (and neither carrying `relatedTo`)\n * produce the SAME tracking key. The harness's `routeJobIds` map is keyed\n * by this value: a duplicate-key publish overwrites the prior mapping, and\n * a later `ackJob` for the original publish acks the wrong audit job.\n * Single-threaded JS makes the typical structural-failure path safe (the\n * ack runs before reingest publishes), but multi-publisher concurrency or\n * batched intake of two items with identical summaries can race.\n *\n * **Caller responsibility:** ensure `summary` uniqueness OR carry an\n * explicit stable id via `relatedTo[0]` for items that may collide. For\n * retry/reingestion paths the `relatedTo` array MUST start with the\n * original tracking key — `[originalKey, ...]` — so the carried-forward\n * identity matches the audit log entry created at first publish.\n *\n * @internal\n */\nexport function trackingKey(item: { summary: string; relatedTo?: string[] }): string {\n\treturn item.relatedTo?.[0] ?? item.summary;\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 * 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 * refineLoop — universal prompt/artifact optimization loop as a reactive Graph.\n *\n * Roadmap §9.8 (Wave 2.5). The loop is a 4-topic reactive pipeline:\n *\n * iterationTrigger ──▶ GENERATE ──▶ EVALUATE ──▶ ANALYZE ──▶ DECIDE\n * │ │\n * └─────── feedback + trigger ◀─────┘\n *\n * Each stage is a `TopicGraph` so dispatches stay O(1) per subscriber (cursor-\n * based) and every iteration is observable, replayable, and checkpointable.\n *\n * Composition invariants (from COMPOSITION-GUIDE):\n * - §7 feedback cycle: only `iterationTrigger` drives re-generation. Strategy\n * + feedback + dataset are read via closure updaters (§28 factory-time seed)\n * so mid-run swaps apply to the NEXT iteration, never retrigger the current.\n * - §28 factory-time seed: strategy, lastFeedback, prevCandidates, dataset\n * closures captured at wiring time + updated via subscribe handlers so the\n * first activation doesn't drop the initial pair.\n * - §32 nested-drain state-mirror: the decide-effect writes `lastFeedback`\n * BEFORE bumping `iterationTrigger` inside its `batch()`, guaranteeing the\n * mirror is current when the next-iteration wave reaches the generate fn.\n * - §19 terminal-emission: history / best emit once per iteration (settled),\n * not on every intermediate wave.\n * - §27 attachSnapshotStorage: the whole graph is checkpointable — pause overnight,\n * resume tomorrow from the exact iteration count, candidate set, strategy.\n *\n * Scope clamp (v1): core factory + `RefineStrategy<T>` + `blindVariation` and\n * `errorCritique` built-ins + budget gating + checkpoint/resume.\n * `mutateAndRefine` / registry / `autoSelectStrategy` / `optimizeCatalog` /\n * `refineExecutor` are deferred.\n *\n * @module\n */\n\n// `createNode` is the local alias for `node` so calls don't shadow\n// `Graph.prototype.node` when the file's body inadvertently references the\n// graph's `.node()` method. B5f keeps protocol-primitive construction visually\n// distinct from graph-instance method dispatch.\nimport {\n\tbatch,\n\tnode as createNode,\n\tDATA,\n\tERROR,\n\tmonotonicNs,\n\ttype Node,\n\tplaceholderArgs,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport type { NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { switchMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { tryIncrementBounded } from \"../../base/mutation/index.js\";\nimport { messagingHub, type TopicGraph } from \"../../utils/messaging/index.js\";\n\n// ---------------------------------------------------------------------------\n// Core types\n// ---------------------------------------------------------------------------\n\n/** A single task row — the unit the evaluator scores one candidate against. */\nexport interface DatasetItem {\n\treadonly id: string;\n\treadonly [k: string]: unknown;\n}\n\n/**\n * One candidate's score on one task. Higher is better by convention.\n *\n * Set `candidateIndex` when the evaluator fans out scores across multiple\n * candidates (e.g. `candidates × tasks`). `pickBest` aggregates mean scores\n * per `candidateIndex` when present; when absent, falls back to positional\n * alignment (`scores[i]` ↔ `candidates[i]`).\n */\nexport interface EvalResult {\n\treadonly taskId: string;\n\treadonly score: number;\n\treadonly error?: string;\n\treadonly detail?: unknown;\n\t/** 0-based index into the `candidates` batch this score belongs to. */\n\treadonly candidateIndex?: number;\n}\n\n/** Aggregated feedback the strategy produces from a scores batch. */\nexport interface Feedback {\n\treadonly summary: string;\n\treadonly critique?: unknown;\n\treadonly weakTasks?: readonly string[];\n\treadonly score: number;\n}\n\n/**\n * Strategy interface — plain object, no base class. Strategies implement three\n * pure hooks; the loop infrastructure wraps them in reactive nodes so every\n * decision is visible in `describe()`.\n *\n * `generate` may be sync or async. Async generates yield a microtask per\n * iteration — that's what gives `pause()` / `setStrategy()` a window to\n * interleave. **A fully synchronous `generate` will drain the entire loop\n * during factory activation** (all iterations run before `refineLoop()`\n * returns), which is usually not what you want for observable, steerable\n * loops. Real strategies that call LLMs / evals are async and Just Work;\n * custom sync strategies for tests are fine but should be marked `async`\n * to match real cadence.\n */\nexport interface RefineStrategy<T> {\n\treadonly name: string;\n\t/** Produce initial candidates from the seed. Called at iteration 0. */\n\tseed(seed: T): readonly T[];\n\t/** Reduce scores to feedback. Pure function. */\n\tanalyze(scores: readonly EvalResult[], candidates: readonly T[]): Feedback;\n\t/**\n\t * Generate next-iteration candidates from feedback + prior candidates.\n\t * Async allowed — the loop awaits via `fromAny`.\n\t */\n\tgenerate(feedback: Feedback, candidates: readonly T[]): Promise<readonly T[]> | readonly T[];\n}\n\n/**\n * Evaluator shape — Shape 4 (2026-04-22): both `candidates` and `dataset` are\n * reactive nodes; the evaluator's returned node IS the EVALUATE topic's source\n * (no glue). Implementers can batch-eval (e.g. `funnel` with concurrency) or\n * map per-candidate — user's code.\n *\n * **Cancel-on-input contract (load-bearing).** Evaluators with async work\n * (LLM calls, network requests, etc.) MUST cancel any in-flight work when\n * `candidates` emits a new batch. The canonical pattern is `switchMap` over\n * `candidates`. If an evaluator does NOT cancel — e.g. naively kicks a\n * `Promise.all` per-batch and emits whatever resolves — late scores from a\n * prior iteration can arrive after the loop has already moved to the next\n * iteration (especially after `pause()` / `resume()`). Such stale scores\n * trip {@link refineLoop}'s `feedbackEnvelopeNode` with mismatched\n * `iter`/`scores`/`items`, producing an incorrect `DecideEvent` and (worse)\n * marking the iter as decided so the real iter's scores get skipped by\n * de-dup, stalling the loop. See `optimizations.md` \"refineLoop async-\n * evaluator stale-scores follow-up\" for the proposed `wrapEvaluator()`\n * helper that would enforce cancellation.\n *\n * **`EvalResult.candidateIndex` semantics.** Optional per-result field.\n * When present, multi-candidate aggregators ({@link errorCritique}'s\n * `pickBest`) score per index, picking the candidate with the highest\n * mean score. When absent across all results, those aggregators fall back\n * to positional matching against `candidates[0]` — meaning a strategy that\n * generates >1 candidate but emits unindexed scores effectively only ever\n * critiques the first candidate. Set `candidateIndex` whenever the\n * evaluator's score corresponds to a specific candidate in the batch.\n */\nexport type Evaluator<T> = (\n\tcandidates: Node<readonly T[]>,\n\tdataset: Node<readonly DatasetItem[]>,\n) => Node<readonly EvalResult[]>;\n\n// ---------------------------------------------------------------------------\n// Convergence\n// ---------------------------------------------------------------------------\n\n/**\n * Early-stop controls. Each field fans into its own derived node; the four\n * combine via `||` into `converged: Node<boolean>`. Callers see exactly\n * which rule tripped via `status` / the DECIDE topic's `reason`.\n */\nexport interface ConvergenceOptions {\n\t/** Stop when aggregate score has not improved for N iterations. */\n\tpatience?: number;\n\t/** Stop when aggregate score reaches or exceeds this. */\n\tminScore?: number;\n\t/** Stop when absolute delta between consecutive scores falls below this. */\n\tminDelta?: number;\n\t/** Stop after N total evaluations (iteration count × per-iter candidates). */\n\tmaxEvaluations?: number;\n\t/** Stop after N iterations. Always set a finite bound in production. */\n\tmaxIterations?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Topic payloads (one per stage)\n// ---------------------------------------------------------------------------\n\n/** Emitted to the GENERATE topic each time the strategy produces a batch. */\nexport interface GenerateEvent<T> {\n\treadonly iteration: number;\n\treadonly candidates: readonly T[];\n\treadonly timestamp_ns: number;\n}\n\n/** Emitted to the EVALUATE topic when scores settle for an iteration. */\nexport interface EvaluateEvent<T> {\n\treadonly iteration: number;\n\treadonly candidates: readonly T[];\n\treadonly scores: readonly EvalResult[];\n\treadonly timestamp_ns: number;\n}\n\n/** Emitted to the ANALYZE topic — strategy's reduction over scores. */\nexport interface AnalyzeEvent<T> {\n\treadonly iteration: number;\n\treadonly candidates: readonly T[];\n\treadonly feedback: Feedback;\n\treadonly timestamp_ns: number;\n}\n\n/** Emitted to the DECIDE topic — branch taken this iteration. */\nexport interface DecideEvent {\n\treadonly iteration: number;\n\treadonly decision: \"continue\" | \"converged\" | \"budget\" | \"paused\";\n\treadonly reason?: string;\n\treadonly timestamp_ns: number;\n}\n\n// ---------------------------------------------------------------------------\n// Status + history\n// ---------------------------------------------------------------------------\n\nexport type RefineStatus = \"running\" | \"converged\" | \"budget\" | \"paused\" | \"errored\";\n\n/**\n * **Internal envelope** — carries the iteration number alongside the\n * candidates batch so `iter` rides the data wave through the pipeline. Lets\n * downstream stages read iter from a real reactive edge instead of from\n * `iterationTrigger.cache` (P3 violation; see /qa D1, 2026-05-01).\n *\n * Sidecar `candidatesItemsNode = derived([candidatesNode], ([env]) => env.items)`\n * preserves the user-facing `Evaluator<T>` API (which sees `Node<readonly T[]>`).\n */\ninterface CandidatesEnvelope<T> {\n\treadonly iter: number;\n\treadonly items: readonly T[];\n}\n\n/**\n * **Internal envelope** — assembled by `feedbackEnvelopeNode` from\n * `userScoresNode` + `candidatesNode`. Carries iter + items + scores +\n * feedback together as the trigger payload for `decideEffect` (`§16` nested\n * `withLatestFrom` advisory-samples history / budget / pause). Lets\n * `decideEffect` read iter from the envelope (no `iterationTrigger.cache` read)\n * AND ensures decideEffect only fires when the user evaluator has actually\n * emitted fresh scores (gate via `batchData[scores]` length, eliminating\n * spurious decides on candidates-only fan-out waves).\n */\ninterface FeedbackEnvelope<T> {\n\treadonly iter: number;\n\treadonly items: readonly T[];\n\treadonly scores: readonly EvalResult[];\n\treadonly feedback: Feedback;\n}\n\nexport interface Iteration<T> {\n\treadonly n: number;\n\treadonly candidates: readonly T[];\n\treadonly scores: readonly EvalResult[];\n\treadonly feedback: Feedback;\n\t/** `null` iff the candidate batch for this iteration was empty. */\n\treadonly best: T | null;\n\treadonly bestScore: number;\n\treadonly timestamp_ns: number;\n}\n\n// ---------------------------------------------------------------------------\n// Factory + returned graph\n// ---------------------------------------------------------------------------\n\nexport interface RefineLoopOptions extends ConvergenceOptions {\n\t/** Reactive dataset OR a plain array (auto-wrapped into `state`). */\n\tdataset: NodeInput<readonly DatasetItem[]> | readonly DatasetItem[];\n\t/** Total teacher calls cap across iterations. Default: unlimited. */\n\tbudget?: number;\n\t/** Graph name. Default: `\"refine-loop\"`. */\n\tname?: string;\n\t/** Extra graph options forwarded to the underlying `Graph`. */\n\tgraph?: GraphOptions;\n}\n\n/**\n * `class RefineLoopGraph<T> extends Graph` — the universal prompt/artifact\n * optimization loop as a reactive Graph subclass.\n *\n * Constructed via the {@link refineLoop} factory in normal use; exported as a\n * class so consumers can `instanceof`-narrow on returned values (Phase 13.G\n * `agent(spec)` is the consumer that motivated the migration). All\n * observability tools (`describe`, `explain`, `observe`, `attachSnapshotStorage`,\n * `snapshot`) Just Work since this `extends Graph`.\n *\n * **Phase 12.D (2026-04-30):** Migrated from `Object.assign(graph, ...)` factory\n * pattern to `class extends Graph` (Tier R5.1 deferral lifted; mirrors the\n * `MemoryWith*Graph` precedent). `setStrategy` / `pause` / `resume` are now\n * instance methods that read `this.strategy` / `this._pauseState` / `this.status`\n * / `this._iteration` instead of factory-local closures.\n */\nexport class RefineLoopGraph<T> extends Graph {\n\treadonly best: Node<T | null>;\n\t/**\n\t * Best score so far. Pseudo-private (`_score`) to avoid colliding with any\n\t * future `Graph.prototype.score` method (B5d forward-compat hazard\n\t * prevention). Typed-public — read via `loop._score.cache` /\n\t * `loop._score.subscribe(...)` from external code.\n\t */\n\treadonly _score: Node<number>;\n\treadonly status: Node<RefineStatus>;\n\treadonly history: Node<readonly Iteration<T>[]>;\n\treadonly strategy: Node<RefineStrategy<T>>;\n\t/**\n\t * Monotonic iteration counter. Pseudo-private (`_iteration`) to avoid\n\t * colliding with any future `Graph.prototype.iteration` method (B5d\n\t * forward-compat hazard prevention). Typed-public — read via\n\t * `loop._iteration.cache` / `loop._iteration.subscribe(...)`.\n\t */\n\treadonly _iteration: Node<number>;\n\t/** Stage topic — subscribe for per-stage streaming / cursor consumers. */\n\treadonly generate: TopicGraph<GenerateEvent<T>>;\n\t/** Stage topic — subscribe for per-stage streaming / cursor consumers. */\n\treadonly evaluate: TopicGraph<EvaluateEvent<T>>;\n\t/** Stage topic — subscribe for per-stage streaming / cursor consumers. */\n\treadonly analyze: TopicGraph<AnalyzeEvent<T>>;\n\t/** Stage topic — subscribe for per-stage streaming / cursor consumers. */\n\treadonly decide: TopicGraph<DecideEvent>;\n\n\t/** Internal: paused-flag node. Mounted as \"paused\" in describe(). */\n\tprivate readonly _pauseState: Node<boolean>;\n\n\tconstructor(\n\t\tseed: T,\n\t\tevaluator: Evaluator<T>,\n\t\tinitialStrategy: RefineStrategy<T>,\n\t\topts: RefineLoopOptions,\n\t) {\n\t\tconst name = opts.name ?? \"refine-loop\";\n\t\tsuper(name, opts.graph);\n\n\t\t// /qa A2 (2026-04-30): tag the Graph with its constructing factory so\n\t\t// `describe()` / `compileSpec` round-trip surfaces provenance — mirrors\n\t\t// the `agentMemory` pattern. `seed` / `evaluator` / `initialStrategy`\n\t\t// and option fields are non-JSON (functions, strategies); route through\n\t\t// `placeholderArgs` (DG2=ii) which substitutes `\"<function>\"` /\n\t\t// `\"<Node>\"` / `\"<unserializable>\"` for non-JSON values.\n\t\tthis.tagFactory(\n\t\t\t\"refineLoop\",\n\t\t\tplaceholderArgs({ seed, evaluator, initialStrategy, ...opts } as unknown as Record<\n\t\t\t\tstring,\n\t\t\t\tunknown\n\t\t\t>),\n\t\t);\n\n\t\t// --- Dataset: auto-wrap arrays into a state node ------------------------\n\t\tconst datasetNode: Node<readonly DatasetItem[]> = isNode<readonly DatasetItem[]>(opts.dataset)\n\t\t\t? opts.dataset\n\t\t\t: createNode<readonly DatasetItem[]>([], {\n\t\t\t\t\tname: \"dataset\",\n\t\t\t\t\tinitial: opts.dataset as readonly DatasetItem[],\n\t\t\t\t});\n\t\tthis.add(datasetNode, { name: \"dataset\" });\n\n\t\t// --- State nodes --------------------------------------------------------\n\t\tconst iterationTrigger = createNode<number>([], { name: \"iteration\", initial: 0 });\n\t\tthis.add(iterationTrigger, { name: \"iteration\" });\n\n\t\tconst strategyNode = createNode<RefineStrategy<T>>([], {\n\t\t\tname: \"strategy\",\n\t\t\tinitial: initialStrategy,\n\t\t\tequals: () => false, // always propagate strategy swaps\n\t\t});\n\t\tthis.add(strategyNode, { name: \"strategy\" });\n\n\t\tconst lastFeedbackState = createNode<Feedback | null>([], {\n\t\t\tname: \"lastFeedback\",\n\t\t\tinitial: null,\n\t\t});\n\t\tthis.add(lastFeedbackState, { name: \"lastFeedback\" });\n\n\t\tconst prevCandidatesState = createNode<readonly T[]>([], {\n\t\t\tname: \"prevCandidates\",\n\t\t\tinitial: [],\n\t\t});\n\t\tthis.add(prevCandidatesState, { name: \"prevCandidates\" });\n\n\t\tconst pauseState = createNode<boolean>([], { name: \"paused\", initial: false });\n\t\tthis.add(pauseState, { name: \"paused\" });\n\n\t\tconst statusState = createNode<RefineStatus>([], { name: \"status\", initial: \"running\" });\n\t\tthis.add(statusState, { name: \"status\" });\n\n\t\tconst historyState = createNode<readonly Iteration<T>[]>([], {\n\t\t\tname: \"history\",\n\t\t\tinitial: [],\n\t\t\tequals: () => false, // append-style; reactive consumers want every push\n\t\t});\n\t\tthis.add(historyState, { name: \"history\" });\n\n\t\tconst bestState = createNode<T | null>([], { name: \"best\", initial: null });\n\t\tthis.add(bestState, { name: \"best\" });\n\n\t\tconst scoreState = createNode<number>([], { name: \"score\", initial: Number.NEGATIVE_INFINITY });\n\t\tthis.add(scoreState, { name: \"score\" });\n\n\t\t// --- Budget counter -----------------------------------------------------\n\t\tconst budgetState = createNode<number>([], { name: \"budget-used\", initial: 0 });\n\t\tthis.add(budgetState, { name: \"budget-used\" });\n\n\t\t// --- Stage hub (Shape B + C-aspects) ------------------------------------\n\t\t// One messagingHub instead of four standalone TopicGraphs. Topics are\n\t\t// eagerly created so the public accessors (loop.generate etc.) are\n\t\t// available immediately without waiting for the first event to fire.\n\t\t// The hub is mounted in this so all stage topics appear under \"stages::\"\n\t\t// in describe()/explain() — visible edges, not closure-held singletons.\n\t\tconst hub = messagingHub(\"stages\");\n\t\tthis.mount(\"stages\", hub);\n\t\tconst hubGenerateTopic = hub.topic<GenerateEvent<T>>(\"generate\");\n\t\tconst hubEvaluateTopic = hub.topic<EvaluateEvent<T>>(\"evaluate\");\n\t\tconst hubAnalyzeTopic = hub.topic<AnalyzeEvent<T>>(\"analyze\");\n\t\tconst hubDecideTopic = hub.topic<DecideEvent>(\"decide\");\n\n\t\t// /qa A1 (2026-04-30): assign the public field surface BEFORE wiring\n\t\t// any effect / subscribe activation below. A synchronous strategy can\n\t\t// drain the entire GENERATE → EVALUATE → ANALYZE → DECIDE cascade\n\t\t// during the constructor body (see strategy doc above); fields must be\n\t\t// reachable in case any future subscribe handler dereferences `this.X`\n\t\t// during that synchronous drain. Defensive — no current handler reads\n\t\t// `this.<field>`, but keeping construction-order safe avoids future\n\t\t// undefined-field crashes.\n\t\tthis.best = bestState as Node<T | null>;\n\t\tthis._score = scoreState;\n\t\tthis.status = statusState;\n\t\tthis.history = historyState;\n\t\tthis.strategy = strategyNode;\n\t\tthis._iteration = iterationTrigger;\n\t\tthis.generate = hubGenerateTopic;\n\t\tthis.evaluate = hubEvaluateTopic;\n\t\tthis.analyze = hubAnalyzeTopic;\n\t\tthis.decide = hubDecideTopic;\n\t\tthis._pauseState = pauseState;\n\n\t\t// --- Factory-time seed closures (§28) -----------------------------------\n\t\t// These mirror the reactive dep values so the generate fn can read them\n\t\t// without the multi-dep push-on-subscribe initial-pair drop. Per\n\t\t// COMPOSITION-GUIDE-PROTOCOL.md §28: \"The closure reads inside the\n\t\t// reactive fn are NOT P3 violations — they read a closure variable,\n\t\t// not a `.cache`.\" Subscribe handlers run synchronously on dep DATA,\n\t\t// so the closure mirrors are always current by the time the generate\n\t\t// fn fires for the next iter.\n\t\tlet latestStrategy: RefineStrategy<T> = initialStrategy;\n\t\tlet latestFeedback: Feedback | null = null;\n\t\tlet latestPrevCandidates: readonly T[] = [];\n\t\tthis.addDisposer(\n\t\t\tstrategyNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) if (m[0] === DATA) latestStrategy = m[1] as RefineStrategy<T>;\n\t\t\t}),\n\t\t);\n\t\tthis.addDisposer(\n\t\t\tlastFeedbackState.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) if (m[0] === DATA) latestFeedback = m[1] as Feedback | null;\n\t\t\t}),\n\t\t);\n\t\tthis.addDisposer(\n\t\t\tprevCandidatesState.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) if (m[0] === DATA) latestPrevCandidates = m[1] as readonly T[];\n\t\t\t}),\n\t\t);\n\n\t\t// --- GENERATE: iterationTrigger → candidates ----------------------------\n\t\t// switchMap cancels any in-flight generate when a new iteration fires.\n\t\t// At iteration 0, strategy.seed(seed). At iteration > 0, strategy.generate.\n\t\t//\n\t\t// Sync strategies emit in the same wave as `iterationTrigger` — no microtask\n\t\t// bridge. This eliminates the per-topic iteration race (Edge #5): all four\n\t\t// stage effects drain under one wave, so iteration numbers across\n\t\t// GENERATE / EVALUATE / ANALYZE / DECIDE are guaranteed identical.\n\t\t//\n\t\t// Async strategies still cross a Promise boundary — that's the strategy's\n\t\t// async-source contract (spec §5.10: async boundaries belong in sources).\n\t\t// Cancellation on strategy swap / pause / new iteration uses switchMap's\n\t\t// inner-node unsubscribe + a `cancelled` flag so late Promise resolutions\n\t\t// don't emit into a torn-down switchMap slot.\n\t\t//\n\t\t// **/qa D1 (2026-05-01) — envelope shape:** the inner producer emits\n\t\t// `{iter, items}` so `iter` rides the data wave through every downstream\n\t\t// stage. Eliminates the cross-node `iterationTrigger.cache` P3 violation\n\t\t// in `decideEffect` (and the resume-stall failure mode it caused). User-\n\t\t// facing evaluator API stays `Node<readonly T[]>` via the\n\t\t// `candidatesItemsNode` sidecar derived below.\n\t\tconst candidatesNode = switchMap<number, CandidatesEnvelope<T>>(\n\t\t\titerationTrigger,\n\t\t\t(iter) => {\n\t\t\t\tconst strat = latestStrategy;\n\t\t\t\tconst isSeed = iter === 0 || latestFeedback == null;\n\t\t\t\treturn createNode<CandidatesEnvelope<T>>(\n\t\t\t\t\t[],\n\t\t\t\t\t(_data, actions) => {\n\t\t\t\t\t\tlet cancelled = false;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = isSeed\n\t\t\t\t\t\t\t\t? strat.seed(seed)\n\t\t\t\t\t\t\t\t: strat.generate(latestFeedback as Feedback, latestPrevCandidates);\n\t\t\t\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\t\t\t\tresult.then(\n\t\t\t\t\t\t\t\t\t(v) => {\n\t\t\t\t\t\t\t\t\t\tif (!cancelled) actions.emit({ iter, items: v });\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t(err) => {\n\t\t\t\t\t\t\t\t\t\tif (!cancelled) actions.down([[ERROR, err]]);\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\treturn {\n\t\t\t\t\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\t\t\t\t\tcancelled = true;\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\tactions.emit({ iter, items: result });\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tcancelled = true;\n\t\t\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t},\n\t\t\t\t\t{ describeKind: \"producer\" },\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ name: \"candidates\" },\n\t\t);\n\t\tthis.add(candidatesNode, { name: \"candidates\" });\n\n\t\t// User-facing items sidecar: preserves the `Evaluator<T>` API\n\t\t// (`(candidates: Node<readonly T[]>, dataset: Node<readonly DatasetItem[]>) => ...`)\n\t\t// while the internal pipeline reads iter from the envelope.\n\t\tconst candidatesItemsNode = createNode<readonly T[]>(\n\t\t\t[candidatesNode],\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 env = data[0] as CandidatesEnvelope<T> | undefined;\n\t\t\t\tif (env === undefined) {\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(env.items);\n\t\t\t},\n\t\t\t{ name: \"candidates-items\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(candidatesItemsNode, { name: \"candidates-items\" });\n\n\t\t// Error watcher — strategy throws surface as ERROR on `candidatesNode`.\n\t\t// Promote to `status = \"errored\"` so callers don't have to subscribe to\n\t\t// the error channel directly.\n\t\tconst errorWatcher = createNode(\n\t\t\t[candidatesNode],\n\t\t\t(_batchData, _actions, ctx) => {\n\t\t\t\tconst terminal = ctx.terminalDeps[0];\n\t\t\t\tif (terminal !== undefined && terminal !== true) {\n\t\t\t\t\tstatusState.emit(\"errored\");\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ name: \"error-watcher\", describeKind: \"effect\", errorWhenDepsError: false },\n\t\t);\n\t\tthis.add(errorWatcher, { name: \"error-watcher\" });\n\t\tthis.addDisposer(errorWatcher.subscribe(() => undefined));\n\n\t\t// GENERATE stage: three nodes replace one monolithic effect.\n\t\t// (1) derived computes the event payload — reactive edge visible in explain().\n\t\t// (2) publish effect routes the derived event to the hub topic.\n\t\t// (3) mirror effect keeps prevCandidatesState in sync for §28 closure reads.\n\t\t// Budget accounting stays in decideEffect (single authority).\n\t\t// /qa D1: iter + items both come from the candidates envelope — no\n\t\t// separate `iterationTrigger` dep, no cross-node cache reads.\n\t\tconst generateEventNode = createNode<GenerateEvent<T>>(\n\t\t\t[candidatesNode],\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 env = data[0] as CandidatesEnvelope<T>;\n\t\t\t\tactions.emit({\n\t\t\t\t\titeration: env.iter,\n\t\t\t\t\tcandidates: env.items,\n\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"generate-event\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(generateEventNode, { name: \"generate-event\" });\n\t\tthis.addDisposer(generateEventNode.subscribe(() => undefined));\n\n\t\tconst generatePublishEffect = createNode(\n\t\t\t[generateEventNode],\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\thubGenerateTopic.publish(data[0] as GenerateEvent<T>);\n\t\t\t},\n\t\t\t{ name: \"generate-publish\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(generatePublishEffect, { name: \"generate-publish\" });\n\t\tthis.addDisposer(generatePublishEffect.subscribe(() => undefined));\n\n\t\tconst generateMirrorEffect = createNode(\n\t\t\t[candidatesNode],\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 env = data[0] as CandidatesEnvelope<T>;\n\t\t\t\tprevCandidatesState.emit(env.items);\n\t\t\t},\n\t\t\t{ name: \"generate-mirror\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(generateMirrorEffect, { name: \"generate-mirror\" });\n\t\tthis.addDisposer(generateMirrorEffect.subscribe(() => undefined));\n\n\t\t// --- EVALUATE: candidates × dataset → scores ----------------------------\n\t\t// User evaluator sees the items sidecar (preserves `Evaluator<T>` API).\n\t\tconst scoresNode = evaluator(candidatesItemsNode, datasetNode);\n\t\tthis.add(scoresNode, { name: \"scores\" });\n\n\t\t// EVALUATE stage: derived event node + publish effect.\n\t\t// /qa D1: iter from candidates envelope; gate on `scoresFired` so a\n\t\t// candidates-only fan-out wave (e.g. async eval still in flight) does\n\t\t// NOT publish a stale evaluate event.\n\t\tconst evaluateEventNode = createNode<EvaluateEvent<T>>(\n\t\t\t[scoresNode, candidatesNode],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst scoresFired = batchData[0] != null && batchData[0].length > 0;\n\t\t\t\tif (!scoresFired) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\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 scores = data[0] as readonly EvalResult[];\n\t\t\t\tconst env = data[1] as CandidatesEnvelope<T>;\n\t\t\t\tactions.emit({\n\t\t\t\t\titeration: env.iter,\n\t\t\t\t\tcandidates: env.items,\n\t\t\t\t\tscores,\n\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"evaluate-event\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(evaluateEventNode, { name: \"evaluate-event\" });\n\t\tthis.addDisposer(evaluateEventNode.subscribe(() => undefined));\n\n\t\tconst evaluatePublishEffect = createNode(\n\t\t\t[evaluateEventNode],\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\thubEvaluateTopic.publish(data[0] as EvaluateEvent<T>);\n\t\t\t},\n\t\t\t{ name: \"evaluate-publish\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(evaluatePublishEffect, { name: \"evaluate-publish\" });\n\t\tthis.addDisposer(evaluatePublishEffect.subscribe(() => undefined));\n\n\t\t// --- ANALYZE: strategy.analyze(scores, candidates) → feedbackEnvelope ---\n\t\t// /qa D1: feedbackEnvelope is the canonical iter-tagged trigger payload\n\t\t// for the DECIDE stage. Gates on `scoresFired` so a candidates-only\n\t\t// wave (async eval not settled yet) does NOT emit stale feedback into\n\t\t// `decideEffect`. When the user evaluator emits, both deps' caches are\n\t\t// consistent (candidates envelope carries iter that matches the scores\n\t\t// the user just produced — *assuming the user evaluator cancels async\n\t\t// work on candidates change; see Evaluator<T> JSDoc contract*).\n\t\tconst feedbackEnvelopeNode = createNode<FeedbackEnvelope<T>>(\n\t\t\t[scoresNode, candidatesNode],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst scoresFired = batchData[0] != null && batchData[0].length > 0;\n\t\t\t\tif (!scoresFired) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\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 scores = data[0] as readonly EvalResult[];\n\t\t\t\tconst env = data[1] as CandidatesEnvelope<T>;\n\t\t\t\tactions.emit({\n\t\t\t\t\titer: env.iter,\n\t\t\t\t\titems: env.items,\n\t\t\t\t\tscores,\n\t\t\t\t\tfeedback: latestStrategy.analyze(scores, env.items),\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"feedback-envelope\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(feedbackEnvelopeNode, { name: \"feedback-envelope\" });\n\n\t\t// User-facing feedback projection sidecar — preserves `feedback` path\n\t\t// for observers that consume the bare `Feedback` shape via\n\t\t// `loop.observe(\"feedback\")` etc.\n\t\tconst feedbackNode = createNode<Feedback>(\n\t\t\t[feedbackEnvelopeNode],\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 fbEnv = data[0] as FeedbackEnvelope<T>;\n\t\t\t\tactions.emit(fbEnv.feedback);\n\t\t\t},\n\t\t\t{ name: \"feedback\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(feedbackNode, { name: \"feedback\" });\n\n\t\t// ANALYZE stage: derived event node + publish effect.\n\t\t// /qa D1: pull iter + items from feedbackEnvelopeNode (single source of\n\t\t// truth for the analyze beat). No cross-node cache reads.\n\t\tconst analyzeEventNode = createNode<AnalyzeEvent<T>>(\n\t\t\t[feedbackEnvelopeNode],\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 fbEnv = data[0] as FeedbackEnvelope<T>;\n\t\t\t\tactions.emit({\n\t\t\t\t\titeration: fbEnv.iter,\n\t\t\t\t\tcandidates: fbEnv.items,\n\t\t\t\t\tfeedback: fbEnv.feedback,\n\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ name: \"analyze-event\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(analyzeEventNode, { name: \"analyze-event\" });\n\t\tthis.addDisposer(analyzeEventNode.subscribe(() => undefined));\n\n\t\tconst analyzePublishEffect = createNode(\n\t\t\t[analyzeEventNode],\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\thubAnalyzeTopic.publish(data[0] as AnalyzeEvent<T>);\n\t\t\t},\n\t\t\t{ name: \"analyze-publish\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(analyzePublishEffect, { name: \"analyze-publish\" });\n\t\tthis.addDisposer(analyzePublishEffect.subscribe(() => undefined));\n\n\t\t// --- Convergence: four derived nodes fanning into one boolean -----------\n\t\tconst patienceNode = createNode<boolean>(\n\t\t\t[historyState],\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 h = data[0] as readonly Iteration<T>[];\n\t\t\t\tif (opts.patience == null || h.length <= opts.patience) {\n\t\t\t\t\tactions.emit(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// No improvement over the last `patience` iterations.\n\t\t\t\tconst lookback = h.slice(-(opts.patience + 1));\n\t\t\t\tconst baseline = lookback[0]!.bestScore;\n\t\t\t\tactions.emit(lookback.slice(1).every((i) => i.bestScore <= baseline));\n\t\t\t},\n\t\t\t{ name: \"patience-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(patienceNode, { name: \"patience-check\" });\n\n\t\tconst minScoreNode = createNode<boolean>(\n\t\t\t[scoreState],\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(opts.minScore != null && (data[0] as number) >= opts.minScore);\n\t\t\t},\n\t\t\t{ name: \"min-score-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(minScoreNode, { name: \"min-score-check\" });\n\n\t\tconst minDeltaNode = createNode<boolean>(\n\t\t\t[historyState],\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 h = data[0] as readonly Iteration<T>[];\n\t\t\t\tif (opts.minDelta == null || h.length < 2) {\n\t\t\t\t\tactions.emit(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst prev = h[h.length - 2]!.bestScore;\n\t\t\t\tconst curr = h[h.length - 1]!.bestScore;\n\t\t\t\tactions.emit(Math.abs(curr - prev) < opts.minDelta);\n\t\t\t},\n\t\t\t{ name: \"min-delta-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(minDeltaNode, { name: \"min-delta-check\" });\n\n\t\tconst maxEvalsNode = createNode<boolean>(\n\t\t\t[budgetState],\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(opts.maxEvaluations != null && (data[0] as number) >= opts.maxEvaluations);\n\t\t\t},\n\t\t\t{ name: \"max-evaluations-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(maxEvalsNode, { name: \"max-evaluations-check\" });\n\n\t\tconst maxIterNode = createNode<boolean>(\n\t\t\t[iterationTrigger],\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(opts.maxIterations != null && (data[0] as number) >= opts.maxIterations);\n\t\t\t},\n\t\t\t{ name: \"max-iterations-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(maxIterNode, { name: \"max-iterations-check\" });\n\n\t\tconst budgetExhaustedNode = createNode<boolean>(\n\t\t\t[budgetState],\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(opts.budget != null && (data[0] as number) >= opts.budget);\n\t\t\t},\n\t\t\t{ name: \"budget-exhausted-check\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(budgetExhaustedNode, { name: \"budget-exhausted-check\" });\n\n\t\t// Activate convergence derivations so their cache stays current — decideEffect\n\t\t// reads their cache via external-boundary reads (§28). They must NOT be direct\n\t\t// deps: that would create a feedback cycle (decideEffect writes history/score,\n\t\t// convergence derives from those, cycle).\n\t\tthis.addDisposer(patienceNode.subscribe(() => undefined));\n\t\tthis.addDisposer(minScoreNode.subscribe(() => undefined));\n\t\tthis.addDisposer(minDeltaNode.subscribe(() => undefined));\n\t\tthis.addDisposer(maxEvalsNode.subscribe(() => undefined));\n\t\tthis.addDisposer(maxIterNode.subscribe(() => undefined));\n\t\tthis.addDisposer(budgetExhaustedNode.subscribe(() => undefined));\n\n\t\tconst convergedNode = createNode<{ converged: boolean; reason?: string }>(\n\t\t\t[patienceNode, minScoreNode, minDeltaNode, maxEvalsNode, maxIterNode],\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 [p, ms, md, me, mi] = data;\n\t\t\t\tif (p) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"patience\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (ms) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"min-score\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (md) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"min-delta\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (me) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"max-evaluations\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (mi) {\n\t\t\t\t\tactions.emit({ converged: true, reason: \"max-iterations\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tactions.emit({ converged: false });\n\t\t\t},\n\t\t\t{ name: \"converged\", describeKind: \"derived\" },\n\t\t);\n\t\tthis.add(convergedNode, { name: \"converged\" });\n\t\tthis.addDisposer(convergedNode.subscribe(() => undefined));\n\n\t\t// --- DECIDE: feedbackEnvelope settles → fire next iteration OR terminate ---\n\t\t// **/qa D1 (2026-05-01) — reactive form via §32 envelope + sole-owner\n\t\t// `.cache` reads + reactive `pauseState` dep.** Two patterns at play:\n\t\t//\n\t\t// - **`iter` rides with the feedbackEnvelope payload** (§32 envelope).\n\t\t// Eliminates the original `iterationTrigger.cache` cross-node read\n\t\t// that caused the resume-stall (where iter.cache was bumped past\n\t\t// the candidates batch we're processing).\n\t\t//\n\t\t// - **`historyState` / `budgetState` are read via `.cache`** as a\n\t\t// sole-owner pattern: decideEffect is the SOLE WRITER + sole\n\t\t// reactive READER, both declared in the same enclosing constructor\n\t\t// scope. Reading their `.cache` here is \"read your own scratchpad\"\n\t\t// semantically, even though they're sibling Node objects. Adding\n\t\t// them as direct deps would create the §7 self-feedback cycle\n\t\t// (decideEffect writes them, would re-trigger itself); closure\n\t\t// mirrors would just duplicate state already held in the nodes\n\t\t// themselves. The comment block belongs to /qa D1 follow-up\n\t\t// (2026-05-01) — explicit user lock that sole-owner-and-reader\n\t\t// nodes in the same enclosing scope are a sanctioned `.cache` read\n\t\t// form.\n\t\t//\n\t\t// - **`pauseState` is a direct dep** because it's an EXTERNAL CONTROL\n\t\t// INPUT — written by `pause()` / `resume()` imperative methods at\n\t\t// the user-call boundary, NOT by decideEffect. Making it a real\n\t\t// declared edge surfaces \"this decision considers pause state\" in\n\t\t// `describe()` / `explain()` topology. The `feedbackFired` gate\n\t\t// below skips fn body execution when only pauseState fired (no new\n\t\t// iteration to decide).\n\t\t//\n\t\t// Trigger semantics: feedbackEnvelopeNode itself only fires when the\n\t\t// user evaluator emits fresh scores (gate via `batchData[scoresIdx]`\n\t\t// in feedbackEnvelopeNode), so a candidates-only fan-out wave (async\n\t\t// eval still in flight after `resume()`) does NOT spuriously trigger\n\t\t// decideEffect.\n\t\t//\n\t\t// **Score-staleness contract:** if the user's `Evaluator<T>` does NOT\n\t\t// cancel its async work when `candidates` changes, late scores from a\n\t\t// prior iter can emit to scoresNode and trip feedbackEnvelopeNode +\n\t\t// decideEffect with the new candidates' iter tag but stale scores\n\t\t// data. See `Evaluator<T>` JSDoc (cancel-on-input contract) and\n\t\t// `optimizations.md` \"refineLoop async-evaluator stale-scores\n\t\t// follow-up\" for the wrapper proposal.\n\t\t//\n\t\t// Track last-decided iteration to avoid re-deciding when feedbackEnv\n\t\t// re-fires within one wave (e.g. async evaluator emits multiple\n\t\t// scores per candidates change).\n\t\tlet lastDecidedIteration = -1;\n\t\tconst decideEffect = createNode(\n\t\t\t[feedbackEnvelopeNode, pauseState],\n\t\t\t(batchData, _actions, ctx) => {\n\t\t\t\t// `pauseState` is declared dep #1 — gate skips fn body when\n\t\t\t\t// only pauseState fired (no new iteration to decide; we just\n\t\t\t\t// want pauseState's prevData to advance for the next feedback\n\t\t\t\t// fire).\n\t\t\t\tconst feedbackFired = batchData[0] != null && batchData[0].length > 0;\n\t\t\t\tif (!feedbackFired) return;\n\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 fbEnv = data[0] as FeedbackEnvelope<T>;\n\t\t\t\tconst paused = data[1] as boolean;\n\n\t\t\t\tconst i = fbEnv.iter;\n\t\t\t\tconst fb = fbEnv.feedback;\n\t\t\t\tconst cs = fbEnv.items;\n\t\t\t\tconst scores = fbEnv.scores;\n\n\t\t\t\t// De-dup: only run once per iteration. fn may fire multiple\n\t\t\t\t// times per wave as feedbackEnvelopeNode settles.\n\t\t\t\tif (i <= lastDecidedIteration) return;\n\t\t\t\tlastDecidedIteration = i;\n\n\t\t\t\t// Sole-owner `.cache` reads — decideEffect is the SOLE\n\t\t\t\t// writer and sole reactive reader of these state nodes.\n\t\t\t\tconst currentHistory = historyState.cache as readonly Iteration<T>[];\n\t\t\t\tconst currentBudget = budgetState.cache as number;\n\n\t\t\t\t// Compute next history / score.\n\t\t\t\tconst { best, bestScore } = pickBest(cs, scores);\n\t\t\t\tconst iteration: Iteration<T> = {\n\t\t\t\t\tn: i,\n\t\t\t\t\tcandidates: cs,\n\t\t\t\t\tscores,\n\t\t\t\t\tfeedback: fb,\n\t\t\t\t\tbest,\n\t\t\t\t\tbestScore,\n\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t};\n\t\t\t\tconst nextHistory = [...currentHistory, iteration];\n\t\t\t\t// Budget accounting — decideEffect is the single authority.\n\t\t\t\tconst nextBudget = currentBudget + cs.length;\n\n\t\t\t\t// Inline convergence checks — single source of truth. The derived\n\t\t\t\t// `convergedNode` + friends exist for describe()/observe() surface;\n\t\t\t\t// inlining here avoids a drain-round-trip deadlock where decideEffect\n\t\t\t\t// would need convergedNode.cache to update before running, but\n\t\t\t\t// convergedNode needs historyState.emit from inside decideEffect.\n\t\t\t\tlet decision: DecideEvent[\"decision\"] = \"continue\";\n\t\t\t\tlet reason: string | undefined;\n\t\t\t\tconst budgetOut = opts.budget != null && nextBudget >= opts.budget;\n\t\t\t\tif (budgetOut) {\n\t\t\t\t\tdecision = \"budget\";\n\t\t\t\t\treason = \"budget\";\n\t\t\t\t} else if (opts.minScore != null && fb.score >= opts.minScore) {\n\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\treason = \"min-score\";\n\t\t\t\t} else if (opts.maxIterations != null && i >= opts.maxIterations) {\n\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\treason = \"max-iterations\";\n\t\t\t\t} else if (opts.maxEvaluations != null && nextBudget >= opts.maxEvaluations) {\n\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\treason = \"max-evaluations\";\n\t\t\t\t} else if (opts.minDelta != null && nextHistory.length >= 2) {\n\t\t\t\t\tconst prev = nextHistory[nextHistory.length - 2]!.bestScore;\n\t\t\t\t\tconst curr = nextHistory[nextHistory.length - 1]!.bestScore;\n\t\t\t\t\tif (Math.abs(curr - prev) < opts.minDelta) {\n\t\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\t\treason = \"min-delta\";\n\t\t\t\t\t}\n\t\t\t\t} else if (opts.patience != null && nextHistory.length > opts.patience) {\n\t\t\t\t\tconst lookback = nextHistory.slice(-(opts.patience + 1));\n\t\t\t\t\tconst baseline = lookback[0]!.bestScore;\n\t\t\t\t\tif (lookback.slice(1).every((it) => it.bestScore <= baseline)) {\n\t\t\t\t\t\tdecision = \"converged\";\n\t\t\t\t\t\treason = \"patience\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// paused takes precedence over continue — if paused AND no convergence,\n\t\t\t\t// we pause. Otherwise if converged we stop for real.\n\t\t\t\tif (decision === \"continue\" && paused) {\n\t\t\t\t\tdecision = \"paused\";\n\t\t\t\t}\n\n\t\t\t\t// All emissions in one batch — drain order is feedback mirror first\n\t\t\t\t// (§32), then iterationTrigger, so the next generate sees fresh fb.\n\t\t\t\t// `lastFeedbackState` is always mirrored (regardless of decision) so\n\t\t\t\t// resume-after-pause gets current feedback; only `iterationTrigger`\n\t\t\t\t// is gated on `continue`.\n\t\t\t\tbatch(() => {\n\t\t\t\t\tbestState.emit(best);\n\t\t\t\t\tscoreState.emit(fb.score);\n\t\t\t\t\thistoryState.emit(nextHistory);\n\t\t\t\t\tbudgetState.emit(nextBudget);\n\t\t\t\t\tlastFeedbackState.emit(fb);\n\t\t\t\t\thubDecideTopic.publish({\n\t\t\t\t\t\titeration: i,\n\t\t\t\t\t\tdecision,\n\t\t\t\t\t\treason,\n\t\t\t\t\t\ttimestamp_ns: monotonicNs(),\n\t\t\t\t\t});\n\n\t\t\t\t\tif (decision === \"continue\") {\n\t\t\t\t\t\titerationTrigger.emit(i + 1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstatusState.emit(\n\t\t\t\t\t\t\tdecision === \"converged\" ? \"converged\" : decision === \"budget\" ? \"budget\" : \"paused\",\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: \"decide-bridge\", describeKind: \"effect\" },\n\t\t);\n\t\tthis.add(decideEffect, { name: \"decide-bridge\" });\n\t\tthis.addDisposer(decideEffect.subscribe(() => undefined));\n\n\t\t// /qa A1 (2026-04-30): public field surface (best / score / status /\n\t\t// history / strategy / iteration / generate / evaluate / analyze /\n\t\t// decide / _pauseState) is assigned EARLIER, immediately after the\n\t\t// stage hub is mounted (search \"qa A1\" above). Doing the assignment\n\t\t// before any subscribe activation keeps `this.<field>` reachable\n\t\t// during a synchronous strategy drain.\n\t}\n\n\t/** Swap the active strategy mid-run (human-in-the-loop handoff). */\n\tsetStrategy(next: RefineStrategy<T>): void {\n\t\tthis.strategy.emit(next);\n\t}\n\n\t/** Pause after the current iteration completes. */\n\tpause(): void {\n\t\tthis._pauseState.emit(true);\n\t}\n\n\t/**\n\t * Resume a paused loop. Idempotent: only un-pauses from the \"paused\"\n\t * terminal state. Converged / budget / errored are permanent — a user\n\t * wanting to start over should construct a fresh refineLoop.\n\t */\n\tresume(): void {\n\t\tif (this.status.cache !== \"paused\") return;\n\t\tbatch(() => {\n\t\t\tthis._pauseState.emit(false);\n\t\t\tthis.status.emit(\"running\" as RefineStatus);\n\t\t\tthis._iteration.emit((this._iteration.cache as number) + 1);\n\t\t});\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Structural type-guard for `Node<T>`. Checks the three core Node methods\n * (`subscribe`, `down`, `emit`) as callable properties — rejects plain objects\n * with a single `subscribe` field that happen to look like a Node but aren't.\n */\nfunction isNode<T>(x: unknown): x is Node<T> {\n\tif (typeof x !== \"object\" || x === null) return false;\n\tconst obj = x as Record<string, unknown>;\n\treturn (\n\t\ttypeof obj.subscribe === \"function\" &&\n\t\ttypeof obj.down === \"function\" &&\n\t\ttypeof obj.emit === \"function\"\n\t);\n}\n\nfunction pickBest<T>(\n\tcandidates: readonly T[],\n\tscores: readonly EvalResult[],\n): { best: T | null; bestScore: number } {\n\t// Empty batch → no best. Use `null` per COMPOSITION-GUIDE §3: `undefined`\n\t// is the protocol SENTINEL, `null` is the domain sentinel for \"no value\".\n\tif (candidates.length === 0) {\n\t\treturn { best: null, bestScore: Number.NEGATIVE_INFINITY };\n\t}\n\tif (candidates.length === 1) {\n\t\tconst mean = meanScore(scores);\n\t\treturn { best: candidates[0]!, bestScore: mean };\n\t}\n\t// Fan-out aware: when any score carries `candidateIndex`, aggregate mean\n\t// score per candidate. When absent, fall back to positional `scores[i]` ↔\n\t// `candidates[i]` alignment (one-score-per-candidate convention).\n\tconst hasFanOut = scores.some((s) => typeof s.candidateIndex === \"number\");\n\tif (hasFanOut) {\n\t\tconst sums = new Array<{ sum: number; count: number }>(candidates.length);\n\t\tfor (let i = 0; i < candidates.length; i++) sums[i] = { sum: 0, count: 0 };\n\t\tfor (const s of scores) {\n\t\t\tconst idx = s.candidateIndex;\n\t\t\tif (typeof idx === \"number\" && idx >= 0 && idx < candidates.length) {\n\t\t\t\tsums[idx]!.sum += s.score;\n\t\t\t\tsums[idx]!.count += 1;\n\t\t\t}\n\t\t}\n\t\tlet best = candidates[0]!;\n\t\tlet bestScore = sums[0]!.count > 0 ? sums[0]!.sum / sums[0]!.count : Number.NEGATIVE_INFINITY;\n\t\tfor (let i = 1; i < candidates.length; i++) {\n\t\t\tconst avg = sums[i]!.count > 0 ? sums[i]!.sum / sums[i]!.count : Number.NEGATIVE_INFINITY;\n\t\t\tif (avg > bestScore) {\n\t\t\t\tbestScore = avg;\n\t\t\t\tbest = candidates[i]!;\n\t\t\t}\n\t\t}\n\t\treturn { best, bestScore };\n\t}\n\tlet best = candidates[0]!;\n\tlet bestScore = scores[0]?.score ?? Number.NEGATIVE_INFINITY;\n\tfor (let i = 1; i < candidates.length; i++) {\n\t\tconst s = scores[i]?.score ?? Number.NEGATIVE_INFINITY;\n\t\tif (s > bestScore) {\n\t\t\tbestScore = s;\n\t\t\tbest = candidates[i]!;\n\t\t}\n\t}\n\treturn { best, bestScore };\n}\n\nfunction meanScore(scores: readonly EvalResult[]): number {\n\tif (scores.length === 0) return Number.NEGATIVE_INFINITY;\n\tlet sum = 0;\n\tfor (const s of scores) sum += s.score;\n\treturn sum / scores.length;\n}\n\n// ---------------------------------------------------------------------------\n// refineLoop factory\n// ---------------------------------------------------------------------------\n\n/**\n * Construct a {@link RefineLoopGraph} — the universal prompt/artifact\n * optimization loop. Thin wrapper over `new RefineLoopGraph(...)` for\n * call-site ergonomics.\n */\nexport function refineLoop<T>(\n\tseed: T,\n\tevaluator: Evaluator<T>,\n\tinitialStrategy: RefineStrategy<T>,\n\topts: RefineLoopOptions,\n): RefineLoopGraph<T> {\n\treturn new RefineLoopGraph<T>(seed, evaluator, initialStrategy, opts);\n}\n\n// ---------------------------------------------------------------------------\n// Built-in strategy: blindVariation\n// ---------------------------------------------------------------------------\n\n/**\n * Context passed to a `blindVariation` teacher per call. `reportCost` is a\n * per-call hook — see `BlindVariationOptions.tokens`.\n */\nexport interface BlindVariationContext<T> {\n\treadonly prior: T;\n\t/**\n\t * Report tokens consumed by this teacher call. Aggregated per iteration\n\t * and flushed to `opts.tokens` in the strategy's `finally` block so\n\t * partial spend is preserved when the teacher throws mid-batch.\n\t */\n\treadonly reportCost: (tokens: number) => void;\n}\n\nexport interface BlindVariationOptions<T> {\n\t/** Name — default: `\"blindVariation\"`. */\n\tname?: string;\n\t/** Number of candidates generated per iteration. Default: 4. */\n\twidth?: number;\n\t/**\n\t * Run teacher calls in parallel via `Promise.all`. Default `true` — the\n\t * common case (independent LLM calls). Set `false` to run sequentially\n\t * via `for/await` when teachers share stateful resources (rate limiters,\n\t * rolling context, serial API ordering) that don't tolerate concurrency.\n\t */\n\tparallel?: boolean;\n\t/**\n\t * Optional cost counter node. Running total tokens reported via\n\t * `ctx.reportCost` during each iteration is added to this node in the\n\t * strategy's `finally` block — fires on success AND on teacher throw so\n\t * partial spend is never lost. User owns the node; wire to `budgetGate`,\n\t * `attachSnapshotStorage`, telemetry, etc.\n\t */\n\ttokens?: Node<number>;\n\t/**\n\t * Teacher — given `{prior, reportCost}`, produce one variant. Async\n\t * allowed. Called `width` times per iteration. Call `ctx.reportCost(n)`\n\t * to track tokens consumed per call (optional, no-op if `opts.tokens`\n\t * is not set).\n\t */\n\tteacher: (ctx: BlindVariationContext<T>) => Promise<T> | T;\n}\n\n/**\n * Simplest built-in strategy: generate N variants per iteration via the\n * supplied `teacher`; no feedback-informed steering (equivalent to Random\n * Search). Validates the loop infrastructure end-to-end and is the baseline\n * every other strategy should outperform.\n *\n * `analyze` records the mean score and flags the worst task — strategies that\n * care about per-task critique layer on top.\n */\nexport function blindVariation<T>(opts: BlindVariationOptions<T>): RefineStrategy<T> {\n\tconst width = opts.width ?? 4;\n\tconst name = opts.name ?? \"blindVariation\";\n\treturn {\n\t\tname,\n\t\tseed(seed) {\n\t\t\t// Iteration 0 emits just the seed — strategy.seed is synchronous by\n\t\t\t// contract, so we can't call an async teacher here. `width`-many\n\t\t\t// teacher-produced variants begin at iteration 1 via `generate`.\n\t\t\treturn [seed];\n\t\t},\n\t\tanalyze(scores, _candidates) {\n\t\t\tconst score = meanScore(scores);\n\t\t\tlet worst: EvalResult | null = null;\n\t\t\tfor (const s of scores) {\n\t\t\t\tif (!worst || s.score < worst.score) worst = s;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsummary: `blindVariation iteration: mean=${score.toFixed(3)}, n=${scores.length}`,\n\t\t\t\tscore,\n\t\t\t\tweakTasks: worst ? [worst.taskId] : [],\n\t\t\t};\n\t\t},\n\t\tasync generate(_feedback, candidates) {\n\t\t\tif (candidates.length === 0) {\n\t\t\t\t// Empty candidate batch is a contract violation — either the\n\t\t\t\t// seed was empty or a previous generate returned nothing. Surface\n\t\t\t\t// as an error rather than silently returning [] (which would\n\t\t\t\t// stall the loop in an infinite zero-candidate cycle).\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"blindVariation.generate: empty candidate batch — cannot derive prior for teacher\",\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Pick the current \"recent best\" — `null` IS a valid domain value\n\t\t\t// per COMPOSITION-GUIDE §3; the length guard above has already\n\t\t\t// filtered the `undefined` protocol sentinel.\n\t\t\tconst prior = candidates[candidates.length - 1] as T;\n\t\t\tlet iterCost = 0;\n\t\t\tconst reportCost = (n: number) => {\n\t\t\t\titerCost += n;\n\t\t\t};\n\t\t\tconst ctx: BlindVariationContext<T> = { prior, reportCost };\n\t\t\ttry {\n\t\t\t\tif (opts.parallel !== false) {\n\t\t\t\t\treturn await Promise.all(Array.from({ length: width }, () => opts.teacher(ctx)));\n\t\t\t\t}\n\t\t\t\tconst out: T[] = [];\n\t\t\t\tfor (let i = 0; i < width; i++) {\n\t\t\t\t\tout.push(await opts.teacher(ctx));\n\t\t\t\t}\n\t\t\t\treturn out;\n\t\t\t} finally {\n\t\t\t\tif (opts.tokens != null && iterCost > 0) {\n\t\t\t\t\t// /qa D1 follow-up (2026-05-01): replaced direct `.cache` read\n\t\t\t\t\t// + emit with `tryIncrementBounded`, which encapsulates the\n\t\t\t\t\t// self-owned-counter `.cache` access in the canonical helper\n\t\t\t\t\t// (sole sanctioned site per its JSDoc). Cap is unbounded for\n\t\t\t\t\t// the token meter.\n\t\t\t\t\ttryIncrementBounded(opts.tokens, Number.MAX_SAFE_INTEGER, iterCost);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Built-in strategy: errorCritique\n// ---------------------------------------------------------------------------\n\n/**\n * Context passed to an `errorCritique` teacher. `critique` is the pre-formatted\n * summary a prompt template can drop in verbatim; `failures` carries the\n * structured evidence (per-task error / score / detail) for richer prompts.\n */\nexport interface ErrorCritiqueContext<T> {\n\treadonly prior: T;\n\treadonly critique: string;\n\treadonly failures: readonly EvalResult[];\n\t/**\n\t * Report tokens consumed by this teacher call. Aggregated per iteration\n\t * and flushed to `opts.tokens` in the strategy's `finally` block so\n\t * partial spend is preserved when the teacher throws mid-batch.\n\t */\n\treadonly reportCost: (tokens: number) => void;\n}\n\nexport interface ErrorCritiqueOptions<T> {\n\t/** Name — default: `\"errorCritique\"`. */\n\tname?: string;\n\t/** Number of candidates generated per iteration. Default: 4. */\n\twidth?: number;\n\t/**\n\t * Cut-off below which a task is classified as a failure and fed into the\n\t * critique. Default: the batch mean — any task scoring below the batch\n\t * mean is a failure. Pass a number for an absolute cut-off, or a function\n\t * for per-batch computation (e.g. a percentile). When the default mean\n\t * is non-finite (NaN / ±Infinity from a degenerate evaluator), ALL scores\n\t * are treated as failures so the critique loop continues to steer.\n\t */\n\tfailureThreshold?: number | ((scores: readonly EvalResult[]) => number);\n\t/** Cap on failure samples packed into the critique. Default: 5. */\n\tmaxFailureSamples?: number;\n\t/**\n\t * Format failures into the `critique` string passed to the teacher. Default\n\t * joins `- taskId (score=N) | error: …` lines. Override to shape LLM prompts.\n\t *\n\t * **Note:** the `feedback` argument is a shell with `{score, weakTasks}`\n\t * populated; `summary` is empty because `analyze` computes the final summary\n\t * AFTER `formatCritique` runs (the summary embeds the formatted count).\n\t * Rely on `failures` and `feedback.score` — do not read `feedback.summary`\n\t * here.\n\t */\n\tformatCritique?: (failures: readonly EvalResult[], feedback: Feedback) => string;\n\t/**\n\t * Run teacher calls in parallel via `Promise.all`. Default `true` — the\n\t * common case (independent LLM calls). Set `false` to run sequentially\n\t * via `for/await` when teachers share stateful resources (rate limiters,\n\t * rolling context, serial API ordering) that don't tolerate concurrency.\n\t */\n\tparallel?: boolean;\n\t/**\n\t * Optional cost counter node. Running total tokens reported via\n\t * `ctx.reportCost` during each iteration is added to this node in the\n\t * strategy's `finally` block — fires on success AND on teacher throw so\n\t * partial spend is never lost. User owns the node; wire to `budgetGate`,\n\t * `attachSnapshotStorage`, telemetry, etc.\n\t */\n\ttokens?: Node<number>;\n\t/**\n\t * Teacher — given `{prior, critique, failures, reportCost}`, produce one\n\t * refined variant. Called `width` times per iteration. Async allowed.\n\t * Call `ctx.reportCost(n)` to track tokens consumed per call (optional,\n\t * no-op if `opts.tokens` is not set).\n\t */\n\tteacher: (ctx: ErrorCritiqueContext<T>) => Promise<T> | T;\n}\n\n/**\n * Private payload stashed inside `Feedback.critique` so `generate` can recover\n * the analyze-time prior + failure set without another pass over scores.\n */\ninterface ErrorCritiquePrivate<T> {\n\treadonly kind: \"errorCritique\";\n\treadonly best: T | null;\n\treadonly failures: readonly EvalResult[];\n\treadonly critiqueText: string;\n}\n\nfunction isErrorCritiquePrivate<T>(v: unknown): v is ErrorCritiquePrivate<T> {\n\treturn typeof v === \"object\" && v !== null && (v as { kind?: unknown }).kind === \"errorCritique\";\n}\n\nfunction defaultFormatCritique(failures: readonly EvalResult[], feedback: Feedback): string {\n\tif (failures.length === 0) {\n\t\treturn `No task scored below the batch mean (${feedback.score.toFixed(3)}). Reinforce the current direction.`;\n\t}\n\tconst lines = failures.map((f) => {\n\t\tconst err = f.error != null ? ` | error: ${f.error}` : \"\";\n\t\treturn `- ${f.taskId} (score=${f.score.toFixed(3)})${err}`;\n\t});\n\treturn `Failures below threshold:\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Critique-driven strategy (ProTeGi-style \"textual gradient\"). Each iteration:\n * 1. `analyze` classifies tasks scoring below a threshold as failures, picks\n * the best candidate from the batch, and packs both plus a formatted\n * critique string into `feedback.critique` as a private payload.\n * 2. `generate` unpacks that payload and calls the teacher with\n * `{prior, critique, failures, reportCost}` `width` times, returning the\n * refined batch.\n *\n * The teacher receives a pre-formatted string (drop into an LLM prompt) AND\n * the structured failure list (for richer prompts that want per-task detail).\n * Throws on empty candidate batches — matches `blindVariation`'s contract\n * (no silent zero-candidate cycles).\n *\n * When `setStrategy()` swaps this strategy in mid-run, the first `generate`\n * may receive a `Feedback` produced by the prior strategy (no private payload);\n * the fallback path uses `candidates[last]` as the prior and the feedback\n * summary as the critique, so the loop keeps running without a stall. When a\n * private payload IS present, `priv.critiqueText` takes precedence over any\n * edits a caller made to `feedback.summary` — treat `critique` as the\n * strategy-owned channel.\n */\nexport function errorCritique<T>(opts: ErrorCritiqueOptions<T>): RefineStrategy<T> {\n\tconst width = opts.width ?? 4;\n\tconst name = opts.name ?? \"errorCritique\";\n\tconst maxFailureSamples = opts.maxFailureSamples ?? 5;\n\tconst format = opts.formatCritique ?? defaultFormatCritique;\n\n\treturn {\n\t\tname,\n\t\tseed(seed) {\n\t\t\t// Iteration 0 emits just the seed. The critique loop begins at\n\t\t\t// iteration 1, once real scores exist to derive failures from.\n\t\t\treturn [seed];\n\t\t},\n\t\tanalyze(scores, candidates) {\n\t\t\tconst score = meanScore(scores);\n\t\t\tconst userThreshold =\n\t\t\t\ttypeof opts.failureThreshold === \"function\"\n\t\t\t\t\t? opts.failureThreshold(scores)\n\t\t\t\t\t: opts.failureThreshold;\n\t\t\t// A1: when the user didn't supply a threshold AND the batch-mean\n\t\t\t// default is non-finite (e.g. evaluator produced NaN / ±Infinity),\n\t\t\t// treat every score as a failure instead of filtering with `< NaN`\n\t\t\t// (which would be false for every score → silent no-op).\n\t\t\tconst thresholdUnresolvable = userThreshold === undefined && !Number.isFinite(score);\n\t\t\tconst threshold = userThreshold ?? score;\n\t\t\tconst allFailures = thresholdUnresolvable\n\t\t\t\t? [...scores].sort((a, b) => a.score - b.score)\n\t\t\t\t: scores\n\t\t\t\t\t\t.filter((s) => s.score < threshold)\n\t\t\t\t\t\t.slice()\n\t\t\t\t\t\t.sort((a, b) => a.score - b.score);\n\t\t\tconst failures = allFailures.slice(0, maxFailureSamples);\n\n\t\t\tconst { best, bestScore } = pickBest(candidates, scores);\n\t\t\tconst feedbackShell: Feedback = {\n\t\t\t\tsummary: \"\",\n\t\t\t\tscore,\n\t\t\t\tweakTasks: failures.map((f) => f.taskId),\n\t\t\t};\n\t\t\tconst critiqueText = format(failures, feedbackShell);\n\n\t\t\tconst priv: ErrorCritiquePrivate<T> = {\n\t\t\t\tkind: \"errorCritique\",\n\t\t\t\tbest,\n\t\t\t\tfailures,\n\t\t\t\tcritiqueText,\n\t\t\t};\n\t\t\tconst retainedSuffix =\n\t\t\t\tallFailures.length > failures.length ? ` (top ${failures.length} retained)` : \"\";\n\t\t\treturn {\n\t\t\t\tsummary: `errorCritique iteration: mean=${score.toFixed(3)}, failures=${allFailures.length}${retainedSuffix}/${scores.length}, bestScore=${bestScore.toFixed(3)}`,\n\t\t\t\tcritique: priv,\n\t\t\t\tweakTasks: failures.map((f) => f.taskId),\n\t\t\t\tscore,\n\t\t\t};\n\t\t},\n\t\tasync generate(feedback, candidates) {\n\t\t\t// N1: Length guard FIRST. The only protocol-sentinel risk is\n\t\t\t// `undefined` sneaking in via an empty candidates array; after\n\t\t\t// this check, `null` values (including `priv.best === null` when\n\t\t\t// T admits null) flow through as domain-valid per\n\t\t\t// COMPOSITION-GUIDE §3 / spec §1.\n\t\t\tif (candidates.length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"errorCritique.generate: empty candidate batch — cannot derive prior for teacher\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst priv = isErrorCritiquePrivate<T>(feedback.critique) ? feedback.critique : undefined;\n\t\t\tconst prior: T =\n\t\t\t\tpriv !== undefined ? (priv.best as T) : (candidates[candidates.length - 1] as T);\n\t\t\tconst critique = priv?.critiqueText ?? feedback.summary;\n\t\t\tconst failures = priv?.failures ?? [];\n\t\t\tlet iterCost = 0;\n\t\t\tconst reportCost = (n: number) => {\n\t\t\t\titerCost += n;\n\t\t\t};\n\t\t\tconst ctx: ErrorCritiqueContext<T> = { prior, critique, failures, reportCost };\n\t\t\ttry {\n\t\t\t\tif (opts.parallel !== false) {\n\t\t\t\t\treturn await Promise.all(Array.from({ length: width }, () => opts.teacher(ctx)));\n\t\t\t\t}\n\t\t\t\tconst out: T[] = [];\n\t\t\t\tfor (let i = 0; i < width; i++) {\n\t\t\t\t\tout.push(await opts.teacher(ctx));\n\t\t\t\t}\n\t\t\t\treturn out;\n\t\t\t} finally {\n\t\t\t\tif (opts.tokens != null && iterCost > 0) {\n\t\t\t\t\t// /qa D1 follow-up (2026-05-01): replaced direct `.cache` read\n\t\t\t\t\t// + emit with `tryIncrementBounded`, which encapsulates the\n\t\t\t\t\t// self-owned-counter `.cache` access in the canonical helper.\n\t\t\t\t\ttryIncrementBounded(opts.tokens, Number.MAX_SAFE_INTEGER, iterCost);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * Phase 13.I — `spawnable()` harness preset.\n *\n * Source: `archive/docs/SESSION-multi-agent-gap-analysis.md` G3 lock B + G5\n * reframe.\n *\n * Wraps a {@link MessagingHubGraph} + {@link presetRegistry} +\n * (per-request) {@link agent} mounting + depth-cap + termination contract.\n * Consumers emit a `TopicMessage<SpawnPayload>` to the well-known\n * {@link SPAWNS_TOPIC}; `spawnable()` mints a fresh agent from the\n * matching preset, mounts it, and tracks it in `activeSlot` until the\n * agent settles or expires. Out-of-policy requests (depth-cap exceeded,\n * unknown presetId, schema-invalid, expired) flow to the `rejected`\n * topic.\n *\n * **Cross-cut #1 lock (no `agent.run()`):** spawnable kicks each agent\n * via `bundle.in.emit(taskInput)`; status transitions are observed via\n * the agent's reactive `status` Node.\n *\n * **Termination contract:**\n * - `done` / `error` from the agent's `status` → unmount + remove from\n * `activeSlot`.\n * - `expiresAt` (set on the request envelope, ISO 8601) — when the wall\n * clock passes the deadline AND the agent is still active, the agent is\n * aborted (via `loop.abort()`) and reported on `rejected` with\n * `reason: \"expired\"`. (Per-spawn timeout via the `timeout` operator\n * recipe is documented in COMPOSITION-GUIDE-PATTERNS.)\n *\n * **Depth-cap:** locked recipe (DS-13.I) is `valve(spawnTopic, derived(\n * [depthCounter], n => n < cap))`, but the practical pattern in\n * `spawnable()` checks depth per-request inside the request handler so\n * over-cap requests can be reported on `rejected`. Callers who want hard\n * cuts (no rejection signal) can wrap their own publish path with\n * `valve` per the recipe.\n */\n\nimport { batch, DATA, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { aiMeta } from \"../../utils/ai/_internal.js\";\nimport type { LLMResponse } from \"../../utils/ai/adapters/core/types.js\";\nimport {\n\ttype MessagingHubGraph,\n\tSPAWNS_TOPIC,\n\ttype SubscriptionGraph,\n\tsubscription,\n\ttype TopicGraph,\n\ttype TopicMessage,\n\ttopic,\n} from \"../../utils/messaging/index.js\";\nimport type { AgentBundle, AgentSpec, AgentStatus } from \"../ai/agent.js\";\nimport type { PresetRegistryBundle } from \"../ai/agents.js\";\nimport { agent } from \"../ai/agents.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Payload of a spawn request envelope. Wraps in a {@link Message}<...>:\n * the request body sets `presetId` (the preset registry key) and\n * `taskInput` (the typed input passed to the spawned agent's `bundle.in`).\n */\nexport interface SpawnPayload<TIn> {\n\treadonly presetId: string;\n\treadonly taskInput: TIn;\n}\n\n/**\n * Rejection record published to the `rejected` topic when a spawn request\n * is denied. `reason` is a short human-readable code.\n */\nexport interface SpawnRejection<TIn> {\n\treadonly request: TopicMessage<SpawnPayload<TIn>>;\n\treadonly reason: string;\n}\n\n/**\n * Options for {@link spawnable}.\n */\nexport interface SpawnableOpts<TIn, TOut> {\n\t/** Existing messaging hub. {@link SPAWNS_TOPIC} is created lazily on it. */\n\treadonly hub: MessagingHubGraph;\n\t/** Preset registry — keys must match `request.payload.presetId`. */\n\treadonly registry: PresetRegistryBundle<AgentSpec<TIn, TOut>>;\n\t/**\n\t * Local mount name on the hub for this spawnable's subgraph. Multiple\n\t * spawnable instances on the same hub must use distinct names. Default\n\t * `\"spawnable\"`.\n\t */\n\treadonly name?: string;\n\t/** Maximum concurrently-active agents. Default unbounded. */\n\treadonly depthCap?: number;\n\t/**\n\t * Initial cursor for the spawn-topic subscription. Default `\"now\"` —\n\t * pre-existing retained spawn requests are NOT replayed at construction.\n\t * Pass `\"retained\"` to replay or a number for explicit cursor offset.\n\t */\n\treadonly from?: \"now\" | \"retained\" | number;\n\t/**\n\t * Optional caller-supplied validator. Returns `true` to accept the\n\t * request, `false` to reject. Reject reason on the `rejected` topic is\n\t * `\"schema validation failed\"`. Pair with the `Message.schema` field carried\n\t * in the envelope when full JSON-Schema validation is needed (consumer\n\t * supplies the validator — ajv / zod / valibot — and reads the schema\n\t * from the envelope to gate). The substrate itself does NOT ship a\n\t * JSON-Schema validator; the `Message.schema` field is wire convention.\n\t */\n\treadonly validate?: (request: TopicMessage<SpawnPayload<TIn>>) => boolean;\n}\n\n/**\n * The bundle returned by {@link spawnable}.\n */\nexport interface SpawnableBundle<TIn, TOut> {\n\t/** The well-known spawn topic — emit `TopicMessage<SpawnPayload<TIn>>` here. */\n\treadonly spawnTopic: TopicGraph<TopicMessage<SpawnPayload<TIn>>>;\n\t/** Reactive map of currently-active agent bundles, keyed by request id. */\n\treadonly activeSlot: Node<ReadonlyMap<string, AgentBundle<TIn, TOut>>>;\n\t/** Topic of rejected requests with reason. */\n\treadonly rejected: TopicGraph<SpawnRejection<TIn>>;\n\t/** The internal SpawnableGraph subgraph (mounted under the hub). */\n\treadonly graph: SpawnableGraph<TIn, TOut>;\n}\n\n// ---------------------------------------------------------------------------\n// SpawnableGraph\n// ---------------------------------------------------------------------------\n\n/**\n * Graph subclass implementing {@link SpawnableBundle}'s topology.\n * Mounted under the hub at `opts.name` (default `\"spawnable\"`).\n *\n * Topology:\n * ```\n * <hub>\n * ├── spawns (TopicGraph; well-known well-named spawn topic)\n * └── <name> (SpawnableGraph)\n * ├── spawn-sub (SubscriptionGraph over hub::spawns::events)\n * ├── rejected (TopicGraph<SpawnRejection>)\n * ├── active-slot (Node<ReadonlyMap<id, AgentBundle>>)\n * └── spawn-{req.id}/ (mounted AgentGraph per active spawn)\n * ```\n */\nexport class SpawnableGraph<TIn, TOut> extends Graph {\n\treadonly spawnTopic: TopicGraph<TopicMessage<SpawnPayload<TIn>>>;\n\treadonly rejected: TopicGraph<SpawnRejection<TIn>>;\n\treadonly activeSlot: Node<ReadonlyMap<string, AgentBundle<TIn, TOut>>>;\n\tprivate readonly _spawnSub: SubscriptionGraph<TopicMessage<SpawnPayload<TIn>>>;\n\tprivate readonly _registry: PresetRegistryBundle<AgentSpec<TIn, TOut>>;\n\tprivate readonly _depthCap: number | undefined;\n\tprivate readonly _validate: ((req: TopicMessage<SpawnPayload<TIn>>) => boolean) | undefined;\n\tprivate _disposed = false;\n\n\tconstructor(opts: SpawnableOpts<TIn, TOut>) {\n\t\tconst name = opts.name ?? \"spawnable\";\n\t\tsuper(name);\n\n\t\tthis._registry = opts.registry;\n\t\tthis._depthCap = opts.depthCap;\n\t\tthis._validate = opts.validate;\n\n\t\t// Spawn topic on the hub (well-known name; lazy-created if absent).\n\t\tthis.spawnTopic = opts.hub.topic<TopicMessage<SpawnPayload<TIn>>>(SPAWNS_TOPIC);\n\n\t\t// Rejected topic is private to this spawnable subgraph.\n\t\tthis.rejected = topic<SpawnRejection<TIn>>(\"rejected\");\n\t\tthis.mount(\"rejected\", this.rejected);\n\n\t\t// Active-slot map. `equals: () => false` so each mutation emits a\n\t\t// fresh snapshot even when callers pass an identity-equal Map ref.\n\t\tconst activeSlotNode = node<ReadonlyMap<string, AgentBundle<TIn, TOut>>>([], {\n\t\t\tname: \"active-slot\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"spawnable_active_slot\"),\n\t\t\tinitial: new Map(),\n\t\t\tequals: () => false,\n\t\t});\n\t\tthis.add(activeSlotNode, { name: \"active-slot\" });\n\t\tthis.activeSlot = activeSlotNode;\n\n\t\t// Cursor-based subscription over hub.spawnTopic.events. Lives under\n\t\t// this spawnable subgraph (NOT the hub), so multiple spawnable\n\t\t// instances on the same hub get independent cursors.\n\t\t// Default `from: \"now\"` skips pre-construction retained requests —\n\t\t// older requests are NOT replayed unless the caller opts in.\n\t\tthis._spawnSub = subscription<TopicMessage<SpawnPayload<TIn>>>(\"spawn-sub\", this.spawnTopic, {\n\t\t\tfrom: opts.from ?? \"now\",\n\t\t});\n\t\tthis.mount(\"spawn-sub\", this._spawnSub);\n\n\t\t// Subscribe to `available` to process new requests; ack as we go.\n\t\tconst subRef = this._spawnSub;\n\t\tconst unsub = subRef.available.subscribe((msgs) => {\n\t\t\tif (this._disposed) return;\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tconst items = m[1] as readonly TopicMessage<SpawnPayload<TIn>>[];\n\t\t\t\tif (items.length === 0) continue;\n\t\t\t\tfor (const req of items) {\n\t\t\t\t\tif (this._disposed) return;\n\t\t\t\t\tthis._processRequest(req);\n\t\t\t\t}\n\t\t\t\tsubRef.ack(items.length);\n\t\t\t}\n\t\t});\n\t\tthis.addDisposer(unsub);\n\t\tthis.addDisposer(() => {\n\t\t\tthis._disposed = true;\n\t\t});\n\t\t// Keepalive on the active-slot Node so external `cache` reads stay\n\t\t// current even when no one is subscribed.\n\t\tthis.addDisposer(keepalive(activeSlotNode));\n\t}\n\n\tprivate _processRequest(req: TopicMessage<SpawnPayload<TIn>>): void {\n\t\tif (this._disposed) return;\n\n\t\t// Custom validation.\n\t\tif (this._validate && !this._validate(req)) {\n\t\t\tthis.rejected.publish({ request: req, reason: \"schema validation failed\" });\n\t\t\treturn;\n\t\t}\n\n\t\t// Expiry check (only on entry — per-agent timeouts during run are a\n\t\t// future iteration; recipe-style composition with `timeout` covers\n\t\t// the in-flight case until then). Use `wallClockNs()` so test\n\t\t// suites that monkey-patch the central clock can pin expiry decisions.\n\t\tif (req.expiresAt != null) {\n\t\t\tconst expiry = Date.parse(req.expiresAt);\n\t\t\tif (!Number.isFinite(expiry)) {\n\t\t\t\tthis.rejected.publish({ request: req, reason: \"invalid expiresAt\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nowMs = wallClockNs() / 1_000_000;\n\t\t\tif (nowMs >= expiry) {\n\t\t\t\tthis.rejected.publish({ request: req, reason: \"expired\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Depth-cap check.\n\t\tconst currentMap =\n\t\t\t(this.activeSlot.cache as ReadonlyMap<string, AgentBundle<TIn, TOut>> | undefined) ??\n\t\t\tnew Map();\n\t\tif (this._depthCap != null && currentMap.size >= this._depthCap) {\n\t\t\tthis.rejected.publish({\n\t\t\t\trequest: req,\n\t\t\t\treason: `depth-cap exceeded (${currentMap.size}/${this._depthCap})`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Look up preset.\n\t\tconst spec = this._registry.registry.get(req.payload.presetId);\n\t\tif (!spec) {\n\t\t\tthis.rejected.publish({\n\t\t\t\trequest: req,\n\t\t\t\treason: `unknown presetId: ${req.payload.presetId}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Mint and mount the agent. Slot name is derived from the request id\n\t\t// so it's traceable in describe / explain output.\n\t\tconst slotName = `spawn-${req.id}`;\n\t\tlet bundle: AgentBundle<TIn, TOut>;\n\t\ttry {\n\t\t\tbundle = agent<TIn, TOut>(this, { ...spec, name: slotName });\n\t\t} catch (e) {\n\t\t\tthis.rejected.publish({\n\t\t\t\trequest: req,\n\t\t\t\treason: `agent mint failed: ${(e as Error).message ?? \"unknown\"}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Update active-slot.\n\t\tconst updated = new Map(currentMap);\n\t\tupdated.set(req.id, bundle);\n\t\tthis.activeSlot.emit(updated);\n\n\t\t// Watch for completion BEFORE kicking, so a synchronous adapter that\n\t\t// drives status straight to \"done\" inside the kick still triggers\n\t\t// cleanup. Subscribe to status; on terminal, unmount + remove. Each\n\t\t// per-spawn statusUnsub releases inside `onTerminal` so we don't\n\t\t// accumulate dead disposers per-spawn over the spawnable's lifetime.\n\t\tlet statusUnsub: (() => void) | undefined;\n\t\tconst onTerminal = (stat: AgentStatus): void => {\n\t\t\tif (stat !== \"done\" && stat !== \"error\") return;\n\t\t\t// Idempotent — guard against double-fire.\n\t\t\tconst live =\n\t\t\t\t(this.activeSlot.cache as ReadonlyMap<string, AgentBundle<TIn, TOut>> | undefined) ??\n\t\t\t\tnew Map();\n\t\t\tif (!live.has(req.id)) return;\n\t\t\tbatch(() => {\n\t\t\t\ttry {\n\t\t\t\t\tthis.remove(slotName);\n\t\t\t\t} catch {\n\t\t\t\t\t// Already removed (e.g., parent destroyed mid-flight).\n\t\t\t\t}\n\t\t\t\tconst next = new Map(live);\n\t\t\t\tnext.delete(req.id);\n\t\t\t\tthis.activeSlot.emit(next);\n\t\t\t});\n\t\t\t// Release the per-spawn status subscription now that the spawn\n\t\t\t// is finished — prevents disposer accumulation over many spawns.\n\t\t\tstatusUnsub?.();\n\t\t\tstatusUnsub = undefined;\n\t\t};\n\t\tstatusUnsub = bundle.status.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) onTerminal(m[1] as AgentStatus);\n\t\t\t}\n\t\t});\n\t\t// Defensive disposer — fires on SpawnableGraph.destroy() if the\n\t\t// spawn is still in-flight. `onTerminal` clears `statusUnsub` so\n\t\t// double-call is a no-op.\n\t\tthis.addDisposer(() => statusUnsub?.());\n\n\t\t// Kick the agent reactively.\n\t\tbundle.in.emit(req.payload.taskInput);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// spawnable() factory\n// ---------------------------------------------------------------------------\n\n/**\n * Constructs a {@link SpawnableGraph}, mounts it under `opts.hub` at\n * `opts.name` (default `\"spawnable\"`), and returns the\n * {@link SpawnableBundle} contract.\n *\n * **Composition with Phase 13 substrate:**\n * - Builds on **13.B** ({@link Message} envelope, {@link SPAWNS_TOPIC}).\n * - Builds on **13.G/H** ({@link agent}, {@link AgentBundle}).\n * - Builds on **13.H** ({@link presetRegistry}).\n * - The depth-cap gate is documented as a **13.D recipe**\n * (`valve(spawnTopic, derived([depthCounter], n => n < cap))`); inside\n * `spawnable()` the depth check is per-request so over-cap requests\n * surface on `rejected`. Callers wanting a hard cut (no rejection\n * signal) can wrap their publish path with `valve`.\n *\n * **Strategy-key axis (DS-13.I):** when `harnessLoop` is wired to a\n * spawnable, downstream `strategy.record(...)` calls should pass the\n * spawning agent's `presetId` for the {@link strategyKey} first axis.\n * Single-agent harness keeps using {@link DEFAULT_PRESET_ID} as before.\n *\n * @example\n * ```ts\n * const hub = messagingHub(\"hub\");\n * const presets = presetRegistry<AgentSpec<string, LLMResponse>>();\n * presets.put(\"researcher\", { name: \"researcher\", adapter: openai, systemPrompt: \"...\" });\n * presets.put(\"coder\", { name: \"coder\", adapter: anthropic, systemPrompt: \"...\" });\n *\n * const sp = spawnable({ hub, registry: presets, depthCap: 5 });\n *\n * // Trigger a spawn:\n * sp.spawnTopic.publish({\n * id: \"req-42\",\n * payload: { presetId: \"researcher\", taskInput: \"what is reactive graph composition?\" },\n * });\n *\n * // Observe active agents:\n * sp.activeSlot.subscribe((msgs) => { ... });\n *\n * // Observe rejections:\n * sp.rejected.events.subscribe((msgs) => { ... });\n * ```\n *\n * @category patterns\n */\nexport function spawnable<TIn = string, TOut = LLMResponse>(\n\topts: SpawnableOpts<TIn, TOut>,\n): SpawnableBundle<TIn, TOut> {\n\tconst graph = new SpawnableGraph<TIn, TOut>(opts);\n\topts.hub.mount(opts.name ?? \"spawnable\", graph);\n\treturn {\n\t\tspawnTopic: graph.spawnTopic,\n\t\tactiveSlot: graph.activeSlot,\n\t\trejected: graph.rejected,\n\t\tgraph,\n\t};\n}\n","/**\n * Phase 13.H — `agent(spec)` preset + `presetRegistry` sugar.\n *\n * Source: `archive/docs/SESSION-multi-agent-gap-analysis.md` G1 + G2.\n *\n * `agent()` is the ergonomic factory — given a parent Graph and an\n * `AgentSpec`, mints an `AgentGraph`, mounts it under the parent at\n * `spec.name`, and returns the `AgentBundle` contract.\n *\n * `presetRegistry()` is thin sugar over `reactiveMap` — a typed reactive\n * map of `<id, preset>`. Pairs with `materialize` (Phase 13.C) for\n * dynamic preset selection: callers store specs / factories / configs in\n * the registry and `materialize` mounts the matching one based on a\n * routing key.\n *\n * **Cross-cut #1 lock:** no `agent.run()` imperative sugar — caller-side\n * runtime is `bundle.in.emit(input)` + `awaitSettled(bundle.out)`.\n */\n\nimport { type ReactiveMapBundle, reactiveMap } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport type { LLMResponse } from \"../../utils/ai/adapters/core/types.js\";\nimport { type AgentBundle, AgentGraph, type AgentSpec } from \"./agent.js\";\n\n// ---------------------------------------------------------------------------\n// agent() factory\n// ---------------------------------------------------------------------------\n\n/**\n * Mints an {@link AgentGraph} from `spec`, mounts it under `parent` at\n * `spec.name`, and returns the {@link AgentBundle} contract.\n *\n * **Default type parameters.** When called without explicit type params,\n * `TIn` defaults to `string` and `TOut` to `LLMResponse` — the common\n * case where the caller writes a user message and reads the raw response.\n * Custom types require both `inMapper` and `outMapper` in the spec; the\n * default mappers throw at runtime if `TIn` / `TOut` aren't string /\n * LLMResponse.\n *\n * **Memory partition default.** Each `agent()` call mints its own\n * `AgentMemoryGraph` if `spec.memory` is omitted (private memory; the\n * common case). Pass an explicit shared instance — e.g.\n * `agent(parent, { ..., memory: sharedMemory })` for two agents — to\n * implement §29 handoff context transfer.\n *\n * **Reactive entry / exit:**\n * - `bundle.in.emit(input)` kicks the loop reactively (no imperative\n * `.run()` per cross-cut #1 lock).\n * - `awaitSettled(bundle.out, { skipCurrent: true })` resolves on the\n * first response after the kick. `skipCurrent` matters for the second\n * call onward — `out` caches the prior response.\n *\n * **Mounting.** The factory mounts under `parent.mount(spec.name, ...)`.\n * The slot name must be free on `parent` at construction time. To keep\n * the agent unmounted, construct `new AgentGraph(spec)` directly.\n *\n * @example\n * ```ts\n * import { agent, awaitSettled, Graph } from \"@graphrefly/graphrefly-ts\";\n *\n * const parent = new Graph(\"parent\");\n * const a = agent(parent, {\n * name: \"researcher\",\n * adapter: openaiAdapter,\n * systemPrompt: \"Research the user's question carefully.\",\n * });\n * a.in.emit(\"What's the capital of France?\");\n * const resp = await awaitSettled(a.out, { skipCurrent: true });\n * ```\n *\n * @category patterns\n */\nexport function agent<TIn = string, TOut = LLMResponse>(\n\tparent: Graph,\n\tspec: AgentSpec<TIn, TOut>,\n): AgentBundle<TIn, TOut> {\n\tconst graph = new AgentGraph<TIn, TOut>(spec);\n\tparent.mount(spec.name, graph);\n\treturn {\n\t\tin: graph.in,\n\t\tout: graph.out,\n\t\tstatus: graph.status,\n\t\tcost: graph.cost,\n\t\tgraph,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// presetRegistry()\n// ---------------------------------------------------------------------------\n\n/**\n * The bundle returned by {@link presetRegistry}. Wraps a `reactiveMap`\n * with imperative `put` / `remove` shortcuts and exposes the underlying\n * `registry` for direct reactive consumption (`.entries` is a\n * `Node<ReadonlyMap<string, TPreset>>`).\n *\n * Use the `registry.entries` Node directly with {@link materialize} (Phase\n * 13.C) — pass it as the `factories` argument when `TPreset` is itself\n * a `() => Graph` factory thunk, or transform via `derived` when\n * `TPreset` is a richer spec type that needs a `spec → factory` adapter.\n */\nexport interface PresetRegistryBundle<TPreset> {\n\t/**\n\t * The underlying reactive map. `registry.entries` is the\n\t * `Node<ReadonlyMap<string, TPreset>>` — pass directly to\n\t * {@link materialize} when preset shape matches the factories arg.\n\t */\n\treadonly registry: ReactiveMapBundle<string, TPreset>;\n\t/** Imperative add / replace. Always emits a fresh snapshot. */\n\tput(id: string, preset: TPreset): void;\n\t/** Imperative remove. Returns `true` if the id was present. */\n\tremove(id: string): boolean;\n}\n\n/**\n * Thin sugar over `reactiveMap` — a typed registry of `<id, preset>` for\n * agent / strategy / persona / skill catalogs.\n *\n * **Generic over preset shape.** `TPreset` is open — could be an\n * {@link AgentSpec}, a `() => Graph` factory thunk, a static config\n * object, or anything else. Decoupled from `agent()` so the same primitive\n * powers harnessLoop strategy registries, pipelineGraph stage catalogs,\n * etc.\n *\n * **Composes with `materialize`.** When `TPreset` is a `() => Graph`\n * factory, pass `registry.entries` directly to\n * {@link materialize} as the `factories` argument. When `TPreset` is a\n * spec, transform via `derived` to build a `Map<id, () => Graph>` adapter:\n *\n * ```ts\n * const presets = presetRegistry<AgentSpec<string, LLMResponse>>();\n * presets.put(\"researcher\", { name: \"researcher\", adapter, systemPrompt: \"...\" });\n *\n * // Adapter: spec → factory.\n * const factories = derived(\n * [presets.registry.entries],\n * ([m]) => new Map(\n * [...m].map(([id, spec]) => [id, () => new AgentGraph(spec)]),\n * ),\n * );\n * const slot = materialize(activeKey, factories, parent);\n * ```\n *\n * @param initial - Optional initial entries.\n * @returns {@link PresetRegistryBundle}.\n *\n * @category patterns\n */\nexport function presetRegistry<TPreset>(\n\tinitial?: ReadonlyMap<string, TPreset>,\n): PresetRegistryBundle<TPreset> {\n\tconst registry = reactiveMap<string, TPreset>({ name: \"presetRegistry\" });\n\tif (initial != null) {\n\t\tfor (const [id, preset] of initial) {\n\t\t\tregistry.set(id, preset);\n\t\t}\n\t}\n\treturn {\n\t\tregistry,\n\t\tput(id, preset) {\n\t\t\tregistry.set(id, preset);\n\t\t},\n\t\tremove(id) {\n\t\t\tif (!registry.has(id)) return false;\n\t\t\tregistry.delete(id);\n\t\t\treturn true;\n\t\t},\n\t};\n}\n","/**\n * Phase 13.G — `AgentBundle<TIn, TOut>` interface + `class AgentGraph extends Graph`.\n *\n * Source: `archive/docs/SESSION-multi-agent-gap-analysis.md` G1 lock B.\n *\n * Composes the existing substrate (`agentLoop`, `toolRegistry`,\n * `agentMemory`) into a typed inbox/outbox subgraph that other parts of a\n * multi-agent system can wire to. Sibling preset `agent()` (in\n * `./agents.ts`) is the ergonomic factory; this file is the contract.\n *\n * **Cross-cut #1 lock (no `agent.run()`):** caller-side runtime entry is\n * `bundle.in.emit(input)` + `awaitSettled(bundle.out)`. The legacy\n * `agentLoop.run()` is still available on `bundle.graph.loop` for\n * single-shot Promise-bridge use cases, but `agent()` does NOT expose a\n * `run()` method on the bundle.\n *\n * **Memory partition default:** private memory per agent (each `agent(...)`\n * call creates its own `AgentMemoryGraph` if none passed). Pass an explicit\n * shared instance for §29 handoff context-transfer.\n */\n\nimport { batch, DATA, INVALIDATE, type Node, node, RESOLVED } from \"@graphrefly/pure-ts/core\";\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { aiMeta } from \"../../utils/ai/_internal.js\";\nimport type {\n\tInputTokens,\n\tLLMAdapter,\n\tLLMResponse,\n\tOutputTokens,\n\tTokenUsage,\n\tToolDefinition,\n} from \"../../utils/ai/adapters/core/types.js\";\nimport {\n\ttype SubscriptionGraph,\n\tsubscription,\n\ttype TopicGraph,\n\ttopic,\n} from \"../../utils/messaging/index.js\";\nimport { type AgentLoopGraph, agentLoop } from \"./agent-loop.js\";\nimport type { AgentMemoryGraph } from \"./agent-memory.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Lifecycle status of an {@link AgentGraph}.\n *\n * - `idle` — no input has been received since construction or last reset.\n * - `running` — inputs are flowing through the underlying agentLoop\n * (collapses the loop's `thinking` + `acting` substates so consumers\n * don't have to model the tool-call inner loop).\n * - `verifying` — verifier subgraph is in flight (reserved; lights up when\n * the verifier slot is added in a future wave per G7 recipe).\n * - `done` — the most recent input has settled with a verified response.\n * - `error` — the loop or verifier produced a terminal error.\n *\n * **Note (Phase 13.G, 2026-05-01):** v1 of `agent()` has no built-in\n * verifier slot — `verifying` is reserved but never produced. When a\n * verifier consumer surfaces, this enum widens (non-breaking type\n * widening; existing consumers see the same `idle | running | done | error`\n * subset).\n */\nexport type AgentStatus = \"idle\" | \"running\" | \"verifying\" | \"done\" | \"error\";\n\n/**\n * Aggregated cost for an agent's run, surfaced as a `Node<CostState>` on\n * the bundle. **Wraps the canonical {@link TokenUsage}** so consumers get\n * the full provider-disaggregated token classes (cache-read /\n * cache-write-5m / cache-write-1h / audio / image / video / tool-use /\n * reasoning / prediction-accepted / prediction-rejected / extensions /\n * auxiliary non-token costs / raw escape-hatch) without losing fidelity\n * for downstream pricing. USD conversion is a downstream `derived` over\n * `usage`.\n *\n * - `usage` — accumulated {@link TokenUsage} across all turns of the\n * current input.\n * - `turns` — number of completed agentLoop iterations (LLM invocations).\n *\n * **Counter scope:** resets to {@link ZERO_COST} on each new `bundle.in`\n * emit (per-input cost rather than per-agent-lifetime). Sum across multiple\n * inputs by snapshotting `cost` at `done` and accumulating externally —\n * a per-lifetime cost is a downstream `scan` over this.\n *\n * **Helpers.** Use `sumInputTokens(usage)` / `sumOutputTokens(usage)` from\n * `@graphrefly/graphrefly-ts` to flatten to scalars when the caller wants\n * a single number.\n */\nexport interface CostState {\n\treadonly usage: TokenUsage;\n\treadonly turns: number;\n}\n\nconst EMPTY_INPUT: InputTokens = Object.freeze({ regular: 0 });\nconst EMPTY_OUTPUT: OutputTokens = Object.freeze({ regular: 0 });\nconst EMPTY_USAGE: TokenUsage = Object.freeze({ input: EMPTY_INPUT, output: EMPTY_OUTPUT });\n\n/** Empty cost. Used as the initial value and the per-input reset baseline. */\nexport const ZERO_COST: CostState = Object.freeze({ usage: EMPTY_USAGE, turns: 0 });\n\n// ---------------------------------------------------------------------------\n// TokenUsage accumulator\n// ---------------------------------------------------------------------------\n\nfunction addOptional(a: number | undefined, b: number | undefined): number | undefined {\n\tif (a == null && b == null) return undefined;\n\treturn (a ?? 0) + (b ?? 0);\n}\n\nfunction addExtensions(\n\ta: Record<string, number> | undefined,\n\tb: Record<string, number> | undefined,\n): Record<string, number> | undefined {\n\tif (a == null && b == null) return undefined;\n\tconst out: Record<string, number> = { ...(a ?? {}) };\n\tfor (const [k, v] of Object.entries(b ?? {})) {\n\t\tout[k] = (out[k] ?? 0) + v;\n\t}\n\treturn out;\n}\n\n/**\n * Accumulates two {@link TokenUsage} snapshots. All field classes are\n * summed; optional fields propagate as `undefined` when absent from both\n * sides, otherwise treated as 0 for the missing side. `auxiliary` and\n * `extensions` merge by key. `raw` is dropped — it's a per-call escape\n * hatch, not summable.\n *\n * @category extra\n */\nexport function addUsage(a: TokenUsage, b: TokenUsage): TokenUsage {\n\tconst out: TokenUsage = {\n\t\tinput: {\n\t\t\tregular: a.input.regular + b.input.regular,\n\t\t\t...(addOptional(a.input.cacheRead, b.input.cacheRead) !== undefined && {\n\t\t\t\tcacheRead: addOptional(a.input.cacheRead, b.input.cacheRead) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.cacheWrite5m, b.input.cacheWrite5m) !== undefined && {\n\t\t\t\tcacheWrite5m: addOptional(a.input.cacheWrite5m, b.input.cacheWrite5m) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.cacheWrite1h, b.input.cacheWrite1h) !== undefined && {\n\t\t\t\tcacheWrite1h: addOptional(a.input.cacheWrite1h, b.input.cacheWrite1h) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.cacheWriteOther, b.input.cacheWriteOther) !== undefined && {\n\t\t\t\tcacheWriteOther: addOptional(a.input.cacheWriteOther, b.input.cacheWriteOther) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.audio, b.input.audio) !== undefined && {\n\t\t\t\taudio: addOptional(a.input.audio, b.input.audio) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.image, b.input.image) !== undefined && {\n\t\t\t\timage: addOptional(a.input.image, b.input.image) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.video, b.input.video) !== undefined && {\n\t\t\t\tvideo: addOptional(a.input.video, b.input.video) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.input.toolUse, b.input.toolUse) !== undefined && {\n\t\t\t\ttoolUse: addOptional(a.input.toolUse, b.input.toolUse) as number,\n\t\t\t}),\n\t\t\t...(addExtensions(a.input.extensions, b.input.extensions) !== undefined && {\n\t\t\t\textensions: addExtensions(a.input.extensions, b.input.extensions) as Record<string, number>,\n\t\t\t}),\n\t\t},\n\t\toutput: {\n\t\t\tregular: a.output.regular + b.output.regular,\n\t\t\t...(addOptional(a.output.reasoning, b.output.reasoning) !== undefined && {\n\t\t\t\treasoning: addOptional(a.output.reasoning, b.output.reasoning) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.output.audio, b.output.audio) !== undefined && {\n\t\t\t\taudio: addOptional(a.output.audio, b.output.audio) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.output.predictionAccepted, b.output.predictionAccepted) !== undefined && {\n\t\t\t\tpredictionAccepted: addOptional(\n\t\t\t\t\ta.output.predictionAccepted,\n\t\t\t\t\tb.output.predictionAccepted,\n\t\t\t\t) as number,\n\t\t\t}),\n\t\t\t...(addOptional(a.output.predictionRejected, b.output.predictionRejected) !== undefined && {\n\t\t\t\tpredictionRejected: addOptional(\n\t\t\t\t\ta.output.predictionRejected,\n\t\t\t\t\tb.output.predictionRejected,\n\t\t\t\t) as number,\n\t\t\t}),\n\t\t\t...(addExtensions(a.output.extensions, b.output.extensions) !== undefined && {\n\t\t\t\textensions: addExtensions(a.output.extensions, b.output.extensions) as Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tnumber\n\t\t\t\t>,\n\t\t\t}),\n\t\t},\n\t\t...(addExtensions(a.auxiliary, b.auxiliary) !== undefined && {\n\t\t\tauxiliary: addExtensions(a.auxiliary, b.auxiliary) as Record<string, number>,\n\t\t}),\n\t};\n\treturn out;\n}\n\n/**\n * Spec for {@link agent} (in `./agents.ts`). Required fields are minimal —\n * `name` and `adapter` cover the common case where the input is a string\n * and the output is the raw `LLMResponse`. Optional fields shape the\n * agent's behavior:\n *\n * - **Mappers** (`inMapper` / `outMapper`) translate between caller-typed\n * `TIn` / `TOut` and the loop's internal `string` / `LLMResponse`. Default\n * identity mappers are wired automatically when `TIn` extends `string`\n * and `TOut` extends `LLMResponse`.\n * - **`tools`** is a reactive `NodeInput<readonly ToolDefinition[]>` —\n * `agent()` subscribes and reconciles the underlying `toolRegistry`'s\n * registrations on each emit. Static-array form is also accepted.\n * - **`memory`** is an explicit `AgentMemoryGraph` instance for shared\n * memory across agents (§29 handoff context transfer). Default: private\n * memory per agent (each `agent()` call mints its own).\n * - **`maxIterations`** caps the underlying agentLoop's tool-call inner\n * loop. Default 10 (matches `agentLoop`).\n * - **Verifier slot** is intentionally not in v1 — G7 reframe locks it as\n * a caller-composed recipe. When a real consumer surfaces, a\n * `verifier?: (out: Node<TOut>) => NodeInput<VerifierResult>` field\n * lands here additively.\n */\nexport interface AgentSpec<TIn, TOut> {\n\t/** Local mount name when wired to a parent graph. Required. */\n\treadonly name: string;\n\t/** LLM adapter for the underlying agentLoop. Required. */\n\treadonly adapter: LLMAdapter;\n\t/** Optional system prompt. Static today; reactive widening pending. */\n\treadonly systemPrompt?: string;\n\t/**\n\t * Optional reactive tool list. When a Node, the agent subscribes and\n\t * reconciles the underlying `toolRegistry` registrations on each emit\n\t * (additions registered, removals unregistered). When a static array,\n\t * tools are registered once at construction.\n\t */\n\treadonly tools?: Node<readonly ToolDefinition[]> | readonly ToolDefinition[];\n\t/**\n\t * Optional shared memory. Default: private (agent mints its own\n\t * `AgentMemoryGraph` if needed; not yet wired into the loop's chat —\n\t * that wiring is a separate follow-up). Pass an explicit instance to\n\t * share memory across agents for §29 handoff context transfer.\n\t */\n\treadonly memory?: AgentMemoryGraph<unknown>;\n\t/**\n\t * Maps caller-typed input → string for the underlying chat. Defaults to\n\t * identity when `TIn extends string`; required otherwise.\n\t */\n\treadonly inMapper?: (input: TIn) => string;\n\t/**\n\t * Maps the agentLoop's `LLMResponse` → caller-typed output. Defaults to\n\t * identity when `TOut extends LLMResponse`; required otherwise.\n\t */\n\treadonly outMapper?: (response: LLMResponse) => TOut;\n\t/** Caps tool-call inner-loop iterations. Default 10. */\n\treadonly maxIterations?: number;\n\t/** Escape hatch for non-core fields. Surfaced in `describe()` via meta. */\n\treadonly meta?: Record<string, unknown>;\n}\n\n/**\n * Public contract for an agent — typed inbox/outbox + lifecycle / cost\n * observables + the underlying graph for inspection / mounting.\n *\n * **Reactive entry:** caller writes to `in` (e.g. `bundle.in.emit(input)`).\n * The agent reactively kicks the underlying loop and produces `out`.\n *\n * **Reactive exit:** caller reads `out` via `subscribe` (continuous) or\n * `awaitSettled(out)` (single-shot). Both `in` and `out` stay SENTINEL\n * (`cache === undefined`) until the first real emission — no `null`\n * push-on-subscribe trap (per `feedback_use_prevdata_for_sentinel`).\n *\n * **Cross-graph wiring:** the bundle's `graph` is mountable under any\n * parent via `parent.mount(name, bundle.graph)`. After mount, the bundle's\n * Nodes are reachable through both the bundle reference (direct) and via\n * `parent.node(\"<name>::out\")` etc. (qualified path).\n */\nexport interface AgentBundle<TIn, TOut> {\n\treadonly in: Node<TIn>;\n\treadonly out: Node<TOut>;\n\treadonly status: Node<AgentStatus>;\n\treadonly cost: Node<CostState>;\n\treadonly graph: AgentGraph<TIn, TOut>;\n}\n\n// ---------------------------------------------------------------------------\n// AgentGraph\n// ---------------------------------------------------------------------------\n\nconst TERMINAL_STATUSES = new Set<AgentStatus>([\"done\", \"error\"]);\n\n/**\n * Graph subclass implementing {@link AgentBundle}. Mounts an inner\n * {@link AgentLoopGraph} at `loop/`; `in` / `out` / `status` / `cost`\n * surface the bundle contract as top-level nodes.\n *\n * Construction is internal — use the {@link agent} factory in\n * `./agents.ts` for normal use. Direct `new AgentGraph(name, spec)` is\n * supported for callers that want full control over mount order.\n *\n * **Topology:**\n * ```\n * <name>\n * ├── loop (AgentLoopGraph subgraph)\n * │ ├── chat\n * │ ├── tools\n * │ ├── status / turn / aborted / lastResponse / ...\n * ├── in (Node<TIn>, SENTINEL until first emit)\n * ├── out (Node<TOut>, SENTINEL until first response)\n * ├── status (Node<AgentStatus>, mirror of loop.status)\n * └── cost (Node<CostState>)\n * ```\n *\n * **Lifecycle:**\n * - On `in` emit: `inMapper` projects to `string`; appended to\n * `loop.chat`; loop status reset (`turn=0`, `aborted=false`,\n * `status=\"thinking\"`); per-input cost counters reset to zero.\n * - On `loop.lastResponse` emit: cost rolls forward; `out` emits\n * `outMapper(response)`.\n * - On `loop.status=\"done\"`: agent's status emits `\"done\"`.\n * - On `loop.status=\"error\"` (or any ERROR propagation): agent's status\n * emits `\"error\"`.\n */\nexport class AgentGraph<TIn, TOut> extends Graph {\n\t/** The agent's typed inbox. Writable; `in.emit(value)` kicks the loop. */\n\treadonly in: Node<TIn>;\n\t/** The agent's typed outbox. SENTINEL until first response. */\n\treadonly out: Node<TOut>;\n\t/** Lifecycle status (translated from the underlying loop's substates). */\n\treadonly status: Node<AgentStatus>;\n\t/** Cumulative cost for the current / most-recent input. */\n\treadonly cost: Node<CostState>;\n\t/** The underlying agentLoop — exposed for inspection / advanced wiring. */\n\treadonly loop: AgentLoopGraph;\n\t/** Optional shared memory subgraph (mounted at `memory/` if provided). */\n\treadonly memory: AgentMemoryGraph<unknown> | null;\n\n\tconstructor(spec: AgentSpec<TIn, TOut>, opts?: GraphOptions) {\n\t\tsuper(spec.name, opts);\n\n\t\t// --- 1. Mount the agentLoop subgraph. ------------------------------\n\t\tconst initialTools = Array.isArray(spec.tools)\n\t\t\t? (spec.tools as readonly ToolDefinition[])\n\t\t\t: undefined;\n\t\tthis.loop = agentLoop(`${spec.name}-loop`, {\n\t\t\tadapter: spec.adapter,\n\t\t\t...(spec.systemPrompt != null ? { systemPrompt: spec.systemPrompt } : {}),\n\t\t\t...(initialTools != null ? { tools: initialTools } : {}),\n\t\t\t...(spec.maxIterations != null ? { maxTurns: spec.maxIterations } : {}),\n\t\t});\n\t\tthis.mount(\"loop\", this.loop);\n\n\t\t// --- 2. Reactive tools subscription (if Node-form). ----------------\n\t\t// agentLoop's tools are static-array at construction; we reconcile\n\t\t// dynamically by subscribing to the user's reactive Node and\n\t\t// register/unregister against the inner toolRegistry.\n\t\tif (spec.tools != null && !Array.isArray(spec.tools)) {\n\t\t\tconst toolsNode = spec.tools as Node<readonly ToolDefinition[]>;\n\t\t\tconst registered = new Set<string>();\n\t\t\tconst unsubTools = toolsNode.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 next = m[1] as readonly ToolDefinition[];\n\t\t\t\t\tconst nextNames = new Set(next.map((t) => t.name));\n\t\t\t\t\t// Unregister missing.\n\t\t\t\t\tfor (const name of registered) {\n\t\t\t\t\t\tif (!nextNames.has(name)) {\n\t\t\t\t\t\t\tthis.loop.tools.unregister(name);\n\t\t\t\t\t\t\tregistered.delete(name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Register new (idempotent guard via local tracking).\n\t\t\t\t\tfor (const tool of next) {\n\t\t\t\t\t\tif (!registered.has(tool.name)) {\n\t\t\t\t\t\t\tthis.loop.tools.register(tool);\n\t\t\t\t\t\t\tregistered.add(tool.name);\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(unsubTools);\n\t\t}\n\n\t\t// --- 3. Optional shared memory subgraph (passed through). ----------\n\t\t// v1: memory is mounted but NOT yet wired into the loop's chat — the\n\t\t// chat-context-from-memory glue is a separate follow-up. Mounting it\n\t\t// here gives the bundle a stable surface for §29 handoff (callers\n\t\t// can pass the SAME instance to multiple agents for shared memory).\n\t\tthis.memory = spec.memory ?? null;\n\t\tif (this.memory != null) {\n\t\t\tthis.mount(\"memory\", this.memory);\n\t\t}\n\n\t\t// --- 4. `in` — the typed inbox. ------------------------------------\n\t\t// SENTINEL until first emit; `equals: () => false` so re-emitting the\n\t\t// same value still kicks (no spurious dedup of repeat inputs).\n\t\tthis.in = node<TIn>([], {\n\t\t\tname: \"in\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_in\"),\n\t\t\tequals: () => false,\n\t\t});\n\t\tthis.add(this.in, { name: \"in\" });\n\n\t\t// --- 5. `cost` — per-input token counters. -------------------------\n\t\tconst costNode = node<CostState>([], {\n\t\t\tname: \"cost\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_cost\"),\n\t\t\tinitial: ZERO_COST,\n\t\t});\n\t\tthis.add(costNode, { name: \"cost\" });\n\t\tthis.cost = costNode;\n\n\t\t// --- 6. `out` — the typed outbox. ----------------------------------\n\t\t// Derived from `loop.lastResponse`. SENTINEL while `loop.lastResponse`\n\t\t// has never emitted a real response (F9 fix: the loop now stays\n\t\t// SENTINEL too — no more eager `null` placeholder), so the SENTINEL\n\t\t// detector inside the fn is `prevData[0] === undefined`. Between\n\t\t// runs, `loop.lastResponse.down([[INVALIDATE]])` clears that\n\t\t// `prevData` slot back to undefined, so this derived correctly gates\n\t\t// to RESOLVED on the next status=\"idle\" wave.\n\t\tconst outMapper = spec.outMapper ?? defaultOutMapper<TOut>();\n\t\tconst outNode = node<TOut>(\n\t\t\t[this.loop.lastResponse],\n\t\t\t(data, a, ctx) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tconst resp =\n\t\t\t\t\tbatch0 != null && batch0.length > 0\n\t\t\t\t\t\t? (batch0.at(-1) as LLMResponse | undefined)\n\t\t\t\t\t\t: (ctx.prevData[0] as LLMResponse | undefined);\n\t\t\t\tif (resp === undefined) {\n\t\t\t\t\ta.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ta.emit(outMapper(resp));\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"out\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: aiMeta(\"agent_out\"),\n\t\t\t\t// Each in.emit may produce a structurally-equal response (e.g.\n\t\t\t\t// from a deterministic adapter) — disable framework dedup so\n\t\t\t\t// repeat emits propagate and `awaitSettled({skipCurrent:true})`\n\t\t\t\t// sees them. Callers can wrap with `distinctUntilChanged` if\n\t\t\t\t// they want change-only semantics.\n\t\t\t\tequals: () => false,\n\t\t\t},\n\t\t);\n\t\tthis.add(outNode, { name: \"out\" });\n\t\tthis.out = outNode;\n\n\t\t// --- 7. `status` — translated from loop.status. --------------------\n\t\t// Mirror via §32 pattern: a state node downstream consumers depend on,\n\t\t// reset and updated by an effect listening to loop.status.\n\t\tconst statusNode = node<AgentStatus>([], {\n\t\t\tname: \"status\",\n\t\t\tdescribeKind: \"state\",\n\t\t\tmeta: aiMeta(\"agent_status\"),\n\t\t\tinitial: \"idle\",\n\t\t});\n\t\tthis.add(statusNode, { name: \"status\" });\n\t\tthis.status = statusNode;\n\n\t\tconst statusMirrorEff = node(\n\t\t\t[this.loop.status],\n\t\t\t(data, _a, ctx) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tconst loopStatus =\n\t\t\t\t\tbatch0 != null && batch0.length > 0\n\t\t\t\t\t\t? (batch0.at(-1) as string)\n\t\t\t\t\t\t: ((ctx.prevData[0] as string | undefined) ?? \"idle\");\n\t\t\t\tconst next: AgentStatus =\n\t\t\t\t\tloopStatus === \"idle\"\n\t\t\t\t\t\t? \"idle\"\n\t\t\t\t\t\t: loopStatus === \"thinking\" || loopStatus === \"acting\"\n\t\t\t\t\t\t\t? \"running\"\n\t\t\t\t\t\t\t: loopStatus === \"done\"\n\t\t\t\t\t\t\t\t? \"done\"\n\t\t\t\t\t\t\t\t: loopStatus === \"error\"\n\t\t\t\t\t\t\t\t\t? \"error\"\n\t\t\t\t\t\t\t\t\t: \"idle\";\n\t\t\t\tif (statusNode.cache !== next) statusNode.emit(next);\n\t\t\t},\n\t\t\t{ describeKind: \"effect\", meta: aiMeta(\"agent_status_mirror\") },\n\t\t);\n\t\tthis.addDisposer(keepalive(statusMirrorEff));\n\n\t\t// --- 8. Cost-rollup effect. ---------------------------------------\n\t\t// Rolls forward on each loop.lastResponse emission. Reads\n\t\t// loop.turn.cache for the iteration count (sole-owner-reactive-reader\n\t\t// per Phase 12 D1 lock — loop is mounted as a subgraph of this Graph).\n\t\t// SENTINEL gate: `prevData[0] === undefined` means no response has\n\t\t// ever been delivered for this run (post-INVALIDATE reset between\n\t\t// runs), so the rollup short-circuits.\n\t\tconst costEff = node(\n\t\t\t[this.loop.lastResponse],\n\t\t\t(data, _a, ctx) => {\n\t\t\t\tconst batch0 = data[0];\n\t\t\t\tconst resp =\n\t\t\t\t\tbatch0 != null && batch0.length > 0\n\t\t\t\t\t\t? (batch0.at(-1) as LLMResponse | undefined)\n\t\t\t\t\t\t: (ctx.prevData[0] as LLMResponse | undefined);\n\t\t\t\tif (resp === undefined) return;\n\t\t\t\tconst prev = (costNode.cache as CostState | undefined) ?? ZERO_COST;\n\t\t\t\tconst turns = (this.loop.turn.cache as number | undefined) ?? prev.turns;\n\t\t\t\tconst next: CostState = {\n\t\t\t\t\tusage: resp.usage != null ? addUsage(prev.usage, resp.usage) : prev.usage,\n\t\t\t\t\tturns,\n\t\t\t\t};\n\t\t\t\tcostNode.emit(next);\n\t\t\t},\n\t\t\t{ describeKind: \"effect\", meta: aiMeta(\"agent_cost_rollup\") },\n\t\t);\n\t\tthis.addDisposer(keepalive(costEff));\n\n\t\t// --- 9. `in` → input queue → drain → kick the loop. ----------------\n\t\t// Phase 13.G/H + /qa N1(b) lock (2026-05-01): bundle.in is a\n\t\t// writable surface, but kicks are queued through an internal\n\t\t// hub-style topic + cursor subscription. Out-of-the-box queueing —\n\t\t// caller fires `in.emit(x)` while the agent is mid-run; the input\n\t\t// is parked on the queue and picked up when the loop returns to\n\t\t// `idle` / `done` / `error`. No mid-run reset / cost-leak hazard\n\t\t// (which the prior raw `in.subscribe → kick` path had).\n\t\t//\n\t\t// Topology:\n\t\t// `in` (state Node, writable) → `inputBridge` (subscribe →\n\t\t// publish) → `inputTopic` (TopicGraph<TIn>) → `inputSub`\n\t\t// (SubscriptionGraph<TIn>) → `drainEffect` (effect on\n\t\t// [inputSub.available, loop.status]) → loop kick.\n\t\tconst inMapper = spec.inMapper ?? defaultInMapper<TIn>();\n\t\tconst inputTopic: TopicGraph<TIn> = topic<TIn>(\"input-topic\");\n\t\tthis.mount(\"input-topic\", inputTopic);\n\t\tconst inputSub: SubscriptionGraph<TIn> = subscription<TIn>(\"input-sub\", inputTopic, {\n\t\t\tfrom: \"now\",\n\t\t});\n\t\tthis.mount(\"input-sub\", inputSub);\n\n\t\t// Bridge: `in.emit(x)` publishes to the topic. Validates the\n\t\t// caller-supplied input via `inMapper` at the boundary so the\n\t\t// type error surfaces in the caller's stack frame (not later\n\t\t// during drain). Per the F9 SENTINEL trap, `in` cache is\n\t\t// `undefined` until the first emit; push-on-subscribe delivers\n\t\t// nothing.\n\t\tconst inputBridge = this.in.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tconst input = m[1] as TIn;\n\t\t\t\t// Boundary type-check: throws if TIn is not string and no\n\t\t\t\t// inMapper supplied. Better here than at drain time so the\n\t\t\t\t// caller's `in.emit(...)` raises synchronously.\n\t\t\t\tinMapper(input);\n\t\t\t\tinputTopic.publish(input);\n\t\t\t}\n\t\t});\n\t\tthis.addDisposer(inputBridge);\n\n\t\t// Drain effect: when an input is pending AND the loop is ready\n\t\t// (`idle` / `done` / `error`), pull one and kick. Re-entrancy\n\t\t// guard via `loop.status` — `thinking` / `acting` skip.\n\t\tconst drainEffect = node(\n\t\t\t[inputSub.available, this.loop.status],\n\t\t\t(data, _a, ctx) => {\n\t\t\t\tconst availBatch = data[0];\n\t\t\t\tconst statusBatch = data[1];\n\t\t\t\tconst avail =\n\t\t\t\t\t(availBatch != null && availBatch.length > 0\n\t\t\t\t\t\t? (availBatch.at(-1) as readonly TIn[])\n\t\t\t\t\t\t: ((ctx.prevData[0] as readonly TIn[] | undefined) ?? [])) ?? [];\n\t\t\t\tconst stat =\n\t\t\t\t\t(statusBatch != null && statusBatch.length > 0\n\t\t\t\t\t\t? (statusBatch.at(-1) as string)\n\t\t\t\t\t\t: ((ctx.prevData[1] as string | undefined) ?? \"idle\")) ?? \"idle\";\n\t\t\t\tif (avail.length === 0) return;\n\t\t\t\tif (stat === \"thinking\" || stat === \"acting\") return;\n\t\t\t\tconst result = inputSub.pullAndAck(1);\n\t\t\t\tif (result.items.length === 0) return;\n\t\t\t\tconst input = result.items[0] as TIn;\n\t\t\t\tconst userMsg = inMapper(input);\n\t\t\t\tbatch(() => {\n\t\t\t\t\t// Reset per-input accumulators so cost/turns don't include\n\t\t\t\t\t// the previous input. `lastResponse` is reset via plain\n\t\t\t\t\t// `[[INVALIDATE]]` — under DS-13.5.A INVALIDATE both clears\n\t\t\t\t\t// `_cached` AND settles the consuming wave (decrements\n\t\t\t\t\t// `_dirtyDepCount` like RESOLVED), so dependents like\n\t\t\t\t\t// `out` / `costEff` fire on the next status transition\n\t\t\t\t\t// without staying wedged in DIRTY. Pre-DS-13.5.A this used\n\t\t\t\t\t// the `[[INVALIDATE], [RESOLVED]]` paired-reset workaround.\n\t\t\t\t\tthis.loop.lastResponse.down([[INVALIDATE]]);\n\t\t\t\t\tthis.loop.turn.emit(0);\n\t\t\t\t\tthis.loop.aborted.emit(false);\n\t\t\t\t\tcostNode.emit(ZERO_COST);\n\t\t\t\t\tthis.loop.chat.append(\"user\", userMsg);\n\t\t\t\t\tthis.loop.status.emit(\"thinking\");\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ describeKind: \"effect\", meta: aiMeta(\"agent_input_drain\") },\n\t\t);\n\t\tthis.addDisposer(keepalive(drainEffect));\n\n\t\t// `out` and `status` keepalives are unnecessary because the cost /\n\t\t// status effects above already activate `loop.lastResponse` and\n\t\t// `loop.status` — the derived `out` reads from a kept-alive source.\n\t\t// We do keep `out` alive explicitly so `awaitSettled(bundle.out,\n\t\t// { skipCurrent: true })` works even when no other consumer\n\t\t// subscribes between input and response.\n\t\tthis.addDisposer(keepalive(this.out));\n\n\t\t// Surface in describe.\n\t\tvoid TERMINAL_STATUSES;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Default mappers\n// ---------------------------------------------------------------------------\n\n/**\n * Default `inMapper` for `TIn extends string`. Asserts the runtime type at\n * the boundary so callers who omit `inMapper` for a non-string `TIn` get a\n * clear error rather than a silent passthrough.\n */\nfunction defaultInMapper<TIn>(): (input: TIn) => string {\n\treturn (input) => {\n\t\tif (typeof input !== \"string\") {\n\t\t\tthrow new TypeError(\n\t\t\t\t`agent: inMapper is required when TIn is not a string (got ${typeof input}). Pass spec.inMapper.`,\n\t\t\t);\n\t\t}\n\t\treturn input;\n\t};\n}\n\n/**\n * Default `outMapper` for `TOut extends LLMResponse`. Asserts the response\n * shape at the boundary; callers with a non-LLMResponse `TOut` must\n * provide `outMapper`.\n */\nfunction defaultOutMapper<TOut>(): (response: LLMResponse) => TOut {\n\treturn (response) => response as unknown as TOut;\n}\n","/**\n * Composable safety layer (roadmap §9.0b — Tier 5.1 Wave-B rebuild).\n *\n * {@link guardedExecution} wraps any {@link Graph} with:\n *\n * - {@link policyGate} — reactive ABAC (Tier 2.3 rename of `policyEnforcer`),\n * policies stored as a `Node` so LLMs / humans can update them at runtime.\n * Full transitive dynamic coverage via `watchTopologyTree`.\n * - Reactive {@link GuardedExecutionGraph.scopedDescribeNode} — a thin\n * delegate over `target.describe({ reactive: true, actor })` that re-derives\n * on every settle (topology change, error transition, actor swap).\n * - The enforcer's `violations` topic is republished as `violations` on\n * the wrapper, composable with {@link graphLens}'s `health`.\n * - The wrapper-level `lints` topic surfaces non-policy diagnostic warnings\n * (`empty-policies` / `audit-no-effect` / `no-actor`) so misconfigurations\n * are caught reactively rather than via thrown errors at scattered call sites.\n * - The `scope` derived publishes the current configuration tuple\n * (`{actor, mode, policiesCount}`) for dashboards.\n *\n * V1 scope: policies + actor + reactive scoped describe + lints + scope.\n * Budget-as-option is NOT in V1 — it requires a cost-tracking design that\n * hasn't landed yet. Callers who need a budget limit today append a\n * budget-aware {@link PolicyRuleData} to the policies list (check current\n * cost and `deny` when exhausted).\n *\n * @module\n */\nimport type { Actor, PolicyRuleData } from \"@graphrefly/pure-ts/core\";\nimport { DATA, monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { keepalive } from \"@graphrefly/pure-ts/extra\";\nimport {\n\ttype DescribeFilter,\n\tGraph,\n\ttype GraphDescribeOptions,\n\ttype GraphDescribeOutput,\n\ttype GraphOptions,\n} from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport {\n\ttype PolicyGateGraph,\n\ttype PolicyViolation,\n\tpolicyGate,\n} from \"../../utils/inspect/audit.js\";\nimport { TopicGraph } from \"../../utils/messaging/index.js\";\n\nfunction isNode<T>(x: unknown): x is Node<T> {\n\treturn (\n\t\ttypeof x === \"object\" && x !== null && \"subscribe\" in (x as object) && \"down\" in (x as object)\n\t);\n}\n\nfunction guardedMeta(kind: string): Record<string, unknown> {\n\treturn domainMeta(\"guarded\", kind);\n}\n\n/** Diagnostic warning published on {@link GuardedExecutionGraph.lints}. */\nexport interface GuardedExecutionLint {\n\t/**\n\t * - `\"empty-policies\"` — `policies` Node emitted an empty array in\n\t * `mode: \"enforce\"`. Static empty arrays throw at construction; this\n\t * covers the reactive case.\n\t * - `\"audit-no-effect\"` — `mode: \"audit\"` plus the target has no per-node\n\t * guards, so `scopedDescribeNode` filters by per-node guards only and\n\t * policies will never gate visibility (they still populate `violations`\n\t * on writes).\n\t * - `\"no-actor\"` — neither a wrapper-configured nor per-call actor was\n\t * supplied. `scopedDescribeNode` falls back to \"describe everything\"\n\t * for the corresponding subscription.\n\t */\n\tkind: \"empty-policies\" | \"audit-no-effect\" | \"no-actor\";\n\tmessage: string;\n\ttimestamp_ns: number;\n}\n\n/** Configuration tuple published on {@link GuardedExecutionGraph.scope}. */\nexport interface GuardedScope {\n\t/** The wrapper-configured default actor, or `null` when none configured. */\n\tactor: Actor | null;\n\tmode: \"audit\" | \"enforce\";\n\t/** Current policy count (reactive — re-emits on `policies` Node updates). */\n\tpoliciesCount: number;\n}\n\n/** Options for {@link guardedExecution}. */\nexport interface GuardedExecutionOptions {\n\t/**\n\t * Policies enforced against every guarded write. Static list or a live\n\t * `Node<readonly PolicyRuleData[]>` (LLM-updatable).\n\t *\n\t * **Empty-policies handling:**\n\t * - Static empty array + `mode: \"enforce\"` throws `RangeError` at\n\t * construction (deny-by-default is almost certainly a misconfiguration).\n\t * - Node-supplied empty array + `mode: \"enforce\"` emits a one-time\n\t * `\"empty-policies\"` lint on first such emission (the wrapper can't\n\t * throw mid-run — surface the warning reactively).\n\t * - `mode: \"audit\"` tolerates empty policies (no guards stacked; policies\n\t * only feed the `violations` channel on writes).\n\t */\n\tpolicies: readonly PolicyRuleData[] | Node<readonly PolicyRuleData[]>;\n\t/**\n\t * Default actor used when the caller invokes\n\t * {@link GuardedExecutionGraph.scopedDescribeNode} without an override.\n\t * Accepts a static {@link Actor} or a `Node<Actor>` — when a Node is\n\t * supplied, the reactive describe re-derives on every actor emission so\n\t * harnesses binding a per-turn actor get a single live describe Node\n\t * instead of re-creating one per turn.\n\t *\n\t * Omit to scope per-call only. A `\"no-actor\"` lint fires once per instance\n\t * if neither a configured nor per-call actor is ever supplied (the\n\t * resulting describe is unscoped — full visibility).\n\t */\n\tactor?: Actor | Node<Actor>;\n\t/**\n\t * `\"enforce\"` (default) — push guards onto target nodes so disallowed\n\t * writes throw {@link GuardDenied}.\n\t * `\"audit\"` — record would-be denials to the `violations` topic without\n\t * blocking writes.\n\t */\n\tmode?: \"audit\" | \"enforce\";\n\t/** Ring-buffer cap for the `violations` topic. Default 1000 (inherited from policyGate). */\n\tviolationsLimit?: number;\n\t/** Ring-buffer cap for the `lints` topic. Default 64 — each lint kind fires at most once per instance. */\n\tlintsLimit?: number;\n\t/** Wrapper graph name. Default `${target.name}_guarded`. */\n\tname?: string;\n\t/** Wrapper graph options. */\n\tgraph?: GraphOptions;\n}\n\n/**\n * Wrapper over a target {@link Graph} providing reactive ABAC + reactive\n * scoped describe + diagnostic lints. Mounts a {@link PolicyGateGraph} under\n * `enforcer`, a {@link TopicGraph} of {@link GuardedExecutionLint} under\n * `lints`, and a `scope` derived publishing `{actor, mode, policiesCount}`.\n *\n * @category patterns\n */\nexport class GuardedExecutionGraph extends Graph {\n\treadonly enforcer: PolicyGateGraph;\n\treadonly violations: TopicGraph<PolicyViolation>;\n\treadonly lints: TopicGraph<GuardedExecutionLint>;\n\treadonly scope: Node<GuardedScope>;\n\t/**\n\t * Canonical reactive describe scoped to the wrapper's configured `actor`.\n\t * Subscribes ONCE at construction; lifecycle owned by the wrapper (disposed\n\t * on `wrapper.destroy()`). Use this property for the common case\n\t * (long-lived consumer wanting \"describe scoped to my actor\"); use\n\t * {@link scopedDescribeNode} only when a per-call actor override or\n\t * different `detail`/`fields` is required.\n\t *\n\t * Re-derives on every settle of the target graph: structural changes,\n\t * status transitions (errors flip nodes into `\"errored\"`), and actor\n\t * emissions (when a `Node<Actor>` is bound, including the SENTINEL bridge\n\t * applied internally — see qa G1B).\n\t */\n\treadonly scopedDescribe: Node<GraphDescribeOutput>;\n\tprivate readonly _target: Graph;\n\tprivate readonly _actorNode: Node<Actor | null>;\n\tprivate readonly _mode: \"audit\" | \"enforce\";\n\tprivate readonly _firedLintKinds = new Set<GuardedExecutionLint[\"kind\"]>();\n\n\tconstructor(target: Graph, opts: GuardedExecutionOptions) {\n\t\tsuper(opts.name ?? `${target.name}_guarded`, opts.graph);\n\t\tthis._target = target;\n\t\tthis._mode = opts.mode ?? \"enforce\";\n\n\t\tconst policiesOpt = opts.policies;\n\t\tconst policiesIsNode = isNode<readonly PolicyRuleData[]>(policiesOpt);\n\t\t// Static empty + enforce → throw (deny-by-default = misconfig).\n\t\tif (\n\t\t\t!policiesIsNode &&\n\t\t\tthis._mode === \"enforce\" &&\n\t\t\t(policiesOpt as readonly PolicyRuleData[]).length === 0\n\t\t) {\n\t\t\tthrow new RangeError(\n\t\t\t\t'guardedExecution: empty `policies` in `mode: \"enforce\"` denies every action. ' +\n\t\t\t\t\t'Pass at least `{ effect: \"allow\", action: \"*\" }` and layer deny rules on top.',\n\t\t\t);\n\t\t}\n\n\t\t// Lints topic — mounted before any potential first-DATA emission.\n\t\tthis.lints = new TopicGraph<GuardedExecutionLint>(\"lints\", {\n\t\t\tretainedLimit: opts.lintsLimit ?? 64,\n\t\t});\n\t\tthis.mount(\"lints\", this.lints);\n\n\t\t// Normalize `actor` to a Node<Actor | null>. `null` (a valid DATA in\n\t\t// the v5 sentinel-as-undefined model) means \"no actor configured\" —\n\t\t// `target.describe({ reactive: true })`'s `resolveActorOption` treats\n\t\t// `null` cache as \"no scoping\" (full visibility), and the `scope`\n\t\t// derived can publish `actor: null` cleanly. Using `node([], { initial: undefined })`\n\t\t// here would leave the actor node in sentinel state, which never fires\n\t\t// DATA on subscribe and would block the `scope` derived's first-run\n\t\t// gate from completing.\n\t\t//\n\t\t// qa G1B (EC2 fix): when the caller passes a `Node<Actor>`, that node's\n\t\t// cache may itself be SENTINEL at construction (e.g. a `producer`\n\t\t// awaiting first emission, or a deferred `derived`). Forwarding the raw\n\t\t// Node would re-introduce the same sentinel-stall on `scope`. Bridge\n\t\t// through a node bridge with a `null` initial so the\n\t\t// internal `_actorNode` always carries non-sentinel cache; the bridge\n\t\t// re-emits whenever the caller's Node emits, and forwards `null`\n\t\t// through unchanged.\n\t\tconst actorOpt = opts.actor;\n\t\tif (actorOpt == null) {\n\t\t\tthis._actorNode = node<Actor | null>([], { name: \"actor\", initial: null });\n\t\t} else if (isNode<Actor>(actorOpt)) {\n\t\t\tthis._actorNode = node<Actor | null>(\n\t\t\t\t[actorOpt],\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] as Actor | null | undefined) ?? null);\n\t\t\t\t},\n\t\t\t\t{ describeKind: \"derived\", name: \"actor\", initial: null },\n\t\t\t);\n\t\t} else {\n\t\t\tthis._actorNode = node<Actor | null>([], { name: \"actor\", initial: actorOpt });\n\t\t}\n\n\t\t// Mount the enforcer.\n\t\tconst enforcerOpts: { mode: \"audit\" | \"enforce\"; name: string; violationsLimit?: number } = {\n\t\t\tmode: this._mode,\n\t\t\tname: \"enforcer\",\n\t\t};\n\t\tif (opts.violationsLimit != null) enforcerOpts.violationsLimit = opts.violationsLimit;\n\t\tthis.enforcer = policyGate(target, opts.policies, enforcerOpts);\n\t\tthis.violations = this.enforcer.violations;\n\t\tthis.mount(\"enforcer\", this.enforcer);\n\n\t\t// Empty-policies one-time lint (Node form, enforce mode only).\n\t\tif (policiesIsNode && this._mode === \"enforce\") {\n\t\t\tconst policiesNode = policiesOpt as Node<readonly PolicyRuleData[]>;\n\t\t\t// Two paths here intentionally:\n\t\t\t// (1) Synchronous cache seed — fires immediately if the Node was\n\t\t\t// constructed with an empty array as its current cache. This\n\t\t\t// covers `node<…[]>([], { initial: [] })` and any pre-emitted derived.\n\t\t\t// (2) Subscribe path — catches subsequent empty emissions AND\n\t\t\t// handles the SENTINEL case (cache=undefined at construction)\n\t\t\t// where the Node fires its first DATA after the wrapper is\n\t\t\t// built. The `_firedLintKinds` Set keeps the lint one-shot\n\t\t\t// across both paths.\n\t\t\t// qa F6 (deferred): if a Node's initial cache is SENTINEL (undefined)\n\t\t\t// AND it never emits an empty array (only ever non-empty), the lint\n\t\t\t// never fires — that's correct behavior, the configuration is\n\t\t\t// effectively non-empty for the wrapper's lifetime.\n\t\t\tconst cached = policiesNode.cache as readonly PolicyRuleData[] | undefined;\n\t\t\tif (cached != null && cached.length === 0) {\n\t\t\t\tthis._fireLint(\n\t\t\t\t\t\"empty-policies\",\n\t\t\t\t\t'`policies` Node cached an empty array in `mode: \"enforce\"` — every action will be denied. Add at least one allow rule.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst offEmpty = policiesNode.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 v = m[1] as readonly PolicyRuleData[] | undefined;\n\t\t\t\t\tif (v == null || v.length === 0) {\n\t\t\t\t\t\tthis._fireLint(\n\t\t\t\t\t\t\t\"empty-policies\",\n\t\t\t\t\t\t\t'`policies` Node emitted an empty array in `mode: \"enforce\"` — every action will be denied. Add at least one allow rule.',\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(offEmpty);\n\t\t}\n\n\t\t// Audit-mode + no per-node guards on the target → fire once.\n\t\t// qa EC5 (deferred): the check is one-shot at construction. If the\n\t\t// caller later mounts a guarded node into the target, the lint stays\n\t\t// retained even though the configuration is now effective. Recommended\n\t\t// pattern: mount per-node guards on the target BEFORE wrapping.\n\t\t// Reactive recompute (subscribe to target.topology, clear lint when a\n\t\t// guard appears) is filed in `docs/optimizations.md` as a follow-up.\n\t\tif (this._mode === \"audit\") {\n\t\t\tconst described = target.describe({ detail: \"full\" });\n\t\t\tconst anyGuard = Object.values(described.nodes).some((n) => n.guard != null);\n\t\t\tif (!anyGuard) {\n\t\t\t\tthis._fireLint(\n\t\t\t\t\t\"audit-no-effect\",\n\t\t\t\t\t'`mode: \"audit\"` + target has no per-node guards — `scopedDescribeNode` filters by per-node guards only, so policy rules will not affect describe() visibility. Policies still populate the `violations` topic on writes.',\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// No-actor lint: fires at construction when neither configured nor\n\t\t// implicitly carried via a Node-cache. Per-call overrides on\n\t\t// `scopedDescribeNode` cannot retroactively suppress this — the\n\t\t// configured-default branch is what callers most often miss.\n\t\tif (actorOpt == null) {\n\t\t\tthis._fireLint(\n\t\t\t\t\"no-actor\",\n\t\t\t\t\"no actor configured — `wrapper.scopedDescribe` and `scopedDescribeNode()` will return an unscoped describe (full visibility) unless a per-call actor is supplied.\",\n\t\t\t);\n\t\t}\n\n\t\t// Scope derived: live tuple of {actor, mode, policiesCount}.\n\t\tthis.scope = node<GuardedScope>(\n\t\t\t[this._actorNode, this.enforcer.policies],\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({\n\t\t\t\t\tactor: (data[0] as Actor | null | undefined) ?? null,\n\t\t\t\t\tmode: this._mode,\n\t\t\t\t\tpoliciesCount: (data[1] as readonly PolicyRuleData[]).length,\n\t\t\t\t});\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"scope\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: guardedMeta(\"scope\"),\n\t\t\t},\n\t\t);\n\t\tthis.add(this.scope, { name: \"scope\" });\n\t\tthis.addDisposer(keepalive(this.scope));\n\n\t\t// qa G1A \"same concept\": single canonical reactive describe bound to\n\t\t// the configured actor, mounted once at construction. Removes the\n\t\t// per-call handle proliferation from the prior `scopedDescribeNode`\n\t\t// pattern (the method is retained as the per-call escape hatch). The\n\t\t// reactive describe re-derives on actor swap / topology change /\n\t\t// status transition; lifecycle owned by the wrapper.\n\t\tconst scopedHandle = target.describe({\n\t\t\treactive: true,\n\t\t\t// F8 (Tier 5.2): `_actorNode` is `Node<Actor | null>`. The cast is\n\t\t\t// safe at runtime per the `resolveActorOption` null-tolerance\n\t\t\t// contract — `null` / `undefined` cache is treated as \"no scoping\"\n\t\t\t// (full visibility). See `scopedDescribeNode` for the matching\n\t\t\t// per-call site and graph.ts § \"Cache-undefined semantics\".\n\t\t\tactor: this._actorNode as Node<Actor>,\n\t\t\treactiveName: \"scopedDescribe\",\n\t\t});\n\t\tthis.scopedDescribe = scopedHandle.node;\n\t\tthis.add(this.scopedDescribe, { name: \"scopedDescribe\" });\n\t\tthis.addDisposer(scopedHandle.dispose);\n\t}\n\n\tprivate _fireLint(kind: GuardedExecutionLint[\"kind\"], message: string): void {\n\t\tif (this._firedLintKinds.has(kind)) return;\n\t\tthis._firedLintKinds.add(kind);\n\t\tthis.lints.publish({ kind, message, timestamp_ns: monotonicNs() });\n\t}\n\n\t/**\n\t * **Per-call escape hatch.** Prefer {@link scopedDescribe} (the mounted\n\t * property) for the common case of \"describe scoped to my actor.\" Use\n\t * this method ONLY when you need a per-call actor override or different\n\t * `detail`/`fields`/`filter`.\n\t *\n\t * Returns a live `Node<GraphDescribeOutput>` scoped to the supplied (or\n\t * configured) actor, plus an explicit `dispose` for caller-controlled\n\t * lifecycle. Re-derives on every settle of the target graph: structural\n\t * changes, status transitions, and actor emissions (when a `Node<Actor>`\n\t * is bound).\n\t *\n\t * **Lifecycle (qa G1A — EC1 fix).** Each call instantiates a fresh\n\t * `target.describe({reactive: true})` handle (with its own version state,\n\t * observe handle, transitive topology subscriptions, derived + keepalive).\n\t * The caller MUST invoke the returned `dispose()` when finished to release\n\t * these resources. Disposers ARE also tracked on the wrapper graph so\n\t * `wrapper.destroy()` cleans up any handles the caller forgot — but a\n\t * long-lived wrapper with heavy per-call usage will leak until destroy\n\t * unless `dispose()` is called explicitly.\n\t *\n\t * @param actorOverride - Optional per-call override. Static {@link Actor}\n\t * or `Node<Actor>`. Omit to use the wrapper-configured default.\n\t * @param opts - Standard {@link GraphDescribeOptions} fields (`detail`,\n\t * `fields`, `filter`). `actor` / `reactive` / `reactiveName` are\n\t * controlled by the wrapper.\n\t * @returns `{node, dispose}` — `node` is the live describe Node; `dispose`\n\t * tears down the underlying reactive describe subscription idempotently.\n\t */\n\tscopedDescribeNode(\n\t\tactorOverride?: Actor | Node<Actor>,\n\t\topts?: Omit<GraphDescribeOptions, \"actor\" | \"reactive\" | \"reactiveName\">,\n\t): { node: Node<GraphDescribeOutput>; dispose: () => void } {\n\t\tconst actorNode =\n\t\t\tactorOverride == null\n\t\t\t\t? this._actorNode\n\t\t\t\t: isNode<Actor>(actorOverride)\n\t\t\t\t\t? actorOverride\n\t\t\t\t\t: node<Actor>([], { name: \"actor_override\", initial: actorOverride });\n\t\tconst handle = this._target.describe({\n\t\t\treactive: true,\n\t\t\t// `_actorNode` is `Node<Actor | null>`. The `as Node<Actor>` cast is\n\t\t\t// safe at runtime: `_describeReactive` resolves the actor via\n\t\t\t// `resolveActorOption`, which treats `null`/`undefined` cache as\n\t\t\t// \"no scoping\" (full visibility). Documented in graph.ts §\n\t\t\t// \"Cache-undefined semantics.\"\n\t\t\tactor: actorNode as Node<Actor>,\n\t\t\t...(opts ?? {}),\n\t\t});\n\t\t// Track on the wrapper as a safety net for callers who forget to\n\t\t// dispose; explicit `dispose()` is still the canonical lifecycle path.\n\t\tthis.addDisposer(handle.dispose);\n\t\treturn { node: handle.node, dispose: handle.dispose };\n\t}\n\n\t/** The wrapped graph (escape hatch for tooling). */\n\tget target(): Graph {\n\t\treturn this._target;\n\t}\n}\n\n/**\n * Wrap a {@link Graph} with {@link policyGate} plus a reactive scoped describe\n * lens. Returns a {@link GuardedExecutionGraph} that can be mounted, diffed,\n * or composed with {@link graphLens}.\n *\n * @param target - The graph to guard.\n * @param opts - See {@link GuardedExecutionOptions}.\n *\n * @example\n * ```ts\n * const guarded = guardedExecution(app, {\n * actor: node<Actor>([], { initial: { type: \"human\", id: \"alice\" } }), // reactive — re-derive on swap\n * policies: [\n * { effect: \"allow\", action: \"read\", actorType: \"human\" },\n * { effect: \"deny\", action: \"write\", pathPattern: \"system::*\" },\n * ],\n * mode: \"enforce\",\n * });\n *\n * // Canonical: subscribe to the mounted reactive describe (no per-call leak).\n * guarded.scopedDescribe.subscribe((msgs) => { /* live describe per actor / topology change *\\/ });\n * // Per-call escape hatch (different actor / detail) — caller manages dispose.\n * const detailed = guarded.scopedDescribeNode(undefined, { detail: \"standard\" });\n * try { detailed.node.subscribe(/* … *\\/); } finally { detailed.dispose(); }\n * guarded.violations.events.subscribe(msgs => console.log(\"violations:\", msgs));\n * guarded.lints.events.subscribe(msgs => console.warn(\"lints:\", msgs));\n * guarded.scope.subscribe(msgs => console.log(\"scope:\", msgs));\n * ```\n *\n * @category patterns\n */\nexport function guardedExecution(\n\ttarget: Graph,\n\topts: GuardedExecutionOptions,\n): GuardedExecutionGraph {\n\treturn new GuardedExecutionGraph(target, opts);\n}\n\n// Re-export types useful for call sites.\nexport type { DescribeFilter };\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 * Resilience composition with correct nesting order (roadmap §9.0b — Tier 5.2 Wave-B rebuild).\n *\n * {@link resilientPipeline} composes the resilience primitives from\n * `extra/resilience/` in the canonical nesting order:\n *\n * ```text\n * rateLimit → budget → breaker → timeout → retry → fallback → status\n * ```\n *\n * Returns a {@link ResilientPipelineGraph} (Graph subclass) with mounted\n * intermediate nodes and per-layer status companions, replacing the prior\n * bundle return. Each intermediate is mounted under a stable name so\n * `pipeline.describe()` shows the resilience chain in topology snapshots,\n * mermaid renders, and `lens.health` aggregations.\n *\n * **Per-attempt timeout vs. retry ordering.** `timeout` is applied BEFORE\n * `retry` so each retry attempt resubscribes to a fresh deadline (per-attempt\n * semantics). If `timeout` wrapped `retry`, a single deadline would apply to\n * the entire retry chain — not what callers expect.\n *\n * **`breakerOnOpen` + `retry` interaction.** With `breakerOnOpen: \"error\"` AND\n * `retry`, retry sees `CircuitOpenError` and resubscribes; the next attempt\n * very likely also breaker-open → another error → retry burns its budget\n * against an open circuit. Either set retry's `backoff` long enough for the\n * breaker reset window OR keep the default `breakerOnOpen: \"skip\"` (emits\n * RESOLVED when open; downstream drops the beat without retry firing).\n *\n * **Reactive options (switchMap rebuild).** Every primitive option accepts a\n * `T | Node<T>` (precedent-aligned with `FallbackInput<T>`). When the caller\n * supplies a static value, the layer is built once at construction. When the\n * caller supplies a `Node<T>`, the pipeline subscribes via `switchMap` and\n * **rebuilds the layer on every option emission** — the chain stalls until\n * the option Node emits its first DATA. Each rebuild creates a fresh\n * primitive instance, so internal state is lost (rate-limiter pending buffer,\n * breaker failure count, retry attempt count, in-flight timeout). Per-layer\n * **companion Nodes** (`droppedCount`, `rateLimitState`, `breakerState`) are\n * therefore exposed ONLY for the static-options path. Primitive-side widening\n * (filed in `docs/optimizations.md` under \"Tier 5.2 follow-up — primitive-side\n * reactive-options widening\") will preserve internal state once it lands and\n * the pipeline will trivially forward Node-form options to the primitive.\n *\n * @module\n */\nimport { ERROR, type Node, node, placeholderArgs } from \"@graphrefly/pure-ts/core\";\nimport { switchMap } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport { NS_PER_MS } from \"../../base/resilience/backoff.js\";\nimport {\n\ttype BreakerState,\n\ttype BudgetConstraint,\n\tbudgetGate,\n\ttype CircuitBreakerOptions,\n\tcircuitBreaker,\n\ttype FallbackInput,\n\tfallback,\n\ttype NodeOrValue,\n\ttype RateLimiterOptions,\n\ttype RateLimiterState,\n\ttype RetryOptions,\n\ttype RetryState,\n\trateLimiter,\n\tretry,\n\ttype StatusValue,\n\ttype TimeoutOptions,\n\ttype TimeoutState,\n\twithBreaker,\n\twithStatus,\n\twithTimeout,\n} from \"../../utils/resilience/index.js\";\n\n// ---------------------------------------------------------------------------\n// Reactive-option helpers\n// ---------------------------------------------------------------------------\n\n/**\n * `T | Node<T>` for primitive options — precedent-aligned with\n * {@link FallbackInput} and `policyGate.policies`. When the caller supplies a\n * static value, the layer is built once at construction. When the caller\n * supplies a `Node<T>`, the pipeline subscribes via {@link switchMap}: the\n * layer is rebuilt on every option emission. **State-loss caveat:** each\n * rebuild creates a fresh primitive instance — `rateLimiter` loses its pending\n * buffer, `circuitBreaker` resets failure count, `retry` resets attempt\n * count, `timeout` cancels in-flight deadline. This is the documented\n * switchMap-pattern semantics; primitive-side widening (filed in\n * `docs/optimizations.md`) will preserve internal state once it lands and the\n * pipeline can forward Node-form options directly.\n *\n * Per-layer **companion Nodes** (`droppedCount`, `rateLimitState`,\n * `breakerState`) are exposed only for the static-options path — Node-form\n * leaves them as `undefined` because each rebuild creates new companion\n * instances and a switchMap-mirrored companion would track only the latest\n * bundle. Callers needing both reactive options AND companions wait for\n * primitive-side widening.\n */\n// NodeOrValue re-imported from utils/resilience (same type, avoid barrel duplicate).\n\nfunction isNode<T>(x: unknown): x is Node<T> {\n\treturn (\n\t\ttypeof x === \"object\" && x !== null && \"subscribe\" in (x as object) && \"down\" in (x as object)\n\t);\n}\n\n/**\n * Validation shared by the static and reactive timeout paths. The reactive\n * path runs this inside the `switchMap` projection so an emitted bad value\n * surfaces as a thrown error at projection time (the consuming subscribe\n * routes it through the reactive ERROR channel rather than crashing\n * construction).\n */\nfunction assertTimeoutMsValid(ms: number): void {\n\tif (ms <= 0) throw new RangeError(\"timeoutMs must be > 0\");\n\t// Guard against `timeoutMs * NS_PER_MS` overflowing\n\t// `Number.MAX_SAFE_INTEGER` (~9.007e15). 9_000_000 ms ≈ 2.5 hours is a\n\t// sane upper bound; callers needing longer deadlines should express them\n\t// at the primitive level.\n\tif (ms > 9_000_000) {\n\t\tthrow new RangeError(\n\t\t\t\"timeoutMs must be <= 9_000_000 (≈2.5h) to stay within safe ns arithmetic\",\n\t\t);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link resilientPipeline}. Every layer is optional — omit a\n * field and that layer is skipped.\n *\n * Reactive (`Node<T>`) forms are accepted everywhere a primitive value would\n * fit; the pipeline subscribes via `switchMap` and rebuilds the layer on each\n * emission. See module JSDoc for the rebuild semantics + state-loss caveat.\n */\nexport interface ResilientPipelineOptions<T> {\n\t/**\n\t * Admission control — at most `maxEvents` `DATA` per `windowNs`. See\n\t * {@link rateLimiter}.\n\t *\n\t * `maxBuffer` is optional at the pipeline layer (defaults to `Infinity`,\n\t * preserving the historical unbounded behavior). Pass an explicit positive\n\t * integer to opt in to a bounded queue.\n\t */\n\trateLimit?: NodeOrValue<Omit<RateLimiterOptions, \"maxBuffer\"> & { maxBuffer?: number }>;\n\t/** Cost/constraint gate. See {@link budgetGate}. */\n\tbudget?: NodeOrValue<ReadonlyArray<BudgetConstraint>>;\n\t/** Circuit breaker — fail-fast when the downstream resource is unhealthy. See {@link circuitBreaker}. */\n\tbreaker?: NodeOrValue<CircuitBreakerOptions>;\n\t/**\n\t * Behavior when the breaker is open:\n\t * - `\"skip\"` (default) — emit `RESOLVED` (lets downstream drop the beat).\n\t * - `\"error\"` — emit a `CircuitOpenError` so `retry` / `fallback` can react.\n\t * See module JSDoc for the retry-budget burn caveat.\n\t *\n\t * Static (configuration-only — no reactive form).\n\t */\n\tbreakerOnOpen?: \"skip\" | \"error\";\n\t/** Retry policy on terminal `ERROR`. See {@link retry}. */\n\tretry?: NodeOrValue<RetryOptions>;\n\t/**\n\t * Per-attempt deadline in milliseconds. Converted to ns internally. Omit\n\t * to skip the timeout wrap.\n\t *\n\t * Specified in ms (not ns) because callers consistently think in\n\t * millisecond deadlines; the underlying {@link timeout} primitive takes ns\n\t * internally.\n\t */\n\ttimeoutMs?: NodeOrValue<number>;\n\t/** Final fallback value emitted on terminal `ERROR` after retry exhausts. See {@link fallback}. */\n\tfallback?: FallbackInput<T>;\n\t/**\n\t * Initial status reported by the status node. Default `\"pending\"`. Static.\n\t */\n\tinitialStatus?: StatusValue;\n\t/** Wrapper graph name. Default `\"resilient_pipeline\"`. */\n\tname?: string;\n\t/** Wrapper graph options. */\n\tgraph?: GraphOptions;\n}\n\n// ---------------------------------------------------------------------------\n// ResilientPipelineGraph\n// ---------------------------------------------------------------------------\n\n/**\n * Graph subclass returned by {@link resilientPipeline}. Mounts each\n * configured intermediate under a stable name and exposes per-layer status\n * companions.\n *\n * @category patterns\n */\nexport class ResilientPipelineGraph<T> extends Graph {\n\t/**\n\t * Final resilient node — subscribe to this for `DATA` emissions.\n\t *\n\t * Named `output` (not `node`) because `Graph.node(name)` already names the\n\t * path-resolution method on the base class; a `readonly node` field would\n\t * shadow it.\n\t */\n\treadonly output: Node<T>;\n\t/** Live status: `\"pending\" | \"running\" | \"completed\" | \"errored\"`. */\n\treadonly status: Node<StatusValue>;\n\t/**\n\t * Last error payload, or `null` when not errored.\n\t *\n\t * Named `lastError` (not `error`) because `Graph.error(name, err)` already\n\t * names a method on the base class.\n\t */\n\treadonly lastError: Node<unknown | null>;\n\t/** Breaker state when `opts.breaker` is provided; `undefined` otherwise. */\n\treadonly breakerState: Node<BreakerState> | undefined;\n\t/**\n\t * Timeout state companion when `opts.timeoutMs` is supplied as a\n\t * `Node<Partial<TimeoutOptions>>`-like form; `undefined` otherwise\n\t * (DS-13.5.B forwarding contract — Node-form opts skip the switchMap\n\t * rebuild and lift the primitive's lifecycle companion onto the\n\t * pipeline bundle).\n\t */\n\treadonly timeoutState: Node<TimeoutState> | undefined;\n\t/**\n\t * Retry state companion when `opts.retry` is supplied as a\n\t * `Node<RetryOptions>`-like form; `undefined` otherwise\n\t * (DS-13.5.B forwarding contract).\n\t */\n\treadonly retryState: Node<RetryState> | undefined;\n\t/**\n\t * Drop-counter when `opts.rateLimit` is provided; `undefined` otherwise.\n\t *\n\t * **Lifetime note:** `droppedCount` retains its final value through\n\t * terminal (`COMPLETE` / `ERROR` / `TEARDOWN`); the underlying counter\n\t * resets to `0` only at the next subscription cycle.\n\t */\n\treadonly droppedCount: Node<number> | undefined;\n\t/**\n\t * Combined rate-limit state when `opts.rateLimit` is provided; `undefined`\n\t * otherwise. Same lifecycle as {@link droppedCount} but exposes\n\t * `pendingCount` and `paused` alongside the drop counter for richer\n\t * backpressure observability (Tier 5.2 D7).\n\t */\n\treadonly rateLimitState: Node<RateLimiterState> | undefined;\n\n\tconstructor(source: Node<T>, opts: ResilientPipelineOptions<T> = {}) {\n\t\tsuper(opts.name ?? \"resilient_pipeline\", opts.graph);\n\n\t\tlet current: Node<T> = source;\n\t\tlet droppedCount: Node<number> | undefined;\n\t\tlet rateLimitState: Node<RateLimiterState> | undefined;\n\t\tlet breakerState: Node<BreakerState> | undefined;\n\t\tlet timeoutState: Node<TimeoutState> | undefined;\n\t\tlet retryState: Node<RetryState> | undefined;\n\n\t\t// 1. Admission control — cheapest to drop / queue before any other work.\n\t\tif (opts.rateLimit != null) {\n\t\t\tif (isNode<Omit<RateLimiterOptions, \"maxBuffer\"> & { maxBuffer?: number }>(opts.rateLimit)) {\n\t\t\t\t// DS-13.5.B forwarding: rateLimiter primitive is widened to\n\t\t\t\t// accept `NodeOrValue<RateLimiterOptions>` directly. Forward\n\t\t\t\t// the Node form to preserve internal state (pending buffer,\n\t\t\t\t// dropped counter) across opts swaps. Companion nodes\n\t\t\t\t// (droppedCount / rateLimitState) lift onto the pipeline\n\t\t\t\t// bundle. The pre-DS-13.5.B switchMap-rebuild path is gone.\n\t\t\t\tconst bundle = rateLimiter(current, opts.rateLimit as NodeOrValue<RateLimiterOptions>);\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\tdroppedCount = bundle.droppedCount;\n\t\t\t\trateLimitState = bundle.rateLimitState;\n\t\t\t\tthis.add(current, { name: \"rateLimited\" });\n\t\t\t\tthis.add(droppedCount, { name: \"droppedCount\" });\n\t\t\t\tthis.add(rateLimitState, { name: \"rateLimitState\" });\n\t\t\t} else {\n\t\t\t\tconst rateOpts: RateLimiterOptions = {\n\t\t\t\t\t...opts.rateLimit,\n\t\t\t\t\tmaxBuffer: opts.rateLimit.maxBuffer ?? Infinity,\n\t\t\t\t\tmeta: domainMeta(\"resilient\", \"rate-limit\"),\n\t\t\t\t};\n\t\t\t\tconst bundle = rateLimiter(current, rateOpts);\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\tdroppedCount = bundle.droppedCount;\n\t\t\t\trateLimitState = bundle.rateLimitState;\n\t\t\t\tthis.add(current, { name: \"rateLimited\" });\n\t\t\t\tthis.add(droppedCount, { name: \"droppedCount\" });\n\t\t\t\tthis.add(rateLimitState, { name: \"rateLimitState\" });\n\t\t\t}\n\t\t}\n\n\t\t// 2. Budget — block when constraints are exhausted. Also cheap (no I/O).\n\t\tif (opts.budget != null) {\n\t\t\tif (isNode<ReadonlyArray<BudgetConstraint>>(opts.budget)) {\n\t\t\t\tconst inputForLayer = current;\n\t\t\t\tconst reactiveBudget = opts.budget;\n\t\t\t\tcurrent = switchMap(reactiveBudget, (constraints) =>\n\t\t\t\t\tconstraints.length > 0\n\t\t\t\t\t\t? budgetGate(inputForLayer, constraints, {\n\t\t\t\t\t\t\t\tmeta: domainMeta(\"resilient\", \"budget\"),\n\t\t\t\t\t\t\t}).node\n\t\t\t\t\t\t: inputForLayer,\n\t\t\t\t);\n\t\t\t\tthis.add(current, { name: \"budgetGated\" });\n\t\t\t} else if (opts.budget.length > 0) {\n\t\t\t\tcurrent = budgetGate(current, opts.budget, {\n\t\t\t\t\tmeta: domainMeta(\"resilient\", \"budget\"),\n\t\t\t\t}).node;\n\t\t\t\tthis.add(current, { name: \"budgetGated\" });\n\t\t\t}\n\t\t}\n\n\t\t// 3. Breaker — skip the resource when unhealthy (fail-fast before retry wastes time).\n\t\tif (opts.breaker != null) {\n\t\t\t// DS-13.5.B forwarding: circuitBreaker primitive accepts\n\t\t\t// `NodeOrValue<CircuitBreakerOptions>` directly. Pass the Node\n\t\t\t// form straight through so internal state (`_state`,\n\t\t\t// `_failureCount`, `_openCycle`, …) is preserved across opts\n\t\t\t// swaps. Companion `breakerState` lifts onto the pipeline\n\t\t\t// bundle in both static and Node-form paths.\n\t\t\tconst breaker = circuitBreaker(opts.breaker as NodeOrValue<CircuitBreakerOptions>);\n\t\t\tconst onOpen = opts.breakerOnOpen ?? \"skip\";\n\t\t\tconst wrapped = withBreaker<T>(breaker, {\n\t\t\t\tonOpen,\n\t\t\t\tmeta: domainMeta(\"resilient\", \"breaker\"),\n\t\t\t})(current);\n\t\t\tcurrent = wrapped.node;\n\t\t\tbreakerState = wrapped.breakerState;\n\t\t\tthis.add(current, { name: \"breakerWrapped\" });\n\t\t\tthis.add(breakerState, { name: \"breakerState\" });\n\t\t}\n\n\t\t// 4. Timeout — per-attempt deadline. Applied BEFORE retry so each retry\n\t\t// resubscribes to a fresh timeout. Swapping the order (timeout\n\t\t// OUTSIDE retry) would apply one global deadline to the entire\n\t\t// retry chain — not what callers expect for \"per-attempt timeout.\"\n\t\tif (opts.timeoutMs != null) {\n\t\t\tif (isNode<number>(opts.timeoutMs)) {\n\t\t\t\t// DS-13.5.B forwarding: build a derived `Node<{ns}>` from\n\t\t\t\t// the caller's `Node<number>` (ms) and pass directly to the\n\t\t\t\t// widened timeout primitive. State preservation (in-flight\n\t\t\t\t// deadline) is handled inside timeout's reactive opts path.\n\t\t\t\t// Companion `timeoutState` lifts onto the pipeline bundle.\n\t\t\t\tconst reactiveTimeoutMs = opts.timeoutMs;\n\t\t\t\tconst initialMs = reactiveTimeoutMs.cache as number | undefined;\n\t\t\t\t// QA A5 (2026-05-03): assert validity of the cached initial\n\t\t\t\t// value at construction so a bad cache fails loud at wire\n\t\t\t\t// time, not silently at first emit. Reactive emits with\n\t\t\t\t// invalid values flow through the producer body's ERROR\n\t\t\t\t// channel rather than throwing into the host scheduler.\n\t\t\t\tif (initialMs !== undefined) assertTimeoutMsValid(initialMs);\n\t\t\t\tconst optsBridge = node<Partial<TimeoutOptions>>(\n\t\t\t\t\t[reactiveTimeoutMs as Node<unknown>],\n\t\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\t\tconst data = batchData.map((b, i) =>\n\t\t\t\t\t\t\tb != null && b.length > 0 ? b.at(-1) : ctx.prevData[i],\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst ms = data[0] as number | undefined;\n\t\t\t\t\t\tif (ms === undefined) return;\n\t\t\t\t\t\t// QA A5: route validation failures through the\n\t\t\t\t\t\t// reactive ERROR channel — sync `throw` inside a\n\t\t\t\t\t\t// producer body corrupts the host scheduler's\n\t\t\t\t\t\t// wave dispatch (mirrors timeout primitive's\n\t\t\t\t\t\t// \"sync throw would corrupt the host scheduler\"\n\t\t\t\t\t\t// rationale).\n\t\t\t\t\t\tif (typeof ms !== \"number\" || !Number.isFinite(ms) || ms <= 0 || ms > 9_000_000) {\n\t\t\t\t\t\t\tactions.down([\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\tERROR,\n\t\t\t\t\t\t\t\t\tnew RangeError(\n\t\t\t\t\t\t\t\t\t\t`resilientPipeline: timeoutMs reactive emit invalid (${ms}); must be > 0 and <= 9_000_000.`,\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\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactions.emit({ ns: ms * NS_PER_MS });\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\t\tname: \"timeoutOptsBridge\",\n\t\t\t\t\t\t...(initialMs !== undefined\n\t\t\t\t\t\t\t? { initial: { ns: initialMs * NS_PER_MS } as Partial<TimeoutOptions> }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\t// QA A5: register the bridge on the pipeline graph so\n\t\t\t\t// describe() walks see the full topology (dry-run /\n\t\t\t\t// real-run equivalence per CLAUDE.md).\n\t\t\t\tthis.add(optsBridge, { name: \"timeoutOptsBridge\" });\n\t\t\t\tconst bundle = withTimeout(current, optsBridge, {\n\t\t\t\t\tmeta: domainMeta(\"resilient\", \"timeout\"),\n\t\t\t\t});\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\ttimeoutState = bundle.timeoutState;\n\t\t\t\tthis.add(current, { name: \"timeoutWrapped\" });\n\t\t\t\tthis.add(timeoutState, { name: \"timeoutState\" });\n\t\t\t} else {\n\t\t\t\tassertTimeoutMsValid(opts.timeoutMs);\n\t\t\t\tconst bundle = withTimeout(\n\t\t\t\t\tcurrent,\n\t\t\t\t\t{ ns: opts.timeoutMs * NS_PER_MS },\n\t\t\t\t\t{\n\t\t\t\t\t\tmeta: domainMeta(\"resilient\", \"timeout\"),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\ttimeoutState = bundle.timeoutState;\n\t\t\t\tthis.add(current, { name: \"timeoutWrapped\" });\n\t\t\t\tthis.add(timeoutState, { name: \"timeoutState\" });\n\t\t\t}\n\t\t}\n\n\t\t// 5. Retry — resubscribe on `ERROR` up to `count` times. Wraps timeout\n\t\t// so each retry gets its own fresh deadline.\n\t\tif (opts.retry != null) {\n\t\t\t// DS-13.5.B forwarding: retry primitive accepts\n\t\t\t// `NodeOrValue<RetryOptions>` directly. Forward Node form so\n\t\t\t// `attempt` / `prevDelay` / in-flight timer survive opts swaps.\n\t\t\t// Companion `retryState` lifts onto the pipeline bundle.\n\t\t\tif (isNode<RetryOptions>(opts.retry)) {\n\t\t\t\tconst bundle = retry(current, opts.retry as NodeOrValue<RetryOptions>);\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\tretryState = bundle.retryState;\n\t\t\t\tthis.add(current, { name: \"retryWrapped\" });\n\t\t\t\tthis.add(retryState, { name: \"retryState\" });\n\t\t\t} else {\n\t\t\t\tconst bundle = retry(current, {\n\t\t\t\t\t...opts.retry,\n\t\t\t\t\tmeta: domainMeta(\"resilient\", \"retry\"),\n\t\t\t\t});\n\t\t\t\tcurrent = bundle.node;\n\t\t\t\tretryState = bundle.retryState;\n\t\t\t\tthis.add(current, { name: \"retryWrapped\" });\n\t\t\t\tthis.add(retryState, { name: \"retryState\" });\n\t\t\t}\n\t\t}\n\n\t\t// 6. Fallback — last resort after retry+timeout exhaust. Guard\n\t\t// `opts.fallback !== undefined` so `null` is a valid fallback.\n\t\tif (opts.fallback !== undefined) {\n\t\t\tcurrent = fallback(current, opts.fallback, {\n\t\t\t\tmeta: domainMeta(\"resilient\", \"fallback\"),\n\t\t\t});\n\t\t\tthis.add(current, { name: \"fallbackWrapped\" });\n\t\t}\n\n\t\t// 7. Status wrapping — observability. Always last so it sees the final shape.\n\t\tconst statusBundle = withStatus(current, {\n\t\t\tinitialStatus: opts.initialStatus ?? \"pending\",\n\t\t\tmeta: domainMeta(\"resilient\", \"status\"),\n\t\t});\n\n\t\tthis.output = statusBundle.node;\n\t\tthis.status = statusBundle.status;\n\t\tthis.lastError = statusBundle.error;\n\t\tthis.breakerState = breakerState;\n\t\tthis.droppedCount = droppedCount;\n\t\tthis.rateLimitState = rateLimitState;\n\t\tthis.timeoutState = timeoutState;\n\t\tthis.retryState = retryState;\n\n\t\t// Mount the externally-visible top-level entries by name. Each carries\n\t\t// its own factoryTag meta from the underlying primitive (`withStatus`\n\t\t// for `output`/`status`/`lastError`); domain-level provenance lives on\n\t\t// the Graph itself via the `tagFactory(\"resilientPipeline\", ...)` call\n\t\t// in the public factory below. The mount names use `output` /\n\t\t// `lastError` to match the property names — the previous `node` /\n\t\t// `error` clashed with `Graph.node(name)` / `Graph.error(name, err)`.\n\t\tthis.add(this.output, { name: \"output\" });\n\t\tthis.add(this.status, { name: \"status\" });\n\t\tthis.add(this.lastError, { name: \"lastError\" });\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Compose a resilient pipeline around `source` in the canonical nesting\n * order — `rateLimit → budget → breaker → timeout → retry → fallback → status`.\n * Omit any option to skip that layer.\n *\n * Returns a {@link ResilientPipelineGraph} (Graph subclass) —\n * `pipeline.output` is the externally visible final node; `pipeline.status`\n * / `pipeline.lastError` / `pipeline.breakerState` / `pipeline.droppedCount`\n * are the per-layer companions. Call `pipeline.describe()` to see the\n * mounted intermediates; compose with {@link graphLens}'s `health` for\n * aggregate status.\n *\n * **Naming note:** `output` and `lastError` (not `node` / `error`) avoid\n * clashes with `Graph.node(name)` and `Graph.error(name, err)` on the base\n * class.\n *\n * @param source - Upstream node to wrap.\n * @param opts - See {@link ResilientPipelineOptions}. All fields optional.\n *\n * @example\n * ```ts\n * const safeFetch = resilientPipeline(fetchNode, {\n * rateLimit: { maxEvents: 10, windowNs: NS_PER_SEC },\n * breaker: { failureThreshold: 5 },\n * retry: { count: 3, backoff: \"exponential\" },\n * timeoutMs: 10_000,\n * fallback: null,\n * });\n * safeFetch.output.subscribe(msgs => console.log(msgs));\n * safeFetch.status.subscribe(msgs => console.log(msgs));\n * graphSpecToAscii(safeFetch.describe()); // visualize the chain\n * ```\n *\n * @category patterns\n */\nexport function resilientPipeline<T>(\n\tsource: Node<T>,\n\topts: ResilientPipelineOptions<T> = {},\n): ResilientPipelineGraph<T> {\n\tconst g = new ResilientPipelineGraph<T>(source, opts);\n\t// Self-tag for `graph.describe()` factory provenance (Phase 2.5 DG1=B).\n\t// `placeholderArgs` substitutes Node-typed and function-typed fields with\n\t// `\"<Node>\"` / `\"<function>\"` so `factoryArgs` stays JSON-serializable.\n\tg.tagFactory(\"resilientPipeline\", placeholderArgs(opts as unknown as Record<string, unknown>));\n\treturn g;\n}\n\n// Tag the underlying status / error / breaker / dropped companions with a\n// best-effort factoryTag too via the wrapper class's meta — already covered\n// by `domainMeta(\"resilient\", kind)` on the mounted nodes.\n\n// Tier 9.1 γ-form: this module now lives inside `extra/resilience/`, so the\n// underlying primitive option types are already exported from the same barrel\n// (`./index.js`). The previous re-exports of `factoryTag` / `placeholderArgs` /\n// `NS_PER_MS` / `NS_PER_SEC` / option types were a workaround for the prior\n// `patterns/resilient-pipeline/` folder location and are now redundant.\n"],"mappings":"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","names":["node","clampNonNegative","import_core","import_core","import_extra","import_graph","import_core","import_core","batch","import_core","import_extra","batch","import_core","import_extra","import_core","batch","import_core","import_extra","import_graph","batch","nodeFactory","batch","fallback","import_core","import_extra","import_graph","import_core","import_extra","import_core","import_extra","isNodeLike","keepalive","node","batch","import_core","import_extra","import_graph","ageSeconds","import_core","import_extra","import_graph","import_core","import_extra","import_graph","meta","NS_PER_SEC","batch","out","meta","ageSeconds","import_core","import_core","import_extra","batch","batch","import_core","import_extra","import_graph","import_core","import_core","import_core","import_core","import_extra","import_core","import_core","import_extra","import_graph","batch","import_core","import_graph","batch","import_core","import_extra","import_graph","import_core","import_extra","import_graph","DEFAULT_MAX_PER_PUMP","requireNonNegativeInt","batch","requireNonNegativeInt","DEFAULT_MAX_PER_PUMP","batch","topic","ageSeconds","import_core","import_extra","import_graph","isNode","createNode","batch","i","best","bestScore","import_core","import_extra","import_graph","import_extra","import_core","import_extra","import_graph","import_core","import_extra","import_graph","import_core","import_extra","import_graph","isNode","batch","node","isNode","isNode","batch","import_core","import_extra","import_graph","isNode"]}