@tangle-network/agent-runtime 0.339.0 → 0.342.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 (83) hide show
  1. package/dist/{activation-CVSFxis9.js → activation-CWPmt0Do.js} +4 -4
  2. package/dist/{activation-CVSFxis9.js.map → activation-CWPmt0Do.js.map} +1 -1
  3. package/dist/{activation-CJIIl_Ey.d.ts → activation-CXqtijue.d.ts} +2 -2
  4. package/dist/agent.d.ts +4 -18
  5. package/dist/agent.js +3 -21
  6. package/dist/agent.js.map +1 -1
  7. package/dist/analyst-loop.d.ts +2 -2
  8. package/dist/{bundle-DVOhBTic.js → bundle-Cwpit6Tg.js} +2 -2
  9. package/dist/{bundle-DVOhBTic.js.map → bundle-Cwpit6Tg.js.map} +1 -1
  10. package/dist/candidate-execution/index.d.ts +2 -40
  11. package/dist/candidate-execution/index.js +9 -255
  12. package/dist/candidate-execution/index.js.map +1 -1
  13. package/dist/{driver-control-acknowledgers-C53ggdJ6.js → coordination-manager-B5JsolDR.js} +4852 -4539
  14. package/dist/coordination-manager-B5JsolDR.js.map +1 -0
  15. package/dist/{delegate-CCWE_AkU.js → delegate-Rl-5paLJ.js} +2 -2
  16. package/dist/{delegate-CCWE_AkU.js.map → delegate-Rl-5paLJ.js.map} +1 -1
  17. package/dist/durable.d.ts +1 -1
  18. package/dist/durable.js +451 -358
  19. package/dist/durable.js.map +1 -1
  20. package/dist/{graph-CI9JXKqO.js → graph-Ce-59ZXn.js} +5 -5
  21. package/dist/{graph-CI9JXKqO.js.map → graph-Ce-59ZXn.js.map} +1 -1
  22. package/dist/{improve-BOXTLWJ3.js → improve-BZXt2qM0.js} +837 -704
  23. package/dist/improve-BZXt2qM0.js.map +1 -0
  24. package/dist/{improvement-adapter-HUt_-cWA.d.ts → improvement-adapter-sIthWkcN.d.ts} +2 -2
  25. package/dist/index.d.ts +6 -14
  26. package/dist/index.js +10 -10
  27. package/dist/intelligence.d.ts +4 -4
  28. package/dist/intelligence.js +205 -191
  29. package/dist/intelligence.js.map +1 -1
  30. package/dist/kernel.d.ts +3 -3
  31. package/dist/kernel.js +10 -10
  32. package/dist/{loop-runner-pmPIHFVY.js → loop-runner-B0MV1-CD.js} +2 -2
  33. package/dist/{loop-runner-pmPIHFVY.js.map → loop-runner-B0MV1-CD.js.map} +1 -1
  34. package/dist/{loop-runner-CWzG1bH4.d.ts → loop-runner-CuhbgVGo.d.ts} +3 -3
  35. package/dist/loop-runner-bin.d.ts +1 -1
  36. package/dist/loop-runner-bin.js +1 -1
  37. package/dist/mcp/bin.js +3 -3
  38. package/dist/mcp/index.d.ts +1 -1
  39. package/dist/mcp/index.js +5 -5
  40. package/dist/placement.d.ts +2 -26
  41. package/dist/placement.js +1 -35
  42. package/dist/placement.js.map +1 -1
  43. package/dist/{prepare-bXkvPMJA.js → prepare-C-cWCyt3.js} +988 -735
  44. package/dist/prepare-C-cWCyt3.js.map +1 -0
  45. package/dist/{profile-Dpei_Sq0.js → profile-CbMw5hAn.js} +2 -2
  46. package/dist/{profile-Dpei_Sq0.js.map → profile-CbMw5hAn.js.map} +1 -1
  47. package/dist/profile-materialization-bPm0gGLO.d.ts +49 -0
  48. package/dist/profiles.d.ts +1 -1
  49. package/dist/{protected-model-port-BGgpy2r9.d.ts → protected-model-port-DVVh-hEk.d.ts} +2 -6
  50. package/dist/{provision-supervisor-CJ6Zz6dz.js → provision-supervisor-DL6gEMQp.js} +444 -419
  51. package/dist/provision-supervisor-DL6gEMQp.js.map +1 -0
  52. package/dist/{runtime-B2fjL9Oi.js → runtime-eghmj6W4.js} +1245 -1028
  53. package/dist/runtime-eghmj6W4.js.map +1 -0
  54. package/dist/{sandbox-profile-compat-BzVBFqrz.js → sandbox-profile-compat-FN2kab2-.js} +72 -72
  55. package/dist/{sandbox-profile-compat-BzVBFqrz.js.map → sandbox-profile-compat-FN2kab2-.js.map} +1 -1
  56. package/dist/{search-executor-zMumiak_.js → search-executor-rbjdZ3OD.js} +3 -3
  57. package/dist/{search-executor-zMumiak_.js.map → search-executor-rbjdZ3OD.js.map} +1 -1
  58. package/dist/{server-_4voDNrl.js → server-BiK1Kcno.js} +4 -4
  59. package/dist/{server-_4voDNrl.js.map → server-BiK1Kcno.js.map} +1 -1
  60. package/dist/{structural-rollout-DpLCXzaL.js → structural-rollout-BD9IN7K_.js} +3 -3
  61. package/dist/{structural-rollout-DpLCXzaL.js.map → structural-rollout-BD9IN7K_.js.map} +1 -1
  62. package/dist/{supervise-qAwXmPtD.js → supervise-DmOi7gll.js} +6525 -5562
  63. package/dist/supervise-DmOi7gll.js.map +1 -0
  64. package/dist/{supervisor-DHrUJhEZ.js → supervisor-DUWcecAd.js} +13717 -12778
  65. package/dist/supervisor-DUWcecAd.js.map +1 -0
  66. package/dist/testing.d.ts +1 -1
  67. package/dist/testing.js +13 -13
  68. package/dist/tui/index.d.ts +1 -1
  69. package/dist/tui/index.js +1 -1
  70. package/dist/{types-CaOXqRTq.d.ts → types-Cgs89PQd.d.ts} +315 -409
  71. package/dist/{types-zWfqDjeL.d.ts → types-Cwrea-bU.d.ts} +2 -17
  72. package/dist/workspace-store/index.d.ts +1 -82
  73. package/dist/workspace-store/index.js +274 -680
  74. package/dist/workspace-store/index.js.map +1 -1
  75. package/package.json +8 -8
  76. package/dist/driver-control-acknowledgers-C53ggdJ6.js.map +0 -1
  77. package/dist/improve-BOXTLWJ3.js.map +0 -1
  78. package/dist/prepare-bXkvPMJA.js.map +0 -1
  79. package/dist/profile-materialization-B1wm2SPT.d.ts +0 -94
  80. package/dist/provision-supervisor-CJ6Zz6dz.js.map +0 -1
  81. package/dist/runtime-B2fjL9Oi.js.map +0 -1
  82. package/dist/supervise-qAwXmPtD.js.map +0 -1
  83. package/dist/supervisor-DHrUJhEZ.js.map +0 -1
