@tangle-network/agent-runtime 0.281.0 → 0.281.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/agent.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { $a as RuntimeStreamEvent, Yi as AgentRunSpec, ba as SandboxClient, va as OutputAdapter } from "./types-D56jQad-.js";
2
2
  import { a as createSurfaceImprovementProposer, c as SurfaceValidationIssue, d as validateSurfaces, i as SurfaceImprovementEdit, l as renderSurfaceIssues, n as DraftPatchInput, o as AgentSurfaces, r as DraftPatchOutput, s as ResolvedSurface, t as CreateSurfaceImprovementProposerOptions, u as resolveSubjectPath } from "./improvement-adapter-D5gwwoXQ.js";
3
- import { $h as fullProfileMaterialization, Gh as DefineProfileMaterializationContractOptions, Hh as AgentProfileMaterializationAxis, Jh as ProfileMaterializationIssue, Kh as KnownAgentProfileMaterializationAxis, Qh as defineProfileMaterializationContract, Uh as AssertProfileMaterializationOptions, Vh as AGENT_PROFILE_MATERIALIZATION_AXES, Wh as CanonicalAgentProfileMaterializationAxis, Xh as assertProfileMaterialization, Yh as ValidateProfileMaterializationOptions, Zh as controlProfileMaterialization, ag as renderProfileMaterializationIssues, cg as worktreeCliProfileMaterialization, eg as profileMaterializationAxes, ig as promptResourceProfileMaterialization, ng as promptModelProfileMaterialization, og as sandboxActProfileMaterialization, qh as ProfileMaterializationContract, rg as promptOnlyProfileMaterialization, sg as validateProfileMaterialization, tg as promptControlProfileMaterialization } from "./index-BSSGMvUd.js";
3
+ import { $h as fullProfileMaterialization, Gh as DefineProfileMaterializationContractOptions, Hh as AgentProfileMaterializationAxis, Jh as ProfileMaterializationIssue, Kh as KnownAgentProfileMaterializationAxis, Qh as defineProfileMaterializationContract, Uh as AssertProfileMaterializationOptions, Vh as AGENT_PROFILE_MATERIALIZATION_AXES, Wh as CanonicalAgentProfileMaterializationAxis, Xh as assertProfileMaterialization, Yh as ValidateProfileMaterializationOptions, Zh as controlProfileMaterialization, ag as renderProfileMaterializationIssues, cg as worktreeCliProfileMaterialization, eg as profileMaterializationAxes, ig as promptResourceProfileMaterialization, ng as promptModelProfileMaterialization, og as sandboxActProfileMaterialization, qh as ProfileMaterializationContract, rg as promptOnlyProfileMaterialization, sg as validateProfileMaterialization, tg as promptControlProfileMaterialization } from "./index-C4ygxavE.js";
4
4
  import { AgentProfile, AgentProfileFileMount, AgentProfileMcpServer } from "@tangle-network/agent-interface";
5
5
  import { TraceAnalystDefinition } from "@tangle-network/agent-eval";
6
6
  import { SandboxEvent } from "@tangle-network/sandbox";
