@tangle-network/agent-runtime 0.280.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.
Files changed (57) hide show
  1. package/dist/{activation-y-60DXF4.d.ts → activation-BcTWDNOD.d.ts} +141 -18
  2. package/dist/{activation-C97Cq4Q_.js → activation-C1ZAyQrQ.js} +2 -2
  3. package/dist/{activation-C97Cq4Q_.js.map → activation-C1ZAyQrQ.js.map} +1 -1
  4. package/dist/agent.d.ts +1 -1
  5. package/dist/agent.js +2 -2
  6. package/dist/{coordination-driver-CraAV-22.js → coordination-driver-B-HOpGN4.js} +2 -2
  7. package/dist/{coordination-driver-CraAV-22.js.map → coordination-driver-B-HOpGN4.js.map} +1 -1
  8. package/dist/{delegate-W1Ws_Wp0.js → delegate-C1eIBN70.js} +2 -2
  9. package/dist/{delegate-W1Ws_Wp0.js.map → delegate-C1eIBN70.js.map} +1 -1
  10. package/dist/durable.d.ts +2 -2
  11. package/dist/durable.js +794 -499
  12. package/dist/durable.js.map +1 -1
  13. package/dist/{graph-DlL_X4HX.js → graph-KjJaTmbO.js} +4 -4
  14. package/dist/{graph-DlL_X4HX.js.map → graph-KjJaTmbO.js.map} +1 -1
  15. package/dist/{improvement-cycle-DXMU-2Y4.js → improvement-cycle-DCTCTmNl.js} +761 -41
  16. package/dist/improvement-cycle-DCTCTmNl.js.map +1 -0
  17. package/dist/{index-Dm8SHDGW.d.ts → index-C4ygxavE.d.ts} +98 -144
  18. package/dist/index.d.ts +4 -4
  19. package/dist/index.js +8 -8
  20. package/dist/intelligence.d.ts +1 -1
  21. package/dist/intelligence.js +3 -3
  22. package/dist/kernel.d.ts +1 -1
  23. package/dist/kernel.js +8 -8
  24. package/dist/{loop-runner-bin-D6khQtoC.d.ts → loop-runner-bin-B9dTzFL3.d.ts} +2 -2
  25. package/dist/{loop-runner-bin-CT_-jSSg.js → loop-runner-bin-Co2eBFbb.js} +3 -3
  26. package/dist/{loop-runner-bin-CT_-jSSg.js.map → loop-runner-bin-Co2eBFbb.js.map} +1 -1
  27. package/dist/loop-runner-bin.d.ts +1 -1
  28. package/dist/loop-runner-bin.js +1 -1
  29. package/dist/mcp/bin.js +3 -3
  30. package/dist/mcp/index.d.ts +1 -1
  31. package/dist/mcp/index.js +4 -4
  32. package/dist/platform.d.ts +34 -36
  33. package/dist/platform.js +122 -29
  34. package/dist/platform.js.map +1 -1
  35. package/dist/{provision-supervisor-BEmE95Mt.js → provision-supervisor-CkN8RRjv.js} +3 -3
  36. package/dist/{provision-supervisor-BEmE95Mt.js.map → provision-supervisor-CkN8RRjv.js.map} +1 -1
  37. package/dist/{runtime-Du7j-nDD.js → runtime-B_yRPBjj.js} +16 -966
  38. package/dist/runtime-B_yRPBjj.js.map +1 -0
  39. package/dist/{server-DZvGznAn.js → server-dOyG5Tw6.js} +3 -3
  40. package/dist/{server-DZvGznAn.js.map → server-dOyG5Tw6.js.map} +1 -1
  41. package/dist/{structural-rollout-Cl4TvomY.js → shared-box-CZFdugL1.js} +959 -9
  42. package/dist/shared-box-CZFdugL1.js.map +1 -0
  43. package/dist/{supervise-CWrLq2-F.js → supervise-zt91I62x.js} +3 -3
  44. package/dist/{supervise-CWrLq2-F.js.map → supervise-zt91I62x.js.map} +1 -1
  45. package/dist/{supervisor-BXXjVCbW.js → supervisor-UXgaPisu.js} +5 -15
  46. package/dist/{supervisor-BXXjVCbW.js.map → supervisor-UXgaPisu.js.map} +1 -1
  47. package/dist/testing.d.ts +1 -1
  48. package/dist/testing.js +12 -12
  49. package/dist/tui/index.d.ts +1 -1
  50. package/dist/tui/index.js +1 -1
  51. package/package.json +4 -4
  52. package/skills/profile-authoring/SKILL.md +210 -0
  53. package/skills/supervise/SKILL.md +2 -2
  54. package/dist/improvement-cycle-DXMU-2Y4.js.map +0 -1
  55. package/dist/runtime-Du7j-nDD.js.map +0 -1
  56. package/dist/structural-rollout-Cl4TvomY.js.map +0 -1
  57. package/skills/supervise/references/profile-authoring.md +0 -19
package/dist/durable.js CHANGED
@@ -1,16 +1,18 @@
1
- import { $i as detachedSnapshot, Ai as readCommittedJsonLines, Di as isNoEntError, E as failedItems, Kt as loadSpawnForest, Oa as zeroSpend, Oi as parseCommittedJsonLines, Or as contentAddress, Pi as authoredProfileDigest, ga as cloneSpend, ji as writeAllBytes, ki as prepareJsonlAppend, ma as addSpend, zt as FileSpawnJournal } from "./supervisor-BXXjVCbW.js";
1
+ import { $i as detachedSnapshot, Ai as readCommittedJsonLines, Bt as FileSpawnJournal, E as failedItems, Oa as zeroSpend, Oi as isNoEntError, Pi as authoredProfileDigest, ga as cloneSpend, ji as writeAllBytes, ki as prepareJsonlAppend, kr as contentAddress, ma as addSpend, qt as loadSpawnForest } from "./supervisor-UXgaPisu.js";
2
2
  import { f as RuntimeRunStateError, m as ValidationError } from "./errors-DodWX-cb.js";
3
3
  import { a as withPursuitContext, t as composeRuntimeHooks } from "./runtime-hooks-tXpAarhW.js";
4
4
  import { a as writeAtomicDurableFile, r as publishExclusiveDurableFile } from "./durable-file-DWQA4ooo.js";
5
5
  import { i as applyExactAgentProfileDiff } from "./profile-D3eXNBQV.js";
6
- import { _ as readRootStream, g as ROOT_STREAM_FILE, i as superviseRootProfile, r as supervise, v as readRootStreamReceipt } from "./supervise-CWrLq2-F.js";
6
+ import { _ as readRootStream, g as ROOT_STREAM_FILE, i as superviseRootProfile, r as supervise, v as readRootStreamReceipt } from "./supervise-zt91I62x.js";
7
7
  import { h as supervisorRunDir } from "./run-layout-vwd4SwX_.js";
8
- import { canonicalCandidateDigest, canonicalCandidateJson, sha256Bytes } from "@tangle-network/agent-interface";
8
+ import { agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, canonicalCandidateJson, sha256Bytes } from "@tangle-network/agent-interface";
9
9
  import { createHash } from "node:crypto";
10
10
  import { execFile } from "node:child_process";
11
11
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
12
- import { mkdir, open, readFile, realpath, rmdir, unlink } from "node:fs/promises";
12
+ import { access, mkdir, readFile, realpath, rmdir, unlink } from "node:fs/promises";
13
13
  import { promisify } from "node:util";
14
+ import { SearchRecorder, developmentClaim, incumbent, openSearchLedger, parseSearchLedgerLine, runSearch, uniform } from "@tangle-network/agent-eval/campaign";
15
+ import { pathToFileURL } from "node:url";
14
16
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
15
17
  //#region src/durable/chat-engine.ts
16
18
  const encoder = new TextEncoder();