package/dist/durable.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { i as publishExclusiveDurableFile, o as writeAtomicDurableFile } from "./durable-file-gNI9ILAn.js";
2
- import { Di as contentAddress, Ei as detachedSnapshot, S as FileSpawnJournal, ar as isFiniteNumber, ir as failedItems, it as loadSpawnForest, qr as authoredProfileDigest } from "./supervisor-DHrUJhEZ.js";
2
+ import { Hr as authoredProfileDigest, S as FileSpawnJournal, Si as contentAddress, ar as isFiniteNumber, at as loadSpawnForest, ir as failedItems, xi as detachedSnapshot } from "./supervisor-DUWcecAd.js";
3
3
  import { f as RuntimeRunStateError, m as ValidationError } from "./errors-DodWX-cb.js";
4
4
  import { t as isRecord } from "./record-value-B6bwJxLa.js";
5
- import { G as addSpend, J as cloneSpend, Z as errorMessage, pt as zeroSpend } from "./sandbox-profile-compat-BzVBFqrz.js";
5
+ import { W as addSpend, X as errorMessage, ft as zeroSpend, q as cloneSpend } from "./sandbox-profile-compat-FN2kab2-.js";
6
6
  import { a as withPursuitContext, t as composeRuntimeHooks } from "./runtime-hooks-tXpAarhW.js";
7
7
  import { a as readCommittedJsonLines, n as isNoEntError, t as appendCommittedJsonLine } from "./jsonl-file-C9Kde_0Z.js";
8
- import { J as readRootStreamReceipt, a as superviseRootProfile, q as readRootStream, t as supervise } from "./supervise-qAwXmPtD.js";
9
- import { a as applyExactAgentProfileDiff } from "./profile-Dpei_Sq0.js";
8
+ import { J as readRootStreamReceipt, a as superviseRootProfile, q as readRootStream, t as supervise } from "./supervise-DmOi7gll.js";
9
+ import { a as applyExactAgentProfileDiff } from "./profile-CbMw5hAn.js";
10
10
  import { g as supervisorRunDir } from "./run-cancellation-C9oL62sW.js";
11
- import { i as superviseAgentGraph } from "./graph-CI9JXKqO.js";
11
+ import { i as superviseAgentGraph } from "./graph-Ce-59ZXn.js";
12
12
  import { agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, canonicalCandidateJson, sha256Bytes } from "@tangle-network/agent-interface";
13
13
  import { createHash } from "node:crypto";
14
14
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -1217,6 +1217,269 @@ function reviewPage(version, score, verdict) {
1217
1217
  ].join("\n");
1218
1218
  }
1219
1219
  //#endregion
