@tangle-network/agent-runtime 0.337.1 → 0.338.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 (112) hide show
  1. package/dist/{activation-DMehb166.d.ts → activation-CsbNax2X.d.ts} +92 -4
  2. package/dist/activation-kbkAuSmY.js +889 -0
  3. package/dist/activation-kbkAuSmY.js.map +1 -0
  4. package/dist/agent.d.ts +1 -1
  5. package/dist/agent.js +3 -6
  6. package/dist/agent.js.map +1 -1
  7. package/dist/{bundle-BPGjESee.js → bundle-DM60AI2B.js} +2 -2
  8. package/dist/{bundle-BPGjESee.js.map → bundle-DM60AI2B.js.map} +1 -1
  9. package/dist/candidate-execution/index.d.ts +2 -2
  10. package/dist/candidate-execution/index.js +4 -5
  11. package/dist/candidate-execution/index.js.map +1 -1
  12. package/dist/content-digest-sBTLujlK.js +9 -0
  13. package/dist/content-digest-sBTLujlK.js.map +1 -0
  14. package/dist/{delegate-aC14Cww3.js → delegate-Se1YZKMb.js} +2 -2
  15. package/dist/{delegate-aC14Cww3.js.map → delegate-Se1YZKMb.js.map} +1 -1
  16. package/dist/{coordination-driver-Dg9a6qsm.js → driver-control-acknowledgers-T2a1Ouay.js} +4514 -4440
  17. package/dist/driver-control-acknowledgers-T2a1Ouay.js.map +1 -0
  18. package/dist/durable.d.ts +1 -1
  19. package/dist/durable.js +223 -227
  20. package/dist/durable.js.map +1 -1
  21. package/dist/{graph-Cfx711ES.js → graph-CY0wH838.js} +65 -18
  22. package/dist/graph-CY0wH838.js.map +1 -0
  23. package/dist/{graph-registry-DAI6KNXB.js → graph-registry-By0tUj4S.js} +16 -15
  24. package/dist/graph-registry-By0tUj4S.js.map +1 -0
  25. package/dist/{improvement-cycle-DHKcb_YW.js → improve-CWGBT13K.js} +75 -1220
  26. package/dist/improve-CWGBT13K.js.map +1 -0
  27. package/dist/index.d.ts +6 -6
  28. package/dist/index.js +10 -13
  29. package/dist/index.js.map +1 -1
  30. package/dist/{integrations-DopfCC2a.d.ts → integrations-6xttbPi9.d.ts} +3 -3
  31. package/dist/integrations-dFi-ALk7.js.map +1 -1
  32. package/dist/intelligence.d.ts +7 -94
  33. package/dist/intelligence.js +505 -13
  34. package/dist/intelligence.js.map +1 -1
  35. package/dist/kernel.d.ts +2 -2
  36. package/dist/kernel.js +13 -12
  37. package/dist/{loop-runner-bin-B86AiPBf.d.ts → loop-runner-bin-CFnrAHpl.d.ts} +2 -2
  38. package/dist/{loop-runner-bin-BSKBNC38.js → loop-runner-bin-CdPlhy9g.js} +3 -3
  39. package/dist/{loop-runner-bin-BSKBNC38.js.map → loop-runner-bin-CdPlhy9g.js.map} +1 -1
  40. package/dist/loop-runner-bin.d.ts +1 -1
  41. package/dist/loop-runner-bin.js +1 -1
  42. package/dist/mcp/bin.js +3 -3
  43. package/dist/mcp/bin.js.map +1 -1
  44. package/dist/mcp/index.d.ts +7 -3
  45. package/dist/mcp/index.js +6 -8
  46. package/dist/mcp/index.js.map +1 -1
  47. package/dist/{openai-tools-DHO2QS1q.d.ts → openai-tools-zh2I_uD7.d.ts} +2 -2
  48. package/dist/platform.d.ts +7 -2
  49. package/dist/platform.js +16 -8
  50. package/dist/platform.js.map +1 -1
  51. package/dist/{prepare-CER-ZkPp.js → prepare-Bt0IouPq.js} +1241 -586
  52. package/dist/prepare-Bt0IouPq.js.map +1 -0
  53. package/dist/{profile-gNUsHNIJ.js → profile-Do-5xO_D.js} +89 -3
  54. package/dist/profile-Do-5xO_D.js.map +1 -0
  55. package/dist/profiles.d.ts +1 -1
  56. package/dist/profiles.js +1 -3
  57. package/dist/profiles.js.map +1 -1
  58. package/dist/{protected-model-port-BhpQRTw-.d.ts → protected-model-port-DGxQ8_YM.d.ts} +3 -3
  59. package/dist/{provision-supervisor-72YFf-i_.js → provision-supervisor-0jMufp4h.js} +12 -9
  60. package/dist/provision-supervisor-0jMufp4h.js.map +1 -0
  61. package/dist/record-value-B6bwJxLa.js +12 -0
  62. package/dist/record-value-B6bwJxLa.js.map +1 -0
  63. package/dist/{run-layout-Cu8H7aeh.js → run-cancellation-BoW5Sg9Y.js} +174 -95
  64. package/dist/run-cancellation-BoW5Sg9Y.js.map +1 -0
  65. package/dist/{runtime-qFLOq1R9.js → runtime-D37zRSs7.js} +432 -684
  66. package/dist/runtime-D37zRSs7.js.map +1 -0
  67. package/dist/{sandbox-profile-compat-QTkLe1Z6.js → sandbox-profile-compat-xSoVtdWw.js} +690 -697
  68. package/dist/sandbox-profile-compat-xSoVtdWw.js.map +1 -0
  69. package/dist/search-executor-DmgUm5p7.js +1916 -0
  70. package/dist/search-executor-DmgUm5p7.js.map +1 -0
  71. package/dist/{server-_FldJ9Cl.js → server-DQHJszfk.js} +4 -4
  72. package/dist/server-DQHJszfk.js.map +1 -0
  73. package/dist/{search-executor-CGxvizHh.js → structural-rollout-DAvIE8mw.js} +2262 -3984
  74. package/dist/structural-rollout-DAvIE8mw.js.map +1 -0
  75. package/dist/{supervise-H4BTN6uA.js → supervise-WuPAwfPh.js} +7793 -5338
  76. package/dist/supervise-WuPAwfPh.js.map +1 -0
  77. package/dist/{supervisor-C27ne4yv.js → supervisor-CPG1I9UN.js} +27379 -27899
  78. package/dist/supervisor-CPG1I9UN.js.map +1 -0
  79. package/dist/testing.d.ts +226 -1
  80. package/dist/testing.js +13 -14
  81. package/dist/testing.js.map +1 -1
  82. package/dist/{top-app-BaMw1W2z.js → top-app-C55Wa7uy.js} +339 -337
  83. package/dist/top-app-C55Wa7uy.js.map +1 -0
  84. package/dist/tui/bin.js +1 -1
  85. package/dist/tui/index.d.ts +17 -15
  86. package/dist/tui/index.js +2 -2
  87. package/dist/{types-CupCBY-j.d.ts → types-CrNWif8-.d.ts} +17655 -17406
  88. package/dist/{workspace-streams-JLjh5DC6.d.ts → workspace-streams-BZZds1Fw.d.ts} +18 -16
  89. package/package.json +4 -4
  90. package/skills/agent-graphs/SKILL.md +10 -3
  91. package/skills/agent-graphs/references/authoring.md +17 -0
  92. package/skills/profile-authoring/SKILL.md +3 -3
  93. package/skills/supervise/SKILL.md +2 -2
  94. package/dist/activation-BgWVlVu2.js +0 -234
  95. package/dist/activation-BgWVlVu2.js.map +0 -1
  96. package/dist/coordination-driver-Dg9a6qsm.js.map +0 -1
  97. package/dist/graph-Cfx711ES.js.map +0 -1
  98. package/dist/graph-registry-DAI6KNXB.js.map +0 -1
  99. package/dist/improvement-cycle-DHKcb_YW.js.map +0 -1
  100. package/dist/prepare-CER-ZkPp.js.map +0 -1
  101. package/dist/profile-gNUsHNIJ.js.map +0 -1
  102. package/dist/protected-model-port-BuRsviSL.js +0 -766
  103. package/dist/protected-model-port-BuRsviSL.js.map +0 -1
  104. package/dist/provision-supervisor-72YFf-i_.js.map +0 -1
  105. package/dist/run-layout-Cu8H7aeh.js.map +0 -1
  106. package/dist/runtime-qFLOq1R9.js.map +0 -1
  107. package/dist/sandbox-profile-compat-QTkLe1Z6.js.map +0 -1
  108. package/dist/search-executor-CGxvizHh.js.map +0 -1
  109. package/dist/server-_FldJ9Cl.js.map +0 -1
  110. package/dist/supervise-H4BTN6uA.js.map +0 -1
  111. package/dist/supervisor-C27ne4yv.js.map +0 -1
  112. package/dist/top-app-BaMw1W2z.js.map +0 -1
@@ -1,14 +1,1185 @@
1
- import { A as verifyMaterializedWorkspace, B as omitTopLevelDigest, E as readVerifiedArtifact, F as canonicalCandidateDigest$1, I as canonicalCandidateDocument, L as deepFreezeCandidate, O as verifyBytes, P as canonicalCandidateBytes$1, R as embeddedCandidateArtifact, S as artifactCacheKey, T as readMaterializedWorkspaceFiles, V as sha256Bytes$1, Y as errorMessage, _ as verifyTaskCheckout, b as isWellFormedUnicode, g as verifyCandidateCode, h as readCandidateGitHubResource, j as verifyWorkspaceSnapshotArtifacts, k as verifyMaterializedProfileWorkspace, m as persistCandidateOutputArtifact, v as verifyTaskOutcomePatch, y as assertExactObjectKeys, z as immutableCandidateValue } from "./sandbox-profile-compat-QTkLe1Z6.js";
1
+ import { A as verifyMaterializedWorkspace, B as omitTopLevelDigest, E as readVerifiedArtifact, F as canonicalCandidateDigest$1, I as canonicalCandidateDocument, L as deepFreezeCandidate, O as verifyBytes, P as canonicalCandidateBytes$1, R as embeddedCandidateArtifact, S as artifactCacheKey, T as readMaterializedWorkspaceFiles, U as hasControlCharacter, V as sha256Bytes$1, Z as errorMessage, b as isWellFormedUnicode, d as readCandidateGitHubResource, f as verifyCandidateCode, j as verifyWorkspaceSnapshotArtifacts, k as verifyMaterializedProfileWorkspace, m as verifyTaskOutcomePatch, p as verifyTaskCheckout, v as persistCandidateOutputArtifact, y as assertExactObjectKeys, z as immutableCandidateValue } from "./sandbox-profile-compat-xSoVtdWw.js";
2
2
  import { i as redactProtectedValue, n as createProtectedRecordRedactor, r as redactProtectedReason, t as assertNoProtectedBytes } from "./protected-redaction-DFCeo4vg.js";
3
- import { f as parseAgentCandidateProfileActivation, g as requirePublicCandidateConfigValue, n as PI_CANDIDATE_SESSION_DIR_ENV, o as assertCandidateProfileExecutionSupport, s as candidateProfileAgentPaths, t as PI_CANDIDATE_AGENT_DIR_ENV, u as materializeAgentCandidateProfilePlan } from "./profile-gNUsHNIJ.js";
3
+ import { _ as parseAgentCandidateProfileActivation, c as buildLaunch, f as exactProfileExecutorFiles, h as modelRoutes, l as candidateEntrypointReceipt, m as materializeAgentCandidateProfilePlan, n as PI_CANDIDATE_SESSION_DIR_ENV, r as absoluteExecutionCwd, s as assertCandidateProfileExecutionSupport, t as PI_CANDIDATE_AGENT_DIR_ENV, u as candidateProfileAgentPaths, x as requirePublicCandidateConfigValue } from "./profile-Do-5xO_D.js";
4
4
  import { agentCandidateArtifactRefSchema, agentCandidateBenchmarkResultEvidenceSchema, agentCandidateBenchmarkSuiteSchema, agentCandidateBenchmarkTaskSchema, agentCandidateBundleSchema, agentCandidateContainerSchema, agentCandidateExecutionLimitsSchema, agentCandidateExecutionPlanEvidenceSchema, agentCandidateExecutionPlanMaterialSchema, agentCandidateMaterializationReceiptSchema, agentCandidateModelAccessNetworkSchema, agentCandidateModelSettlementEvidenceSchema, agentCandidateProfilePlanEvidenceSchema, agentCandidateResolvedModelSchema, agentCandidateRunCellSchema, agentCandidateRunReceiptSchema, agentCandidateTaskOutcomeEvidenceSchema, agentCandidateTaskOutcomeSpecSchema, agentCandidateTerminationSchema, agentCandidateWorkspaceManifestMaterialSchema, agentCandidateWorkspaceSnapshotEvidenceSchema, sha256DigestSchema } from "@tangle-network/agent-interface";
5
5
  import { REDACTION_VERSION, isLlmSpan } from "@tangle-network/agent-eval";
6
6
  import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
7
7
  import { isAbsolute, join, posix, relative, resolve } from "node:path";
8
8
  import { lstat, mkdtemp, readFile, readdir, rm } from "node:fs/promises";
9
9
  import { applyAgentCandidateWorkspacePlan } from "@tangle-network/agent-profile-materialize";
10
+ import { isDeepStrictEqual } from "node:util";
10
11
  import { tmpdir } from "node:os";
11
12
  import { hashKnowledgeBase } from "@tangle-network/agent-knowledge";