package/dist/durable.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { J as RootStreamReceipt, j as NodeId, lt as SupervisedResult, y as ExecutorProgressEvent } from "./types-D56jQad-.js";
2
- import { $s as SupervisePursuitError, Cc as observerRecordDigest, Gs as PursuitVersionStop, Hs as NextPursuitVersion, Js as SettledPursuitVersion, Ks as PursuitVersions, Qs as pursuitVersionsLedgerPath, Sc as createFileObserverHooks, Us as NextPursuitVersionInput, Vs as JudgedPursuitVersion, Ws as PursuitVersionChain, Xs as VersionVerdict, Ys as VersionJudge, Zs as assertPursuitVersions, _c as projectPursuit, ac as RUN_FORK_CORRELATION_KEYS, bc as ObserverRecord, cc as PursuitNodePlacement, dc as PursuitNodeTiming, ec as SupervisePursuitOptions, fc as PursuitNodeUsage, gc as PursuitStatus, hc as PursuitRunTotals, ic as PursuitFork, lc as PursuitNodePlatform, mc as PursuitRunProjection, nc as supervisePursuit, oc as PursuitCostProvenance, pc as PursuitProjection, qs as REVIEW_DIR, rc as FORK_PARENT_UNCERTAIN_NODES_KEY, sc as PursuitNodeCost, tc as SupervisedPursuitResult, uc as PursuitNodeProjection, vc as FileObserverJournal, wc as verifyObserverRecords, xc as ObserverRecordKind, yc as ObserverJournal } from "./index-BSSGMvUd.js";
2
+ import { $s as SupervisePursuitError, Cc as observerRecordDigest, Gs as PursuitVersionStop, Hs as NextPursuitVersion, Js as SettledPursuitVersion, Ks as PursuitVersions, Qs as pursuitVersionsLedgerPath, Sc as createFileObserverHooks, Us as NextPursuitVersionInput, Vs as JudgedPursuitVersion, Ws as PursuitVersionChain, Xs as VersionVerdict, Ys as VersionJudge, Zs as assertPursuitVersions, _c as projectPursuit, ac as RUN_FORK_CORRELATION_KEYS, bc as ObserverRecord, cc as PursuitNodePlacement, dc as PursuitNodeTiming, ec as SupervisePursuitOptions, fc as PursuitNodeUsage, gc as PursuitStatus, hc as PursuitRunTotals, ic as PursuitFork, lc as PursuitNodePlatform, mc as PursuitRunProjection, nc as supervisePursuit, oc as PursuitCostProvenance, pc as PursuitProjection, qs as REVIEW_DIR, rc as FORK_PARENT_UNCERTAIN_NODES_KEY, sc as PursuitNodeCost, tc as SupervisedPursuitResult, uc as PursuitNodeProjection, vc as FileObserverJournal, wc as verifyObserverRecords, xc as ObserverRecordKind, yc as ObserverJournal } from "./index-C4ygxavE.js";
3
3
  //#region src/runtime/supervise/root-stream.d.ts
4
4
  /** The root stream: one JSONL line per progress event the root's executor observed. */
5
5
  declare const ROOT_STREAM_FILE = "root-stream.jsonl";
package/dist/durable.js CHANGED
@@ -930,6 +930,10 @@ async function readSettleRecord(runDir) {
930
930
  if (isNoEntError(error)) return void 0;
931
931
  throw error;
932
932
  }
