@graphrefly/graphrefly 0.47.2 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base/composition/index.cjs +4 -3
- package/dist/base/composition/index.cjs.map +1 -1
- package/dist/base/composition/index.d.cts +14 -5
- package/dist/base/composition/index.d.ts +14 -5
- package/dist/base/composition/index.js +8 -8
- package/dist/base/index.cjs +152 -78
- package/dist/base/index.cjs.map +1 -1
- package/dist/base/index.d.cts +2 -2
- package/dist/base/index.d.ts +2 -2
- package/dist/base/index.js +75 -70
- package/dist/base/io/index.cjs +31 -17
- package/dist/base/io/index.cjs.map +1 -1
- package/dist/base/io/index.d.cts +32 -5
- package/dist/base/io/index.d.ts +32 -5
- package/dist/base/io/index.js +1 -1
- package/dist/base/mutation/index.cjs +21 -0
- package/dist/base/mutation/index.cjs.map +1 -1
- package/dist/base/mutation/index.d.cts +23 -1
- package/dist/base/mutation/index.d.ts +23 -1
- package/dist/base/mutation/index.js +3 -1
- package/dist/base/sources/browser/index.cjs +5 -3
- package/dist/base/sources/browser/index.cjs.map +1 -1
- package/dist/base/sources/browser/index.d.cts +20 -2
- package/dist/base/sources/browser/index.d.ts +20 -2
- package/dist/base/sources/browser/index.js +5 -3
- package/dist/base/sources/browser/index.js.map +1 -1
- package/dist/base/sources/event/index.cjs +28 -0
- package/dist/base/sources/event/index.cjs.map +1 -1
- package/dist/base/sources/event/index.d.cts +67 -3
- package/dist/base/sources/event/index.d.ts +67 -3
- package/dist/base/sources/event/index.js +4 -1
- package/dist/base/sources/index.cjs +75 -37
- package/dist/base/sources/index.cjs.map +1 -1
- package/dist/base/sources/index.d.cts +1 -1
- package/dist/base/sources/index.d.ts +1 -1
- package/dist/base/sources/index.js +5 -2
- package/dist/{chunk-R6ZCSXKX.js → chunk-23MAWVOJ.js} +3 -3
- package/dist/{chunk-MS3WPRJR.js → chunk-3REMCHSS.js} +6 -6
- package/dist/chunk-3REMCHSS.js.map +1 -0
- package/dist/{chunk-CEVNQ74M.js → chunk-3YGXPUHW.js} +2 -2
- package/dist/{chunk-CEVNQ74M.js.map → chunk-3YGXPUHW.js.map} +1 -1
- package/dist/{chunk-6ZLCPUXS.js → chunk-46X2EFQH.js} +15 -4
- package/dist/chunk-46X2EFQH.js.map +1 -0
- package/dist/{chunk-NY2PYHNC.js → chunk-5UY3PNFY.js} +12 -5
- package/dist/chunk-5UY3PNFY.js.map +1 -0
- package/dist/{chunk-FQSQONOU.js → chunk-65OM4XLQ.js} +49 -3
- package/dist/chunk-65OM4XLQ.js.map +1 -0
- package/dist/{chunk-3PSLNJDU.js → chunk-6DQYBIHW.js} +314 -49
- package/dist/chunk-6DQYBIHW.js.map +1 -0
- package/dist/{chunk-LDCSZ72P.js → chunk-6YBER5UP.js} +3 -3
- package/dist/{chunk-LDCSZ72P.js.map → chunk-6YBER5UP.js.map} +1 -1
- package/dist/{chunk-3O3NKZJW.js → chunk-7T7WLEPM.js} +24 -3
- package/dist/chunk-7T7WLEPM.js.map +1 -0
- package/dist/{chunk-PKPO3JTZ.js → chunk-AQAKDE7F.js} +29 -11
- package/dist/chunk-AQAKDE7F.js.map +1 -0
- package/dist/{chunk-6MRSX3YK.js → chunk-B5Y5GPD5.js} +2 -2
- package/dist/{chunk-BXGZFGZ4.js → chunk-C5QD5DQX.js} +22 -1
- package/dist/chunk-C5QD5DQX.js.map +1 -0
- package/dist/{chunk-4XCHZRUJ.js → chunk-D5YGR4TP.js} +58 -7
- package/dist/chunk-D5YGR4TP.js.map +1 -0
- package/dist/{chunk-NPRP3MCV.js → chunk-DHDCOOJU.js} +2 -2
- package/dist/chunk-DHDCOOJU.js.map +1 -0
- package/dist/{chunk-VP3TIUDF.js → chunk-DVTDF5OI.js} +2 -2
- package/dist/{chunk-OXD5LFQP.js → chunk-G7H6PN7P.js} +2 -2
- package/dist/{chunk-EL5VHUGK.js → chunk-GGKHHG5Y.js} +32 -18
- package/dist/chunk-GGKHHG5Y.js.map +1 -0
- package/dist/{chunk-446I4EGD.js → chunk-J5TBZFBD.js} +2 -2
- package/dist/{chunk-7AVQIGF6.js → chunk-K4ZYJ4EM.js} +554 -460
- package/dist/chunk-K4ZYJ4EM.js.map +1 -0
- package/dist/{chunk-QFE5BQH7.js → chunk-LTSI7ULC.js} +2 -2
- package/dist/{chunk-5GVURVIG.js → chunk-MMHGYX44.js} +12 -2
- package/dist/{chunk-5GVURVIG.js.map → chunk-MMHGYX44.js.map} +1 -1
- package/dist/{chunk-KRFGO5QH.js → chunk-MQMTRKY3.js} +118 -43
- package/dist/chunk-MQMTRKY3.js.map +1 -0
- package/dist/{chunk-42FQ27MQ.js → chunk-MTODGQBR.js} +44 -179
- package/dist/chunk-MTODGQBR.js.map +1 -0
- package/dist/{chunk-FVINAAKA.js → chunk-NBK6QQMG.js} +14 -13
- package/dist/{chunk-FVINAAKA.js.map → chunk-NBK6QQMG.js.map} +1 -1
- package/dist/{chunk-KNU73RZW.js → chunk-NSA5K5G2.js} +2 -2
- package/dist/{chunk-MLTPJMH6.js → chunk-QQYULEZL.js} +2 -2
- package/dist/chunk-QSW4DFKE.js +31 -0
- package/dist/chunk-QSW4DFKE.js.map +1 -0
- package/dist/{chunk-VAZXUK6G.js → chunk-SUNCHMML.js} +2 -2
- package/dist/{chunk-EP4WVQLX.js → chunk-T2U6N3FV.js} +6 -6
- package/dist/{chunk-T7SP3EYR.js → chunk-T5URUIIY.js} +33 -24
- package/dist/chunk-T5URUIIY.js.map +1 -0
- package/dist/{chunk-VNXAF2KE.js → chunk-TPTZZV25.js} +6 -6
- package/dist/chunk-TPTZZV25.js.map +1 -0
- package/dist/{chunk-IOJDYUA7.js → chunk-V46JWFGV.js} +6 -5
- package/dist/chunk-V46JWFGV.js.map +1 -0
- package/dist/{chunk-WGDEBIP4.js → chunk-X6ESZDR6.js} +5 -6
- package/dist/chunk-X6ESZDR6.js.map +1 -0
- package/dist/{chunk-N65E26UL.js → chunk-XEWV254I.js} +2 -2
- package/dist/{chunk-N65E26UL.js.map → chunk-XEWV254I.js.map} +1 -1
- package/dist/{chunk-PTWADEH3.js → chunk-YBJVKMTM.js} +34 -14
- package/dist/chunk-YBJVKMTM.js.map +1 -0
- package/dist/{chunk-DDTS7F5O.js → chunk-ZW32BPXV.js} +12 -3
- package/dist/chunk-ZW32BPXV.js.map +1 -0
- package/dist/compat/index.cjs +51 -4
- package/dist/compat/index.cjs.map +1 -1
- package/dist/compat/index.d.cts +1 -1
- package/dist/compat/index.d.ts +1 -1
- package/dist/compat/index.js +6 -6
- package/dist/compat/nestjs/index.cjs +51 -4
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +1 -1
- package/dist/compat/nestjs/index.d.ts +1 -1
- package/dist/compat/nestjs/index.js +3 -3
- package/dist/{fallback-Bx46zqky.d.cts → fallback-BROR6ZhO.d.cts} +1 -1
- package/dist/{fallback-pIWW8A2d.d.ts → fallback-DO80aM_3.d.ts} +1 -1
- package/dist/{index-B_p8tnvf.d.cts → index-D1z3XcF9.d.cts} +1 -0
- package/dist/{index-_HDSmPyp.d.ts → index-DZ6yua0Q.d.ts} +1 -0
- package/dist/index.cjs +2215 -1676
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +169 -146
- package/dist/index.js.map +1 -1
- package/dist/presets/ai/index.cjs +46 -0
- package/dist/presets/ai/index.cjs.map +1 -1
- package/dist/presets/ai/index.js +12 -12
- package/dist/presets/harness/index.cjs +130 -18
- package/dist/presets/harness/index.cjs.map +1 -1
- package/dist/presets/harness/index.d.cts +15 -5
- package/dist/presets/harness/index.d.ts +15 -5
- package/dist/presets/harness/index.js +22 -22
- package/dist/presets/index.cjs +222 -53
- package/dist/presets/index.cjs.map +1 -1
- package/dist/presets/index.d.cts +2 -2
- package/dist/presets/index.d.ts +2 -2
- package/dist/presets/index.js +45 -45
- package/dist/presets/inspect/index.cjs +63 -14
- package/dist/presets/inspect/index.cjs.map +1 -1
- package/dist/presets/inspect/index.d.cts +1 -1
- package/dist/presets/inspect/index.d.ts +1 -1
- package/dist/presets/inspect/index.js +6 -6
- package/dist/presets/resilience/index.cjs +29 -21
- package/dist/presets/resilience/index.cjs.map +1 -1
- package/dist/presets/resilience/index.d.cts +12 -8
- package/dist/presets/resilience/index.d.ts +12 -8
- package/dist/presets/resilience/index.js +3 -3
- package/dist/{rate-limiter-DpVbSYdH.d.cts → rate-limiter-DC26FM8J.d.cts} +10 -1
- package/dist/{rate-limiter-CEALq4N1.d.ts → rate-limiter-DyWpwpQP.d.ts} +10 -1
- package/dist/{reactive-layout-fswlBUvX.d.ts → reactive-layout-BBBWH0V_.d.cts} +85 -4
- package/dist/{reactive-layout-fswlBUvX.d.cts → reactive-layout-BBBWH0V_.d.ts} +85 -4
- package/dist/solutions/index.cjs +168 -47
- package/dist/solutions/index.cjs.map +1 -1
- package/dist/solutions/index.d.cts +2 -2
- package/dist/solutions/index.d.ts +2 -2
- package/dist/solutions/index.js +28 -28
- package/dist/{spawnable-5mDY501F.d.cts → spawnable-B2IlW60f.d.cts} +23 -2
- package/dist/{spawnable-D3lR0oQu.d.ts → spawnable-tttFz2Nh.d.ts} +23 -2
- package/dist/testing/index.cjs +94 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +59 -0
- package/dist/testing/index.d.ts +59 -0
- package/dist/testing/index.js +73 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/utils/ai/browser.cjs.map +1 -1
- package/dist/utils/ai/browser.d.cts +2 -2
- package/dist/utils/ai/browser.d.ts +2 -2
- package/dist/utils/ai/browser.js +6 -6
- package/dist/utils/ai/browser.js.map +1 -1
- package/dist/utils/ai/index.cjs +250 -166
- package/dist/utils/ai/index.cjs.map +1 -1
- package/dist/utils/ai/index.d.cts +108 -12
- package/dist/utils/ai/index.d.ts +108 -12
- package/dist/utils/ai/index.js +21 -19
- package/dist/utils/ai/node.cjs.map +1 -1
- package/dist/utils/ai/node.d.cts +5 -5
- package/dist/utils/ai/node.d.ts +5 -5
- package/dist/utils/ai/node.js +2 -2
- package/dist/utils/ai/node.js.map +1 -1
- package/dist/utils/cqrs/index.cjs +29 -3
- package/dist/utils/cqrs/index.cjs.map +1 -1
- package/dist/utils/cqrs/index.d.cts +12 -7
- package/dist/utils/cqrs/index.d.ts +12 -7
- package/dist/utils/cqrs/index.js +2 -2
- package/dist/utils/demo-shell/index.cjs +45 -19
- package/dist/utils/demo-shell/index.cjs.map +1 -1
- package/dist/utils/demo-shell/index.d.cts +1 -1
- package/dist/utils/demo-shell/index.d.ts +1 -1
- package/dist/utils/demo-shell/index.js +2 -2
- package/dist/utils/domain-templates/index.cjs.map +1 -1
- package/dist/utils/domain-templates/index.js +3 -3
- package/dist/utils/graphspec/index.cjs.map +1 -1
- package/dist/utils/graphspec/index.js +3 -3
- package/dist/utils/index.cjs +1642 -1225
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +7 -7
- package/dist/utils/index.d.ts +7 -7
- package/dist/utils/index.js +72 -54
- package/dist/utils/inspect/index.cjs +52 -4
- package/dist/utils/inspect/index.cjs.map +1 -1
- package/dist/utils/inspect/index.d.cts +32 -3
- package/dist/utils/inspect/index.d.ts +32 -3
- package/dist/utils/inspect/index.js +4 -4
- package/dist/utils/job-queue/index.cjs +46 -9
- package/dist/utils/job-queue/index.cjs.map +1 -1
- package/dist/utils/job-queue/index.d.cts +33 -3
- package/dist/utils/job-queue/index.d.ts +33 -3
- package/dist/utils/job-queue/index.js +2 -2
- package/dist/utils/memory/index.cjs +556 -462
- package/dist/utils/memory/index.cjs.map +1 -1
- package/dist/utils/memory/index.d.cts +203 -24
- package/dist/utils/memory/index.d.ts +203 -24
- package/dist/utils/memory/index.js +10 -2
- package/dist/utils/messaging/index.cjs.map +1 -1
- package/dist/utils/messaging/index.d.cts +4 -3
- package/dist/utils/messaging/index.d.ts +4 -3
- package/dist/utils/messaging/index.js +2 -2
- package/dist/utils/orchestration/index.cjs +9 -0
- package/dist/utils/orchestration/index.cjs.map +1 -1
- package/dist/utils/orchestration/index.js +3 -3
- package/dist/utils/process/index.cjs +32 -2
- package/dist/utils/process/index.cjs.map +1 -1
- package/dist/utils/process/index.d.cts +4 -3
- package/dist/utils/process/index.d.ts +4 -3
- package/dist/utils/process/index.js +2 -2
- package/dist/utils/reactive-layout/index.cjs +184 -55
- package/dist/utils/reactive-layout/index.cjs.map +1 -1
- package/dist/utils/reactive-layout/index.d.cts +128 -3
- package/dist/utils/reactive-layout/index.d.ts +128 -3
- package/dist/utils/reactive-layout/index.js +16 -8
- package/dist/utils/reduction/index.cjs.map +1 -1
- package/dist/utils/reduction/index.js +2 -2
- package/dist/utils/resilience/index.cjs +29 -20
- package/dist/utils/resilience/index.cjs.map +1 -1
- package/dist/utils/resilience/index.d.cts +1 -1
- package/dist/utils/resilience/index.d.ts +1 -1
- package/dist/utils/resilience/index.js +2 -2
- package/dist/utils/surface/index.cjs.map +1 -1
- package/dist/utils/surface/index.js +4 -4
- package/package.json +15 -3
- package/dist/chunk-3O3NKZJW.js.map +0 -1
- package/dist/chunk-3PSLNJDU.js.map +0 -1
- package/dist/chunk-42FQ27MQ.js.map +0 -1
- package/dist/chunk-4XCHZRUJ.js.map +0 -1
- package/dist/chunk-6ZLCPUXS.js.map +0 -1
- package/dist/chunk-7AVQIGF6.js.map +0 -1
- package/dist/chunk-BXGZFGZ4.js.map +0 -1
- package/dist/chunk-DDTS7F5O.js.map +0 -1
- package/dist/chunk-EL5VHUGK.js.map +0 -1
- package/dist/chunk-FQSQONOU.js.map +0 -1
- package/dist/chunk-IOJDYUA7.js.map +0 -1
- package/dist/chunk-KRFGO5QH.js.map +0 -1
- package/dist/chunk-MS3WPRJR.js.map +0 -1
- package/dist/chunk-NPRP3MCV.js.map +0 -1
- package/dist/chunk-NY2PYHNC.js.map +0 -1
- package/dist/chunk-PKPO3JTZ.js.map +0 -1
- package/dist/chunk-PTWADEH3.js.map +0 -1
- package/dist/chunk-T7SP3EYR.js.map +0 -1
- package/dist/chunk-VNXAF2KE.js.map +0 -1
- package/dist/chunk-W2BOPXTI.js +0 -1
- package/dist/chunk-W2BOPXTI.js.map +0 -1
- package/dist/chunk-WGDEBIP4.js.map +0 -1
- /package/dist/{chunk-R6ZCSXKX.js.map → chunk-23MAWVOJ.js.map} +0 -0
- /package/dist/{chunk-6MRSX3YK.js.map → chunk-B5Y5GPD5.js.map} +0 -0
- /package/dist/{chunk-VP3TIUDF.js.map → chunk-DVTDF5OI.js.map} +0 -0
- /package/dist/{chunk-OXD5LFQP.js.map → chunk-G7H6PN7P.js.map} +0 -0
- /package/dist/{chunk-446I4EGD.js.map → chunk-J5TBZFBD.js.map} +0 -0
- /package/dist/{chunk-QFE5BQH7.js.map → chunk-LTSI7ULC.js.map} +0 -0
- /package/dist/{chunk-KNU73RZW.js.map → chunk-NSA5K5G2.js.map} +0 -0
- /package/dist/{chunk-MLTPJMH6.js.map → chunk-QQYULEZL.js.map} +0 -0
- /package/dist/{chunk-VAZXUK6G.js.map → chunk-SUNCHMML.js.map} +0 -0
- /package/dist/{chunk-EP4WVQLX.js.map → chunk-T2U6N3FV.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presets/harness/refine-loop.ts","../src/presets/harness/harness-loop.ts","../src/utils/harness/_internal.ts","../src/presets/harness/spawnable.ts"],"sourcesContent":["/**\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\t/**\n\t * Best candidate so far. **SENTINEL until the first iteration settles** —\n\t * `loop.best.cache` is `undefined` (not `null`) before any iteration\n\t * produces a best, and a degenerate empty-candidate iteration leaves the\n\t * prior best in place rather than wiping it. Consumers guard with\n\t * `=== undefined` (spec §3 SENTINEL), not `== null`. (Anti-pattern sweep\n\t * 2026-05-18: dropped the `initial: null` eager-placeholder; `null` is\n\t * reserved for the per-iteration {@link Iteration.best} data field where an\n\t * empty batch is a valid domain value.)\n\t */\n\treadonly best: Node<T>;\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\t// SENTINEL until the first iteration mirrors feedback (anti-pattern\n\t\t// sweep 2026-05-18 — dropped the `initial: null` eager-placeholder that\n\t\t// pushed `[null]` to every fresh subscriber). Only ever carries a real\n\t\t// `Feedback` (the decide-effect mirror at the bottom always emits a\n\t\t// concrete `fb`), so SENTINEL-before-first cleanly means \"no iteration\n\t\t// has completed yet\" rather than a spurious `null` DATA.\n\t\tconst lastFeedbackState = createNode<Feedback>([], {\n\t\t\tname: \"lastFeedback\",\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\t// SENTINEL until the first iteration produces a best (anti-pattern\n\t\t// sweep 2026-05-18). Never carries `null`: the decide-effect skips the\n\t\t// emit when `pickBest` yields no best, so a degenerate empty-candidate\n\t\t// iteration preserves the prior best instead of wiping it to `null`.\n\t\tconst bestState = createNode<T>([], { name: \"best\" });\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;\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 | undefined;\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;\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 === undefined;\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\t// `best` is `T | null` from pickBest — `null` only on an empty\n\t\t\t\t\t// candidate batch (strategies throw on empty, so unreachable in\n\t\t\t\t\t// practice). Skip the emit rather than pushing `null` into the\n\t\t\t\t\t// SENTINEL `Node<T>`: a degenerate iteration preserves the prior\n\t\t\t\t\t// best instead of wiping it. (Anti-pattern sweep 2026-05-18.)\n\t\t\t\t\tif (best !== null) bestState.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 * 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/**\n\t * Strategy model — `auditedSuccessTracker` keyed by `StrategyKey`.\n\t *\n\t * **Ownership (EC10/EC15).** Owned by the harness: it is mounted as a\n\t * child subgraph (`harness.mount(\"strategy\", strategy)`), so its disposal\n\t * cascades from `harness.destroy()` via the mount lifecycle. Do **not**\n\t * call `strategy.destroy()` independently — the harness's `triage-input`\n\t * node and (when `opts.priority` is set) `buildPriorityScores` hold\n\t * cross-graph deps on `strategy.entries`; destroying the strategy out of\n\t * band staleness those nodes while the rest of the loop keeps running.\n\t * Read/subscribe freely; let the harness own the lifecycle.\n\t */\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 * 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 * 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"],"mappings":"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","names":["batch","i","best","bestScore","monotonicNs","placeholderArgs","Graph","Graph","batch","topic","placeholderArgs","monotonicNs","batch","DATA","node","Graph","Graph","node","DATA","batch"]}
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
PROMPTS_TOPIC,
|
|
4
4
|
RESPONSES_TOPIC,
|
|
5
5
|
subscription
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DHDCOOJU.js";
|
|
7
7
|
import {
|
|
8
8
|
domainMeta
|
|
9
9
|
} from "./chunk-FMPF42Q4.js";
|
|
10
10
|
import {
|
|
11
11
|
createAuditLog,
|
|
12
12
|
mutate
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-C5QD5DQX.js";
|
|
14
14
|
|
|
15
15
|
// src/utils/orchestration/human-input.ts
|
|
16
16
|
import { COMPLETE, DATA, node, wallClockNs } from "@graphrefly/pure-ts/core";
|
|
@@ -298,6 +298,10 @@ var PipelineGraph = class extends Graph {
|
|
|
298
298
|
{
|
|
299
299
|
name,
|
|
300
300
|
describeKind: "derived",
|
|
301
|
+
// Spec §2.7 R2.7.1 (DS-2.7.A). fn must fire on
|
|
302
|
+
// upstream-COMPLETE/ERROR-only-without-DATA so the
|
|
303
|
+
// teardown-decision record + downstream terminal forward run.
|
|
304
|
+
terminalAsRealInput: true,
|
|
301
305
|
meta: meta("approval_gate", opts.meta)
|
|
302
306
|
}
|
|
303
307
|
);
|
|
@@ -515,6 +519,11 @@ var PipelineGraph = class extends Graph {
|
|
|
515
519
|
describeKind: "derived",
|
|
516
520
|
completeWhenDepsComplete: opts.completeWhenDepsComplete ?? !(mode === "completed" || mode === "terminal"),
|
|
517
521
|
errorWhenDepsError: !(mode === "errored" || mode === "terminal"),
|
|
522
|
+
// Spec §2.7 R2.7.1 (DS-2.7.A). `catch` exists to fire on a
|
|
523
|
+
// source terminal — its whole job is `recover(cause, …)` on a
|
|
524
|
+
// terminal-only wave. Without this opt-in the gate holds and
|
|
525
|
+
// the recover branch never runs.
|
|
526
|
+
terminalAsRealInput: true,
|
|
518
527
|
meta: meta("catch", opts.meta)
|
|
519
528
|
}
|
|
520
529
|
);
|
|
@@ -578,4 +587,4 @@ export {
|
|
|
578
587
|
pipelineGraph,
|
|
579
588
|
tracker
|
|
580
589
|
};
|
|
581
|
-
//# sourceMappingURL=chunk-
|
|
590
|
+
//# sourceMappingURL=chunk-ZW32BPXV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/orchestration/human-input.ts","../src/utils/orchestration/pipeline-graph.ts","../src/utils/orchestration/tracker.ts"],"sourcesContent":["/**\n * Phase 13.F — `humanInput<T>` sibling preset.\n *\n * Source: `archive/docs/SESSION-human-llm-intervention-primitives.md` §5\n * \"Sibling presets on the substrate\" + §9 Phase 2.\n *\n * **Role.** LLM↔human runtime Q&A channel. The agent (or any consumer)\n * reactively asks for human input by emitting a prompt; humanInput\n * publishes a {@link Message} envelope to the well-known\n * {@link PROMPTS_TOPIC} on the hub and watches {@link RESPONSES_TOPIC} for\n * the matching `correlationId`. When the response arrives, humanInput's\n * output Node emits the typed payload `T`.\n *\n * **Sibling to `approvalGate`** ([pipeline-graph.ts](pipeline-graph.ts)):\n * approvalGate is design-time veto on a topology edge; humanInput is a\n * runtime Q&A channel. They share substrate (hub + envelope) but differ\n * in role and initiator.\n *\n * **No imperative `.run()` / `.ask()`** — caller writes to `prompt` (any\n * `NodeInput<string>`) and reads `humanInput()`'s output Node.\n *\n * **Multi-prompt.** Each new `prompt` DATA mints a fresh correlationId\n * and a new pending request. The output Node's emission tracks the latest\n * correlationId — earlier in-flight requests are abandoned (switchMap\n * semantics). To run parallel requests, instantiate two humanInput nodes.\n */\n\nimport { COMPLETE, DATA, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport {\n\ttype JsonSchema,\n\ttype MessagingHubGraph,\n\tPROMPTS_TOPIC,\n\tRESPONSES_TOPIC,\n\ttype TopicMessage,\n} from \"../messaging/index.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Outbound prompt envelope payload. */\nexport interface HumanPromptPayload {\n\treadonly prompt: string;\n\treadonly schema?: JsonSchema;\n}\n\n/**\n * Options for {@link humanInput}.\n */\nexport interface HumanInputOpts {\n\t/**\n\t * Messaging hub. {@link PROMPTS_TOPIC} is created lazily for outbound\n\t * prompts; {@link RESPONSES_TOPIC} is read for incoming responses.\n\t */\n\treadonly hub: MessagingHubGraph;\n\t/**\n\t * Reactive prompt source. Any `NodeInput<string>` is accepted (Node,\n\t * Promise, AsyncIterable, scalar) — coerced via `fromAny`. Each new\n\t * DATA on this input mints a fresh request.\n\t */\n\treadonly prompt: NodeInput<string>;\n\t/**\n\t * Optional response-shape schema. Carried in the prompt envelope for\n\t * UI / consumer-side validation. Caller-supplied validators (ajv,\n\t * zod, valibot) consume this field; the substrate doesn't validate.\n\t */\n\treadonly schema?: JsonSchema;\n\t/**\n\t * Optional ID generator for the per-prompt correlationId. Default is\n\t * a monotonic counter derived from a tight closure (sufficient for\n\t * in-process correlation; cross-process consumers should supply UUID\n\t * / ULID generation).\n\t */\n\treadonly idGenerator?: () => string;\n}\n\n// ---------------------------------------------------------------------------\n// humanInput\n// ---------------------------------------------------------------------------\n\n/**\n * Constructs a reactive human-input request channel. Each DATA on\n * `prompt` mints a fresh request:\n *\n * 1. Mints a fresh `correlationId` (via `opts.idGenerator` if provided).\n * 2. Publishes `TopicMessage<HumanPromptPayload>` to {@link PROMPTS_TOPIC}\n * (`{ id, schema?, correlationId, payload: { prompt, schema? } }`).\n * 3. Watches {@link RESPONSES_TOPIC} for an envelope whose\n * `correlationId` matches.\n * 4. When matched, emits the response payload as the output Node's DATA.\n *\n * **Switchmap semantics.** A new prompt arriving before the prior\n * response abandons the prior wait. Output Node emits the response for\n * the latest in-flight request only.\n *\n * **Output type `T`** is the response payload type. Caller is responsible\n * for ensuring the response producer (UI / human-side) sends the right\n * shape — `schema` is the wire-level convention for validation.\n *\n * @example\n * ```ts\n * import {\n * humanInput,\n * messagingHub,\n * PROMPTS_TOPIC,\n * RESPONSES_TOPIC,\n * } from \"@graphrefly/graphrefly-ts\";\n *\n * const hub = messagingHub(\"hub\");\n * const promptN = state<string>(\"prompt\");\n * const reply = humanInput<{ ok: boolean; reason: string }>({\n * hub,\n * prompt: promptN,\n * schema: { type: \"object\", required: [\"ok\", \"reason\"] },\n * });\n *\n * // UI / human side: subscribe to PROMPTS_TOPIC, present, then publish to\n * // RESPONSES_TOPIC with the matching correlationId.\n * promptN.emit(\"Approve change?\");\n * const decision = await awaitSettled(reply); // resolves when human responds\n * ```\n *\n * @category patterns\n */\nexport function humanInput<T>(opts: HumanInputOpts): Node<T> {\n\tconst { hub, prompt, schema, idGenerator } = opts;\n\tconst promptNode = fromAny<string>(prompt);\n\tconst promptsTopic = hub.topic<TopicMessage<HumanPromptPayload>>(PROMPTS_TOPIC);\n\tconst responsesTopic = hub.topic<TopicMessage<T>>(RESPONSES_TOPIC);\n\n\tconst nextId = idGenerator ?? defaultIdGenerator();\n\n\treturn node<T>(\n\t\t(_data, a) => {\n\t\t\tlet activeCorrelationId: string | undefined;\n\t\t\tlet respUnsub: (() => void) | undefined;\n\n\t\t\tconst promptUnsub = promptNode.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\t\trespUnsub?.();\n\t\t\t\t\t\trespUnsub = undefined;\n\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\t\tconst promptStr = m[1] as string;\n\t\t\t\t\t// Switch-map semantics: drop the prior in-flight watcher.\n\t\t\t\t\trespUnsub?.();\n\t\t\t\t\trespUnsub = undefined;\n\t\t\t\t\t// Mint new correlationId.\n\t\t\t\t\tconst correlationId = nextId();\n\t\t\t\t\tactiveCorrelationId = correlationId;\n\n\t\t\t\t\t// Snapshot the responses topic length BEFORE publishing so\n\t\t\t\t\t// we only consider envelopes that arrive AFTER this\n\t\t\t\t\t// subscription. Eliminates the stale-replay-on-subscribe\n\t\t\t\t\t// hazard (push-on-subscribe of `events` delivers the full\n\t\t\t\t\t// retained log, which could include an unrelated old\n\t\t\t\t\t// envelope whose `correlationId` happens to match if the\n\t\t\t\t\t// caller's id-generator is non-unique).\n\t\t\t\t\tconst responseCursorAtSubscribe =\n\t\t\t\t\t\t(responsesTopic.events.cache as readonly TopicMessage<T>[] | undefined)?.length ?? 0;\n\n\t\t\t\t\t// Publish the prompt envelope. Schema is carried at\n\t\t\t\t\t// envelope-level only (Phase 13.B TopicMessage<T> contract);\n\t\t\t\t\t// the payload itself is `HumanPromptPayload` and stays\n\t\t\t\t\t// schema-free.\n\t\t\t\t\tconst envelope: TopicMessage<HumanPromptPayload> = {\n\t\t\t\t\t\tid: correlationId,\n\t\t\t\t\t\tcorrelationId,\n\t\t\t\t\t\tpayload: { prompt: promptStr },\n\t\t\t\t\t\t...(schema != null && { schema }),\n\t\t\t\t\t};\n\t\t\t\t\tpromptsTopic.publish(envelope);\n\n\t\t\t\t\t// Watch responses topic for matching correlationId, but\n\t\t\t\t\t// skip the retained log (only consider envelopes at index\n\t\t\t\t\t// >= responseCursorAtSubscribe).\n\t\t\t\t\trespUnsub = responsesTopic.events.subscribe((rspMsgs) => {\n\t\t\t\t\t\tfor (const rm of rspMsgs) {\n\t\t\t\t\t\t\tif (rm[0] !== DATA) continue;\n\t\t\t\t\t\t\tconst arr = rm[1] as readonly TopicMessage<T>[];\n\t\t\t\t\t\t\tfor (let i = responseCursorAtSubscribe; i < arr.length; i++) {\n\t\t\t\t\t\t\t\tconst env = arr[i] as TopicMessage<T>;\n\t\t\t\t\t\t\t\tif (env.correlationId === activeCorrelationId) {\n\t\t\t\t\t\t\t\t\ta.emit(env.payload);\n\t\t\t\t\t\t\t\t\t// One-shot per prompt — next prompt re-arms the watcher.\n\t\t\t\t\t\t\t\t\trespUnsub?.();\n\t\t\t\t\t\t\t\t\trespUnsub = undefined;\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tonDeactivation: () => {\n\t\t\t\t\tpromptUnsub();\n\t\t\t\t\trespUnsub?.();\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tname: \"humanInput\",\n\t\t\t// Each new prompt may produce a structurally-equal response (e.g.\n\t\t\t// from a deterministic UI mock) — disable framework dedup so\n\t\t\t// repeat emissions propagate. Same precedent as `agent.out`.\n\t\t\tequals: () => false,\n\t\t},\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Default ID generator\n// ---------------------------------------------------------------------------\n\nfunction defaultIdGenerator(): () => string {\n\tlet n = 0;\n\t// `wallClockNs()` routes through the central clock per CLAUDE.md \"Time\n\t// utility rule\" — testing harnesses that monkey-patch the clock can pin\n\t// id generation deterministically.\n\tconst base = wallClockNs().toString(36);\n\treturn () => {\n\t\tn += 1;\n\t\treturn `humanInput-${base}-${n.toString(36)}`;\n\t};\n}\n","/**\n * PipelineGraph subclass (Wave A.1 Unit 1 — locked 2026-04-24).\n *\n * Specialized {@link Graph} that hosts workflow-DAG sugar methods:\n * `task` / `classify` / `combine` / `approval` / `approvalGate` / `catch`.\n * The legacy `pipeline` / `task` / `branch` / `join` / `subPipeline` /\n * `approval` / `loop` / `onFailure` factories from {@link ./index} continue\n * to work for migration ease; new code should prefer methods on this class.\n *\n * **Tier 2.3 rename:** the prior `gate(...)` method is now `approvalGate(...)`,\n * disambiguating it from the other gate-family primitives (`budgetGate` for\n * numeric constraints, `valve` for boolean switching, `policyGate` for ABAC\n * rules). The \"gating dimension\" here is **human judgment**.\n *\n * Construction: `pipelineGraph(name, opts?)` or `new PipelineGraph(name, opts)`.\n */\n\nimport type { NodeActions } from \"@graphrefly/pure-ts/core\";\nimport {\n\tbatch,\n\tCOMPLETE,\n\tDATA,\n\tERROR,\n\tfactoryTag,\n\ttype Node,\n\ttype NodeOptions,\n\tnode,\n\tplaceholderArgs,\n\tRESOLVED,\n\twallClockNs,\n} from \"@graphrefly/pure-ts/core\";\nimport type { ReactiveLogBundle } from \"@graphrefly/pure-ts/extra\";\nimport { Graph, type GraphOptions } from \"@graphrefly/pure-ts/graph\";\nimport { domainMeta } from \"../../base/meta/domain-meta.js\";\nimport { type BaseAuditRecord, createAuditLog, mutate } from \"../../base/mutation/index.js\";\n\nexport type StepRef = string | Node<unknown>;\n\nfunction meta(kind: string, extra?: Record<string, unknown>): Record<string, unknown> {\n\treturn domainMeta(\"orchestration\", kind, extra);\n}\n\n// ── Decision audit record (Audit 2 + Wave A.2 Unit 8) ─────────────────────\n\nexport type DecisionAction =\n\t| \"approve\"\n\t| \"reject\"\n\t| \"modify\"\n\t| \"drop\"\n\t| \"open\"\n\t| \"close\"\n\t| \"teardown\";\n\nexport interface Decision<T = unknown> extends BaseAuditRecord {\n\treadonly action: DecisionAction;\n\treadonly count?: number;\n\treadonly items?: readonly T[];\n\treadonly unflushed?: number;\n}\n\n/** Recommended `keyOf` for keyed-storage adapters (Audit 2 #7). */\nexport const decisionKeyOf = <T>(d: Decision<T>): string => d.action;\n\n// ── Gate ─────────────────────────────────────────────────────────────────\n\nexport interface GateOptions<_T = unknown> {\n\t/** Bounded default 1000 (Audit 2 cross-cutting). `Infinity` is opt-in. */\n\tmaxPending?: number;\n\tstartOpen?: boolean;\n\t/**\n\t * Reactive auto-approve: gate's `latestIsOpen` mirrors this node's truthy\n\t * value. False→true transition drains the pending queue.\n\t *\n\t * **`COMPLETE` / `ERROR` on the approver are silently ignored** — the gate\n\t * stays in its current state. For permanent-open latching, use\n\t * `onceOnly: true` (the first truthy approval latches; subsequent falsy\n\t * values are ignored). The gate has no graceful terminal-state behavior\n\t * for the approver itself.\n\t */\n\tapprover?: Node<unknown>;\n\t/** Latch — first truthy approval opens permanently; `close()` becomes no-op. */\n\tonceOnly?: boolean;\n\tmeta?: Record<string, unknown>;\n\thandlerVersion?: { id: string; version: string | number };\n}\n\nexport interface GateController<T> {\n\t/**\n\t * The post-gate output node. Renamed from `node` (Tier 5.2 / EC6,\n\t * 2026-04-29) to avoid shadowing `Graph.node(name)` when a gate is\n\t * accessed off a `PipelineGraph` instance.\n\t */\n\treadonly output: Node<T>;\n\treadonly pending: Node<readonly T[]>;\n\treadonly count: Node<number>;\n\treadonly isOpen: Node<boolean>;\n\treadonly droppedCount: Node<number>;\n\treadonly decisions: ReactiveLogBundle<Decision<T>>;\n\treadonly audit: ReactiveLogBundle<Decision<T>>;\n\tapprove(count?: number): void;\n\treject(count?: number): void;\n\tmodify(fn: (value: T, index: number, pending: readonly T[]) => T, count?: number): void;\n\topen(): void;\n\tclose(): void;\n}\n\n// ── catch (rename of onFailure; Wave A.2 Unit 10) ─────────────────────────\n\n/**\n * Terminal-cause discriminator for the {@link PipelineGraph.catch} recovery\n * handler. Tier 1.6.3 status-enum migration: was `{ kind: \"complete\" | \"error\" }`\n * pre-1.0; aligned with the canonical lifecycle enum\n * (`status: \"running\" | \"completed\" | \"errored\" | \"cancelled\"`). The variant\n * structure is preserved — `errored` still carries `error: unknown` and\n * `completed` carries no payload.\n */\nexport type TerminalCause = { kind: \"errored\"; error: unknown } | { kind: \"completed\" };\n\nexport interface CatchOptions<_T> {\n\t/**\n\t * Which terminal cause to recover. Default `\"errored\"` (Tier 1.6.3 rename\n\t * of `\"error\"`). `\"completed\"` recovers COMPLETE; `\"terminal\"` recovers\n\t * either. Aligns with the canonical lifecycle enum that\n\t * {@link TerminalCause.kind} now uses.\n\t */\n\ton?: \"errored\" | \"completed\" | \"terminal\";\n\tcompleteWhenDepsComplete?: boolean;\n\tmeta?: Record<string, unknown>;\n\thandlerVersion?: { id: string; version: string | number };\n}\n\n// ── classify result envelope (Wave A.1 Unit 3) ───────────────────────────\n\nexport interface ClassifyResult<TTag extends string, T> {\n\treadonly tag: TTag | \"error\";\n\treadonly value: T;\n\treadonly error?: unknown;\n}\n\n// ── PipelineGraph ────────────────────────────────────────────────────────\n\nexport class PipelineGraph extends Graph {\n\t// -- task -----------------------------------------------------------------\n\n\t/**\n\t * Register a workflow task (`node` + auto-add). String deps resolve via\n\t * `this.resolve(path)`; Node deps via {@link Graph.nameOf} O(1) lookup.\n\t *\n\t * `run` receives `(data: readonly unknown[], ctx)` — the snapshot of latest\n\t * values per dep (same shape as the old `DerivedFn` sugar).\n\t */\n\ttask<T>(\n\t\tname: string,\n\t\trun: (data: readonly unknown[], ctx: { prevData: readonly unknown[] }) => T | undefined | null,\n\t\topts: { deps?: ReadonlyArray<StepRef>; meta?: Record<string, unknown> } = {},\n\t): Node<T> {\n\t\tconst deps = (opts.deps ?? []).map((d) => this._resolveStep(d));\n\t\tconst step = node<T>(\n\t\t\tdeps,\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst result = run(data, ctx);\n\t\t\t\tif (result !== undefined && result !== null) actions.emit(result);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: meta(\"task\", opts.meta),\n\t\t\t} as NodeOptions<T>,\n\t\t);\n\t\tthis.add(step, { name });\n\t\treturn step;\n\t}\n\n\t// -- classify (n-way; replaces binary `branch`) --------------------------\n\n\tclassify<TTag extends string, T>(\n\t\tname: string,\n\t\tsource: StepRef,\n\t\ttagger: (value: T) => TTag,\n\t\topts: { meta?: Record<string, unknown> } = {},\n\t): Node<ClassifyResult<TTag, T>> {\n\t\tconst src = this._resolveStep(source);\n\t\tconst step = node<ClassifyResult<TTag, T>>(\n\t\t\t[src],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst value = data[0];\n\t\t\t\ttry {\n\t\t\t\t\tactions.emit({ tag: tagger(value as T), value: value as T });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tactions.emit({ tag: \"error\" as const, value: value as T, error });\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: meta(\"classify\", opts.meta),\n\t\t\t} as NodeOptions<ClassifyResult<TTag, T>>,\n\t\t);\n\t\tthis.add(step, { name });\n\t\treturn step;\n\t}\n\n\t// -- combine (keyed-record fan-in; replaces positional `join`) -----------\n\n\tcombine<R extends Record<string, StepRef>>(\n\t\tname: string,\n\t\tdeps: R,\n\t\topts: { meta?: Record<string, unknown> } = {},\n\t): Node<{ [K in keyof R]: unknown }> {\n\t\tconst keys = Object.keys(deps) as Array<keyof R & string>;\n\t\tconst nodes = keys.map((k) => this._resolveStep(deps[k] as StepRef));\n\t\tconst step = node<{ [K in keyof R]: unknown }>(\n\t\t\tnodes,\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst values = batchData.map((batch, i) =>\n\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t);\n\t\t\t\tconst out = {} as { [K in keyof R]: unknown };\n\t\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\t\t(out as Record<string, unknown>)[keys[i] as string] = values[i];\n\t\t\t\t}\n\t\t\t\tactions.emit(out);\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tmeta: meta(\"combine\", opts.meta),\n\t\t\t} as NodeOptions<{ [K in keyof R]: unknown }>,\n\t\t);\n\t\tthis.add(step, { name });\n\t\treturn step;\n\t}\n\n\t// -- approvalGate ---------------------------------------------------------\n\n\tapprovalGate<T>(name: string, source: StepRef, opts: GateOptions<T> = {}): GateController<T> {\n\t\tconst maxPending = opts.maxPending ?? 1000;\n\t\tif (maxPending < 1 && maxPending !== Number.POSITIVE_INFINITY) {\n\t\t\tthrow new RangeError(\"approvalGate: maxPending must be >= 1\");\n\t\t}\n\t\tconst startOpen = opts.startOpen ?? false;\n\n\t\t// C3 — wrap a foreign Node source in a local proxy derived. The proxy\n\t\t// is owned by THIS graph; downstream wiring uses the proxy (not the\n\t\t// foreign Node) so the cross-graph ownership invariant holds. Causal\n\t\t// chain is preserved via the dep edge — `describe()` still surfaces\n\t\t// the foreign Node's path through the proxy.\n\t\tlet src: Node<unknown>;\n\t\tif (typeof source === \"string\") {\n\t\t\tsrc = this._resolveStep(source);\n\t\t} else if (this.nameOf(source) !== undefined) {\n\t\t\tsrc = source;\n\t\t} else {\n\t\t\tconst proxy = node<unknown>(\n\t\t\t\t[source],\n\t\t\t\t(batchData, actions) => {\n\t\t\t\t\tconst batch0 = batchData[0];\n\t\t\t\t\tif (batch0 == null || batch0.length === 0) return;\n\t\t\t\t\tfor (const v of batch0) actions.emit(v);\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\tmeta: factoryTag(\"proxy\"),\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.add(proxy, { name: `${name}/source` });\n\t\t\tsrc = proxy;\n\t\t}\n\n\t\t// State subgraph\n\t\tconst internal = new Graph(`${name}-state`);\n\t\tconst pendingNode = internal.state<readonly T[]>(\"pending\", [], {\n\t\t\tequals: () => false,\n\t\t});\n\t\tconst isOpenNode = internal.state<boolean>(\"isOpen\", startOpen);\n\t\tconst countNode = internal.derived<number>(\"count\", [\"pending\"], (batchData, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\treturn [(data[0] as readonly T[]).length];\n\t\t});\n\t\tconst droppedCountNode = internal.state<number>(\"droppedCount\", 0);\n\t\tconst decisions = createAuditLog<Decision<T>>({\n\t\t\tname: \"decisions\",\n\t\t\tretainedLimit: 1024,\n\t\t\tgraph: internal,\n\t\t});\n\t\tthis.mount(`${name}-state`, internal);\n\n\t\tlet queue: T[] = [];\n\t\tlet torn = false;\n\t\tlet latched = false;\n\t\t// Closure-mirror per COMPOSITION-GUIDE §28 factory-time seed pattern.\n\t\t// `output` samples `latestIsOpen` inside its fn body when deciding\n\t\t// emit-vs-enqueue; reading a closure variable is NOT a P3 violation\n\t\t// (§28). An in-session Phase 9 plan would have relocated the value to\n\t\t// `internal.derived(\"latestIsOpen\", ...)` + `.cache` reads (which IS\n\t\t// a P3 violation); plan was reverted at the design level after\n\t\t// re-reading §28 — pattern preserved here. See `archive/docs/SESSION-\n\t\t// graph-narrow-waist.md` § \"Status of existing modifications\".\n\t\tlet latestIsOpen = startOpen;\n\t\tconst isOpenUnsub = isOpenNode.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) latestIsOpen = m[1] as boolean;\n\t\t\t}\n\t\t});\n\t\tthis.addDisposer(isOpenUnsub);\n\n\t\tfunction syncPending(): void {\n\t\t\tpendingNode.emit([...queue]);\n\t\t}\n\n\t\tfunction recordDecision(\n\t\t\taction: DecisionAction,\n\t\t\titems?: readonly T[],\n\t\t\tunflushed?: number,\n\t\t): void {\n\t\t\tdecisions.append({\n\t\t\t\taction,\n\t\t\t\tt_ns: wallClockNs(),\n\t\t\t\t...(items !== undefined ? { items, count: items.length } : {}),\n\t\t\t\t...(unflushed !== undefined ? { unflushed } : {}),\n\t\t\t\t...(opts.handlerVersion != null ? { handlerVersion: opts.handlerVersion } : {}),\n\t\t\t} as Decision<T>);\n\t\t}\n\n\t\tfunction enqueue(value: T): void {\n\t\t\tqueue.push(value);\n\t\t\tif (queue.length > maxPending) {\n\t\t\t\tconst dropped = queue.shift() as T;\n\t\t\t\tdroppedCountNode.emit((droppedCountNode.cache as number) + 1);\n\t\t\t\trecordDecision(\"drop\", [dropped]);\n\t\t\t}\n\t\t\tsyncPending();\n\t\t}\n\n\t\tfunction dequeue(n: number): T[] {\n\t\t\tconst items = queue.splice(0, n);\n\t\t\tsyncPending();\n\t\t\treturn items;\n\t\t}\n\n\t\tconst output = node<T>(\n\t\t\t[src],\n\t\t\t(batchData, actions, ctx) => {\n\t\t\t\tconst terminal = ctx.terminalDeps[0];\n\t\t\t\tif (terminal !== undefined) {\n\t\t\t\t\ttorn = true;\n\t\t\t\t\tconst unflushed = queue.length;\n\t\t\t\t\tqueue = [];\n\t\t\t\t\tsyncPending();\n\t\t\t\t\trecordDecision(\"teardown\", undefined, unflushed);\n\t\t\t\t\tactions.down(terminal === true ? [[COMPLETE]] : [[ERROR, terminal]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst batch0 = batchData[0];\n\t\t\t\tif (batch0 == null || batch0.length === 0) {\n\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const v of batch0 as T[]) {\n\t\t\t\t\tif (latestIsOpen) {\n\t\t\t\t\t\tactions.emit(v);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenqueue(v);\n\t\t\t\t\t\tactions.down([[RESOLVED]]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t// Spec §2.7 R2.7.1 (DS-2.7.A). fn must fire on\n\t\t\t\t// upstream-COMPLETE/ERROR-only-without-DATA so the\n\t\t\t\t// teardown-decision record + downstream terminal forward run.\n\t\t\t\tterminalAsRealInput: true,\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\t// Spec §2.7 R2.7.1 (DS-2.7.A). `catch` exists to fire on a\n\t\t\t\t// source terminal — its whole job is `recover(cause, …)` on a\n\t\t\t\t// terminal-only wave. Without this opt-in the gate holds and\n\t\t\t\t// the recover branch never runs.\n\t\t\t\tterminalAsRealInput: true,\n\t\t\t\tmeta: meta(\"catch\", opts.meta),\n\t\t\t} as NodeOptions<T>,\n\t\t);\n\t\tthis.add(step, { name });\n\t\treturn step;\n\t}\n\n\t// -- internals ----------------------------------------------------------\n\n\tprivate _resolveStep(dep: StepRef): Node<unknown> {\n\t\tif (typeof dep === \"string\") return this.resolve(dep);\n\t\tconst existing = this.nameOf(dep);\n\t\tif (existing === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`PipelineGraph \"${this.name}\": Node dep is not registered. Pass a string path or call graph.add(node) first.`,\n\t\t\t);\n\t\t}\n\t\treturn dep;\n\t}\n}\n\n/** Factory wrapper — `pipelineGraph(name, opts?)`. Equivalent to `new PipelineGraph(name, opts)`. */\nexport function pipelineGraph(name: string, opts?: GraphOptions): PipelineGraph {\n\tconst g = new PipelineGraph(name, opts);\n\t// Tier 1.5.3 Phase 2.5 (DG1=B): tag the Graph with its constructing\n\t// factory so `describe()` exposes provenance. `factoryArgs` is the\n\t// constructor opts (sans the `factory`/`factoryArgs` keys themselves to\n\t// avoid recursive nesting). QA F13: route through `placeholderArgs` for\n\t// consistency with sibling factories — `GraphOptions[key: string]: unknown`\n\t// is open-ended, so user-extension keys may carry non-JSON content.\n\tconst { factory: _f, factoryArgs: _fa, ...tagArgs } = (opts ?? {}) as Record<string, unknown>;\n\tg.tagFactory(\"pipelineGraph\", placeholderArgs(tagArgs));\n\treturn g;\n}\n","/**\n * Phase 13.F — `tracker` sibling preset.\n *\n * Source: `archive/docs/SESSION-human-llm-intervention-primitives.md` §5\n * \"Sibling presets on the substrate\" + `archive/docs/SKETCH-reactive-tracker-factory.md`\n * + `project_reactive_tracker` memory.\n *\n * **Role.** Park-as-deferred queue consumer. The tracker is the\n * cursor-based read surface over the well-known {@link DEFERRED_TOPIC}\n * — items the harness (or any consumer) defers for later attention.\n * Sibling to `humanInput` and `approvalGate`; all three share substrate\n * (hub + envelope + reactive cursor) but differ in role.\n *\n * **Cursor handle.** Per the SESSION's \"Cursor handle\" return — tracker\n * exposes the cursor-based pull / ack surface so the consumer (a\n * dashboard, a post-run review, an LLM watcher) can iterate over\n * unconsumed items in order.\n *\n * **Naming locked (open question §11 #3 resolved):** `tracker`. The\n * SESSION mentioned `tracker` vs `parkedQueue` vs `deferredTracker`;\n * `tracker` is the simplest and most general — the deferred-queue\n * semantic is a recipe, not a name overload. Other use cases (issue\n * tracker, todo tracker, retrospective tracker per\n * `project_reactive_tracker`) reuse the same primitive.\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport {\n\tDEFERRED_TOPIC,\n\ttype MessagingHubGraph,\n\ttype SubscriptionGraph,\n\tsubscription,\n\ttype TopicGraph,\n} from \"../messaging/index.js\";\n\n// ---------------------------------------------------------------------------\n// Bundle\n// ---------------------------------------------------------------------------\n\n/**\n * Bundle returned by {@link tracker}. Wraps a topic + cursor-based\n * subscription with imperative `add` / `ack` helpers.\n */\nexport interface TrackerBundle<T> {\n\t/**\n\t * The underlying topic. Either freshly minted on the hub at\n\t * `topicName` (default {@link DEFERRED_TOPIC}) or reused if the topic\n\t * already exists.\n\t */\n\treadonly topic: TopicGraph<T>;\n\t/** Cursor-based subscription view over `topic.events`. */\n\treadonly subscription: SubscriptionGraph<T>;\n\t/**\n\t * Items beyond the current cursor — i.e. the deferred queue's\n\t * \"pending\" head. Reactive `Node<readonly T[]>`.\n\t */\n\treadonly pending: Node<readonly T[]>;\n\t/** Current cursor position (number of items already acked). */\n\treadonly cursor: Node<number>;\n\t/**\n\t * Reactive total count of items added since construction (matches the\n\t * topic's retained-events length until the topic's retention cap is\n\t * reached).\n\t */\n\treadonly total: Node<number>;\n\t/** Append an item to the deferred queue. */\n\tadd(item: T): void;\n\t/**\n\t * Advance the cursor past `n` items (default 1). Acks the next batch\n\t * of pending items; subsequent reads of `pending` exclude them.\n\t */\n\tack(n?: number): void;\n\t/**\n\t * Pull-and-ack at most `limit` items in one shot. Returns the items\n\t * + the new cursor position (matches `subscription.pullAndAck`).\n\t */\n\tpullAndAck(limit?: number): { items: readonly T[]; cursor: number };\n}\n\n// ---------------------------------------------------------------------------\n// tracker()\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link tracker}.\n */\nexport interface TrackerOpts {\n\t/**\n\t * Messaging hub. The tracker creates / reuses a topic on this hub\n\t * named `topicName` (default {@link DEFERRED_TOPIC}).\n\t */\n\treadonly hub: MessagingHubGraph;\n\t/**\n\t * Topic name on the hub. Default {@link DEFERRED_TOPIC}. Override to\n\t * use a non-deferred topic (e.g. a custom domain queue).\n\t */\n\treadonly topicName?: string;\n\t/**\n\t * Subscription graph name. Default `\"tracker\"`. Multiple trackers on\n\t * the same hub topic must use distinct names.\n\t */\n\treadonly name?: string;\n\t/**\n\t * Initial cursor. Forwarded to the underlying subscription. See\n\t * {@link SubscriptionOptions.from}.\n\t */\n\treadonly from?: \"now\" | \"retained\" | number;\n}\n\n/**\n * Mints a tracker bundle over a hub topic.\n *\n * @example\n * ```ts\n * import { messagingHub, tracker } from \"@graphrefly/graphrefly-ts\";\n *\n * const hub = messagingHub(\"hub\");\n * const issues = tracker<{ summary: string }>({ hub });\n *\n * issues.add({ summary: \"investigate flaky test\" });\n * issues.add({ summary: \"follow up on auth refactor\" });\n *\n * // Subscribe to the pending queue (for a dashboard, watcher, etc.)\n * issues.pending.subscribe((msgs) => { ... });\n *\n * // Imperative pull + ack\n * const next = issues.pullAndAck(1);\n * console.log(next.items[0]?.summary);\n * ```\n *\n * @category patterns\n */\nexport function tracker<T>(opts: TrackerOpts): TrackerBundle<T> {\n\tconst { hub, topicName, name, from } = opts;\n\tconst effectiveTopicName = topicName ?? DEFERRED_TOPIC;\n\tconst effectiveName = name ?? \"tracker\";\n\n\t// Reuse existing topic on the hub or lazy-create.\n\tconst topicGraph = hub.topic<T>(effectiveTopicName);\n\n\t// Cursor-based subscription. The subscription is owned by the tracker\n\t// (not mounted on the hub) — multiple trackers can share the topic with\n\t// independent cursors.\n\tconst sub: SubscriptionGraph<T> = subscription<T>(effectiveName, topicGraph, {\n\t\t...(from != null && { from }),\n\t});\n\n\t// `total` derives from topic.events.length. Use a derived node owned by\n\t// the subscription for a self-contained surface. `keepAlive: true` so\n\t// `total.cache` stays current even without external subscribers.\n\tconst total = sub.derived<number>(\n\t\t\"tracker-total\",\n\t\t[topicGraph.events],\n\t\t(data, ctx) => {\n\t\t\tconst b0 = data[0];\n\t\t\tconst arr =\n\t\t\t\tb0 != null && b0.length > 0\n\t\t\t\t\t? (b0.at(-1) as readonly T[])\n\t\t\t\t\t: ((ctx.prevData[0] as readonly T[] | undefined) ?? []);\n\t\t\treturn [arr.length];\n\t\t},\n\t\t{ keepAlive: true },\n\t);\n\n\treturn {\n\t\ttopic: topicGraph,\n\t\tsubscription: sub,\n\t\tpending: sub.available,\n\t\tcursor: sub.cursor,\n\t\ttotal,\n\t\tadd: (item) => topicGraph.publish(item),\n\t\tack: (n) => sub.ack(n ?? 1),\n\t\tpullAndAck: (limit) => sub.pullAndAck(limit),\n\t};\n}\n"],"mappings":"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","names":["COMPLETE","DATA","node","wallClockNs","node","batch","DATA","wallClockNs","COMPLETE"]}
|