13
+ //#region src/candidate-execution/execution-roots.ts
14
+ /** Validate the canonical identity and isolation boundary for execution roots. */
15
+ function assertAgentCandidateExecutionRoots(roots) {
16
+ const entries = [
17
+ ["task", roots.taskRoot],
18
+ ["candidate", roots.candidateRoot],
19
+ ["profile", roots.profileRoot]
20
+ ];
21
+ for (const [name, root] of entries) {
22
+ if (root === void 0) continue;
23
+ if (!posix.isAbsolute(root) || posix.normalize(root) !== root) throw new Error(`execution ${name} root must be a canonical absolute path`);
24
+ }
25
+ for (let left = 0; left < entries.length; left++) {
26
+ const entry = entries[left];
27
+ if (!entry) continue;
28
+ const [leftName, leftRoot] = entry;
29
+ if (leftRoot === void 0) continue;
30
+ for (let right = left + 1; right < entries.length; right++) {
31
+ const rightEntry = entries[right];
32
+ if (!rightEntry) continue;
33
+ const [rightName, rightRoot] = rightEntry;
34
+ if (rightRoot !== void 0 && executionPathsOverlap(leftRoot, rightRoot)) throw new Error(`execution ${leftName} and ${rightName} roots must be distinct and non-overlapping`);
35
+ }
36
+ }
37
+ }
38
+ function executionPathsOverlap(left, right) {
39
+ const a = posix.normalize(left);
40
+ const b = posix.normalize(right);
41
+ return a === b || b.startsWith(a === "/" ? "/" : `${a}/`) || a.startsWith(b === "/" ? "/" : `${b}/`);
42
+ }
43
+ //#endregion
44
+ //#region src/candidate-execution/types.ts
45
+ const verifiedCandidateBrand = Symbol("verifiedAgentCandidate");
46
+ const preparedCandidateBrand = Symbol("preparedAgentCandidate");
47
+ const verifiedTaskOutcomeBrand = Symbol("verifiedTaskOutcome");
48
+ /** Protected trace tags that bind a run to one prepared candidate execution. */
49
+ const CANDIDATE_TRACE_TAGS = {
50
+ executionId: "tangle.candidate.execution_id",
51
+ bundleDigest: "tangle.candidate.bundle_digest",
52
+ executionPlanDigest: "tangle.candidate.execution_plan_digest",
53
+ materializationReceiptDigest: "tangle.candidate.materialization_receipt_digest"
54
+ };
55
+ /** Environment keys used to propagate immutable candidate trace identity. */
56
+ const CANDIDATE_TRACE_ENV = {
57
+ executionId: "TANGLE_CANDIDATE_EXECUTION_ID",
58
+ bundleDigest: "TANGLE_CANDIDATE_BUNDLE_DIGEST",
59
+ executionPlanDigest: "TANGLE_CANDIDATE_EXECUTION_PLAN_DIGEST",
60
+ materializationReceiptDigest: "TANGLE_CANDIDATE_MATERIALIZATION_RECEIPT_DIGEST",
61
+ traceRunId: "TANGLE_TRACE_RUN_ID"
62
+ };
63
+ //#endregion
64
+ //#region src/candidate-execution/verify.ts
65
+ const verifiedCandidateState = /* @__PURE__ */ new WeakMap();
66
+ /** Surfaces admitted by Runtime's verifier before an environment adapter is selected. */
67
+ const AGENT_CANDIDATE_EXECUTION_SUPPORT = Object.freeze({
68
+ outcomes: Object.freeze(["workspace", "output"]),
69
+ code: Object.freeze([
70
+ "disabled",
71
+ "no-op",
72
+ "git-patch"
73
+ ]),
74
+ memory: Object.freeze(["disabled", "isolated"]),
75
+ knowledge: true,
76
+ profile: Object.freeze({
77
+ mcpTransports: Object.freeze(["stdio"]),
78
+ remoteMcp: false,
79
+ tools: false,
80
+ permissions: false,
81
+ modes: false,
82
+ confidential: false
83
+ })
84
+ });
85
+ /** Verifies every digest, resource, workspace, and Git object in a candidate bundle. */
86
+ async function verifyAgentCandidateBundle(input, ports) {
87
+ const parsed = agentCandidateBundleSchema.parse(input);
88
+ const withoutDigest = omitTopLevelDigest(parsed);
89
+ const actualDigest = canonicalCandidateDigest$1(withoutDigest);
90
+ if (actualDigest !== parsed.digest) throw new Error(`candidate bundle digest ${parsed.digest} does not match ${actualDigest}`);
91
+ const canonicalBytes = canonicalCandidateBytes$1(withoutDigest);
92
+ verifyBytes(canonicalBytes, parsed.digest, canonicalBytes.byteLength, "candidate bundle");
93
+ assertCandidateProfileExecutionSupport(parsed.profile);
94
+ const artifactBytes = /* @__PURE__ */ new Map();
95
+ const readArtifact = async (artifact) => {
96
+ const key = artifactCacheKey(artifact);
97
+ const existing = artifactBytes.get(key);
98
+ if (existing) return Uint8Array.from(existing);
99
+ const bytes = await readVerifiedArtifact(artifact, ports.artifacts);
100
+ artifactBytes.set(key, Uint8Array.from(bytes));
101
+ return bytes;
102
+ };
103
+ let patchBytes;
104
+ if (parsed.code.kind === "git-patch") patchBytes = await readArtifact(parsed.code.patch.artifact);
105
+ const materializedTree = await verifyCandidateCode(parsed.code, ports.repositories, patchBytes);
106
+ const resourceBytes = /* @__PURE__ */ new Map();
107
+ for (const resource of candidateResources(parsed)) {
108
+ const bytes = resource.kind === "inline" ? Buffer.from(resource.content, "utf8") : await readCandidateGitHubResource(resource, ports.repositories);
109
+ verifyBytes(bytes, resource.sha256, resource.byteLength, `candidate resource ${resource.name ?? (resource.kind === "github" ? resource.path : "<unnamed>")}`);
110
+ resourceBytes.set(resourceKey(resource), Uint8Array.from(bytes));
111
+ resourceBytes.set(resource.sha256, Uint8Array.from(bytes));
112
+ }
113
+ if (parsed.execution.workspace) {
114
+ const workspace = await verifyWorkspaceSnapshotArtifacts(parsed.execution.workspace, ports.artifacts);
115
+ artifactBytes.set(artifactCacheKey(parsed.execution.workspace.manifest), workspace.manifest);
116
+ artifactBytes.set(artifactCacheKey(parsed.execution.workspace.archive), workspace.archive);
117
+ }
118
+ if (parsed.knowledge) {
119
+ const knowledge = await verifyWorkspaceSnapshotArtifacts(parsed.knowledge.snapshot, ports.artifacts);
120
+ artifactBytes.set(artifactCacheKey(parsed.knowledge.snapshot.manifest), knowledge.manifest);
121
+ artifactBytes.set(artifactCacheKey(parsed.knowledge.snapshot.archive), knowledge.archive);
122
+ if (parsed.knowledge.retrievalConfig) await readArtifact(parsed.knowledge.retrievalConfig);
123
+ await readArtifact(parsed.knowledge.evaluation);
124
+ }
125
+ if (parsed.memory.mode === "isolated" && parsed.memory.seed) await readArtifact(parsed.memory.seed);
126
+ deepFreezeCandidate(parsed);
127
+ const verified = Object.freeze({
128
+ bundle: parsed,
129
+ ...materializedTree === void 0 ? {} : { materializedTree },
130
+ [verifiedCandidateBrand]: true
131
+ });
132
+ verifiedCandidateState.set(verified, {
133
+ ports,
134
+ artifactBytes,
135
+ resourceBytes
136
+ });
137
+ return verified;
138
+ }
139
+ function getVerifiedCandidateState(candidate) {
140
+ const state = verifiedCandidateState.get(candidate);
141
+ if (!state || candidate[verifiedCandidateBrand] !== true) throw new Error("candidate must come from verifyAgentCandidateBundle");
142
+ return state;
143
+ }
144
+ async function verifiedArtifactBytes(candidate, artifact) {
145
+ const state = getVerifiedCandidateState(candidate);
146
+ const key = artifactCacheKey(artifact);
147
+ const existing = state.artifactBytes.get(key);
148
+ if (existing) return Uint8Array.from(existing);
149
+ const bytes = await readVerifiedArtifact(artifact, state.ports.artifacts);
150
+ state.artifactBytes.set(key, Uint8Array.from(bytes));
151
+ return bytes;
152
+ }
153
+ function verifiedResourceTextByDigest(candidate) {
154
+ const output = /* @__PURE__ */ new Map();
155
+ for (const resource of candidateResources(candidate.bundle)) {
156
+ const bytes = getVerifiedCandidateState(candidate).resourceBytes.get(resource.sha256);
157
+ if (!bytes) throw new Error(`candidate resource digest was not verified: ${resource.sha256}`);
158
+ output.set(resource.sha256, new TextDecoder("utf-8", { fatal: true }).decode(bytes));
159
+ }
160
+ return output;
161
+ }
162
+ function candidateResources(bundle) {
163
+ const resources = bundle.profile.resources;
164
+ if (!resources) return [];
165
+ const output = [];
166
+ for (const mount of resources.files ?? []) output.push(mount.resource);
167
+ output.push(...resources.tools ?? []);
168
+ output.push(...resources.skills ?? []);
169
+ output.push(...resources.agents ?? []);
170
+ output.push(...resources.commands ?? []);
171
+ if (typeof resources.instructions === "object") output.push(resources.instructions);
172
+ return output;
173
+ }
174
+ function resourceKey(resource) {
175
+ return canonicalCandidateDigest$1(resource);
176
+ }
177
+ //#endregion
178
+ //#region src/candidate-execution/knowledge.ts
179
+ /** Environment variable containing the materialized candidate knowledge root. */
180
+ const CANDIDATE_KNOWLEDGE_ROOT_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_ROOT";
181
+ /** Environment variable containing the materialized retrieval configuration path. */
182
+ const CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG";
183
+ /** Deterministic, signed locations used by every candidate executor. */
184
+ function candidateKnowledgeExecutionPaths(taskRoot, hasRetrievalConfig) {
185
+ if (!posix.isAbsolute(taskRoot) || posix.normalize(taskRoot) !== taskRoot) throw new Error("candidate knowledge requires a normalized absolute task root");
186
+ const parent = posix.join(taskRoot, ".tangle");
187
+ return {
188
+ root: posix.join(parent, "knowledge"),
189
+ ...hasRetrievalConfig ? { retrievalConfig: posix.join(parent, "knowledge-retrieval-config.json") } : {}
190
+ };
191
+ }
192
+ /** Verify and detach the exact file-backed knowledge admitted by the bundle. */
193
+ async function prepareAgentCandidateKnowledge(candidate, ports, arm) {
194
+ const knowledge = candidate.bundle.knowledge;
195
+ if (!knowledge) return void 0;
196
+ const archive = await verifiedArtifactBytes(candidate, knowledge.snapshot.archive);
197
+ const retrievalConfig = knowledge.retrievalConfig ? await verifiedArtifactBytes(candidate, knowledge.retrievalConfig) : void 0;
198
+ const root = await mkdtemp(join(tmpdir(), "agent-candidate-knowledge-"));
199
+ try {
200
+ await ports.workspaces.materialize({
201
+ role: "knowledge",
202
+ snapshot: knowledge.snapshot,
203
+ archive,
204
+ destination: root
205
+ });
206
+ const expectedHash = arm === "baseline" ? knowledge.candidate.baseHash : knowledge.candidate.candidateHash;
207
+ const actualHash = `sha256:${await hashKnowledgeBase(root, knowledge.stateScope)}`;
208
+ if (actualHash !== expectedHash) throw new Error(`materialized ${arm} knowledge does not match its measured content: expected ${expectedHash}, got ${actualHash}`);
209
+ const files = await readMaterializedWorkspaceFiles(root, knowledge.snapshot.material);
210
+ return Object.freeze({
211
+ candidate: knowledge.candidate,
212
+ ...knowledge.stateScope ? { stateScope: Object.freeze({ ...knowledge.stateScope }) } : {},
213
+ snapshot: knowledge.snapshot,
214
+ files: Object.freeze(files.map((file) => Object.freeze({
215
+ path: file.path,
216
+ mode: file.mode,
217
+ bytes: Uint8Array.from(file.bytes)
218
+ }))),
219
+ ...retrievalConfig ? { retrievalConfig: Uint8Array.from(retrievalConfig) } : {}
220
+ });
221
+ } finally {
222
+ await rm(root, {
223
+ recursive: true,
224
+ force: true
225
+ });
226
+ }
227
+ }
228
+ //#endregion
229
+ //#region src/candidate-execution/exact-process-executor.ts
230
+ const DEFAULT_PROVISION_TIMEOUT_MS = 12e4;
231
+ const DEFAULT_RECOVERY_RETENTION_MS = 15 * 6e4;
232
+ /** Adapt one neutral exact-process provider to Runtime's trusted candidate boundary. */
233
+ function exactProcessProviderAsCandidateExecutor(options) {
234
+ return new ExactProcessAgentCandidateExecutor(options);
235
+ }
236
+ var ExactProcessAgentCandidateExecutor = class {
237
+ options;
238
+ states = /* @__PURE__ */ new Map();
239
+ exactProcess;
240
+ resources;
241
+ provisionTimeoutMs;
242
+ recoveryRetentionMs;
243
+ providerOptions;
244
+ capabilitiesPromise;
245
+ constructor(options) {
246
+ this.options = options;
247
+ if (!options.provider.exactProcess) throw new Error(`agent environment provider "${options.provider.name}" does not implement exact processes`);
248
+ this.exactProcess = options.provider.exactProcess;
249
+ this.resources = exactResources(options.resources);
250
+ this.provisionTimeoutMs = positiveInteger(options.provisionTimeoutMs ?? DEFAULT_PROVISION_TIMEOUT_MS, "exact process provision timeout");
251
+ this.recoveryRetentionMs = positiveInteger(options.recoveryRetentionMs ?? DEFAULT_RECOVERY_RETENTION_MS, "exact process recovery retention");
252
+ this.providerOptions = options.providerOptions ? immutableCandidateValue(options.providerOptions) : void 0;
253
+ }
254
+ async execute(request, context) {
255
+ assertSupportedRequest(request);
256
+ const outcome = request.benchmark.task.outcome;
257
+ if (outcome.kind !== "output") throw new Error("exact process executor requires an output task");
258
+ const network = request.executionPlan.value.material.model.access.network;
259
+ const egress = network.mode === "disabled" ? { mode: "blocked" } : {
260
+ mode: "strict",
261
+ allowDomains: [...network.domains]
262
+ };
263
+ await this.assertCapability(egress.mode);
264
+ context.signal.throwIfAborted();
265
+ const key = executionKey(request.executionId, request.executionPlan.value.digest);
266
+ if (this.states.has(key)) throw new Error("candidate execution environment is already active");
267
+ const image = exactImage(request.executionPlan.value.material.container.image, request.executionPlan.value.material.container.manifestDigest);
268
+ const maxLifetimeMs = environmentLifetimeMs(request.hardLimits.timeoutMs, this.recoveryRetentionMs);
269
+ const createInputDigest = canonicalCandidateDigest$1(immutableCandidateValue({
270
+ kind: "agent-candidate-exact-process-create",
271
+ provider: this.options.provider.name,
272
+ executionId: request.executionId,
273
+ executionPlanDigest: request.executionPlan.value.digest,
274
+ image,
275
+ egress,
276
+ maxLifetimeMs,
277
+ provisionTimeoutMs: this.provisionTimeoutMs,
278
+ resources: this.resources,
279
+ output: {
280
+ mediaType: outcome.mediaType,
281
+ maxBytes: outcome.maxBytes
282
+ },
283
+ ...this.providerOptions ? { providerOptions: this.providerOptions } : {}
284
+ }));
285
+ const metadata = immutableCandidateValue({
286
+ kind: "agent-candidate-execution",
287
+ provider: this.options.provider.name,
288
+ executionId: request.executionId,
289
+ executionPlanDigest: request.executionPlan.value.digest,
290
+ createInputDigest,
291
+ outputMediaType: outcome.mediaType,
292
+ outputMaxBytes: outcome.maxBytes
293
+ });
294
+ const environment = await this.exactProcess.create({
295
+ image,
296
+ egress,
297
+ maxLifetimeMs,
298
+ provisionTimeoutMs: this.provisionTimeoutMs,
299
+ resources: this.resources,
300
+ metadata,
301
+ idempotencyKey: executionIdempotencyKey(request.executionId, request.executionPlan.value.digest),
302
+ signal: context.signal,
303
+ ...this.providerOptions ? { providerOptions: this.providerOptions } : {}
304
+ });
305
+ try {
306
+ assertExecutionEnvironment(environment, metadata, this.options.provider.name);
307
+ } catch (error) {
308
+ try {
309
+ await environment.destroy();
310
+ } catch (cleanupError) {
311
+ throw new AggregateError([error, cleanupError], "exact process validation and cleanup both failed");
312
+ }
313
+ throw error;
314
+ }
315
+ const state = { environment };
316
+ this.states.set(key, state);
317
+ if ((await environment.process.list()).length !== 0) throw new Error("fresh candidate environment already contains a process");
318
+ await materializeRequest(environment, request, context.signal);
319
+ const launch = exactLaunch(request);
320
+ const startedAt = Date.now();
321
+ state.trace = {
322
+ runId: request.trace.runId,
323
+ scenarioId: request.benchmark.task.scenario.id,
324
+ startedAt,
325
+ deadlineAtMs: context.deadlineAtMs,
326
+ timeoutMs: request.hardLimits.timeoutMs,
327
+ tags: {
328
+ ...request.trace.tags,
329
+ environmentId: environment.id,
330
+ environmentProvider: environment.provider
331
+ },
332
+ written: false
333
+ };
334
+ const process = await environment.process.spawn(launch, { signal: context.signal });
335
+ const outputPromise = collectOutput(process, outcome.maxBytes);
336
+ outputPromise.catch(() => void 0);
337
+ let cancellation;
338
+ let processExited = false;
339
+ const cancel = () => {
340
+ if (!processExited) cancellation ??= stopProcess(process);
341
+ };
342
+ context.signal.addEventListener("abort", cancel, { once: true });
343
+ if (context.signal.aborted) cancel();
344
+ try {
345
+ const termination = await process.wait();
346
+ processExited = true;
347
+ context.signal.removeEventListener("abort", cancel);
348
+ if (cancellation) await cancellation;
349
+ const status = await process.status();
350
+ assertTerminalStatus(status, termination);
351
+ state.output = await awaitOutput(outputPromise, context.signal, context.deadlineAtMs);
352
+ state.termination = termination;
353
+ await appendExactProcessTrace(state, context.traceStore, status);
354
+ return {
355
+ executionId: request.executionId,
356
+ termination
357
+ };
358
+ } finally {
359
+ context.signal.removeEventListener("abort", cancel);
360
+ }
361
+ }
362
+ async stop(request, context) {
363
+ await this.assertCapability();
364
+ context.signal.throwIfAborted();
365
+ const environment = await this.resolve(request, true);
366
+ if (!environment) return { stopped: true };
367
+ let statuses = await environment.process.list();
368
+ if (statuses.length > 1) throw new Error("candidate exact process environment contains more than one process");
369
+ const status = statuses[0];
370
+ if (status?.running) {
371
+ const process = await environment.process.get(status.pid);
372
+ if (!process) throw new Error("candidate environment lost its running process handle");
373
+ await stopProcess(process);
374
+ }
375
+ context.signal.throwIfAborted();
376
+ statuses = await environment.process.list();
377
+ if (statuses.some((entry) => entry.running)) throw new Error("candidate exact process termination is not proven");
378
+ const finalStatus = statuses[0];
379
+ if (finalStatus) assertTerminalStatus(finalStatus);
380
+ const state = this.states.get(executionKey(request.executionId, request.executionPlanDigest));
381
+ if (state) {
382
+ state.termination = finalStatus?.termination ?? state.termination;
383
+ if (context.reason === "timeout" && state.trace) state.runtimeTermination = {
384
+ kind: "timeout",
385
+ timeoutMs: state.trace.timeoutMs
386
+ };
387
+ await appendExactProcessTrace(state, context.traceStore, finalStatus);
388
+ }
389
+ return { stopped: true };
390
+ }
391
+ async capture(request, context) {
392
+ await this.assertCapability();
393
+ context.signal.throwIfAborted();
394
+ const environment = await this.resolve(request, false);
395
+ const statuses = await environment.process.list();
396
+ const status = statuses[0];
397
+ if (statuses.length !== 1 || !status || status.running) throw new Error("candidate environment must contain one stopped process before capture");
398
+ assertTerminalStatus(status);
399
+ const process = await environment.process.get(status.pid);
400
+ if (!process) throw new Error("candidate environment lost its captured process handle");
401
+ assertTerminalStatus(await process.status(), status.termination);
402
+ const state = this.states.get(executionKey(request.executionId, request.executionPlanDigest));
403
+ const output = state?.output ?? await awaitOutput(collectOutput(process, outputSpec(environment).maxBytes), context.signal, Date.now() + this.provisionTimeoutMs);
404
+ context.signal.throwIfAborted();
405
+ const evidence = canonicalCandidateBytes$1({
406
+ kind: "agent-candidate-exact-process-capture",
407
+ provider: environment.provider,
408
+ environmentId: environment.id,
409
+ executionId: request.executionId,
410
+ executionPlanDigest: request.executionPlanDigest,
411
+ createInputDigest: environment.metadata?.createInputDigest,
412
+ process: {
413
+ pid: status.pid,
414
+ exitCode: status.exitCode,
415
+ ...status.exitSignal ? { exitSignal: status.exitSignal } : {},
416
+ termination: status.termination
417
+ },
418
+ ...state?.runtimeTermination ? { runtimeTermination: state.runtimeTermination } : {},
419
+ output: {
420
+ sha256: sha256Bytes$1(output),
421
+ byteLength: output.byteLength
422
+ }
423
+ });
424
+ return {
425
+ taskOutcome: {
426
+ kind: "output",
427
+ bytes: output
428
+ },
429
+ evidence
430
+ };
431
+ }
432
+ async dispose(request, context) {
433
+ await this.assertCapability();
434
+ context.signal.throwIfAborted();
435
+ const environment = await this.resolve(request, true);
436
+ if (!environment) return { disposed: true };
437
+ let destroyError;
438
+ try {
439
+ await environment.destroy();
440
+ } catch (error) {
441
+ destroyError = error;
442
+ }
443
+ if (await this.exactProcess.get(environment.id)) throw new Error("exact process environment disposal is not proven", { cause: destroyError });
444
+ context.signal.throwIfAborted();
445
+ this.states.delete(executionKey(request.executionId, request.executionPlanDigest));
446
+ return { disposed: true };
447
+ }
448
+ async assertCapability(mode) {
449
+ const pending = this.capabilitiesPromise ?? Promise.resolve(this.options.provider.capabilities());
450
+ this.capabilitiesPromise = pending;
451
+ let capabilities;
452
+ try {
453
+ capabilities = await pending;
454
+ } catch (error) {
455
+ if (this.capabilitiesPromise === pending) this.capabilitiesPromise = void 0;
456
+ throw error;
457
+ }
458
+ const exact = capabilities.exactProcess;
459
+ if (!exact) throw new Error(`agent environment provider "${this.options.provider.name}" does not declare exact process support`);
460
+ if (mode && !exact.egress.includes(mode)) throw new Error(`agent environment provider "${this.options.provider.name}" does not declare ${mode} exact egress`);
461
+ }
462
+ async resolve(request, missingIsDeleted) {
463
+ const key = executionKey(request.executionId, request.executionPlanDigest);
464
+ const active = this.states.get(key)?.environment;
465
+ if (active) return active;
466
+ const metadata = {
467
+ kind: "agent-candidate-execution",
468
+ provider: this.options.provider.name,
469
+ executionId: request.executionId,
470
+ executionPlanDigest: request.executionPlanDigest
471
+ };
472
+ const matches = (await this.exactProcess.list({
473
+ metadata,
474
+ ...this.providerOptions ? { providerOptions: this.providerOptions } : {}
475
+ })).filter((environment) => environment.provider === this.options.provider.name && Object.entries(metadata).every(([name, value]) => isDeepStrictEqual(environment.metadata?.[name], value)));
476
+ if (matches.length > 1) throw new Error("multiple exact process environments match one candidate execution");
477
+ const environment = matches[0];
478
+ if (!environment) {
479
+ if (missingIsDeleted) return void 0;
480
+ throw new Error("candidate exact process evidence is unavailable");
481
+ }
482
+ if (!isSha256Digest$1(environment.metadata?.createInputDigest)) throw new Error("candidate exact process create-input digest is unavailable");
483
+ this.states.set(key, { environment });
484
+ return environment;
485
+ }
486
+ };
487
+ async function appendExactProcessTrace(state, traceStore, status) {
488
+ const trace = state.trace;
489
+ if (!trace || trace.written) return;
490
+ const endedAt = Math.max(trace.startedAt, Math.min(Date.now(), trace.deadlineAtMs));
491
+ const termination = state.runtimeTermination ?? state.termination ?? status?.termination;
492
+ await traceStore.appendRun({
493
+ runId: trace.runId,
494
+ scenarioId: trace.scenarioId,
495
+ startedAt: trace.startedAt,
496
+ endedAt,
497
+ status: termination?.kind === "exit" && termination.exitCode === 0 ? "completed" : "failed",
498
+ tags: trace.tags
499
+ });
500
+ trace.written = true;
501
+ }
502
+ function assertSupportedRequest(request) {
503
+ if (request.benchmark.task.outcome.kind !== "output") throw new Error("exact process candidate executor does not support workspace outcomes; use Pier");
504
+ if (request.executionPlan.value.material.codeKind !== "disabled" || request.inputs.candidate) throw new Error("exact process candidate executor does not support code workspaces; use Pier");
505
+ if (request.memory.mode !== "disabled") throw new Error("exact process candidate executor does not support isolated memory");
506
+ const mediaType = request.benchmark.task.outcome.mediaType.toLowerCase();
507
+ if (!(mediaType.startsWith("text/") || mediaType === "application/json" || mediaType.endsWith("+json"))) throw new Error("exact process candidate executor supports only UTF-8 text and JSON outputs");
508
+ if (!posix.isAbsolute(request.launch.executable) && !request.launch.env.PATH?.trim()) throw new Error("exact process candidate executable must be absolute or declare a signed PATH");
509
+ if (!request.roots) throw new Error("candidate execution roots are missing");
510
+ assertAgentCandidateExecutionRoots(request.roots);
511
+ }
512
+ async function materializeRequest(environment, request, signal) {
513
+ assertAgentCandidateExecutionRoots(request.roots);
514
+ const knowledgePaths = assertKnowledgeExecutionBinding(request);
515
+ for (const file of request.inputs.task.files) await environment.writeFile(beneath(request.roots.taskRoot, file.path), file.bytes, {
516
+ mode: file.mode,
517
+ signal
518
+ });
519
+ for (const file of request.inputs.profile.files) await environment.writeFile(profileFileExecutionPath(request, file), file.bytes, {
520
+ mode: file.mode,
521
+ signal
522
+ });
523
+ if (request.knowledge && knowledgePaths) {
524
+ for (const file of request.knowledge.files) await environment.writeFile(beneath(knowledgePaths.root, file.path), file.bytes, {
525
+ mode: file.mode,
526
+ signal
527
+ });
528
+ if (request.knowledge.retrievalConfig && knowledgePaths.retrievalConfig) await environment.writeFile(knowledgePaths.retrievalConfig, request.knowledge.retrievalConfig, {
529
+ mode: 420,
530
+ signal
531
+ });
532
+ }
533
+ if (request.instruction.delivery.kind === "utf8-file") await environment.writeFile(request.instruction.delivery.path, request.instruction.bytes, {
534
+ mode: 420,
535
+ signal
536
+ });
537
+ }
538
+ function assertKnowledgeExecutionBinding(request) {
539
+ const knowledge = request.knowledge;
540
+ if (!knowledge) {
541
+ if (request.launch.env["TANGLE_CANDIDATE_KNOWLEDGE_ROOT"] !== void 0 || request.launch.env["TANGLE_CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG"] !== void 0) throw new Error("candidate launch declares knowledge paths without verified knowledge");
542
+ return;
543
+ }
544
+ const paths = candidateKnowledgeExecutionPaths(request.roots.taskRoot, knowledge.retrievalConfig !== void 0);
545
+ if (request.launch.env["TANGLE_CANDIDATE_KNOWLEDGE_ROOT"] !== paths.root || request.launch.env["TANGLE_CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG"] !== paths.retrievalConfig) throw new Error("candidate knowledge paths do not match the signed launch environment");
546
+ const reserved = [paths.root, paths.retrievalConfig].filter((value) => value !== void 0);
547
+ if ([
548
+ ...request.inputs.task.files.map((file) => beneath(request.roots.taskRoot, file.path)),
549
+ ...request.inputs.profile.files.map((file) => profileFileExecutionPath(request, file)),
550
+ ...request.instruction.delivery.kind === "utf8-file" ? [request.instruction.delivery.path] : []
551
+ ].some((path) => reserved.some((reservedPath) => path === reservedPath || path.startsWith(`${reservedPath}/`) || reservedPath.startsWith(`${path}/`)))) throw new Error("candidate knowledge paths overlap other execution inputs");
552
+ return paths;
553
+ }
554
+ function profileFileExecutionPath(request, file) {
555
+ const workspaceRoot = request.executionPlan.value.material.profile.targetWorkspace === "task" ? request.roots.taskRoot : request.roots.candidateRoot;
556
+ if (!workspaceRoot) throw new Error("candidate profile targets a missing workspace");
557
+ if (file.root !== "agent") return beneath(workspaceRoot, file.path);
558
+ return beneath(profileAgentDirectory(request), file.path);
559
+ }
560
+ function profileAgentDirectory(request) {
561
+ const paths = candidateProfileAgentPaths(request.profilePlan.value.material, request.roots.profileRoot);
562
+ if (!paths) throw new Error("candidate profile agent-root file is missing its private root");
563
+ if (request.launch.env["PI_CODING_AGENT_DIR"] !== paths.agentDir || request.launch.env["PI_CODING_AGENT_SESSION_DIR"] !== paths.sessionDir) throw new Error("candidate Pi agent-root files do not match the signed launch environment");
564
+ return paths.agentDir;
565
+ }
566
+ function exactLaunch(request) {
567
+ const instruction = new TextDecoder("utf-8", { fatal: true }).decode(request.instruction.bytes);
568
+ const base = {
569
+ executable: request.launch.executable,
570
+ args: request.launch.args,
571
+ cwd: request.launch.cwd,
572
+ env: request.launch.env,
573
+ timeoutMs: 0
574
+ };
575
+ switch (request.instruction.delivery.kind) {
576
+ case "argv-append": return {
577
+ ...base,
578
+ args: [...base.args, instruction]
579
+ };
580
+ case "stdin-utf8": return {
581
+ ...base,
582
+ stdin: instruction
583
+ };
584
+ case "utf8-file": return base;
585
+ }
586
+ }
587
+ async function collectOutput(process, maxBytes) {
588
+ const chunks = [];
589
+ let byteLength = 0;
590
+ for await (const chunk of process.stdout()) {
591
+ const bytes = Buffer.from(chunk, "utf8");
592
+ byteLength += bytes.byteLength;
593
+ if (byteLength > maxBytes) {
594
+ let stopError;
595
+ try {
596
+ await stopProcess(process);
597
+ } catch (error) {
598
+ stopError = error;
599
+ }
600
+ throw new Error(`candidate output exceeds its ${maxBytes}-byte maximum`, { cause: stopError });
601
+ }
602
+ chunks.push(bytes);
603
+ }
604
+ return Uint8Array.from(Buffer.concat(chunks, byteLength));
605
+ }
606
+ async function awaitOutput(output, signal, deadlineAtMs) {
607
+ signal.throwIfAborted();
608
+ const remainingMs = deadlineAtMs - Date.now();
609
+ if (remainingMs <= 0) throw new Error("candidate output deadline expired");
610
+ let timer;
611
+ let onAbort;
612
+ try {
613
+ return await Promise.race([output, new Promise((_resolve, reject) => {
614
+ onAbort = () => reject(signal.reason ?? /* @__PURE__ */ new Error("candidate output cancelled"));
615
+ signal.addEventListener("abort", onAbort, { once: true });
616
+ timer = setTimeout(() => reject(/* @__PURE__ */ new Error("candidate output deadline expired")), remainingMs);
617
+ })]);
618
+ } finally {
619
+ if (onAbort) signal.removeEventListener("abort", onAbort);
620
+ if (timer) clearTimeout(timer);
621
+ }
622
+ }
623
+ async function stopProcess(process) {
624
+ if (!(await process.status()).running) return;
625
+ try {
626
+ await process.kill();
627
+ } catch (error) {
628
+ if ((await process.status()).running) throw error;
629
+ }
630
+ const termination = await process.wait();
631
+ assertTerminalStatus(await process.status(), termination);
632
+ }
633
+ function assertTerminalStatus(status, expected) {
634
+ if (status.running || !status.termination) throw new Error("exact process returned no terminal reason after exit");
635
+ if (expected && !isDeepStrictEqual(status.termination, expected)) throw new Error("exact process wait and status returned different terminal reasons");
636
+ }
637
+ function assertExecutionEnvironment(environment, metadata, providerName) {
638
+ if (!environment.id || environment.provider !== providerName) throw new Error("exact process provider returned the wrong environment identity");
639
+ if (!Object.entries(metadata).every(([name, value]) => isDeepStrictEqual(environment.metadata?.[name], value))) throw new Error("exact process provider did not persist candidate execution metadata");
640
+ }
641
+ function outputSpec(environment) {
642
+ const maxBytes = environment.metadata?.outputMaxBytes;
643
+ if (!Number.isSafeInteger(maxBytes) || Number(maxBytes) < 1) throw new Error("candidate exact process output bound is unavailable");
644
+ return { maxBytes: Number(maxBytes) };
645
+ }
646
+ function executionKey(executionId, executionPlanDigest) {
647
+ return `${executionId}\0${executionPlanDigest}`;
648
+ }
649
+ function executionIdempotencyKey(executionId, executionPlanDigest) {
650
+ return `candidate-${canonicalCandidateDigest$1({
651
+ kind: "agent-candidate-execution-identity",
652
+ executionId,
653
+ executionPlanDigest
654
+ }).slice(7)}`;
655
+ }
656
+ function exactImage(image, manifestDigest) {
657
+ if (isSha256Digest$1(image)) {
658
+ if (image !== manifestDigest) throw new Error("candidate container image conflicts with its resolved manifest");
659
+ return image;
660
+ }
661
+ const marker = image.lastIndexOf("@");
662
+ if (marker < 0) return `${image}@${manifestDigest}`;
663
+ if (image.slice(marker + 1) !== manifestDigest) throw new Error("candidate container image conflicts with its resolved manifest");
664
+ return image;
665
+ }
666
+ function environmentLifetimeMs(timeoutMs, retentionMs) {
667
+ const total = positiveInteger(timeoutMs, "candidate execution timeout") + retentionMs;
668
+ if (!Number.isSafeInteger(total)) throw new Error("candidate environment lifetime is too large");
669
+ return Math.ceil(total / 1e3) * 1e3;
670
+ }
671
+ function exactResources(resources) {
672
+ if (!Number.isFinite(resources.cpu) || resources.cpu <= 0) throw new Error("exact process CPU must be positive and finite");
673
+ return Object.freeze({
674
+ cpu: resources.cpu,
675
+ memoryMb: positiveInteger(resources.memoryMb, "exact process memory"),
676
+ diskMb: positiveInteger(resources.diskMb, "exact process disk")
677
+ });
678
+ }
679
+ function positiveInteger(value, label) {
680
+ if (!Number.isSafeInteger(value) || value < 1) throw new Error(`${label} must be a positive integer`);
681
+ return value;
682
+ }
683
+ function beneath(root, relativePath) {
684
+ if (posix.isAbsolute(relativePath)) throw new Error("candidate input path must be relative");
685
+ const path = posix.normalize(relativePath);
686
+ if (path === ".." || path.startsWith("../")) throw new Error("candidate input path escapes its execution root");
687
+ return posix.join(root, path);
688
+ }
689
+ function isSha256Digest$1(value) {
690
+ return typeof value === "string" && /^sha256:[a-f0-9]{64}$/.test(value);
691
+ }
692
+ //#endregion
693
+ //#region src/candidate-execution/model-settlement.ts
694
+ const USD_NANOS = 1e9;
695
+ /** Validate and detach the evaluator gateway's terminal, revoked call ledger. */
696
+ function sealAgentCandidateModelSettlement(settlement, expected) {
697
+ assertExactObjectKeys(settlement, [
698
+ "preparationId",
699
+ "grantDigest",
700
+ "closed",
701
+ "usageWithinLimits",
702
+ "calls"
703
+ ], "model settlement");
704
+ if (settlement.closed !== true) throw new Error("protected model grant is not closed");
705
+ if (settlement.usageWithinLimits !== true) throw new Error("protected model settlement reports usage outside frozen limits");
706
+ if (settlement.grantDigest !== expected.grantDigest) throw new Error("protected model settlement grant digest does not match the reservation");
707
+ if (settlement.preparationId !== expected.preparationId) throw new Error("protected model settlement preparation does not match the reservation");
708
+ if (!Array.isArray(settlement.calls)) throw new Error("protected model settlement calls must be an array");
709
+ const callIds = /* @__PURE__ */ new Set();
710
+ const spanIds = /* @__PURE__ */ new Set();
711
+ let accountedInputTokens = 0;
712
+ let outputTokens = 0;
713
+ let cachedInputTokens = 0;
714
+ let reasoningTokens = 0;
715
+ let costUsdNanos = 0;
716
+ let costProvenance = "observed";
717
+ const calls = settlement.calls.map((source, index) => {
718
+ assertExactObjectKeys(source, [
719
+ "callId",
720
+ "generationId",
721
+ "traceSpanId",
722
+ "status",
723
+ "model",
724
+ "startedAtMs",
725
+ "endedAtMs",
726
+ "inputTokens",
727
+ "accountedInputTokens",
728
+ "outputTokens",
729
+ "cachedInputTokens",
730
+ "reasoningTokens",
731
+ "costUsdNanos",
732
+ "costProvenance"
733
+ ], `model settlement call ${index}`);
734
+ assertIdentifier(source.callId, `model settlement call ${index} callId`);
735
+ assertIdentifier(source.generationId, `model settlement call ${index} generationId`);
736
+ assertIdentifier(source.traceSpanId, `model settlement call ${index} traceSpanId`);
737
+ if (source.traceSpanId !== source.generationId) throw new Error(`model settlement call ${index} traceSpanId is not its router generationId`);
738
+ if (source.status !== "succeeded" && source.status !== "failed") throw new Error(`model settlement call ${index} has an invalid status`);
739
+ if (callIds.has(source.callId)) throw new Error("protected model settlement has duplicate call ids");
740
+ if (spanIds.has(source.traceSpanId)) throw new Error("protected model settlement has duplicate trace span ids");
741
+ callIds.add(source.callId);
742
+ spanIds.add(source.traceSpanId);
743
+ if (source.model !== expected.model) throw new Error(`protected model settlement call ${index} has an unexpected model`);
744
+ assertTimestamp(source.startedAtMs, `model settlement call ${index} startedAtMs`);
745
+ assertTimestamp(source.endedAtMs, `model settlement call ${index} endedAtMs`);
746
+ if (source.endedAtMs < source.startedAtMs) throw new Error(`model settlement call ${index} ended before it started`);
747
+ assertCount$1(source.inputTokens, `model settlement call ${index} inputTokens`);
748
+ assertCount$1(source.accountedInputTokens, `model settlement call ${index} accountedInputTokens`);
749
+ if (source.accountedInputTokens < source.inputTokens) throw new Error(`model settlement call ${index} accountedInputTokens cannot be less than inputTokens`);
750
+ assertCount$1(source.outputTokens, `model settlement call ${index} outputTokens`);
751
+ assertCount$1(source.cachedInputTokens, `model settlement call ${index} cachedInputTokens`);
752
+ cachedInputTokens = safeAdd(cachedInputTokens, source.cachedInputTokens, "cached input token total");
753
+ assertCount$1(source.reasoningTokens, `model settlement call ${index} reasoningTokens`);
754
+ reasoningTokens = safeAdd(reasoningTokens, source.reasoningTokens, "reasoning token total");
755
+ assertCount$1(source.costUsdNanos, `model settlement call ${index} costUsdNanos`);
756
+ if (source.costProvenance !== "observed" && source.costProvenance !== "estimated") throw new Error(`model settlement call ${index} has an invalid cost provenance`);
757
+ if (source.costProvenance === "estimated") costProvenance = "estimated";
758
+ accountedInputTokens = safeAdd(accountedInputTokens, source.accountedInputTokens, "accounted input token total");
759
+ outputTokens = safeAdd(outputTokens, source.outputTokens, "output token total");
760
+ costUsdNanos = safeAdd(costUsdNanos, source.costUsdNanos, "cost total");
761
+ return Object.freeze({ ...source });
762
+ });
763
+ const usage = Object.freeze({
764
+ costUsdNanos,
765
+ inputTokens: accountedInputTokens,
766
+ outputTokens,
767
+ cachedInputTokens,
768
+ reasoningTokens,
769
+ modelCalls: calls.length,
770
+ costProvenance
771
+ });
772
+ return Object.freeze({
773
+ value: Object.freeze({
774
+ preparationId: settlement.preparationId,
775
+ grantDigest: settlement.grantDigest,
776
+ closed: true,
777
+ usageWithinLimits: true,
778
+ calls: Object.freeze(calls)
779
+ }),
780
+ usage
781
+ });
782
+ }
783
+ /**
784
+ * Append the only accepted LLM spans from the router's closed ledger.
785
+ * Candidate and executor code may write tool/process spans, but never model usage.
786
+ */
787
+ async function appendAuthoritativeModelSettlementSpans(traceStore, runId, settlement) {
788
+ const run = await traceStore.getRun(runId);
789
+ if (!run) throw new Error(`protected trace run is missing before model settlement: ${runId}`);
790
+ if (run.status === "running" || run.endedAt === void 0) throw new Error("protected trace run must be terminal before model spans are appended");
791
+ const existing = await traceStore.spans({ runId });
792
+ if (existing.some(isLlmSpan)) throw new Error("protected trace contains a model span not authored from the closed router ledger");
793
+ const occupiedIds = new Set(existing.map((span) => span.spanId));
794
+ for (const call of settlement.value.calls) {
795
+ if (occupiedIds.has(call.traceSpanId)) throw new Error(`protected trace span identity collides with router generation ${call.generationId}`);
796
+ await traceStore.appendSpan({
797
+ runId,
798
+ spanId: call.traceSpanId,
799
+ kind: "llm",
800
+ name: "protected model call",
801
+ model: call.model,
802
+ messages: [],
803
+ startedAt: call.startedAtMs,
804
+ endedAt: call.endedAtMs,
805
+ status: call.status === "succeeded" ? "ok" : "error",
806
+ inputTokens: call.inputTokens,
807
+ outputTokens: call.outputTokens,
808
+ cachedTokens: call.cachedInputTokens,
809
+ reasoningTokens: call.reasoningTokens,
810
+ costUsd: call.costUsdNanos / USD_NANOS,
811
+ attributes: {
812
+ "tangle.protected_model.source": "router-settlement",
813
+ "tangle.router.call_id": call.callId,
814
+ "tangle.router.generation_id": call.generationId
815
+ }
816
+ });
817
+ }
818
+ }
819
+ /** Match every protected trace span one-for-one against gateway call evidence. */
820
+ function assertTraceMatchesModelSettlement(spans, settlement) {
821
+ if (spans.length !== settlement.value.calls.length) throw new Error(`protected trace model calls ${spans.length} do not match model ledger ${settlement.value.calls.length}`);
822
+ const byId = new Map(spans.map((span) => [span.spanId, span]));
823
+ if (byId.size !== spans.length) throw new Error("protected trace has duplicate model span ids");
824
+ for (const call of settlement.value.calls) {
825
+ const span = byId.get(call.traceSpanId);
826
+ if (!span) throw new Error(`protected trace is missing model ledger span ${call.traceSpanId}`);
827
+ assertTraceCall(span, call);
828
+ }
829
+ }
830
+ function usdToNanos(value, label) {
831
+ if (!Number.isFinite(value) || value < 0) throw new Error(`${label} must be nonnegative`);
832
+ const nanos = Math.round(value * USD_NANOS);
833
+ if (!Number.isSafeInteger(nanos)) throw new Error(`${label} exceeds fixed-point range`);
834
+ return nanos;
835
+ }
836
+ function assertTraceCall(span, call) {
837
+ if (span.model !== call.model) throw new Error(`protected trace span ${span.spanId} model does not match model ledger`);
838
+ if (span.startedAt !== call.startedAtMs || span.endedAt !== call.endedAtMs || span.status !== (call.status === "succeeded" ? "ok" : "error")) throw new Error(`protected trace span ${span.spanId} timing or status does not match model ledger`);
839
+ if (span.attributes?.["tangle.protected_model.source"] !== "router-settlement" || span.attributes?.["tangle.router.call_id"] !== call.callId || span.attributes?.["tangle.router.generation_id"] !== call.generationId) throw new Error(`protected trace span ${span.spanId} lacks router settlement provenance`);
840
+ for (const [name, traced, settled] of [
841
+ [
842
+ "inputTokens",
843
+ span.inputTokens,
844
+ call.inputTokens
845
+ ],
846
+ [
847
+ "outputTokens",
848
+ span.outputTokens,
849
+ call.outputTokens
850
+ ],
851
+ [
852
+ "cachedInputTokens",
853
+ span.cachedTokens ?? 0,
854
+ call.cachedInputTokens
855
+ ],
856
+ [
857
+ "reasoningTokens",
858
+ span.reasoningTokens ?? 0,
859
+ call.reasoningTokens
860
+ ]
861
+ ]) if (traced === void 0 || traced !== settled) throw new Error(`protected trace span ${span.spanId} ${name} ${traced} does not match model ledger ${settled}`);
862
+ if (span.costUsd === void 0) throw new Error(`protected trace span ${span.spanId} is missing costUsd`);
863
+ const tracedCost = usdToNanos(span.costUsd, `protected trace span ${span.spanId} costUsd`);
864
+ if (tracedCost !== call.costUsdNanos) throw new Error(`protected trace span ${span.spanId} costUsdNanos ${tracedCost} does not match model ledger ${call.costUsdNanos}`);
865
+ }
866
+ function assertIdentifier(value, label) {
867
+ if (typeof value !== "string" || value.length === 0 || value.length > 256) throw new Error(`${label} must be a non-empty bounded string`);
868
+ }
869
+ function assertCount$1(value, label) {
870
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${label} must be a nonnegative safe integer`);
871
+ }
872
+ function assertTimestamp(value, label) {
873
+ if (!Number.isSafeInteger(value) || value <= 0) throw new Error(`${label} must be a positive safe integer`);
874
+ }
875
+ function safeAdd(left, right, label) {
876
+ const total = left + right;
877
+ if (!Number.isSafeInteger(total)) throw new Error(`${label} exceeds safe integer range`);
878
+ return total;
879
+ }
880
+ //#endregion
881
+ //#region src/candidate-execution/protected-model-port.ts
882
+ const MAX_RECENT_SETTLEMENTS = 4096;
883
+ const RECOVERED_SETTLEMENT_RETENTION_MS = 900 * 1e3;
884
+ /**
885
+ * Bind a protected model-grant service to the immutable candidate runtime.
886
+ *
887
+ * The service remains the authority for expiry, admission, revocation, and
888
+ * metering. This adapter independently checks every response before allowing
889
+ * it to cross into candidate execution or durable receipt finalization.
890
+ */
891
+ function createProtectedAgentCandidateModelPort(options) {
892
+ const gatewayDomain = assertGatewayDomain(options.gatewayDomain);
893
+ const activationEnvNames = exactEnvironmentNames(options.activationEnvNames);
894
+ const reservations = /* @__PURE__ */ new Map();
895
+ const expiredReservations = /* @__PURE__ */ new Map();
896
+ const recentSettlements = /* @__PURE__ */ new Map();
897
+ return {
898
+ resolve: async (input) => {
899
+ const request = immutableCandidateValue(input);
900
+ return immutableCandidateValue(validateResolvedModel(await options.resolveModel(request), request));
901
+ },
902
+ reserveGrant: async (input) => {
903
+ pruneExpiredState(reservations, expiredReservations, recentSettlements, Date.now());
904
+ const request = immutableCandidateValue(input);
905
+ validateReserveInput(request);
906
+ const requestDigest = canonicalCandidateDigest$1(request);
907
+ const key = reservationKey(request.executionId, request.preparationId);
908
+ if (recentSettlements.has(key)) throw new Error("protected model reservation is already settled");
909
+ if (expiredReservations.get(key)) throw new Error("protected model reservation has expired");
910
+ const previous = reservations.get(key);
911
+ if (previous && previous.requestDigest !== requestDigest) throw new Error("protected model reservation retry changed immutable input");
912
+ const reservation = validateReservation(await options.client.reserve(request), request, gatewayDomain);
913
+ const responseDigest = canonicalCandidateDigest$1(reservation);
914
+ if (recentSettlements.has(key)) throw new Error("protected model reservation completed after the grant was settled");
915
+ const recorded = previous ?? reservations.get(key);
916
+ if (recorded && recorded.requestDigest !== requestDigest) throw new Error("protected model reservation retry changed immutable input");
917
+ if (recorded && recorded.responseDigest !== responseDigest) throw new Error("protected model reservation retry returned different evidence");
918
+ if (!recorded) reservations.set(key, {
919
+ requestDigest,
920
+ responseDigest,
921
+ executionId: request.executionId,
922
+ preparationId: request.preparationId,
923
+ grantDigest: reservation.digest,
924
+ expiresAtMs: request.expiresAtMs,
925
+ resolved: immutableCandidateValue(request.resolved),
926
+ limits: immutableCandidateValue(request.limits),
927
+ maxCostUsdNanos: usdToNanos(request.limits.maxCostUsd, "reserved maxCostUsd"),
928
+ activation: "reserved"
929
+ });
930
+ return reservation;
931
+ },
932
+ activateGrant: async (input) => {
933
+ pruneExpiredState(reservations, expiredReservations, recentSettlements, Date.now());
934
+ const request = immutableCandidateValue(input);
935
+ const key = reservationKey(request.executionId, request.preparationId);
936
+ if (recentSettlements.has(key)) throw new Error("protected model grant is already settled");
937
+ const state = reservations.get(key);
938
+ if (!state && expiredReservations.has(key)) throw new Error("protected model grant reservation has expired");
939
+ if (!state) throw new Error("protected model grant was not reserved by this port");
940
+ assertGrantIdentity(state, request);
941
+ if (state.settlementDigest) throw new Error("protected model grant is already settled");
942
+ if (state.activation !== "reserved") throw new Error("protected model grant activation is single-use");
943
+ if (!Number.isSafeInteger(request.deadlineAtMs) || request.deadlineAtMs <= 0) throw new Error("protected model activation deadline must be a positive safe integer");
944
+ if (request.deadlineAtMs <= Date.now()) throw new Error("protected model activation deadline must be in the future");
945
+ if (request.deadlineAtMs > state.expiresAtMs) throw new Error("protected model activation deadline exceeds the reserved expiry");
946
+ state.activation = "activating";
947
+ try {
948
+ const activation = validateActivation(await options.client.activate(request), state.limits.maxModelCalls === 0 ? [] : activationEnvNames);
949
+ if (recentSettlements.has(key) || reservations.get(key) !== state) throw new Error("protected model grant settled while activation was in flight");
950
+ state.activation = "activated";
951
+ return activation;
952
+ } catch (error) {
953
+ state.activation = "reserved";
954
+ throw error;
955
+ }
956
+ },
957
+ settleGrant: async (input) => {
958
+ const now = Date.now();
959
+ pruneExpiredState(reservations, expiredReservations, recentSettlements, now);
960
+ const request = immutableCandidateValue(input);
961
+ const key = reservationKey(request.executionId, request.preparationId);
962
+ const state = reservations.get(key) ?? expiredReservations.get(key)?.state;
963
+ if (state) assertGrantIdentity(state, request);
964
+ const remembered = state ?? recentSettlements.get(key);
965
+ if (remembered?.settlementReason && remembered.settlementReason !== request.reason) throw new Error("protected model settlement retry changed the termination reason");
966
+ const sealed = sealAgentCandidateModelSettlement(await options.client.settle(request), {
967
+ preparationId: request.preparationId,
968
+ grantDigest: request.grantDigest,
969
+ model: request.resolved.model
970
+ });
971
+ if (state) assertWithinReservedLimits(sealed.usage, state);
972
+ const settlementDigest = canonicalCandidateDigest$1(sealed.value);
973
+ if (remembered?.settlementDigest && remembered.settlementDigest !== settlementDigest) throw new Error("protected model settlement retry returned a different final ledger");
974
+ if (remembered?.settlementReason && remembered.settlementReason !== request.reason) throw new Error("protected model settlement retry changed the termination reason");
975
+ const expiresAtMs = state?.expiresAtMs ?? now + RECOVERED_SETTLEMENT_RETENTION_MS;
976
+ if (state) {
977
+ state.settlementDigest = settlementDigest;
978
+ state.settlementReason = request.reason;
979
+ }
980
+ reservations.delete(key);
981
+ expiredReservations.delete(key);
982
+ rememberSettlement(recentSettlements, key, {
983
+ settlementDigest,
984
+ settlementReason: request.reason,
985
+ expiresAtMs
986
+ });
987
+ return sealed.value;
988
+ }
989
+ };
990
+ }
991
+ function validateReserveInput(input) {
992
+ if (!Number.isSafeInteger(input.expiresAtMs) || input.expiresAtMs <= 0) throw new Error("protected model reservation expiry must be a positive safe integer");
993
+ if (input.expiresAtMs <= Date.now()) throw new Error("protected model reservation expiry must be in the future");
994
+ for (const [name, value] of [
995
+ ["maxModelCalls", input.limits.maxModelCalls],
996
+ ["maxInputTokens", input.limits.maxInputTokens],
997
+ ["maxOutputTokens", input.limits.maxOutputTokens],
998
+ ["maxTotalTokens", input.limits.maxTotalTokens]
999
+ ]) {
1000
+ if (value === void 0) continue;
1001
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error(`protected model reservation ${name} must be a nonnegative safe integer`);
1002
+ }
1003
+ usdToNanos(input.limits.maxCostUsd, "reserved maxCostUsd");
1004
+ }
1005
+ function validateReservation(value, expected, gatewayDomain) {
1006
+ const source = exactRecord(value, [
1007
+ "preparationId",
1008
+ "digest",
1009
+ "expiresAtMs",
1010
+ "enforcedLimits",
1011
+ "network"
1012
+ ], "protected model reservation response");
1013
+ if (source.preparationId !== expected.preparationId) throw new Error("protected model reservation response changed preparation identity");
1014
+ if (!isSha256Digest(source.digest)) throw new Error("protected model reservation response has an invalid digest");
1015
+ if (source.expiresAtMs !== expected.expiresAtMs) throw new Error("protected model reservation response changed expiry");
1016
+ exactRecord(source.enforcedLimits, modelLimitKeys(expected.limits), "protected model reservation enforced limits");
1017
+ if (canonicalCandidateDigest$1(source.enforcedLimits) !== canonicalCandidateDigest$1(expected.limits)) throw new Error("protected model reservation response changed enforced limits");
1018
+ const network = validateReservationNetwork(source.network, expected.limits.maxModelCalls, gatewayDomain);
1019
+ return immutableCandidateValue({
1020
+ preparationId: source.preparationId,
1021
+ digest: source.digest,
1022
+ expiresAtMs: source.expiresAtMs,
1023
+ enforcedLimits: source.enforcedLimits,
1024
+ network
1025
+ });
1026
+ }
1027
+ function validateReservationNetwork(value, maxModelCalls, gatewayDomain) {
1028
+ if (maxModelCalls === 0) {
1029
+ if (exactRecord(value, ["mode"], "protected model reservation network").mode !== "disabled") throw new Error("zero-call protected model reservation must disable gateway access");
1030
+ return { mode: "disabled" };
1031
+ }
1032
+ const source = exactRecord(value, ["mode", "domains"], "protected model reservation network");
1033
+ if (source.mode !== "gateway-only") throw new Error("protected model reservation must allow only its model gateway");
1034
+ if (!Array.isArray(source.domains) || source.domains.length !== 1 || source.domains[0] !== gatewayDomain) throw new Error("protected model reservation returned an unexpected gateway domain");
1035
+ return {
1036
+ mode: "gateway-only",
1037
+ domains: [gatewayDomain]
1038
+ };
1039
+ }
1040
+ function validateActivation(value, expectedNames) {
1041
+ const env = record(exactRecord(value, ["env"], "protected model activation response").env, "protected model activation environment");
1042
+ const actualNames = Object.keys(env).sort();
1043
+ if (actualNames.length !== expectedNames.length || actualNames.some((name, index) => name !== expectedNames[index])) throw new Error("protected model activation returned unexpected environment names");
1044
+ const detached = Object.create(null);
1045
+ for (const name of expectedNames) {
1046
+ const value = env[name];
1047
+ if (typeof value !== "string" || value.length < 8 || value.length > 65536) throw new Error(`protected model activation ${name} must be a non-empty protected value`);
1048
+ detached[name] = value;
1049
+ }
1050
+ return Object.freeze({ env: Object.freeze(detached) });
1051
+ }
1052
+ function validateResolvedModel(value, expected) {
1053
+ const source = exactRecord(value, [
1054
+ "requested",
1055
+ "provider",
1056
+ "model",
1057
+ "snapshot",
1058
+ "reasoningEffort"
1059
+ ], "resolved candidate model");
1060
+ if (source.requested !== expected.requested) throw new Error("model resolver changed the evaluator-owned request");
1061
+ if (source.reasoningEffort !== expected.reasoningEffort) throw new Error("model resolver changed the evaluator-owned reasoning effort");
1062
+ for (const name of [
1063
+ "requested",
1064
+ "provider",
1065
+ "model",
1066
+ "snapshot"
1067
+ ]) if (typeof source[name] !== "string" || source[name].length === 0) throw new Error(`resolved candidate model ${name} must be non-empty`);
1068
+ return source;
1069
+ }
1070
+ function assertGrantIdentity(expected, actual) {
1071
+ if (actual.executionId !== expected.executionId || actual.preparationId !== expected.preparationId || actual.grantDigest !== expected.grantDigest || canonicalCandidateDigest$1(actual.resolved) !== canonicalCandidateDigest$1(expected.resolved)) throw new Error("protected model grant input does not match its immutable reservation");
1072
+ }
1073
+ function assertWithinReservedLimits(usage, reservation) {
1074
+ for (const [name, actual, limit] of [
1075
+ [
1076
+ "model calls",
1077
+ usage.modelCalls,
1078
+ reservation.limits.maxModelCalls
1079
+ ],
1080
+ [
1081
+ "input tokens",
1082
+ usage.inputTokens,
1083
+ reservation.limits.maxInputTokens
1084
+ ],
1085
+ [
1086
+ "output tokens",
1087
+ usage.outputTokens,
1088
+ reservation.limits.maxOutputTokens
1089
+ ],
1090
+ [
1091
+ "cost USD nanos",
1092
+ usage.costUsdNanos,
1093
+ reservation.maxCostUsdNanos
1094
+ ]
1095
+ ]) if (actual > limit) throw new Error(`protected model settlement ${name} ${actual} exceeds reserved ${limit}`);
1096
+ const maxTotalTokens = reservation.limits.maxTotalTokens;
1097
+ if (maxTotalTokens !== void 0) {
1098
+ const totalTokens = usage.inputTokens + usage.outputTokens;
1099
+ if (!Number.isSafeInteger(totalTokens)) throw new Error("protected model settlement total token usage is incomplete");
1100
+ if (totalTokens > maxTotalTokens) throw new Error(`protected model settlement total tokens ${totalTokens} exceeds reserved ${maxTotalTokens}`);
1101
+ }
1102
+ }
1103
+ function modelLimitKeys(limits) {
1104
+ return limits.maxTotalTokens === void 0 ? [
1105
+ "maxModelCalls",
1106
+ "maxInputTokens",
1107
+ "maxOutputTokens",
1108
+ "maxCostUsd"
1109
+ ] : [
1110
+ "maxModelCalls",
1111
+ "maxInputTokens",
1112
+ "maxOutputTokens",
1113
+ "maxTotalTokens",
1114
+ "maxCostUsd"
1115
+ ];
1116
+ }
1117
+ function exactEnvironmentNames(values) {
1118
+ if (values.length === 0) throw new Error("protected model activation environment names must not be empty");
1119
+ const names = [...values].sort();
1120
+ if (new Set(names).size !== names.length) throw new Error("protected model activation environment names must be unique");
1121
+ for (const name of names) if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name) || [
1122
+ "__proto__",
1123
+ "constructor",
1124
+ "prototype"
1125
+ ].includes(name)) throw new Error(`protected model activation environment name is invalid: ${name}`);
1126
+ return Object.freeze(names);
1127
+ }
1128
+ function assertGatewayDomain(value) {
1129
+ if (value.length > 253 || value !== value.toLowerCase() || value.endsWith(".") || value.includes(":") || value === "localhost" || value.endsWith(".localhost") || value === "metadata.google" || value === "metadata.google.internal") throw new Error("protected model gateway must be an exact lowercase public DNS name");
1130
+ const labels = value.split(".");
1131
+ if (labels.length < 2 || !labels.every((label) => label.length >= 1 && label.length <= 63 && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(label)) || !/[a-z]/.test(labels.at(-1) ?? "")) throw new Error("protected model gateway must be an exact lowercase public DNS name");
1132
+ return value;
1133
+ }
1134
+ function reservationKey(executionId, preparationId) {
1135
+ return canonicalCandidateDigest$1({
1136
+ executionId,
1137
+ preparationId
1138
+ });
1139
+ }
1140
+ function pruneExpiredState(reservations, expiredReservations, settlements, now) {
1141
+ for (const [key, value] of reservations) if (value.expiresAtMs <= now) {
1142
+ reservations.delete(key);
1143
+ expiredReservations.set(key, {
1144
+ state: value,
1145
+ retainedUntilMs: now + RECOVERED_SETTLEMENT_RETENTION_MS
1146
+ });
1147
+ }
1148
+ for (const [key, value] of expiredReservations) if (value.retainedUntilMs <= now) expiredReservations.delete(key);
1149
+ for (const [key, value] of settlements) if (value.expiresAtMs <= now) settlements.delete(key);
1150
+ }
1151
+ function rememberSettlement(settlements, key, value) {
1152
+ settlements.delete(key);
1153
+ settlements.set(key, value);
1154
+ while (settlements.size > MAX_RECENT_SETTLEMENTS) {
1155
+ const oldest = settlements.keys().next().value;
1156
+ if (oldest === void 0) return;
1157
+ settlements.delete(oldest);
1158
+ }
1159
+ }
1160
+ function isSha256Digest(value) {
1161
+ return typeof value === "string" && /^sha256:[a-f0-9]{64}$/.test(value);
1162
+ }
1163
+ function exactRecord(value, keys, label) {
1164
+ const source = record(value, label);
1165
+ assertExactObjectKeys(source, keys, label);
1166
+ return source;
1167
+ }
1168
+ function record(value, label) {
1169
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
1170
+ const prototype = Object.getPrototypeOf(value);
1171
+ if (prototype !== Object.prototype && prototype !== null) throw new Error(`${label} must be a plain object`);
1172
+ return value;
1173
+ }
1174
+ function modelLimits(limits) {
1175
+ return {
1176
+ maxModelCalls: limits.maxModelCalls,
1177
+ maxInputTokens: limits.maxInputTokens,
1178
+ maxOutputTokens: limits.maxOutputTokens,
1179
+ maxCostUsd: limits.maxCostUsd
1180
+ };
1181
+ }
1182
+ //#endregion
12
1183
  //#region src/candidate-execution/claim-file-formats.ts
13
1184
  function sealCandidatePreparationEvidence(value, executionPlanDigest) {
14
1185
  if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("candidate execution preparation evidence must be an object");
@@ -249,7 +1420,7 @@ function sealUsage(usage) {
249
1420
  "cachedInputTokens",
250
1421
  "reasoningTokens",
251
1422
  "modelCalls"
252
- ]) assertCount$1(usage[field], `terminal usage ${field}`);
1423
+ ]) assertCount(usage[field], `terminal usage ${field}`);
253
1424
  if (usage.costProvenance !== "observed" && usage.costProvenance !== "estimated") throw new Error("terminal usage costProvenance must be observed or estimated");
254
1425
  return Object.freeze({
255
1426
  costUsdNanos: usage.costUsdNanos,
@@ -302,7 +1473,7 @@ function assertExecutionId$1(value) {
302
1473
  function assertSha256Digest$1(value, field) {
303
1474
  if (!SHA256_PATTERN$1.test(value)) throw new Error(`candidate execution claim ${field} must be a lowercase sha256 digest`);
304
1475
  }
305
- function assertCount$1(value, label) {
1476
+ function assertCount(value, label) {
306
1477
  if (!Number.isSafeInteger(value) || value < 0) throw new Error(`candidate execution ${label} must be a non-negative safe integer`);
307
1478
  }
308
1479
  function candidateCleanupTimeout(timeoutMs) {
@@ -767,13 +1938,6 @@ function assertExecutionId(value) {
767
1938
  function assertBoundedIdentifier(value, label, maxLength) {
768
1939
  if (typeof value !== "string" || value.length === 0 || value.length > maxLength || hasControlCharacter(value)) throw new Error(`candidate execution ${label} is invalid`);
769
1940
  }
770
- function hasControlCharacter(value) {
771
- for (let index = 0; index < value.length; index++) {
772
- const code = value.charCodeAt(index);
773
- if (code < 32 || code === 127) return true;
774
- }
775
- return false;
776
- }
777
1941
  function assertPositiveTimestamp(value, label) {
778
1942
  if (!Number.isSafeInteger(value) || value <= 0) throw new Error(`candidate execution ${label} must be a positive safe timestamp`);
779
1943
  }
@@ -820,77 +1984,26 @@ const candidateClaimFileInternals = Object.freeze({
820
1984
  });
821
1985
  //#endregion
822
1986
  //#region src/candidate-execution/execution-window.ts
823
- const CANDIDATE_TERMINAL_PERSISTENCE_MARGIN_MS = 1e4;
824
- const CANDIDATE_POST_RUN_CLEANUP_PHASES = 4;
825
- /** Process stop, access closure, model evidence, and task/result evidence. */
826
- function candidatePostRunWindowMs(cleanupTimeoutMs, resultTimeoutMs) {
827
- const windowMs = cleanupTimeoutMs * CANDIDATE_POST_RUN_CLEANUP_PHASES + resultTimeoutMs + CANDIDATE_TERMINAL_PERSISTENCE_MARGIN_MS;
828
- if (!Number.isSafeInteger(windowMs) || windowMs > 2147483647) throw new Error("candidate post-run window exceeds the supported timer range");
829
- return windowMs;
830
- }
831
- /** Maximum owner lifetime from claim through process stop, access closure, and terminal write. */
832
- function candidateExecutionOwnerWindowMs(timeoutMs, cleanupTimeoutMs, resultTimeoutMs) {
833
- const windowMs = timeoutMs + candidatePostRunWindowMs(cleanupTimeoutMs, resultTimeoutMs);
834
- if (!Number.isSafeInteger(windowMs) || windowMs > 2147483647) throw new Error("candidate execution and cleanup window exceeds the supported timer range");
835
- return windowMs;
836
- }
837
- /** Time reserved after scoring for failure evidence plus terminal publication. */
838
- function candidateTerminalWindowMs(cleanupTimeoutMs) {
839
- const windowMs = cleanupTimeoutMs + CANDIDATE_TERMINAL_PERSISTENCE_MARGIN_MS;
840
- if (!Number.isSafeInteger(windowMs) || windowMs > 2147483647) throw new Error("candidate terminal window exceeds the supported timer range");
841
- return windowMs;
842
- }
843
- //#endregion
844
- //#region src/candidate-execution/execution-roots.ts
845
- /** Validate the canonical identity and isolation boundary for execution roots. */
846
- function assertAgentCandidateExecutionRoots(roots) {
847
- const entries = [
848
- ["task", roots.taskRoot],
849
- ["candidate", roots.candidateRoot],
850
- ["profile", roots.profileRoot]
851
- ];
852
- for (const [name, root] of entries) {
853
- if (root === void 0) continue;
854
- if (!posix.isAbsolute(root) || posix.normalize(root) !== root) throw new Error(`execution ${name} root must be a canonical absolute path`);
855
- }
856
- for (let left = 0; left < entries.length; left++) {
857
- const entry = entries[left];
858
- if (!entry) continue;
859
- const [leftName, leftRoot] = entry;
860
- if (leftRoot === void 0) continue;
861
- for (let right = left + 1; right < entries.length; right++) {
862
- const rightEntry = entries[right];
863
- if (!rightEntry) continue;
864
- const [rightName, rightRoot] = rightEntry;
865
- if (rightRoot !== void 0 && executionPathsOverlap(leftRoot, rightRoot)) throw new Error(`execution ${leftName} and ${rightName} roots must be distinct and non-overlapping`);
866
- }
867
- }
1987
+ const CANDIDATE_TERMINAL_PERSISTENCE_MARGIN_MS = 1e4;
1988
+ const CANDIDATE_POST_RUN_CLEANUP_PHASES = 4;
1989
+ /** Process stop, access closure, model evidence, and task/result evidence. */
1990
+ function candidatePostRunWindowMs(cleanupTimeoutMs, resultTimeoutMs) {
1991
+ const windowMs = cleanupTimeoutMs * CANDIDATE_POST_RUN_CLEANUP_PHASES + resultTimeoutMs + CANDIDATE_TERMINAL_PERSISTENCE_MARGIN_MS;
1992
+ if (!Number.isSafeInteger(windowMs) || windowMs > 2147483647) throw new Error("candidate post-run window exceeds the supported timer range");
1993
+ return windowMs;
868
1994
  }
869
- function executionPathsOverlap(left, right) {
870
- const a = posix.normalize(left);
871
- const b = posix.normalize(right);
872
- return a === b || b.startsWith(a === "/" ? "/" : `${a}/`) || a.startsWith(b === "/" ? "/" : `${b}/`);
1995
+ /** Maximum owner lifetime from claim through process stop, access closure, and terminal write. */
1996
+ function candidateExecutionOwnerWindowMs(timeoutMs, cleanupTimeoutMs, resultTimeoutMs) {
1997
+ const windowMs = timeoutMs + candidatePostRunWindowMs(cleanupTimeoutMs, resultTimeoutMs);
1998
+ if (!Number.isSafeInteger(windowMs) || windowMs > 2147483647) throw new Error("candidate execution and cleanup window exceeds the supported timer range");
1999
+ return windowMs;
2000
+ }
2001
+ /** Time reserved after scoring for failure evidence plus terminal publication. */
2002
+ function candidateTerminalWindowMs(cleanupTimeoutMs) {
2003
+ const windowMs = cleanupTimeoutMs + CANDIDATE_TERMINAL_PERSISTENCE_MARGIN_MS;
2004
+ if (!Number.isSafeInteger(windowMs) || windowMs > 2147483647) throw new Error("candidate terminal window exceeds the supported timer range");
2005
+ return windowMs;
873
2006
  }
874
- //#endregion
875
- //#region src/candidate-execution/types.ts
876
- const verifiedCandidateBrand = Symbol("verifiedAgentCandidate");
877
- const preparedCandidateBrand = Symbol("preparedAgentCandidate");
878
- const verifiedTaskOutcomeBrand = Symbol("verifiedTaskOutcome");
879
- /** Protected trace tags that bind a run to one prepared candidate execution. */
880
- const CANDIDATE_TRACE_TAGS = {
881
- executionId: "tangle.candidate.execution_id",
882
- bundleDigest: "tangle.candidate.bundle_digest",
883
- executionPlanDigest: "tangle.candidate.execution_plan_digest",
884
- materializationReceiptDigest: "tangle.candidate.materialization_receipt_digest"
885
- };
886
- /** Environment keys used to propagate immutable candidate trace identity. */
887
- const CANDIDATE_TRACE_ENV = {
888
- executionId: "TANGLE_CANDIDATE_EXECUTION_ID",
889
- bundleDigest: "TANGLE_CANDIDATE_BUNDLE_DIGEST",
890
- executionPlanDigest: "TANGLE_CANDIDATE_EXECUTION_PLAN_DIGEST",
891
- materializationReceiptDigest: "TANGLE_CANDIDATE_MATERIALIZATION_RECEIPT_DIGEST",
892
- traceRunId: "TANGLE_TRACE_RUN_ID"
893
- };
894
2007
  //#endregion
895
2008
  //#region src/candidate-execution/prepared-state.ts
896
2009
  const stateByExecution = /* @__PURE__ */ new WeakMap();
@@ -1088,7 +2201,7 @@ function assertPrivateCandidateIntegrity(state) {
1088
2201
  assertSignedBenchmarkInput(state);
1089
2202
  const instruction = Buffer.from(state.benchmarkTask.instruction, "utf8");
1090
2203
  if (!Buffer.from(state.instruction.bytes).equals(instruction) || JSON.stringify(state.instruction.delivery) !== JSON.stringify(state.executionPlan.value.material.instructionDelivery)) throw new Error("prepared instruction no longer matches the signed execution plan");
1091
- if (!/^candidate-preparation\.[A-Za-z0-9_-]{43}$/.test(state.preparationId) || !Number.isSafeInteger(state.reservationExpiresAtMs) || state.reservationExpiresAtMs <= 0 || !Number.isSafeInteger(state.cleanupTimeoutMs) || state.cleanupTimeoutMs <= 0 || !Number.isSafeInteger(state.resultTimeoutMs) || state.resultTimeoutMs <= 0 || JSON.stringify(state.resolvedModel) !== JSON.stringify(state.executionPlan.value.material.model.resolved) || state.modelReservation.digest !== state.executionPlan.value.material.model.access.grantDigest || state.modelReservation.preparationId !== state.preparationId || state.modelReservation.expiresAtMs !== state.reservationExpiresAtMs || canonicalCandidateDigest$1(state.modelReservation.network) !== canonicalCandidateDigest$1(state.executionPlan.value.material.model.access.network) || canonicalCandidateDigest$1(state.modelReservation.enforcedLimits) !== canonicalCandidateDigest$1(modelLimits$1(state.executionPlan.value.material.limits))) throw new Error("prepared model access no longer matches the signed execution plan");
2204
+ if (!/^candidate-preparation\.[A-Za-z0-9_-]{43}$/.test(state.preparationId) || !Number.isSafeInteger(state.reservationExpiresAtMs) || state.reservationExpiresAtMs <= 0 || !Number.isSafeInteger(state.cleanupTimeoutMs) || state.cleanupTimeoutMs <= 0 || !Number.isSafeInteger(state.resultTimeoutMs) || state.resultTimeoutMs <= 0 || JSON.stringify(state.resolvedModel) !== JSON.stringify(state.executionPlan.value.material.model.resolved) || state.modelReservation.digest !== state.executionPlan.value.material.model.access.grantDigest || state.modelReservation.preparationId !== state.preparationId || state.modelReservation.expiresAtMs !== state.reservationExpiresAtMs || canonicalCandidateDigest$1(state.modelReservation.network) !== canonicalCandidateDigest$1(state.executionPlan.value.material.model.access.network) || canonicalCandidateDigest$1(state.modelReservation.enforcedLimits) !== canonicalCandidateDigest$1(modelLimits(state.executionPlan.value.material.limits))) throw new Error("prepared model access no longer matches the signed execution plan");
1092
2205
  assertExecutorInputs(state);
1093
2206
  assertPreparedKnowledge(state);
1094
2207
  if (state.memory.mode === "isolated" && !state.memoryReservation || state.memory.mode === "disabled" && state.memoryReservation) throw new Error("prepared memory reservation does not match the signed execution plan");
@@ -1225,14 +2338,6 @@ function immutableExecutorFiles(files) {
1225
2338
  bytes: Uint8Array.from(file.bytes)
1226
2339
  })));
1227
2340
  }
1228
- function modelLimits$1(limits) {
1229
- return {
1230
- maxModelCalls: limits.maxModelCalls,
1231
- maxInputTokens: limits.maxInputTokens,
1232
- maxOutputTokens: limits.maxOutputTokens,
1233
- maxCostUsd: limits.maxCostUsd
1234
- };
1235
- }
1236
2341
  function transitionLifecycle(prepared, expected, next) {
1237
2342
  const lifecycle = lifecycleByExecution.get(prepared);
1238
2343
  if (!lifecycle || !expected.includes(lifecycle.status)) throw new Error(`prepared candidate execution is already ${lifecycle?.status ?? "unknown"}`);
@@ -1383,224 +2488,36 @@ function sealTaskOutcomeCapture(value, expected) {
1383
2488
  if (capture.kind === "output") {
1384
2489
  assertExactObjectKeys(capture, ["kind", "bytes"], "candidate task output capture");
1385
2490
  if (expected.kind !== "output") throw new Error("candidate task output capture does not match the signed outcome kind");
1386
- if (!(capture.bytes instanceof Uint8Array)) throw new Error("candidate task output capture must contain a byte array");
1387
- if (capture.bytes.byteLength > expected.maxBytes) throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
1388
- return Object.freeze({
1389
- kind: "output",
1390
- bytes: Uint8Array.from(capture.bytes)
1391
- });
1392
- }
1393
- assertExactObjectKeys(capture, [
1394
- "kind",
1395
- "resultTree",
1396
- "afterState",
1397
- "archive",
1398
- "gitDiff"
1399
- ], "candidate task capture");
1400
- if (capture.kind !== "workspace") throw new Error("candidate task capture has an invalid outcome kind");
1401
- if (expected.kind !== "workspace") throw new Error("candidate workspace capture does not match the signed outcome kind");
1402
- if (typeof capture.resultTree !== "string" || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(capture.resultTree)) throw new Error("candidate task capture resultTree is not a Git object id");
1403
- if (!(capture.archive instanceof Uint8Array) || !(capture.gitDiff instanceof Uint8Array)) throw new Error("candidate task capture archive and gitDiff must be byte arrays");
1404
- const afterState = agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState);
1405
- return Object.freeze({
1406
- kind: "workspace",
1407
- resultTree: capture.resultTree,
1408
- afterState: Object.freeze(afterState),
1409
- archive: Uint8Array.from(capture.archive),
1410
- gitDiff: Uint8Array.from(capture.gitDiff)
1411
- });
1412
- }
1413
- function requireRecord(value, label) {
1414
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
1415
- return value;
1416
- }
1417
- //#endregion
1418
- //#region src/candidate-execution/model-settlement.ts
1419
- const USD_NANOS = 1e9;
1420
- /** Validate and detach the evaluator gateway's terminal, revoked call ledger. */
1421
- function sealAgentCandidateModelSettlement(settlement, expected) {
1422
- assertExactObjectKeys(settlement, [
1423
- "preparationId",
1424
- "grantDigest",
1425
- "closed",
1426
- "usageWithinLimits",
1427
- "calls"
1428
- ], "model settlement");
1429
- if (settlement.closed !== true) throw new Error("protected model grant is not closed");
1430
- if (settlement.usageWithinLimits !== true) throw new Error("protected model settlement reports usage outside frozen limits");
1431
- if (settlement.grantDigest !== expected.grantDigest) throw new Error("protected model settlement grant digest does not match the reservation");
1432
- if (settlement.preparationId !== expected.preparationId) throw new Error("protected model settlement preparation does not match the reservation");
1433
- if (!Array.isArray(settlement.calls)) throw new Error("protected model settlement calls must be an array");
1434
- const callIds = /* @__PURE__ */ new Set();
1435
- const spanIds = /* @__PURE__ */ new Set();
1436
- let accountedInputTokens = 0;
1437
- let outputTokens = 0;
1438
- let cachedInputTokens = 0;
1439
- let reasoningTokens = 0;
1440
- let costUsdNanos = 0;
1441
- let costProvenance = "observed";
1442
- const calls = settlement.calls.map((source, index) => {
1443
- assertExactObjectKeys(source, [
1444
- "callId",
1445
- "generationId",
1446
- "traceSpanId",
1447
- "status",
1448
- "model",
1449
- "startedAtMs",
1450
- "endedAtMs",
1451
- "inputTokens",
1452
- "accountedInputTokens",
1453
- "outputTokens",
1454
- "cachedInputTokens",
1455
- "reasoningTokens",
1456
- "costUsdNanos",
1457
- "costProvenance"
1458
- ], `model settlement call ${index}`);
1459
- assertIdentifier(source.callId, `model settlement call ${index} callId`);
1460
- assertIdentifier(source.generationId, `model settlement call ${index} generationId`);
1461
- assertIdentifier(source.traceSpanId, `model settlement call ${index} traceSpanId`);
1462
- if (source.traceSpanId !== source.generationId) throw new Error(`model settlement call ${index} traceSpanId is not its router generationId`);
1463
- if (source.status !== "succeeded" && source.status !== "failed") throw new Error(`model settlement call ${index} has an invalid status`);
1464
- if (callIds.has(source.callId)) throw new Error("protected model settlement has duplicate call ids");
1465
- if (spanIds.has(source.traceSpanId)) throw new Error("protected model settlement has duplicate trace span ids");
1466
- callIds.add(source.callId);
1467
- spanIds.add(source.traceSpanId);
1468
- if (source.model !== expected.model) throw new Error(`protected model settlement call ${index} has an unexpected model`);
1469
- assertTimestamp(source.startedAtMs, `model settlement call ${index} startedAtMs`);
1470
- assertTimestamp(source.endedAtMs, `model settlement call ${index} endedAtMs`);
1471
- if (source.endedAtMs < source.startedAtMs) throw new Error(`model settlement call ${index} ended before it started`);
1472
- assertCount(source.inputTokens, `model settlement call ${index} inputTokens`);
1473
- assertCount(source.accountedInputTokens, `model settlement call ${index} accountedInputTokens`);
1474
- if (source.accountedInputTokens < source.inputTokens) throw new Error(`model settlement call ${index} accountedInputTokens cannot be less than inputTokens`);
1475
- assertCount(source.outputTokens, `model settlement call ${index} outputTokens`);
1476
- assertCount(source.cachedInputTokens, `model settlement call ${index} cachedInputTokens`);
1477
- cachedInputTokens = safeAdd(cachedInputTokens, source.cachedInputTokens, "cached input token total");
1478
- assertCount(source.reasoningTokens, `model settlement call ${index} reasoningTokens`);
1479
- reasoningTokens = safeAdd(reasoningTokens, source.reasoningTokens, "reasoning token total");
1480
- assertCount(source.costUsdNanos, `model settlement call ${index} costUsdNanos`);
1481
- if (source.costProvenance !== "observed" && source.costProvenance !== "estimated") throw new Error(`model settlement call ${index} has an invalid cost provenance`);
1482
- if (source.costProvenance === "estimated") costProvenance = "estimated";
1483
- accountedInputTokens = safeAdd(accountedInputTokens, source.accountedInputTokens, "accounted input token total");
1484
- outputTokens = safeAdd(outputTokens, source.outputTokens, "output token total");
1485
- costUsdNanos = safeAdd(costUsdNanos, source.costUsdNanos, "cost total");
1486
- return Object.freeze({ ...source });
1487
- });
1488
- const usage = Object.freeze({
1489
- costUsdNanos,
1490
- inputTokens: accountedInputTokens,
1491
- outputTokens,
1492
- cachedInputTokens,
1493
- reasoningTokens,
1494
- modelCalls: calls.length,
1495
- costProvenance
1496
- });
1497
- return Object.freeze({
1498
- value: Object.freeze({
1499
- preparationId: settlement.preparationId,
1500
- grantDigest: settlement.grantDigest,
1501
- closed: true,
1502
- usageWithinLimits: true,
1503
- calls: Object.freeze(calls)
1504
- }),
1505
- usage
1506
- });
1507
- }
1508
- /**
1509
- * Append the only accepted LLM spans from the router's closed ledger.
1510
- * Candidate and executor code may write tool/process spans, but never model usage.
1511
- */
1512
- async function appendAuthoritativeModelSettlementSpans(traceStore, runId, settlement) {
1513
- const run = await traceStore.getRun(runId);
1514
- if (!run) throw new Error(`protected trace run is missing before model settlement: ${runId}`);
1515
- if (run.status === "running" || run.endedAt === void 0) throw new Error("protected trace run must be terminal before model spans are appended");
1516
- const existing = await traceStore.spans({ runId });
1517
- if (existing.some(isLlmSpan)) throw new Error("protected trace contains a model span not authored from the closed router ledger");
1518
- const occupiedIds = new Set(existing.map((span) => span.spanId));
1519
- for (const call of settlement.value.calls) {
1520
- if (occupiedIds.has(call.traceSpanId)) throw new Error(`protected trace span identity collides with router generation ${call.generationId}`);
1521
- await traceStore.appendSpan({
1522
- runId,
1523
- spanId: call.traceSpanId,
1524
- kind: "llm",
1525
- name: "protected model call",
1526
- model: call.model,
1527
- messages: [],
1528
- startedAt: call.startedAtMs,
1529
- endedAt: call.endedAtMs,
1530
- status: call.status === "succeeded" ? "ok" : "error",
1531
- inputTokens: call.inputTokens,
1532
- outputTokens: call.outputTokens,
1533
- cachedTokens: call.cachedInputTokens,
1534
- reasoningTokens: call.reasoningTokens,
1535
- costUsd: call.costUsdNanos / USD_NANOS,
1536
- attributes: {
1537
- "tangle.protected_model.source": "router-settlement",
1538
- "tangle.router.call_id": call.callId,
1539
- "tangle.router.generation_id": call.generationId
1540
- }
1541
- });
1542
- }
1543
- }
1544
- /** Match every protected trace span one-for-one against gateway call evidence. */
1545
- function assertTraceMatchesModelSettlement(spans, settlement) {
1546
- if (spans.length !== settlement.value.calls.length) throw new Error(`protected trace model calls ${spans.length} do not match model ledger ${settlement.value.calls.length}`);
1547
- const byId = new Map(spans.map((span) => [span.spanId, span]));
1548
- if (byId.size !== spans.length) throw new Error("protected trace has duplicate model span ids");
1549
- for (const call of settlement.value.calls) {
1550
- const span = byId.get(call.traceSpanId);
1551
- if (!span) throw new Error(`protected trace is missing model ledger span ${call.traceSpanId}`);
1552
- assertTraceCall(span, call);
1553
- }
1554
- }
1555
- function usdToNanos(value, label) {
1556
- if (!Number.isFinite(value) || value < 0) throw new Error(`${label} must be nonnegative`);
1557
- const nanos = Math.round(value * USD_NANOS);
1558
- if (!Number.isSafeInteger(nanos)) throw new Error(`${label} exceeds fixed-point range`);
1559
- return nanos;
1560
- }
1561
- function assertTraceCall(span, call) {
1562
- if (span.model !== call.model) throw new Error(`protected trace span ${span.spanId} model does not match model ledger`);
1563
- if (span.startedAt !== call.startedAtMs || span.endedAt !== call.endedAtMs || span.status !== (call.status === "succeeded" ? "ok" : "error")) throw new Error(`protected trace span ${span.spanId} timing or status does not match model ledger`);
1564
- if (span.attributes?.["tangle.protected_model.source"] !== "router-settlement" || span.attributes?.["tangle.router.call_id"] !== call.callId || span.attributes?.["tangle.router.generation_id"] !== call.generationId) throw new Error(`protected trace span ${span.spanId} lacks router settlement provenance`);
1565
- for (const [name, traced, settled] of [
1566
- [
1567
- "inputTokens",
1568
- span.inputTokens,
1569
- call.inputTokens
1570
- ],
1571
- [
1572
- "outputTokens",
1573
- span.outputTokens,
1574
- call.outputTokens
1575
- ],
1576
- [
1577
- "cachedInputTokens",
1578
- span.cachedTokens ?? 0,
1579
- call.cachedInputTokens
1580
- ],
1581
- [
1582
- "reasoningTokens",
1583
- span.reasoningTokens ?? 0,
1584
- call.reasoningTokens
1585
- ]
1586
- ]) if (traced === void 0 || traced !== settled) throw new Error(`protected trace span ${span.spanId} ${name} ${traced} does not match model ledger ${settled}`);
1587
- if (span.costUsd === void 0) throw new Error(`protected trace span ${span.spanId} is missing costUsd`);
1588
- const tracedCost = usdToNanos(span.costUsd, `protected trace span ${span.spanId} costUsd`);
1589
- if (tracedCost !== call.costUsdNanos) throw new Error(`protected trace span ${span.spanId} costUsdNanos ${tracedCost} does not match model ledger ${call.costUsdNanos}`);
1590
- }
1591
- function assertIdentifier(value, label) {
1592
- if (typeof value !== "string" || value.length === 0 || value.length > 256) throw new Error(`${label} must be a non-empty bounded string`);
1593
- }
1594
- function assertCount(value, label) {
1595
- if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${label} must be a nonnegative safe integer`);
1596
- }
1597
- function assertTimestamp(value, label) {
1598
- if (!Number.isSafeInteger(value) || value <= 0) throw new Error(`${label} must be a positive safe integer`);
2491
+ if (!(capture.bytes instanceof Uint8Array)) throw new Error("candidate task output capture must contain a byte array");
2492
+ if (capture.bytes.byteLength > expected.maxBytes) throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
2493
+ return Object.freeze({
2494
+ kind: "output",
2495
+ bytes: Uint8Array.from(capture.bytes)
2496
+ });
2497
+ }
2498
+ assertExactObjectKeys(capture, [
2499
+ "kind",
2500
+ "resultTree",
2501
+ "afterState",
2502
+ "archive",
2503
+ "gitDiff"
2504
+ ], "candidate task capture");
2505
+ if (capture.kind !== "workspace") throw new Error("candidate task capture has an invalid outcome kind");
2506
+ if (expected.kind !== "workspace") throw new Error("candidate workspace capture does not match the signed outcome kind");
2507
+ if (typeof capture.resultTree !== "string" || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(capture.resultTree)) throw new Error("candidate task capture resultTree is not a Git object id");
2508
+ if (!(capture.archive instanceof Uint8Array) || !(capture.gitDiff instanceof Uint8Array)) throw new Error("candidate task capture archive and gitDiff must be byte arrays");
2509
+ const afterState = agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState);
2510
+ return Object.freeze({
2511
+ kind: "workspace",
2512
+ resultTree: capture.resultTree,
2513
+ afterState: Object.freeze(afterState),
2514
+ archive: Uint8Array.from(capture.archive),
2515
+ gitDiff: Uint8Array.from(capture.gitDiff)
2516
+ });
1599
2517
  }
