@tangle-network/agent-runtime 0.104.0 → 0.106.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +176 -42
  2. package/dist/activation-CRjVfOiy.js +203 -0
  3. package/dist/activation-CRjVfOiy.js.map +1 -0
  4. package/dist/activation-DyWB0K6E.d.ts +98 -0
  5. package/dist/agent.d.ts +216 -234
  6. package/dist/agent.js +615 -547
  7. package/dist/agent.js.map +1 -1
  8. package/dist/analyst-loop-DGdtVENg.js +517 -0
  9. package/dist/analyst-loop-DGdtVENg.js.map +1 -0
  10. package/dist/analyst-loop.d.ts +10 -43
  11. package/dist/analyst-loop.js +2 -11
  12. package/dist/backends-Dy8NujB4.js +713 -0
  13. package/dist/backends-Dy8NujB4.js.map +1 -0
  14. package/dist/candidate-execution/index.d.ts +4 -192
  15. package/dist/candidate-execution/index.js +5 -66
  16. package/dist/candidate-execution-DqMbv1rU.js +488 -0
  17. package/dist/candidate-execution-DqMbv1rU.js.map +1 -0
  18. package/dist/coder-yhVWbdWc.js +40 -0
  19. package/dist/coder-yhVWbdWc.js.map +1 -0
  20. package/dist/conversation-XucG_K3l.js +1265 -0
  21. package/dist/conversation-XucG_K3l.js.map +1 -0
  22. package/dist/conversation.d.ts +2 -804
  23. package/dist/conversation.js +2 -55
  24. package/dist/environment-provider-CfLUmKmf.js +1168 -0
  25. package/dist/environment-provider-CfLUmKmf.js.map +1 -0
  26. package/dist/environment-provider-IUGU3epE.d.ts +964 -0
  27. package/dist/environment-provider.d.ts +2 -78
  28. package/dist/environment-provider.js +2 -18
  29. package/dist/errors-DEAvWQPy.js +111 -0
  30. package/dist/errors-DEAvWQPy.js.map +1 -0
  31. package/dist/improvement-adapter-Cr5TBSji.d.ts +166 -0
  32. package/dist/improvement-cycle-C095kS_g.js +2624 -0
  33. package/dist/improvement-cycle-C095kS_g.js.map +1 -0
  34. package/dist/index-BGdxAwfO.d.ts +838 -0
  35. package/dist/index-C-FYUuFG.d.ts +193 -0
  36. package/dist/index-CbNM40xG.d.ts +140 -0
  37. package/dist/index-DruSKs3Z.d.ts +7224 -0
  38. package/dist/index-Efjb3nrQ.d.ts +671 -0
  39. package/dist/index.d.ts +14 -1134
  40. package/dist/index.js +2134 -1972
  41. package/dist/index.js.map +1 -1
  42. package/dist/intelligence.d.ts +776 -888
  43. package/dist/intelligence.js +1466 -1410
  44. package/dist/intelligence.js.map +1 -1
  45. package/dist/{kb-gate-CwHO0vz6.d.ts → kb-gate-C8z2juK8.d.ts} +33 -31
  46. package/dist/kb-gate-DpaSwXVx.js +80 -0
  47. package/dist/kb-gate-DpaSwXVx.js.map +1 -0
  48. package/dist/knowledge-Ku-mPP4f.js +433 -0
  49. package/dist/knowledge-Ku-mPP4f.js.map +1 -0
  50. package/dist/knowledge.d.ts +2 -150
  51. package/dist/knowledge.js +2 -40
  52. package/dist/local-harness-Dh8PJ0ot.d.ts +455 -0
  53. package/dist/loop-runner-bin-BXsFEUcf.d.ts +162 -0
  54. package/dist/loop-runner-bin-BwjQ1NfH.js +268 -0
  55. package/dist/loop-runner-bin-BwjQ1NfH.js.map +1 -0
  56. package/dist/loop-runner-bin.d.ts +2 -17
  57. package/dist/loop-runner-bin.js +2 -24
  58. package/dist/loops.d.ts +5 -4164
  59. package/dist/loops.js +8 -419
  60. package/dist/mcp/bin.d.ts +1 -1
  61. package/dist/mcp/bin.js +116 -146
  62. package/dist/mcp/bin.js.map +1 -1
  63. package/dist/mcp/index.d.ts +295 -437
  64. package/dist/mcp/index.js +1242 -1177
  65. package/dist/mcp/index.js.map +1 -1
  66. package/dist/mcp/memory-bin.d.ts +1 -1
  67. package/dist/mcp/memory-bin.js +37 -16
  68. package/dist/mcp/memory-bin.js.map +1 -1
  69. package/dist/memory-server-DL6cE2Ag.js +234 -0
  70. package/dist/memory-server-DL6cE2Ag.js.map +1 -0
  71. package/dist/model-resolution-Btd9iIKV.js +98 -0
  72. package/dist/model-resolution-Btd9iIKV.js.map +1 -0
  73. package/dist/openai-tools-B68JaOCx.d.ts +24 -0
  74. package/dist/openai-tools-CKLy1C7M.js +44 -0
  75. package/dist/openai-tools-CKLy1C7M.js.map +1 -0
  76. package/dist/otel-export-D34IQW1C.js +843 -0
  77. package/dist/otel-export-D34IQW1C.js.map +1 -0
  78. package/dist/platform.d.ts +188 -185
  79. package/dist/platform.js +185 -218
  80. package/dist/platform.js.map +1 -1
  81. package/dist/prepare-B53sPV7M.js +4292 -0
  82. package/dist/prepare-B53sPV7M.js.map +1 -0
  83. package/dist/primeintellect/index.d.ts +150 -147
  84. package/dist/primeintellect/index.js +626 -1004
  85. package/dist/primeintellect/index.js.map +1 -1
  86. package/dist/profiles.d.ts +296 -490
  87. package/dist/profiles.js +722 -749
  88. package/dist/profiles.js.map +1 -1
  89. package/dist/protected-model-port-BLPH5VVv.js +722 -0
  90. package/dist/protected-model-port-BLPH5VVv.js.map +1 -0
  91. package/dist/protected-model-port-BP6Z4eau.d.ts +283 -0
  92. package/dist/protected-redaction--F3v1oo8.js +200 -0
  93. package/dist/protected-redaction--F3v1oo8.js.map +1 -0
  94. package/dist/redact-D-u-rrcn.js +82 -0
  95. package/dist/redact-D-u-rrcn.js.map +1 -0
  96. package/dist/redact-kbIOjfjM.d.ts +452 -0
  97. package/dist/researcher-CoVqNhfI.js +433 -0
  98. package/dist/researcher-CoVqNhfI.js.map +1 -0
  99. package/dist/runtime-BG0BziaP.js +5408 -0
  100. package/dist/runtime-BG0BziaP.js.map +1 -0
  101. package/dist/sandbox-events-DeI5xX8P.js +316 -0
  102. package/dist/sandbox-events-DeI5xX8P.js.map +1 -0
  103. package/dist/spawn-journal-CwPvKUTa.js +456 -0
  104. package/dist/spawn-journal-CwPvKUTa.js.map +1 -0
  105. package/dist/structural-rollout-IXUEplky.js +1445 -0
  106. package/dist/structural-rollout-IXUEplky.js.map +1 -0
  107. package/dist/substrate-B0TYNrXn.js +27 -0
  108. package/dist/substrate-B0TYNrXn.js.map +1 -0
  109. package/dist/{substrate-Dyiqmd3o.d.ts → substrate-BcnuSHXm.d.ts} +57 -54
  110. package/dist/supervise-BiRutHS9.js +7321 -0
  111. package/dist/supervise-BiRutHS9.js.map +1 -0
  112. package/dist/supervisor-DTKhF-RV.js +3826 -0
  113. package/dist/supervisor-DTKhF-RV.js.map +1 -0
  114. package/dist/testing.d.ts +4 -3
  115. package/dist/testing.js +2478 -2637
  116. package/dist/testing.js.map +1 -1
  117. package/dist/tool-server-RcWgLIsL.js +141 -0
  118. package/dist/tool-server-RcWgLIsL.js.map +1 -0
  119. package/dist/trace-propagation-CJJC7SVB.js +57 -0
  120. package/dist/trace-propagation-CJJC7SVB.js.map +1 -0
  121. package/dist/types-BaIpb0XT.d.ts +492 -0
  122. package/dist/types-BevOjfTY.d.ts +765 -0
  123. package/dist/types-C9j4qg6l.d.ts +500 -0
  124. package/dist/types-Cja5OTGh.d.ts +190 -0
  125. package/dist/util-MVgdwuIS.js +145 -0
  126. package/dist/util-MVgdwuIS.js.map +1 -0
  127. package/dist/workspace-archive-BosQiotA.js +575 -0
  128. package/dist/workspace-archive-BosQiotA.js.map +1 -0
  129. package/package.json +43 -55
  130. package/skills/build-with-agent-runtime/SKILL.md +16 -9
  131. package/skills/loop-writer/SKILL.md +1 -1
  132. package/dist/activation-Cm-9MMX1.d.ts +0 -69
  133. package/dist/analyst-loop.js.map +0 -1
  134. package/dist/backends-BO4Jqoe2.d.ts +0 -134
  135. package/dist/candidate-execution/index.js.map +0 -1
  136. package/dist/chunk-2KGAN2HM.js +0 -1256
  137. package/dist/chunk-2KGAN2HM.js.map +0 -1
  138. package/dist/chunk-2QJSNOGK.js +0 -48
  139. package/dist/chunk-2QJSNOGK.js.map +0 -1
  140. package/dist/chunk-2UABGGUB.js +0 -474
  141. package/dist/chunk-2UABGGUB.js.map +0 -1
  142. package/dist/chunk-2VZYRB55.js +0 -834
  143. package/dist/chunk-2VZYRB55.js.map +0 -1
  144. package/dist/chunk-2X65HYMI.js +0 -3526
  145. package/dist/chunk-2X65HYMI.js.map +0 -1
  146. package/dist/chunk-3MDZX7YU.js +0 -125
  147. package/dist/chunk-3MDZX7YU.js.map +0 -1
  148. package/dist/chunk-3PPVCS75.js +0 -199
  149. package/dist/chunk-3PPVCS75.js.map +0 -1
  150. package/dist/chunk-5HNDYWUT.js +0 -6424
  151. package/dist/chunk-5HNDYWUT.js.map +0 -1
  152. package/dist/chunk-5IBQAPVB.js +0 -29
  153. package/dist/chunk-5IBQAPVB.js.map +0 -1
  154. package/dist/chunk-5QOB7H74.js +0 -387
  155. package/dist/chunk-5QOB7H74.js.map +0 -1
  156. package/dist/chunk-ATDFUJYI.js +0 -4728
  157. package/dist/chunk-ATDFUJYI.js.map +0 -1
  158. package/dist/chunk-B7K7V22Y.js +0 -699
  159. package/dist/chunk-B7K7V22Y.js.map +0 -1
  160. package/dist/chunk-DPEUKJRO.js +0 -27
  161. package/dist/chunk-DPEUKJRO.js.map +0 -1
  162. package/dist/chunk-FD2MBMOH.js +0 -494
  163. package/dist/chunk-FD2MBMOH.js.map +0 -1
  164. package/dist/chunk-FJI3EXU3.js +0 -2402
  165. package/dist/chunk-FJI3EXU3.js.map +0 -1
  166. package/dist/chunk-HAO4CXHP.js +0 -200
  167. package/dist/chunk-HAO4CXHP.js.map +0 -1
  168. package/dist/chunk-ISPWRSEC.js +0 -408
  169. package/dist/chunk-ISPWRSEC.js.map +0 -1
  170. package/dist/chunk-KRBFHMV6.js +0 -1228
  171. package/dist/chunk-KRBFHMV6.js.map +0 -1
  172. package/dist/chunk-L5DST3QC.js +0 -351
  173. package/dist/chunk-L5DST3QC.js.map +0 -1
  174. package/dist/chunk-M22PL4GH.js +0 -171
  175. package/dist/chunk-M22PL4GH.js.map +0 -1
  176. package/dist/chunk-NURIQBJQ.js +0 -72
  177. package/dist/chunk-NURIQBJQ.js.map +0 -1
  178. package/dist/chunk-PZZKQVQV.js +0 -52
  179. package/dist/chunk-PZZKQVQV.js.map +0 -1
  180. package/dist/chunk-Q2JSAVQ3.js +0 -671
  181. package/dist/chunk-Q2JSAVQ3.js.map +0 -1
  182. package/dist/chunk-SBTWKPVR.js +0 -5576
  183. package/dist/chunk-SBTWKPVR.js.map +0 -1
  184. package/dist/chunk-SGKPNBXE.js +0 -60
  185. package/dist/chunk-SGKPNBXE.js.map +0 -1
  186. package/dist/chunk-SNSMRT6H.js +0 -680
  187. package/dist/chunk-SNSMRT6H.js.map +0 -1
  188. package/dist/chunk-STJEHM5F.js +0 -1338
  189. package/dist/chunk-STJEHM5F.js.map +0 -1
  190. package/dist/chunk-UPWGXKXB.js +0 -254
  191. package/dist/chunk-UPWGXKXB.js.map +0 -1
  192. package/dist/chunk-YEJR7IXO.js +0 -68
  193. package/dist/chunk-YEJR7IXO.js.map +0 -1
  194. package/dist/chunk-ZXICDSAK.js +0 -907
  195. package/dist/chunk-ZXICDSAK.js.map +0 -1
  196. package/dist/completion-gate-Bv47cOnn.d.ts +0 -256
  197. package/dist/conversation.js.map +0 -1
  198. package/dist/coordination-CxtzMxSM.d.ts +0 -2570
  199. package/dist/environment-provider.js.map +0 -1
  200. package/dist/improve--2A0gK1-.d.ts +0 -440
  201. package/dist/improvement-adapter-HAZz-7vK.d.ts +0 -203
  202. package/dist/knowledge.js.map +0 -1
  203. package/dist/local-harness-CtK9dSny.d.ts +0 -175
  204. package/dist/loop-runner-bin-DUOGtvOl.d.ts +0 -207
  205. package/dist/loop-runner-bin.js.map +0 -1
  206. package/dist/loops.js.map +0 -1
  207. package/dist/openai-tools-fnj6SRVg.d.ts +0 -46
  208. package/dist/protected-model-port-DzkUY3HQ.d.ts +0 -271
  209. package/dist/sanitize-DEbPNtyI.d.ts +0 -328
  210. package/dist/structural-rollout-C4mabf87.d.ts +0 -446
  211. package/dist/supervise-7q9F5brx.d.ts +0 -379
  212. package/dist/types-BCoemcXU.d.ts +0 -802
  213. package/dist/types-BwoZWq-i.d.ts +0 -510
  214. package/dist/types-Cbp72qyu.d.ts +0 -491
  215. package/dist/types-CmYCMbFT.d.ts +0 -203
  216. package/dist/types-CvNwMzQt.d.ts +0 -957
  217. package/dist/worktree-fanout-WsOzt8qu.d.ts +0 -999