@@ -928,6 +930,10 @@ async function readSettleRecord(runDir) {
928
930
  if (isNoEntError(error)) return void 0;
929
931
  throw error;
930
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) {
931
937
  let parsed;
932
938
  try {
933
939
  parsed = JSON.parse(text);
@@ -959,6 +965,789 @@ async function readFailureRecord(runDir) {
959
965
  return parsed;
960
966
  }
961
967
  //#endregion
968
+ //#region src/durable/pursuit-versions.ts
969
+ /**
970
+ * The pursuit version chain, on Eval's search kernel (`runSearch`).
971
+ *
972
+ * A version is a search node: the exact AgentProfile it executes, content-addressed by
973
+ * `canonicalAgentProfileDigest`. Every later version is an edge from the version the chain keeps,
974
+ * whose diff is the one change `next` returned, and one cell: a `supervisePursuit` run of the
975
+ * version, forked from its parent's sealed `result.json`, then scored by the outside judge. The
976
+ * policy is the kernel's hill climb, `incumbent({ patience, minImprovement })`. The search ledger
977
+ * at `<runDir>.search/ledger.jsonl` is the chain's only record and its only checkpoint: a call on
978
+ * a closed chain reads it back, and a call on an open chain continues it.
979
+ */
980
+ /** Where `'review-of-best'` mounts a review: `inputs/review/version-<n>.md`. One review lives in
981
+ * a profile at a time. */
982
+ const REVIEW_DIR = "inputs/review/";
983
+ /** The chain's directory beside the first version's: the ledger and its content blobs. */
984
+ function pursuitVersionsLedgerPath(runDir) {
985
+ return resolve(`${resolve(runDir.trim())}.search`, "ledger.jsonl");
986
+ }
987
+ /**
988
+ * Validate a `versions` option before any compute. The same check runs inside `supervisePursuit`;
989
+ * a caller that records the option as data can run it at preflight.
990
+ */
991
+ function assertPursuitVersions(versions) {
992
+ const fail = (message) => {
993
+ throw new ValidationError(`supervisePursuit versions: ${message}`);
994
+ };
995
+ if (typeof versions !== "object" || versions === null) fail("must be an object");
996
+ const option = versions;
997
+ const extra = Object.keys(option).filter((key) => ![
998
+ "judge",
999
+ "next",
1000
+ "stop"
1001
+ ].includes(key));
1002
+ if (extra.length > 0) fail(`unknown fields: ${extra.join(", ")}`);
1003
+ const { judge, next, stop } = option;
1004
+ if (typeof judge !== "object" || judge === null || typeof judge.judge !== "function") fail("judge must be a VersionJudge, such as declaredCheckJudge(check)");
1005
+ else if (!isSha256(judge.digest)) fail("judge.digest must be a sha256 digest (sha256:<64 hex>)");
1006
+ if (next !== "review-of-best" && typeof next !== "function") fail("next must be a function or 'review-of-best'");
1007
+ if (typeof stop !== "object" || stop === null) fail("stop must be an object");
1008
+ const rule = stop;
1009
+ const known = /* @__PURE__ */ new Set([
1010
+ "patience",
1011
+ "maxVersions",
1012
+ "maxUsd",
1013
+ "deadlineMs",
1014
+ "minImprovement"
1015
+ ]);
1016
+ const unknown = Object.keys(rule).filter((key) => !known.has(key));
1017
+ if (unknown.length > 0) fail(`stop has unknown fields: ${unknown.join(", ")}`);
1018
+ for (const key of ["patience", "maxVersions"]) if (!Number.isInteger(rule[key]) || rule[key] < 1) fail(`stop.${key} must be an integer of at least 1`);
1019
+ for (const key of ["maxUsd", "deadlineMs"]) if (!isFiniteNumber(rule[key]) || rule[key] <= 0) fail(`stop.${key} must be a finite number above 0`);
1020
+ if (rule.minImprovement !== void 0 && (!isFiniteNumber(rule.minImprovement) || rule.minImprovement < 0)) fail("stop.minImprovement must be a finite number of at least 0");
1021
+ }
1022
+ /** Every rule the chain adds to the kernel's. Its digest, with the stop rule, is the process
1023
+ * revision the ledger records, so a changed rule or stop rule is a different search. */
1024
+ const VERSION_CHAIN_DEFINITION = {
1025
+ name: "agent-runtime.pursuit-versions.2026-09",
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",
1027
+ edge: "one change from the kept version, stored as its Interface profile diff",
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",
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",
1030
+ deadline: "the chain deadline aborts a running version; its judge still runs",
1031
+ directories: "version n runs at <runDir>.v<n> with run id <runId>.v<n>; version 1 at <runDir>"
1032
+ };
1033
+ const VERSION_CHAIN_URI = "npm:@tangle-network/agent-runtime#supervisePursuit.versions";
1034
+ /** The pursuit task's one train task. */
1035
+ const TASK_ID = "pursuit";
1036
+ const LANE = "in-process";
1037
+ /** The longest delay Node's setTimeout honors. */
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;
1042
+ /** Run a version chain. `supervisePursuit` calls this when `versions` is set. */
1043
+ async function runPursuitVersions(profile, task, opts, runOne) {
1044
+ const { versions, fork: firstFork, signal: callerSignal, ...base } = opts;
1045
+ assertPursuitVersions(versions);
1046
+ for (const key of [
1047
+ "journal",
1048
+ "blobs",
1049
+ "rootHandle",
1050
+ "steerDir"
1051
+ ]) if (base[key] !== void 0) throw new ValidationError(`supervisePursuit versions: ${key} names one run, and a version chain has one per version; omit it`);
1052
+ 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");
1053
+ const { judge, stop } = versions;
1054
+ 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`);
1055
+ const next = versions.next === "review-of-best" ? reviewOfBest(base.runId ?? "supervise", base.continuation?.profile.review ?? "") : versions.next;
1056
+ const now = base.now ?? Date.now;
1057
+ const pursuitId = base.pursuitId.trim();
1058
+ const runDir = resolve(base.runDir.trim());
1059
+ const runId = base.runId ?? "supervise";
1060
+ const ledgerPath = pursuitVersionsLedgerPath(runDir);
1061
+ const searchId = `versions:${pursuitId}:${runId}`;
1062
+ const retired = resolve(`${runDir}.versions`, "versions.jsonl");
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`);
1064
+ const firstProfile = jsonProfile(firstFork === void 0 ? profile : applyExactAgentProfileDiff(profile, firstFork.change, "supervisePursuit versions"));
1065
+ const taskRevision = digestOf(task, "task");
1066
+ const identity = (nodeProfile) => ({
1067
+ model: {
1068
+ provider: "agent-runtime",
1069
+ alias: "supervisePursuit",
1070
+ unknown: "a version runs every model its tree chose; the version's settle record names them"
1071
+ },
1072
+ agent: {
1073
+ uri: `agent-profile:${pursuitId}`,
1074
+ revision: canonicalAgentProfileDigest(nodeProfile)
1075
+ },
1076
+ benchmark: {
1077
+ uri: `pursuit:${pursuitId}`,
1078
+ revision: taskRevision
1079
+ }
1080
+ });
1081
+ const ledger = openSearchLedger({
1082
+ path: ledgerPath,
1083
+ searchId
1084
+ });
1085
+ const deadline = (await ledger.state()).header?.budget.deadline ?? new Date(Math.min(now() - settledElapsed(await readSettleRecord(runDir)) + stop.deadlineMs, LATEST_DEADLINE_MS)).toISOString();
1086
+ const policy = incumbent({
1087
+ patience: stop.patience,
1088
+ ...stop.minImprovement === void 0 ? {} : { minImprovement: stop.minImprovement }
1089
+ });
1090
+ const allocation = uniform();
1091
+ const recorder = await SearchRecorder.open({
1092
+ ledger,
1093
+ now
1094
+ }, {
1095
+ subject: pursuitId,
1096
+ process: {
1097
+ name: "pursuit-versions",
1098
+ executionRef: {
1099
+ uri: VERSION_CHAIN_URI,
1100
+ revision: canonicalCandidateDigest({
1101
+ ...VERSION_CHAIN_DEFINITION,
1102
+ stop: canonicalStop(stop)
1103
+ })
1104
+ }
1105
+ },
1106
+ artifactKind: "agent-profile",
1107
+ objective: {
1108
+ metric: "version-judge-score",
1109
+ direction: "maximize",
1110
+ judge: {
1111
+ uri: "agent-runtime:version-judge",
1112
+ revision: judge.digest
1113
+ },
1114
+ claim: developmentClaim(pursuitId)
1115
+ },
1116
+ splits: {
1117
+ train: [{
1118
+ taskId: TASK_ID,
1119
+ unitId: TASK_ID,
1120
+ source: {
1121
+ uri: `pursuit:${pursuitId}`,
1122
+ revision: taskRevision
1123
+ }
1124
+ }],
1125
+ selection: [],
1126
+ test: [],
1127
+ heldOutUnits: true
1128
+ },
1129
+ policy: {
1130
+ expansion: policy.name,
1131
+ allocation: allocation.name,
1132
+ seed: 0
1133
+ },
1134
+ budget: {
1135
+ maxUsd: stop.maxUsd,
1136
+ maxCells: null,
1137
+ maxNodes: stop.maxVersions,
1138
+ deadline,
1139
+ maxConcurrency: 1,
1140
+ reservedClaimUsd: 0
1141
+ },
1142
+ containment: null,
1143
+ derivedFrom: null,
1144
+ identity: identity(firstProfile)
1145
+ });
1146
+ const deadlineAt = Date.parse(deadline);
1147
+ const expired = new AbortController();
1148
+ let timer;
1149
+ const arm = () => {
1150
+ const remaining = deadlineAt - now();
1151
+ if (remaining <= 0) {
1152
+ expired.abort(/* @__PURE__ */ new Error("the version chain reached its deadline"));
1153
+ return;
1154
+ }
1155
+ timer = setTimeout(arm, Math.min(remaining, MAX_TIMER_MS));
1156
+ timer.unref?.();
1157
+ };
1158
+ arm();
1159
+ const sealed = /* @__PURE__ */ new Map();
1160
+ const codec = {
1161
+ node(store, node) {
1162
+ if (node.profile !== null) {
1163
+ const artifact = store.blob("agent-profile", {
1164
+ kind: "agent-profile",
1165
+ profile: node.profile
1166
+ });
1167
+ return {
1168
+ artifactDigest: canonicalAgentProfileDigest(node.profile),
1169
+ artifact,
1170
+ surfaces: [{
1171
+ surfaceId: "profile",
1172
+ kind: "agent-profile",
1173
+ artifact
1174
+ }]
1175
+ };
1176
+ }
1177
+ const refused = {
1178
+ kind: "unapplied-change",
1179
+ parentDigest: node.parentDigest ?? null,
1180
+ change: node.change ?? null
1181
+ };
1182
+ const artifact = store.blob("change", {
1183
+ ...refused,
1184
+ refusal: node.refusal
1185
+ });
1186
+ return {
1187
+ artifactDigest: canonicalCandidateDigest(refused),
1188
+ artifact,
1189
+ surfaces: [{
1190
+ surfaceId: "profile",
1191
+ kind: "agent-profile",
1192
+ artifact
1193
+ }]
1194
+ };
1195
+ },
1196
+ diff(store, parent, child) {
1197
+ if (parent.profile === null || child.profile === null || child.change === void 0) return { unknown: "a refused change has no profile to diff" };
1198
+ const from = canonicalAgentProfileDigest(parent.profile);
1199
+ if (child.parentDigest !== from) return { unknown: "the change was written against another parent" };
1200
+ return store.blob("diff", {
1201
+ kind: "agent-profile-diff",
1202
+ from,
1203
+ to: canonicalAgentProfileDigest(child.profile),
1204
+ diffs: [child.change]
1205
+ });
1206
+ },
1207
+ load(store, node) {
1208
+ return loadNode(store, node);
1209
+ }
1210
+ };
1211
+ const executor = {
1212
+ lanes: () => [base.budget.maxUsd === void 0 ? {
1213
+ name: LANE,
1214
+ capacity: 1,
1215
+ costCap: "estimate",
1216
+ cellUsd: 0
1217
+ } : {
1218
+ name: LANE,
1219
+ capacity: 1,
1220
+ costCap: "hard",
1221
+ cellUsd: base.budget.maxUsd
1222
+ }],
1223
+ place: () => LANE,
1224
+ adopt: async () => null,
1225
+ async run(work) {
1226
+ const chain = await versionsOf();
1227
+ const record = chain.get(work.nodeId);
1228
+ if (record?.profile == null) throw new RuntimeRunStateError(`version node ${work.nodeId} has no profile to run`);
1229
+ const parent = record.parentNodeId === null ? void 0 : chain.get(record.parentNodeId);
1230
+ if (parent !== void 0 && (parent.seal === void 0 || parent.profile === null)) throw new RuntimeRunStateError(`version ${record.version}'s parent has no sealed result`);
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
+ }
1236
+ const { settled, byteLength } = await readVersion(record, parent);
1237
+ return cellResult(settled, byteLength, await judgeVersion(settled, work.signal), work.lane);
1238
+ }
1239
+ };
1240
+ const proposerSource = {
1241
+ uri: versions.next === "review-of-best" ? `${VERSION_CHAIN_URI}.review-of-best` : `${VERSION_CHAIN_URI}.next`,
1242
+ revision: canonicalCandidateDigest({ next: versions.next === "review-of-best" ? "review-of-best" : Function.prototype.toString.call(versions.next) })
1243
+ };
1244
+ const proposer = {
1245
+ name: versions.next === "review-of-best" ? "review-of-best" : "next",
1246
+ kind: "optimizer",
1247
+ source: proposerSource,
1248
+ execution: {
1249
+ kind: "deterministic",
1250
+ source: proposerSource
1251
+ },
1252
+ childrenPerProposal: 1,
1253
+ async propose(request) {
1254
+ const parent = request.parents[0];
1255
+ const judged = await judgedVersions(await versionsOf());
1256
+ const best = judged.find((version) => version.nodeId === parent.nodeId);
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`);
1258
+ const returned = await next({
1259
+ best,
1260
+ last: judged.at(-1),
1261
+ versions: Object.freeze(judged)
1262
+ }, request.signal);
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));
1265
+ const parentDigest = canonicalAgentProfileDigest(parent.artifact.profile);
1266
+ let child;
1267
+ try {
1268
+ child = {
1269
+ profile: applyExactAgentProfileDiff(parent.artifact.profile, change, "supervisePursuit versions"),
1270
+ change,
1271
+ parentDigest,
1272
+ refusal: null
1273
+ };
1274
+ } catch (error) {
1275
+ child = {
1276
+ profile: null,
1277
+ change,
1278
+ parentDigest,
1279
+ refusal: errorMessage$1(error)
1280
+ };
1281
+ }
1282
+ return {
1283
+ children: [{
1284
+ artifact: child,
1285
+ label: change.title ?? returned.id,
1286
+ rationale: (change.source?.notes ?? []).join("\n")
1287
+ }],
1288
+ accounting: versions.next === "review-of-best" ? FREE : {
1289
+ tokens: {
1290
+ status: "unknown",
1291
+ reason: "the caller's next reports no usage"
1292
+ },
1293
+ cost: {
1294
+ status: "unknown",
1295
+ knownLowerBoundUsd: 0,
1296
+ reason: "the caller's next reports no spend"
1297
+ }
1298
+ }
1299
+ };
1300
+ }
1301
+ };
1302
+ try {
1303
+ const closed = await runSearch({
1304
+ recorder,
1305
+ root: {
1306
+ profile: firstProfile,
1307
+ refusal: null
1308
+ },
1309
+ codec,
1310
+ policy,
1311
+ allocation,
1312
+ proposer,
1313
+ executor,
1314
+ admit: (node) => node.refusal,
1315
+ ...callerSignal === void 0 ? {} : { signal: callerSignal },
1316
+ now
1317
+ });
1318
+ const judged = await judgedVersions(await versionsOf());
1319
+ const best = judged.find((version) => version.nodeId === closed.leader);
1320
+ if (best === void 0) throw new RuntimeRunStateError(`supervisePursuit versions: the chain in ${ledgerPath} closed (${closed.reason}) without a judged version to keep`);
1321
+ const observerPath = resolve(best.runDir, "observer.jsonl");
1322
+ return Object.freeze({
1323
+ result: best.result,
1324
+ pursuit: projectPursuit(await new FileObserverJournal(observerPath, pursuitId).read()),
1325
+ observerPath,
1326
+ settlePath: resolve(best.runDir, SETTLE_RECORD_FILE),
1327
+ versions: Object.freeze({
1328
+ ledgerPath,
1329
+ searchId,
1330
+ reason: closed.reason,
1331
+ best: best.version,
1332
+ versions: Object.freeze(judged),
1333
+ spend: closed.state.audit.spend,
1334
+ receipt: recorder.receipt({
1335
+ producerId: "pursuit-versions",
1336
+ runId
1337
+ })
1338
+ })
1339
+ });
1340
+ } finally {
1341
+ if (timer !== void 0) clearTimeout(timer);
1342
+ }
1343
+ /** Run one version: the first as the call's own run, a later one as a fork of its parent. */
1344
+ async function runVersion(record, parent, signal) {
1345
+ if (parent === void 0 || record.change === void 0) {
1346
+ await runOne(profile, task, {
1347
+ ...base,
1348
+ runId: record.runId,
1349
+ runDir: record.runDir,
1350
+ ...firstFork === void 0 ? {} : { fork: firstFork },
1351
+ signal
1352
+ });
1353
+ return;
1354
+ }
1355
+ const fork = {
1356
+ runDir: parent.runDir,
1357
+ settleDigest: parent.seal.sha256,
1358
+ change: record.change,
1359
+ acceptUncertain: true
1360
+ };
1361
+ const check = parent.verdict?.check;
1362
+ await runOne(parent.profile, task, {
1363
+ ...base,
1364
+ ...base.continuation !== void 0 && check !== void 0 ? { continuation: {
1365
+ ...base.continuation,
1366
+ best: {
1367
+ label: `v${parent.version}`,
1368
+ verdict: check
1369
+ }
1370
+ } } : {},
1371
+ runId: record.runId,
1372
+ runDir: record.runDir,
1373
+ fork,
1374
+ signal
1375
+ });
1376
+ }
1377
+ /**
1378
+ * Read a settled version back and check it is this node's run: its root ran the node's profile
1379
+ * and, for a fork, recorded the parent's seal and the change. A directory that holds another
1380
+ * run is refused, never adopted.
1381
+ */
1382
+ async function readVersion(record, parent) {
1383
+ const { bytes, result } = await readSealed(record.runDir, record.version);
1384
+ 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}'`);
1385
+ const root = (await new FileSpawnJournal(resolve(record.runDir, "spawn-journal.jsonl")).loadTree(record.runId))?.find((event) => event.kind === "spawned" && event.parent === void 0);
1386
+ const ran = root?.identity?.profileDigest;
1387
+ const expected = authoredProfileDigest(superviseRootProfile(record.profile, base.profileGuidance));
1388
+ const ranTask = root?.identity?.taskDigest;
1389
+ const correlation = root?.identity?.correlation;
1390
+ const fork = parent !== void 0 ? {
1391
+ settleDigest: parent.seal?.sha256,
1392
+ changeId: record.change?.id
1393
+ } : firstFork === void 0 ? void 0 : {
1394
+ settleDigest: firstFork.settleDigest,
1395
+ changeId: firstFork.change.id
1396
+ };
1397
+ const mismatch = [
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,
1401
+ fork !== void 0 && correlation?.forkParentSettleDigest !== fork.settleDigest ? `its root forked from seal ${correlation?.forkParentSettleDigest}, not ${fork.settleDigest}` : void 0,
1402
+ fork !== void 0 && correlation?.forkProfileDiffId !== fork.changeId ? `its root applied change ${correlation?.forkProfileDiffId}, not ${fork.changeId}` : void 0
1403
+ ].filter((item) => item !== void 0);
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);
1407
+ return {
1408
+ settled,
1409
+ byteLength: bytes.byteLength
1410
+ };
1411
+ }
1412
+ async function judgeVersion(settled, signal) {
1413
+ const verdict = await judge.judge(settled, signal);
1414
+ if (typeof verdict !== "object" || verdict === null) throw new ValidationError("supervisePursuit versions: the judge returned no verdict");
1415
+ 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}`);
1416
+ if (verdict.score !== null && !isFiniteNumber(verdict.score)) throw new ValidationError("supervisePursuit versions: a verdict score must be a finite number or null");
1417
+ return JSON.parse(JSON.stringify(verdict));
1418
+ }
1419
+ function cellResult(settled, byteLength, verdict, lane) {
1420
+ const spent = settled.result.spentTotal;
1421
+ const settlePath = resolve(settled.runDir, SETTLE_RECORD_FILE);
1422
+ return {
1423
+ outcome: verdict.score === null ? {
1424
+ status: "errored",
1425
+ metrics: {},
1426
+ error: {
1427
+ code: "unscored",
1428
+ message: `the judge could not score version ${settled.version}`,
1429
+ retryable: false
1430
+ }
1431
+ } : settled.result.kind === "winner" ? {
1432
+ status: "passed",
1433
+ score: verdict.score,
1434
+ metrics: {}
1435
+ } : {
1436
+ status: "failed",
1437
+ score: verdict.score,
1438
+ metrics: {},
1439
+ failure: {
1440
+ code: settled.result.reason,
1441
+ message: `version ${settled.version} settled without a winner: ${settled.result.reason}`
1442
+ }
1443
+ },
1444
+ accounting: versionAccounting(spent),
1445
+ identity: identity(settled.profile),
1446
+ boxMinutes: isFiniteNumber(spent.boxMinutes) && spent.boxMinutesKnown !== false ? spent.boxMinutes : null,
1447
+ wallMs: isFiniteNumber(spent.ms) ? Math.max(0, Math.round(spent.ms)) : null,
1448
+ placement: {
1449
+ lane,
1450
+ boxId: null
1451
+ },
1452
+ traceRef: { unknown: `version ${settled.version} is run ${settled.runId}; the chain records no trace id` },
1453
+ artifacts: [{
1454
+ role: "settle-record",
1455
+ uri: pathToFileURL(settlePath).href,
1456
+ sha256: settled.settleDigest,
1457
+ byteLength
1458
+ }, recorder.blob("verdict", {
1459
+ kind: "version-verdict",
1460
+ version: settled.version,
1461
+ runId: settled.runId,
1462
+ verdict
1463
+ })]
1464
+ };
1465
+ }
1466
+ /** A version as the judge and `next` read it. */
1467
+ function versionOf(record, parent, settleDigest, result) {
1468
+ return Object.freeze({
1469
+ version: record.version,
1470
+ nodeId: record.nodeId,
1471
+ runId: record.runId,
1472
+ runDir: record.runDir,
1473
+ settleDigest,
1474
+ result,
1475
+ profile: record.profile,
1476
+ ...parent?.seal === void 0 ? {} : { parent: {
1477
+ version: parent.version,
1478
+ runId: parent.runId,
1479
+ settleDigest: parent.seal.sha256
1480
+ } },
1481
+ ...record.change === void 0 ? {} : { change: record.change }
1482
+ });
1483
+ }
1484
+ /** Every version whose latest settled cell carries a verdict, first first, each read back from
1485
+ * its sealed `result.json`. */
1486
+ async function judgedVersions(chain) {
1487
+ const judged = [];
1488
+ for (const record of chain.values()) {
1489
+ if (record.seal === void 0 || record.verdict === void 0) continue;
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
+ }
1498
+ const parent = record.parentNodeId === null ? void 0 : chain.get(record.parentNodeId);
1499
+ judged.push(Object.freeze({
1500
+ ...versionOf(record, parent, seal, result),
1501
+ verdict: record.verdict
1502
+ }));
1503
+ }
1504
+ return judged;
1505
+ }
1506
+ /**
1507
+ * Every node of the chain, in registration order, from the ledger. The state holds cells, not
1508
+ * their events' artifacts, so each cell's seal and verdict are read from the ledger lines the
1509
+ * state verified, through Eval's own line parser.
1510
+ */
1511
+ async function versionsOf() {
1512
+ const state = await recorder.state();
1513
+ const head = state.head?.sequence ?? -1;
1514
+ const nodes = state.nodes().map((node) => ({
1515
+ node,
1516
+ cellId: state.cells({ nodeId: node.nodeId })[0]?.cellId,
1517
+ diff: node.edgeIds[0] === void 0 ? void 0 : state.edge(node.edgeIds[0])?.diffs[0]
1518
+ }));
1519
+ const settledCells = /* @__PURE__ */ new Map();
1520
+ const text = await readFile(ledgerPath, "utf8");
1521
+ for (const [index, line] of text.split("\n").entries()) {
1522
+ if (line.length === 0) continue;
1523
+ const entry = parseSearchLedgerLine(line, searchId, {
1524
+ path: ledgerPath,
1525
+ line: index + 1
1526
+ });
1527
+ if (entry.sequence > head) break;
1528
+ if (entry.event.kind === "cell-settled") settledCells.set(entry.event.cellId, entry.event);
1529
+ }
1530
+ const chain = /* @__PURE__ */ new Map();
1531
+ for (const { node, cellId, diff } of nodes) {
1532
+ const settled = cellId === void 0 ? void 0 : settledCells.get(cellId);
1533
+ const artifact = (role) => settled?.artifacts.find((candidate) => candidate.role === role);
1534
+ const seal = artifact("settle-record");
1535
+ const verdict = artifact("verdict");
1536
+ chain.set(node.nodeId, {
1537
+ nodeId: node.nodeId,
1538
+ version: node.ordinal + 1,
1539
+ ...versionRun(runDir, runId, node.ordinal + 1),
1540
+ profile: loadNode(recorder, node).profile,
1541
+ parentNodeId: node.primaryParentId,
1542
+ ...diff === void 0 || "unknown" in diff ? {} : { change: recorder.readBlob(diff).diffs[0] },
1543
+ ...seal === void 0 ? {} : { seal },
1544
+ ...verdict === void 0 ? {} : { verdict: recorder.readBlob(verdict).verdict }
1545
+ });
1546
+ }
1547
+ return chain;
1548
+ }
1549
+ }
1550
+ /** The bytes of a version's sealed `result.json` and the record they hold, parsed from the same
1551
+ * bytes that are hashed. */
1552
+ async function readSealed(runDir, version) {
1553
+ const path = resolve(runDir, SETTLE_RECORD_FILE);
1554
+ let bytes;
1555
+ try {
1556
+ bytes = await readFile(path);
1557
+ } catch (error) {
1558
+ if (!isNoEntError(error)) throw error;
1559
+ throw new RuntimeRunStateError(`supervisePursuit versions: version ${version} has no settle record in ${runDir}`);
1560
+ }
1561
+ return {
1562
+ bytes,
1563
+ result: parseSettleRecord(Buffer.from(bytes).toString("utf8"), path)
1564
+ };
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
+ }
1571
+ function loadNode(store, node) {
1572
+ const stored = store.readBlob(node.artifact);
1573
+ if (stored.kind === "agent-profile") {
1574
+ const parsed = agentProfileSchema.safeParse(stored.profile);
1575
+ if (!parsed.success) throw new RuntimeRunStateError(`version node ${node.nodeId} holds an invalid AgentProfile`);
1576
+ return {
1577
+ profile: parsed.data,
1578
+ refusal: null
1579
+ };
1580
+ }
1581
+ if (stored.kind === "unapplied-change") return {
1582
+ profile: null,
1583
+ ...stored.change ? { change: stored.change } : {},
1584
+ ...stored.parentDigest ? { parentDigest: stored.parentDigest } : {},
1585
+ refusal: stored.refusal ?? "the change did not apply"
1586
+ };
1587
+ throw new RuntimeRunStateError(`version node ${node.nodeId} holds no version artifact`);
1588
+ }
1589
+ /** The `<runDir>.v<n>` directory and `<runId>.v<n>` id of version `n`, beside the first. */
1590
+ function versionRun(runDir, runId, version) {
1591
+ return version === 1 ? {
1592
+ runDir,
1593
+ runId
1594
+ } : {
1595
+ runDir: `${runDir}.v${version}`,
1596
+ runId: `${runId}.v${version}`
1597
+ };
1598
+ }
1599
+ /** A version's settled spend as the ledger's accounting. Unknown dollars carry the part a
1600
+ * provider is known to have billed as their floor. */
1601
+ function versionAccounting(spent) {
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);
1603
+ const usdKnown = spent !== void 0 && spent.usdKnown !== false && isFiniteNumber(spent.usd);
1604
+ return {
1605
+ tokens: tokensKnown ? {
1606
+ status: "known",
1607
+ inputTokens: spent.tokens.input,
1608
+ outputTokens: spent.tokens.output,
1609
+ cachedTokens: spent.tokens.cacheRead
1610
+ } : {
1611
+ status: "unknown",
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"})`
1613
+ },
1614
+ cost: usdKnown ? {
1615
+ status: "known",
1616
+ usd: spent.usd,
1617
+ source: "provider"
1618
+ } : {
1619
+ status: "unknown",
1620
+ knownLowerBoundUsd: Math.max(0, isFiniteNumber(spent?.usd) ? spent.usd - (spent.usdEstimated ?? 0) : 0),
1621
+ reason: "the version's settled spend names unpriced or unreported work"
1622
+ }
1623
+ };
1624
+ }
1625
+ /** How long a version that settled before its chain opened ran, from its settle record. */
1626
+ function settledElapsed(settled) {
1627
+ const elapsed = settled?.spentTotal?.ms;
1628
+ return isFiniteNumber(elapsed) ? elapsed : 0;
1629
+ }
1630
+ const FREE = {
1631
+ tokens: {
1632
+ status: "known",
1633
+ inputTokens: 0,
1634
+ outputTokens: 0,
1635
+ cachedTokens: 0
1636
+ },
1637
+ cost: {
1638
+ status: "known",
1639
+ usd: 0,
1640
+ source: "free"
1641
+ }
1642
+ };
1643
+ function canonicalStop(stop) {
1644
+ return {
1645
+ patience: stop.patience,
1646
+ maxVersions: stop.maxVersions,
1647
+ maxUsd: stop.maxUsd,
1648
+ deadlineMs: stop.deadlineMs,
1649
+ ...stop.minImprovement === void 0 ? {} : { minImprovement: stop.minImprovement }
1650
+ };
1651
+ }
1652
+ /**
1653
+ * `'review-of-best'`: fork from the kept version with its check's verdict mounted under
1654
+ * {@link REVIEW_DIR} and the profile's review words as one instruction. The previous review's
1655
+ * mount and instruction are removed, so a profile carries one review.
1656
+ */
1657
+ function reviewOfBest(runId, words) {
1658
+ return ({ best, versions }) => {
1659
+ const n = versions.length + 1;
1660
+ const verdict = best.verdict.check;
1661
+ const path = `${REVIEW_DIR}version-${best.version}.md`;
1662
+ const instruction = words.replaceAll("{version}", String(best.version)).replaceAll("{path}", path).replaceAll("{score}", best.verdict.score === null ? "none" : String(best.verdict.score)).trim();
1663
+ const page = reviewPage(best.version, best.verdict.score, verdict);
1664
+ const earlier = best.change?.set?.prompt?.instructions ?? [];
1665
+ const earlierInstructions = earlier.filter((text) => text !== instruction);
1666
+ const earlierMounts = (best.profile.resources?.files ?? []).map((file) => file.path).filter((mounted) => mounted.startsWith("inputs/review/") && mounted !== path);
1667
+ return {
1668
+ kind: "agent-profile-diff",
1669
+ id: `${runId}-v${n}-review-of-v${best.version}`,
1670
+ title: `Version ${n}: review of version ${best.version}`,
1671
+ source: {
1672
+ kind: "optimizer",
1673
+ notes: [`review-of-best: version ${best.version}`, `judge ${best.verdict.judgeDigest}`]
1674
+ },
1675
+ set: {
1676
+ ...earlier.includes(instruction) ? {} : { prompt: { instructions: [instruction] } },
1677
+ resources: { files: [{
1678
+ path,
1679
+ resource: {
1680
+ kind: "inline",
1681
+ name: path,
1682
+ content: page
1683
+ }
1684
+ }] }
1685
+ },
1686
+ ...earlierInstructions.length > 0 || earlierMounts.length > 0 ? { remove: {
1687
+ ...earlierInstructions.length > 0 ? { prompt: { instructions: [...earlierInstructions] } } : {},
1688
+ ...earlierMounts.length > 0 ? { resources: { files: earlierMounts } } : {}
1689
+ } } : {}
1690
+ };
1691
+ };
1692
+ }
1693
+ /** The review page: facts only, in the check's own lines. */
1694
+ function reviewPage(version, score, verdict) {
1695
+ if (verdict === void 0) return [
1696
+ `# Version ${version}`,
1697
+ "",
1698
+ `Score: ${score ?? "none"}. The judge reported no per-item verdict.`,
1699
+ ""
1700
+ ].join("\n");
1701
+ const failing = failedItems(verdict);
1702
+ return [
1703
+ `# Version ${version}`,
1704
+ "",
1705
+ `Score: ${score ?? "none"}.${verdict.threshold === void 0 ? "" : ` The check passes at ${verdict.threshold}.`}`,
1706
+ "",
1707
+ "## Items",
1708
+ "",
1709
+ ...Object.entries(verdict.items ?? {}).map(([item, value]) => `- ${item}: ${value >= 1 ? "passes" : `fails (${value})`}`),
1710
+ "",
1711
+ ...failing.length === 0 ? [] : [
1712
+ "## Failures",
1713
+ "",
1714
+ ...verdict.failures ?? [],
1715
+ ""
1716
+ ],
1717
+ ...verdict.review === void 0 ? [] : [
1718
+ "## The check's review",
1719
+ "",
1720
+ verdict.review,
1721
+ ""
1722
+ ]
1723
+ ].join("\n");
1724
+ }
1725
+ function digestOf(value, name) {
1726
+ try {
1727
+ return canonicalCandidateDigest(value);
1728
+ } catch (error) {
1729
+ throw new ValidationError(`supervisePursuit versions: the ${name} must be canonical JSON to pin the chain: ${errorMessage$1(error)}`);
1730
+ }
1731
+ }
1732
+ async function exists(path) {
1733
+ try {
1734
+ await access(path);
1735
+ return true;
1736
+ } catch (error) {
1737
+ if (isNoEntError(error)) return false;
1738
+ throw error;
1739
+ }
1740
+ }
1741
+ function isSha256(value) {
1742
+ return typeof value === "string" && /^sha256:[0-9a-f]{64}$/u.test(value);
1743
+ }
1744
+ function isFiniteNumber(value) {
1745
+ return typeof value === "number" && Number.isFinite(value);
1746
+ }
1747
+ function errorMessage$1(error) {
1748
+ return error instanceof Error ? error.message : String(error);
1749
+ }
1750
+ //#endregion
962
1751
  //#region src/durable/run-fork.ts