933
+ return parseSettleRecord(text, path);
934
+ }
935
+ /** Parse settle-record bytes already read, so a caller hashes and parses the same bytes. */
936
+ function parseSettleRecord(text, path) {
933
937
  let parsed;
934
938
  try {
935
939
  parsed = JSON.parse(text);
@@ -1022,7 +1026,7 @@ const VERSION_CHAIN_DEFINITION = {
1022
1026
  node: "the exact AgentProfile a version executes, content-addressed by canonicalAgentProfileDigest; a change that does not apply is a node addressed by its parent digest and change, and refused",
1023
1027
  edge: "one change from the kept version, stored as its Interface profile diff",
1024
1028
  cell: "one supervisePursuit run of the version on the pursuit task, forked from its parent sealed result.json, then scored by the outside judge; a settled version directory is read back after its root identity and fork seal are checked",
1025
- outcome: "a scored winner passes; a scored no-winner fails with its reason; an unscored version is a retryable error; a run that throws fails the call and leaves its cell open",
1029
+ outcome: "a scored winner passes; a scored no-winner fails with its reason; an unscored version is a final error; a run that throws fails the call and leaves its cell open",
1026
1030
  deadline: "the chain deadline aborts a running version; its judge still runs",
1027
1031
  directories: "version n runs at <runDir>.v<n> with run id <runId>.v<n>; version 1 at <runDir>"
1028
1032
  };
@@ -1032,6 +1036,9 @@ const TASK_ID = "pursuit";
1032
1036
  const LANE = "in-process";
1033
1037
  /** The longest delay Node's setTimeout honors. */
1034
1038
  const MAX_TIMER_MS = 2147483647;
1039
+ /** 9999-12-31T23:59:59.999Z: the latest instant the ledger's four-digit-year timestamps hold, so
1040
+ * a deadline such as `Number.MAX_SAFE_INTEGER` means no deadline rather than an invalid date. */
1041
+ const LATEST_DEADLINE_MS = 0xe677d21fdbff;
1035
1042
  /** Run a version chain. `supervisePursuit` calls this when `versions` is set. */
1036
1043
  async function runPursuitVersions(profile, task, opts, runOne) {
1037
1044
  const { versions, fork: firstFork, signal: callerSignal, ...base } = opts;
@@ -1054,7 +1061,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1054
1061
  const searchId = `versions:${pursuitId}:${runId}`;
1055
1062
  const retired = resolve(`${runDir}.versions`, "versions.jsonl");
1056
1063
  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`);
1057
- const firstProfile = firstFork === void 0 ? profile : applyExactAgentProfileDiff(profile, firstFork.change, "supervisePursuit versions");
1064
+ const firstProfile = jsonProfile(firstFork === void 0 ? profile : applyExactAgentProfileDiff(profile, firstFork.change, "supervisePursuit versions"));
1058
1065
  const taskRevision = digestOf(task, "task");
1059
1066
  const identity = (nodeProfile) => ({
1060
1067
  model: {
@@ -1075,7 +1082,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1075
1082
  path: ledgerPath,
1076
1083
  searchId
1077
1084
  });
1078
- const deadline = (await ledger.state()).header?.budget.deadline ?? new Date(now() - settledElapsed(await readSettleRecord(runDir)) + stop.deadlineMs).toISOString();
1085
+ const deadline = (await ledger.state()).header?.budget.deadline ?? new Date(Math.min(now() - settledElapsed(await readSettleRecord(runDir)) + stop.deadlineMs, LATEST_DEADLINE_MS)).toISOString();
1079
1086
  const policy = incumbent({
1080
1087
  patience: stop.patience,
1081
1088
  ...stop.minImprovement === void 0 ? {} : { minImprovement: stop.minImprovement }
@@ -1149,6 +1156,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1149
1156
  timer.unref?.();
1150
1157
  };
1151
1158
  arm();
1159
+ const sealed = /* @__PURE__ */ new Map();
1152
1160
  const codec = {
1153
1161
  node(store, node) {
1154
1162
  if (node.profile !== null) {
@@ -1201,11 +1209,16 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1201
1209
  }
1202
1210
  };
1203
1211
  const executor = {
1204
- lanes: () => [{
1212
+ lanes: () => [base.budget.maxUsd === void 0 ? {
1205
1213
  name: LANE,
1206
1214
  capacity: 1,
1207
1215
  costCap: "estimate",
1208
- cellUsd: base.budget.maxUsd ?? 0
1216
+ cellUsd: 0
1217
+ } : {
1218
+ name: LANE,
1219
+ capacity: 1,
1220
+ costCap: "hard",
1221
+ cellUsd: base.budget.maxUsd
1209
1222
  }],
1210
1223
  place: () => LANE,
1211
1224
  adopt: async () => null,
@@ -1215,10 +1228,13 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1215
1228
  if (record?.profile == null) throw new RuntimeRunStateError(`version node ${work.nodeId} has no profile to run`);
1216
1229
  const parent = record.parentNodeId === null ? void 0 : chain.get(record.parentNodeId);
1217
1230
  if (parent !== void 0 && (parent.seal === void 0 || parent.profile === null)) throw new RuntimeRunStateError(`version ${record.version}'s parent has no sealed result`);
1218
- if (await readSettleRecord(record.runDir) === void 0) await runVersion(record, parent, AbortSignal.any([work.signal, expired.signal]));
1231
+ if (await readSettleRecord(record.runDir) === void 0) {
1232
+ const signal = AbortSignal.any([work.signal, expired.signal]);
1233
+ if (signal.aborted) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version} was not started: ${errorMessage$1(signal.reason)}`);
1234
+ await runVersion(record, parent, signal);
1235
+ }
1219
1236
  const { settled, byteLength } = await readVersion(record, parent);
1220
- const charged = !record.seals.has(settled.settleDigest);
1221
- return cellResult(settled, byteLength, await judgeVersion(settled, work.signal), work.lane, charged);
1237
+ return cellResult(settled, byteLength, await judgeVersion(settled, work.signal), work.lane);
1222
1238
  }
1223
1239
  };
1224
1240
  const proposerSource = {
@@ -1239,12 +1255,13 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1239
1255
  const judged = await judgedVersions(await versionsOf());
1240
1256
  const best = judged.find((version) => version.nodeId === parent.nodeId);
1241
1257
  if (best === void 0 || parent.artifact.profile === null) throw new RuntimeRunStateError(`supervisePursuit versions: the kept version ${parent.nodeId} has no judged run to fork from`);
1242
- const change = await next({
1258
+ const returned = await next({
1243
1259
  best,
1244
1260
  last: judged.at(-1),
1245
1261
  versions: Object.freeze(judged)
1246
1262
  }, request.signal);
1247
- if (typeof change?.id !== "string" || change.id.trim().length === 0) throw new ValidationError("supervisePursuit versions: next must return a change with an id");
1263
+ if (typeof returned?.id !== "string" || returned.id.trim().length === 0) throw new ValidationError("supervisePursuit versions: next must return a change with an id");
1264
+ const change = JSON.parse(JSON.stringify(returned));
1248
1265
  const parentDigest = canonicalAgentProfileDigest(parent.artifact.profile);
1249
1266
  let child;
1250
1267
  try {
@@ -1265,7 +1282,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1265
1282
  return {
1266
1283
  children: [{
1267
1284
  artifact: child,
1268
- label: change.title ?? change.id,
1285
+ label: change.title ?? returned.id,
1269
1286
  rationale: (change.source?.notes ?? []).join("\n")
1270
1287
  }],
1271
1288
  accounting: versions.next === "review-of-best" ? FREE : {
@@ -1368,6 +1385,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1368
1385
  const root = (await new FileSpawnJournal(resolve(record.runDir, "spawn-journal.jsonl")).loadTree(record.runId))?.find((event) => event.kind === "spawned" && event.parent === void 0);
1369
1386
  const ran = root?.identity?.profileDigest;
1370
1387
  const expected = authoredProfileDigest(superviseRootProfile(record.profile, base.profileGuidance));
1388
+ const ranTask = root?.identity?.taskDigest;
1371
1389
  const correlation = root?.identity?.correlation;
1372
1390
  const fork = parent !== void 0 ? {
1373
1391
  settleDigest: parent.seal?.sha256,
@@ -1378,12 +1396,16 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1378
1396
  };
1379
1397
  const mismatch = [
1380
1398
  ran !== expected ? `its root ran profile ${ran}, not ${expected}` : void 0,
1399
+ ranTask !== taskRevision ? `its root ran task ${ranTask}, not ${taskRevision}` : void 0,
1400
+ contentAddress(root?.budget) !== contentAddress(base.budget) ? "its root ran under another budget" : void 0,
1381
1401
  fork !== void 0 && correlation?.forkParentSettleDigest !== fork.settleDigest ? `its root forked from seal ${correlation?.forkParentSettleDigest}, not ${fork.settleDigest}` : void 0,
1382
1402
  fork !== void 0 && correlation?.forkProfileDiffId !== fork.changeId ? `its root applied change ${correlation?.forkProfileDiffId}, not ${fork.changeId}` : void 0
1383
1403
  ].filter((item) => item !== void 0);
1384
1404
  if (mismatch.length > 0) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version} at ${record.runDir} is not this chain's run: ${mismatch.join("; ")}`);
1405
+ const settled = versionOf(record, parent, sha256Bytes(bytes), result);
1406
+ sealed.set(settled.settleDigest, result);
1385
1407
  return {
1386
- settled: versionOf(record, parent, bytes, result),
1408
+ settled,
1387
1409
  byteLength: bytes.byteLength
1388
1410
  };
1389
1411
  }
@@ -1394,7 +1416,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1394
1416
  if (verdict.score !== null && !isFiniteNumber(verdict.score)) throw new ValidationError("supervisePursuit versions: a verdict score must be a finite number or null");
1395
1417
  return JSON.parse(JSON.stringify(verdict));
1396
1418
  }
