@tangle-network/agent-runtime 0.340.0 → 0.342.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/{activation-D2PVljaw.js → activation-CWPmt0Do.js} +4 -4
  2. package/dist/{activation-D2PVljaw.js.map → activation-CWPmt0Do.js.map} +1 -1
  3. package/dist/{activation-DGDl4wwI.d.ts → activation-CXqtijue.d.ts} +2 -2
  4. package/dist/agent.d.ts +1 -1
  5. package/dist/agent.js +2 -2
  6. package/dist/{bundle-DNUq-OPW.js → bundle-Cwpit6Tg.js} +2 -2
  7. package/dist/{bundle-DNUq-OPW.js.map → bundle-Cwpit6Tg.js.map} +1 -1
  8. package/dist/candidate-execution/index.js +4 -4
  9. package/dist/{driver-control-acknowledgers-MTrs8HAF.js → coordination-manager-B5JsolDR.js} +4852 -4539
  10. package/dist/coordination-manager-B5JsolDR.js.map +1 -0
  11. package/dist/{delegate-CtJIS-tp.js → delegate-Rl-5paLJ.js} +2 -2
  12. package/dist/{delegate-CtJIS-tp.js.map → delegate-Rl-5paLJ.js.map} +1 -1
  13. package/dist/durable.d.ts +1 -1
  14. package/dist/durable.js +451 -358
  15. package/dist/durable.js.map +1 -1
  16. package/dist/{graph-DfWqp_1e.js → graph-Ce-59ZXn.js} +5 -5
  17. package/dist/{graph-DfWqp_1e.js.map → graph-Ce-59ZXn.js.map} +1 -1
  18. package/dist/{improve-CKRVQqzt.js → improve-BZXt2qM0.js} +837 -704
  19. package/dist/improve-BZXt2qM0.js.map +1 -0
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.js +9 -9
  22. package/dist/intelligence.d.ts +2 -2
  23. package/dist/intelligence.js +205 -191
  24. package/dist/intelligence.js.map +1 -1
  25. package/dist/kernel.d.ts +1 -1
  26. package/dist/kernel.js +9 -9
  27. package/dist/{loop-runner-DNWbTcVm.js → loop-runner-B0MV1-CD.js} +2 -2
  28. package/dist/{loop-runner-DNWbTcVm.js.map → loop-runner-B0MV1-CD.js.map} +1 -1
  29. package/dist/{loop-runner-C4EWEcXf.d.ts → loop-runner-CuhbgVGo.d.ts} +2 -2
  30. package/dist/loop-runner-bin.d.ts +1 -1
  31. package/dist/loop-runner-bin.js +1 -1
  32. package/dist/mcp/bin.js +3 -3
  33. package/dist/mcp/index.d.ts +1 -1
  34. package/dist/mcp/index.js +5 -5
  35. package/dist/{prepare-FzJoS68l.js → prepare-C-cWCyt3.js} +988 -735
  36. package/dist/prepare-C-cWCyt3.js.map +1 -0
  37. package/dist/{profile-DToH0XEs.js → profile-CbMw5hAn.js} +2 -2
  38. package/dist/{profile-DToH0XEs.js.map → profile-CbMw5hAn.js.map} +1 -1
  39. package/dist/profiles.d.ts +1 -1
  40. package/dist/{provision-supervisor-DqvWXmAE.js → provision-supervisor-DL6gEMQp.js} +444 -419
  41. package/dist/provision-supervisor-DL6gEMQp.js.map +1 -0
  42. package/dist/{runtime-C55Zgo1R.js → runtime-eghmj6W4.js} +1245 -1028
  43. package/dist/runtime-eghmj6W4.js.map +1 -0
  44. package/dist/{sandbox-profile-compat-DRr3JwDx.js → sandbox-profile-compat-FN2kab2-.js} +72 -72
  45. package/dist/{sandbox-profile-compat-DRr3JwDx.js.map → sandbox-profile-compat-FN2kab2-.js.map} +1 -1
  46. package/dist/{search-executor-ChOlRBgg.js → search-executor-rbjdZ3OD.js} +3 -3
  47. package/dist/{search-executor-ChOlRBgg.js.map → search-executor-rbjdZ3OD.js.map} +1 -1
  48. package/dist/{server-DkVBSN_S.js → server-BiK1Kcno.js} +4 -4
  49. package/dist/{server-DkVBSN_S.js.map → server-BiK1Kcno.js.map} +1 -1
  50. package/dist/{structural-rollout-C1LEk_zq.js → structural-rollout-BD9IN7K_.js} +3 -3
  51. package/dist/{structural-rollout-C1LEk_zq.js.map → structural-rollout-BD9IN7K_.js.map} +1 -1
  52. package/dist/{supervise-CaUAxZZP.js → supervise-DmOi7gll.js} +6346 -5447
  53. package/dist/supervise-DmOi7gll.js.map +1 -0
  54. package/dist/{supervisor-VXuN2OHT.js → supervisor-DUWcecAd.js} +13822 -12826
  55. package/dist/supervisor-DUWcecAd.js.map +1 -0
  56. package/dist/testing.d.ts +1 -1
  57. package/dist/testing.js +13 -13
  58. package/dist/tui/index.d.ts +1 -1
  59. package/dist/tui/index.js +1 -1
  60. package/dist/{types-DZ6L0Bv3.d.ts → types-Cgs89PQd.d.ts} +266 -356
  61. package/dist/workspace-store/index.js +273 -265
  62. package/dist/workspace-store/index.js.map +1 -1
  63. package/package.json +8 -8
  64. package/dist/driver-control-acknowledgers-MTrs8HAF.js.map +0 -1
  65. package/dist/improve-CKRVQqzt.js.map +0 -1
  66. package/dist/prepare-FzJoS68l.js.map +0 -1
  67. package/dist/provision-supervisor-DqvWXmAE.js.map +0 -1
  68. package/dist/runtime-C55Zgo1R.js.map +0 -1
  69. package/dist/supervise-CaUAxZZP.js.map +0 -1
  70. package/dist/supervisor-VXuN2OHT.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { A as verifyWorkspaceSnapshotArtifacts, B as sha256Bytes$1, D as verifyBytes, E as readVerifiedArtifact, F as canonicalCandidateDocument, H as hasControlCharacter, I as deepFreezeCandidate, L as embeddedCandidateArtifact, N as canonicalCandidateBytes$1, O as verifyMaterializedProfileWorkspace, P as canonicalCandidateDigest$1, R as immutableCandidateValue, S as artifactCacheKey, T as readMaterializedWorkspaceFiles, X as errorMessage, b as isWellFormedUnicode, d as readCandidateGitHubResource, f as verifyCandidateCode, k as verifyMaterializedWorkspace, m as verifyTaskOutcomePatch, p as verifyTaskCheckout, v as persistCandidateOutputArtifact, y as assertExactObjectKeys, z as omitTopLevelDigest } from "./sandbox-profile-compat-DRr3JwDx.js";
2
- 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-DToH0XEs.js";
1
+ import { A as verifyMaterializedProfileWorkspace, B as sha256Bytes$1, D as readMaterializedWorkspaceFiles, F as canonicalCandidateDocument, H as hasControlCharacter, I as deepFreezeCandidate, L as embeddedCandidateArtifact, M as verifyWorkspaceSnapshotArtifacts, N as canonicalCandidateBytes$1, O as readVerifiedArtifact, P as canonicalCandidateDigest$1, R as immutableCandidateValue, S as isWellFormedUnicode, X as errorMessage, b as persistCandidateOutputArtifact, d as readCandidateGitHubResource, f as verifyCandidateCode, j as verifyMaterializedWorkspace, k as verifyBytes, m as verifyTaskOutcomePatch, p as verifyTaskCheckout, w as artifactCacheKey, x as assertExactObjectKeys, z as omitTopLevelDigest } from "./sandbox-profile-compat-FN2kab2-.js";
2
+ 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-CbMw5hAn.js";
3
3
  import { i as redactProtectedValue, n as createProtectedRecordRedactor, r as redactProtectedReason, t as assertNoProtectedBytes } from "./protected-redaction-DFCeo4vg.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";
@@ -2334,89 +2334,6 @@ function retryLineageDigest(prepared, resultTimeoutMs) {
2334
2334
  });
2335
2335
  }
2336
2336
  //#endregion
2337
- //#region src/candidate-execution/executor-capture.ts
2338
- const sealedFinalCaptureBrand = Symbol("sealedAgentCandidateExecutorFinalCapture");
2339
- /** Validate and detach the only candidate-authored fields accepted from execution. */
2340
- function sealAgentCandidateProtectedRunCapture(value) {
2341
- const capture = requireRecord(value, "candidate execution capture");
2342
- assertExactObjectKeys(capture, ["executionId", "termination"], "candidate execution capture");
2343
- if (typeof capture.executionId !== "string" || capture.executionId.length === 0) throw new Error("candidate execution capture has an invalid executionId");
2344
- return Object.freeze({
2345
- executionId: capture.executionId,
2346
- termination: Object.freeze(agentCandidateTerminationSchema.parse(capture.termination))
2347
- });
2348
- }
2349
- /** Validate, detach, and freeze evaluator-owned evidence captured after process death. */
2350
- function sealAgentCandidateExecutorFinalCapture(value, expectedOutcome) {
2351
- const capture = requireRecord(value, "candidate final capture");
2352
- assertExactObjectKeys(capture, [], "candidate final capture", [
2353
- "taskOutcome",
2354
- "memoryAfter",
2355
- "evidence"
2356
- ]);
2357
- const taskOutcome = capture.taskOutcome ? sealTaskOutcomeCapture(capture.taskOutcome, expectedOutcome) : void 0;
2358
- const memoryAfter = capture.memoryAfter ? sealMemoryCapture(capture.memoryAfter) : void 0;
2359
- if (capture.evidence !== void 0 && !(capture.evidence instanceof Uint8Array)) throw new Error("candidate executor evidence must be a byte array");
2360
- const evidence = capture.evidence ? Uint8Array.from(capture.evidence) : void 0;
2361
- return Object.freeze({
2362
- ...taskOutcome ? { taskOutcome } : {},
2363
- ...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {},
2364
- ...evidence ? { evidence } : {},
2365
- [sealedFinalCaptureBrand]: true
2366
- });
2367
- }
2368
- /** Prove exact process death before any final evidence capture. */
2369
- function sealAgentCandidateExecutorStopAcknowledgement(value) {
2370
- const capture = requireRecord(value, "candidate stop acknowledgement");
2371
- assertExactObjectKeys(capture, ["stopped"], "candidate stop acknowledgement");
2372
- if (capture.stopped !== true) throw new Error("candidate stop acknowledgement does not prove process death");
2373
- }
2374
- function sealMemoryCapture(value) {
2375
- const capture = requireRecord(value, "candidate memory capture");
2376
- assertExactObjectKeys(capture, ["afterState", "archive"], "candidate memory capture");
2377
- if (!(capture.archive instanceof Uint8Array)) throw new Error("candidate memory capture archive must be a byte array");
2378
- return Object.freeze({
2379
- afterState: Object.freeze(agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState)),
2380
- archive: Uint8Array.from(capture.archive)
2381
- });
2382
- }
2383
- function sealTaskOutcomeCapture(value, expected) {
2384
- const capture = requireRecord(value, "candidate task capture");
2385
- if (capture.kind === "output") {
2386
- assertExactObjectKeys(capture, ["kind", "bytes"], "candidate task output capture");
2387
- if (expected.kind !== "output") throw new Error("candidate task output capture does not match the signed outcome kind");
2388
- if (!(capture.bytes instanceof Uint8Array)) throw new Error("candidate task output capture must contain a byte array");
2389
- if (capture.bytes.byteLength > expected.maxBytes) throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
2390
- return Object.freeze({
2391
- kind: "output",
2392
- bytes: Uint8Array.from(capture.bytes)
2393
- });
2394
- }
2395
- assertExactObjectKeys(capture, [
2396
- "kind",
2397
- "resultTree",
2398
- "afterState",
2399
- "archive",
2400
- "gitDiff"
2401
- ], "candidate task capture");
2402
- if (capture.kind !== "workspace") throw new Error("candidate task capture has an invalid outcome kind");
2403
- if (expected.kind !== "workspace") throw new Error("candidate workspace capture does not match the signed outcome kind");
2404
- 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");
2405
- if (!(capture.archive instanceof Uint8Array) || !(capture.gitDiff instanceof Uint8Array)) throw new Error("candidate task capture archive and gitDiff must be byte arrays");
2406
- const afterState = agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState);
2407
- return Object.freeze({
2408
- kind: "workspace",
2409
- resultTree: capture.resultTree,
2410
- afterState: Object.freeze(afterState),
2411
- archive: Uint8Array.from(capture.archive),
2412
- gitDiff: Uint8Array.from(capture.gitDiff)
2413
- });
2414
- }
2415
- function requireRecord(value, label) {
2416
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
2417
- return value;
2418
- }
2419
- //#endregion
2420
2337
  //#region src/candidate-execution/finalize.ts
2421
2338
  /** Builds a candidate run receipt exclusively from protected trace and memory evidence. */
2422
2339
  async function finalizeAgentCandidateRun(state, capture, traceStore, traceIdentity, settlement, evidence, protectedValues, writeRedactionReport, signal) {
@@ -3117,230 +3034,187 @@ async function persistFailureEvidence(state, reason, failureClass, termination,
3117
3034
  });
3118
3035
  }
3119
3036
  //#endregion