1600
- function safeAdd(left, right, label) {
1601
- const total = left + right;
1602
- if (!Number.isSafeInteger(total)) throw new Error(`${label} exceeds safe integer range`);
1603
- return total;
2518
+ function requireRecord(value, label) {
2519
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
2520
+ return value;
1604
2521
  }
1605
2522
  //#endregion
1606
2523
  //#region src/candidate-execution/finalize.ts
@@ -2286,6 +3203,22 @@ function normalizeEvaluation(evaluation, termination) {
2286
3203
  function assertUnitScore(value, label) {
2287
3204
  if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1) throw new Error(`${label} must be finite and within [0, 1]`);
2288
3205
  }
3206
+ async function persistFailureEvidence(state, reason, failureClass, termination, outputArtifacts) {
3207
+ const bytes = canonicalCandidateBytes$1({
3208
+ kind: "agent-candidate-execution-failure",
3209
+ executionId: state.executionId,
3210
+ bundleDigest: state.bundle.digest,
3211
+ executionPlanDigest: state.executionPlan.value.digest,
3212
+ failureClass,
3213
+ reason,
3214
+ ...termination ? { termination } : {}
3215
+ });
3216
+ return await persistCandidateOutputArtifact(outputArtifacts, {
3217
+ executionId: state.executionId,
3218
+ purpose: "failure-evidence",
3219
+ bytes
3220
+ });
3221
+ }
2289
3222
  //#endregion
2290
3223
  //#region src/candidate-execution/protected-trace-store.ts
2291
3224
  /** Keep the identity key in evaluator-owned closures and expose only the redacting store to code. */
@@ -2791,22 +3724,6 @@ async function finishClaim(store, lease, terminal, deadlineAtMs) {
2791
3724
  return false;
2792
3725
  }
2793
3726
  }