1397
- function cellResult(settled, byteLength, verdict, lane, charged) {
1419
+ function cellResult(settled, byteLength, verdict, lane) {
1398
1420
  const spent = settled.result.spentTotal;
1399
1421
  const settlePath = resolve(settled.runDir, SETTLE_RECORD_FILE);
1400
1422
  return {
@@ -1404,7 +1426,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1404
1426
  error: {
1405
1427
  code: "unscored",
1406
1428
  message: `the judge could not score version ${settled.version}`,
1407
- retryable: true
1429
+ retryable: false
1408
1430
  }
1409
1431
  } : settled.result.kind === "winner" ? {
1410
1432
  status: "passed",
@@ -1419,10 +1441,10 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1419
1441
  message: `version ${settled.version} settled without a winner: ${settled.result.reason}`
1420
1442
  }
1421
1443
  },
1422
- accounting: charged ? versionAccounting(spent) : FREE,
1444
+ accounting: versionAccounting(spent),
1423
1445
  identity: identity(settled.profile),
1424
- boxMinutes: charged && isFiniteNumber(spent.boxMinutes) && spent.boxMinutesKnown !== false ? spent.boxMinutes : null,
1425
- wallMs: charged && isFiniteNumber(spent.ms) ? Math.max(0, Math.round(spent.ms)) : null,
1446
+ boxMinutes: isFiniteNumber(spent.boxMinutes) && spent.boxMinutesKnown !== false ? spent.boxMinutes : null,
1447
+ wallMs: isFiniteNumber(spent.ms) ? Math.max(0, Math.round(spent.ms)) : null,
1426
1448
  placement: {
1427
1449
  lane,
1428
1450
  boxId: null
@@ -1442,13 +1464,13 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1442
1464
  };
1443
1465
  }