3120
- //#region src/candidate-execution/protected-trace-store.ts
3121
- /** Keep the identity key in evaluator-owned closures and expose only the redacting store to code. */
3122
- function createProtectedAgentCandidateTraceAccess(inner, protectedValues) {
3123
- const redactor = createProtectedRecordRedactor(protectedValues);
3124
- const pendingWrites = /* @__PURE__ */ new Set();
3125
- let acceptsWrites = true;
3126
- const write = (operation) => {
3127
- if (!acceptsWrites) return Promise.reject(/* @__PURE__ */ new Error("candidate trace writes are closed"));
3128
- let started;
3129
- try {
3130
- started = operation();
3131
- } catch (error) {
3132
- return Promise.reject(error);
3133
- }
3134
- let tracked;
3135
- tracked = started.finally(() => pendingWrites.delete(tracked));
3136
- pendingWrites.add(tracked);
3137
- return tracked;
3138
- };
3139
- const store = Object.freeze({
3140
- appendRun: (run) => write(() => inner.appendRun(redactor.record(run))),
3141
- updateRun: (runId, patch) => write(() => inner.updateRun(redactor.identifier(runId), redactor.record(patch))),
3142
- appendSpan: (span) => write(async () => {
3143
- if (span.kind === "llm") throw new Error("candidate executors cannot author protected model spans");
3144
- await inner.appendSpan(redactor.record(span));
3145
- }),
3146
- updateSpan: (spanId, patch) => write(async () => {
3147
- if (patch.kind === "llm") throw new Error("candidate executors cannot author protected model spans");
3148
- await inner.updateSpan(redactor.identifier(spanId), redactor.record(patch));
3149
- }),
3150
- appendEvent: (event) => write(() => inner.appendEvent(redactor.record(event))),
3151
- appendArtifact: (artifact) => write(() => inner.appendArtifact(redactor.record(artifact))),
3152
- appendBudgetEntry: (entry) => write(() => inner.appendBudgetEntry(redactor.record(entry))),
3153
- getRun: async (runId) => inner.getRun(redactor.identifier(runId)),
3154
- listRuns: async (filter) => inner.listRuns(filter ? redactor.query(filter) : void 0),
3155
- spans: async (filter) => inner.spans(filter ? redactor.query(filter) : void 0),
3156
- events: async (filter) => inner.events(filter ? redactor.query(filter) : void 0),
3157
- budget: async (runId) => inner.budget(redactor.identifier(runId)),
3158
- artifacts: async (runId) => inner.artifacts(redactor.identifier(runId))
3159
- });
3160
- return Object.freeze({
3161
- store,
3162
- closeWrites: async () => {
3163
- acceptsWrites = false;
3164
- await Promise.all([...pendingWrites]);
3165
- },
3166
- identity: (trace) => redactor.traceIdentity(trace),
3167
- report: () => redactor.report()
3168
- });
3037
+ //#region src/candidate-execution/execute-cleanup.ts
3038
+ /**
3039
+ * Failure and cleanup paths of an execution: closing isolated memory, settling the model grant,
3040
+ * recording a failed attempt's terminal result, and reporting why a run failed.
3041
+ */
3042
+ async function failBeforeActivation(run, error, reason) {
3043
+ const { prepared, state } = run;
3044
+ beginPreparedCandidateSettlement(prepared);
3045
+ const cleanupDeadlineAtMs = candidateCleanupDeadline(run.cleanupTimeoutMs);
3046
+ const [memoryClose, settled] = await Promise.all([closeMemoryAccess(state, reason, cleanupDeadlineAtMs), settleModelGrant(state, reason, cleanupDeadlineAtMs)]);
3047
+ const cleanupProven = memoryClose.closed && settled.settlement !== void 0;
3048
+ consumePreparedCandidateExecution(prepared, cleanupProven ? "failed" : "cleanup-failed");
3049
+ return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, memoryClose.error, settled.error, !cleanupProven ? /* @__PURE__ */ new Error("prepared access cleanup remains incomplete and may be retried by disposal") : void 0), []), void 0, settled.settlement?.usage ?? null);
3169
3050
  }
3170
- //#endregion
3171
- //#region src/candidate-execution/execute.ts
3172
- /** Executes and finalizes one durably claimed candidate without exposing an unproven result. */
3173
- async function executePreparedAgentCandidate(prepared, options) {
3174
- const initialState = assertPreparedCandidateIntegrity(prepared);
3175
- const cleanupTimeoutMs = candidateCleanupTimeout(options.cleanupTimeoutMs ?? initialState.cleanupTimeoutMs);
3176
- if (cleanupTimeoutMs > initialState.cleanupTimeoutMs) throw new Error("execution cleanup timeout exceeds the frozen preparation bound");
3177
- const resultTimeoutMs = candidateResultTimeout(options.resultTimeoutMs ?? initialState.resultTimeoutMs, initialState.resultTimeoutMs);
3178
- if (resultTimeoutMs > initialState.resultTimeoutMs) throw new Error("execution result timeout exceeds the frozen preparation bound");
3179
- let state;
3180
- try {
3181
- state = beginPreparedCandidateClaim(prepared);
3182
- } catch (error) {
3183
- return failedAgentCandidateRun(initialState, errorMessage(error));
3184
- }
3185
- try {
3186
- await assertPreparedCandidateWorkspaces(state);
3187
- } catch (error) {
3188
- return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
3189
- }
3190
- let preparationEvidence;
3191
- try {
3192
- const [executionPlan, materializationReceipt] = await Promise.all([persistCandidateOutputArtifact(options.outputArtifacts, {
3193
- executionId: state.executionId,
3194
- purpose: "execution-plan",
3195
- bytes: state.executionPlan.bytes
3196
- }), persistCandidateOutputArtifact(options.outputArtifacts, {
3197
- executionId: state.executionId,
3198
- purpose: "materialization-receipt",
3199
- bytes: state.materializationReceipt.bytes
3200
- })]);
3201
- preparationEvidence = Object.freeze({
3202
- executionPlan,
3203
- materializationReceipt
3204
- });
3205
- } catch (error) {
3206
- return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
3207
- }
3208
- let acquired;
3209
- try {
3210
- acquired = await options.claimStore.tryClaim(candidateExecutionClaim(prepared, preparationEvidence));
3211
- } catch (error) {
3212
- return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
3051
+ /** Fail a claimed attempt before the candidate may run: clean up, then record the failure. */
3052
+ async function failClaimedExecution(run, lease, error, failureClass, access = {}) {
3053
+ const { prepared, state, claimStore, outputArtifacts } = run;
3054
+ beginPreparedCandidateSettlement(prepared);
3055
+ const cleanupDeadlineAtMs = candidateCleanupDeadline(run.cleanupTimeoutMs);
3056
+ const [memoryClose, settled] = await Promise.all([closeMemoryAccess(state, "failed", cleanupDeadlineAtMs), settleModelGrant(state, "failed", cleanupDeadlineAtMs)]);
3057
+ const protectedValues = protectedEnvironmentValues(access.activation, access.memoryActivation);
3058
+ const safeReason = redactProtectedReason(joinErrors(error, memoryClose.error, settled.error), protectedValues);
3059
+ let finishFailed = false;
3060
+ let persistenceFailure;
3061
+ if (settled.settlement && memoryClose.closed) try {
3062
+ const modelSettlement = await withinCandidateCleanupDeadline(() => persistCandidateModelSettlement(state, settled.settlement, outputArtifacts), lease.expiresAtMs, "candidate pre-run model-settlement persistence");
3063
+ const failureEvidence = await withinCandidateCleanupDeadline(() => persistFailureEvidence(state, safeReason, failureClass, void 0, outputArtifacts), lease.expiresAtMs, "candidate pre-run failure-evidence persistence");
3064
+ finishFailed = !await finishClaim(claimStore, lease, {
3065
+ status: "failed",
3066
+ failureClass,
3067
+ usage: settled.settlement.usage,
3068
+ modelSettlement: modelSettlement.artifact,
3069
+ failureEvidence
3070
+ }, lease.expiresAtMs);
3071
+ } catch (persistenceError) {
3072
+ finishFailed = true;
3073
+ persistenceFailure = persistenceError;
3213
3074
  }
3214
- if (!acquired.acquired) return await failBeforeActivation(prepared, state, /* @__PURE__ */ new Error(acquired.reason === "retry-not-eligible" ? `candidate execution retry is not eligible: ${acquired.detail}` : "candidate execution attempt is already claimed"), "replayed", cleanupTimeoutMs);
3215
- markPreparedCandidateClaimed(prepared);
3216
- const postRunWindowMs = candidatePostRunWindowMs(cleanupTimeoutMs, resultTimeoutMs);
3217
- const deadlineAtMs = acquired.claim.leaseExpiresAtMs - candidatePostRunWindowMs(state.cleanupTimeoutMs, state.resultTimeoutMs);
3218
- const requiredLeaseExpiry = deadlineAtMs + postRunWindowMs;
3219
- if (Date.now() >= deadlineAtMs || deadlineAtMs > state.reservationExpiresAtMs || requiredLeaseExpiry > acquired.lease.expiresAtMs) return await failClaimedExecution(prepared, state, acquired.lease, options.claimStore, options.outputArtifacts, /* @__PURE__ */ new Error("candidate claim no longer covers its full execution and cleanup window"), "failed", cleanupTimeoutMs, "pre-model-infrastructure");
3220
- let activation;
3075
+ consumePreparedCandidateExecution(prepared, "failed");
3076
+ return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(safeReason, persistenceFailure, memoryClose.error, settled.error, !memoryClose.closed || !settled.settlement ? /* @__PURE__ */ new Error("candidate claim remains recoverable until protected cleanup is proven") : void 0, finishFailed ? /* @__PURE__ */ new Error("candidate execution terminal record could not be persisted") : void 0), protectedValues), void 0, settled.settlement?.usage ?? null);
3077
+ }
3078
+ async function closeMemoryAccess(state, reason, cleanupDeadlineAtMs) {
3079
+ if (state.memory.mode === "disabled") return { closed: true };
3221
3080
  try {
3222
- const activated = await withinCandidateCleanupDeadline(() => state.ports.models.activateGrant({
3223
- executionId: state.executionId,
3224
- preparationId: state.preparationId,
3225
- grantDigest: state.modelReservation.digest,
3226
- resolved: state.resolvedModel,
3227
- deadlineAtMs
3228
- }), Math.min(deadlineAtMs, candidateCleanupDeadline(cleanupTimeoutMs)), "protected model activation");
3229
- activation = Object.freeze({ env: Object.freeze({ ...activated.env }) });
3230
- } catch (error) {
3231
- return await failClaimedExecution(prepared, state, acquired.lease, options.claimStore, options.outputArtifacts, new Error("protected model activation failed", { cause: error }), "failed", cleanupTimeoutMs, "pre-model-infrastructure");
3232
- }
3233
- let memoryActivation;
3234
- if (state.memory.mode === "isolated") try {
3235
3081
  const reservation = state.memoryReservation;
3236
3082
  if (!reservation) throw new Error("isolated memory reservation is missing");
3237
- const activated = await withinCandidateCleanupDeadline(() => state.ports.memory.activate({
3083
+ const closed = await withinCandidateCleanupDeadline(() => state.ports.memory.close({
3238
3084
  executionId: state.executionId,
3239
3085
  preparationId: reservation.preparationId,
3240
3086
  accessDigest: reservation.accessDigest,
3241
3087
  effectiveNamespace: reservation.effectiveNamespace,
3242
- deadlineAtMs
3243
- }), Math.min(deadlineAtMs, candidateCleanupDeadline(cleanupTimeoutMs)), "isolated memory activation");
3244
- memoryActivation = Object.freeze({ env: Object.freeze({ ...activated.env }) });
3088
+ reason
3089
+ }), cleanupDeadlineAtMs, "isolated memory closure");
3090
+ if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("isolated memory access did not acknowledge closure");
3091
+ return { closed: true };
3245
3092
  } catch (error) {
3246
- return await failClaimedExecution(prepared, state, acquired.lease, options.claimStore, options.outputArtifacts, new Error("isolated memory activation failed", { cause: error }), "failed", cleanupTimeoutMs, "pre-model-infrastructure", activation);
3093
+ return {
3094
+ closed: false,
3095
+ error
3096
+ };
3247
3097
  }
3248
- let request;
3098
+ }
3099
+ async function settleModelGrant(state, reason, cleanupDeadlineAtMs) {
3249
3100
  try {
3250
- request = beginPreparedCandidateRun(prepared, activation, memoryActivation).request;
3101
+ return { settlement: sealAgentCandidateModelSettlement(await withinCandidateCleanupDeadline(() => state.ports.models.settleGrant({
3102
+ executionId: state.executionId,
3103
+ preparationId: state.preparationId,
3104
+ grantDigest: state.modelReservation.digest,
3105
+ resolved: state.resolvedModel,
3106
+ reason
3107
+ }), cleanupDeadlineAtMs, "protected model settlement"), {
3108
+ preparationId: state.preparationId,
3109
+ grantDigest: state.modelReservation.digest,
3110
+ model: state.resolvedModel.model
3111
+ }) };
3251
3112
  } catch (error) {
3252
- return await failClaimedExecution(prepared, state, acquired.lease, options.claimStore, options.outputArtifacts, error, "failed", cleanupTimeoutMs, "pre-model-infrastructure", activation, memoryActivation);
3113
+ return { error: new Error("protected model settlement failed", { cause: error }) };
3253
3114
  }
3115
+ }
3116
+ async function finishClaim(store, lease, terminal, deadlineAtMs) {
3254
3117
  try {
3255
- if ((await options.claimStore.markCandidateMayRun(acquired.lease)).phase !== "candidate-may-run") throw new Error("candidate claim did not persist the candidate-may-run phase");
3256
- } catch (error) {
3257
- return await failClaimedExecution(prepared, state, acquired.lease, options.claimStore, options.outputArtifacts, new Error("candidate execution phase persistence failed", { cause: error }), "failed", cleanupTimeoutMs, "pre-model-infrastructure", activation, memoryActivation);
3118
+ const staged = await withinCandidateCleanupDeadline(() => store.stageTerminal(lease, terminal), deadlineAtMs ?? lease.expiresAtMs, "candidate terminal staging");
3119
+ if (!staged.staged && !staged.exactReplay) return false;
3120
+ const result = await withinCandidateCleanupDeadline(() => store.finish(lease, staged.terminal.terminalDigest), deadlineAtMs ?? lease.expiresAtMs, "candidate terminal publication");
3121
+ return result.finished || result.exactReplay;
3122
+ } catch {
3123
+ return false;
3258
3124
  }
3259
- if (Date.now() >= deadlineAtMs) return await failClaimedExecution(prepared, state, acquired.lease, options.claimStore, options.outputArtifacts, /* @__PURE__ */ new Error("candidate execution deadline elapsed while persisting its launch phase"), "failed", cleanupTimeoutMs, "unknown", activation, memoryActivation);
3260
- const protectedValues = protectedEnvironmentValues(activation, memoryActivation);
3261
- const protectedTrace = createProtectedAgentCandidateTraceAccess(options.traceStore, protectedValues);
3262
- const persistedTrace = protectedTrace.identity(state.trace);
3263
- const execution = await runAndStopExecutor(options.executor, request, state.benchmarkTask.outcome, protectedTrace.store, deadlineAtMs, cleanupTimeoutMs);
3264
- beginPreparedCandidateSettlement(prepared);
3265
- const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
3266
- const accessReason = execution.kind === "timeout" || execution.termination?.kind === "timeout" ? "timeout" : execution.kind === "capture" ? "completed" : "failed";
3267
- const traceClosure = withinCandidateCleanupDeadline(() => protectedTrace.closeWrites(), cleanupDeadlineAtMs, "candidate trace write closure").then(() => ({
3268
- closed: true,
3269
- error: void 0
3270
- }), (error) => ({
3271
- closed: false,
3272
- error
3273
- }));
3274
- const [traceClose, memoryClose, settlementResult] = await Promise.all([
3275
- traceClosure,
3276
- closeMemoryAccess(state, accessReason, cleanupDeadlineAtMs),
3277
- settleModelGrant(state, accessReason, cleanupDeadlineAtMs)
3125
+ }
3126
+ function protectedEnvironmentValues(activation, memoryActivation) {
3127
+ return [...Object.values(activation?.env ?? {}), ...Object.values(memoryActivation?.env ?? {})];
3128
+ }
3129
+ function joinErrors(...errors) {
3130
+ return errors.filter((error) => error !== void 0).map(errorMessage).join("; ");
3131
+ }
3132
+ //#endregion
3133
+ //#region src/candidate-execution/executor-capture.ts
3134
+ const sealedFinalCaptureBrand = Symbol("sealedAgentCandidateExecutorFinalCapture");
3135
+ /** Validate and detach the only candidate-authored fields accepted from execution. */
3136
+ function sealAgentCandidateProtectedRunCapture(value) {
3137
+ const capture = requireRecord(value, "candidate execution capture");
3138
+ assertExactObjectKeys(capture, ["executionId", "termination"], "candidate execution capture");
3139
+ if (typeof capture.executionId !== "string" || capture.executionId.length === 0) throw new Error("candidate execution capture has an invalid executionId");
3140
+ return Object.freeze({
3141
+ executionId: capture.executionId,
3142
+ termination: Object.freeze(agentCandidateTerminationSchema.parse(capture.termination))
3143
+ });
3144
+ }
3145
+ /** Validate, detach, and freeze evaluator-owned evidence captured after process death. */
3146
+ function sealAgentCandidateExecutorFinalCapture(value, expectedOutcome) {
3147
+ const capture = requireRecord(value, "candidate final capture");
3148
+ assertExactObjectKeys(capture, [], "candidate final capture", [
3149
+ "taskOutcome",
3150
+ "memoryAfter",
3151
+ "evidence"
3278
3152
  ]);
3279
- if (!execution.processStopped || !traceClose.closed || !settlementResult.settlement || !memoryClose.closed) {
3280
- consumePreparedCandidateExecution(prepared, "failed");
3281
- return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(execution.error, !execution.processStopped ? /* @__PURE__ */ new Error("candidate process termination is not proven") : void 0, traceClose.error, memoryClose.error, settlementResult.error ?? (!settlementResult.settlement ? /* @__PURE__ */ new Error("model settlement failed") : void 0), /* @__PURE__ */ new Error("candidate claim remains recoverable until protected cleanup is proven")), protectedValues), execution.termination, settlementResult.settlement?.usage ?? null);
3282
- }
3283
- let modelSettlement;
3284
- try {
3285
- modelSettlement = await withinCandidateCleanupDeadline(() => persistCandidateModelSettlement(state, settlementResult.settlement, options.outputArtifacts), candidateCleanupDeadline(cleanupTimeoutMs), "candidate model settlement persistence");
3286
- } catch (error) {
3287
- consumePreparedCandidateExecution(prepared, "failed");
3288
- return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, /* @__PURE__ */ new Error("candidate claim remains recoverable until settlement evidence is durable")), protectedValues), execution.termination, settlementResult.settlement.usage);
3289
- }
3290
- let result;
3291
- const failureClass = execution.kind === "error" ? "execution" : "post-model-infrastructure";
3292
- if (execution.kind === "error") result = failedAgentCandidateRun(state, redactProtectedReason(errorMessage(execution.error), protectedValues), execution.termination, settlementResult.settlement.usage);
3293
- else if (!execution.finalCapture.taskOutcome) result = failedAgentCandidateRun(state, "candidate executor stopped without a captured task outcome", execution.termination, settlementResult.settlement.usage);
3294
- else {
3295
- const capture = execution.kind === "capture" ? execution.capture : {
3296
- executionId: state.executionId,
3297
- termination: execution.termination
3298
- };
3299
- try {
3300
- result = await withinCandidateResultDeadline(async (signal) => {
3301
- await appendAuthoritativeModelSettlementSpans(options.traceStore, persistedTrace.runId, settlementResult.settlement);
3302
- const { persistedCapture, taskOutcome } = await persistVerifiedAgentCandidateExecutorCapture(state, execution.finalCapture, options.outputArtifacts, protectedValues, signal);
3303
- const benchmarkResult = await persistCandidateBenchmarkResult(state, capture.termination, taskOutcome, options.grader, options.outputArtifacts, protectedValues, signal);
3304
- return await finalizeAgentCandidateRun(state, capture, options.traceStore, persistedTrace, settlementResult.settlement, {
3305
- finalCapture: execution.finalCapture,
3306
- persistedCapture,
3307
- modelSettlement,
3308
- taskOutcome,
3309
- benchmarkResult,
3310
- outputArtifacts: options.outputArtifacts
3311
- }, protectedValues, protectedTrace.report(), signal);
3312
- }, Math.min(Date.now() + resultTimeoutMs, acquired.lease.expiresAtMs - candidateTerminalWindowMs(cleanupTimeoutMs)), "candidate evidence finalization");
3313
- } catch (error) {
3314
- result = failedAgentCandidateRun(state, redactProtectedReason(errorMessage(error), protectedValues), execution.termination, settlementResult.settlement.usage);
3315
- }
3316
- }
3317
- let terminal;
3318
- try {
3319
- terminal = result.succeeded ? {
3320
- status: "succeeded",
3321
- usage: settlementResult.settlement.usage,
3322
- modelSettlement: result.artifacts.modelSettlement,
3323
- taskOutcome: result.artifacts.taskOutcome,
3324
- benchmarkResult: result.artifacts.benchmarkResult,
3325
- runReceipt: result.artifacts.runReceipt
3326
- } : {
3327
- status: "failed",
3328
- failureClass,
3329
- usage: settlementResult.settlement.usage,
3330
- modelSettlement: modelSettlement.artifact,
3331
- failureEvidence: await withinCandidateCleanupDeadline(() => persistFailureEvidence(state, result.reason, failureClass, execution.termination, options.outputArtifacts), acquired.lease.expiresAtMs, "candidate failure-evidence persistence")
3332
- };
3333
- } catch (error) {
3334
- consumePreparedCandidateExecution(prepared, "failed");
3335
- return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, /* @__PURE__ */ new Error("candidate claim remains recoverable until terminal evidence is durable")), protectedValues), execution.termination, settlementResult.settlement.usage);
3336
- }
3337
- if (await finishClaim(options.claimStore, acquired.lease, terminal, acquired.lease.expiresAtMs)) {
3338
- consumePreparedCandidateExecution(prepared, result.succeeded ? "succeeded" : "failed");
3339
- return result;
3153
+ const taskOutcome = capture.taskOutcome ? sealTaskOutcomeCapture(capture.taskOutcome, expectedOutcome) : void 0;
3154
+ const memoryAfter = capture.memoryAfter ? sealMemoryCapture(capture.memoryAfter) : void 0;
3155
+ if (capture.evidence !== void 0 && !(capture.evidence instanceof Uint8Array)) throw new Error("candidate executor evidence must be a byte array");
3156
+ const evidence = capture.evidence ? Uint8Array.from(capture.evidence) : void 0;
3157
+ return Object.freeze({
3158
+ ...taskOutcome ? { taskOutcome } : {},
3159
+ ...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {},
3160
+ ...evidence ? { evidence } : {},
3161
+ [sealedFinalCaptureBrand]: true
3162
+ });
3163
+ }
3164
+ /** Prove exact process death before any final evidence capture. */
3165
+ function sealAgentCandidateExecutorStopAcknowledgement(value) {
3166
+ const capture = requireRecord(value, "candidate stop acknowledgement");
3167
+ assertExactObjectKeys(capture, ["stopped"], "candidate stop acknowledgement");
3168
+ if (capture.stopped !== true) throw new Error("candidate stop acknowledgement does not prove process death");
3169
+ }
3170
+ function sealMemoryCapture(value) {
3171
+ const capture = requireRecord(value, "candidate memory capture");
3172
+ assertExactObjectKeys(capture, ["afterState", "archive"], "candidate memory capture");
3173
+ if (!(capture.archive instanceof Uint8Array)) throw new Error("candidate memory capture archive must be a byte array");
3174
+ return Object.freeze({
3175
+ afterState: Object.freeze(agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState)),
3176
+ archive: Uint8Array.from(capture.archive)
3177
+ });
3178
+ }
3179
+ function sealTaskOutcomeCapture(value, expected) {
3180
+ const capture = requireRecord(value, "candidate task capture");
3181
+ if (capture.kind === "output") {
3182
+ assertExactObjectKeys(capture, ["kind", "bytes"], "candidate task output capture");
3183
+ if (expected.kind !== "output") throw new Error("candidate task output capture does not match the signed outcome kind");
3184
+ if (!(capture.bytes instanceof Uint8Array)) throw new Error("candidate task output capture must contain a byte array");
3185
+ if (capture.bytes.byteLength > expected.maxBytes) throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
3186
+ return Object.freeze({
3187
+ kind: "output",
3188
+ bytes: Uint8Array.from(capture.bytes)
3189
+ });
3340
3190
  }
3341
- consumePreparedCandidateExecution(prepared, "failed");
3342
- return failedAgentCandidateRun(state, "candidate execution terminal record could not be persisted", execution.termination, settlementResult.settlement.usage);
3191
+ assertExactObjectKeys(capture, [
3192
+ "kind",
3193
+ "resultTree",
3194
+ "afterState",
3195
+ "archive",
3196
+ "gitDiff"
3197
+ ], "candidate task capture");
3198
+ if (capture.kind !== "workspace") throw new Error("candidate task capture has an invalid outcome kind");
3199
+ if (expected.kind !== "workspace") throw new Error("candidate workspace capture does not match the signed outcome kind");
3200
+ 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");
3201
+ if (!(capture.archive instanceof Uint8Array) || !(capture.gitDiff instanceof Uint8Array)) throw new Error("candidate task capture archive and gitDiff must be byte arrays");
3202
+ const afterState = agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState);
3203
+ return Object.freeze({
3204
+ kind: "workspace",
3205
+ resultTree: capture.resultTree,
3206
+ afterState: Object.freeze(afterState),
3207
+ archive: Uint8Array.from(capture.archive),
3208
+ gitDiff: Uint8Array.from(capture.gitDiff)
3209
+ });
3343
3210
  }