2794
- async function persistFailureEvidence(state, reason, failureClass, termination, outputArtifacts) {
2795
- const bytes = canonicalCandidateBytes$1({
2796
- kind: "agent-candidate-execution-failure",
2797
- executionId: state.executionId,
2798
- bundleDigest: state.bundle.digest,
2799
- executionPlanDigest: state.executionPlan.value.digest,
2800
- failureClass,
2801
- reason,
2802
- ...termination ? { termination } : {}
2803
- });
2804
- return await persistCandidateOutputArtifact(outputArtifacts, {
2805
- executionId: state.executionId,
2806
- purpose: "failure-evidence",
2807
- bytes
2808
- });
2809
- }
2810
3727
  function protectedEnvironmentValues(activation, memoryActivation) {
2811
3728
  return [...Object.values(activation?.env ?? {}), ...Object.values(memoryActivation?.env ?? {})];
2812
3729
  }
@@ -2820,171 +3737,6 @@ var CandidateExecutionDeadlineError = class extends Error {
2820
3737
  }
2821
3738
  };
2822
3739
  //#endregion
2823
- //#region src/candidate-execution/verify.ts
2824
- const verifiedCandidateState = /* @__PURE__ */ new WeakMap();
2825
- /** Surfaces admitted by Runtime's verifier before an environment adapter is selected. */
2826
- const AGENT_CANDIDATE_EXECUTION_SUPPORT = Object.freeze({
2827
- outcomes: Object.freeze(["workspace", "output"]),
2828
- code: Object.freeze([
2829
- "disabled",
2830
- "no-op",
2831
- "git-patch"
2832
- ]),
2833
- memory: Object.freeze(["disabled", "isolated"]),
2834
- knowledge: true,
2835
- profile: Object.freeze({
2836
- mcpTransports: Object.freeze(["stdio"]),
2837
- remoteMcp: false,
2838
- tools: false,
2839
- permissions: false,
2840
- modes: false,
2841
- confidential: false
2842
- })
2843
- });
2844
- /** Verifies every digest, resource, workspace, and Git object in a candidate bundle. */
2845
- async function verifyAgentCandidateBundle(input, ports) {
2846
- const parsed = agentCandidateBundleSchema.parse(input);
2847
- const withoutDigest = omitTopLevelDigest(parsed);
2848
- const actualDigest = canonicalCandidateDigest$1(withoutDigest);
2849
- if (actualDigest !== parsed.digest) throw new Error(`candidate bundle digest ${parsed.digest} does not match ${actualDigest}`);
2850
- const canonicalBytes = canonicalCandidateBytes$1(withoutDigest);
2851
- verifyBytes(canonicalBytes, parsed.digest, canonicalBytes.byteLength, "candidate bundle");
2852
- assertCandidateProfileExecutionSupport(parsed.profile);
2853
- const artifactBytes = /* @__PURE__ */ new Map();
2854
- const readArtifact = async (artifact) => {
2855
- const key = artifactCacheKey(artifact);
2856
- const existing = artifactBytes.get(key);
2857
- if (existing) return Uint8Array.from(existing);
2858
- const bytes = await readVerifiedArtifact(artifact, ports.artifacts);
2859
- artifactBytes.set(key, Uint8Array.from(bytes));
2860
- return bytes;
2861
- };
2862
- let patchBytes;
2863
- if (parsed.code.kind === "git-patch") patchBytes = await readArtifact(parsed.code.patch.artifact);
2864
- const materializedTree = await verifyCandidateCode(parsed.code, ports.repositories, patchBytes);
2865
- const resourceBytes = /* @__PURE__ */ new Map();
2866
- for (const resource of candidateResources(parsed)) {
2867
- const bytes = resource.kind === "inline" ? Buffer.from(resource.content, "utf8") : await readCandidateGitHubResource(resource, ports.repositories);
2868
- verifyBytes(bytes, resource.sha256, resource.byteLength, `candidate resource ${resource.name ?? (resource.kind === "github" ? resource.path : "<unnamed>")}`);
2869
- resourceBytes.set(resourceKey(resource), Uint8Array.from(bytes));
2870
- resourceBytes.set(resource.sha256, Uint8Array.from(bytes));
2871
- }
2872
- if (parsed.execution.workspace) {
2873
- const workspace = await verifyWorkspaceSnapshotArtifacts(parsed.execution.workspace, ports.artifacts);
2874
- artifactBytes.set(artifactCacheKey(parsed.execution.workspace.manifest), workspace.manifest);
2875
- artifactBytes.set(artifactCacheKey(parsed.execution.workspace.archive), workspace.archive);
2876
- }
2877
- if (parsed.knowledge) {
2878
- const knowledge = await verifyWorkspaceSnapshotArtifacts(parsed.knowledge.snapshot, ports.artifacts);
2879
- artifactBytes.set(artifactCacheKey(parsed.knowledge.snapshot.manifest), knowledge.manifest);
2880
- artifactBytes.set(artifactCacheKey(parsed.knowledge.snapshot.archive), knowledge.archive);
2881
- if (parsed.knowledge.retrievalConfig) await readArtifact(parsed.knowledge.retrievalConfig);
2882
- await readArtifact(parsed.knowledge.evaluation);
2883
- }
2884
- if (parsed.memory.mode === "isolated" && parsed.memory.seed) await readArtifact(parsed.memory.seed);
2885
- deepFreezeCandidate(parsed);
2886
- const verified = Object.freeze({
2887
- bundle: parsed,
2888
- ...materializedTree === void 0 ? {} : { materializedTree },
2889
- [verifiedCandidateBrand]: true
2890
- });
2891
- verifiedCandidateState.set(verified, {
2892
- ports,
2893
- artifactBytes,
2894
- resourceBytes
2895
- });
2896
- return verified;
2897
- }
2898
- function getVerifiedCandidateState(candidate) {
2899
- const state = verifiedCandidateState.get(candidate);
2900
- if (!state || candidate[verifiedCandidateBrand] !== true) throw new Error("candidate must come from verifyAgentCandidateBundle");
2901
- return state;
2902
- }
2903
- async function verifiedArtifactBytes(candidate, artifact) {
2904
- const state = getVerifiedCandidateState(candidate);
2905
- const key = artifactCacheKey(artifact);
2906
- const existing = state.artifactBytes.get(key);
2907
- if (existing) return Uint8Array.from(existing);
2908
- const bytes = await readVerifiedArtifact(artifact, state.ports.artifacts);
2909
- state.artifactBytes.set(key, Uint8Array.from(bytes));
2910
- return bytes;
2911
- }
2912
- function verifiedResourceTextByDigest(candidate) {
2913
- const output = /* @__PURE__ */ new Map();
2914
- for (const resource of candidateResources(candidate.bundle)) {
2915
- const bytes = getVerifiedCandidateState(candidate).resourceBytes.get(resource.sha256);
2916
- if (!bytes) throw new Error(`candidate resource digest was not verified: ${resource.sha256}`);
2917
- output.set(resource.sha256, new TextDecoder("utf-8", { fatal: true }).decode(bytes));
2918
- }
2919
- return output;
2920
- }
2921
- function candidateResources(bundle) {
2922
- const resources = bundle.profile.resources;
2923
- if (!resources) return [];
2924
- const output = [];
2925
- for (const mount of resources.files ?? []) output.push(mount.resource);
2926
- output.push(...resources.tools ?? []);
2927
- output.push(...resources.skills ?? []);
2928
- output.push(...resources.agents ?? []);
2929
- output.push(...resources.commands ?? []);
2930
- if (typeof resources.instructions === "object") output.push(resources.instructions);
2931
- return output;
2932
- }
2933
- function resourceKey(resource) {
2934
- return canonicalCandidateDigest$1(resource);
2935
- }
2936
- //#endregion
2937
- //#region src/candidate-execution/knowledge.ts
2938
- /** Environment variable containing the materialized candidate knowledge root. */
2939
- const CANDIDATE_KNOWLEDGE_ROOT_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_ROOT";
2940
- /** Environment variable containing the materialized retrieval configuration path. */
2941
- const CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG";
2942
- /** Deterministic, signed locations used by every candidate executor. */
2943
- function candidateKnowledgeExecutionPaths(taskRoot, hasRetrievalConfig) {
2944
- if (!posix.isAbsolute(taskRoot) || posix.normalize(taskRoot) !== taskRoot) throw new Error("candidate knowledge requires a normalized absolute task root");
2945
- const parent = posix.join(taskRoot, ".tangle");
2946
- return {
2947
- root: posix.join(parent, "knowledge"),
2948
- ...hasRetrievalConfig ? { retrievalConfig: posix.join(parent, "knowledge-retrieval-config.json") } : {}
2949
- };
2950
- }
2951
- /** Verify and detach the exact file-backed knowledge admitted by the bundle. */
2952
- async function prepareAgentCandidateKnowledge(candidate, ports, arm) {
2953
- const knowledge = candidate.bundle.knowledge;
2954
- if (!knowledge) return void 0;
2955
- const archive = await verifiedArtifactBytes(candidate, knowledge.snapshot.archive);
2956
- const retrievalConfig = knowledge.retrievalConfig ? await verifiedArtifactBytes(candidate, knowledge.retrievalConfig) : void 0;
2957
- const root = await mkdtemp(join(tmpdir(), "agent-candidate-knowledge-"));
2958
- try {
2959
- await ports.workspaces.materialize({
2960
- role: "knowledge",
2961
- snapshot: knowledge.snapshot,
2962
- archive,
2963
- destination: root
2964
- });
2965
- const expectedHash = arm === "baseline" ? knowledge.candidate.baseHash : knowledge.candidate.candidateHash;
2966
- const actualHash = `sha256:${await hashKnowledgeBase(root, knowledge.stateScope)}`;
2967
- if (actualHash !== expectedHash) throw new Error(`materialized ${arm} knowledge does not match its measured content: expected ${expectedHash}, got ${actualHash}`);
2968
- const files = await readMaterializedWorkspaceFiles(root, knowledge.snapshot.material);
2969
- return Object.freeze({
2970
- candidate: knowledge.candidate,
2971
- ...knowledge.stateScope ? { stateScope: Object.freeze({ ...knowledge.stateScope }) } : {},
2972
- snapshot: knowledge.snapshot,
2973
- files: Object.freeze(files.map((file) => Object.freeze({
2974
- path: file.path,
2975
- mode: file.mode,
2976
- bytes: Uint8Array.from(file.bytes)
2977
- }))),
2978
- ...retrievalConfig ? { retrievalConfig: Uint8Array.from(retrievalConfig) } : {}
2979
- });
2980
- } finally {
2981
- await rm(root, {
2982
- recursive: true,
2983
- force: true
2984
- });
2985
- }
2986
- }
2987
- //#endregion
2988
3740
  //#region src/candidate-execution/prepare.ts