1444
1466
  /** A version as the judge and `next` read it. */
1445
- function versionOf(record, parent, bytes, result) {
1467
+ function versionOf(record, parent, settleDigest, result) {
1446
1468
  return Object.freeze({
1447
1469
  version: record.version,
1448
1470
  nodeId: record.nodeId,
1449
1471
  runId: record.runId,
1450
1472
  runDir: record.runDir,
1451
- settleDigest: sha256Bytes(bytes),
1473
+ settleDigest,
1452
1474
  result,
1453
1475
  profile: record.profile,
1454
1476
  ...parent?.seal === void 0 ? {} : { parent: {
@@ -1465,11 +1487,17 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1465
1487
  const judged = [];
1466
1488
  for (const record of chain.values()) {
1467
1489
  if (record.seal === void 0 || record.verdict === void 0) continue;
1468
- const { bytes, result } = await readSealed(record.runDir, record.version);
1469
- if (sha256Bytes(bytes) !== record.seal.sha256) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version}'s result.json changed after it was judged`);
1490
+ const seal = record.seal.sha256;
1491
+ let result = sealed.get(seal);
1492
+ if (result === void 0) {
1493
+ const read = await readSealed(record.runDir, record.version);
1494
+ if (sha256Bytes(read.bytes) !== seal) throw new RuntimeRunStateError(`supervisePursuit versions: version ${record.version}'s result.json changed after it was judged`);
1495
+ result = read.result;
1496
+ sealed.set(seal, result);
1497
+ }
1470
1498
  const parent = record.parentNodeId === null ? void 0 : chain.get(record.parentNodeId);
1471
1499
  judged.push(Object.freeze({
1472
- ...versionOf(record, parent, bytes, result),
1500
+ ...versionOf(record, parent, seal, result),
1473
1501
  verdict: record.verdict
1474
1502
  }));
1475
1503
  }
@@ -1488,7 +1516,7 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1488
1516
  cellId: state.cells({ nodeId: node.nodeId })[0]?.cellId,
1489
1517
  diff: node.edgeIds[0] === void 0 ? void 0 : state.edge(node.edgeIds[0])?.diffs[0]
1490
1518
  }));
1491
- const attempts = /* @__PURE__ */ new Map();
1519
+ const settledCells = /* @__PURE__ */ new Map();
1492
1520
  const text = await readFile(ledgerPath, "utf8");
1493
1521
  for (const [index, line] of text.split("\n").entries()) {
1494
1522
  if (line.length === 0) continue;
@@ -1497,20 +1525,12 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1497
1525
  line: index + 1
1498
1526
  });
1499
1527
  if (entry.sequence > head) break;
1500
- const { event } = entry;
1501
- if (event.kind !== "cell-settled") continue;
1502
- const seals = attempts.get(event.cellId)?.seals ?? /* @__PURE__ */ new Set();
1503
- const seal = event.artifacts.find((artifact) => artifact.role === "settle-record");
1504
- if (seal !== void 0) seals.add(seal.sha256);
1505
- attempts.set(event.cellId, {
1506
- latest: event,
1507
- seals
1508
- });
1528
+ if (entry.event.kind === "cell-settled") settledCells.set(entry.event.cellId, entry.event);
1509
1529
  }