3211
+ function requireRecord(value, label) {
3212
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
3213
+ return value;
3214
+ }
3215
+ //#endregion
3216
+ //#region src/candidate-execution/execute-executor.ts
3217
+ /** Run the executor until it returns or the deadline passes, then stop and capture it. */
3344
3218
  async function runAndStopExecutor(executor, request, expectedOutcome, traceStore, deadlineAtMs, cleanupTimeoutMs) {
3345
3219
  const timeoutMs = request.hardLimits.timeoutMs;
3346
3220
  const timeoutError = new CandidateExecutionDeadlineError(timeoutMs);
@@ -3353,113 +3227,49 @@ async function runAndStopExecutor(executor, request, expectedOutcome, traceStore
3353
3227
  },
3354
3228
  processStopped: true
3355
3229
  };
3356
- const controller = new AbortController();
3357
- let timer;
3358
- let timedOut = false;
3359
- let capture;
3360
- let executionError;
3361
- const executionPromise = Promise.resolve().then(() => executor.execute(request, {
3362
- traceStore,
3363
- signal: controller.signal,
3364
- deadlineAtMs
3365
- }));
3366
- executionPromise.catch(() => void 0);
3367
- const deadlinePromise = new Promise((_resolve, reject) => {
3368
- timer = setTimeout(() => {
3369
- timedOut = true;
3370
- controller.abort(timeoutError);
3371
- reject(timeoutError);
3372
- }, Math.max(0, deadlineAtMs - Date.now()));
3373
- });
3374
- deadlinePromise.catch(() => void 0);
3375
- try {
3376
- capture = sealAgentCandidateProtectedRunCapture(await Promise.race([executionPromise, deadlinePromise]));
3377
- } catch (error) {
3378
- executionError = error;
3379
- }
3380
- if (!timedOut && capture && capture.executionId !== request.executionId) {
3381
- executionError = /* @__PURE__ */ new Error("candidate execution capture id does not match the request");
3382
- capture = void 0;
3383
- } else if (!timedOut && capture && Date.now() >= deadlineAtMs) {
3384
- timedOut = true;
3385
- executionError = timeoutError;
3386
- capture = void 0;
3387
- } else if (!timedOut && capture?.termination.kind === "timeout") {
3388
- executionError = /* @__PURE__ */ new Error("candidate executor cannot declare the runtime-owned timeout");
3389
- capture = void 0;
3390
- }
3391
- if (!capture || timedOut) controller.abort(executionError);
3392
- const stopReason = timedOut ? "timeout" : capture ? "completed" : "failed";
3230
+ const run = await executeUntilDeadline(executor, request, traceStore, deadlineAtMs, timeoutError);
3231
+ rejectAmbiguousCapture(run, request, deadlineAtMs);
3232
+ const { controller } = run;
3233
+ if (!run.capture || run.timedOut) controller.abort(run.executionError);
3234
+ const stopReason = run.timedOut ? "timeout" : run.capture ? "completed" : "failed";
3393
3235
  const cleanupDeadlineAtMs = Date.now() + cleanupTimeoutMs;