@@ -0,0 +1,456 @@
1
+ import { f as zeroTokenUsage } from "./util-MVgdwuIS.js";
2
+ import { createHash } from "node:crypto";
3
+ //#region src/durable/spawn-journal.ts
4
+ /**
5
+ *
6
+ * Event-sourced spawn journal for the recursive execution atom (build steps 3 + 7).
7
+ *
8
+ * The supervision tree is journaled as an append-only event log: every `spawned`,
9
+ * `settled`, and `cancelled` is recorded AFTER it is observed-committed (never
10
+ * speculative), mirroring `ConversationJournal`'s begin/append/load shape. The log
11
+ * holds only the THIN decision record — ids, parentage, budget, the spend a decision
12
+ * consumed, and a content-addressed `outRef`. The payloads the driver branched on
13
+ * (the `out` artifacts) live in a separate `ResultBlobStore`, keyed by `outRef`, so
14
+ * the journal stays small (decisions) and replay rehydrates the exact `Settled` from
15
+ * the blob store (evidence). This is the decision/payload split the replay argument
16
+ * rests on (B1/B2).
17
+ *
18
+ * Replay determinism (B2): `seq` is the monotonic cursor order `scope.next()` yielded
19
+ * each settlement — NOT wall-clock. `replaySpawnTree` sorts strictly by `seq` before
20
+ * touching the blob store, so the order in which rehydration `get`s resolve can never
21
+ * reorder the replayed `Settled[]`; the result is identical regardless of blob latency.
22
+ *
23
+ * @experimental
24
+ */
25
+ /**
26
+ * Mint the content-addressed `outRef` for a result artifact: `sha256:<hex>` over a
27
+ * stable JSON encoding. Producers call this to derive the `outRef` they journal and
28
+ * `put`; the FS/in-mem stores re-derive it on `put` to verify the supplied ref
29
+ * matches (fail loud on a mismatch — a forged ref breaks the replay invariant).
30
+ *
31
+ * Stable encoding: object keys are sorted recursively so two structurally-equal
32
+ * artifacts hash identically regardless of key insertion order.
33
+ */
34
+ function contentAddress(artifact) {
35
+ return `sha256:${createHash("sha256").update(stableStringify(artifact), "utf-8").digest("hex")}`;
36
+ }
37
+ function stableStringify(value) {
38
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
39
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
40
+ return `{${Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
41
+ }
42
+ /**
43
+ * In-memory `ResultBlobStore`. Content-addressed: `put` verifies the supplied
44
+ * `outRef` matches the artifact's hash so a stale/forged ref fails loud rather than
45
+ * silently rehydrating the wrong payload. Idempotent on an identical re-put.
46
+ */
47
+ var InMemoryResultBlobStore = class {
48
+ blobs = /* @__PURE__ */ new Map();
49
+ async put(outRef, artifact) {
50
+ assertContentAddress(outRef, artifact);
51
+ this.blobs.set(outRef, artifact);
52
+ }
53
+ async get(outRef) {
54
+ return this.blobs.has(outRef) ? this.blobs.get(outRef) : void 0;
55
+ }
56
+ };
57
+ /**
58
+ * FS `ResultBlobStore`. One JSON file per artifact under `dir`, named by a
59
+ * filesystem-safe encoding of the `outRef` (`sha256:<hex>` → `sha256-<hex>.json`).
60
+ * `put` fsyncs so a crash between writes never loses an acknowledged blob.
61
+ */
62
+ var FileResultBlobStore = class {
63
+ dir;
64
+ constructor(dir) {
65
+ this.dir = dir;
66
+ }
67
+ async put(outRef, artifact) {
68
+ assertContentAddress(outRef, artifact);
69
+ const fs = await import("node:fs/promises");
70
+ await fs.mkdir(this.dir, { recursive: true });
71
+ const fh = await fs.open(this.blobPath(outRef), "w");
72
+ try {
73
+ await fh.write(JSON.stringify(artifact));
74
+ await fh.sync();
75
+ } finally {
76
+ await fh.close();
77
+ }
78
+ }
79
+ async get(outRef) {
80
+ const fs = await import("node:fs/promises");
81
+ let text;
82
+ try {
83
+ text = await fs.readFile(this.blobPath(outRef), "utf8");
84
+ } catch (err) {
85
+ if (isNoEntError(err)) return void 0;
86
+ throw err;
87
+ }
88
+ return JSON.parse(text);
89
+ }
90
+ blobPath(outRef) {
91
+ return `${this.dir}/${outRef.replace(/:/g, "-")}.json`;
92
+ }
93
+ };
94
+ function assertContentAddress(outRef, artifact) {
95
+ const expected = contentAddress(artifact);
96
+ if (outRef !== expected) throw new Error(`blob outRef '${outRef}' does not match the artifact content hash '${expected}'; a content-addressed store refuses a mismatched ref (breaks the replay invariant)`);
97
+ }
98
+ /**
99
+ * In-memory `SpawnJournal`. Appends are observed-committed only; the impl enforces
100
+ * the corruption guards a durable replay rests on:
101
+ * - an event before `beginTree` is a corrupted tree (fail loud),
102
+ * - a duplicate `seq` within a tree is a corrupted cursor (fail loud) — two
103
+ * settlements cannot share the cursor position replay orders by.
104
+ */
105
+ var InMemorySpawnJournal = class {
106
+ trees = /* @__PURE__ */ new Map();
107
+ async loadTree(root) {
108
+ const tree = this.trees.get(root);
109
+ if (!tree) return void 0;
110
+ return tree.events.map((ev) => ({ ...ev }));
111
+ }
112
+ async beginTree(root, at) {
113
+ const existing = this.trees.get(root);
114
+ if (existing) {
115
+ if (existing.begunAt !== at) throw new Error(`spawn tree '${root}' already begun at ${existing.begunAt}; refusing to overwrite with ${at}`);
116
+ return;
117
+ }
118
+ this.trees.set(root, {
119
+ begunAt: at,
120
+ events: []
121
+ });
122
+ }
123
+ async appendEvent(root, ev) {
124
+ const tree = this.trees.get(root);
125
+ if (!tree) throw new Error(`appendEvent called for unknown spawn tree '${root}'; call beginTree first`);
126
+ assertSeqUnique(root, tree.events, ev);
127
+ tree.events.push({ ...ev });
128
+ }
129
+ };
130
+ /**
131
+ * JSONL on disk. One line per record: the first record is `begin`, subsequent records
132
+ * are `event` envelopes wrapping a `SpawnEvent`. `loadTree` replays the whole file,
133
+ * filtering by `root`, and applies the same begin-precedes-events + unique-seq
134
+ * corruption guards as the in-memory impl. Each append fsyncs so a crash between
135
+ * writes never loses an acknowledged event.
136
+ */
137
+ var FileSpawnJournal = class {
138
+ path;
139
+ constructor(path) {
140
+ this.path = path;
141
+ }
142
+ async loadTree(root) {
143
+ const fs = await import("node:fs/promises");
144
+ let text;
145
+ try {
146
+ text = await fs.readFile(this.path, "utf8");
147
+ } catch (err) {
148
+ if (isNoEntError(err)) return void 0;
149
+ throw err;
150
+ }
151
+ const lines = text.split("\n").filter((line) => line.length > 0);
152
+ let begun = false;
153
+ const events = [];
154
+ for (const line of lines) {
155
+ const record = JSON.parse(line);
156
+ if (record.root !== root) continue;
157
+ if (record.kind === "begin") begun = true;
158
+ else {
159
+ if (!begun) throw new Error(`spawn journal corrupted: event for tree '${root}' precedes its begin record`);
160
+ assertSeqUnique(root, events, record.event);
161
+ events.push(record.event);
162
+ }
163
+ }
164
+ return begun ? events : void 0;
165
+ }
166
+ async beginTree(root, at) {
167
+ const existing = await this.loadTreeBegin(root);
168
+ if (existing) {
169
+ if (existing !== at) throw new Error(`spawn tree '${root}' already begun in ${this.path} at ${existing}; refusing to overwrite with ${at}`);
170
+ return;
171
+ }
172
+ await this.appendRecord({
173
+ kind: "begin",
174
+ root,
175
+ at
176
+ });
177
+ }
178
+ async appendEvent(root, ev) {
179
+ const events = await this.loadTree(root);
180
+ if (events === void 0) throw new Error(`appendEvent called for unknown spawn tree '${root}'; call beginTree first`);
181
+ assertSeqUnique(root, events, ev);
182
+ await this.appendRecord({
183
+ kind: "event",
184
+ root,
185
+ event: ev
186
+ });
187
+ }
188
+ async loadTreeBegin(root) {
189
+ const fs = await import("node:fs/promises");
190
+ let text;
191
+ try {
192
+ text = await fs.readFile(this.path, "utf8");
193
+ } catch (err) {
194
+ if (isNoEntError(err)) return void 0;
195
+ throw err;
196
+ }
197
+ const lines = text.split("\n").filter((line) => line.length > 0);
198
+ for (const line of lines) {
199
+ const record = JSON.parse(line);
200
+ if (record.root === root && record.kind === "begin") return record.at;
201
+ }
202
+ }
203
+ async appendRecord(record) {
204
+ const fs = await import("node:fs/promises");
205
+ const path = await import("node:path");
206
+ await fs.mkdir(path.dirname(this.path), { recursive: true });
207
+ const fh = await fs.open(this.path, "a");
208
+ try {
209
+ await fh.write(`${JSON.stringify(record)}\n`);
210
+ await fh.sync();
211
+ } finally {
212
+ await fh.close();
213
+ }
214
+ }
215
+ };
216
+ /**
217
+ * Two `seq` namespaces share the journal: a `spawned` event's `seq` is the spawn ordinal
218
+ * (the order children were created), and a `settled`/`cancelled` event's `seq` is the
219
+ * monotonic CURSOR order `scope.next()` yielded that settlement (B2). The uniqueness
220
+ * replay rests on is the cursor namespace — two settlements cannot share the position
221
+ * replay orders by — so the guard checks only settled/cancelled events. A `spawned`
222
+ * ordinal legitimately equals a later `settled` cursor seq and is not a collision.
223
+ */
224
+ function assertSeqUnique(root, events, ev) {
225
+ if (outsideCursorNamespace(ev)) return;
226
+ if (events.some((e) => !outsideCursorNamespace(e) && e.seq === ev.seq)) throw new Error(`spawn journal corrupted: duplicate cursor seq ${ev.seq} in tree '${root}'; the cursor order replay relies on is not unique`);
227
+ }
228
+ /** Node-CREATION and informational records — outside the cursor namespace whose uniqueness replay
229
+ * ordering rests on. The single predicate both the guard's sides read, so a new event kind is
230
+ * classified once. */
231
+ function outsideCursorNamespace(ev) {
232
+ return ev.kind === "spawned" || ev.kind === "waiting" || ev.kind === "metered";
233
+ }
234
+ /**
235
+ * Re-feed a journaled spawn tree in strict `seq` order, rehydrating each settled
236
+ * child's `out` from the blob store by `outRef`, and return the `Settled[]` exactly
237
+ * as `scope.next()` originally delivered them.
238
+ *
239
+ * Determinism (B2): the events are sorted by `seq` BEFORE any blob `get`, so the
240
+ * replay order is the recorded cursor order regardless of how fast each rehydration
241
+ * resolves. `at` (wall-clock) is never a replay input. Fail loud on a tree that was
242
+ * never begun, a settled-done event missing its `outRef`, or a blob the store can't
243
+ * rehydrate — a silent gap would let `act` branch on the wrong evidence.
244
+ */
245
+ async function replaySpawnTree(journal, blobs, root) {
246
+ const events = await journal.loadTree(root);
247
+ if (events === void 0) throw new Error(`replaySpawnTree: no journaled tree for root '${root}'`);
248
+ const ordered = [...events].sort((a, b) => a.seq - b.seq);
249
+ const labels = /* @__PURE__ */ new Map();
250
+ for (const ev of ordered) if (ev.kind === "spawned" || ev.kind === "waiting") labels.set(ev.id, ev.label);
251
+ const settled = [];
252
+ for (const ev of ordered) {
253
+ if (ev.kind === "spawned") continue;
254
+ if (ev.kind === "waiting") continue;
255
+ if (ev.kind === "metered") continue;
256
+ if (ev.kind === "woken") {
257
+ if (ev.by === "cancelled" || ev.outRef === void 0) {
258
+ settled.push({
259
+ kind: "down",
260
+ handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, "cancelled"),
261
+ reason: "wait cancelled",
262
+ infra: false,
263
+ restartCount: 0,
264
+ seq: ev.seq
265
+ });
266
+ continue;
267
+ }
268
+ const outcome = await blobs.get(ev.outRef);
269
+ if (outcome === void 0) throw new Error(`replaySpawnTree: blob store has no wait outcome for outRef '${ev.outRef}' (node '${ev.id}', seq ${ev.seq})`);
270
+ settled.push({
271
+ kind: "done",
272
+ handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, "done"),
273
+ out: outcome,
274
+ outRef: ev.outRef,
275
+ spent: zeroSpend(),
276
+ seq: ev.seq
277
+ });
278
+ continue;
279
+ }
280
+ if (ev.kind === "cancelled") {
281
+ settled.push({
282
+ kind: "down",
283
+ handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, "cancelled"),
284
+ reason: ev.reason,
285
+ infra: false,
286
+ restartCount: 0,
287
+ seq: ev.seq
288
+ });
289
+ continue;
290
+ }
291
+ if (ev.status === "down") {
292
+ settled.push({
293
+ kind: "down",
294
+ handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, "failed"),
295
+ reason: ev.verdict?.notes ?? "child down",
296
+ infra: ev.infra === true,
297
+ restartCount: 0,
298
+ seq: ev.seq
299
+ });
300
+ continue;
301
+ }
302
+ if (ev.outRef === void 0) throw new Error(`replaySpawnTree: settled-done event for '${ev.id}' (seq ${ev.seq}) has no outRef; cannot rehydrate the result the driver branched on`);
303
+ const out = await blobs.get(ev.outRef);
304
+ if (out === void 0) throw new Error(`replaySpawnTree: blob store has no artifact for outRef '${ev.outRef}' (node '${ev.id}', seq ${ev.seq})`);
305
+ settled.push({
306
+ kind: "done",
307
+ handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, "done"),
308
+ out,
309
+ outRef: ev.outRef,
310
+ verdict: ev.verdict,
311
+ spent: ev.spent,
312
+ seq: ev.seq
313
+ });
314
+ }
315
+ return settled;
316
+ }
317
+ function replayHandle(id, label, status) {
318
+ return {
319
+ id,
320
+ label,
321
+ status,
322
+ abort() {
323
+ throw new Error(`cannot abort node '${id}': replayed handles are terminal, not live`);
324
+ }
325
+ };
326
+ }
327
+ /**
328
+ * Materialize a recorded `TreeView` from a journaled event list for inspection. Folds
329
+ * `spawned`/`settled`/`cancelled` into a per-node snapshot in `seq` order, then adds each
330
+ * `metered` event's driver-inference spend onto its node in a separate additive pass so the view
331
+ * matches the recorded cursor. It does not recover live executors or driver state after restart.
332
+ */
333
+ function materializeTreeView(events) {
334
+ const nodes = /* @__PURE__ */ new Map();
335
+ let root;
336
+ const spawns = events.filter((ev) => ev.kind === "spawned" || ev.kind === "waiting").sort((a, b) => a.seq - b.seq);
337
+ const settlements = events.filter((ev) => ev.kind !== "spawned" && ev.kind !== "waiting" && ev.kind !== "metered").sort((a, b) => a.seq - b.seq);
338
+ for (const ev of spawns) {
339
+ if (ev.kind === "waiting") {
340
+ nodes.set(ev.id, {
341
+ id: ev.id,
342
+ parent: ev.parent,
343
+ label: ev.label,
344
+ status: "waiting",
345
+ runtime: "wait",
346
+ budget: {
347
+ maxIterations: 0,
348
+ maxTokens: 0
349
+ },
350
+ spent: zeroSpend()
351
+ });
352
+ continue;
353
+ }
354
+ if (ev.parent === void 0 && root === void 0) root = ev.id;
355
+ nodes.set(ev.id, {
356
+ id: ev.id,
357
+ parent: ev.parent,
358
+ label: ev.label,
359
+ status: "pending",
360
+ runtime: ev.runtime,
361
+ budget: ev.budget,
362
+ spent: zeroSpend()
363
+ });
364
+ }
365
+ for (const ev of settlements) if (ev.kind === "settled") {
366
+ const node = requireNode(nodes, ev.id);
367
+ node.status = ev.status === "done" ? "done" : "failed";
368
+ node.spent = ev.spent;
369
+ node.outRef = ev.outRef;
370
+ } else if (ev.kind === "woken") {
371
+ const node = requireNode(nodes, ev.id);
372
+ node.status = ev.by === "cancelled" ? "cancelled" : "done";
373
+ node.outRef = ev.outRef;
374
+ } else {
375
+ const node = requireNode(nodes, ev.id);
376
+ node.status = "cancelled";
377
+ }
378
+ for (const ev of events) {
379
+ if (ev.kind !== "metered") continue;
380
+ const node = requireNode(nodes, ev.id);
381
+ node.spent = addJournalSpend(node.spent, ev.spend);
382
+ }
383
+ const snapshots = [...nodes.values()].map(freezeSnapshot);
384
+ return {
385
+ root: root ?? snapshots[0]?.id ?? "",
386
+ nodes: snapshots,
387
+ inFlight: snapshots.filter((n) => n.status === "running" || n.status === "acquiring").length,
388
+ waiting: snapshots.filter((n) => n.status === "waiting").length
389
+ };
390
+ }
391
+ /**
392
+ * The waits a journaled tree shows as ARMED but never woken — what a resumed run re-arms with the
393
+ * ORIGINAL absolute deadline. Reading it from the journal (rather than from any live state) is
394
+ * what makes "SIGKILL a waiting tree, a new process keeps waiting to the same instant" true.
395
+ */
396
+ function pendingWaits(events) {
397
+ const woken = /* @__PURE__ */ new Set();
398
+ for (const ev of events) if (ev.kind === "woken") woken.add(ev.id);
399
+ const pending = [];
400
+ for (const ev of events) {
401
+ if (ev.kind !== "waiting" || woken.has(ev.id)) continue;
402
+ pending.push({
403
+ id: ev.id,
404
+ label: ev.label,
405
+ spec: ev.spec,
406
+ armedAt: ev.armedAt,
407
+ ordinal: ev.seq
408
+ });
409
+ }
410
+ return pending.sort((a, b) => a.ordinal - b.ordinal);
411
+ }
412
+ function zeroSpend() {
413
+ return {
414
+ iterations: 0,
415
+ tokens: zeroTokenUsage(),
416
+ usd: 0,
417
+ ms: 0
418
+ };
419
+ }
420
+ /** Add a `metered` spend record onto a node's accumulated spend (per channel). */
421
+ function addJournalSpend(a, b) {
422
+ return {
423
+ iterations: a.iterations + b.iterations,
424
+ tokens: {
425
+ input: a.tokens.input + b.tokens.input,
426
+ output: a.tokens.output + b.tokens.output
427
+ },
428
+ usd: a.usd + b.usd,
429
+ ...a.usdKnown === false || b.usdKnown === false ? { usdKnown: false } : {},
430
+ ms: a.ms + b.ms
431
+ };
432
+ }
433
+ function requireNode(nodes, id) {
434
+ const node = nodes.get(id);
435
+ if (!node) throw new Error(`spawn journal corrupted: settle/cancel for node '${id}' with no prior spawn`);
436
+ return node;
437
+ }
438
+ function freezeSnapshot(node) {
439
+ return {
440
+ id: node.id,
441
+ parent: node.parent,
442
+ label: node.label,
443
+ status: node.status,
444
+ runtime: node.runtime,
445
+ budget: node.budget,
446
+ spent: node.spent,
447
+ outRef: node.outRef
448
+ };
449
+ }
450
+ function isNoEntError(err) {
451
+ return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
452
+ }
453
+ //#endregion
454
+ export { contentAddress as a, replaySpawnTree as c, InMemorySpawnJournal as i, FileSpawnJournal as n, materializeTreeView as o, InMemoryResultBlobStore as r, pendingWaits as s, FileResultBlobStore as t };
455
+
456
+ //# sourceMappingURL=spawn-journal-CwPvKUTa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-journal-CwPvKUTa.js","names":[],"sources":["../src/durable/spawn-journal.ts"],"sourcesContent":["/**\n *\n * Event-sourced spawn journal for the recursive execution atom (build steps 3 + 7).\n *\n * The supervision tree is journaled as an append-only event log: every `spawned`,\n * `settled`, and `cancelled` is recorded AFTER it is observed-committed (never\n * speculative), mirroring `ConversationJournal`'s begin/append/load shape. The log\n * holds only the THIN decision record — ids, parentage, budget, the spend a decision\n * consumed, and a content-addressed `outRef`. The payloads the driver branched on\n * (the `out` artifacts) live in a separate `ResultBlobStore`, keyed by `outRef`, so\n * the journal stays small (decisions) and replay rehydrates the exact `Settled` from\n * the blob store (evidence). This is the decision/payload split the replay argument\n * rests on (B1/B2).\n *\n * Replay determinism (B2): `seq` is the monotonic cursor order `scope.next()` yielded\n * each settlement — NOT wall-clock. `replaySpawnTree` sorts strictly by `seq` before\n * touching the blob store, so the order in which rehydration `get`s resolve can never\n * reorder the replayed `Settled[]`; the result is identical regardless of blob latency.\n *\n * @experimental\n */\n\nimport { createHash } from 'node:crypto'\nimport type {\n NodeId,\n NodeSnapshot,\n NodeStatus,\n ResultBlobStore,\n Runtime,\n Settled,\n SpawnEvent,\n SpawnJournal,\n Spend,\n TreeView,\n} from '../runtime/supervise/types'\nimport type { PendingWait } from '../runtime/supervise/wait'\nimport { zeroTokenUsage } from '../runtime/util'\n\n// ── Content addressing ──────────────────────────────────────────────────────\n\n/**\n * Mint the content-addressed `outRef` for a result artifact: `sha256:<hex>` over a\n * stable JSON encoding. Producers call this to derive the `outRef` they journal and\n * `put`; the FS/in-mem stores re-derive it on `put` to verify the supplied ref\n * matches (fail loud on a mismatch — a forged ref breaks the replay invariant).\n *\n * Stable encoding: object keys are sorted recursively so two structurally-equal\n * artifacts hash identically regardless of key insertion order.\n */\nexport function contentAddress(artifact: unknown): string {\n const hex = createHash('sha256').update(stableStringify(artifact), 'utf-8').digest('hex')\n return `sha256:${hex}`\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value) ?? 'null'\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(',')}}`\n}\n\n// ── Result blob store ─────────────────────────────────────────────────────────\n\n/**\n * In-memory `ResultBlobStore`. Content-addressed: `put` verifies the supplied\n * `outRef` matches the artifact's hash so a stale/forged ref fails loud rather than\n * silently rehydrating the wrong payload. Idempotent on an identical re-put.\n */\nexport class InMemoryResultBlobStore implements ResultBlobStore {\n private readonly blobs = new Map<string, unknown>()\n\n async put(outRef: string, artifact: unknown): Promise<void> {\n assertContentAddress(outRef, artifact)\n this.blobs.set(outRef, artifact)\n }\n\n async get(outRef: string): Promise<unknown | undefined> {\n return this.blobs.has(outRef) ? this.blobs.get(outRef) : undefined\n }\n}\n\n/**\n * FS `ResultBlobStore`. One JSON file per artifact under `dir`, named by a\n * filesystem-safe encoding of the `outRef` (`sha256:<hex>` → `sha256-<hex>.json`).\n * `put` fsyncs so a crash between writes never loses an acknowledged blob.\n */\nexport class FileResultBlobStore implements ResultBlobStore {\n constructor(private readonly dir: string) {}\n\n async put(outRef: string, artifact: unknown): Promise<void> {\n assertContentAddress(outRef, artifact)\n const fs = await import('node:fs/promises')\n await fs.mkdir(this.dir, { recursive: true })\n const fh = await fs.open(this.blobPath(outRef), 'w')\n try {\n await fh.write(JSON.stringify(artifact))\n await fh.sync()\n } finally {\n await fh.close()\n }\n }\n\n async get(outRef: string): Promise<unknown | undefined> {\n const fs = await import('node:fs/promises')\n let text: string\n try {\n text = await fs.readFile(this.blobPath(outRef), 'utf8')\n } catch (err) {\n if (isNoEntError(err)) return undefined\n throw err\n }\n return JSON.parse(text)\n }\n\n private blobPath(outRef: string): string {\n return `${this.dir}/${outRef.replace(/:/g, '-')}.json`\n }\n}\n\nfunction assertContentAddress(outRef: string, artifact: unknown): void {\n const expected = contentAddress(artifact)\n if (outRef !== expected) {\n throw new Error(\n `blob outRef '${outRef}' does not match the artifact content hash '${expected}'; ` +\n 'a content-addressed store refuses a mismatched ref (breaks the replay invariant)',\n )\n }\n}\n\n// ── Spawn journal ──────────────────────────────────────────────────────────────\n\n/**\n * In-memory `SpawnJournal`. Appends are observed-committed only; the impl enforces\n * the corruption guards a durable replay rests on:\n * - an event before `beginTree` is a corrupted tree (fail loud),\n * - a duplicate `seq` within a tree is a corrupted cursor (fail loud) — two\n * settlements cannot share the cursor position replay orders by.\n */\nexport class InMemorySpawnJournal implements SpawnJournal {\n private readonly trees = new Map<NodeId, { begunAt: string; events: SpawnEvent[] }>()\n\n async loadTree(root: NodeId): Promise<SpawnEvent[] | undefined> {\n const tree = this.trees.get(root)\n if (!tree) return undefined\n return tree.events.map((ev) => ({ ...ev }))\n }\n\n async beginTree(root: NodeId, at: string): Promise<void> {\n const existing = this.trees.get(root)\n if (existing) {\n if (existing.begunAt !== at) {\n throw new Error(\n `spawn tree '${root}' already begun at ${existing.begunAt}; refusing to overwrite with ${at}`,\n )\n }\n return\n }\n this.trees.set(root, { begunAt: at, events: [] })\n }\n\n async appendEvent(root: NodeId, ev: SpawnEvent): Promise<void> {\n const tree = this.trees.get(root)\n if (!tree) {\n throw new Error(`appendEvent called for unknown spawn tree '${root}'; call beginTree first`)\n }\n assertSeqUnique(root, tree.events, ev)\n tree.events.push({ ...ev })\n }\n}\n\n/**\n * JSONL on disk. One line per record: the first record is `begin`, subsequent records\n * are `event` envelopes wrapping a `SpawnEvent`. `loadTree` replays the whole file,\n * filtering by `root`, and applies the same begin-precedes-events + unique-seq\n * corruption guards as the in-memory impl. Each append fsyncs so a crash between\n * writes never loses an acknowledged event.\n */\nexport class FileSpawnJournal implements SpawnJournal {\n constructor(private readonly path: string) {}\n\n async loadTree(root: NodeId): Promise<SpawnEvent[] | undefined> {\n const fs = await import('node:fs/promises')\n let text: string\n try {\n text = await fs.readFile(this.path, 'utf8')\n } catch (err) {\n if (isNoEntError(err)) return undefined\n throw err\n }\n const lines = text.split('\\n').filter((line) => line.length > 0)\n let begun = false\n const events: SpawnEvent[] = []\n for (const line of lines) {\n const record = JSON.parse(line) as SpawnJournalRecord\n if (record.root !== root) continue\n if (record.kind === 'begin') {\n begun = true\n } else {\n if (!begun) {\n throw new Error(\n `spawn journal corrupted: event for tree '${root}' precedes its begin record`,\n )\n }\n assertSeqUnique(root, events, record.event)\n events.push(record.event)\n }\n }\n return begun ? events : undefined\n }\n\n async beginTree(root: NodeId, at: string): Promise<void> {\n const existing = await this.loadTreeBegin(root)\n if (existing) {\n if (existing !== at) {\n throw new Error(\n `spawn tree '${root}' already begun in ${this.path} at ${existing}; refusing to overwrite with ${at}`,\n )\n }\n return\n }\n await this.appendRecord({ kind: 'begin', root, at })\n }\n\n async appendEvent(root: NodeId, ev: SpawnEvent): Promise<void> {\n const events = await this.loadTree(root)\n if (events === undefined) {\n throw new Error(`appendEvent called for unknown spawn tree '${root}'; call beginTree first`)\n }\n assertSeqUnique(root, events, ev)\n await this.appendRecord({ kind: 'event', root, event: ev })\n }\n\n private async loadTreeBegin(root: NodeId): Promise<string | undefined> {\n const fs = await import('node:fs/promises')\n let text: string\n try {\n text = await fs.readFile(this.path, 'utf8')\n } catch (err) {\n if (isNoEntError(err)) return undefined\n throw err\n }\n const lines = text.split('\\n').filter((line) => line.length > 0)\n for (const line of lines) {\n const record = JSON.parse(line) as SpawnJournalRecord\n if (record.root === root && record.kind === 'begin') return record.at\n }\n return undefined\n }\n\n private async appendRecord(record: SpawnJournalRecord): Promise<void> {\n const fs = await import('node:fs/promises')\n const path = await import('node:path')\n await fs.mkdir(path.dirname(this.path), { recursive: true })\n const fh = await fs.open(this.path, 'a')\n try {\n await fh.write(`${JSON.stringify(record)}\\n`)\n await fh.sync()\n } finally {\n await fh.close()\n }\n }\n}\n\ntype SpawnJournalRecord =\n | { kind: 'begin'; root: NodeId; at: string }\n | { kind: 'event'; root: NodeId; event: SpawnEvent }\n\n/**\n * Two `seq` namespaces share the journal: a `spawned` event's `seq` is the spawn ordinal\n * (the order children were created), and a `settled`/`cancelled` event's `seq` is the\n * monotonic CURSOR order `scope.next()` yielded that settlement (B2). The uniqueness\n * replay rests on is the cursor namespace — two settlements cannot share the position\n * replay orders by — so the guard checks only settled/cancelled events. A `spawned`\n * ordinal legitimately equals a later `settled` cursor seq and is not a collision.\n */\nfunction assertSeqUnique(root: NodeId, events: SpawnEvent[], ev: SpawnEvent): void {\n // `spawned` (ordinal namespace), `waiting` (the wait-ordinal namespace — it CREATES a node, it\n // does not settle one), and `metered` (informational spend, no settlement order) live outside\n // the cursor-uniqueness namespace replay relies on. `woken` IS a settlement and does not.\n if (outsideCursorNamespace(ev)) return\n if (events.some((e) => !outsideCursorNamespace(e) && e.seq === ev.seq)) {\n throw new Error(\n `spawn journal corrupted: duplicate cursor seq ${ev.seq} in tree '${root}'; ` +\n 'the cursor order replay relies on is not unique',\n )\n }\n}\n\n/** Node-CREATION and informational records — outside the cursor namespace whose uniqueness replay\n * ordering rests on. The single predicate both the guard's sides read, so a new event kind is\n * classified once. */\nfunction outsideCursorNamespace(ev: SpawnEvent): boolean {\n return ev.kind === 'spawned' || ev.kind === 'waiting' || ev.kind === 'metered'\n}\n\n// ── Replay executor (build step 7) ───────────────────────────────────────────────\n\n/**\n * Re-feed a journaled spawn tree in strict `seq` order, rehydrating each settled\n * child's `out` from the blob store by `outRef`, and return the `Settled[]` exactly\n * as `scope.next()` originally delivered them.\n *\n * Determinism (B2): the events are sorted by `seq` BEFORE any blob `get`, so the\n * replay order is the recorded cursor order regardless of how fast each rehydration\n * resolves. `at` (wall-clock) is never a replay input. Fail loud on a tree that was\n * never begun, a settled-done event missing its `outRef`, or a blob the store can't\n * rehydrate — a silent gap would let `act` branch on the wrong evidence.\n */\nexport async function replaySpawnTree(\n journal: SpawnJournal,\n blobs: ResultBlobStore,\n root: NodeId,\n): Promise<Settled<unknown>[]> {\n const events = await journal.loadTree(root)\n if (events === undefined) {\n throw new Error(`replaySpawnTree: no journaled tree for root '${root}'`)\n }\n const ordered = [...events].sort((a, b) => a.seq - b.seq)\n const labels = new Map<NodeId, string>()\n for (const ev of ordered) {\n if (ev.kind === 'spawned' || ev.kind === 'waiting') labels.set(ev.id, ev.label)\n }\n const settled: Settled<unknown>[] = []\n for (const ev of ordered) {\n if (ev.kind === 'spawned') continue\n if (ev.kind === 'waiting') continue // arms a wait node; `woken` is its settlement\n if (ev.kind === 'metered') continue // a spend record, not a settlement — irrelevant to replay\n if (ev.kind === 'woken') {\n // A wait that was cancelled carries no outcome blob — it replays as a `down`, exactly as a\n // cancelled worker does. A fired/timed-out wait rehydrates its `WaitOutcome` and costs zero.\n if (ev.by === 'cancelled' || ev.outRef === undefined) {\n settled.push({\n kind: 'down',\n handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, 'cancelled'),\n reason: 'wait cancelled',\n infra: false,\n restartCount: 0,\n seq: ev.seq,\n })\n continue\n }\n const outcome = await blobs.get(ev.outRef)\n if (outcome === undefined) {\n throw new Error(\n `replaySpawnTree: blob store has no wait outcome for outRef '${ev.outRef}' (node '${ev.id}', seq ${ev.seq})`,\n )\n }\n settled.push({\n kind: 'done',\n handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, 'done'),\n out: outcome,\n outRef: ev.outRef,\n spent: zeroSpend(),\n seq: ev.seq,\n })\n continue\n }\n if (ev.kind === 'cancelled') {\n settled.push({\n kind: 'down',\n handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, 'cancelled'),\n reason: ev.reason,\n infra: false,\n restartCount: 0,\n seq: ev.seq,\n })\n continue\n }\n if (ev.status === 'down') {\n settled.push({\n kind: 'down',\n handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, 'failed'),\n reason: ev.verdict?.notes ?? 'child down',\n infra: ev.infra === true,\n restartCount: 0,\n seq: ev.seq,\n })\n continue\n }\n if (ev.outRef === undefined) {\n throw new Error(\n `replaySpawnTree: settled-done event for '${ev.id}' (seq ${ev.seq}) has no outRef; ` +\n 'cannot rehydrate the result the driver branched on',\n )\n }\n const out = await blobs.get(ev.outRef)\n if (out === undefined) {\n throw new Error(\n `replaySpawnTree: blob store has no artifact for outRef '${ev.outRef}' (node '${ev.id}', seq ${ev.seq})`,\n )\n }\n settled.push({\n kind: 'done',\n handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, 'done'),\n out,\n outRef: ev.outRef,\n verdict: ev.verdict,\n spent: ev.spent,\n seq: ev.seq,\n })\n }\n return settled\n}\n\nfunction replayHandle(id: NodeId, label: string, status: NodeStatus) {\n return {\n id,\n label,\n status,\n abort() {\n throw new Error(`cannot abort node '${id}': replayed handles are terminal, not live`)\n },\n }\n}\n\n/**\n * Materialize a recorded `TreeView` from a journaled event list for inspection. Folds\n * `spawned`/`settled`/`cancelled` into a per-node snapshot in `seq` order, then adds each\n * `metered` event's driver-inference spend onto its node in a separate additive pass so the view\n * matches the recorded cursor. It does not recover live executors or driver state after restart.\n */\nexport function materializeTreeView(events: SpawnEvent[]): TreeView {\n const nodes = new Map<NodeId, MutableSnapshot>()\n let root: NodeId | undefined\n // `spawned` (ordinal namespace) and `settled`/`cancelled` (cursor namespace) carry\n // overlapping `seq` values, so create every node before any update — process spawns in\n // ordinal order, then settlements/cancellations in cursor order. A settle/cancel for an\n // un-spawned node is a corrupted log (fail loud via requireNode).\n const spawns = events\n .filter(\n (ev): ev is Extract<SpawnEvent, { kind: 'spawned' | 'waiting' }> =>\n ev.kind === 'spawned' || ev.kind === 'waiting',\n )\n .sort((a, b) => a.seq - b.seq)\n const settlements = events\n .filter((ev) => ev.kind !== 'spawned' && ev.kind !== 'waiting' && ev.kind !== 'metered')\n .sort((a, b) => a.seq - b.seq)\n for (const ev of spawns) {\n if (ev.kind === 'waiting') {\n // An ARMED wait reads `waiting` until a `woken` event lands. That is the whole durability\n // claim: a materialized tree from a journal whose process died mid-wait still shows the wait.\n nodes.set(ev.id, {\n id: ev.id,\n parent: ev.parent,\n label: ev.label,\n status: 'waiting',\n runtime: 'wait',\n budget: { maxIterations: 0, maxTokens: 0 },\n spent: zeroSpend(),\n })\n continue\n }\n if (ev.parent === undefined && root === undefined) root = ev.id\n nodes.set(ev.id, {\n id: ev.id,\n parent: ev.parent,\n label: ev.label,\n status: 'pending',\n runtime: ev.runtime,\n budget: ev.budget,\n spent: zeroSpend(),\n })\n }\n for (const ev of settlements) {\n if (ev.kind === 'settled') {\n const node = requireNode(nodes, ev.id)\n node.status = ev.status === 'done' ? 'done' : 'failed'\n node.spent = ev.spent\n node.outRef = ev.outRef\n } else if (ev.kind === 'woken') {\n const node = requireNode(nodes, ev.id)\n node.status = ev.by === 'cancelled' ? 'cancelled' : 'done'\n node.outRef = ev.outRef\n } else {\n const node = requireNode(nodes, ev.id)\n node.status = 'cancelled'\n }\n }\n // Driver inference: a separate pass so it accumulates ONTO the settled child-work base (no\n // dependence on metered-vs-settled seq order) without touching node status.\n for (const ev of events) {\n if (ev.kind !== 'metered') continue\n const node = requireNode(nodes, ev.id)\n node.spent = addJournalSpend(node.spent, ev.spend)\n }\n const snapshots = [...nodes.values()].map(freezeSnapshot)\n return {\n root: root ?? snapshots[0]?.id ?? '',\n nodes: snapshots,\n inFlight: snapshots.filter((n) => n.status === 'running' || n.status === 'acquiring').length,\n waiting: snapshots.filter((n) => n.status === 'waiting').length,\n }\n}\n\n/**\n * The waits a journaled tree shows as ARMED but never woken — what a resumed run re-arms with the\n * ORIGINAL absolute deadline. Reading it from the journal (rather than from any live state) is\n * what makes \"SIGKILL a waiting tree, a new process keeps waiting to the same instant\" true.\n */\nexport function pendingWaits(events: SpawnEvent[]): PendingWait[] {\n const woken = new Set<NodeId>()\n for (const ev of events) if (ev.kind === 'woken') woken.add(ev.id)\n const pending: PendingWait[] = []\n for (const ev of events) {\n if (ev.kind !== 'waiting' || woken.has(ev.id)) continue\n pending.push({\n id: ev.id,\n label: ev.label,\n spec: ev.spec,\n armedAt: ev.armedAt,\n ordinal: ev.seq,\n })\n }\n return pending.sort((a, b) => a.ordinal - b.ordinal)\n}\n\ninterface MutableSnapshot {\n id: NodeId\n parent?: NodeId\n label: string\n status: NodeStatus\n runtime: Runtime\n budget: NodeSnapshot['budget']\n spent: Spend\n outRef?: string\n}\n\nfunction zeroSpend(): Spend {\n return { iterations: 0, tokens: zeroTokenUsage(), usd: 0, ms: 0 }\n}\n\n/** Add a `metered` spend record onto a node's accumulated spend (per channel). */\nfunction addJournalSpend(a: Spend, b: Spend): Spend {\n return {\n iterations: a.iterations + b.iterations,\n tokens: { input: a.tokens.input + b.tokens.input, output: a.tokens.output + b.tokens.output },\n usd: a.usd + b.usd,\n ...(a.usdKnown === false || b.usdKnown === false ? { usdKnown: false } : {}),\n ms: a.ms + b.ms,\n }\n}\n\nfunction requireNode(nodes: Map<NodeId, MutableSnapshot>, id: NodeId): MutableSnapshot {\n const node = nodes.get(id)\n if (!node) {\n throw new Error(`spawn journal corrupted: settle/cancel for node '${id}' with no prior spawn`)\n }\n return node\n}\n\nfunction freezeSnapshot(node: MutableSnapshot): NodeSnapshot {\n return {\n id: node.id,\n parent: node.parent,\n label: node.label,\n status: node.status,\n runtime: node.runtime,\n budget: node.budget,\n spent: node.spent,\n outRef: node.outRef,\n }\n}\n\nfunction isNoEntError(err: unknown): boolean {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n (err as { code: unknown }).code === 'ENOENT'\n )\n}\n"],"mappings":"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"}