1220
+ //#region src/durable/pursuit-version-run.ts
1221
+ /**
1222
+ * One pursuit version chain at run time: running a version in its directory, reading it back
1223
+ * and checking it is this node's run, judging it, turning it into the kernel's cell result, and
1224
+ * reading the chain back from its search ledger.
1225
+ */
1226
+ /** The execution identity a version's node and cell record. */
1227
+ function versionExecutionIdentity(pursuitId, taskRevision, nodeProfile) {
1228
+ return {
1229
+ model: {
1230
+ provider: "agent-runtime",
1231
+ alias: "supervisePursuit",
1232
+ unknown: "a version runs every model its tree chose; the version's settle record names them"
1233
+ },
1234
+ agent: {
1235
+ uri: `agent-profile:${pursuitId}`,
1236
+ revision: canonicalAgentProfileDigest(nodeProfile)
1237
+ },
1238
+ benchmark: {
1239
+ uri: `pursuit:${pursuitId}`,
1240
+ revision: taskRevision
1241
+ }
1242
+ };
1243
+ }
1244
+ /** A version as the judge and `next` read it. */
1245
+ function versionOf(record, parent, settleDigest, result) {
1246
+ return Object.freeze({
1247
+ version: record.version,
1248
+ nodeId: record.nodeId,
1249
+ runId: record.runId,
1250
+ runDir: record.runDir,
1251
+ settleDigest,
1252
+ result,
1253
+ profile: record.profile,
1254
+ ...parent?.seal === void 0 ? {} : { parent: {
1255
+ version: parent.version,
1256
+ runId: parent.runId,
1257
+ settleDigest: parent.seal.sha256
1258
+ } },
1259
+ ...record.change === void 0 ? {} : { change: record.change }
1260
+ });
1261
+ }
1262
+ function outcomeOf(settled, verdict) {
1263
+ if (verdict.score === null) return {
1264
+ status: "errored",
1265
+ metrics: {},
1266
+ error: {
1267
+ code: "unscored",
1268
+ message: `the judge could not score version ${settled.version}`,
1269
+ retryable: false
1270
+ }
1271
+ };
1272
+ if (settled.result.kind === "winner") return {
1273
+ status: "passed",
1274
+ score: verdict.score,
1275
+ metrics: {}
1276
+ };
1277
+ return {
1278
+ status: "failed",
1279
+ score: verdict.score,
1280
+ metrics: {},
1281
+ failure: {
1282
+ code: settled.result.reason,
1283
+ message: `version ${settled.version} settled without a winner: ${settled.result.reason}`
1284
+ }
1285
+ };
1286
+ }
1287
+ var VersionChainRun = class {
1288
+ ctx;
1289
+ sealed = /* @__PURE__ */ new Map();
1290
+ constructor(ctx) {
1291
+ this.ctx = ctx;
1292
+ }
1293
+ /** Run a version if its directory holds no settle record, read it back, and judge it. */
1294
+ async runCell(work) {
1295
+ const chain = await this.versionsOf();
1296
+ const record = chain.get(work.nodeId);
1297
+ if (record?.profile == null) throw new RuntimeRunStateError(`version node ${work.nodeId} has no profile to run`);
1298
+ const parent = record.parentNodeId === null ? void 0 : chain.get(record.parentNodeId);
1299
+ if (parent !== void 0 && (parent.seal === void 0 || parent.profile === null)) throw new RuntimeRunStateError(`version ${record.version}'s parent has no sealed result`);
1300
+ if (await readSettleRecord(record.runDir) === void 0) {
1301
+ const signal = AbortSignal.any([work.signal, this.ctx.expired]);
1302
+ if (signal.aborted) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version} was not started: ${errorMessage(signal.reason)}`);
1303
+ await this.runVersion(record, parent, signal);
1304
+ }
1305
+ const { settled, byteLength } = await this.readVersion(record, parent);
1306
+ const verdict = await this.judgeVersion(settled, work.signal);
1307
+ return this.cellResult(settled, byteLength, verdict, work.lane);
1308
+ }
1309
+ /** Run one version: the first as the call's own run, a later one as a fork of its parent. */
1310
+ async runVersion(record, parent, signal) {
1311
+ const { profile, task, base, firstFork, runOne } = this.ctx;
1312
+ if (parent === void 0 || record.change === void 0) {
1313
+ await runOne(profile, task, {
1314
+ ...base,
1315
+ runId: record.runId,
1316
+ runDir: record.runDir,
1317
+ ...firstFork === void 0 ? {} : { fork: firstFork },
1318
+ signal
1319
+ });
1320
+ return;
1321
+ }
1322
+ const fork = {
1323
+ runDir: parent.runDir,
1324
+ settleDigest: parent.seal.sha256,
1325
+ change: record.change,
1326
+ acceptUncertain: true
1327
+ };
1328
+ const check = parent.verdict?.check;
1329
+ await runOne(parent.profile, task, {
1330
+ ...base,
1331
+ ...base.continuation !== void 0 && check !== void 0 ? { continuation: {
1332
+ ...base.continuation,
1333
+ best: {
1334
+ label: `v${parent.version}`,
1335
+ verdict: check
1336
+ }
1337
+ } } : {},
1338
+ runId: record.runId,
1339
+ runDir: record.runDir,
1340
+ fork,
1341
+ signal
1342
+ });
1343
+ }
1344
+ /**
1345
+ * Read a settled version back and check it is this node's run: its root ran the node's profile
1346
+ * and, for a fork, recorded the parent's seal and the change. A directory that holds another
1347
+ * run is refused, never adopted.
1348
+ */
1349
+ async readVersion(record, parent) {
1350
+ const { base, firstFork, taskRevision } = this.ctx;
1351
+ const { bytes, result } = await readSealed(record.runDir, record.version);
1352
+ if (result.tree.root !== record.runId) throw new RuntimeRunStateError(`supervisePursuit versions: ${record.runDir} holds run '${result.tree.root}', not version ${record.version}'s '${record.runId}'`);
1353
+ const root = (await new FileSpawnJournal(resolve(record.runDir, "spawn-journal.jsonl")).loadTree(record.runId))?.find((event) => event.kind === "spawned" && event.parent === void 0);
1354
+ const ran = root?.identity?.profileDigest;
1355
+ const expected = authoredProfileDigest(superviseRootProfile(record.profile, base.profileGuidance));
1356
+ const ranTask = root?.identity?.taskDigest;
1357
+ const correlation = root?.identity?.correlation;
1358
+ const fork = parent !== void 0 ? {
1359
+ settleDigest: parent.seal?.sha256,
1360
+ changeId: record.change?.id
1361
+ } : firstFork === void 0 ? void 0 : {
1362
+ settleDigest: firstFork.settleDigest,
1363
+ changeId: firstFork.change.id
1364
+ };
1365
+ const mismatch = [
1366
+ ran !== expected ? `its root ran profile ${ran}, not ${expected}` : void 0,
1367
+ ranTask !== taskRevision ? `its root ran task ${ranTask}, not ${taskRevision}` : void 0,
1368
+ contentAddress(root?.budget) !== contentAddress(base.budget) ? "its root ran under another budget" : void 0,
1369
+ fork !== void 0 && correlation?.forkParentSettleDigest !== fork.settleDigest ? `its root forked from seal ${correlation?.forkParentSettleDigest}, not ${fork.settleDigest}` : void 0,
1370
+ fork !== void 0 && correlation?.forkProfileDiffId !== fork.changeId ? `its root applied change ${correlation?.forkProfileDiffId}, not ${fork.changeId}` : void 0
1371
+ ].filter((item) => item !== void 0);
1372
+ if (mismatch.length > 0) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version} at ${record.runDir} is not this chain's run: ${mismatch.join("; ")}`);
1373
+ const settled = versionOf(record, parent, sha256Bytes(bytes), result);
1374
+ this.sealed.set(settled.settleDigest, result);
1375
+ return {
1376
+ settled,
1377
+ byteLength: bytes.byteLength
1378
+ };
1379
+ }
1380
+ async judgeVersion(settled, signal) {
1381
+ const { judge } = this.ctx;
1382
+ const verdict = await judge.judge(settled, signal);
1383
+ if (typeof verdict !== "object" || verdict === null) throw new ValidationError("supervisePursuit versions: the judge returned no verdict");
1384
+ if (verdict.judgeDigest !== judge.digest) throw new ValidationError(`supervisePursuit versions: the verdict for version ${settled.version} carries ${String(verdict.judgeDigest)}, not the pinned judge ${judge.digest}`);
1385
+ if (verdict.score !== null && !isFiniteNumber(verdict.score)) throw new ValidationError("supervisePursuit versions: a verdict score must be a finite number or null");
1386
+ return JSON.parse(JSON.stringify(verdict));
1387
+ }
1388
+ cellResult(settled, byteLength, verdict, lane) {
1389
+ const spent = settled.result.spentTotal;
1390
+ const settlePath = resolve(settled.runDir, SETTLE_RECORD_FILE);
1391
+ return {
1392
+ outcome: outcomeOf(settled, verdict),
1393
+ accounting: versionAccounting(spent),
1394
+ identity: versionExecutionIdentity(this.ctx.pursuitId, this.ctx.taskRevision, settled.profile),
1395
+ boxMinutes: isFiniteNumber(spent.boxMinutes) && spent.boxMinutesKnown !== false ? spent.boxMinutes : null,
1396
+ wallMs: isFiniteNumber(spent.ms) ? Math.max(0, Math.round(spent.ms)) : null,
1397
+ placement: {
1398
+ lane,
1399
+ boxId: null
1400
+ },
1401
+ traceRef: { unknown: `version ${settled.version} is run ${settled.runId}; the chain records no trace id` },
1402
+ artifacts: [{
1403
+ role: "settle-record",
1404
+ uri: pathToFileURL(settlePath).href,
1405
+ sha256: settled.settleDigest,
1406
+ byteLength
1407
+ }, this.ctx.recorder.blob("verdict", {
1408
+ kind: "version-verdict",
1409
+ version: settled.version,
1410
+ runId: settled.runId,
1411
+ verdict
1412
+ })]
1413
+ };
1414
+ }
1415
+ /** Every version whose latest settled cell carries a verdict, first first, each read back from
1416
+ * its sealed `result.json`. */
1417
+ async judgedVersions(chain) {
1418
+ const judged = [];
1419
+ for (const record of chain.values()) {
1420
+ if (record.seal === void 0 || record.verdict === void 0) continue;
1421
+ const seal = record.seal.sha256;
1422
+ let result = this.sealed.get(seal);
1423
+ if (result === void 0) {
1424
+ const read = await readSealed(record.runDir, record.version);
1425
+ if (sha256Bytes(read.bytes) !== seal) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version}'s result.json changed after it was judged`);
1426
+ result = read.result;
1427
+ this.sealed.set(seal, result);
1428
+ }
1429
+ const parent = record.parentNodeId === null ? void 0 : chain.get(record.parentNodeId);
1430
+ judged.push(Object.freeze({
1431
+ ...versionOf(record, parent, seal, result),
1432
+ verdict: record.verdict
1433
+ }));
1434
+ }
1435
+ return judged;
1436
+ }
1437
+ /**
1438
+ * Every node of the chain, in registration order, from the ledger. The state holds cells, not
1439
+ * their events' artifacts, so each cell's seal and verdict are read from the ledger lines the
1440
+ * state verified, through Eval's own line parser.
1441
+ */
1442
+ async versionsOf() {
1443
+ const { recorder, ledgerPath, searchId, runDir, runId } = this.ctx;
1444
+ const state = await recorder.state();
1445
+ const head = state.head?.sequence ?? -1;
1446
+ const nodes = state.nodes().map((node) => ({
1447
+ node,
1448
+ cellId: state.cells({ nodeId: node.nodeId })[0]?.cellId,
1449
+ diff: node.edgeIds[0] === void 0 ? void 0 : state.edge(node.edgeIds[0])?.diffs[0]
1450
+ }));
1451
+ const settledCells = /* @__PURE__ */ new Map();
1452
+ const text = await readFile(ledgerPath, "utf8");
1453
+ for (const [index, line] of text.split("\n").entries()) {
1454
+ if (line.length === 0) continue;
1455
+ const entry = parseSearchLedgerLine(line, searchId, {
1456
+ path: ledgerPath,
1457
+ line: index + 1
1458
+ });
1459
+ if (entry.sequence > head) break;
1460
+ if (entry.event.kind === "cell-settled") settledCells.set(entry.event.cellId, entry.event);
1461
+ }
1462
+ const chain = /* @__PURE__ */ new Map();
1463
+ for (const { node, cellId, diff } of nodes) {
1464
+ const settled = cellId === void 0 ? void 0 : settledCells.get(cellId);
1465
+ const artifact = (role) => settled?.artifacts.find((candidate) => candidate.role === role);
1466
+ const seal = artifact("settle-record");
1467
+ const verdict = artifact("verdict");
1468
+ chain.set(node.nodeId, {
1469
+ nodeId: node.nodeId,
1470
+ version: node.ordinal + 1,
1471
+ ...versionRun(runDir, runId, node.ordinal + 1),
1472
+ profile: loadNode(recorder, node).profile,
1473
+ parentNodeId: node.primaryParentId,
1474
+ ...diff === void 0 || "unknown" in diff ? {} : { change: recorder.readBlob(diff).diffs[0] },
1475
+ ...seal === void 0 ? {} : { seal },
1476
+ ...verdict === void 0 ? {} : { verdict: recorder.readBlob(verdict).verdict }
1477
+ });
1478
+ }
1479
+ return chain;
1480
+ }
1481
+ };
1482
+ //#endregion
1220
1483
  //#region src/durable/pursuit-versions.ts