3394
- try {
3395
- sealAgentCandidateExecutorStopAcknowledgement(await withinCandidateCleanupDeadline((cleanupSignal) => executor.stop({
3396
- executionId: request.executionId,
3397
- executionPlanDigest: request.executionPlan.value.digest
3398
- }, {
3399
- traceStore,
3400
- reason: stopReason,
3401
- signal: cleanupSignal,
3402
- deadlineAtMs: cleanupDeadlineAtMs
3403
- }), cleanupDeadlineAtMs, "candidate process termination"));
3404
- } catch (stopError) {
3405
- let disposalError;
3406
- try {
3407
- await disposeExecutor(executor, request, cleanupDeadlineAtMs);
3408
- } catch (error) {
3409
- disposalError = error;
3410
- }
3411
- if (timer) clearTimeout(timer);
3412
- controller.abort(stopError);
3236
+ const timeoutTermination = () => run.timedOut ? { termination: {
3237
+ kind: "timeout",
3238
+ timeoutMs
3239
+ } } : {};
3240
+ const stop = await stopExecutor(executor, request, traceStore, stopReason, cleanupDeadlineAtMs);
3241
+ if (!stop.stopped) {
3242
+ const disposalError = await disposalFailure(executor, request, cleanupDeadlineAtMs);
3243
+ if (run.timer) clearTimeout(run.timer);
3244
+ controller.abort(stop.error);
3413
3245
  return {
3414
3246
  kind: "error",
3415
- error: new Error(joinErrors(executionError, stopError, disposalError)),
3416
- ...timedOut ? { termination: {
3417
- kind: "timeout",
3418
- timeoutMs
3419
- } } : {},
3247
+ error: new Error(joinErrors(run.executionError, stop.error, disposalError)),
3248
+ ...timeoutTermination(),
3420
3249
  processStopped: false
3421
3250
  };
3422
3251
  }
3423
- let finalCapture;
3424
- let finalCaptureError;
3425
- try {
3426
- finalCapture = sealAgentCandidateExecutorFinalCapture(await withinCandidateCleanupDeadline((cleanupSignal) => executor.capture({
3427
- executionId: request.executionId,
3428
- executionPlanDigest: request.executionPlan.value.digest
3429
- }, {
3430
- traceStore,
3431
- signal: cleanupSignal
3432
- }), cleanupDeadlineAtMs, "candidate final evidence capture"), expectedOutcome);
3433
- } catch (captureError) {
3434
- finalCaptureError = captureError;
3435
- }
3436
- let disposalError;
3437
- try {
3438
- await disposeExecutor(executor, request, cleanupDeadlineAtMs);
3439
- } catch (disposeError) {
3440
- disposalError = disposeError;
3441
- }
3442
- if (finalCaptureError || disposalError || !finalCapture) {
3443
- if (timer) clearTimeout(timer);
3444
- controller.abort(finalCaptureError ?? disposalError);
3252
+ const final = await captureFinalEvidence(executor, request, traceStore, expectedOutcome, cleanupDeadlineAtMs);
3253
+ const disposalError = await disposalFailure(executor, request, cleanupDeadlineAtMs);
3254
+ const { finalCapture } = final;
3255
+ if (final.error || disposalError || !finalCapture) {
3256
+ if (run.timer) clearTimeout(run.timer);
3257
+ controller.abort(final.error ?? disposalError);
3445
3258
  return {
3446
3259
  kind: "error",
3447
- error: new Error(joinErrors(executionError, finalCaptureError, disposalError)),
3448
- ...timedOut ? { termination: {
3449
- kind: "timeout",
3450
- timeoutMs
3451
- } } : {},
3260
+ error: new Error(joinErrors(run.executionError, final.error, disposalError)),
3261
+ ...timeoutTermination(),
3452
3262
  processStopped: true
3453
3263
  };
3454
3264
  }
3455
3265
  if (Date.now() >= deadlineAtMs) {
3456
- timedOut = true;
3457
- executionError = timeoutError;
3458
- capture = void 0;
3266
+ run.timedOut = true;
3267
+ run.executionError = timeoutError;
3268
+ run.capture = void 0;
3459
3269
  controller.abort(timeoutError);
3460
3270
  }
3461
- if (timer) clearTimeout(timer);
3462
- if (timedOut) return {
3271
+ if (run.timer) clearTimeout(run.timer);
3272
+ if (run.timedOut) return {
3463
3273
  kind: "timeout",
3464
3274
  termination: {
3465
3275
  kind: "timeout",
@@ -3468,144 +3278,603 @@ async function runAndStopExecutor(executor, request, expectedOutcome, traceStore
3468
3278
  finalCapture,
3469
3279
  processStopped: true
3470
3280
  };
3471
- if (executionError || !capture) return {
3281
+ if (run.executionError || !run.capture) return {
3472
3282
  kind: "error",
3473
- error: executionError ?? /* @__PURE__ */ new Error("candidate executor returned no capture"),
3283
+ error: run.executionError ?? /* @__PURE__ */ new Error("candidate executor returned no capture"),
3474
3284
  finalCapture,
3475
3285
  processStopped: true
3476
3286
  };
3477
3287
  return {
3478
3288
  kind: "capture",
3479
- capture,
3480
- termination: capture.termination,
3289
+ capture: run.capture,
3290
+ termination: run.capture.termination,
3481
3291
  finalCapture,
3482
3292
  processStopped: true
3483
3293
  };
3484
3294
  }
3485
- async function disposeExecutor(executor, request, cleanupDeadlineAtMs) {
3486
- const dispose = executor.dispose;
3487
- if (!dispose) return;
3488
- const disposed = await withinCandidateCleanupDeadline((cleanupSignal) => dispose.call(executor, {
3489
- executionId: request.executionId,
3490
- executionPlanDigest: request.executionPlan.value.digest
3491
- }, { signal: cleanupSignal }), cleanupDeadlineAtMs, "candidate execution resource disposal");
3492
- if (disposed?.disposed !== true || Object.keys(disposed).some((key) => key !== "disposed")) throw new Error("candidate executor did not acknowledge resource disposal");
3295
+ async function executeUntilDeadline(executor, request, traceStore, deadlineAtMs, timeoutError) {
3296
+ const run = {
3297
+ controller: new AbortController(),
3298
+ timeoutError,
3299
+ timer: void 0,
3300
+ timedOut: false,
3301
+ capture: void 0,
3302
+ executionError: void 0
3303
+ };
3304
+ const executionPromise = Promise.resolve().then(() => executor.execute(request, {
3305
+ traceStore,
3306
+ signal: run.controller.signal,
3307
+ deadlineAtMs
3308
+ }));
3309
+ executionPromise.catch(() => void 0);
3310
+ const deadlinePromise = new Promise((_resolve, reject) => {
3311
+ run.timer = setTimeout(() => {
3312
+ run.timedOut = true;
3313
+ run.controller.abort(timeoutError);
3314
+ reject(timeoutError);
3315
+ }, Math.max(0, deadlineAtMs - Date.now()));
3316
+ });
3317
+ deadlinePromise.catch(() => void 0);
3318
+ try {
3319
+ run.capture = sealAgentCandidateProtectedRunCapture(await Promise.race([executionPromise, deadlinePromise]));
3320
+ } catch (error) {
3321
+ run.executionError = error;
3322
+ }
3323
+ return run;
3324
+ }
3325
+ /** Refuse a capture for another execution, one at the deadline, or one that claims the timeout. */
3326
+ function rejectAmbiguousCapture(run, request, deadlineAtMs) {
3327
+ const { capture } = run;
3328
+ if (!run.timedOut && capture && capture.executionId !== request.executionId) {
3329
+ run.executionError = /* @__PURE__ */ new Error("candidate execution capture id does not match the request");
3330
+ run.capture = void 0;
3331
+ } else if (!run.timedOut && capture && Date.now() >= deadlineAtMs) {
3332
+ run.timedOut = true;
3333
+ run.executionError = run.timeoutError;
3334
+ run.capture = void 0;
3335
+ } else if (!run.timedOut && capture?.termination.kind === "timeout") {
3336
+ run.executionError = /* @__PURE__ */ new Error("candidate executor cannot declare the runtime-owned timeout");
3337
+ run.capture = void 0;
3338
+ }
3493
3339
  }
3494
- async function failBeforeActivation(prepared, state, error, reason, cleanupTimeoutMs) {
3495
- beginPreparedCandidateSettlement(prepared);
3496
- const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
3497
- const [memoryClose, settled] = await Promise.all([closeMemoryAccess(state, reason, cleanupDeadlineAtMs), settleModelGrant(state, reason, cleanupDeadlineAtMs)]);
3498
- const cleanupProven = memoryClose.closed && settled.settlement !== void 0;
3499
- consumePreparedCandidateExecution(prepared, cleanupProven ? "failed" : "cleanup-failed");
3500
- return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, memoryClose.error, settled.error, !cleanupProven ? /* @__PURE__ */ new Error("prepared access cleanup remains incomplete and may be retried by disposal") : void 0), []), void 0, settled.settlement?.usage ?? null);
3340
+ async function stopExecutor(executor, request, traceStore, reason, cleanupDeadlineAtMs) {
3341
+ try {
3342
+ sealAgentCandidateExecutorStopAcknowledgement(await withinCandidateCleanupDeadline((cleanupSignal) => executor.stop(executionTarget(request), {
3343
+ traceStore,
3344
+ reason,
3345
+ signal: cleanupSignal,
3346
+ deadlineAtMs: cleanupDeadlineAtMs
3347
+ }), cleanupDeadlineAtMs, "candidate process termination"));
3348
+ return { stopped: true };
3349
+ } catch (error) {
3350
+ return {
3351
+ stopped: false,
3352
+ error
3353
+ };
3354
+ }
3501
3355
  }
3502
- async function failClaimedExecution(prepared, state, lease, claimStore, outputArtifacts, error, reason, cleanupTimeoutMs, failureClass, activation, memoryActivation) {
3503
- beginPreparedCandidateSettlement(prepared);
3504
- const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
3505
- const [memoryClose, settled] = await Promise.all([closeMemoryAccess(state, reason, cleanupDeadlineAtMs), settleModelGrant(state, reason, cleanupDeadlineAtMs)]);
3506
- const protectedValues = protectedEnvironmentValues(activation, memoryActivation);
3507
- const safeReason = redactProtectedReason(joinErrors(error, memoryClose.error, settled.error), protectedValues);
3508
- let finishFailed = false;
3509
- let persistenceFailure;
3510
- if (settled.settlement && memoryClose.closed) try {
3511
- const modelSettlement = await withinCandidateCleanupDeadline(() => persistCandidateModelSettlement(state, settled.settlement, outputArtifacts), lease.expiresAtMs, "candidate pre-run model-settlement persistence");
3512
- const failureEvidence = await withinCandidateCleanupDeadline(() => persistFailureEvidence(state, safeReason, failureClass, void 0, outputArtifacts), lease.expiresAtMs, "candidate pre-run failure-evidence persistence");
3513
- finishFailed = !await finishClaim(claimStore, lease, {
3356
+ async function captureFinalEvidence(executor, request, traceStore, expectedOutcome, cleanupDeadlineAtMs) {
3357
+ try {
3358
+ return { finalCapture: sealAgentCandidateExecutorFinalCapture(await withinCandidateCleanupDeadline((cleanupSignal) => executor.capture(executionTarget(request), {
3359
+ traceStore,
3360
+ signal: cleanupSignal
3361
+ }), cleanupDeadlineAtMs, "candidate final evidence capture"), expectedOutcome) };
3362
+ } catch (error) {
3363
+ return { error };
3364
+ }
3365
+ }
3366
+ /** The error disposal threw, or undefined when the executor's resources were disposed. */
3367
+ async function disposalFailure(executor, request, cleanupDeadlineAtMs) {
3368
+ try {
3369
+ const dispose = executor.dispose;
3370
+ if (!dispose) return void 0;
3371
+ const disposed = await withinCandidateCleanupDeadline((cleanupSignal) => dispose.call(executor, executionTarget(request), { signal: cleanupSignal }), cleanupDeadlineAtMs, "candidate execution resource disposal");
3372
+ if (disposed?.disposed !== true || Object.keys(disposed).some((key) => key !== "disposed")) throw new Error("candidate executor did not acknowledge resource disposal");
3373
+ return;
3374
+ } catch (error) {
3375
+ return error;
3376
+ }
3377
+ }
3378
+ const executionTarget = (request) => ({
3379
+ executionId: request.executionId,
3380
+ executionPlanDigest: request.executionPlan.value.digest
3381
+ });
3382
+ var CandidateExecutionDeadlineError = class extends Error {
3383
+ constructor(timeoutMs) {
3384
+ super(`candidate execution reached its frozen ${timeoutMs}ms deadline`);
3385
+ this.name = "CandidateExecutionDeadlineError";
3386
+ }
3387
+ };
3388
+ //#endregion
3389
+ //#region src/candidate-execution/protected-trace-store.ts
3390
+ /** Keep the identity key in evaluator-owned closures and expose only the redacting store to code. */
3391
+ function createProtectedAgentCandidateTraceAccess(inner, protectedValues) {
3392
+ const redactor = createProtectedRecordRedactor(protectedValues);
3393
+ const pendingWrites = /* @__PURE__ */ new Set();
3394
+ let acceptsWrites = true;
3395
+ const write = (operation) => {
3396
+ if (!acceptsWrites) return Promise.reject(/* @__PURE__ */ new Error("candidate trace writes are closed"));
3397
+ let started;
3398
+ try {
3399
+ started = operation();
3400
+ } catch (error) {
3401
+ return Promise.reject(error);
3402
+ }
3403
+ let tracked;
3404
+ tracked = started.finally(() => pendingWrites.delete(tracked));
3405
+ pendingWrites.add(tracked);
3406
+ return tracked;
3407
+ };
3408
+ const store = Object.freeze({
3409
+ appendRun: (run) => write(() => inner.appendRun(redactor.record(run))),
3410
+ updateRun: (runId, patch) => write(() => inner.updateRun(redactor.identifier(runId), redactor.record(patch))),
3411
+ appendSpan: (span) => write(async () => {
3412
+ if (span.kind === "llm") throw new Error("candidate executors cannot author protected model spans");
3413
+ await inner.appendSpan(redactor.record(span));
3414
+ }),
3415
+ updateSpan: (spanId, patch) => write(async () => {
3416
+ if (patch.kind === "llm") throw new Error("candidate executors cannot author protected model spans");
3417
+ await inner.updateSpan(redactor.identifier(spanId), redactor.record(patch));
3418
+ }),
3419
+ appendEvent: (event) => write(() => inner.appendEvent(redactor.record(event))),
3420
+ appendArtifact: (artifact) => write(() => inner.appendArtifact(redactor.record(artifact))),
3421
+ appendBudgetEntry: (entry) => write(() => inner.appendBudgetEntry(redactor.record(entry))),
3422
+ getRun: async (runId) => inner.getRun(redactor.identifier(runId)),
3423
+ listRuns: async (filter) => inner.listRuns(filter ? redactor.query(filter) : void 0),
3424
+ spans: async (filter) => inner.spans(filter ? redactor.query(filter) : void 0),
3425
+ events: async (filter) => inner.events(filter ? redactor.query(filter) : void 0),
3426
+ budget: async (runId) => inner.budget(redactor.identifier(runId)),
3427
+ artifacts: async (runId) => inner.artifacts(redactor.identifier(runId))
3428
+ });
3429
+ return Object.freeze({
3430
+ store,
3431
+ closeWrites: async () => {
3432
+ acceptsWrites = false;
3433
+ await Promise.all([...pendingWrites]);
3434
+ },
3435
+ identity: (trace) => redactor.traceIdentity(trace),
3436
+ report: () => redactor.report()
3437
+ });
3438
+ }
3439
+ //#endregion
3440
+ //#region src/candidate-execution/execute.ts
3441
+ /** Executes and finalizes one durably claimed candidate without exposing an unproven result. */
3442
+ async function executePreparedAgentCandidate(prepared, options) {
3443
+ const initialState = assertPreparedCandidateIntegrity(prepared);
3444
+ const cleanupTimeoutMs = candidateCleanupTimeout(options.cleanupTimeoutMs ?? initialState.cleanupTimeoutMs);
3445
+ if (cleanupTimeoutMs > initialState.cleanupTimeoutMs) throw new Error("execution cleanup timeout exceeds the frozen preparation bound");
3446
+ const resultTimeoutMs = candidateResultTimeout(options.resultTimeoutMs ?? initialState.resultTimeoutMs, initialState.resultTimeoutMs);
3447
+ if (resultTimeoutMs > initialState.resultTimeoutMs) throw new Error("execution result timeout exceeds the frozen preparation bound");
3448
+ let state;
3449
+ try {
3450
+ state = beginPreparedCandidateClaim(prepared);
3451
+ } catch (error) {
3452
+ return failedAgentCandidateRun(initialState, errorMessage(error));
3453
+ }
3454
+ const run = {
3455
+ prepared,
3456
+ state,
3457
+ claimStore: options.claimStore,
3458
+ outputArtifacts: options.outputArtifacts,
3459
+ cleanupTimeoutMs,
3460
+ resultTimeoutMs
3461
+ };
3462
+ const claimed = await claimExecution(run, options);
3463
+ if (!claimed.ok) return claimed.result;
3464
+ const launchable = await activateAccess(run, claimed.value);
3465
+ if (!launchable.ok) return launchable.result;
3466
+ const settled = await runAndSettle(run, options, claimed.value, launchable.value);
3467
+ if (!settled.ok) return settled.result;
3468
+ const { execution, settlement } = settled.value;
3469
+ let modelSettlement;
3470
+ try {
3471
+ modelSettlement = await withinCandidateCleanupDeadline(() => persistCandidateModelSettlement(state, settlement, options.outputArtifacts), candidateCleanupDeadline(cleanupTimeoutMs), "candidate model settlement persistence");
3472
+ } catch (error) {
3473
+ consumePreparedCandidateExecution(prepared, "failed");
3474
+ return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, /* @__PURE__ */ new Error("candidate claim remains recoverable until settlement evidence is durable")), settled.value.protectedValues), execution.termination, settlement.usage);
3475
+ }
3476
+ const result = await finalizeEvidence(run, options, claimed.value, settled.value, modelSettlement);
3477
+ return recordTerminal(run, claimed.value, settled.value, modelSettlement, result);
3478
+ }
3479
+ /** Stage and publish the attempt's terminal record, then consume the prepared execution. */
3480
+ async function recordTerminal(run, claimed, settled, modelSettlement, result) {
3481
+ const { prepared, state } = run;
3482
+ const { execution, settlement } = settled;
3483
+ const { lease } = claimed.acquired;
3484
+ const failureClass = execution.kind === "error" ? "execution" : "post-model-infrastructure";
3485
+ let terminal;
3486
+ try {
3487
+ terminal = result.succeeded ? {
3488
+ status: "succeeded",
3489
+ usage: settlement.usage,
3490
+ modelSettlement: result.artifacts.modelSettlement,
3491
+ taskOutcome: result.artifacts.taskOutcome,
3492
+ benchmarkResult: result.artifacts.benchmarkResult,
3493
+ runReceipt: result.artifacts.runReceipt
3494
+ } : {
3514
3495
  status: "failed",
3515
3496
  failureClass,
3516
- usage: settled.settlement.usage,
3497
+ usage: settlement.usage,
3517
3498
  modelSettlement: modelSettlement.artifact,
3518
- failureEvidence
3519
- }, lease.expiresAtMs);
3520
- } catch (persistenceError) {
3521
- finishFailed = true;
3522
- persistenceFailure = persistenceError;
3499
+ failureEvidence: await withinCandidateCleanupDeadline(() => persistFailureEvidence(state, result.reason, failureClass, execution.termination, run.outputArtifacts), lease.expiresAtMs, "candidate failure-evidence persistence")
3500
+ };
3501
+ } catch (error) {
3502
+ consumePreparedCandidateExecution(prepared, "failed");
3503
+ return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, /* @__PURE__ */ new Error("candidate claim remains recoverable until terminal evidence is durable")), settled.protectedValues), execution.termination, settlement.usage);
3504
+ }
3505
+ if (await finishClaim(run.claimStore, lease, terminal, lease.expiresAtMs)) {
3506
+ consumePreparedCandidateExecution(prepared, result.succeeded ? "succeeded" : "failed");
3507
+ return result;
3523
3508
  }
3524
3509
  consumePreparedCandidateExecution(prepared, "failed");
3525
- return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(safeReason, persistenceFailure, memoryClose.error, settled.error, !memoryClose.closed || !settled.settlement ? /* @__PURE__ */ new Error("candidate claim remains recoverable until protected cleanup is proven") : void 0, finishFailed ? /* @__PURE__ */ new Error("candidate execution terminal record could not be persisted") : void 0), protectedValues), void 0, settled.settlement?.usage ?? null);
3510
+ return failedAgentCandidateRun(state, "candidate execution terminal record could not be persisted", execution.termination, settlement.usage);
3526
3511
  }