1510
1530
  const chain = /* @__PURE__ */ new Map();
1511
1531
  for (const { node, cellId, diff } of nodes) {
1512
- const settled = cellId === void 0 ? void 0 : attempts.get(cellId);
1513
- const artifact = (role) => settled?.latest.artifacts.find((candidate) => candidate.role === role);
1532
+ const settled = cellId === void 0 ? void 0 : settledCells.get(cellId);
1533
+ const artifact = (role) => settled?.artifacts.find((candidate) => candidate.role === role);
1514
1534
  const seal = artifact("settle-record");
1515
1535
  const verdict = artifact("verdict");
1516
1536
  chain.set(node.nodeId, {
@@ -1521,28 +1541,33 @@ async function runPursuitVersions(profile, task, opts, runOne) {
1521
1541
  parentNodeId: node.primaryParentId,
1522
1542
  ...diff === void 0 || "unknown" in diff ? {} : { change: recorder.readBlob(diff).diffs[0] },
1523
1543
  ...seal === void 0 ? {} : { seal },
1524
- ...verdict === void 0 ? {} : { verdict: recorder.readBlob(verdict).verdict },
1525
- seals: settled?.seals ?? /* @__PURE__ */ new Set()
1544
+ ...verdict === void 0 ? {} : { verdict: recorder.readBlob(verdict).verdict }
1526
1545
  });
1527
1546
  }
1528
1547
  return chain;
1529
1548
  }
1530
1549
  }
1531
- /** The bytes of a version's sealed `result.json` and the record they hold. */
1550
+ /** The bytes of a version's sealed `result.json` and the record they hold, parsed from the same
1551
+ * bytes that are hashed. */
1532
1552
  async function readSealed(runDir, version) {
1553
+ const path = resolve(runDir, SETTLE_RECORD_FILE);
1533
1554
  let bytes;
1534
1555
  try {
1535
- bytes = await readFile(resolve(runDir, SETTLE_RECORD_FILE));
1556
+ bytes = await readFile(path);
1536
1557
  } catch (error) {
1537
1558
  if (!isNoEntError(error)) throw error;
1538
1559
  throw new RuntimeRunStateError(`supervisePursuit versions: version ${version} has no settle record in ${runDir}`);
1539
1560
  }
1540
- const result = await readSettleRecord(runDir);
1541
1561
  return {
1542
1562
  bytes,
1543
- result
1563
+ result: parseSettleRecord(Buffer.from(bytes).toString("utf8"), path)
1544
1564
  };
1545
1565
  }