963
1752
  /**
964
1753
  * The `execution.correlation` keys a fork records on its root. Runtime writes them; a caller that
@@ -1254,500 +2043,6 @@ async function removeIfPresent(path) {
1254
2043
  }
1255
2044
  }
1256
2045
  //#endregion
1257
- //#region src/durable/pursuit-versions.ts
1258
- /** The longest delay Node's setTimeout honors. */
1259
- const MAX_TIMER_MS = 2147483647;
1260
- /** The ledger file inside the lineage directory. */
1261
- const PURSUIT_VERSIONS_FILE = "versions.jsonl";
1262
- /** The `<runDir>.v<n>` directory and `<runId>.v<n>` id of version `n`, beside the first. */
1263
- function pursuitVersionRun(runDir, runId, version) {
1264
- return version === 1 ? {
1265
- runDir,
1266
- runId
1267
- } : {
1268
- runDir: `${runDir}.v${version}`,
1269
- runId: `${runId}.v${version}`
1270
- };
1271
- }
1272
- /**
1273
- * Validate a `versions` option before any compute. The same check runs inside `supervisePursuit`;
1274
- * a caller that records the option as data can run it at preflight.
1275
- */
1276
- function assertPursuitVersions(versions) {
1277
- const fail = (message) => {
1278
- throw new ValidationError(`supervisePursuit versions: ${message}`);
1279
- };
1280
- if (typeof versions !== "object" || versions === null) fail("must be an object");
1281
- const { judge, next, stop, run } = versions;
1282
- if (typeof judge !== "object" || judge === null || typeof judge.judge !== "function") fail("judge must be a VersionJudge, such as declaredCheckJudge(check)");
1283
- else if (!isSha256(judge.digest)) fail("judge.digest must be a sha256 digest (sha256:<64 hex>)");
1284
- if (next !== "review-of-best" && typeof next !== "function") fail("next must be a function or 'review-of-best'");
1285
- if (run !== void 0 && typeof run !== "function") fail("run must be a function when set");
1286
- const { usd } = versions;
1287
- if (usd !== void 0 && typeof usd !== "function") fail("usd must be a function when set");
1288
- if (typeof stop !== "object" || stop === null) fail("stop must be an object");
1289
- const rule = stop;
1290
- const known = /* @__PURE__ */ new Set([
1291
- "patience",
1292
- "maxVersions",
1293
- "maxUsd",
1294
- "deadlineMs",
1295
- "minImprovement"
1296
- ]);
1297
- const unknown = Object.keys(rule).filter((key) => !known.has(key));
1298
- if (unknown.length > 0) fail(`stop has unknown fields: ${unknown.join(", ")}`);
1299
- for (const key of ["patience", "maxVersions"]) if (!Number.isInteger(rule[key]) || rule[key] < 1) fail(`stop.${key} must be an integer of at least 1`);
1300
- for (const key of ["maxUsd", "deadlineMs"]) if (typeof rule[key] !== "number" || !Number.isFinite(rule[key]) || rule[key] <= 0) fail(`stop.${key} must be a finite number above 0`);
1301
- if (rule.minImprovement !== void 0 && (typeof rule.minImprovement !== "number" || !Number.isFinite(rule.minImprovement) || rule.minImprovement < 0)) fail("stop.minImprovement must be a finite number of at least 0");
1302
- }
1303
- /** Run a version chain. `supervisePursuit` calls this when `versions` is set. */
1304
- async function runPursuitVersions(profile, task, opts, runOne) {
1305
- const { versions, ...rest } = opts;
1306
- assertPursuitVersions(versions);
1307
- for (const key of [
1308
- "journal",
1309
- "blobs",
1310
- "rootHandle",
1311
- "steerDir"
1312
- ]) if (rest[key] !== void 0) throw new ValidationError(`supervisePursuit versions: ${key} names one run, and a version chain has one per version; omit it`);
1313
- const judge = versions.judge;
1314
- if (versions.next === "review-of-best" && rest.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");
1315
- const next = versions.next === "review-of-best" ? reviewOfBest(rest.runId ?? "supervise", rest.continuation?.profile.review ?? "") : versions.next;
1316
- const stop = versions.stop;
1317
- const minImprovement = stop.minImprovement ?? 0;
1318
- const now = rest.now ?? Date.now;
1319
- const pursuitId = rest.pursuitId.trim();
1320
- const runDir = resolve(rest.runDir.trim());
1321
- const runId = rest.runId ?? "supervise";
1322
- const { fork: firstFork, signal: callerSignal, ...base } = rest;
1323
- const lineageDir = `${runDir}.versions`;
1324
- const ledgerPath = resolve(lineageDir, PURSUIT_VERSIONS_FILE);
1325
- const firstProfile = firstFork === void 0 ? profile : applyExactAgentProfileDiff(profile, firstFork.change, "supervisePursuit versions");
1326
- await mkdir(lineageDir, { recursive: true });
1327
- const lock = await acquireRunDirectoryLock(lineageDir, `${runId}:versions`, now);
1328
- try {
1329
- const ledger = await readLedger(ledgerPath);
1330
- let chain = ledger.find((line) => line.kind === "chain");
1331
- if (chain === void 0) {
1332
- const elapsed = (await readSettleRecord(runDir))?.spentTotal?.ms;
1333
- const startedAt = new Date(now() - (typeof elapsed === "number" && Number.isFinite(elapsed) ? elapsed : 0)).toISOString();
1334
- chain = {
1335
- kind: "chain",
1336
- pursuitId,
1337
- runId,
1338
- runDir,
1339
- judgeDigest: judge.digest,
1340
- stop: canonicalStop(stop),
1341
- startedAt
1342
- };
1343
- await appendLedger(ledgerPath, chain);
1344
- } else {
1345
- const mismatch = [
1346
- chain.pursuitId !== pursuitId ? `pursuitId '${chain.pursuitId}'` : void 0,
1347
- chain.runId !== runId ? `runId '${chain.runId}'` : void 0,
1348
- chain.runDir !== runDir ? `runDir '${chain.runDir}'` : void 0,
1349
- chain.judgeDigest !== judge.digest ? `judge digest ${chain.judgeDigest}` : void 0,
1350
- contentAddress(chain.stop) !== contentAddress(canonicalStop(stop)) ? "another stop rule" : void 0
1351
- ].filter((item) => item !== void 0);
1352
- if (mismatch.length > 0) throw new ValidationError(`supervisePursuit versions: ${ledgerPath} records a chain with ${mismatch.join(", ")}; a chain keeps its identity, judge and stop rule`);
1353
- }
1354
- const startedAtMs = Date.parse(chain.startedAt);
1355
- const deadline = new AbortController();
1356
- let timer;
1357
- const arm = () => {
1358
- const remaining = startedAtMs + stop.deadlineMs - now();
1359
- if (remaining <= 0) {
1360
- deadline.abort(/* @__PURE__ */ new Error("the version chain reached its deadline"));
1361
- return;
1362
- }
1363
- timer = setTimeout(arm, Math.min(remaining, MAX_TIMER_MS));
1364
- timer.unref?.();
1365
- };
1366
- arm();
1367
- const signal = callerSignal === void 0 ? deadline.signal : AbortSignal.any([callerSignal, deadline.signal]);
1368
- try {
1369
- const judged = [];
1370
- const profiles = /* @__PURE__ */ new Map([[1, firstProfile]]);
1371
- let pending = {
1372
- version: 1,
1373
- runId,
1374
- runDir
1375
- };
1376
- let stopped;
1377
- for (const line of ledger) if (line.kind === "start") {
1378
- const parentProfile = profiles.get(line.parent.version);
1379
- if (parentProfile === void 0) throw new RuntimeRunStateError(`supervisePursuit versions: ${ledgerPath} starts version ${line.version} from unknown version ${line.parent.version}`);
1380
- profiles.set(line.version, applyExactAgentProfileDiff(parentProfile, line.change, "supervisePursuit versions"));
1381
- pending = {
1382
- version: line.version,
1383
- runId: line.runId,
1384
- runDir: line.runDir,
1385
- parent: line.parent,
1386
- change: line.change
1387
- };
1388
- } else if (line.kind === "judged") {
1389
- if (line.version !== judged.length + 1 || line.version !== pending?.version) throw new RuntimeRunStateError(`supervisePursuit versions: ${ledgerPath} judges version ${line.version} out of order`);
1390
- if (line.verdict.judgeDigest !== judge.digest) throw new ValidationError(`supervisePursuit versions: version ${line.version} was judged under ${line.verdict.judgeDigest}, not ${judge.digest}`);
1391
- const settled = await readSettled(pending, profiles);
1392
- if (settled.settleDigest !== line.settleDigest) throw new RuntimeRunStateError(`supervisePursuit versions: version ${line.version}'s result.json changed after it was judged`);
1393
- judged.push(Object.freeze({
1394
- ...settled,
1395
- verdict: line.verdict,
1396
- improved: line.improved,
1397
- usd: line.usd,
1398
- usdKnown: line.usdKnown,
1399
- usdSource: line.usdSource,
1400
- ...line.lineage === void 0 ? {} : { lineage: line.lineage }
1401
- }));
1402
- pending = void 0;
1403
- } else if (line.kind === "stopped") stopped = line;
1404
- while (stopped === void 0) {
1405
- if (pending !== void 0) {
1406
- const spec = pending;
1407
- const settled = await settle(spec);
1408
- const verdict = await judgeVersion(settled);
1409
- const bestScore = bestOf(judged)?.verdict.score;
1410
- const improved = isFiniteNumber(verdict.score) && (!isFiniteNumber(bestScore) || verdict.score > bestScore + minImprovement);
1411
- const spent = settled.result.spentTotal;
1412
- const measured = versions.usd === void 0 ? void 0 : await versions.usd(settled, signal);
1413
- const usdSource = measured === void 0 ? "runtime" : "caller";
1414
- const usd = measured === void 0 ? isFiniteNumber(spent?.usd) ? spent.usd : null : isFiniteNumber(measured) ? measured : null;
1415
- const usdKnown = usd !== null && (measured !== void 0 || spent?.usdKnown !== false);
1416
- const lineage = versionLineage(spec, firstFork);
1417
- await appendLedger(ledgerPath, {
1418
- kind: "judged",
1419
- version: spec.version,
1420
- runId: spec.runId,
1421
- runDir: spec.runDir,
1422
- settleDigest: settled.settleDigest,
1423
- ...spec.parent === void 0 ? {} : { parent: spec.parent },
1424
- ...spec.change?.id === void 0 ? {} : { changeId: spec.change.id },
1425
- verdict,
1426
- improved,
1427
- usd,
1428
- usdKnown,
1429
- usdSource,
1430
- ...lineage === void 0 ? {} : { lineage }
1431
- });
1432
- judged.push(Object.freeze({
1433
- ...settled,
1434
- verdict,
1435
- improved,
1436
- usd,
1437
- usdKnown,
1438
- usdSource,
1439
- ...lineage === void 0 ? {} : { lineage }
1440
- }));
1441
- pending = void 0;
1442
- }
1443
- const reason = stopReason(judged);
1444
- if (reason !== void 0) {
1445
- stopped = {
1446
- kind: "stopped",
1447
- reason,
1448
- at: new Date(now()).toISOString(),
1449
- best: (bestOf(judged) ?? judged[0]).version,
1450
- spentUsd: spentOf(judged)
1451
- };
1452
- await appendLedger(ledgerPath, stopped);
1453
- break;
1454
- }
1455
- const best = bestOf(judged) ?? judged[0];
1456
- const last = judged[judged.length - 1];
1457
- const change = await next({
1458
- best,
1459
- last,
1460
- versions: Object.freeze([...judged])
1461
- }, signal);
1462
- if (typeof change?.id !== "string" || change.id.trim().length === 0) throw new ValidationError("supervisePursuit versions: next must return a change with an id");
1463
- const version = judged.length + 1;
1464
- const spec = {
1465
- version,
1466
- ...pursuitVersionRun(runDir, runId, version),
1467
- parent: {
1468
- version: best.version,
1469
- runId: best.runId,
1470
- settleDigest: best.settleDigest
1471
- },
1472
- change
1473
- };
1474
- profiles.set(version, applyExactAgentProfileDiff(best.profile, change, "supervisePursuit versions"));
1475
- await appendLedger(ledgerPath, {
1476
- kind: "start",
1477
- version,
1478
- runId: spec.runId,
1479
- runDir: spec.runDir,
1480
- parent: spec.parent,
1481
- change
1482
- });
1483
- pending = spec;
1484
- }
1485
- const bestVersion = judged.find((item) => item.version === stopped.best) ?? judged[0];
1486
- const record = Object.freeze({
1487
- lineageDir,
1488
- judgeDigest: judge.digest,
1489
- stop: canonicalStop(stop),
1490
- startedAt: chain.startedAt,
1491
- versions: Object.freeze([...judged]),
1492
- best: bestVersion.version,
1493
- spentUsd: stopped.spentUsd,
1494
- stopped: Object.freeze({
1495
- reason: stopped.reason,
1496
- at: stopped.at
1497
- })
1498
- });
1499
- const observerPath = resolve(bestVersion.runDir, "observer.jsonl");
1500
- return Object.freeze({
1501
- result: bestVersion.result,
1502
- pursuit: projectPursuit(await new FileObserverJournal(observerPath, pursuitId).read()),
1503
- observerPath,
1504
- settlePath: resolve(bestVersion.runDir, SETTLE_RECORD_FILE),
1505
- versions: record
1506
- });
1507
- /** Run the version unless its directory already settled, then read it back. */
1508
- async function settle(spec) {
1509
- if (await readSettleRecord(spec.runDir) === void 0) {
1510
- if (signal.aborted) throw new RuntimeRunStateError(`supervisePursuit versions: version ${spec.version} was not started: ${abortMessage(signal)}`);
1511
- if (spec.parent === void 0 || spec.change === void 0) await runOne(profile, task, {
1512
- ...base,
1513
- ...firstFork === void 0 ? {} : { fork: firstFork },
1514
- signal
1515
- });
1516
- else {
1517
- const parent = judged.find((item) => item.version === spec.parent.version);
1518
- if (parent === void 0) throw new RuntimeRunStateError(`supervisePursuit versions: version ${spec.version}'s parent ${spec.parent.version} is not judged`);
1519
- const fork = {
1520
- runDir: parent.runDir,
1521
- settleDigest: parent.settleDigest,
1522
- change: spec.change,
1523
- acceptUncertain: true
1524
- };
1525
- const bar = base.continuation !== void 0 && parent.verdict.check !== void 0 ? { continuation: {
1526
- ...base.continuation,
1527
- best: {
1528
- label: `v${parent.version}`,
1529
- verdict: parent.verdict.check
1530
- }
1531
- } } : {};
1532
- const options = {
1533
- ...base,
1534
- ...bar,
1535
- runId: spec.runId,
1536
- runDir: spec.runDir,
1537
- fork,
1538
- signal
1539
- };
1540
- if (versions.run === void 0) await runOne(parent.profile, task, options);
1541
- else {
1542
- const prepared = await prepareRunFork(parent.profile, task, options, fork);
1543
- await versions.run(Object.freeze({
1544
- version: spec.version,
1545
- runId: spec.runId,
1546
- runDir: spec.runDir,
1547
- pursuitId,
1548
- profile: prepared.profile,
1549
- task,
1550
- budget: base.budget,
1551
- execution: prepared.execution,
1552
- fork,
1553
- parentProfile: parent.profile
1554
- }), signal);
1555
- }
1556
- }
1557
- }
1558
- const settled = await readSettled(spec, profiles);
1559
- if (settled === void 0) throw new RuntimeRunStateError(`supervisePursuit versions: version ${spec.version} returned without a settle record in ${spec.runDir}`);
1560
- return settled;
1561
- }
1562
- async function judgeVersion(settled) {
1563
- const verdict = await judge.judge(settled, signal);
1564
- if (typeof verdict !== "object" || verdict === null) throw new ValidationError("supervisePursuit versions: the judge returned no verdict");
1565
- 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}`);
1566
- if (verdict.score !== null && !isFiniteNumber(verdict.score)) throw new ValidationError("supervisePursuit versions: a verdict score must be a finite number or null");
1567
- return JSON.parse(JSON.stringify(verdict));
1568
- }
1569
- function stopReason(done) {
1570
- if (callerSignal?.aborted) return "aborted";
1571
- if (done.length >= stop.maxVersions) return "max-versions";
1572
- let stale = 0;
1573
- for (let index = done.length - 1; index >= 0 && !done[index].improved; index -= 1) stale += 1;
1574
- if (stale >= stop.patience) return "no-improvement";
1575
- if (done.some((item) => item.usd === null)) return "spend-unknown";
1576
- if (spentOf(done) >= stop.maxUsd) return "max-usd";
1577
- if (deadline.signal.aborted || now() - startedAtMs >= stop.deadlineMs) return "deadline";
1578
- }
1579
- } finally {
1580
- if (timer !== void 0) clearTimeout(timer);
1581
- }
1582
- } finally {
1583
- await lock.release();
1584
- }
1585
- }
1586
- async function readSettled(spec, profiles) {
1587
- let bytes;
1588
- try {
1589
- bytes = await readFile(resolve(spec.runDir, SETTLE_RECORD_FILE));
1590
- } catch (error) {
1591
- if (!isNoEntError(error)) throw error;
1592
- throw new RuntimeRunStateError(`supervisePursuit versions: version ${spec.version} has no settle record in ${spec.runDir}`);
1593
- }
1594
- const result = await readSettleRecord(spec.runDir);
1595
- const profile = profiles.get(spec.version);
1596
- if (profile === void 0) throw new RuntimeRunStateError(`supervisePursuit versions: version ${spec.version} has no recorded profile`);
1597
- return Object.freeze({
1598
- version: spec.version,
1599
- runId: spec.runId,
1600
- runDir: spec.runDir,
1601
- settleDigest: sha256Bytes(bytes),
1602
- result,
1603
- profile,
1604
- ...spec.parent === void 0 ? {} : { parent: spec.parent },
1605
- ...spec.change === void 0 ? {} : { change: spec.change }
1606
- });
1607
- }
1608
- function versionLineage(spec, firstFork) {
1609
- if (spec.parent !== void 0 && spec.change !== void 0) return {
1610
- source: lineageSource(spec.change),
1611
- runIds: [spec.parent.runId],
1612
- profileDiffIds: [spec.change.id]
1613
- };
1614
- if (firstFork !== void 0) return {
1615
- source: lineageSource(firstFork.change),
1616
- profileDiffIds: [firstFork.change.id]
1617
- };
1618
- }
1619
- /** The change's author, in the lineage's words. A trace-derived change is a compound of runs. */
1620
- function lineageSource(change) {
1621
- const kind = change.source?.kind;
1622
- return kind === "human" || kind === "optimizer" || kind === "frontier-author" ? kind : "compound";
1623
- }
1624
- function bestOf(done) {
1625
- let best;
1626
- for (const item of done) {
1627
- if (!isFiniteNumber(item.verdict.score)) continue;
1628
- if (best === void 0 || item.verdict.score > best.verdict.score) best = item;
1629
- }
1630
- return best;
1631
- }
1632
- function spentOf(done) {
1633
- return done.reduce((sum, item) => sum + (item.usd ?? 0), 0);
1634
- }
1635
- function canonicalStop(stop) {
1636
- return {
1637
- patience: stop.patience,
1638
- maxVersions: stop.maxVersions,
1639
- maxUsd: stop.maxUsd,
1640
- deadlineMs: stop.deadlineMs,
1641
- ...stop.minImprovement === void 0 ? {} : { minImprovement: stop.minImprovement }
1642
- };
1643
- }
1644
- /** Where `'review-of-best'` mounts a review: `inputs/review/version-<n>.md`. One review lives in
1645
- * a profile at a time. */
1646
- const REVIEW_DIR = "inputs/review/";
1647
- /**
1648
- * `'review-of-best'`: fork from the best version with its check's verdict mounted under
1649
- * {@link REVIEW_DIR} and the profile's review words as one instruction. The previous review's
1650
- * mount and instruction are removed, so a profile carries one review. This is what the Lab's
1651
- * `continue-best` changes did in Lab code, now written once from the check's own verdict.
1652
- */
1653
- function reviewOfBest(runId, words) {
1654
- return ({ best, versions }) => {
1655
- const n = versions.length + 1;
1656
- const verdict = best.verdict.check;
1657
- const path = `${REVIEW_DIR}version-${best.version}.md`;
1658
- const instruction = words.replaceAll("{version}", String(best.version)).replaceAll("{path}", path).replaceAll("{score}", best.verdict.score === null ? "none" : String(best.verdict.score)).trim();
1659
- const page = reviewPage(best.version, best.verdict.score, verdict);
1660
- const earlierInstructions = best.change?.set?.prompt?.instructions ?? [];
1661
- const earlierMounts = (best.profile.resources?.files ?? []).map((file) => file.path).filter((mounted) => mounted.startsWith("inputs/review/") && mounted !== path);
1662
- return {
1663
- kind: "agent-profile-diff",
1664
- id: `${runId}-v${n}-review-of-v${best.version}`,
1665
- title: `Version ${n}: review of version ${best.version}`,
1666
- source: {
1667
- kind: "optimizer",
1668
- notes: [`review-of-best: version ${best.version}`, `judge ${best.verdict.judgeDigest}`]
1669
- },
1670
- set: {
1671
- prompt: { instructions: [instruction] },
1672
- resources: { files: [{
1673
- path,
1674
- resource: {
1675
- kind: "inline",
1676
- name: path,
1677
- content: page
1678
- }
1679
- }] }
1680
- },
1681
- ...earlierInstructions.length > 0 || earlierMounts.length > 0 ? { remove: {
1682
- ...earlierInstructions.length > 0 ? { prompt: { instructions: [...earlierInstructions] } } : {},
1683
- ...earlierMounts.length > 0 ? { resources: { files: earlierMounts } } : {}
1684
- } } : {}
1685
- };
1686
- };
1687
- }
1688
- /** The review page: facts only, in the check's own lines. */
1689
- function reviewPage(version, score, verdict) {
1690
- if (verdict === void 0) return [
1691
- `# Version ${version}`,
1692
- "",
1693
- `Score: ${score ?? "none"}. The judge reported no per-item verdict.`,
1694
- ""
1695
- ].join("\n");
1696
- const failing = failedItems(verdict);
1697
- return [
1698
- `# Version ${version}`,
1699
- "",
1700
- `Score: ${score ?? "none"}.${verdict.threshold === void 0 ? "" : ` The check passes at ${verdict.threshold}.`}`,
1701
- "",
1702
- "## Items",
1703
- "",
1704
- ...Object.entries(verdict.items ?? {}).map(([item, value]) => `- ${item}: ${value >= 1 ? "passes" : `fails (${value})`}`),
1705
- "",
1706
- ...failing.length === 0 ? [] : [
1707
- "## Failures",
1708
- "",
1709
- ...verdict.failures ?? [],
1710
- ""
1711
- ],
1712
- ...verdict.review === void 0 ? [] : [
1713
- "## The check's review",
1714
- "",
1715
- verdict.review,
1716
- ""
1717
- ]
1718
- ].join("\n");
1719
- }
1720
- async function readLedger(path) {
1721
- let text;
1722
- try {
1723
- text = await readFile(path, "utf8");
1724
- } catch (error) {
1725
- if (isNoEntError(error)) return [];
1726
- throw error;
1727
- }
1728
- return parseCommittedJsonLines(text, path);
1729
- }
1730
- async function appendLedger(path, line) {
1731
- const endsWithRecord = await prepareJsonlAppend(path);
1732
- const handle = await open(path, "a");
1733
- try {
1734
- await writeAllBytes(handle, `${endsWithRecord ? "\n" : ""}${JSON.stringify(line)}\n`);
1735
- await handle.sync();
1736
- } finally {
1737
- await handle.close();
1738
- }
1739
- }
1740
- function isSha256(value) {
1741
- return typeof value === "string" && /^sha256:[0-9a-f]{64}$/u.test(value);
1742
- }
1743
- function isFiniteNumber(value) {
1744
- return typeof value === "number" && Number.isFinite(value);
1745
- }
1746
- function abortMessage(signal) {
1747
- const reason = signal.reason;
1748
- return reason instanceof Error ? reason.message : String(reason ?? "aborted");
1749
- }
1750
- //#endregion
1751
2046
  //#region src/durable/supervise-pursuit.ts
1752
2047
  /** A failed Runtime execution whose complete third-person projection was retained. */
1753
2048
  var SupervisePursuitError = class extends Error {
@@ -1946,6 +2241,6 @@ function compareText(left, right) {
1946
2241
  return left < right ? -1 : left > right ? 1 : 0;
1947
2242
  }
1948
2243
  //#endregion
1949
- export { FAILURE_RECORD_FILE, FORK_PARENT_UNCERTAIN_NODES_KEY, FileObserverJournal, PURSUIT_VERSIONS_FILE, REVIEW_DIR, ROOT_STREAM_FILE, RUN_DIRECTORY_LOCK_FILE, RUN_FORK_CORRELATION_KEYS, RunDirectoryLockedError, SETTLE_RECORD_FILE, SettledRunDirectoryError, SupervisePursuitError, acquireRunDirectoryLock, assertPursuitVersions, createFileObserverHooks, deriveExecutionId, discoverDurableSupervisionRun, handleChatTurn, observerRecordDigest, projectPursuit, pursuitVersionRun, readFailureRecord, readRootStream, readRootStreamReceipt, readRunDirectoryLock, readSettleRecord, runDirectoryHolderIsLive, settleRecordJson, supervisePursuit, verifyObserverRecords };
2244
+ export { FAILURE_RECORD_FILE, FORK_PARENT_UNCERTAIN_NODES_KEY, FileObserverJournal, REVIEW_DIR, ROOT_STREAM_FILE, RUN_DIRECTORY_LOCK_FILE, RUN_FORK_CORRELATION_KEYS, RunDirectoryLockedError, SETTLE_RECORD_FILE, SettledRunDirectoryError, SupervisePursuitError, acquireRunDirectoryLock, assertPursuitVersions, createFileObserverHooks, deriveExecutionId, discoverDurableSupervisionRun, handleChatTurn, observerRecordDigest, projectPursuit, pursuitVersionsLedgerPath, readFailureRecord, readRootStream, readRootStreamReceipt, readRunDirectoryLock, readSettleRecord, runDirectoryHolderIsLive, settleRecordJson, supervisePursuit, verifyObserverRecords };
1950
2245
 
1951
2246
  //# sourceMappingURL=durable.js.map