1221
1484
  /**
1222
1485
  * The pursuit version chain, on Eval's search kernel (`runSearch`).
@@ -1287,9 +1550,8 @@ const MAX_TIMER_MS = 2147483647;
1287
1550
  /** 9999-12-31T23:59:59.999Z: the latest instant the ledger's four-digit-year timestamps hold, so
1288
1551
  * a deadline such as `Number.MAX_SAFE_INTEGER` means no deadline rather than an invalid date. */
1289
1552
  const LATEST_DEADLINE_MS = 0xe677d21fdbff;
1290
- /** Run a version chain. `supervisePursuit` calls this when `versions` is set. */
1291
- async function runPursuitVersions(profile, task, opts, runOne) {
1292
- const { versions, fork: firstFork, signal: callerSignal, ...base } = opts;
1553
+ /** Refuse a chain call that no version could satisfy, before any compute. */
1554
+ function assertChainCall(versions, base) {
1293
1555
  assertPursuitVersions(versions);
1294
1556
  for (const key of [
1295
1557
  "journal",
@@ -1298,8 +1560,14 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1298
1560
  "steerDir"
1299
1561
  ]) if (base[key] !== void 0) throw new ValidationError(`supervisePursuit versions: ${key} names one run, and a version chain has one per version; omit it`);
1300
1562
  if (versions.next === "review-of-best" && base.continuation?.profile.review === void 0) throw new ValidationError("supervisePursuit versions: next 'review-of-best' needs continuation.profile.review, the words the next version reads about its review");
1301
- const { judge, stop } = versions;
1563
+ const { stop } = versions;
1302
1564
  if (base.budget.maxUsd !== void 0 && base.budget.maxUsd > stop.maxUsd) throw new ValidationError(`supervisePursuit versions: budget.maxUsd ${base.budget.maxUsd} is above stop.maxUsd ${stop.maxUsd}, so no version could start`);
1565
+ }
1566
+ /** Run a version chain. `supervisePursuit` calls this when `versions` is set. */
1567
+ async function runPursuitVersions(profile, task, opts, runOne) {
1568
+ const { versions, fork: firstFork, signal: callerSignal, ...base } = opts;
1569
+ assertChainCall(versions, base);
1570
+ const { judge, stop } = versions;
1303
1571
  const next = versions.next === "review-of-best" ? reviewOfBest(base.runId ?? "supervise", base.continuation?.profile.review ?? "") : versions.next;
1304
1572
  const now = base.now ?? Date.now;
1305
1573
  const pursuitId = base.pursuitId.trim();
@@ -1311,33 +1579,98 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1311
1579
  if (await exists(retired)) throw new ValidationError(`supervisePursuit versions: ${retired} holds a chain in the retired versions.jsonl format; finish it on the agent-runtime release that wrote it, or start a new chain in another runDir`);
1312
1580
  const firstProfile = jsonProfile(firstFork === void 0 ? profile : applyExactAgentProfileDiff(profile, firstFork.change, "supervisePursuit versions"));
1313
1581
  const taskRevision = pursuitValueDigest(task, "task");
1314
- const identity = (nodeProfile) => ({
1315
- model: {
1316
- provider: "agent-runtime",
1317
- alias: "supervisePursuit",
1318
- unknown: "a version runs every model its tree chose; the version's settle record names them"
1319
- },
1320
- agent: {
1321
- uri: `agent-profile:${pursuitId}`,
1322
- revision: canonicalAgentProfileDigest(nodeProfile)
1323
- },
1324
- benchmark: {
1325
- uri: `pursuit:${pursuitId}`,
1326
- revision: taskRevision
1327
- }
1328
- });
1329
1582
  const ledger = openSearchLedger({
1330
1583
  path: ledgerPath,
1331
1584
  searchId
1332
1585
  });
1333
- const deadline = (await ledger.state()).header?.budget.deadline ?? new Date(Math.min(now() - settledElapsed(await readSettleRecord(runDir)) + stop.deadlineMs, LATEST_DEADLINE_MS)).toISOString();
1334
- const failureLimit = stop.identicalFailures ?? DEFAULT_IDENTICAL_FAILURES;
1586
+ const deadline = await chainDeadline((await ledger.state()).header, now, runDir, stop);
1335
1587
  const policy = incumbent({
1336
1588
  patience: stop.patience,
1337
1589
  ...stop.minImprovement === void 0 ? {} : { minImprovement: stop.minImprovement }
1338
1590
  });
1339
1591
  const allocation = uniform();
1340
- const recorder = await SearchRecorder.open({
1592
+ const recorder = await openVersionRecorder({
1593
+ ledger,
1594
+ now,
1595
+ pursuitId,
1596
+ taskRevision,
1597
+ judge,
1598
+ stop,
1599
+ policy,
1600
+ allocation,
1601
+ deadline,
1602
+ firstProfile
1603
+ });
1604
+ const clock = armChainDeadline(deadline, now);
1605
+ const chain = new VersionChainRun({
1606
+ profile,
1607
+ task,
1608
+ base,
1609
+ firstFork,
1610
+ runOne,
1611
+ judge,
1612
+ recorder,
1613
+ expired: clock.signal,
1614
+ pursuitId,
1615
+ runDir,
1616
+ runId,
1617
+ ledgerPath,
1618
+ searchId,
1619
+ taskRevision
1620
+ });
1621
+ const failureLimit = stop.identicalFailures ?? DEFAULT_IDENTICAL_FAILURES;
1622
+ try {
1623
+ const closed = await runSearch({
1624
+ recorder,
1625
+ root: {
1626
+ profile: firstProfile,
1627
+ refusal: null
1628
+ },
1629
+ codec: versionCodec,
1630
+ policy,
1631
+ allocation,
1632
+ proposer: versionProposer(versions.next, next, chain, failureLimit),
1633
+ executor: versionExecutor(chain, base.budget.maxUsd),
1634
+ admit: (node) => node.refusal,
1635
+ ...callerSignal === void 0 ? {} : { signal: callerSignal },
1636
+ now
1637
+ });
1638
+ const judged = await chain.judgedVersions(await chain.versionsOf());
1639
+ const failed = closed.reason === "converged" ? identicalFailureStreak(judged, failureLimit) : null;
1640
+ const stopped = failed === null ? null : {
1641
+ versions: failureLimit,
1642
+ failure: failed
1643
+ };
1644
+ const best = judged.find((version) => version.nodeId === closed.leader);
1645
+ if (best === void 0) throw new RuntimeRunStateError(`supervisePursuit versions: the chain in ${ledgerPath} closed (${closed.reason}) without a judged version to keep`);
1646
+ const observerPath = resolve(best.runDir, "observer.jsonl");
1647
+ return Object.freeze({
1648
+ result: best.result,
1649
+ pursuit: projectPursuit(await new FileObserverJournal(observerPath, pursuitId).read()),
1650
+ observerPath,
1651
+ settlePath: resolve(best.runDir, SETTLE_RECORD_FILE),
1652
+ versions: Object.freeze({
1653
+ ledgerPath,
1654
+ searchId,
1655
+ reason: closed.reason,
1656
+ ...stopped === null ? {} : { identicalFailures: stopped },
1657
+ best: best.version,
1658
+ versions: Object.freeze(judged),
1659
+ spend: closed.state.audit.spend,
1660
+ receipt: recorder.receipt({
1661
+ producerId: "pursuit-versions",
1662
+ runId
1663
+ })
1664
+ })
1665
+ });
1666
+ } finally {
1667
+ clock.cancel();
1668
+ }
1669
+ }
1670
+ /** Open the chain's search recorder: its subject, process revision, splits, policy and budget. */
1671
+ function openVersionRecorder(input) {
1672
+ const { ledger, now, pursuitId, taskRevision, judge, stop, policy, allocation, deadline } = input;
1673
+ return SearchRecorder.open({
1341
1674
  ledger,
1342
1675
  now
1343
1676
  }, {
@@ -1390,8 +1723,21 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1390
1723
  },
1391
1724
  containment: null,
1392
1725
  derivedFrom: null,
1393
- identity: identity(firstProfile)
1726
+ identity: versionExecutionIdentity(pursuitId, taskRevision, input.firstProfile)
1394
1727
  });
1728
+ }
1729
+ /**
1730
+ * The chain's clock starts with its first version, or when the chain opened on a first version
1731
+ * that had already settled. A resumed chain keeps the deadline its ledger recorded.
1732
+ */
1733
+ async function chainDeadline(opened, now, runDir, stop) {
1734
+ return opened?.budget.deadline ?? new Date(Math.min(now() - settledElapsed(await readSettleRecord(runDir)) + stop.deadlineMs, LATEST_DEADLINE_MS)).toISOString();
1735
+ }
1736
+ /**
1737
+ * The chain's deadline aborts a running version. A timer longer than 2^31 - 1 ms fires at once
1738
+ * in Node, so a long chain re-arms in steps.
1739
+ */
1740
+ function armChainDeadline(deadline, now) {
1395
1741
  const deadlineAt = Date.parse(deadline);
1396
1742
  const expired = new AbortController();
1397
1743
  let timer;
@@ -1405,35 +1751,22 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1405
1751
  timer.unref?.();
1406
1752
  };
1407
1753
  arm();
1408
- const sealed = /* @__PURE__ */ new Map();
1409
- const codec = {
1410
- node(store, node) {
1411
- if (node.profile !== null) {
1412
- const artifact = store.blob("agent-profile", {
1413
- kind: "agent-profile",
1414
- profile: node.profile
1415
- });
1416
- return {
1417
- artifactDigest: canonicalAgentProfileDigest(node.profile),
1418
- artifact,
1419
- surfaces: [{
1420
- surfaceId: "profile",
1421
- kind: "agent-profile",
1422
- artifact
1423
- }]
1424
- };
1425
- }
1426
- const refused = {
1427
- kind: "unapplied-change",
1428
- parentDigest: node.parentDigest ?? null,
1429
- change: node.change ?? null
1430
- };
1431
- const artifact = store.blob("change", {
1432
- ...refused,
1433
- refusal: node.refusal
1754
+ return {
1755
+ signal: expired.signal,
1756
+ cancel() {
1757
+ if (timer !== void 0) clearTimeout(timer);
1758
+ }
1759
+ };
1760
+ }
1761
+ const versionCodec = {
1762
+ node(store, node) {
1763
+ if (node.profile !== null) {
1764
+ const artifact = store.blob("agent-profile", {
1765
+ kind: "agent-profile",
1766
+ profile: node.profile
1434
1767
  });
1435
1768
  return {
1436
- artifactDigest: canonicalCandidateDigest(refused),
1769
+ artifactDigest: canonicalAgentProfileDigest(node.profile),
1437
1770
  artifact,
1438
1771
  surfaces: [{
1439
1772
  surfaceId: "profile",
@@ -1441,24 +1774,44 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1441
1774
  artifact
1442
1775
  }]
1443
1776
  };
1444
- },
1445
- diff(store, parent, child) {
1446
- if (parent.profile === null || child.profile === null || child.change === void 0) return { unknown: "a refused change has no profile to diff" };
1447
- const from = canonicalAgentProfileDigest(parent.profile);
1448
- if (child.parentDigest !== from) return { unknown: "the change was written against another parent" };
1449
- return store.blob("diff", {
1450
- kind: "agent-profile-diff",
1451
- from,
1452
- to: canonicalAgentProfileDigest(child.profile),
1453
- diffs: [child.change]
1454
- });
1455
- },
1456
- load(store, node) {
1457
- return loadNode(store, node);
1458
1777
  }
1459
- };
1460
- const executor = {
1461
- lanes: () => [base.budget.maxUsd === void 0 ? {
1778
+ const refused = {
1779
+ kind: "unapplied-change",
1780
+ parentDigest: node.parentDigest ?? null,
1781
+ change: node.change ?? null
1782
+ };
1783
+ const artifact = store.blob("change", {
1784
+ ...refused,
1785
+ refusal: node.refusal
1786
+ });
1787
+ return {
1788
+ artifactDigest: canonicalCandidateDigest(refused),
1789
+ artifact,
1790
+ surfaces: [{
1791
+ surfaceId: "profile",
1792
+ kind: "agent-profile",
1793
+ artifact
1794
+ }]
1795
+ };
1796
+ },
1797
+ diff(store, parent, child) {
1798
+ if (parent.profile === null || child.profile === null || child.change === void 0) return { unknown: "a refused change has no profile to diff" };
1799
+ const from = canonicalAgentProfileDigest(parent.profile);
1800
+ if (child.parentDigest !== from) return { unknown: "the change was written against another parent" };
1801
+ return store.blob("diff", {
1802
+ kind: "agent-profile-diff",
1803
+ from,
1804
+ to: canonicalAgentProfileDigest(child.profile),
1805
+ diffs: [child.change]
1806
+ });
1807
+ },
1808
+ load(store, node) {
1809
+ return loadNode(store, node);
1810
+ }
1811
+ };
1812
+ function versionExecutor(chain, maxUsd) {
1813
+ return {
1814
+ lanes: () => [maxUsd === void 0 ? {
1462
1815
  name: LANE,
1463
1816
  capacity: 1,
1464
1817
  costCap: "estimate",
@@ -1467,31 +1820,22 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1467
1820
  name: LANE,
1468
1821
  capacity: 1,
1469
1822
  costCap: "hard",
1470
- cellUsd: base.budget.maxUsd
1823
+ cellUsd: maxUsd
1471
1824
  }],
1472
1825
  place: () => LANE,
1473
1826
  adopt: async () => null,
1474
- async run(work) {
1475
- const chain = await versionsOf();
1476
- const record = chain.get(work.nodeId);
1477
- if (record?.profile == null) throw new RuntimeRunStateError(`version node ${work.nodeId} has no profile to run`);
1478
- const parent = record.parentNodeId === null ? void 0 : chain.get(record.parentNodeId);
1479
- if (parent !== void 0 && (parent.seal === void 0 || parent.profile === null)) throw new RuntimeRunStateError(`version ${record.version}'s parent has no sealed result`);
1480
- if (await readSettleRecord(record.runDir) === void 0) {
1481
- const signal = AbortSignal.any([work.signal, expired.signal]);
1482
- if (signal.aborted) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version} was not started: ${errorMessage(signal.reason)}`);
1483
- await runVersion(record, parent, signal);
1484
- }
1485
- const { settled, byteLength } = await readVersion(record, parent);
1486
- return cellResult(settled, byteLength, await judgeVersion(settled, work.signal), work.lane);
1487
- }
1827
+ run: (work) => chain.runCell(work)
1488
1828
  };
1829
+ }
1830
+ /** The proposer: the caller's `next` (or the review of the kept version) as the one edge. */
1831
+ function versionProposer(nextOption, next, chain, failureLimit) {
1832
+ const reviewing = nextOption === "review-of-best";
1489
1833
  const proposerSource = {
1490
- uri: versions.next === "review-of-best" ? `${VERSION_CHAIN_URI}.review-of-best` : `${VERSION_CHAIN_URI}.next`,
1491
- revision: canonicalCandidateDigest({ next: versions.next === "review-of-best" ? "review-of-best" : Function.prototype.toString.call(versions.next) })
1834
+ uri: reviewing ? `${VERSION_CHAIN_URI}.review-of-best` : `${VERSION_CHAIN_URI}.next`,
1835
+ revision: canonicalCandidateDigest({ next: reviewing ? "review-of-best" : Function.prototype.toString.call(nextOption) })
1492
1836
  };
1493
- const proposer = {
1494
- name: versions.next === "review-of-best" ? "review-of-best" : "next",
1837
+ return {
1838
+ name: reviewing ? "review-of-best" : "next",
1495
1839
  kind: "optimizer",
1496
1840
  source: proposerSource,
1497
1841
  execution: {
@@ -1501,7 +1845,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1501
1845
  childrenPerProposal: 1,
1502
1846
  async propose(request) {
1503
1847
  const parent = request.parents[0];
1504
- const judged = await judgedVersions(await versionsOf());
1848
+ const judged = await chain.judgedVersions(await chain.versionsOf());
1505
1849
  const failure = identicalFailureStreak(judged, failureLimit);
1506
1850
  if (failure !== null) return {
1507
1851
  children: [],
@@ -1517,30 +1861,13 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1517
1861
  }, request.signal);
1518
1862
  if (typeof returned?.id !== "string" || returned.id.trim().length === 0) throw new ValidationError("supervisePursuit versions: next must return a change with an id");
1519
1863
  const change = JSON.parse(JSON.stringify(returned));
1520
- const parentDigest = canonicalAgentProfileDigest(parent.artifact.profile);
1521
- let child;
1522
- try {
1523
- child = {
1524
- profile: applyExactAgentProfileDiff(parent.artifact.profile, change, "supervisePursuit versions"),
1525
- change,
1526
- parentDigest,
1527
- refusal: null
1528
- };
1529
- } catch (error) {
1530
- child = {
1531
- profile: null,
1532
- change,
1533
- parentDigest,
1534
- refusal: errorMessage(error)
1535
- };
1536
- }
1537
1864
  return {
1538
1865
  children: [{
1539
- artifact: child,
1866
+ artifact: childNode(parent.artifact.profile, change),
1540
1867
  label: change.title ?? returned.id,
1541
1868
  rationale: (change.source?.notes ?? []).join("\n")
1542
1869
  }],
1543
- accounting: versions.next === "review-of-best" ? FREE : {
1870
+ accounting: reviewing ? FREE : {
1544
1871
  tokens: {
1545
1872
  status: "unknown",
1546
1873
  reason: "the caller's next reports no usage"
@@ -1554,259 +1881,25 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1554
1881
  };
1555
1882
  }
1556
1883
  };
1884
+ }
1885
+ /** The node a change makes, or the refused node when it does not apply to the parent. */
1886
+ function childNode(parentProfile, change) {
1887
+ const parentDigest = canonicalAgentProfileDigest(parentProfile);
1557
1888
  try {
1558
- const closed = await runSearch({
1559
- recorder,
1560
- root: {
1561
- profile: firstProfile,
1562
- refusal: null
1563
- },
1564
- codec,
1565
- policy,
1566
- allocation,
1567
- proposer,
1568
- executor,
1569
- admit: (node) => node.refusal,
1570
- ...callerSignal === void 0 ? {} : { signal: callerSignal },
1571
- now
1572
- });
1573
- const judged = await judgedVersions(await versionsOf());
1574
- const failed = closed.reason === "converged" ? identicalFailureStreak(judged, failureLimit) : null;
1575
- const stopped = failed === null ? null : {
1576
- versions: failureLimit,
1577
- failure: failed
1578
- };
1579
- const best = judged.find((version) => version.nodeId === closed.leader);
1580
- if (best === void 0) throw new RuntimeRunStateError(`supervisePursuit versions: the chain in ${ledgerPath} closed (${closed.reason}) without a judged version to keep`);
1581
- const observerPath = resolve(best.runDir, "observer.jsonl");
1582
- return Object.freeze({
1583
- result: best.result,
1584
- pursuit: projectPursuit(await new FileObserverJournal(observerPath, pursuitId).read()),
1585
- observerPath,
1586
- settlePath: resolve(best.runDir, SETTLE_RECORD_FILE),
1587
- versions: Object.freeze({
1588
- ledgerPath,
1589
- searchId,
1590
- reason: closed.reason,
1591
- ...stopped === null ? {} : { identicalFailures: stopped },
1592
- best: best.version,
1593
- versions: Object.freeze(judged),
1594
- spend: closed.state.audit.spend,
1595
- receipt: recorder.receipt({
1596
- producerId: "pursuit-versions",
1597
- runId
1598
- })
1599
- })
1600
- });
1601
- } finally {
1602
- if (timer !== void 0) clearTimeout(timer);
1603
- }
1604
- /** Run one version: the first as the call's own run, a later one as a fork of its parent. */
1605
- async function runVersion(record, parent, signal) {
1606
- if (parent === void 0 || record.change === void 0) {
1607
- await runOne(profile, task, {
1608
- ...base,
1609
- runId: record.runId,
1610
- runDir: record.runDir,
1611
- ...firstFork === void 0 ? {} : { fork: firstFork },
1612
- signal
1613
- });
1614
- return;
1615
- }
1616
- const fork = {
1617
- runDir: parent.runDir,
1618
- settleDigest: parent.seal.sha256,
1619
- change: record.change,
1620
- acceptUncertain: true
1621
- };
1622
- const check = parent.verdict?.check;
1623
- await runOne(parent.profile, task, {
1624
- ...base,
1625
- ...base.continuation !== void 0 && check !== void 0 ? { continuation: {
1626
- ...base.continuation,
1627
- best: {
1628
- label: `v${parent.version}`,
1629
- verdict: check
1630
- }
1631
- } } : {},
1632
- runId: record.runId,
1633
- runDir: record.runDir,
1634
- fork,
1635
- signal
1636
- });
1637
- }
1638
- /**
1639
- * Read a settled version back and check it is this node's run: its root ran the node's profile
1640
- * and, for a fork, recorded the parent's seal and the change. A directory that holds another
1641
- * run is refused, never adopted.
1642
- */
1643
- async function readVersion(record, parent) {
1644
- const { bytes, result } = await readSealed(record.runDir, record.version);
1645
- if (result.tree.root !== record.runId) throw new RuntimeRunStateError(`supervisePursuit versions: ${record.runDir} holds run '${result.tree.root}', not version ${record.version}'s '${record.runId}'`);
1646
- const root = (await new FileSpawnJournal(resolve(record.runDir, "spawn-journal.jsonl")).loadTree(record.runId))?.find((event) => event.kind === "spawned" && event.parent === void 0);
1647
- const ran = root?.identity?.profileDigest;
1648
- const expected = authoredProfileDigest(superviseRootProfile(record.profile, base.profileGuidance));
1649
- const ranTask = root?.identity?.taskDigest;
1650
- const correlation = root?.identity?.correlation;
1651
- const fork = parent !== void 0 ? {
1652
- settleDigest: parent.seal?.sha256,
1653
- changeId: record.change?.id
1654
- } : firstFork === void 0 ? void 0 : {
1655
- settleDigest: firstFork.settleDigest,
1656
- changeId: firstFork.change.id
1657
- };
1658
- const mismatch = [
1659
- ran !== expected ? `its root ran profile ${ran}, not ${expected}` : void 0,
1660
- ranTask !== taskRevision ? `its root ran task ${ranTask}, not ${taskRevision}` : void 0,
1661
- contentAddress(root?.budget) !== contentAddress(base.budget) ? "its root ran under another budget" : void 0,
1662
- fork !== void 0 && correlation?.forkParentSettleDigest !== fork.settleDigest ? `its root forked from seal ${correlation?.forkParentSettleDigest}, not ${fork.settleDigest}` : void 0,
1663
- fork !== void 0 && correlation?.forkProfileDiffId !== fork.changeId ? `its root applied change ${correlation?.forkProfileDiffId}, not ${fork.changeId}` : void 0
1664
- ].filter((item) => item !== void 0);
1665
- if (mismatch.length > 0) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version} at ${record.runDir} is not this chain's run: ${mismatch.join("; ")}`);
1666
- const settled = versionOf(record, parent, sha256Bytes(bytes), result);
1667
- sealed.set(settled.settleDigest, result);
1668
1889
  return {
1669
- settled,
1670
- byteLength: bytes.byteLength
1890
+ profile: applyExactAgentProfileDiff(parentProfile, change, "supervisePursuit versions"),
1891
+ change,
1892
+ parentDigest,
1893
+ refusal: null
1671
1894
  };
1672
- }
1673
- async function judgeVersion(settled, signal) {
1674
- const verdict = await judge.judge(settled, signal);
1675
- if (typeof verdict !== "object" || verdict === null) throw new ValidationError("supervisePursuit versions: the judge returned no verdict");
1676
- if (verdict.judgeDigest !== judge.digest) throw new ValidationError(`supervisePursuit versions: the verdict for version ${settled.version} carries ${String(verdict.judgeDigest)}, not the pinned judge ${judge.digest}`);
1677
- if (verdict.score !== null && !isFiniteNumber(verdict.score)) throw new ValidationError("supervisePursuit versions: a verdict score must be a finite number or null");
1678
- return JSON.parse(JSON.stringify(verdict));
1679
- }
1680
- function cellResult(settled, byteLength, verdict, lane) {
1681
- const spent = settled.result.spentTotal;
1682
- const settlePath = resolve(settled.runDir, SETTLE_RECORD_FILE);
1895
+ } catch (error) {
1683
1896
  return {
1684
- outcome: verdict.score === null ? {
1685
- status: "errored",
1686
- metrics: {},
1687
- error: {
1688
- code: "unscored",
1689
- message: `the judge could not score version ${settled.version}`,
1690
- retryable: false
1691
- }
1692
- } : settled.result.kind === "winner" ? {
1693
- status: "passed",
1694
- score: verdict.score,
1695
- metrics: {}
1696
- } : {
1697
- status: "failed",
1698
- score: verdict.score,
1699
- metrics: {},
1700
- failure: {
1701
- code: settled.result.reason,
1702
- message: `version ${settled.version} settled without a winner: ${settled.result.reason}`
1703
- }
1704
- },
1705
- accounting: versionAccounting(spent),
1706
- identity: identity(settled.profile),
1707
- boxMinutes: isFiniteNumber(spent.boxMinutes) && spent.boxMinutesKnown !== false ? spent.boxMinutes : null,
1708
- wallMs: isFiniteNumber(spent.ms) ? Math.max(0, Math.round(spent.ms)) : null,
1709
- placement: {
1710
- lane,
1711
- boxId: null
1712
- },
1713
- traceRef: { unknown: `version ${settled.version} is run ${settled.runId}; the chain records no trace id` },
1714
- artifacts: [{
1715
- role: "settle-record",
1716
- uri: pathToFileURL(settlePath).href,
1717
- sha256: settled.settleDigest,
1718
- byteLength
1719
- }, recorder.blob("verdict", {
1720
- kind: "version-verdict",
1721
- version: settled.version,
1722
- runId: settled.runId,
1723
- verdict
1724
- })]
1897
+ profile: null,
1898
+ change,
1899
+ parentDigest,
1900
+ refusal: errorMessage(error)
1725
1901
  };
1726
1902
  }
1727
- /** A version as the judge and `next` read it. */
1728
- function versionOf(record, parent, settleDigest, result) {
1729
- return Object.freeze({
1730
- version: record.version,
1731
- nodeId: record.nodeId,
1732
- runId: record.runId,
1733
- runDir: record.runDir,
1734
- settleDigest,
1735
- result,
1736
- profile: record.profile,
1737
- ...parent?.seal === void 0 ? {} : { parent: {
1738
- version: parent.version,
1739
- runId: parent.runId,
1740
- settleDigest: parent.seal.sha256
1741
- } },
1742
- ...record.change === void 0 ? {} : { change: record.change }
1743
- });
1744
- }
1745
- /** Every version whose latest settled cell carries a verdict, first first, each read back from
1746
- * its sealed `result.json`. */
1747
- async function judgedVersions(chain) {
1748
- const judged = [];
1749
- for (const record of chain.values()) {
1750
- if (record.seal === void 0 || record.verdict === void 0) continue;
1751
- const seal = record.seal.sha256;
1752
- let result = sealed.get(seal);
1753
- if (result === void 0) {
1754
- const read = await readSealed(record.runDir, record.version);
1755
- if (sha256Bytes(read.bytes) !== seal) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version}'s result.json changed after it was judged`);
1756
- result = read.result;
1757
- sealed.set(seal, result);
1758
- }
1759
- const parent = record.parentNodeId === null ? void 0 : chain.get(record.parentNodeId);
1760
- judged.push(Object.freeze({
1761
- ...versionOf(record, parent, seal, result),
1762
- verdict: record.verdict
1763
- }));
1764
- }
1765
- return judged;
1766
- }
1767
- /**
1768
- * Every node of the chain, in registration order, from the ledger. The state holds cells, not
1769
- * their events' artifacts, so each cell's seal and verdict are read from the ledger lines the
1770
- * state verified, through Eval's own line parser.
1771
- */
1772
- async function versionsOf() {
1773
- const state = await recorder.state();
1774
- const head = state.head?.sequence ?? -1;
1775
- const nodes = state.nodes().map((node) => ({
1776
- node,
1777
- cellId: state.cells({ nodeId: node.nodeId })[0]?.cellId,
1778
- diff: node.edgeIds[0] === void 0 ? void 0 : state.edge(node.edgeIds[0])?.diffs[0]
1779
- }));
1780
- const settledCells = /* @__PURE__ */ new Map();
1781
- const text = await readFile(ledgerPath, "utf8");
1782
- for (const [index, line] of text.split("\n").entries()) {
1783
- if (line.length === 0) continue;
1784
- const entry = parseSearchLedgerLine(line, searchId, {
1785
- path: ledgerPath,
1786
- line: index + 1
1787
- });
1788
- if (entry.sequence > head) break;
1789
- if (entry.event.kind === "cell-settled") settledCells.set(entry.event.cellId, entry.event);
1790
- }
1791
- const chain = /* @__PURE__ */ new Map();
1792
- for (const { node, cellId, diff } of nodes) {
1793
- const settled = cellId === void 0 ? void 0 : settledCells.get(cellId);
1794
- const artifact = (role) => settled?.artifacts.find((candidate) => candidate.role === role);
1795
- const seal = artifact("settle-record");
1796
- const verdict = artifact("verdict");
1797
- chain.set(node.nodeId, {
1798
- nodeId: node.nodeId,
1799
- version: node.ordinal + 1,
1800
- ...versionRun(runDir, runId, node.ordinal + 1),
1801
- profile: loadNode(recorder, node).profile,
1802
- parentNodeId: node.primaryParentId,
1803
- ...diff === void 0 || "unknown" in diff ? {} : { change: recorder.readBlob(diff).diffs[0] },
1804
- ...seal === void 0 ? {} : { seal },
1805
- ...verdict === void 0 ? {} : { verdict: recorder.readBlob(verdict).verdict }
1806
- });
1807
- }
1808
- return chain;
1809
- }
1810
1903
  }
1811
1904
  function canonicalStop(stop) {
1812
1905
  return {