1566
+ /** A profile as the JSON the ledger stores: validated, with undefined entries absent. */
1567
+ function jsonProfile(profile) {
1568
+ canonicalAgentProfileDigest(profile);
1569
+ return JSON.parse(JSON.stringify(agentProfileSchema.parse(profile)));
1570
+ }
1546
1571
  function loadNode(store, node) {
1547
1572
  const stored = store.readBlob(node.artifact);
1548
1573
  if (stored.kind === "agent-profile") {
@@ -1574,17 +1599,17 @@ function versionRun(runDir, runId, version) {
1574
1599
  /** A version's settled spend as the ledger's accounting. Unknown dollars carry the part a
1575
1600
  * provider is known to have billed as their floor. */
1576
1601
  function versionAccounting(spent) {
1577
- const tokensKnown = spent !== void 0 && spent.tokensKnown !== false && Number.isSafeInteger(spent.tokens?.input) && Number.isSafeInteger(spent.tokens?.output);
1602
+ const tokensKnown = spent !== void 0 && spent.tokensKnown !== false && spent.tokens?.tokensKnown !== false && Number.isSafeInteger(spent.tokens?.input) && Number.isSafeInteger(spent.tokens?.output) && Number.isSafeInteger(spent.tokens?.cacheRead);
1578
1603
  const usdKnown = spent !== void 0 && spent.usdKnown !== false && isFiniteNumber(spent.usd);
1579
1604
  return {
1580
1605
  tokens: tokensKnown ? {
1581
1606
  status: "known",
1582
1607
  inputTokens: spent.tokens.input,
1583
1608
  outputTokens: spent.tokens.output,
1584
- cachedTokens: spent.tokens.cacheRead ?? 0
1609
+ cachedTokens: spent.tokens.cacheRead
1585
1610
  } : {
1586
1611
  status: "unknown",
1587
- reason: "the version's settled spend names unreported tokens"
1612
+ reason: `the version's settled spend reports no complete token count with its cache split (input ${spent?.tokens?.input ?? "none"}, output ${spent?.tokens?.output ?? "none"})`
1588
1613
  },
1589
1614
  cost: usdKnown ? {
1590
1615
  status: "known",
@@ -1636,7 +1661,8 @@ function reviewOfBest(runId, words) {
1636
1661
  const path = `${REVIEW_DIR}version-${best.version}.md`;
1637
1662
  const instruction = words.replaceAll("{version}", String(best.version)).replaceAll("{path}", path).replaceAll("{score}", best.verdict.score === null ? "none" : String(best.verdict.score)).trim();
1638
1663
  const page = reviewPage(best.version, best.verdict.score, verdict);
1639
- const earlierInstructions = best.change?.set?.prompt?.instructions ?? [];
1664
+ const earlier = best.change?.set?.prompt?.instructions ?? [];
1665
+ const earlierInstructions = earlier.filter((text) => text !== instruction);
1640
1666
  const earlierMounts = (best.profile.resources?.files ?? []).map((file) => file.path).filter((mounted) => mounted.startsWith("inputs/review/") && mounted !== path);
1641
1667
  return {
1642
1668
  kind: "agent-profile-diff",
@@ -1647,7 +1673,7 @@ function reviewOfBest(runId, words) {
1647
1673
  notes: [`review-of-best: version ${best.version}`, `judge ${best.verdict.judgeDigest}`]
1648
1674
  },
1649
1675
  set: {
1650
- prompt: { instructions: [instruction] },
1676
+ ...earlier.includes(instruction) ? {} : { prompt: { instructions: [instruction] } },
1651
1677
  resources: { files: [{
1652
1678
  path,
1653
1679
  resource: {