2989
3741
  const MIN_RESERVATION_TTL_MS = 15 * 6e4;
2990
3742
  const PREPARED_HOLD_MARGIN_MS = 5 * 6e4;
@@ -3454,32 +4206,6 @@ async function prepareMemory(candidate, task, ports, preparationId, expiresAtMs,
3454
4206
  throw error;
3455
4207
  }
3456
4208
  }
3457
- function buildLaunch(candidate, task, profileFlags) {
3458
- const launch = candidate.bundle.execution.launch;
3459
- if (launch.kind === "container-command") return {
3460
- executable: launch.executable,
3461
- args: [...launch.args ?? [], ...profileFlags]
3462
- };
3463
- const candidateRoot = task.executionRoots.candidateRoot;
3464
- if (!candidateRoot) throw new Error("candidate entrypoint requires a container candidate root");
3465
- const entrypoint = posix.join(candidateRoot, launch.entrypoint);
3466
- const candidateArgs = launch.args ?? [];
3467
- if (launch.interpreter) return {
3468
- executable: launch.interpreter,
3469
- args: [
3470
- {
3471
- kind: "public",
3472
- value: entrypoint
3473
- },
3474
- ...candidateArgs,
3475
- ...profileFlags
3476
- ]
3477
- };
3478
- return {
3479
- executable: entrypoint,
3480
- args: [...candidateArgs, ...profileFlags]
3481
- };
3482
- }
3483
4209
  function mergePublicEnvironment(...records) {
3484
4210
  const output = {};
3485
4211
  for (const record of records) for (const [name, value] of Object.entries(record)) {
@@ -3493,50 +4219,6 @@ function mergePublicEnvironment(...records) {
3493
4219
  function unwrapPublicEnvironment(values) {
3494
4220
  return Object.fromEntries(Object.entries(values).map(([name, value]) => [name, requirePublicCandidateConfigValue(value, `env.${name}`)]));
3495
4221
  }
3496
- function modelRoutes(profile, requested) {
3497
- const routes = [{
3498
- kind: "primary",
3499
- requested
3500
- }];
3501
- if (profile.model?.small) routes.push({
3502
- kind: "small",
3503
- requested
3504
- });
3505
- for (const name of Object.keys(profile.modes ?? {}).sort()) if (profile.modes?.[name]?.model) routes.push({
3506
- kind: "mode",
3507
- name,
3508
- requested
3509
- });
3510
- for (const name of Object.keys(profile.subagents ?? {}).sort()) if (profile.subagents?.[name]?.model) routes.push({
3511
- kind: "subagent",
3512
- name,
3513
- requested
3514
- });
3515
- return routes;
3516
- }
3517
- function candidateEntrypointReceipt(candidate) {
3518
- const launch = candidate.bundle.execution.launch;
3519
- const workspace = candidate.bundle.execution.workspace;
3520
- if (launch.kind !== "candidate-entrypoint" || !workspace) return void 0;
3521
- const file = workspace.material.files.find((entry) => entry.path === launch.entrypoint);
3522
- if (!file) throw new Error("candidate entrypoint is absent from the verified workspace");
3523
- return {
3524
- path: file.path,
3525
- sha256: file.sha256,
3526
- byteLength: file.byteLength
3527
- };
3528
- }
3529
- function absoluteExecutionCwd(cwd, roots) {
3530
- const root = workspaceExecutionRoot(cwd.workspace, roots);
3531
- const absolute = cwd.path === "." ? root : posix.join(root, cwd.path);
3532
- if (absolute !== root && !absolute.startsWith(`${root}/`)) throw new Error("candidate cwd escapes its execution workspace");
3533
- return absolute;
3534
- }
3535
- function workspaceExecutionRoot(workspace, roots) {
3536
- const root = workspace === "task" ? roots.taskRoot : roots.candidateRoot;
3537
- if (!root) throw new Error(`candidate ${workspace} workspace root is missing`);
3538
- return root;
3539
- }
3540
4222
  function validateProtectedModelReservation(reservation, expectedLimits, preparationId, expiresAtMs) {
3541
4223
  if (!/^sha256:[a-f0-9]{64}$/.test(reservation.digest)) throw new Error("protected model reservation has an invalid identity digest");
3542
4224
  if (reservation.preparationId !== preparationId || reservation.expiresAtMs !== expiresAtMs) throw new Error("protected model reservation is not scoped to this preparation");
@@ -3552,34 +4234,7 @@ function assertEnvironmentDisjoint(publicEnv, traceEnv) {
3552
4234
  seen.add(name);
3553
4235
  }
3554
4236
  }
3555
- function modelLimits(limits) {
3556
- return {
3557
- maxModelCalls: limits.maxModelCalls,
3558
- maxInputTokens: limits.maxInputTokens,
3559
- maxOutputTokens: limits.maxOutputTokens,
3560
- maxCostUsd: limits.maxCostUsd
3561
- };
3562
- }
3563
- function exactProfileExecutorFiles(sourceFiles, expectedFiles) {
3564
- const byIdentity = new Map(sourceFiles.map((file) => [profileFileIdentity(file.root, file.relPath), file]));
3565
- if (byIdentity.size !== sourceFiles.length || sourceFiles.length !== expectedFiles.length) throw new Error("profile source files do not match the signed profile plan");
3566
- return expectedFiles.map((expected) => {
3567
- const source = byIdentity.get(profileFileIdentity(expected.root, expected.relPath));
3568
- const mode = source?.mode ?? 420;
3569
- const bytes = Buffer.from(source?.content ?? "", "utf8");
3570
- if (!source || !Number.isInteger(mode) || mode < 0 || mode > 511 || mode !== expected.mode || sha256Bytes$1(bytes) !== expected.contentSha256) throw new Error("profile source files do not match the signed profile plan");
3571
- return {
3572
- path: expected.relPath,
3573
- mode,
3574
- ...expected.root === "agent" ? { root: "agent" } : {},
3575
- bytes: Uint8Array.from(bytes)
3576
- };
3577
- });
3578
- }
3579
- function profileFileIdentity(root, relPath) {
3580
- return `${root ?? "workspace"}\0${relPath}`;
3581
- }
3582
4237
  //#endregion
3583
- export { recoveredTerminalRecord as A, candidateCleanupDeadline as C, assertTerminalAllowedInPhase as D, assertRecoveryMatchesStaged as E, terminalRecord as F, rejectedStage as M, requireStagedTerminal as N, assertTerminalMatchesClaim as O, sealTerminalDigest as P, candidateClaimFileInternals as S, withinCandidateCleanupDeadline as T, consumePreparedCandidateExecution as _, AGENT_CANDIDATE_EXECUTION_SUPPORT as a, assertAgentCandidateExecutionRoots as b, executePreparedAgentCandidate as c, sealAgentCandidateModelSettlement as d, usdToNanos as f, beginPreparedCandidateDisposal as g, assertPreparedCandidateIntegrity as h, candidateKnowledgeExecutionPaths as i, rejectedFinish as j, assertTerminalMatchesStaged as k, RecoveryAgentCandidateTraceStore as l, candidateExecutionClaim as m, CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV as n, verifiedResourceTextByDigest as o, sealAgentCandidateExecutorStopAcknowledgement as p, CANDIDATE_KNOWLEDGE_ROOT_ENV as r, verifyAgentCandidateBundle as s, prepareAgentCandidateExecution as t, persistCandidateModelSettlementEvidence as u, CANDIDATE_TRACE_ENV as v, candidateCleanupTimeout as w, InMemoryAgentCandidateExecutionClaimStore as x, CANDIDATE_TRACE_TAGS as y };
4238
+ export { candidateKnowledgeExecutionPaths as A, sealTerminalDigest as C, exactProcessProviderAsCandidateExecutor as D, sealAgentCandidateModelSettlement as E, CANDIDATE_TRACE_TAGS as F, verifiedResourceTextByDigest as M, verifyAgentCandidateBundle as N, CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV as O, CANDIDATE_TRACE_ENV as P, requireStagedTerminal as S, createProtectedAgentCandidateModelPort as T, assertTerminalMatchesClaim as _, sealAgentCandidateExecutorStopAcknowledgement as a, rejectedFinish as b, beginPreparedCandidateDisposal as c, candidateClaimFileInternals as d, candidateCleanupDeadline as f, assertTerminalAllowedInPhase as g, assertRecoveryMatchesStaged as h, persistCandidateModelSettlementEvidence as i, AGENT_CANDIDATE_EXECUTION_SUPPORT as j, CANDIDATE_KNOWLEDGE_ROOT_ENV as k, consumePreparedCandidateExecution as l, withinCandidateCleanupDeadline as m, executePreparedAgentCandidate as n, candidateExecutionClaim as o, candidateCleanupTimeout as p, RecoveryAgentCandidateTraceStore as r, assertPreparedCandidateIntegrity as s, prepareAgentCandidateExecution as t, InMemoryAgentCandidateExecutionClaimStore as u, assertTerminalMatchesStaged as v, terminalRecord as w, rejectedStage as x, recoveredTerminalRecord as y };
3584
4239
 
3585
- //# sourceMappingURL=prepare-CER-ZkPp.js.map
4240
+ //# sourceMappingURL=prepare-Bt0IouPq.js.map