3527
- async function closeMemoryAccess(state, reason, cleanupDeadlineAtMs) {
3528
- if (state.memory.mode === "disabled") return { closed: true };
3512
+ /** Persist the plan and receipt, claim the attempt, and check the claim covers the run. */
3513
+ async function claimExecution(run, options) {
3514
+ const { prepared, state, cleanupTimeoutMs, resultTimeoutMs } = run;
3529
3515
  try {
3530
- const reservation = state.memoryReservation;
3531
- if (!reservation) throw new Error("isolated memory reservation is missing");
3532
- const closed = await withinCandidateCleanupDeadline(() => state.ports.memory.close({
3516
+ await assertPreparedCandidateWorkspaces(state);
3517
+ } catch (error) {
3518
+ return {
3519
+ ok: false,
3520
+ result: await failBeforeActivation(run, error, "failed")
3521
+ };
3522
+ }
3523
+ let preparationEvidence;
3524
+ try {
3525
+ const [executionPlan, materializationReceipt] = await Promise.all([persistCandidateOutputArtifact(options.outputArtifacts, {
3533
3526
  executionId: state.executionId,
3534
- preparationId: reservation.preparationId,
3535
- accessDigest: reservation.accessDigest,
3536
- effectiveNamespace: reservation.effectiveNamespace,
3537
- reason
3538
- }), cleanupDeadlineAtMs, "isolated memory closure");
3539
- if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("isolated memory access did not acknowledge closure");
3540
- return { closed: true };
3527
+ purpose: "execution-plan",
3528
+ bytes: state.executionPlan.bytes
3529
+ }), persistCandidateOutputArtifact(options.outputArtifacts, {
3530
+ executionId: state.executionId,
3531
+ purpose: "materialization-receipt",
3532
+ bytes: state.materializationReceipt.bytes
3533
+ })]);
3534
+ preparationEvidence = Object.freeze({
3535
+ executionPlan,
3536
+ materializationReceipt
3537
+ });
3541
3538
  } catch (error) {
3542
3539
  return {
3543
- closed: false,
3544
- error
3540
+ ok: false,
3541
+ result: await failBeforeActivation(run, error, "failed")
3542
+ };
3543
+ }
3544
+ let acquired;
3545
+ try {
3546
+ acquired = await options.claimStore.tryClaim(candidateExecutionClaim(prepared, preparationEvidence));
3547
+ } catch (error) {
3548
+ return {
3549
+ ok: false,
3550
+ result: await failBeforeActivation(run, error, "failed")
3545
3551
  };
3546
3552
  }
3553
+ if (!acquired.acquired) return {
3554
+ ok: false,
3555
+ result: await failBeforeActivation(run, /* @__PURE__ */ new Error(acquired.reason === "retry-not-eligible" ? `candidate execution retry is not eligible: ${acquired.detail}` : "candidate execution attempt is already claimed"), "replayed")
3556
+ };
3557
+ markPreparedCandidateClaimed(prepared);
3558
+ const postRunWindowMs = candidatePostRunWindowMs(cleanupTimeoutMs, resultTimeoutMs);
3559
+ const deadlineAtMs = acquired.claim.leaseExpiresAtMs - candidatePostRunWindowMs(state.cleanupTimeoutMs, state.resultTimeoutMs);
3560
+ const requiredLeaseExpiry = deadlineAtMs + postRunWindowMs;
3561
+ if (Date.now() >= deadlineAtMs || deadlineAtMs > state.reservationExpiresAtMs || requiredLeaseExpiry > acquired.lease.expiresAtMs) return {
3562
+ ok: false,
3563
+ result: await failClaimedExecution(run, acquired.lease, /* @__PURE__ */ new Error("candidate claim no longer covers its full execution and cleanup window"), "pre-model-infrastructure")
3564
+ };
3565
+ return {
3566
+ ok: true,
3567
+ value: {
3568
+ acquired,
3569
+ deadlineAtMs
3570
+ }
3571
+ };
3547
3572
  }
3548
- async function settleModelGrant(state, reason, cleanupDeadlineAtMs) {
3573
+ /** Activate model and memory access, build the executor request, and persist that it may run. */
3574
+ async function activateAccess(run, claimed) {
3575
+ const { prepared, state, cleanupTimeoutMs } = run;
3576
+ const { acquired, deadlineAtMs } = claimed;
3577
+ const fail = async (error, failureClass, access) => ({
3578
+ ok: false,
3579
+ result: await failClaimedExecution(run, acquired.lease, error, failureClass, access)
3580
+ });
3581
+ let activation;
3549
3582
  try {
3550
- return { settlement: sealAgentCandidateModelSettlement(await withinCandidateCleanupDeadline(() => state.ports.models.settleGrant({
3583
+ const activated = await withinCandidateCleanupDeadline(() => state.ports.models.activateGrant({
3551
3584
  executionId: state.executionId,
3552
3585
  preparationId: state.preparationId,
3553
3586
  grantDigest: state.modelReservation.digest,
3554
3587
  resolved: state.resolvedModel,
3555
- reason
3556
- }), cleanupDeadlineAtMs, "protected model settlement"), {
3557
- preparationId: state.preparationId,
3558
- grantDigest: state.modelReservation.digest,
3559
- model: state.resolvedModel.model
3560
- }) };
3588
+ deadlineAtMs
3589
+ }), Math.min(deadlineAtMs, candidateCleanupDeadline(cleanupTimeoutMs)), "protected model activation");
3590
+ activation = Object.freeze({ env: Object.freeze({ ...activated.env }) });
3561
3591
  } catch (error) {
3562
- return { error: new Error("protected model settlement failed", { cause: error }) };
3592
+ return fail(new Error("protected model activation failed", { cause: error }), "pre-model-infrastructure");
3593
+ }
3594
+ let memoryActivation;
3595
+ if (state.memory.mode === "isolated") try {
3596
+ const reservation = state.memoryReservation;
3597
+ if (!reservation) throw new Error("isolated memory reservation is missing");
3598
+ const activated = await withinCandidateCleanupDeadline(() => state.ports.memory.activate({
3599
+ executionId: state.executionId,
3600
+ preparationId: reservation.preparationId,
3601
+ accessDigest: reservation.accessDigest,
3602
+ effectiveNamespace: reservation.effectiveNamespace,
3603
+ deadlineAtMs
3604
+ }), Math.min(deadlineAtMs, candidateCleanupDeadline(cleanupTimeoutMs)), "isolated memory activation");
3605
+ memoryActivation = Object.freeze({ env: Object.freeze({ ...activated.env }) });
3606
+ } catch (error) {
3607
+ return fail(new Error("isolated memory activation failed", { cause: error }), "pre-model-infrastructure", { activation });
3608
+ }
3609
+ const access = {
3610
+ activation,
3611
+ memoryActivation
3612
+ };
3613
+ let request;
3614
+ try {
3615
+ request = beginPreparedCandidateRun(prepared, activation, memoryActivation).request;
3616
+ } catch (error) {
3617
+ return fail(error, "pre-model-infrastructure", access);
3618
+ }
3619
+ try {
3620
+ if ((await run.claimStore.markCandidateMayRun(acquired.lease)).phase !== "candidate-may-run") throw new Error("candidate claim did not persist the candidate-may-run phase");
3621
+ } catch (error) {
3622
+ return fail(new Error("candidate execution phase persistence failed", { cause: error }), "pre-model-infrastructure", access);
3623
+ }
3624
+ if (Date.now() >= deadlineAtMs) return fail(/* @__PURE__ */ new Error("candidate execution deadline elapsed while persisting its launch phase"), "unknown", access);
3625
+ return {
3626
+ ok: true,
3627
+ value: {
3628
+ ...access,
3629
+ request
3630
+ }
3631
+ };
3632
+ }
3633
+ /** Run the executor, prove its process stopped, and close and settle the protected access. */
3634
+ async function runAndSettle(run, options, claimed, launchable) {
3635
+ const { prepared, state, cleanupTimeoutMs } = run;
3636
+ const protectedValues = protectedEnvironmentValues(launchable.activation, launchable.memoryActivation);
3637
+ const protectedTrace = createProtectedAgentCandidateTraceAccess(options.traceStore, protectedValues);
3638
+ const persistedTrace = protectedTrace.identity(state.trace);
3639
+ const execution = await runAndStopExecutor(options.executor, launchable.request, state.benchmarkTask.outcome, protectedTrace.store, claimed.deadlineAtMs, cleanupTimeoutMs);
3640
+ beginPreparedCandidateSettlement(prepared);
3641
+ const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
3642
+ const accessReason = execution.kind === "timeout" || execution.termination?.kind === "timeout" ? "timeout" : execution.kind === "capture" ? "completed" : "failed";
3643
+ const traceClosure = withinCandidateCleanupDeadline(() => protectedTrace.closeWrites(), cleanupDeadlineAtMs, "candidate trace write closure").then(() => ({
3644
+ closed: true,
3645
+ error: void 0
3646
+ }), (error) => ({
3647
+ closed: false,
3648
+ error
3649
+ }));
3650
+ const [traceClose, memoryClose, settlementResult] = await Promise.all([
3651
+ traceClosure,
3652
+ closeMemoryAccess(state, accessReason, cleanupDeadlineAtMs),
3653
+ settleModelGrant(state, accessReason, cleanupDeadlineAtMs)
3654
+ ]);
3655
+ if (!execution.processStopped || !traceClose.closed || !settlementResult.settlement || !memoryClose.closed) {
3656
+ consumePreparedCandidateExecution(prepared, "failed");
3657
+ return {
3658
+ ok: false,
3659
+ result: failedAgentCandidateRun(state, redactProtectedReason(joinErrors(execution.error, !execution.processStopped ? /* @__PURE__ */ new Error("candidate process termination is not proven") : void 0, traceClose.error, memoryClose.error, settlementResult.error ?? (!settlementResult.settlement ? /* @__PURE__ */ new Error("model settlement failed") : void 0), /* @__PURE__ */ new Error("candidate claim remains recoverable until protected cleanup is proven")), protectedValues), execution.termination, settlementResult.settlement?.usage ?? null)
3660
+ };
3563
3661
  }
3662
+ return {
3663
+ ok: true,
3664
+ value: {
3665
+ execution,
3666
+ settlement: settlementResult.settlement,
3667
+ protectedValues,
3668
+ persistedTrace,
3669
+ protectedTrace
3670
+ }
3671
+ };
3564
3672
  }
3565
- async function finishClaim(store, lease, terminal, deadlineAtMs) {
3673
+ /** Verify and grade the captured evidence into the run's result; a failure is a failed run. */
3674
+ async function finalizeEvidence(run, options, claimed, settled, modelSettlement) {
3675
+ const { state, cleanupTimeoutMs, resultTimeoutMs } = run;
3676
+ const { execution, settlement, protectedValues, persistedTrace, protectedTrace } = settled;
3677
+ if (execution.kind === "error") return failedAgentCandidateRun(state, redactProtectedReason(errorMessage(execution.error), protectedValues), execution.termination, settlement.usage);
3678
+ if (!execution.finalCapture.taskOutcome) return failedAgentCandidateRun(state, "candidate executor stopped without a captured task outcome", execution.termination, settlement.usage);
3679
+ const capture = execution.kind === "capture" ? execution.capture : {
3680
+ executionId: state.executionId,
3681
+ termination: execution.termination
3682
+ };
3566
3683
  try {
3567
- const staged = await withinCandidateCleanupDeadline(() => store.stageTerminal(lease, terminal), deadlineAtMs ?? lease.expiresAtMs, "candidate terminal staging");
3568
- if (!staged.staged && !staged.exactReplay) return false;
3569
- const result = await withinCandidateCleanupDeadline(() => store.finish(lease, staged.terminal.terminalDigest), deadlineAtMs ?? lease.expiresAtMs, "candidate terminal publication");
3570
- return result.finished || result.exactReplay;
3571
- } catch {
3572
- return false;
3684
+ return await withinCandidateResultDeadline(async (signal) => {
3685
+ await appendAuthoritativeModelSettlementSpans(options.traceStore, persistedTrace.runId, settlement);
3686
+ const { persistedCapture, taskOutcome } = await persistVerifiedAgentCandidateExecutorCapture(state, execution.finalCapture, options.outputArtifacts, protectedValues, signal);
3687
+ const benchmarkResult = await persistCandidateBenchmarkResult(state, capture.termination, taskOutcome, options.grader, options.outputArtifacts, protectedValues, signal);
3688
+ return await finalizeAgentCandidateRun(state, capture, options.traceStore, persistedTrace, settlement, {
3689
+ finalCapture: execution.finalCapture,
3690
+ persistedCapture,
3691
+ modelSettlement,
3692
+ taskOutcome,
3693
+ benchmarkResult,
3694
+ outputArtifacts: options.outputArtifacts
3695
+ }, protectedValues, protectedTrace.report(), signal);
3696
+ }, Math.min(Date.now() + resultTimeoutMs, claimed.acquired.lease.expiresAtMs - candidateTerminalWindowMs(cleanupTimeoutMs)), "candidate evidence finalization");
3697
+ } catch (error) {
3698
+ return failedAgentCandidateRun(state, redactProtectedReason(errorMessage(error), protectedValues), execution.termination, settlement.usage);
3573
3699
  }
3574
3700
  }
3575
- function protectedEnvironmentValues(activation, memoryActivation) {
3576
- return [...Object.values(activation?.env ?? {}), ...Object.values(memoryActivation?.env ?? {})];
3701
+ //#endregion
3702
+ //#region src/candidate-execution/prepare-plan.ts
3703
+ /**
3704
+ * The evaluator-owned documents of a preparation: the launch environment, the execution plan,
3705
+ * the materialization receipt, and the trace bindings that tie a run back to them.
3706
+ */
3707
+ /** The public environment: the candidate's own, the profile's, and the evaluator's path bindings. */
3708
+ function launchEnvironment(candidate, profile, knowledgePaths) {
3709
+ const { execution } = candidate.bundle;
3710
+ const { agentPaths } = profile;
3711
+ return mergePublicEnvironment(execution.env ?? {}, profile.application.env, agentPaths ? {
3712
+ [PI_CANDIDATE_AGENT_DIR_ENV]: {
3713
+ kind: "public",
3714
+ value: agentPaths.agentDir
3715
+ },
3716
+ [PI_CANDIDATE_SESSION_DIR_ENV]: {
3717
+ kind: "public",
3718
+ value: agentPaths.sessionDir
3719
+ }
3720
+ } : {}, execution.instructionDelivery.kind === "utf8-file" ? { [execution.instructionDelivery.env]: {
3721
+ kind: "public",
3722
+ value: execution.instructionDelivery.path
3723
+ } } : {}, knowledgePaths ? {
3724
+ [CANDIDATE_KNOWLEDGE_ROOT_ENV]: {
3725
+ kind: "public",
3726
+ value: knowledgePaths.root
3727
+ },
3728
+ ...knowledgePaths.retrievalConfig ? { [CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV]: {
3729
+ kind: "public",
3730
+ value: knowledgePaths.retrievalConfig
3731
+ } } : {}
3732
+ } : {});
3577
3733
  }
3578
- function joinErrors(...errors) {
3579
- return errors.filter((error) => error !== void 0).map(errorMessage).join("; ");
3734
+ /** The plan material for one execution: workspaces, profile, model access, launch and memory. */
3735
+ function executionPlanMaterial(input) {
3736
+ const { candidate, task } = input;
3737
+ const { bundle } = candidate;
3738
+ return {
3739
+ kind: "agent-candidate-execution-plan-material",
3740
+ runCell: task.runCell,
3741
+ executionId: task.executionId,
3742
+ workspaces: {
3743
+ taskRoot: task.executionRoots.taskRoot,
3744
+ ...task.executionRoots.candidateRoot ? { candidateRoot: task.executionRoots.candidateRoot } : {}
3745
+ },
3746
+ codeKind: bundle.code.kind,
3747
+ ...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
3748
+ profile: input.profile.application.application,
3749
+ harness: bundle.execution.harness,
3750
+ harnessVersion: bundle.execution.harnessVersion,
3751
+ instructionDelivery: bundle.execution.instructionDelivery,
3752
+ limits: task.task.limits,
3753
+ container: input.container,
3754
+ model: {
3755
+ policy: "single",
3756
+ resolved: input.resolvedModel,
3757
+ access: {
3758
+ kind: "evaluator-mediated",
3759
+ grantDigest: input.modelReservation.digest,
3760
+ network: input.modelReservation.network
3761
+ },
3762
+ routes: modelRoutes(bundle.profile, task.task.model.requested)
3763
+ },
3764
+ launch: {
3765
+ executable: input.launch.executable,
3766
+ args: input.launch.args,
3767
+ env: input.publicEnv,
3768
+ cwd: bundle.execution.cwd
3769
+ },
3770
+ ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
3771
+ memory: input.memory,
3772
+ network: { mode: "disabled" }
3773
+ };
3580
3774
  }
3581
- var CandidateExecutionDeadlineError = class extends Error {
3582
- constructor(timeoutMs) {
3583
- super(`candidate execution reached its frozen ${timeoutMs}ms deadline`);
3584
- this.name = "CandidateExecutionDeadlineError";
3775
+ /** Check and canonically serialize the plan material into the plan's evidence. */
3776
+ function sealExecutionPlan(material) {
3777
+ agentCandidateExecutionPlanMaterialSchema.parse(material);
3778
+ const bytes = canonicalCandidateBytes$1(material);
3779
+ const digest = canonicalCandidateDigest$1(material);
3780
+ if (sha256Bytes$1(bytes) !== digest) throw new Error("execution plan canonical serializers disagree");
3781
+ return {
3782
+ evidence: agentCandidateExecutionPlanEvidenceSchema.parse({
3783
+ kind: "agent-candidate-execution-plan",
3784
+ digest,
3785
+ material,
3786
+ artifact: embeddedCandidateArtifact(bytes)
3787
+ }),
3788
+ bytes
3789
+ };
3790
+ }
3791
+ /** The receipt that binds the bundle, the benchmark task, and the sealed plan together. */
3792
+ function sealMaterializationReceipt(input) {
3793
+ const { candidate, task } = input;
3794
+ const { bundle } = candidate;
3795
+ const benchmarkTask = task.task;
3796
+ const entrypoint = candidateEntrypointReceipt(candidate);
3797
+ const materializationReceipt = canonicalCandidateDocument({
3798
+ kind: "agent-candidate-materialization",
3799
+ digestAlgorithm: "rfc8785-sha256",
3800
+ bundleDigest: bundle.digest,
3801
+ benchmark: {
3802
+ suite: {
3803
+ digest: task.benchmarkSuite.digest,
3804
+ material: embeddedCandidateArtifact(canonicalCandidateBytes$1(omitTopLevelDigest(task.benchmarkSuite)))
3805
+ },
3806
+ task: {
3807
+ digest: benchmarkTask.digest,
3808
+ material: embeddedCandidateArtifact(canonicalCandidateBytes$1(omitTopLevelDigest(benchmarkTask)))
3809
+ }
3810
+ },
3811
+ profileActivation: input.profile.application.profileActivation,
3812
+ executionPlan: input.executionPlan,
3813
+ ...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
3814
+ codeKind: bundle.code.kind,
3815
+ ...candidate.materializedTree ? { materializedTree: candidate.materializedTree } : {},
3816
+ harness: bundle.execution.harness,
3817
+ harnessVersion: bundle.execution.harnessVersion,
3818
+ container: input.container,
3819
+ resolvedModel: input.resolvedModel,
3820
+ ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
3821
+ ...entrypoint ? { entrypoint } : {}
3822
+ });
3823
+ agentCandidateMaterializationReceiptSchema.parse(materializationReceipt.value);
3824
+ return materializationReceipt;
3825
+ }
3826
+ /** The run id, tags and environment that tie a trace to this execution's sealed documents. */
3827
+ function candidateTraceBindings(input) {
3828
+ const { task, bundleDigest, executionPlanDigest, materializationReceiptDigest } = input;
3829
+ const runId = `${task.executionId}:attempt-${input.attemptNumber}:${canonicalCandidateDigest$1({ preparationId: input.preparationId }).slice(7, 23)}`;
3830
+ const tags = {
3831
+ [CANDIDATE_TRACE_TAGS.executionId]: task.executionId,
3832
+ [CANDIDATE_TRACE_TAGS.bundleDigest]: bundleDigest,
3833
+ [CANDIDATE_TRACE_TAGS.executionPlanDigest]: executionPlanDigest,
3834
+ [CANDIDATE_TRACE_TAGS.materializationReceiptDigest]: materializationReceiptDigest
3835
+ };
3836
+ const env = {
3837
+ [CANDIDATE_TRACE_ENV.executionId]: task.executionId,
3838
+ [CANDIDATE_TRACE_ENV.bundleDigest]: bundleDigest,
3839
+ [CANDIDATE_TRACE_ENV.executionPlanDigest]: executionPlanDigest,
3840
+ [CANDIDATE_TRACE_ENV.materializationReceiptDigest]: materializationReceiptDigest,
3841
+ [CANDIDATE_TRACE_ENV.traceRunId]: runId
3842
+ };
3843
+ assertEnvironmentDisjoint(input.publicEnv, env);
3844
+ return {
3845
+ runId,
3846
+ tags,
3847
+ env
3848
+ };
3849
+ }
3850
+ function unwrapPublicEnvironment(values) {
3851
+ return Object.fromEntries(Object.entries(values).map(([name, value]) => [name, requirePublicCandidateConfigValue(value, `env.${name}`)]));
3852
+ }
3853
+ function mergePublicEnvironment(...records) {
3854
+ const output = {};
3855
+ for (const record of records) for (const [name, value] of Object.entries(record)) {
3856
+ const previous = output[name];
3857
+ const publicValue = requirePublicCandidateConfigValue(value, `env.${name}`);
3858
+ if (previous && requirePublicCandidateConfigValue(previous, `env.${name}`) !== publicValue) throw new Error(`candidate and profile environment disagree on ${name}`);
3859
+ output[name] = value;
3585
3860
  }
3586
- };
3861
+ return output;
3862
+ }
3863
+ function assertEnvironmentDisjoint(publicEnv, traceEnv) {
3864
+ const seen = new Set(Object.keys(publicEnv));
3865
+ for (const name of Object.keys(traceEnv)) {
3866
+ if (seen.has(name)) throw new Error(`evaluator environment binding collides with ${name}`);
3867
+ seen.add(name);
3868
+ }
3869
+ }
3587
3870
  //#endregion
3588
- //#region src/candidate-execution/prepare.ts
3589
- const MIN_RESERVATION_TTL_MS = 15 * 6e4;
3590
- const PREPARED_HOLD_MARGIN_MS = 5 * 6e4;
3591
- /** Materializes a verified candidate into one immutable evaluator-owned execution plan. */
3592
- async function prepareAgentCandidateExecution(candidate, task, ports, options = {}) {
3593
- const cleanupTimeoutMs = candidateCleanupTimeout(options.cleanupTimeoutMs);
3594
- assertSameVerificationPorts(getVerifiedCandidateState(candidate).ports, ports);
3595
- const bundle = candidate.bundle;
3596
- if (task.runCell.bundleDigest !== bundle.digest) throw new Error("candidate experiment cell does not bind the verified bundle");
3871
+ //#region src/candidate-execution/prepare-workspaces.ts
3872
+ /**
3873
+ * The three host staging roots of a preparation: the task workspace, the candidate workspace,
3874
+ * and the profile workspace, each materialized and verified against its signed material.
3875
+ */
3876
+ async function materializeTaskWorkspace(task, ports) {
3597
3877
  const benchmarkTask = task.task;
3598
- const attempt = {
3599
- number: task.runCell.attempt,
3600
- maxAttempts: benchmarkTask.attempt.maxAttempts,
3601
- retryPolicy: benchmarkTask.attempt.retryPolicy
3602
- };
3603
- assertTaskInput(task, bundle.execution.instructionDelivery);
3604
- const resultTimeoutMs = candidateResultTimeout(options.resultTimeoutMs, benchmarkTask.limits.timeoutMs);
3605
- const reservationWindowMs = candidateExecutionOwnerWindowMs(benchmarkTask.limits.timeoutMs, cleanupTimeoutMs, resultTimeoutMs) + PREPARED_HOLD_MARGIN_MS;
3606
- if (reservationWindowMs > 2147483647) throw new Error("candidate reservation window exceeds the supported timer range");
3607
- assertDisjointHostStagingRoots(task);
3608
- const instructionBytes = Buffer.from(benchmarkTask.instruction, "utf8");
3609
3878
  const taskArtifacts = await verifyWorkspaceSnapshotArtifacts(benchmarkTask.workspace, ports.artifacts);
3610
3879
  await ports.workspaces.materialize({
3611
3880
  role: "task",
@@ -3615,23 +3884,31 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
3615
3884
  });
3616
3885
  await verifyMaterializedWorkspace(task.stagingRoots.taskRoot, benchmarkTask.workspace.material, { ignoredProtectedRootEntries: [".git", ".sidecar"] });
3617
3886
  if (benchmarkTask.repository) await verifyTaskCheckout(task.stagingRoots.taskRoot, benchmarkTask.repository);
3618
- const taskExecutorFiles = await readMaterializedWorkspaceFiles(task.stagingRoots.taskRoot, benchmarkTask.workspace.material, { ignoredProtectedRootEntries: [".git", ".sidecar"] });
3619
- let candidateArchive;
3620
- let candidateExecutorFiles;
3621
- if (bundle.execution.workspace) {
3622
- if (!task.stagingRoots.candidateRoot || !task.executionRoots.candidateRoot) throw new Error("active candidate execution requires host and container candidate roots");
3623
- candidateArchive = await verifiedArtifactBytes(candidate, bundle.execution.workspace.archive);
3624
- await ports.workspaces.materialize({
3625
- role: "candidate",
3626
- snapshot: bundle.execution.workspace,
3627
- archive: candidateArchive,
3628
- destination: task.stagingRoots.candidateRoot
3629
- });
3630
- await verifyMaterializedWorkspace(task.stagingRoots.candidateRoot, bundle.execution.workspace.material);
3631
- candidateExecutorFiles = await readMaterializedWorkspaceFiles(task.stagingRoots.candidateRoot, bundle.execution.workspace.material);
3632
- } else if (task.stagingRoots.candidateRoot || task.executionRoots.candidateRoot) throw new Error("disabled code cannot receive a candidate workspace root");
3887
+ return readMaterializedWorkspaceFiles(task.stagingRoots.taskRoot, benchmarkTask.workspace.material, { ignoredProtectedRootEntries: [".git", ".sidecar"] });
3888
+ }
3889
+ /** The candidate's own workspace files, or undefined when its code is disabled. */
3890
+ async function materializeCandidateWorkspace(candidate, task, ports) {
3891
+ const workspace = candidate.bundle.execution.workspace;
3892
+ if (!workspace) {
3893
+ if (task.stagingRoots.candidateRoot || task.executionRoots.candidateRoot) throw new Error("disabled code cannot receive a candidate workspace root");
3894
+ return;
3895
+ }
3896
+ if (!task.stagingRoots.candidateRoot || !task.executionRoots.candidateRoot) throw new Error("active candidate execution requires host and container candidate roots");
3897
+ const archive = await verifiedArtifactBytes(candidate, workspace.archive);
3898
+ await ports.workspaces.materialize({
3899
+ role: "candidate",
3900
+ snapshot: workspace,
3901
+ archive,
3902
+ destination: task.stagingRoots.candidateRoot
3903
+ });
3904
+ await verifyMaterializedWorkspace(task.stagingRoots.candidateRoot, workspace.material);
3905
+ return readMaterializedWorkspaceFiles(task.stagingRoots.candidateRoot, workspace.material);
3906
+ }
3907
+ /** Materialize the profile into its empty staging root and check the plan's exact bytes. */
3908
+ async function stageCandidateProfile(candidate, task, ports) {
3909
+ const { bundle } = candidate;
3633
3910
  await assertEmptyDirectory(task.stagingRoots.profileRoot);
3634
- const profileWorkspacePlan = materializeAgentCandidateProfilePlan({
3911
+ const workspacePlan = materializeAgentCandidateProfilePlan({
3635
3912
  profile: bundle.profile,
3636
3913
  harness: bundle.execution.harness,
3637
3914
  launch: bundle.execution.launch,
@@ -3642,22 +3919,46 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
3642
3919
  },
3643
3920
  resolvedResources: verifiedResourceTextByDigest(candidate)
3644
3921
  });
3645
- const profileAgentPaths = candidateProfileAgentPaths(profileWorkspacePlan, task.executionRoots.profileRoot);
3646
- const profileAgentStagingRoot = profileWorkspacePlan.files.some((file) => file.root === "agent") ? await mkdtemp(join(tmpdir(), "tangle-candidate-profile-agent-")) : void 0;
3647
- let profileApplication;
3922
+ const agentPaths = candidateProfileAgentPaths(workspacePlan, task.executionRoots.profileRoot);
3923
+ const agentStagingRoot = workspacePlan.files.some((file) => file.root === "agent") ? await mkdtemp(join(tmpdir(), "tangle-candidate-profile-agent-")) : void 0;
3924
+ let application;
3648
3925
  try {
3649
- profileApplication = applyAgentCandidateWorkspacePlan(profileWorkspacePlan, task.stagingRoots.profileRoot, bundle.execution.cwd.workspace, profileAgentStagingRoot ? { agentDir: profileAgentStagingRoot } : void 0);
3650
- await verifyMaterializedProfileWorkspace(task.stagingRoots.profileRoot, profileApplication.profileActivation.profilePlan.material);
3651
- if (profileAgentStagingRoot) await verifyMaterializedProfileWorkspace(profileAgentStagingRoot, profileApplication.profileActivation.profilePlan.material, "agent");
3926
+ application = applyAgentCandidateWorkspacePlan(workspacePlan, task.stagingRoots.profileRoot, bundle.execution.cwd.workspace, agentStagingRoot ? { agentDir: agentStagingRoot } : void 0);
3927
+ await verifyMaterializedProfileWorkspace(task.stagingRoots.profileRoot, application.profileActivation.profilePlan.material);
3928
+ if (agentStagingRoot) await verifyMaterializedProfileWorkspace(agentStagingRoot, application.profileActivation.profilePlan.material, "agent");
3652
3929
  } finally {
3653
- if (profileAgentStagingRoot) await rm(profileAgentStagingRoot, {
3930
+ if (agentStagingRoot) await rm(agentStagingRoot, {
3654
3931
  recursive: true,
3655
3932
  force: true
3656
3933
  });
3657
3934
  }
3658
- const profilePlanBytes = await readVerifiedArtifact(profileApplication.profileActivation.profilePlan.artifact, ports.artifacts);
3659
- if (!Buffer.from(profilePlanBytes).equals(Buffer.from(canonicalCandidateBytes$1(profileApplication.profileActivation.profilePlan.material)))) throw new Error("profile materializer did not capture exact canonical plan bytes");
3660
- const profileActivation = profileApplication.profileActivation;
3935
+ const planBytes = await readVerifiedArtifact(application.profileActivation.profilePlan.artifact, ports.artifacts);
3936
+ if (!Buffer.from(planBytes).equals(Buffer.from(canonicalCandidateBytes$1(application.profileActivation.profilePlan.material)))) throw new Error("profile materializer did not capture exact canonical plan bytes");
3937
+ return {
3938
+ workspacePlan,
3939
+ agentPaths,
3940
+ application,
3941
+ planBytes
3942
+ };
3943
+ }
3944
+ async function assertEmptyDirectory(path) {
3945
+ const stats = await lstat(path);
3946
+ if (!stats.isDirectory() || stats.isSymbolicLink()) throw new Error("profile staging root must be a real directory");
3947
+ if ((await readdir(path)).length !== 0) throw new Error("profile staging root must be empty before materialization");
3948
+ }
3949
+ //#endregion
3950
+ //#region src/candidate-execution/prepare.ts
3951
+ const MIN_RESERVATION_TTL_MS = 15 * 6e4;
3952
+ const PREPARED_HOLD_MARGIN_MS = 5 * 6e4;
3953
+ /** Materializes a verified candidate into one immutable evaluator-owned execution plan. */
3954
+ async function prepareAgentCandidateExecution(candidate, task, ports, options = {}) {
3955
+ const { cleanupTimeoutMs, resultTimeoutMs, reservationWindowMs } = checkPreparation(candidate, task, ports, options);
3956
+ const bundle = candidate.bundle;
3957
+ const benchmarkTask = task.task;
3958
+ const instructionBytes = Buffer.from(benchmarkTask.instruction, "utf8");
3959
+ const taskExecutorFiles = await materializeTaskWorkspace(task, ports);
3960
+ const candidateExecutorFiles = await materializeCandidateWorkspace(candidate, task, ports);
3961
+ const profile = await stageCandidateProfile(candidate, task, ports);
3661
3962
  const container = await resolveContainer(candidate, task, ports);
3662
3963
  const resolvedModel = await resolveModel(candidate, task, ports);
3663
3964
  const preparationId = `candidate-preparation.${randomBytes(32).toString("base64url")}`;
@@ -3666,7 +3967,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
3666
3967
  executionId: task.executionId,
3667
3968
  preparationId,
3668
3969
  expiresAtMs: reservationExpiresAtMs,
3669
- attempt,
3970
+ attempt: attemptOf(task),
3670
3971
  bundleDigest: bundle.digest,
3671
3972
  resolved: resolvedModel,
3672
3973
  limits: modelLimits(benchmarkTask.limits)
@@ -3675,221 +3976,160 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
3675
3976
  try {
3676
3977
  validateProtectedModelReservation(modelReservation, benchmarkTask.limits, preparationId, reservationExpiresAtMs);
3677
3978
  preparedMemory = await prepareMemory(candidate, task, ports, preparationId, reservationExpiresAtMs, cleanupTimeoutMs);
3678
- const memory = preparedMemory.value;
3679
- const knowledge = await prepareAgentCandidateKnowledge(candidate, ports, task.runCell.arm);
3680
- const knowledgePaths = knowledge ? candidateKnowledgeExecutionPaths(task.executionRoots.taskRoot, knowledge.retrievalConfig !== void 0) : void 0;
3681
- const baseLaunch = buildLaunch(candidate, task, profileApplication.flags);
3682
- const publicEnv = mergePublicEnvironment(bundle.execution.env ?? {}, profileApplication.env, profileAgentPaths ? {
3683
- [PI_CANDIDATE_AGENT_DIR_ENV]: {
3684
- kind: "public",
3685
- value: profileAgentPaths.agentDir
3686
- },
3687
- [PI_CANDIDATE_SESSION_DIR_ENV]: {
3688
- kind: "public",
3689
- value: profileAgentPaths.sessionDir
3690
- }
3691
- } : {}, bundle.execution.instructionDelivery.kind === "utf8-file" ? { [bundle.execution.instructionDelivery.env]: {
3692
- kind: "public",
3693
- value: bundle.execution.instructionDelivery.path
3694
- } } : {}, knowledgePaths ? {
3695
- [CANDIDATE_KNOWLEDGE_ROOT_ENV]: {
3696
- kind: "public",
3697
- value: knowledgePaths.root
3698
- },
3699
- ...knowledgePaths.retrievalConfig ? { [CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV]: {
3700
- kind: "public",
3701
- value: knowledgePaths.retrievalConfig
3702
- } } : {}
3703
- } : {});
3704
- const routes = modelRoutes(bundle.profile, benchmarkTask.model.requested);
3705
- const executionMaterial = {
3706
- kind: "agent-candidate-execution-plan-material",
3707
- runCell: task.runCell,
3708
- executionId: task.executionId,
3709
- workspaces: {
3710
- taskRoot: task.executionRoots.taskRoot,
3711
- ...task.executionRoots.candidateRoot ? { candidateRoot: task.executionRoots.candidateRoot } : {}
3712
- },
3713
- codeKind: bundle.code.kind,
3714
- ...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
3715
- profile: profileApplication.application,
3716
- harness: bundle.execution.harness,
3717
- harnessVersion: bundle.execution.harnessVersion,
3718
- instructionDelivery: bundle.execution.instructionDelivery,
3719
- limits: benchmarkTask.limits,
3720
- container,
3721
- model: {
3722
- policy: "single",
3723
- resolved: resolvedModel,
3724
- access: {
3725
- kind: "evaluator-mediated",
3726
- grantDigest: modelReservation.digest,
3727
- network: modelReservation.network
3728
- },
3729
- routes
3730
- },
3731
- launch: {
3732
- executable: baseLaunch.executable,
3733
- args: baseLaunch.args,
3734
- env: publicEnv,
3735
- cwd: bundle.execution.cwd
3736
- },
3737
- ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
3738
- memory,
3739
- network: { mode: "disabled" }
3740
- };
3741
- agentCandidateExecutionPlanMaterialSchema.parse(executionMaterial);
3742
- const executionBytes = canonicalCandidateBytes$1(executionMaterial);
3743
- const executionDigest = canonicalCandidateDigest$1(executionMaterial);
3744
- if (sha256Bytes$1(executionBytes) !== executionDigest) throw new Error("execution plan canonical serializers disagree");
3745
- const executionPlan = agentCandidateExecutionPlanEvidenceSchema.parse({
3746
- kind: "agent-candidate-execution-plan",
3747
- digest: executionDigest,
3748
- material: executionMaterial,
3749
- artifact: embeddedCandidateArtifact(executionBytes)
3750
- });
3751
- const entrypoint = candidateEntrypointReceipt(candidate);
3752
- const materializationReceipt = canonicalCandidateDocument({
3753
- kind: "agent-candidate-materialization",
3754
- digestAlgorithm: "rfc8785-sha256",
3755
- bundleDigest: bundle.digest,
3756
- benchmark: {
3757
- suite: {
3758
- digest: task.benchmarkSuite.digest,
3759
- material: embeddedCandidateArtifact(canonicalCandidateBytes$1(omitTopLevelDigest(task.benchmarkSuite)))
3760
- },
3761
- task: {
3762
- digest: benchmarkTask.digest,
3763
- material: embeddedCandidateArtifact(canonicalCandidateBytes$1(omitTopLevelDigest(benchmarkTask)))
3764
- }
3765
- },
3766
- profileActivation,
3767
- executionPlan,
3768
- ...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
3769
- codeKind: bundle.code.kind,
3770
- ...candidate.materializedTree ? { materializedTree: candidate.materializedTree } : {},
3771
- harness: bundle.execution.harness,
3772
- harnessVersion: bundle.execution.harnessVersion,
3979
+ return await assemblePrepared({
3980
+ candidate,
3981
+ task,
3982
+ ports,
3983
+ cleanupTimeoutMs,
3984
+ resultTimeoutMs,
3985
+ taskExecutorFiles,
3986
+ candidateExecutorFiles,
3987
+ profile,
3773
3988
  container,
3774
3989
  resolvedModel,
3775
- ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
3776
- ...entrypoint ? { entrypoint } : {}
3990
+ preparationId,
3991
+ reservationExpiresAtMs,
3992
+ modelReservation,
3993
+ preparedMemory,
3994
+ instructionBytes
3777
3995
  });
3778
- agentCandidateMaterializationReceiptSchema.parse(materializationReceipt.value);
3779
- const traceRunId = `${task.executionId}:attempt-${attempt.number}:${canonicalCandidateDigest$1({ preparationId }).slice(7, 23)}`;
3780
- const traceTags = {
3781
- [CANDIDATE_TRACE_TAGS.executionId]: task.executionId,
3782
- [CANDIDATE_TRACE_TAGS.bundleDigest]: bundle.digest,
3783
- [CANDIDATE_TRACE_TAGS.executionPlanDigest]: executionPlan.digest,
3784
- [CANDIDATE_TRACE_TAGS.materializationReceiptDigest]: materializationReceipt.digest
3785
- };
3786
- const traceEnv = {
3787
- [CANDIDATE_TRACE_ENV.executionId]: task.executionId,
3788
- [CANDIDATE_TRACE_ENV.bundleDigest]: bundle.digest,
3789
- [CANDIDATE_TRACE_ENV.executionPlanDigest]: executionPlan.digest,
3790
- [CANDIDATE_TRACE_ENV.materializationReceiptDigest]: materializationReceipt.digest,
3791
- [CANDIDATE_TRACE_ENV.traceRunId]: traceRunId
3792
- };
3793
- assertEnvironmentDisjoint(publicEnv, traceEnv);
3794
- return createPreparedCandidateExecution({
3996
+ } catch (error) {
3997
+ await cleanupFailedPreparation({
3998
+ task,
3795
3999
  ports,
3796
- bundle,
3797
- benchmarkSuite: task.benchmarkSuite,
3798
- benchmarkTask,
3799
- executionId: task.executionId,
3800
- roots: {
3801
- execution: { ...task.executionRoots },
3802
- staging: { ...task.stagingRoots }
3803
- },
3804
- profilePlan: {
3805
- value: profileApplication.profileActivation.profilePlan,
3806
- bytes: profilePlanBytes,
3807
- written: [...profileApplication.application.mountPaths]
3808
- },
3809
- profileActivation,
3810
- executionPlan: {
3811
- value: executionPlan,
3812
- bytes: executionBytes
3813
- },
3814
- materializationReceipt,
3815
- launch: {
3816
- executable: baseLaunch.executable,
3817
- args: baseLaunch.args.map((value, index) => requirePublicCandidateConfigValue(value, `launch.args[${index}]`)),
3818
- env: unwrapPublicEnvironment(publicEnv),
3819
- flags: profileApplication.flags.map((value, index) => requirePublicCandidateConfigValue(value, `profile.flags[${index}]`)),
3820
- cwd: absoluteExecutionCwd(bundle.execution.cwd, task.executionRoots)
3821
- },
3822
- instruction: {
3823
- bytes: Uint8Array.from(instructionBytes),
3824
- delivery: bundle.execution.instructionDelivery
3825
- },
3826
- resolvedModel,
3827
4000
  preparationId,
3828
- reservationExpiresAtMs,
3829
4001
  cleanupTimeoutMs,
3830
- resultTimeoutMs,
3831
- modelReservation: {
3832
- preparationId: modelReservation.preparationId,
3833
- digest: modelReservation.digest,
3834
- expiresAtMs: modelReservation.expiresAtMs,
3835
- enforcedLimits: modelReservation.enforcedLimits,
3836
- network: modelReservation.network
3837
- },
3838
- executorInputs: {
3839
- taskFiles: taskExecutorFiles,
3840
- ...candidateExecutorFiles ? { candidateFiles: candidateExecutorFiles } : {},
3841
- profileFiles: exactProfileExecutorFiles(profileWorkspacePlan.files, profileApplication.profileActivation.profilePlan.material.files)
3842
- },
3843
- ...preparedMemory.accessDigest && preparedMemory.value.mode === "isolated" ? { memoryReservation: {
3844
- preparationId,
4002
+ modelGrantDigest: modelReservation.digest,
4003
+ resolvedModel,
4004
+ ...preparedMemory?.value.mode === "isolated" ? { memory: {
3845
4005
  accessDigest: preparedMemory.accessDigest,
3846
- expiresAtMs: reservationExpiresAtMs,
3847
4006
  effectiveNamespace: preparedMemory.value.effectiveNamespace
3848
- } } : {},
3849
- ...knowledge ? { knowledge } : {},
3850
- trace: {
3851
- runId: traceRunId,
3852
- tags: traceTags,
3853
- env: traceEnv
3854
- },
3855
- memory
3856
- });
3857
- } catch (error) {
3858
- const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
3859
- const cleanup = [];
3860
- if (preparedMemory?.value.mode === "isolated") {
3861
- const accessDigest = preparedMemory.accessDigest;
3862
- const effectiveNamespace = preparedMemory.value.effectiveNamespace;
3863
- if (!accessDigest) throw new Error("isolated memory preparation is missing access identity");
3864
- cleanup.push(withinCandidateCleanupDeadline(async () => {
3865
- const closed = await ports.memory.close({
3866
- executionId: task.executionId,
3867
- preparationId,
3868
- accessDigest,
3869
- effectiveNamespace,
3870
- reason: "preparation-failed"
3871
- });
3872
- if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("failed preparation did not close isolated memory access");
3873
- }, cleanupDeadlineAtMs, "failed preparation memory cleanup"));
3874
- }
3875
- cleanup.push(withinCandidateCleanupDeadline(async () => {
3876
- if (sealAgentCandidateModelSettlement(await ports.models.settleGrant({
3877
- executionId: task.executionId,
3878
- preparationId,
3879
- grantDigest: modelReservation.digest,
3880
- resolved: resolvedModel,
3881
- reason: "preparation-failed"
3882
- }), {
3883
- preparationId,
3884
- grantDigest: modelReservation.digest,
3885
- model: resolvedModel.model
3886
- }).usage.modelCalls !== 0) throw new Error("failed preparation unexpectedly contains model calls");
3887
- }, cleanupDeadlineAtMs, "failed preparation model cleanup"));
3888
- const cleanupErrors = (await Promise.allSettled(cleanup)).filter((result) => result.status === "rejected").map((result) => result.reason);
3889
- if (cleanupErrors.length > 0) throw new Error(`candidate preparation failed and protected access cleanup failed: ${cleanupErrors.map(errorMessage).join("; ")}`, { cause: error });
4007
+ } } : {}
4008
+ }, error);
3890
4009
  throw error;
3891
4010
  }
3892
4011
  }
4012
+ const attemptOf = (task) => ({
4013
+ number: task.runCell.attempt,
4014
+ maxAttempts: task.task.attempt.maxAttempts,
4015
+ retryPolicy: task.task.attempt.retryPolicy
4016
+ });
4017
+ /** Check the call before any compute, and size its timeouts and reservation window. */
4018
+ function checkPreparation(candidate, task, ports, options) {
4019
+ const cleanupTimeoutMs = candidateCleanupTimeout(options.cleanupTimeoutMs);
4020
+ assertSameVerificationPorts(getVerifiedCandidateState(candidate).ports, ports);
4021
+ const bundle = candidate.bundle;
4022
+ if (task.runCell.bundleDigest !== bundle.digest) throw new Error("candidate experiment cell does not bind the verified bundle");
4023
+ const benchmarkTask = task.task;
4024
+ assertTaskInput(task, bundle.execution.instructionDelivery);
4025
+ const resultTimeoutMs = candidateResultTimeout(options.resultTimeoutMs, benchmarkTask.limits.timeoutMs);
4026
+ const reservationWindowMs = candidateExecutionOwnerWindowMs(benchmarkTask.limits.timeoutMs, cleanupTimeoutMs, resultTimeoutMs) + PREPARED_HOLD_MARGIN_MS;
4027
+ if (reservationWindowMs > 2147483647) throw new Error("candidate reservation window exceeds the supported timer range");
4028
+ assertDisjointHostStagingRoots(task);
4029
+ return {
4030
+ cleanupTimeoutMs,
4031
+ resultTimeoutMs,
4032
+ reservationWindowMs
4033
+ };
4034
+ }
4035
+ /** Seal the plan and receipt over what the preparation staged and reserved, and freeze it. */
4036
+ async function assemblePrepared(hold) {
4037
+ const { candidate, task, ports, profile, container, resolvedModel, preparedMemory } = hold;
4038
+ const { bundle } = candidate;
4039
+ const memory = preparedMemory.value;
4040
+ const knowledge = await prepareAgentCandidateKnowledge(candidate, ports, task.runCell.arm);
4041
+ const knowledgePaths = knowledge ? candidateKnowledgeExecutionPaths(task.executionRoots.taskRoot, knowledge.retrievalConfig !== void 0) : void 0;
4042
+ const baseLaunch = buildLaunch(candidate, task, profile.application.flags);
4043
+ const publicEnv = launchEnvironment(candidate, profile, knowledgePaths);
4044
+ const executionPlan = sealExecutionPlan(executionPlanMaterial({
4045
+ candidate,
4046
+ task,
4047
+ profile,
4048
+ container,
4049
+ resolvedModel,
4050
+ modelReservation: hold.modelReservation,
4051
+ launch: baseLaunch,
4052
+ publicEnv,
4053
+ memory
4054
+ }));
4055
+ const materializationReceipt = sealMaterializationReceipt({
4056
+ candidate,
4057
+ task,
4058
+ profile,
4059
+ executionPlan: executionPlan.evidence,
4060
+ container,
4061
+ resolvedModel
4062
+ });
4063
+ const trace = candidateTraceBindings({
4064
+ task,
4065
+ bundleDigest: bundle.digest,
4066
+ attemptNumber: task.runCell.attempt,
4067
+ preparationId: hold.preparationId,
4068
+ executionPlanDigest: executionPlan.evidence.digest,
4069
+ materializationReceiptDigest: materializationReceipt.digest,
4070
+ publicEnv
4071
+ });
4072
+ const { modelReservation } = hold;
4073
+ return createPreparedCandidateExecution({
4074
+ ports,
4075
+ bundle,
4076
+ benchmarkSuite: task.benchmarkSuite,
4077
+ benchmarkTask: task.task,
4078
+ executionId: task.executionId,
4079
+ roots: {
4080
+ execution: { ...task.executionRoots },
4081
+ staging: { ...task.stagingRoots }
4082
+ },
4083
+ profilePlan: {
4084
+ value: profile.application.profileActivation.profilePlan,
4085
+ bytes: profile.planBytes,
4086
+ written: [...profile.application.application.mountPaths]
4087
+ },
4088
+ profileActivation: profile.application.profileActivation,
4089
+ executionPlan: {
4090
+ value: executionPlan.evidence,
4091
+ bytes: executionPlan.bytes
4092
+ },
4093
+ materializationReceipt,
4094
+ launch: {
4095
+ executable: baseLaunch.executable,
4096
+ args: baseLaunch.args.map((value, index) => requirePublicCandidateConfigValue(value, `launch.args[${index}]`)),
4097
+ env: unwrapPublicEnvironment(publicEnv),
4098
+ flags: profile.application.flags.map((value, index) => requirePublicCandidateConfigValue(value, `profile.flags[${index}]`)),
4099
+ cwd: absoluteExecutionCwd(bundle.execution.cwd, task.executionRoots)
4100
+ },
4101
+ instruction: {
4102
+ bytes: Uint8Array.from(hold.instructionBytes),
4103
+ delivery: bundle.execution.instructionDelivery
4104
+ },
4105
+ resolvedModel,
4106
+ preparationId: hold.preparationId,
4107
+ reservationExpiresAtMs: hold.reservationExpiresAtMs,
4108
+ cleanupTimeoutMs: hold.cleanupTimeoutMs,
4109
+ resultTimeoutMs: hold.resultTimeoutMs,
4110
+ modelReservation: {
4111
+ preparationId: modelReservation.preparationId,
4112
+ digest: modelReservation.digest,
4113
+ expiresAtMs: modelReservation.expiresAtMs,
4114
+ enforcedLimits: modelReservation.enforcedLimits,
4115
+ network: modelReservation.network
4116
+ },
4117
+ executorInputs: {
4118
+ taskFiles: hold.taskExecutorFiles,
4119
+ ...hold.candidateExecutorFiles ? { candidateFiles: hold.candidateExecutorFiles } : {},
4120
+ profileFiles: exactProfileExecutorFiles(profile.workspacePlan.files, profile.application.profileActivation.profilePlan.material.files)
4121
+ },
4122
+ ...preparedMemory.accessDigest && memory.mode === "isolated" ? { memoryReservation: {
4123
+ preparationId: hold.preparationId,
4124
+ accessDigest: preparedMemory.accessDigest,
4125
+ expiresAtMs: hold.reservationExpiresAtMs,
4126
+ effectiveNamespace: memory.effectiveNamespace
4127
+ } } : {},
4128
+ ...knowledge ? { knowledge } : {},
4129
+ trace,
4130
+ memory
4131
+ });
4132
+ }
3893
4133
  function assertSameVerificationPorts(verified, execution) {
3894
4134
  if (verified.artifacts !== execution.artifacts || verified.repositories !== execution.repositories) throw new Error("prepare must use the same artifact and repository ports that verified the bundle");
3895
4135
  }
@@ -3970,11 +4210,6 @@ function isContainedPath(parent, child) {
3970
4210
  const path = relative(parent, child);
3971
4211
  return path !== "" && !path.startsWith("..") && !isAbsolute(path);
3972
4212
  }
3973
- async function assertEmptyDirectory(path) {
3974
- const stats = await lstat(path);
3975
- if (!stats.isDirectory() || stats.isSymbolicLink()) throw new Error("profile staging root must be a real directory");
3976
- if ((await readdir(path)).length !== 0) throw new Error("profile staging root must be empty before materialization");
3977
- }
3978
4213
  async function resolveContainer(candidate, task, ports) {
3979
4214
  const environment = candidate.bundle.execution.environment;
3980
4215
  const evaluatorTaskContainer = task.task.evaluatorTaskContainer;
@@ -4054,19 +4289,6 @@ async function prepareMemory(candidate, task, ports, preparationId, expiresAtMs,
4054
4289
  throw error;
4055
4290
  }
4056
4291
  }
4057
- function mergePublicEnvironment(...records) {
4058
- const output = {};
4059
- for (const record of records) for (const [name, value] of Object.entries(record)) {
4060
- const previous = output[name];
4061
- const publicValue = requirePublicCandidateConfigValue(value, `env.${name}`);
4062
- if (previous && requirePublicCandidateConfigValue(previous, `env.${name}`) !== publicValue) throw new Error(`candidate and profile environment disagree on ${name}`);
4063
- output[name] = value;
4064
- }
4065
- return output;
4066
- }
4067
- function unwrapPublicEnvironment(values) {
4068
- return Object.fromEntries(Object.entries(values).map(([name, value]) => [name, requirePublicCandidateConfigValue(value, `env.${name}`)]));
4069
- }
4070
4292
  function validateProtectedModelReservation(reservation, expectedLimits, preparationId, expiresAtMs) {
4071
4293
  if (!/^sha256:[a-f0-9]{64}$/.test(reservation.digest)) throw new Error("protected model reservation has an invalid identity digest");
4072
4294
  if (reservation.preparationId !== preparationId || reservation.expiresAtMs !== expiresAtMs) throw new Error("protected model reservation is not scoped to this preparation");
@@ -4075,14 +4297,45 @@ function validateProtectedModelReservation(reservation, expectedLimits, preparat
4075
4297
  const expectedNetworkMode = limits.maxModelCalls === 0 ? "disabled" : "gateway-only";
4076
4298
  if (agentCandidateModelAccessNetworkSchema.parse(reservation.network).mode !== expectedNetworkMode) throw new Error("protected model reservation has the wrong network policy for its call limit");
4077
4299
  }
4078
- function assertEnvironmentDisjoint(publicEnv, traceEnv) {
4079
- const seen = new Set(Object.keys(publicEnv));
4080
- for (const name of Object.keys(traceEnv)) {
4081
- if (seen.has(name)) throw new Error(`evaluator environment binding collides with ${name}`);
4082
- seen.add(name);
4300
+ /**
4301
+ * Close the isolated memory and settle the model grant of a preparation that failed. Throws a
4302
+ * combined error, with `cause` set to the preparation's own, when a cleanup fails too.
4303
+ */
4304
+ async function cleanupFailedPreparation(held, error) {
4305
+ const { task, ports, preparationId, resolvedModel } = held;
4306
+ const cleanupDeadlineAtMs = candidateCleanupDeadline(held.cleanupTimeoutMs);
4307
+ const cleanup = [];
4308
+ if (held.memory !== void 0) {
4309
+ const { accessDigest, effectiveNamespace } = held.memory;
4310
+ if (!accessDigest) throw new Error("isolated memory preparation is missing access identity");
4311
+ cleanup.push(withinCandidateCleanupDeadline(async () => {
4312
+ const closed = await ports.memory.close({
4313
+ executionId: task.executionId,
4314
+ preparationId,
4315
+ accessDigest,
4316
+ effectiveNamespace,
4317
+ reason: "preparation-failed"
4318
+ });
4319
+ if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("failed preparation did not close isolated memory access");
4320
+ }, cleanupDeadlineAtMs, "failed preparation memory cleanup"));
4083
4321
  }
4322
+ cleanup.push(withinCandidateCleanupDeadline(async () => {
4323
+ if (sealAgentCandidateModelSettlement(await ports.models.settleGrant({
4324
+ executionId: task.executionId,
4325
+ preparationId,
4326
+ grantDigest: held.modelGrantDigest,
4327
+ resolved: resolvedModel,
4328
+ reason: "preparation-failed"
4329
+ }), {
4330
+ preparationId,
4331
+ grantDigest: held.modelGrantDigest,
4332
+ model: resolvedModel.model
4333
+ }).usage.modelCalls !== 0) throw new Error("failed preparation unexpectedly contains model calls");
4334
+ }, cleanupDeadlineAtMs, "failed preparation model cleanup"));
4335
+ const cleanupErrors = (await Promise.allSettled(cleanup)).filter((result) => result.status === "rejected").map((result) => result.reason);
4336
+ if (cleanupErrors.length > 0) throw new Error(`candidate preparation failed and protected access cleanup failed: ${cleanupErrors.map(errorMessage).join("; ")}`, { cause: error });
4084
4337
  }
4085
4338
  //#endregion
4086
4339
  export { verifiedResourceTextByDigest as C, AGENT_CANDIDATE_EXECUTION_SUPPORT as S, sealTerminalDigest as _, consumePreparedCandidateExecution as a, sealAgentCandidateModelSettlement as b, withinCandidateCleanupDeadline as c, assertTerminalMatchesClaim as d, assertTerminalMatchesStaged as f, requireStagedTerminal as g, rejectedStage as h, beginPreparedCandidateDisposal as i, assertRecoveryMatchesStaged as l, rejectedFinish as m, executePreparedAgentCandidate as n, candidateClaimFileInternals as o, recoveredTerminalRecord as p, assertPreparedCandidateIntegrity as r, candidateCleanupDeadline as s, prepareAgentCandidateExecution as t, assertTerminalAllowedInPhase as u, terminalRecord as v, verifyAgentCandidateBundle as w, exactProcessProviderAsCandidateExecutor as x, createProtectedAgentCandidateModelPort as y };
4087
4340
 
4088
- //# sourceMappingURL=prepare-FzJoS68l.js.map
4341
+ //# sourceMappingURL=prepare-C-cWCyt3.js.map