@tangle-network/agent-runtime 0.94.13 → 0.96.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -15
- package/dist/activation-B0ZD7nfX.d.ts +63 -0
- package/dist/agent.d.ts +6 -193
- package/dist/agent.js +10 -234
- package/dist/agent.js.map +1 -1
- package/dist/analyst-loop.d.ts +7 -10
- package/dist/analyst-loop.js +1 -2
- package/dist/candidate-execution/index.d.ts +43 -16
- package/dist/candidate-execution/index.js +17 -8
- package/dist/{chunk-VYA2YEKA.js → chunk-2KGAN2HM.js} +83 -14
- package/dist/chunk-2KGAN2HM.js.map +1 -0
- package/dist/chunk-3XKSBI2U.js +474 -0
- package/dist/chunk-3XKSBI2U.js.map +1 -0
- package/dist/{chunk-TVJQAYQM.js → chunk-6XKPVJAZ.js} +107 -716
- package/dist/chunk-6XKPVJAZ.js.map +1 -0
- package/dist/chunk-BLQIYRVR.js +699 -0
- package/dist/chunk-BLQIYRVR.js.map +1 -0
- package/dist/{chunk-QDSOD7RC.js → chunk-FD2MBMOH.js} +13 -101
- package/dist/chunk-FD2MBMOH.js.map +1 -0
- package/dist/{chunk-U33YZ7B2.js → chunk-FXF2OL34.js} +8 -8
- package/dist/{chunk-EP6RVHMX.js → chunk-HZDEXTSL.js} +848 -2
- package/dist/chunk-HZDEXTSL.js.map +1 -0
- package/dist/{chunk-WIPGQ4GT.js → chunk-IMSNJSXH.js} +1 -1
- package/dist/{chunk-WIPGQ4GT.js.map → chunk-IMSNJSXH.js.map} +1 -1
- package/dist/{chunk-VSWBYWFK.js → chunk-M6MD6JBS.js} +20 -27
- package/dist/chunk-M6MD6JBS.js.map +1 -0
- package/dist/chunk-PSOCBNM3.js +2069 -0
- package/dist/chunk-PSOCBNM3.js.map +1 -0
- package/dist/{chunk-AEG3NGJ2.js → chunk-Q2JSAVQ3.js} +34 -2
- package/dist/chunk-Q2JSAVQ3.js.map +1 -0
- package/dist/{chunk-XP5KDM3R.js → chunk-SGQ4YIQW.js} +4 -4
- package/dist/{chunk-C3UKLQ54.js → chunk-UQ6PNNXM.js} +18 -10
- package/dist/chunk-UQ6PNNXM.js.map +1 -0
- package/dist/{chunk-33OG2NN3.js → chunk-WYC2XJF2.js} +2 -2
- package/dist/{chunk-ZEYAT33L.js → chunk-Y3SRWZMP.js} +2 -2
- package/dist/{chunk-CNH7DF7Z.js → chunk-YOLKCWRV.js} +1116 -591
- package/dist/chunk-YOLKCWRV.js.map +1 -0
- package/dist/{completion-gate-D1gX1-hg.d.ts → completion-gate-C80jiRfN.d.ts} +1 -1
- package/dist/conversation.d.ts +12 -1
- package/dist/conversation.js +2 -3
- package/dist/{coordination-Dr_axlAf.d.ts → coordination-BFE3Den7.d.ts} +10 -11
- package/dist/environment-provider.d.ts +2 -2
- package/dist/environment-provider.js +1 -2
- package/dist/{agentic-generator-DDMM45kZ.d.ts → improve-g75IE2Cx.d.ts} +152 -4
- package/dist/{improvement-adapter-BieWeK5J.d.ts → improvement-adapter-HAZz-7vK.d.ts} +8 -31
- package/dist/index.d.ts +55 -28
- package/dist/index.js +206 -82
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +185 -120
- package/dist/intelligence.js +509 -345
- package/dist/intelligence.js.map +1 -1
- package/dist/knowledge.d.ts +40 -12
- package/dist/knowledge.js +13 -7
- package/dist/{loop-runner-bin-BRQSQdHa.d.ts → loop-runner-bin-Cn1N2rRo.d.ts} +3 -3
- package/dist/loop-runner-bin.d.ts +6 -6
- package/dist/loop-runner-bin.js +8 -10
- package/dist/loops.d.ts +13 -13
- package/dist/loops.js +6 -8
- package/dist/mcp/bin.js +5 -7
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +6 -6
- package/dist/mcp/index.js +12 -14
- package/dist/mcp/index.js.map +1 -1
- package/dist/platform.js +0 -2
- package/dist/platform.js.map +1 -1
- package/dist/primeintellect/index.js +1 -2
- package/dist/primeintellect/index.js.map +1 -1
- package/dist/profile-DbfaMTdk.d.ts +233 -0
- package/dist/profiles.d.ts +1 -1
- package/dist/profiles.js +0 -1
- package/dist/profiles.js.map +1 -1
- package/dist/{supervise-DmYOug5f.d.ts → supervise-BLPI50-w.d.ts} +3 -3
- package/dist/{types-ByAYqlVb.d.ts → types-B3vAW0Oq.d.ts} +1 -1
- package/dist/{prepare-CtdtsFNG.d.ts → types-CWqfCO8s.d.ts} +67 -298
- package/dist/{types-BC3bZpH0.d.ts → types-CmYCMbFT.d.ts} +12 -54
- package/dist/{types-1d5QGK3t.d.ts → types-CmnA2iL3.d.ts} +3 -3
- package/dist/{worktree-fanout-CPprU-qI.d.ts → worktree-fanout-DCA3G4bO.d.ts} +3 -3
- package/package.json +14 -16
- package/skills/build-with-agent-runtime/SKILL.md +122 -213
- package/dist/chunk-6O73TRHW.js +0 -142
- package/dist/chunk-6O73TRHW.js.map +0 -1
- package/dist/chunk-AEG3NGJ2.js.map +0 -1
- package/dist/chunk-C3UKLQ54.js.map +0 -1
- package/dist/chunk-CNH7DF7Z.js.map +0 -1
- package/dist/chunk-D3H7F6L2.js +0 -626
- package/dist/chunk-D3H7F6L2.js.map +0 -1
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-DGUM43GV.js.map +0 -1
- package/dist/chunk-EP6RVHMX.js.map +0 -1
- package/dist/chunk-HGRW27YY.js +0 -214
- package/dist/chunk-HGRW27YY.js.map +0 -1
- package/dist/chunk-ISTDY47H.js +0 -849
- package/dist/chunk-ISTDY47H.js.map +0 -1
- package/dist/chunk-PCURO3DL.js +0 -661
- package/dist/chunk-PCURO3DL.js.map +0 -1
- package/dist/chunk-QDSOD7RC.js.map +0 -1
- package/dist/chunk-TVJQAYQM.js.map +0 -1
- package/dist/chunk-VSWBYWFK.js.map +0 -1
- package/dist/chunk-VYA2YEKA.js.map +0 -1
- package/dist/generator-YkAQrOoD.d.ts +0 -382
- package/dist/improve-BN3HyXIO.d.ts +0 -172
- package/dist/lifecycle.d.ts +0 -870
- package/dist/lifecycle.js +0 -981
- package/dist/lifecycle.js.map +0 -1
- package/dist/mcp-serve-verifier-DQQDbuyz.d.ts +0 -34
- package/skills/agent-runtime-adoption/SKILL.md +0 -246
- /package/dist/{chunk-U33YZ7B2.js.map → chunk-FXF2OL34.js.map} +0 -0
- /package/dist/{chunk-XP5KDM3R.js.map → chunk-SGQ4YIQW.js.map} +0 -0
- /package/dist/{chunk-33OG2NN3.js.map → chunk-WYC2XJF2.js.map} +0 -0
- /package/dist/{chunk-ZEYAT33L.js.map → chunk-Y3SRWZMP.js.map} +0 -0
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
contentAddress
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IMSNJSXH.js";
|
|
4
4
|
|
|
5
|
-
// src/candidate-execution/
|
|
6
|
-
import {
|
|
5
|
+
// src/candidate-execution/profile.ts
|
|
6
|
+
import {
|
|
7
|
+
agentCandidateProfileActivationSchema,
|
|
8
|
+
agentCandidateProfileSchema,
|
|
9
|
+
agentProfileDiffSchema,
|
|
10
|
+
agentProfileSchema,
|
|
11
|
+
applyAgentProfileDiff
|
|
12
|
+
} from "@tangle-network/agent-interface";
|
|
7
13
|
|
|
8
14
|
// src/candidate-execution/digest.ts
|
|
9
15
|
import { createHash } from "crypto";
|
|
@@ -38,6 +44,12 @@ function canonicalCandidateDocument(valueWithoutDigest) {
|
|
|
38
44
|
digest
|
|
39
45
|
});
|
|
40
46
|
}
|
|
47
|
+
function verifyCanonicalCandidateDocument(value, label) {
|
|
48
|
+
if (canonicalCandidateDigest(omitTopLevelDigest(value)) !== value.digest) {
|
|
49
|
+
throw new Error(`${label} digest does not match`);
|
|
50
|
+
}
|
|
51
|
+
return immutableCandidateValue(value);
|
|
52
|
+
}
|
|
41
53
|
function embeddedCandidateArtifact(bytes) {
|
|
42
54
|
return {
|
|
43
55
|
encoding: "base64",
|
|
@@ -61,24 +73,69 @@ function deepFreezeCandidate(value, seen = /* @__PURE__ */ new Set()) {
|
|
|
61
73
|
return Object.freeze(value);
|
|
62
74
|
}
|
|
63
75
|
|
|
64
|
-
// src/candidate-execution/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
// src/candidate-execution/profile.ts
|
|
77
|
+
var MATERIALIZER_HARNESSES = /* @__PURE__ */ new Set([
|
|
78
|
+
"claude-code",
|
|
79
|
+
"claude",
|
|
80
|
+
"claudish",
|
|
81
|
+
"nanoclaw",
|
|
82
|
+
"codex",
|
|
83
|
+
"opencode",
|
|
84
|
+
"kimi-code",
|
|
85
|
+
"kimi",
|
|
86
|
+
"pi",
|
|
87
|
+
"gemini",
|
|
88
|
+
"hermes",
|
|
89
|
+
"openclaw"
|
|
90
|
+
]);
|
|
91
|
+
function candidateMaterializerHarness(harness) {
|
|
92
|
+
if (!MATERIALIZER_HARNESSES.has(harness)) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`sealed candidate profile materialization is unsupported for harness ${harness}`
|
|
95
|
+
);
|
|
71
96
|
}
|
|
72
|
-
return
|
|
97
|
+
return harness;
|
|
98
|
+
}
|
|
99
|
+
function createAgentCandidateProfileActivation(plan, profilePlan) {
|
|
100
|
+
const sourceByPath = new Map(plan.files.map((file) => [file.relPath, file]));
|
|
101
|
+
if (sourceByPath.size !== plan.files.length) {
|
|
102
|
+
throw new Error("candidate profile activation contains duplicate native file paths");
|
|
103
|
+
}
|
|
104
|
+
const files = profilePlan.material.files.map((expected) => {
|
|
105
|
+
const source = sourceByPath.get(expected.relPath);
|
|
106
|
+
if (!source) {
|
|
107
|
+
throw new Error(`candidate profile activation is missing ${expected.relPath}`);
|
|
108
|
+
}
|
|
109
|
+
const mode = source.mode ?? 420;
|
|
110
|
+
if (!Number.isSafeInteger(mode) || mode < 0 || mode > 511) {
|
|
111
|
+
throw new Error(`candidate profile activation has invalid mode for ${expected.relPath}`);
|
|
112
|
+
}
|
|
113
|
+
return { path: expected.relPath, mode, content: source.content };
|
|
114
|
+
});
|
|
115
|
+
if (files.length !== plan.files.length) {
|
|
116
|
+
throw new Error("candidate profile activation contains unplanned native files");
|
|
117
|
+
}
|
|
118
|
+
return parseAgentCandidateProfileActivation(
|
|
119
|
+
canonicalCandidateDocument({
|
|
120
|
+
kind: "agent-candidate-profile-activation",
|
|
121
|
+
profilePlan,
|
|
122
|
+
files
|
|
123
|
+
}).value,
|
|
124
|
+
profilePlan.digest
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
function parseAgentCandidateProfileActivation(input, expectedProfilePlanDigest) {
|
|
128
|
+
const activation = agentCandidateProfileActivationSchema.parse(input);
|
|
129
|
+
const planBytes = canonicalCandidateBytes(activation.profilePlan.material);
|
|
130
|
+
const profilePlanArtifact = activation.profilePlan.artifact;
|
|
131
|
+
if (sha256Bytes(planBytes) !== activation.profilePlan.digest || profilePlanArtifact.sha256 !== activation.profilePlan.digest || profilePlanArtifact.byteLength !== planBytes.byteLength || "content" in profilePlanArtifact && !Buffer.from(profilePlanArtifact.content, "base64").equals(Buffer.from(planBytes)) || expectedProfilePlanDigest !== void 0 && activation.profilePlan.digest !== expectedProfilePlanDigest) {
|
|
132
|
+
throw new Error("candidate profile activation has an invalid canonical profile plan");
|
|
133
|
+
}
|
|
134
|
+
if (canonicalCandidateDigest(omitTopLevelDigest(activation)) !== activation.digest) {
|
|
135
|
+
throw new Error("candidate profile activation digest does not match");
|
|
136
|
+
}
|
|
137
|
+
return immutableCandidateValue(activation);
|
|
73
138
|
}
|
|
74
|
-
|
|
75
|
-
// src/candidate-execution/profile.ts
|
|
76
|
-
import {
|
|
77
|
-
agentCandidateProfileSchema,
|
|
78
|
-
agentProfileDiffSchema,
|
|
79
|
-
agentProfileSchema,
|
|
80
|
-
applyAgentProfileDiff
|
|
81
|
-
} from "@tangle-network/agent-interface";
|
|
82
139
|
var CANDIDATE_PROFILE_DIRECT_FIELDS = [
|
|
83
140
|
"name",
|
|
84
141
|
"description",
|
|
@@ -137,18 +194,28 @@ function assertCandidateProfileBinding(measuredInput, bundled) {
|
|
|
137
194
|
if (measured.connections || measured.metadata || measured.extensions) {
|
|
138
195
|
throw new Error("proposal candidate profile contains fields unsupported by sealed candidates");
|
|
139
196
|
}
|
|
140
|
-
const normalized =
|
|
197
|
+
const normalized = agentCandidateProfileAsAgentProfile(bundled);
|
|
141
198
|
if (canonicalCandidateDigest(measured) !== canonicalCandidateDigest(normalized)) {
|
|
142
199
|
throw new Error("proposal candidateProfile does not match candidateBundle.profile");
|
|
143
200
|
}
|
|
144
201
|
}
|
|
145
202
|
function parseExactAgentProfile(input, label) {
|
|
146
|
-
|
|
203
|
+
let parsed;
|
|
204
|
+
try {
|
|
205
|
+
parsed = agentProfileSchema.parse(input);
|
|
206
|
+
} catch (cause) {
|
|
207
|
+
throw new Error(`${label} contains unsupported or non-canonical fields`, { cause });
|
|
208
|
+
}
|
|
147
209
|
assertCanonicalParse(input, parsed, label);
|
|
148
210
|
return parsed;
|
|
149
211
|
}
|
|
150
212
|
function parseExactAgentProfileDiff(input, label) {
|
|
151
|
-
|
|
213
|
+
let parsed;
|
|
214
|
+
try {
|
|
215
|
+
parsed = agentProfileDiffSchema.parse(input);
|
|
216
|
+
} catch (cause) {
|
|
217
|
+
throw new Error(`${label} contains unsupported or non-canonical fields`, { cause });
|
|
218
|
+
}
|
|
152
219
|
assertCanonicalParse(input, parsed, label);
|
|
153
220
|
return parsed;
|
|
154
221
|
}
|
|
@@ -172,7 +239,7 @@ function assertCandidateProfileExecutionSupport(profile) {
|
|
|
172
239
|
);
|
|
173
240
|
}
|
|
174
241
|
}
|
|
175
|
-
function
|
|
242
|
+
function agentCandidateProfileAsAgentProfile(candidate) {
|
|
176
243
|
const output = {};
|
|
177
244
|
copyDirectProfileFields(output, candidate);
|
|
178
245
|
if (candidate.model) output.model = { ...candidate.model };
|
|
@@ -375,13 +442,9 @@ import {
|
|
|
375
442
|
} from "@tangle-network/agent-interface";
|
|
376
443
|
|
|
377
444
|
// src/candidate-execution/claim-file-formats.ts
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
var PHASE_FORMAT_VERSION = 1;
|
|
382
|
-
|
|
383
|
-
// src/candidate-execution/claim-terminal.ts
|
|
384
|
-
import { agentCandidateArtifactRefSchema } from "@tangle-network/agent-interface";
|
|
445
|
+
import {
|
|
446
|
+
agentCandidateArtifactRefSchema
|
|
447
|
+
} from "@tangle-network/agent-interface";
|
|
385
448
|
|
|
386
449
|
// src/candidate-execution/exact-object.ts
|
|
387
450
|
function assertExactObjectKeys(value, required, label, optional = []) {
|
|
@@ -400,7 +463,31 @@ function assertExactObjectKeys(value, required, label, optional = []) {
|
|
|
400
463
|
}
|
|
401
464
|
}
|
|
402
465
|
|
|
466
|
+
// src/candidate-execution/claim-file-formats.ts
|
|
467
|
+
function sealCandidatePreparationEvidence(value, executionPlanDigest) {
|
|
468
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
469
|
+
throw new Error("candidate execution preparation evidence must be an object");
|
|
470
|
+
}
|
|
471
|
+
const record = value;
|
|
472
|
+
assertExactObjectKeys(
|
|
473
|
+
record,
|
|
474
|
+
["executionPlan", "materializationReceipt"],
|
|
475
|
+
"candidate execution preparation evidence"
|
|
476
|
+
);
|
|
477
|
+
const executionPlan = immutableCandidateValue(
|
|
478
|
+
agentCandidateArtifactRefSchema.parse(record.executionPlan)
|
|
479
|
+
);
|
|
480
|
+
const materializationReceipt = immutableCandidateValue(
|
|
481
|
+
agentCandidateArtifactRefSchema.parse(record.materializationReceipt)
|
|
482
|
+
);
|
|
483
|
+
if (executionPlan.sha256 !== executionPlanDigest) {
|
|
484
|
+
throw new Error("candidate execution plan artifact digest does not match its claim");
|
|
485
|
+
}
|
|
486
|
+
return Object.freeze({ executionPlan, materializationReceipt });
|
|
487
|
+
}
|
|
488
|
+
|
|
403
489
|
// src/candidate-execution/claim-terminal.ts
|
|
490
|
+
import { agentCandidateArtifactRefSchema as agentCandidateArtifactRefSchema2 } from "@tangle-network/agent-interface";
|
|
404
491
|
var SHA256_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
405
492
|
function terminalRecord(claim, result) {
|
|
406
493
|
const terminal = sealTerminalResult(result);
|
|
@@ -409,6 +496,7 @@ function terminalRecord(claim, result) {
|
|
|
409
496
|
attempt: claim.attempt,
|
|
410
497
|
bundleDigest: claim.bundleDigest,
|
|
411
498
|
executionPlanDigest: claim.executionPlanDigest,
|
|
499
|
+
preparationEvidence: claim.preparationEvidence,
|
|
412
500
|
...terminal
|
|
413
501
|
};
|
|
414
502
|
return immutableCandidateValue({
|
|
@@ -419,7 +507,6 @@ function terminalRecord(claim, result) {
|
|
|
419
507
|
function recoveredTerminalRecord(claim, phase, evidence) {
|
|
420
508
|
const recovered = sealRecoveryEvidence(evidence, claim);
|
|
421
509
|
return terminalRecord(claim, {
|
|
422
|
-
schemaVersion: 1,
|
|
423
510
|
status: "failed",
|
|
424
511
|
failureClass: recovered.failureClass === "pre-model-infrastructure" && phase !== "claimed" ? "unknown" : recovered.failureClass,
|
|
425
512
|
usage: recovered.usage,
|
|
@@ -474,8 +561,8 @@ function sealTerminalRecordValue(value, label) {
|
|
|
474
561
|
"attempt",
|
|
475
562
|
"bundleDigest",
|
|
476
563
|
"executionPlanDigest",
|
|
564
|
+
"preparationEvidence",
|
|
477
565
|
"terminalDigest",
|
|
478
|
-
"schemaVersion",
|
|
479
566
|
"status",
|
|
480
567
|
"usage",
|
|
481
568
|
"modelSettlement",
|
|
@@ -487,8 +574,8 @@ function sealTerminalRecordValue(value, label) {
|
|
|
487
574
|
"attempt",
|
|
488
575
|
"bundleDigest",
|
|
489
576
|
"executionPlanDigest",
|
|
577
|
+
"preparationEvidence",
|
|
490
578
|
"terminalDigest",
|
|
491
|
-
"schemaVersion",
|
|
492
579
|
"status",
|
|
493
580
|
"failureClass",
|
|
494
581
|
"usage",
|
|
@@ -497,14 +584,19 @@ function sealTerminalRecordValue(value, label) {
|
|
|
497
584
|
],
|
|
498
585
|
label
|
|
499
586
|
);
|
|
587
|
+
const executionPlanDigest = requireString(
|
|
588
|
+
value.executionPlanDigest,
|
|
589
|
+
label,
|
|
590
|
+
"executionPlanDigest"
|
|
591
|
+
);
|
|
500
592
|
const identity = {
|
|
501
593
|
executionId: requireString(value.executionId, label, "executionId"),
|
|
502
594
|
attempt: requireNumber(value.attempt, label, "attempt"),
|
|
503
595
|
bundleDigest: requireString(value.bundleDigest, label, "bundleDigest"),
|
|
504
|
-
executionPlanDigest
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
596
|
+
executionPlanDigest,
|
|
597
|
+
preparationEvidence: sealCandidatePreparationEvidence(
|
|
598
|
+
value.preparationEvidence,
|
|
599
|
+
executionPlanDigest
|
|
508
600
|
)
|
|
509
601
|
};
|
|
510
602
|
assertExecutionId(identity.executionId);
|
|
@@ -513,28 +605,21 @@ function sealTerminalRecordValue(value, label) {
|
|
|
513
605
|
}
|
|
514
606
|
assertSha256Digest(identity.bundleDigest, "bundleDigest");
|
|
515
607
|
assertSha256Digest(identity.executionPlanDigest, "executionPlanDigest");
|
|
608
|
+
if (identity.preparationEvidence.executionPlan.sha256 !== identity.executionPlanDigest) {
|
|
609
|
+
throw new Error(`${label} execution plan artifact does not match executionPlanDigest`);
|
|
610
|
+
}
|
|
516
611
|
const result = sealTerminalResult(
|
|
517
612
|
status === "succeeded" ? {
|
|
518
|
-
schemaVersion: requireNumber(value.schemaVersion, label, "schemaVersion"),
|
|
519
613
|
status,
|
|
520
|
-
usage: requireObject(
|
|
521
|
-
value.usage,
|
|
522
|
-
label,
|
|
523
|
-
"usage"
|
|
524
|
-
),
|
|
614
|
+
usage: requireObject(value.usage, label, "usage"),
|
|
525
615
|
modelSettlement: requireArtifactRef(value.modelSettlement, label, "modelSettlement"),
|
|
526
616
|
taskOutcome: requireArtifactRef(value.taskOutcome, label, "taskOutcome"),
|
|
527
617
|
benchmarkResult: requireArtifactRef(value.benchmarkResult, label, "benchmarkResult"),
|
|
528
618
|
runReceipt: requireArtifactRef(value.runReceipt, label, "runReceipt")
|
|
529
619
|
} : {
|
|
530
|
-
schemaVersion: requireNumber(value.schemaVersion, label, "schemaVersion"),
|
|
531
620
|
status,
|
|
532
621
|
failureClass: requireFailureClass(value.failureClass, label),
|
|
533
|
-
usage: requireObject(
|
|
534
|
-
value.usage,
|
|
535
|
-
label,
|
|
536
|
-
"usage"
|
|
537
|
-
),
|
|
622
|
+
usage: requireObject(value.usage, label, "usage"),
|
|
538
623
|
modelSettlement: requireArtifactRef(value.modelSettlement, label, "modelSettlement"),
|
|
539
624
|
...value.failureEvidence ? {
|
|
540
625
|
failureEvidence: requireArtifactRef(
|
|
@@ -561,7 +646,7 @@ function sealTerminalRecordValue(value, label) {
|
|
|
561
646
|
});
|
|
562
647
|
}
|
|
563
648
|
function assertTerminalMatchesClaim(terminal, claim, path) {
|
|
564
|
-
if (terminal.executionId !== claim.executionId || terminal.attempt !== claim.attempt || terminal.bundleDigest !== claim.bundleDigest || terminal.executionPlanDigest !== claim.executionPlanDigest) {
|
|
649
|
+
if (terminal.executionId !== claim.executionId || terminal.attempt !== claim.attempt || terminal.bundleDigest !== claim.bundleDigest || terminal.executionPlanDigest !== claim.executionPlanDigest || canonicalCandidateDigest(terminal.preparationEvidence) !== canonicalCandidateDigest(claim.preparationEvidence)) {
|
|
565
650
|
throw new Error(`candidate execution terminal record at ${path} does not match its claim`);
|
|
566
651
|
}
|
|
567
652
|
}
|
|
@@ -640,16 +725,7 @@ function sealTerminalResult(result) {
|
|
|
640
725
|
}
|
|
641
726
|
assertExactObjectKeys(
|
|
642
727
|
result,
|
|
643
|
-
result.status === "succeeded" ? [
|
|
644
|
-
"schemaVersion",
|
|
645
|
-
"status",
|
|
646
|
-
"usage",
|
|
647
|
-
"modelSettlement",
|
|
648
|
-
"taskOutcome",
|
|
649
|
-
"benchmarkResult",
|
|
650
|
-
"runReceipt"
|
|
651
|
-
] : [
|
|
652
|
-
"schemaVersion",
|
|
728
|
+
result.status === "succeeded" ? ["status", "usage", "modelSettlement", "taskOutcome", "benchmarkResult", "runReceipt"] : [
|
|
653
729
|
"status",
|
|
654
730
|
"failureClass",
|
|
655
731
|
"usage",
|
|
@@ -658,14 +734,10 @@ function sealTerminalResult(result) {
|
|
|
658
734
|
],
|
|
659
735
|
"candidate execution terminal result"
|
|
660
736
|
);
|
|
661
|
-
if (result.schemaVersion !== 1) {
|
|
662
|
-
throw new Error("candidate execution terminal schemaVersion must be 1");
|
|
663
|
-
}
|
|
664
737
|
const usage = sealUsage(result.usage);
|
|
665
738
|
const modelSettlement = sealArtifactRef(result.modelSettlement, "modelSettlement");
|
|
666
739
|
if (result.status === "succeeded") {
|
|
667
740
|
return Object.freeze({
|
|
668
|
-
schemaVersion: 1,
|
|
669
741
|
status: "succeeded",
|
|
670
742
|
usage,
|
|
671
743
|
modelSettlement,
|
|
@@ -679,7 +751,6 @@ function sealTerminalResult(result) {
|
|
|
679
751
|
throw new Error("pre-model infrastructure failure cannot contain model calls");
|
|
680
752
|
}
|
|
681
753
|
return Object.freeze({
|
|
682
|
-
schemaVersion: 1,
|
|
683
754
|
status: "failed",
|
|
684
755
|
failureClass: result.failureClass,
|
|
685
756
|
usage,
|
|
@@ -713,7 +784,7 @@ function sealUsage(usage) {
|
|
|
713
784
|
});
|
|
714
785
|
}
|
|
715
786
|
function sealArtifactRef(ref, label) {
|
|
716
|
-
const parsed =
|
|
787
|
+
const parsed = agentCandidateArtifactRefSchema2.parse(ref);
|
|
717
788
|
if (!Number.isSafeInteger(parsed.byteLength)) {
|
|
718
789
|
throw new Error(`candidate execution terminal ${label} byteLength exceeds safe integer range`);
|
|
719
790
|
}
|
|
@@ -798,29 +869,15 @@ function candidateResultTimeout(timeoutMs, taskTimeoutMs) {
|
|
|
798
869
|
return effective;
|
|
799
870
|
}
|
|
800
871
|
async function withinCandidateCleanupDeadline(operation, deadlineAtMs, label) {
|
|
801
|
-
|
|
802
|
-
if (remainingMs <= 0) throw new CandidateCleanupTimeoutError(label);
|
|
803
|
-
const pending = Promise.resolve().then(operation);
|
|
804
|
-
void pending.catch(() => void 0);
|
|
805
|
-
let timer;
|
|
806
|
-
try {
|
|
807
|
-
const result = await Promise.race([
|
|
808
|
-
pending,
|
|
809
|
-
new Promise((_resolve, reject) => {
|
|
810
|
-
timer = setTimeout(() => reject(new CandidateCleanupTimeoutError(label)), remainingMs);
|
|
811
|
-
})
|
|
812
|
-
]);
|
|
813
|
-
if (Date.now() >= deadlineAtMs) throw new CandidateCleanupTimeoutError(label);
|
|
814
|
-
return result;
|
|
815
|
-
} finally {
|
|
816
|
-
if (timer) clearTimeout(timer);
|
|
817
|
-
}
|
|
872
|
+
return withinCandidateDeadline(operation, deadlineAtMs, new CandidateCleanupTimeoutError(label));
|
|
818
873
|
}
|
|
819
874
|
async function withinCandidateResultDeadline(operation, deadlineAtMs, label) {
|
|
875
|
+
return withinCandidateDeadline(operation, deadlineAtMs, new CandidateResultTimeoutError(label));
|
|
876
|
+
}
|
|
877
|
+
async function withinCandidateDeadline(operation, deadlineAtMs, timeoutError) {
|
|
820
878
|
const remainingMs = deadlineAtMs - Date.now();
|
|
821
|
-
if (remainingMs <= 0) throw
|
|
879
|
+
if (remainingMs <= 0) throw timeoutError;
|
|
822
880
|
const controller = new AbortController();
|
|
823
|
-
const timeoutError = new CandidateResultTimeoutError(label);
|
|
824
881
|
const pending = Promise.resolve().then(() => operation(controller.signal));
|
|
825
882
|
void pending.catch(() => void 0);
|
|
826
883
|
let timer;
|
|
@@ -949,8 +1006,8 @@ var InMemoryAgentCandidateExecutionClaimStore = class {
|
|
|
949
1006
|
}
|
|
950
1007
|
};
|
|
951
1008
|
var SHA256_PATTERN2 = /^sha256:[a-f0-9]{64}$/;
|
|
952
|
-
var LEASE_TOKEN_PATTERN = /^candidate-execution-lease
|
|
953
|
-
var PREPARATION_ID_PATTERN = /^candidate-preparation
|
|
1009
|
+
var LEASE_TOKEN_PATTERN = /^candidate-execution-lease\.[A-Za-z0-9_-]{43}$/;
|
|
1010
|
+
var PREPARATION_ID_PATTERN = /^candidate-preparation\.[A-Za-z0-9_-]{43}$/;
|
|
954
1011
|
function sealClaim(claim) {
|
|
955
1012
|
assertExactObjectKeys(
|
|
956
1013
|
claim,
|
|
@@ -961,6 +1018,7 @@ function sealClaim(claim) {
|
|
|
961
1018
|
"retryPolicy",
|
|
962
1019
|
"bundleDigest",
|
|
963
1020
|
"executionPlanDigest",
|
|
1021
|
+
"preparationEvidence",
|
|
964
1022
|
"retryLineageDigest",
|
|
965
1023
|
"leaseExpiresAtMs",
|
|
966
1024
|
"resultTimeoutMs",
|
|
@@ -986,6 +1044,10 @@ function sealClaim(claim) {
|
|
|
986
1044
|
}
|
|
987
1045
|
assertSha256Digest2(claim.bundleDigest, "bundleDigest");
|
|
988
1046
|
assertSha256Digest2(claim.executionPlanDigest, "executionPlanDigest");
|
|
1047
|
+
const preparationEvidence = sealCandidatePreparationEvidence(
|
|
1048
|
+
claim.preparationEvidence,
|
|
1049
|
+
claim.executionPlanDigest
|
|
1050
|
+
);
|
|
989
1051
|
assertSha256Digest2(claim.retryLineageDigest, "retryLineageDigest");
|
|
990
1052
|
assertPositiveTimestamp(claim.leaseExpiresAtMs, "leaseExpiresAtMs");
|
|
991
1053
|
candidateResultTimeout(claim.resultTimeoutMs, claim.resultTimeoutMs);
|
|
@@ -997,6 +1059,7 @@ function sealClaim(claim) {
|
|
|
997
1059
|
retryPolicy: claim.retryPolicy,
|
|
998
1060
|
bundleDigest: claim.bundleDigest,
|
|
999
1061
|
executionPlanDigest: claim.executionPlanDigest,
|
|
1062
|
+
preparationEvidence,
|
|
1000
1063
|
retryLineageDigest: claim.retryLineageDigest,
|
|
1001
1064
|
leaseExpiresAtMs: claim.leaseExpiresAtMs,
|
|
1002
1065
|
resultTimeoutMs: claim.resultTimeoutMs,
|
|
@@ -1080,7 +1143,7 @@ function newLease(claim) {
|
|
|
1080
1143
|
return Object.freeze({
|
|
1081
1144
|
executionId: claim.executionId,
|
|
1082
1145
|
attempt: claim.attempt,
|
|
1083
|
-
token: `candidate-execution-lease
|
|
1146
|
+
token: `candidate-execution-lease.${randomBytes(32).toString("base64url")}`,
|
|
1084
1147
|
expiresAtMs: claim.leaseExpiresAtMs
|
|
1085
1148
|
});
|
|
1086
1149
|
}
|
|
@@ -1131,19 +1194,16 @@ function rejectedRetry(claim, detail) {
|
|
|
1131
1194
|
async function readClaim(path) {
|
|
1132
1195
|
const parsed = await readJsonObject(path, "claim");
|
|
1133
1196
|
const record = parsed;
|
|
1134
|
-
if (record.version !== CLAIM_FORMAT_VERSION) {
|
|
1135
|
-
throw new Error(`candidate execution claim at ${path} has unsupported version`);
|
|
1136
|
-
}
|
|
1137
1197
|
assertExactObjectKeys(
|
|
1138
1198
|
parsed,
|
|
1139
1199
|
[
|
|
1140
|
-
"version",
|
|
1141
1200
|
"executionId",
|
|
1142
1201
|
"attempt",
|
|
1143
1202
|
"maxAttempts",
|
|
1144
1203
|
"retryPolicy",
|
|
1145
1204
|
"bundleDigest",
|
|
1146
1205
|
"executionPlanDigest",
|
|
1206
|
+
"preparationEvidence",
|
|
1147
1207
|
"retryLineageDigest",
|
|
1148
1208
|
"leaseExpiresAtMs",
|
|
1149
1209
|
"resultTimeoutMs",
|
|
@@ -1164,6 +1224,11 @@ async function readClaim(path) {
|
|
|
1164
1224
|
path,
|
|
1165
1225
|
"executionPlanDigest"
|
|
1166
1226
|
),
|
|
1227
|
+
preparationEvidence: requireObject2(
|
|
1228
|
+
record.preparationEvidence,
|
|
1229
|
+
path,
|
|
1230
|
+
"preparationEvidence"
|
|
1231
|
+
),
|
|
1167
1232
|
retryLineageDigest: requireString2(
|
|
1168
1233
|
record.retryLineageDigest,
|
|
1169
1234
|
path,
|
|
@@ -1199,10 +1264,7 @@ async function readClaimIfPresent(path) {
|
|
|
1199
1264
|
async function readTerminal(path) {
|
|
1200
1265
|
const parsed = await readJsonObject(path, "terminal record");
|
|
1201
1266
|
const record = parsed;
|
|
1202
|
-
|
|
1203
|
-
throw new Error(`candidate execution terminal record at ${path} has unsupported version`);
|
|
1204
|
-
}
|
|
1205
|
-
assertExactObjectKeys(parsed, ["version", "terminal"], `candidate execution terminal record at ${path}`);
|
|
1267
|
+
assertExactObjectKeys(parsed, ["terminal"], `candidate execution terminal record at ${path}`);
|
|
1206
1268
|
return sealTerminalRecordValue(
|
|
1207
1269
|
requireObject2(record.terminal, path, "terminal"),
|
|
1208
1270
|
`candidate execution terminal record at ${path}`
|
|
@@ -1226,12 +1288,9 @@ async function readTransitionIfPresent(path, claim) {
|
|
|
1226
1288
|
}
|
|
1227
1289
|
if (parsed.kind === "candidate-execution-phase") {
|
|
1228
1290
|
const record = parsed;
|
|
1229
|
-
if (record.version !== PHASE_FORMAT_VERSION) {
|
|
1230
|
-
throw new Error(`candidate execution phase record at ${path} has unsupported version`);
|
|
1231
|
-
}
|
|
1232
1291
|
assertExactObjectKeys(
|
|
1233
1292
|
parsed,
|
|
1234
|
-
["
|
|
1293
|
+
["kind", "executionId", "attempt", "executionPlanDigest", "phase"],
|
|
1235
1294
|
`candidate execution phase record at ${path}`
|
|
1236
1295
|
);
|
|
1237
1296
|
if (record.executionId !== claim.executionId || record.attempt !== claim.attempt || record.executionPlanDigest !== claim.executionPlanDigest || record.phase !== "candidate-may-run") {
|
|
@@ -1241,14 +1300,7 @@ async function readTransitionIfPresent(path, claim) {
|
|
|
1241
1300
|
}
|
|
1242
1301
|
if (parsed.kind === "candidate-execution-pending-terminal") {
|
|
1243
1302
|
const record = parsed;
|
|
1244
|
-
|
|
1245
|
-
throw new Error(`candidate execution pending record at ${path} has unsupported version`);
|
|
1246
|
-
}
|
|
1247
|
-
assertExactObjectKeys(
|
|
1248
|
-
parsed,
|
|
1249
|
-
["version", "kind", "terminal"],
|
|
1250
|
-
`candidate execution pending record at ${path}`
|
|
1251
|
-
);
|
|
1303
|
+
assertExactObjectKeys(parsed, ["kind", "terminal"], `candidate execution pending record at ${path}`);
|
|
1252
1304
|
const terminal = sealTerminalRecordValue(
|
|
1253
1305
|
requireObject2(record.terminal, path, "terminal"),
|
|
1254
1306
|
`candidate execution pending record at ${path}`
|
|
@@ -1398,6 +1450,8 @@ function candidateTerminalWindowMs(cleanupTimeoutMs) {
|
|
|
1398
1450
|
|
|
1399
1451
|
// src/candidate-execution/prepared-state.ts
|
|
1400
1452
|
import {
|
|
1453
|
+
agentCandidateBenchmarkSuiteSchema,
|
|
1454
|
+
agentCandidateBenchmarkTaskSchema,
|
|
1401
1455
|
agentCandidateExecutionPlanEvidenceSchema,
|
|
1402
1456
|
agentCandidateMaterializationReceiptSchema,
|
|
1403
1457
|
agentCandidateProfilePlanEvidenceSchema
|
|
@@ -1466,7 +1520,6 @@ async function readMaterializedWorkspaceFiles(root, expected, options = {}) {
|
|
|
1466
1520
|
}
|
|
1467
1521
|
function candidateWorkspaceManifest(files) {
|
|
1468
1522
|
return {
|
|
1469
|
-
schemaVersion: 2,
|
|
1470
1523
|
kind: "agent-candidate-workspace-manifest",
|
|
1471
1524
|
files: files.map((file) => ({
|
|
1472
1525
|
path: file.path,
|
|
@@ -1936,14 +1989,6 @@ function isNoEntry(error) {
|
|
|
1936
1989
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
1937
1990
|
}
|
|
1938
1991
|
|
|
1939
|
-
// src/candidate-execution/workspace-task.ts
|
|
1940
|
-
function workspaceTaskRepository(task) {
|
|
1941
|
-
if (task.outcome.kind !== "workspace" || !task.repository) {
|
|
1942
|
-
throw new Error("candidate runtime requires a workspace outcome with repository provenance");
|
|
1943
|
-
}
|
|
1944
|
-
return task.repository;
|
|
1945
|
-
}
|
|
1946
|
-
|
|
1947
1992
|
// src/candidate-execution/prepared-state.ts
|
|
1948
1993
|
var stateByExecution = /* @__PURE__ */ new WeakMap();
|
|
1949
1994
|
var lifecycleByExecution = /* @__PURE__ */ new WeakMap();
|
|
@@ -1952,9 +1997,11 @@ function createPreparedCandidateExecution(input) {
|
|
|
1952
1997
|
assertPrivateCandidateIntegrity(state);
|
|
1953
1998
|
const prepared = Object.freeze({
|
|
1954
1999
|
bundle: state.bundle,
|
|
2000
|
+
benchmark: Object.freeze({ suite: state.benchmarkSuite, task: state.benchmarkTask }),
|
|
1955
2001
|
executionId: state.executionId,
|
|
1956
2002
|
roots: state.roots,
|
|
1957
2003
|
profilePlan: evidenceView(state.profilePlan),
|
|
2004
|
+
profileActivation: state.profileActivation,
|
|
1958
2005
|
executionPlan: evidenceView(state.executionPlan),
|
|
1959
2006
|
materializationReceipt: state.materializationReceipt,
|
|
1960
2007
|
launch: state.launch,
|
|
@@ -2007,8 +2054,9 @@ function beginPreparedCandidateRun(prepared, modelAccess, memoryAccess) {
|
|
|
2007
2054
|
const material = state.executionPlan.value.material;
|
|
2008
2055
|
const request = Object.freeze({
|
|
2009
2056
|
executionId: state.executionId,
|
|
2057
|
+
benchmark: preparedBenchmark(state),
|
|
2010
2058
|
inputs: Object.freeze({
|
|
2011
|
-
task: workspaceInputView(
|
|
2059
|
+
task: workspaceInputView(state.benchmarkTask.workspace, state.executorInputs.taskFiles),
|
|
2012
2060
|
...material.candidateWorkspace && state.executorInputs.candidateFiles ? {
|
|
2013
2061
|
candidate: workspaceInputView(
|
|
2014
2062
|
material.candidateWorkspace,
|
|
@@ -2023,6 +2071,7 @@ function beginPreparedCandidateRun(prepared, modelAccess, memoryAccess) {
|
|
|
2023
2071
|
}),
|
|
2024
2072
|
roots: state.roots.execution,
|
|
2025
2073
|
profilePlan: evidenceView(state.profilePlan),
|
|
2074
|
+
profileActivation: state.profileActivation,
|
|
2026
2075
|
executionPlan: evidenceView(state.executionPlan),
|
|
2027
2076
|
materializationReceipt: state.materializationReceipt,
|
|
2028
2077
|
launch: immutableCandidateValue({ ...state.launch, env: completeEnvironment }),
|
|
@@ -2036,6 +2085,9 @@ function beginPreparedCandidateRun(prepared, modelAccess, memoryAccess) {
|
|
|
2036
2085
|
});
|
|
2037
2086
|
return { state, request };
|
|
2038
2087
|
}
|
|
2088
|
+
function preparedBenchmark(state) {
|
|
2089
|
+
return Object.freeze({ suite: state.benchmarkSuite, task: state.benchmarkTask });
|
|
2090
|
+
}
|
|
2039
2091
|
function consumePreparedCandidateExecution(prepared, outcome) {
|
|
2040
2092
|
transitionLifecycle(
|
|
2041
2093
|
prepared,
|
|
@@ -2048,10 +2100,16 @@ function beginPreparedCandidateSettlement(prepared) {
|
|
|
2048
2100
|
}
|
|
2049
2101
|
async function assertPreparedCandidateWorkspaces(state) {
|
|
2050
2102
|
const plan = state.executionPlan.value.material;
|
|
2051
|
-
await verifyMaterializedWorkspace(
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2103
|
+
await verifyMaterializedWorkspace(
|
|
2104
|
+
state.roots.staging.taskRoot,
|
|
2105
|
+
state.benchmarkTask.workspace.material,
|
|
2106
|
+
{
|
|
2107
|
+
ignoredProtectedRootEntries: [".git", ".sidecar"]
|
|
2108
|
+
}
|
|
2109
|
+
);
|
|
2110
|
+
if (state.benchmarkTask.repository) {
|
|
2111
|
+
await verifyTaskCheckout(state.roots.staging.taskRoot, state.benchmarkTask.repository);
|
|
2112
|
+
}
|
|
2055
2113
|
await verifyMaterializedProfileWorkspace(
|
|
2056
2114
|
state.roots.staging.profileRoot,
|
|
2057
2115
|
state.profilePlan.value.material
|
|
@@ -2065,9 +2123,19 @@ async function assertPreparedCandidateWorkspaces(state) {
|
|
|
2065
2123
|
}
|
|
2066
2124
|
}
|
|
2067
2125
|
function detachPreparedCandidateState(input) {
|
|
2126
|
+
const benchmarkSuite = immutableCandidateValue(
|
|
2127
|
+
agentCandidateBenchmarkSuiteSchema.parse(input.benchmarkSuite)
|
|
2128
|
+
);
|
|
2129
|
+
const benchmarkTask = immutableCandidateValue(
|
|
2130
|
+
agentCandidateBenchmarkTaskSchema.parse(input.benchmarkTask)
|
|
2131
|
+
);
|
|
2068
2132
|
const profilePlan = immutableCandidateValue(
|
|
2069
2133
|
agentCandidateProfilePlanEvidenceSchema.parse(input.profilePlan.value)
|
|
2070
2134
|
);
|
|
2135
|
+
const profileActivation = parseAgentCandidateProfileActivation(
|
|
2136
|
+
input.profileActivation,
|
|
2137
|
+
profilePlan.digest
|
|
2138
|
+
);
|
|
2071
2139
|
const executionPlan = immutableCandidateValue(
|
|
2072
2140
|
agentCandidateExecutionPlanEvidenceSchema.parse(input.executionPlan.value)
|
|
2073
2141
|
);
|
|
@@ -2083,6 +2151,8 @@ function detachPreparedCandidateState(input) {
|
|
|
2083
2151
|
return Object.freeze({
|
|
2084
2152
|
ports: input.ports,
|
|
2085
2153
|
bundle: input.bundle,
|
|
2154
|
+
benchmarkSuite,
|
|
2155
|
+
benchmarkTask,
|
|
2086
2156
|
executionId: input.executionId,
|
|
2087
2157
|
roots: immutableCandidateValue(input.roots),
|
|
2088
2158
|
profilePlan: Object.freeze({
|
|
@@ -2090,6 +2160,7 @@ function detachPreparedCandidateState(input) {
|
|
|
2090
2160
|
bytes: Uint8Array.from(input.profilePlan.bytes),
|
|
2091
2161
|
written: Object.freeze([...input.profilePlan.written])
|
|
2092
2162
|
}),
|
|
2163
|
+
profileActivation,
|
|
2093
2164
|
executionPlan: Object.freeze({
|
|
2094
2165
|
value: executionPlan,
|
|
2095
2166
|
bytes: Uint8Array.from(input.executionPlan.bytes)
|
|
@@ -2109,11 +2180,7 @@ function detachPreparedCandidateState(input) {
|
|
|
2109
2180
|
executorInputs: Object.freeze({
|
|
2110
2181
|
taskFiles: immutableExecutorFiles(input.executorInputs.taskFiles),
|
|
2111
2182
|
...input.executorInputs.candidateFiles ? { candidateFiles: immutableExecutorFiles(input.executorInputs.candidateFiles) } : {},
|
|
2112
|
-
profileFiles:
|
|
2113
|
-
input.executorInputs.profileFiles.map(
|
|
2114
|
-
(file) => Object.freeze({ ...file, bytes: Uint8Array.from(file.bytes) })
|
|
2115
|
-
)
|
|
2116
|
-
)
|
|
2183
|
+
profileFiles: immutableExecutorFiles(input.executorInputs.profileFiles)
|
|
2117
2184
|
}),
|
|
2118
2185
|
...input.memoryReservation ? { memoryReservation: immutableCandidateValue(input.memoryReservation) } : {},
|
|
2119
2186
|
...input.knowledge ? {
|
|
@@ -2134,6 +2201,7 @@ function assertPrivateCandidateIntegrity(state) {
|
|
|
2134
2201
|
throw new Error("prepared candidate bundle no longer matches its digest");
|
|
2135
2202
|
}
|
|
2136
2203
|
assertPlanEvidence(state.profilePlan.value, state.profilePlan.bytes, "profile plan");
|
|
2204
|
+
parseAgentCandidateProfileActivation(state.profileActivation, state.profilePlan.value.digest);
|
|
2137
2205
|
assertPlanEvidence(state.executionPlan.value, state.executionPlan.bytes, "execution plan");
|
|
2138
2206
|
agentCandidateExecutionPlanEvidenceSchema.parse(state.executionPlan.value);
|
|
2139
2207
|
const receipt = agentCandidateMaterializationReceiptSchema.parse(
|
|
@@ -2143,11 +2211,12 @@ function assertPrivateCandidateIntegrity(state) {
|
|
|
2143
2211
|
if (canonicalCandidateDigest(omitTopLevelDigest(receipt)) !== state.materializationReceipt.digest || !Buffer.from(receiptBytes).equals(Buffer.from(state.materializationReceipt.bytes))) {
|
|
2144
2212
|
throw new Error("prepared materialization receipt no longer matches its canonical bytes");
|
|
2145
2213
|
}
|
|
2146
|
-
|
|
2147
|
-
|
|
2214
|
+
assertSignedBenchmarkInput(state);
|
|
2215
|
+
const instruction = Buffer.from(state.benchmarkTask.instruction, "utf8");
|
|
2216
|
+
if (!Buffer.from(state.instruction.bytes).equals(instruction) || JSON.stringify(state.instruction.delivery) !== JSON.stringify(state.executionPlan.value.material.instructionDelivery)) {
|
|
2148
2217
|
throw new Error("prepared instruction no longer matches the signed execution plan");
|
|
2149
2218
|
}
|
|
2150
|
-
if (!/^candidate-preparation
|
|
2219
|
+
if (!/^candidate-preparation\.[A-Za-z0-9_-]{43}$/.test(state.preparationId) || !Number.isSafeInteger(state.reservationExpiresAtMs) || state.reservationExpiresAtMs <= 0 || !Number.isSafeInteger(state.cleanupTimeoutMs) || state.cleanupTimeoutMs <= 0 || !Number.isSafeInteger(state.resultTimeoutMs) || state.resultTimeoutMs <= 0 || JSON.stringify(state.resolvedModel) !== JSON.stringify(state.executionPlan.value.material.model.resolved) || state.modelReservation.digest !== state.executionPlan.value.material.model.access.grantDigest || state.modelReservation.preparationId !== state.preparationId || state.modelReservation.expiresAtMs !== state.reservationExpiresAtMs || canonicalCandidateDigest(state.modelReservation.network) !== canonicalCandidateDigest(state.executionPlan.value.material.model.access.network) || canonicalCandidateDigest(state.modelReservation.enforcedLimits) !== canonicalCandidateDigest(modelLimits(state.executionPlan.value.material.limits))) {
|
|
2151
2220
|
throw new Error("prepared model access no longer matches the signed execution plan");
|
|
2152
2221
|
}
|
|
2153
2222
|
assertExecutorInputs(state);
|
|
@@ -2175,7 +2244,7 @@ function assertPrivateCandidateIntegrity(state) {
|
|
|
2175
2244
|
[CANDIDATE_TRACE_ENV.traceRunId]: state.trace.runId
|
|
2176
2245
|
};
|
|
2177
2246
|
if (!state.trace.runId.startsWith(
|
|
2178
|
-
`${state.executionId}:attempt-${state.executionPlan.value.material.attempt
|
|
2247
|
+
`${state.executionId}:attempt-${state.executionPlan.value.material.runCell.attempt}:`
|
|
2179
2248
|
) || canonicalCandidateDigest(state.trace.tags) !== canonicalCandidateDigest(expectedTags) || canonicalCandidateDigest(state.trace.env) !== canonicalCandidateDigest(expectedTraceEnvironment)) {
|
|
2180
2249
|
throw new Error("prepared trace identity no longer matches the signed execution");
|
|
2181
2250
|
}
|
|
@@ -2220,7 +2289,7 @@ function knowledgeView(knowledge) {
|
|
|
2220
2289
|
function workspaceInputView(snapshot, sourceFiles) {
|
|
2221
2290
|
return Object.freeze({
|
|
2222
2291
|
snapshot,
|
|
2223
|
-
files: Object.freeze(sourceFiles.map((file) =>
|
|
2292
|
+
files: Object.freeze(sourceFiles.map((file) => executorFileView(file)))
|
|
2224
2293
|
});
|
|
2225
2294
|
}
|
|
2226
2295
|
function profileFileView(source) {
|
|
@@ -2233,9 +2302,22 @@ function profileFileView(source) {
|
|
|
2233
2302
|
}
|
|
2234
2303
|
});
|
|
2235
2304
|
}
|
|
2305
|
+
function executorFileView(source) {
|
|
2306
|
+
const bytes = Uint8Array.from(source.bytes);
|
|
2307
|
+
return Object.freeze({
|
|
2308
|
+
path: source.path,
|
|
2309
|
+
mode: source.mode,
|
|
2310
|
+
get bytes() {
|
|
2311
|
+
return Uint8Array.from(bytes);
|
|
2312
|
+
}
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2236
2315
|
function assertExecutorInputs(state) {
|
|
2237
2316
|
const material = state.executionPlan.value.material;
|
|
2238
|
-
assertWorkspaceExecutorFiles(
|
|
2317
|
+
assertWorkspaceExecutorFiles(
|
|
2318
|
+
state.executorInputs.taskFiles,
|
|
2319
|
+
state.benchmarkTask.workspace.material
|
|
2320
|
+
);
|
|
2239
2321
|
if (material.candidateWorkspace) {
|
|
2240
2322
|
if (!state.executorInputs.candidateFiles) {
|
|
2241
2323
|
throw new Error("prepared candidate executor files are missing");
|
|
@@ -2293,6 +2375,22 @@ function assertWorkspaceExecutorFiles(actualFiles, expected) {
|
|
|
2293
2375
|
}
|
|
2294
2376
|
}
|
|
2295
2377
|
}
|
|
2378
|
+
function assertSignedBenchmarkInput(state) {
|
|
2379
|
+
const plan = state.executionPlan.value.material;
|
|
2380
|
+
const cell = plan.runCell;
|
|
2381
|
+
const suite = state.benchmarkSuite;
|
|
2382
|
+
const task = state.benchmarkTask;
|
|
2383
|
+
const receipt = state.materializationReceipt.value;
|
|
2384
|
+
const cellIndex = cell.taskIndex * suite.reps + cell.repetition;
|
|
2385
|
+
if (canonicalCandidateDigest(omitTopLevelDigest(suite)) !== suite.digest || canonicalCandidateDigest(omitTopLevelDigest(task)) !== task.digest || canonicalCandidateDigest(omitTopLevelDigest(cell)) !== cell.digest || cell.bundleDigest !== state.bundle.digest || cell.suiteDigest !== suite.digest || cell.taskDigest !== task.digest || suite.taskDigests[cell.taskIndex] !== task.digest || suite.seeds[cellIndex] !== cell.seed || cell.repetition >= suite.reps || cell.attempt < 1 || cell.attempt > task.attempt.maxAttempts) {
|
|
2386
|
+
throw new Error("prepared candidate no longer matches its signed experiment cell");
|
|
2387
|
+
}
|
|
2388
|
+
const suiteBytes = canonicalCandidateBytes(omitTopLevelDigest(suite));
|
|
2389
|
+
const taskBytes = canonicalCandidateBytes(omitTopLevelDigest(task));
|
|
2390
|
+
if (receipt.benchmark.suite.digest !== suite.digest || receipt.benchmark.suite.material.sha256 !== sha256Bytes(suiteBytes) || receipt.benchmark.suite.material.byteLength !== suiteBytes.byteLength || receipt.benchmark.task.digest !== task.digest || receipt.benchmark.task.material.sha256 !== sha256Bytes(taskBytes) || receipt.benchmark.task.material.byteLength !== taskBytes.byteLength) {
|
|
2391
|
+
throw new Error("materialization receipt no longer matches its signed benchmark input");
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2296
2394
|
function immutableExecutorFiles(files) {
|
|
2297
2395
|
return Object.freeze(
|
|
2298
2396
|
files.map((file) => Object.freeze({ ...file, bytes: Uint8Array.from(file.bytes) }))
|
|
@@ -2330,10 +2428,14 @@ function assertProtectedEnvironment(state, modelEnvironment, memoryEnvironment)
|
|
|
2330
2428
|
}
|
|
2331
2429
|
|
|
2332
2430
|
// src/candidate-execution/claim-plan.ts
|
|
2333
|
-
function candidateExecutionClaim(prepared) {
|
|
2431
|
+
function candidateExecutionClaim(prepared, preparationEvidence) {
|
|
2334
2432
|
const state = assertPreparedCandidateIntegrity(prepared);
|
|
2335
2433
|
const material = prepared.executionPlan.value.material;
|
|
2336
|
-
const attempt =
|
|
2434
|
+
const attempt = {
|
|
2435
|
+
number: material.runCell.attempt,
|
|
2436
|
+
maxAttempts: state.benchmarkTask.attempt.maxAttempts,
|
|
2437
|
+
retryPolicy: state.benchmarkTask.attempt.retryPolicy
|
|
2438
|
+
};
|
|
2337
2439
|
const nowMs = Date.now();
|
|
2338
2440
|
if (!Number.isSafeInteger(nowMs) || nowMs < 0) {
|
|
2339
2441
|
throw new Error("candidate execution claim-store clock returned an invalid timestamp");
|
|
@@ -2351,6 +2453,14 @@ function candidateExecutionClaim(prepared) {
|
|
|
2351
2453
|
"candidate preparation expires before its full execution and cleanup owner window"
|
|
2352
2454
|
);
|
|
2353
2455
|
}
|
|
2456
|
+
if (preparationEvidence.executionPlan.sha256 !== prepared.executionPlan.value.digest || preparationEvidence.executionPlan.byteLength !== state.executionPlan.bytes.byteLength) {
|
|
2457
|
+
throw new Error("persisted execution plan does not match its canonical preparation bytes");
|
|
2458
|
+
}
|
|
2459
|
+
if (preparationEvidence.materializationReceipt.sha256 !== state.materializationReceipt.digest || preparationEvidence.materializationReceipt.byteLength !== state.materializationReceipt.bytes.byteLength) {
|
|
2460
|
+
throw new Error(
|
|
2461
|
+
"persisted materialization receipt does not match its canonical preparation bytes"
|
|
2462
|
+
);
|
|
2463
|
+
}
|
|
2354
2464
|
return candidateClaimFileInternals.sealClaim({
|
|
2355
2465
|
executionId: prepared.executionId,
|
|
2356
2466
|
attempt: attempt.number,
|
|
@@ -2358,6 +2468,7 @@ function candidateExecutionClaim(prepared) {
|
|
|
2358
2468
|
retryPolicy: attempt.retryPolicy,
|
|
2359
2469
|
bundleDigest: prepared.bundle.digest,
|
|
2360
2470
|
executionPlanDigest: prepared.executionPlan.value.digest,
|
|
2471
|
+
preparationEvidence,
|
|
2361
2472
|
retryLineageDigest: retryLineageDigest(prepared, state.resultTimeoutMs),
|
|
2362
2473
|
leaseExpiresAtMs,
|
|
2363
2474
|
resultTimeoutMs: state.resultTimeoutMs,
|
|
@@ -2382,7 +2493,11 @@ function retryLineageDigest(prepared, resultTimeoutMs) {
|
|
|
2382
2493
|
resultTimeoutMs,
|
|
2383
2494
|
executionPlan: {
|
|
2384
2495
|
...material,
|
|
2385
|
-
|
|
2496
|
+
runCell: {
|
|
2497
|
+
...material.runCell,
|
|
2498
|
+
attempt: 0,
|
|
2499
|
+
digest: `sha256:${"0".repeat(64)}`
|
|
2500
|
+
},
|
|
2386
2501
|
model: {
|
|
2387
2502
|
...material.model,
|
|
2388
2503
|
access: {
|
|
@@ -2418,13 +2533,13 @@ function retryLineageDigest(prepared, resultTimeoutMs) {
|
|
|
2418
2533
|
|
|
2419
2534
|
// src/candidate-execution/output-artifacts.ts
|
|
2420
2535
|
import {
|
|
2421
|
-
agentCandidateArtifactRefSchema as
|
|
2536
|
+
agentCandidateArtifactRefSchema as agentCandidateArtifactRefSchema3
|
|
2422
2537
|
} from "@tangle-network/agent-interface";
|
|
2423
2538
|
async function persistCandidateOutputArtifact(port, input) {
|
|
2424
2539
|
input.signal?.throwIfAborted();
|
|
2425
2540
|
const bytes = Uint8Array.from(input.bytes);
|
|
2426
2541
|
const expectedDigest = sha256Bytes(bytes);
|
|
2427
|
-
const ref =
|
|
2542
|
+
const ref = agentCandidateArtifactRefSchema3.parse(
|
|
2428
2543
|
await port.put({
|
|
2429
2544
|
executionId: input.executionId,
|
|
2430
2545
|
purpose: input.purpose,
|
|
@@ -2447,6 +2562,7 @@ import {
|
|
|
2447
2562
|
agentCandidateTerminationSchema,
|
|
2448
2563
|
agentCandidateWorkspaceManifestMaterialSchema
|
|
2449
2564
|
} from "@tangle-network/agent-interface";
|
|
2565
|
+
var sealedFinalCaptureBrand = /* @__PURE__ */ Symbol("sealedAgentCandidateExecutorFinalCapture");
|
|
2450
2566
|
function sealAgentCandidateProtectedRunCapture(value) {
|
|
2451
2567
|
const capture = requireRecord(value, "candidate execution capture");
|
|
2452
2568
|
assertExactObjectKeys(capture, ["executionId", "termination"], "candidate execution capture");
|
|
@@ -2458,31 +2574,32 @@ function sealAgentCandidateProtectedRunCapture(value) {
|
|
|
2458
2574
|
termination: Object.freeze(agentCandidateTerminationSchema.parse(capture.termination))
|
|
2459
2575
|
});
|
|
2460
2576
|
}
|
|
2461
|
-
function sealAgentCandidateExecutorFinalCapture(value) {
|
|
2577
|
+
function sealAgentCandidateExecutorFinalCapture(value, expectedOutcome) {
|
|
2462
2578
|
const capture = requireRecord(value, "candidate final capture");
|
|
2463
|
-
assertExactObjectKeys(capture, [
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2579
|
+
assertExactObjectKeys(capture, [], "candidate final capture", [
|
|
2580
|
+
"taskOutcome",
|
|
2581
|
+
"memoryAfter",
|
|
2582
|
+
"evidence"
|
|
2583
|
+
]);
|
|
2584
|
+
const taskOutcome = capture.taskOutcome ? sealTaskOutcomeCapture(capture.taskOutcome, expectedOutcome) : void 0;
|
|
2468
2585
|
const memoryAfter = capture.memoryAfter ? sealMemoryCapture(capture.memoryAfter) : void 0;
|
|
2586
|
+
if (capture.evidence !== void 0 && !(capture.evidence instanceof Uint8Array)) {
|
|
2587
|
+
throw new Error("candidate executor evidence must be a byte array");
|
|
2588
|
+
}
|
|
2589
|
+
const evidence = capture.evidence ? Uint8Array.from(capture.evidence) : void 0;
|
|
2469
2590
|
return Object.freeze({
|
|
2470
|
-
stopped: true,
|
|
2471
2591
|
...taskOutcome ? { taskOutcome } : {},
|
|
2472
|
-
...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {}
|
|
2592
|
+
...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {},
|
|
2593
|
+
...evidence ? { evidence } : {},
|
|
2594
|
+
[sealedFinalCaptureBrand]: true
|
|
2473
2595
|
});
|
|
2474
2596
|
}
|
|
2475
|
-
function
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
termination: input.termination,
|
|
2482
|
-
stopped: true,
|
|
2483
|
-
taskOutcome: input.taskOutcome,
|
|
2484
|
-
...input.memoryAfter ? { memoryAfter: input.memoryAfter } : {}
|
|
2485
|
-
});
|
|
2597
|
+
function sealAgentCandidateExecutorStopAcknowledgement(value) {
|
|
2598
|
+
const capture = requireRecord(value, "candidate stop acknowledgement");
|
|
2599
|
+
assertExactObjectKeys(capture, ["stopped"], "candidate stop acknowledgement");
|
|
2600
|
+
if (capture.stopped !== true) {
|
|
2601
|
+
throw new Error("candidate stop acknowledgement does not prove process death");
|
|
2602
|
+
}
|
|
2486
2603
|
}
|
|
2487
2604
|
function sealMemoryCapture(value) {
|
|
2488
2605
|
const capture = requireRecord(value, "candidate memory capture");
|
|
@@ -2497,13 +2614,32 @@ function sealMemoryCapture(value) {
|
|
|
2497
2614
|
archive: Uint8Array.from(capture.archive)
|
|
2498
2615
|
});
|
|
2499
2616
|
}
|
|
2500
|
-
function sealTaskOutcomeCapture(value) {
|
|
2617
|
+
function sealTaskOutcomeCapture(value, expected) {
|
|
2501
2618
|
const capture = requireRecord(value, "candidate task capture");
|
|
2619
|
+
if (capture.kind === "output") {
|
|
2620
|
+
assertExactObjectKeys(capture, ["kind", "bytes"], "candidate task output capture");
|
|
2621
|
+
if (expected.kind !== "output") {
|
|
2622
|
+
throw new Error("candidate task output capture does not match the signed outcome kind");
|
|
2623
|
+
}
|
|
2624
|
+
if (!(capture.bytes instanceof Uint8Array)) {
|
|
2625
|
+
throw new Error("candidate task output capture must contain a byte array");
|
|
2626
|
+
}
|
|
2627
|
+
if (capture.bytes.byteLength > expected.maxBytes) {
|
|
2628
|
+
throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
|
|
2629
|
+
}
|
|
2630
|
+
return Object.freeze({ kind: "output", bytes: Uint8Array.from(capture.bytes) });
|
|
2631
|
+
}
|
|
2502
2632
|
assertExactObjectKeys(
|
|
2503
2633
|
capture,
|
|
2504
|
-
["resultTree", "afterState", "archive", "gitDiff"],
|
|
2634
|
+
["kind", "resultTree", "afterState", "archive", "gitDiff"],
|
|
2505
2635
|
"candidate task capture"
|
|
2506
2636
|
);
|
|
2637
|
+
if (capture.kind !== "workspace") {
|
|
2638
|
+
throw new Error("candidate task capture has an invalid outcome kind");
|
|
2639
|
+
}
|
|
2640
|
+
if (expected.kind !== "workspace") {
|
|
2641
|
+
throw new Error("candidate workspace capture does not match the signed outcome kind");
|
|
2642
|
+
}
|
|
2507
2643
|
if (typeof capture.resultTree !== "string" || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(capture.resultTree)) {
|
|
2508
2644
|
throw new Error("candidate task capture resultTree is not a Git object id");
|
|
2509
2645
|
}
|
|
@@ -2512,6 +2648,7 @@ function sealTaskOutcomeCapture(value) {
|
|
|
2512
2648
|
}
|
|
2513
2649
|
const afterState = agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState);
|
|
2514
2650
|
return Object.freeze({
|
|
2651
|
+
kind: "workspace",
|
|
2515
2652
|
resultTree: capture.resultTree,
|
|
2516
2653
|
afterState: Object.freeze(afterState),
|
|
2517
2654
|
archive: Uint8Array.from(capture.archive),
|
|
@@ -2526,11 +2663,11 @@ function requireRecord(value, label) {
|
|
|
2526
2663
|
}
|
|
2527
2664
|
|
|
2528
2665
|
// src/candidate-execution/finalize.ts
|
|
2529
|
-
import { mkdtemp as mkdtemp2, rm as rm2 } from "fs/promises";
|
|
2530
|
-
import { tmpdir as tmpdir2 } from "os";
|
|
2531
|
-
import { join as join2 } from "path";
|
|
2532
2666
|
import { isLlmSpan as isLlmSpan2, REDACTION_VERSION as REDACTION_VERSION2 } from "@tangle-network/agent-eval";
|
|
2533
|
-
import {
|
|
2667
|
+
import {
|
|
2668
|
+
agentCandidateRunReceiptSchema,
|
|
2669
|
+
agentCandidateWorkspaceSnapshotEvidenceSchema
|
|
2670
|
+
} from "@tangle-network/agent-interface";
|
|
2534
2671
|
|
|
2535
2672
|
// src/candidate-execution/model-settlement.ts
|
|
2536
2673
|
import { isLlmSpan } from "@tangle-network/agent-eval";
|
|
@@ -2557,7 +2694,6 @@ function sealAgentCandidateModelSettlement(settlement, expected) {
|
|
|
2557
2694
|
let outputTokens = 0;
|
|
2558
2695
|
let cachedInputTokens = 0;
|
|
2559
2696
|
let reasoningTokens = 0;
|
|
2560
|
-
let hasCachedInput = false;
|
|
2561
2697
|
let costUsdNanos = 0;
|
|
2562
2698
|
const calls = settlement.calls.map((source, index) => {
|
|
2563
2699
|
assertExactObjectKeys(
|
|
@@ -2610,7 +2746,6 @@ function sealAgentCandidateModelSettlement(settlement, expected) {
|
|
|
2610
2746
|
source.cachedInputTokens,
|
|
2611
2747
|
"cached input token total"
|
|
2612
2748
|
);
|
|
2613
|
-
hasCachedInput = true;
|
|
2614
2749
|
assertCount2(source.reasoningTokens, `model settlement call ${index} reasoningTokens`);
|
|
2615
2750
|
reasoningTokens = safeAdd(reasoningTokens, source.reasoningTokens, "reasoning token total");
|
|
2616
2751
|
assertCount2(source.costUsdNanos, `model settlement call ${index} costUsdNanos`);
|
|
@@ -2620,13 +2755,6 @@ function sealAgentCandidateModelSettlement(settlement, expected) {
|
|
|
2620
2755
|
return Object.freeze({ ...source });
|
|
2621
2756
|
});
|
|
2622
2757
|
const usage = Object.freeze({
|
|
2623
|
-
costUsd: costUsdNanos / USD_NANOS,
|
|
2624
|
-
inputTokens,
|
|
2625
|
-
outputTokens,
|
|
2626
|
-
...hasCachedInput ? { cachedInputTokens } : {},
|
|
2627
|
-
modelCalls: calls.length
|
|
2628
|
-
});
|
|
2629
|
-
const fixedUsage = Object.freeze({
|
|
2630
2758
|
costUsdNanos,
|
|
2631
2759
|
inputTokens,
|
|
2632
2760
|
outputTokens,
|
|
@@ -2641,9 +2769,7 @@ function sealAgentCandidateModelSettlement(settlement, expected) {
|
|
|
2641
2769
|
closed: true,
|
|
2642
2770
|
calls: Object.freeze(calls)
|
|
2643
2771
|
}),
|
|
2644
|
-
usage
|
|
2645
|
-
fixedUsage,
|
|
2646
|
-
costUsdNanos
|
|
2772
|
+
usage
|
|
2647
2773
|
});
|
|
2648
2774
|
}
|
|
2649
2775
|
async function appendAuthoritativeModelSettlementSpans(traceStore, runId, settlement) {
|
|
@@ -2766,11 +2892,60 @@ function safeAdd(left, right, label) {
|
|
|
2766
2892
|
}
|
|
2767
2893
|
|
|
2768
2894
|
// src/candidate-execution/protected-redaction.ts
|
|
2895
|
+
import { createHmac, randomBytes as randomBytes2 } from "crypto";
|
|
2769
2896
|
import {
|
|
2770
2897
|
DEFAULT_REDACTION_RULES,
|
|
2771
2898
|
REDACTION_VERSION,
|
|
2772
2899
|
redactString
|
|
2773
2900
|
} from "@tangle-network/agent-eval";
|
|
2901
|
+
function createProtectedRecordRedactor(protectedValues) {
|
|
2902
|
+
const identityKey = randomBytes2(32);
|
|
2903
|
+
const aggregate = {
|
|
2904
|
+
version: REDACTION_VERSION,
|
|
2905
|
+
redactionCount: 0,
|
|
2906
|
+
byRule: {}
|
|
2907
|
+
};
|
|
2908
|
+
const mergeReport = (report) => {
|
|
2909
|
+
aggregate.version = report.version;
|
|
2910
|
+
aggregate.redactionCount += report.redactionCount;
|
|
2911
|
+
for (const [rule, count] of Object.entries(report.byRule)) {
|
|
2912
|
+
aggregate.byRule[rule] = (aggregate.byRule[rule] ?? 0) + count;
|
|
2913
|
+
}
|
|
2914
|
+
};
|
|
2915
|
+
const redactScalar = (value, record) => {
|
|
2916
|
+
const redacted = redactProtectedValue(value, protectedValues);
|
|
2917
|
+
if (record) mergeReport(redacted.report);
|
|
2918
|
+
return redacted.value;
|
|
2919
|
+
};
|
|
2920
|
+
const identifier = (value, record) => {
|
|
2921
|
+
const redacted = redactScalar(value, record);
|
|
2922
|
+
if (redacted === value) return value;
|
|
2923
|
+
const digest = createHmac("sha256", identityKey).update(value).digest("hex");
|
|
2924
|
+
return `${redacted}:hmac-sha256:${digest}`;
|
|
2925
|
+
};
|
|
2926
|
+
const transform = (value, record) => {
|
|
2927
|
+
const transformed = transformProtectedRecord(
|
|
2928
|
+
value,
|
|
2929
|
+
void 0,
|
|
2930
|
+
record,
|
|
2931
|
+
redactScalar,
|
|
2932
|
+
identifier
|
|
2933
|
+
);
|
|
2934
|
+
assertNoProtectedEvidence(transformed, protectedValues);
|
|
2935
|
+
return transformed;
|
|
2936
|
+
};
|
|
2937
|
+
return Object.freeze({
|
|
2938
|
+
record: (value) => transform(value, true),
|
|
2939
|
+
query: (value) => transform(value, false),
|
|
2940
|
+
identifier: (value) => identifier(value, false),
|
|
2941
|
+
traceIdentity: (trace) => transform(trace, false),
|
|
2942
|
+
report: () => ({
|
|
2943
|
+
version: aggregate.version,
|
|
2944
|
+
redactionCount: aggregate.redactionCount,
|
|
2945
|
+
byRule: { ...aggregate.byRule }
|
|
2946
|
+
})
|
|
2947
|
+
});
|
|
2948
|
+
}
|
|
2774
2949
|
function redactProtectedValue(value, protectedValues) {
|
|
2775
2950
|
const report = {
|
|
2776
2951
|
version: REDACTION_VERSION,
|
|
@@ -2858,6 +3033,65 @@ function redactNode(value, protectedValues, rules, report) {
|
|
|
2858
3033
|
}
|
|
2859
3034
|
return value;
|
|
2860
3035
|
}
|
|
3036
|
+
function transformProtectedRecord(value, fieldName, record, redactScalar, redactIdentifier) {
|
|
3037
|
+
if (value instanceof Uint8Array) return redactScalar(value, record);
|
|
3038
|
+
if (typeof value === "string") {
|
|
3039
|
+
return fieldName && isIdentifierFieldName(fieldName) ? redactIdentifier(value, record) : redactScalar(value, record);
|
|
3040
|
+
}
|
|
3041
|
+
if (Array.isArray(value)) {
|
|
3042
|
+
return value.map(
|
|
3043
|
+
(entry) => transformProtectedRecord(entry, fieldName, record, redactScalar, redactIdentifier)
|
|
3044
|
+
);
|
|
3045
|
+
}
|
|
3046
|
+
if (!value || typeof value !== "object") return value;
|
|
3047
|
+
if (fieldName === "tags") {
|
|
3048
|
+
return transformTagMap(value, record, redactScalar, redactIdentifier);
|
|
3049
|
+
}
|
|
3050
|
+
if (fieldName === "tag") {
|
|
3051
|
+
return transformTagFilter(value, record, redactScalar, redactIdentifier);
|
|
3052
|
+
}
|
|
3053
|
+
const entries = [];
|
|
3054
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
3055
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
3056
|
+
const redactedKey = redactScalar(key, record);
|
|
3057
|
+
if (seenKeys.has(redactedKey)) {
|
|
3058
|
+
throw new Error("protected evidence redaction produced an ambiguous object key");
|
|
3059
|
+
}
|
|
3060
|
+
seenKeys.add(redactedKey);
|
|
3061
|
+
entries.push([
|
|
3062
|
+
redactedKey,
|
|
3063
|
+
transformProtectedRecord(entry, key, record, redactScalar, redactIdentifier)
|
|
3064
|
+
]);
|
|
3065
|
+
}
|
|
3066
|
+
return Object.fromEntries(entries);
|
|
3067
|
+
}
|
|
3068
|
+
function transformTagMap(value, record, redactScalar, redactIdentifier) {
|
|
3069
|
+
const entries = [];
|
|
3070
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
3071
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
3072
|
+
const redactedKey = redactIdentifier(key, record);
|
|
3073
|
+
if (seenKeys.has(redactedKey)) {
|
|
3074
|
+
throw new Error("protected evidence redaction produced an ambiguous trace tag");
|
|
3075
|
+
}
|
|
3076
|
+
seenKeys.add(redactedKey);
|
|
3077
|
+
entries.push([
|
|
3078
|
+
redactedKey,
|
|
3079
|
+
typeof entry === "string" ? redactIdentifier(entry, record) : transformProtectedRecord(entry, key, record, redactScalar, redactIdentifier)
|
|
3080
|
+
]);
|
|
3081
|
+
}
|
|
3082
|
+
return Object.fromEntries(entries);
|
|
3083
|
+
}
|
|
3084
|
+
function transformTagFilter(value, record, redactScalar, redactIdentifier) {
|
|
3085
|
+
const output = {};
|
|
3086
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
3087
|
+
const redactedKey = redactScalar(key, record);
|
|
3088
|
+
output[redactedKey] = (key === "key" || key === "value") && typeof entry === "string" ? redactIdentifier(entry, record) : transformProtectedRecord(entry, key, record, redactScalar, redactIdentifier);
|
|
3089
|
+
}
|
|
3090
|
+
return output;
|
|
3091
|
+
}
|
|
3092
|
+
function isIdentifierFieldName(name) {
|
|
3093
|
+
return /ids?$/i.test(name);
|
|
3094
|
+
}
|
|
2861
3095
|
function protectedRedactionRules(protectedValues) {
|
|
2862
3096
|
const exactRules = protectedValueVariants(protectedValues).sort((left, right) => right.length - left.length || left.localeCompare(right)).map((value, index) => ({
|
|
2863
3097
|
id: `candidate-access-${index}`,
|
|
@@ -2904,75 +3138,24 @@ function escapeRegularExpression(value) {
|
|
|
2904
3138
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2905
3139
|
}
|
|
2906
3140
|
|
|
2907
|
-
// src/candidate-execution/workspace-snapshot.ts
|
|
2908
|
-
import {
|
|
2909
|
-
agentCandidateWorkspaceManifestMaterialSchema as agentCandidateWorkspaceManifestMaterialSchema2,
|
|
2910
|
-
agentCandidateWorkspaceSnapshotEvidenceSchema
|
|
2911
|
-
} from "@tangle-network/agent-interface";
|
|
2912
|
-
function provisionalCandidateWorkspaceSnapshot(materialInput, archive) {
|
|
2913
|
-
const material = immutableCandidateValue(
|
|
2914
|
-
agentCandidateWorkspaceManifestMaterialSchema2.parse(materialInput)
|
|
2915
|
-
);
|
|
2916
|
-
const manifestBytes = canonicalCandidateBytes(material);
|
|
2917
|
-
const snapshot = Object.freeze({
|
|
2918
|
-
schemaVersion: 2,
|
|
2919
|
-
kind: "agent-candidate-workspace-snapshot",
|
|
2920
|
-
digest: sha256Bytes(manifestBytes),
|
|
2921
|
-
material,
|
|
2922
|
-
manifest: Object.freeze(embeddedCandidateArtifact(manifestBytes)),
|
|
2923
|
-
archive: Object.freeze(embeddedCandidateArtifact(archive))
|
|
2924
|
-
});
|
|
2925
|
-
return Object.freeze({ material, manifestBytes, snapshot });
|
|
2926
|
-
}
|
|
2927
|
-
async function persistCandidateWorkspaceSnapshot(port, input) {
|
|
2928
|
-
input.signal?.throwIfAborted();
|
|
2929
|
-
const material = immutableCandidateValue(input.material);
|
|
2930
|
-
const manifestBytes = canonicalCandidateBytes(material);
|
|
2931
|
-
const [manifest, archive] = await Promise.all([
|
|
2932
|
-
persistCandidateOutputArtifact(port, {
|
|
2933
|
-
executionId: input.executionId,
|
|
2934
|
-
purpose: input.purpose === "task" ? "task-manifest" : "memory-after-manifest",
|
|
2935
|
-
bytes: manifestBytes,
|
|
2936
|
-
...input.signal ? { signal: input.signal } : {}
|
|
2937
|
-
}),
|
|
2938
|
-
persistCandidateOutputArtifact(port, {
|
|
2939
|
-
executionId: input.executionId,
|
|
2940
|
-
purpose: input.purpose === "task" ? "task-archive" : "memory-after-archive",
|
|
2941
|
-
bytes: input.archive,
|
|
2942
|
-
...input.signal ? { signal: input.signal } : {}
|
|
2943
|
-
})
|
|
2944
|
-
]);
|
|
2945
|
-
return immutableCandidateValue(
|
|
2946
|
-
agentCandidateWorkspaceSnapshotEvidenceSchema.parse({
|
|
2947
|
-
schemaVersion: 2,
|
|
2948
|
-
kind: "agent-candidate-workspace-snapshot",
|
|
2949
|
-
digest: sha256Bytes(manifestBytes),
|
|
2950
|
-
material,
|
|
2951
|
-
manifest,
|
|
2952
|
-
archive
|
|
2953
|
-
})
|
|
2954
|
-
);
|
|
2955
|
-
}
|
|
2956
|
-
|
|
2957
3141
|
// src/candidate-execution/finalize.ts
|
|
2958
|
-
async function finalizeAgentCandidateRun(state, capture, traceStore, settlement, evidence, protectedValues, writeRedactionReport, signal) {
|
|
3142
|
+
async function finalizeAgentCandidateRun(state, capture, traceStore, traceIdentity, settlement, evidence, protectedValues, writeRedactionReport, signal) {
|
|
2959
3143
|
let termination;
|
|
2960
3144
|
try {
|
|
2961
3145
|
signal?.throwIfAborted();
|
|
2962
|
-
|
|
2963
|
-
if (protectedCapture.executionId !== state.executionId) {
|
|
3146
|
+
if (capture.executionId !== state.executionId) {
|
|
2964
3147
|
throw new Error("protected capture execution id does not match the prepared execution");
|
|
2965
3148
|
}
|
|
2966
|
-
termination =
|
|
3149
|
+
termination = capture.termination;
|
|
2967
3150
|
if (termination.kind === "timeout" && termination.timeoutMs !== state.executionPlan.value.material.limits.timeoutMs) {
|
|
2968
3151
|
throw new Error("timeout termination does not match the frozen execution limit");
|
|
2969
3152
|
}
|
|
2970
|
-
const run = await traceStore.getRun(
|
|
2971
|
-
if (!run) throw new Error(`protected trace run is missing: ${
|
|
3153
|
+
const run = await traceStore.getRun(traceIdentity.runId);
|
|
3154
|
+
if (!run) throw new Error(`protected trace run is missing: ${traceIdentity.runId}`);
|
|
2972
3155
|
if (run.status === "running" || run.endedAt === void 0) {
|
|
2973
3156
|
throw new Error("protected trace run is not terminal");
|
|
2974
3157
|
}
|
|
2975
|
-
assertTraceBindings(run.tags,
|
|
3158
|
+
assertTraceBindings(run.tags, traceIdentity.tags);
|
|
2976
3159
|
const [spans, events, budget, artifacts] = await Promise.all([
|
|
2977
3160
|
traceStore.spans({ runId: run.runId }),
|
|
2978
3161
|
traceStore.events({ runId: run.runId }),
|
|
@@ -2994,31 +3177,14 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
|
|
|
2994
3177
|
const modelSpans = orderedSpans.filter(isLlmSpan2);
|
|
2995
3178
|
assertTraceMatchesModelSettlement(modelSpans, settlement);
|
|
2996
3179
|
enforceLimits(state, run.startedAt, run.endedAt, orderedSpans, settlement);
|
|
2997
|
-
const finalCapture = sealAgentCandidateExecutorFinalCapture(evidence.finalCapture);
|
|
2998
3180
|
const memory = await memoryReceipt(
|
|
2999
3181
|
state,
|
|
3000
|
-
finalCapture,
|
|
3001
|
-
evidence.
|
|
3002
|
-
protectedValues,
|
|
3182
|
+
evidence.finalCapture,
|
|
3183
|
+
evidence.persistedCapture.memoryAfter,
|
|
3003
3184
|
signal
|
|
3004
3185
|
);
|
|
3005
|
-
const executorCaptureBytes = encodeAgentCandidateExecutorCapture({
|
|
3006
|
-
executionId: protectedCapture.executionId,
|
|
3007
|
-
executionPlanDigest: state.executionPlan.value.digest,
|
|
3008
|
-
termination: protectedCapture.termination,
|
|
3009
|
-
taskOutcome: evidence.taskOutcome.evidence,
|
|
3010
|
-
...memory.mode === "isolated" ? { memoryAfter: memory.afterState } : {}
|
|
3011
|
-
});
|
|
3012
|
-
assertNoProtectedBytes(executorCaptureBytes, protectedValues);
|
|
3013
|
-
const executorCapture = await persistCandidateOutputArtifact(evidence.outputArtifacts, {
|
|
3014
|
-
executionId: state.executionId,
|
|
3015
|
-
purpose: "executor-capture",
|
|
3016
|
-
bytes: executorCaptureBytes,
|
|
3017
|
-
signal
|
|
3018
|
-
});
|
|
3019
3186
|
const redacted = redactProtectedValue(
|
|
3020
3187
|
{
|
|
3021
|
-
schemaVersion: 1,
|
|
3022
3188
|
run: { ...run, redactionVersion: REDACTION_VERSION2 },
|
|
3023
3189
|
spans: orderedSpans,
|
|
3024
3190
|
events: orderedEvents,
|
|
@@ -3049,22 +3215,26 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
|
|
|
3049
3215
|
signal
|
|
3050
3216
|
});
|
|
3051
3217
|
const trace = {
|
|
3052
|
-
schemaVersion: 1,
|
|
3053
3218
|
artifact: traceArtifact,
|
|
3054
3219
|
eventCount: 1 + orderedSpans.length + orderedEvents.length + orderedBudget.length + orderedArtifacts.length,
|
|
3055
3220
|
modelCallCount: modelSpans.length
|
|
3056
3221
|
};
|
|
3057
3222
|
const document = canonicalCandidateDocument({
|
|
3058
|
-
schemaVersion: 3,
|
|
3059
3223
|
kind: "agent-candidate-run",
|
|
3060
3224
|
digestAlgorithm: "rfc8785-sha256",
|
|
3061
3225
|
bundleDigest: state.bundle.digest,
|
|
3226
|
+
runCellDigest: state.executionPlan.value.material.runCell.digest,
|
|
3062
3227
|
materializationReceiptDigest: state.materializationReceipt.digest,
|
|
3063
3228
|
executionPlanDigest: state.executionPlan.value.digest,
|
|
3229
|
+
timing: {
|
|
3230
|
+
startedAtMs: run.startedAt,
|
|
3231
|
+
endedAtMs: run.endedAt,
|
|
3232
|
+
durationMs: run.endedAt - run.startedAt
|
|
3233
|
+
},
|
|
3064
3234
|
memory,
|
|
3065
3235
|
trace,
|
|
3066
3236
|
termination,
|
|
3067
|
-
executorCapture,
|
|
3237
|
+
executorCapture: evidence.persistedCapture.evidence,
|
|
3068
3238
|
modelSettlement: evidence.modelSettlement,
|
|
3069
3239
|
taskOutcome: evidence.taskOutcome.evidence,
|
|
3070
3240
|
benchmarkResult: evidence.benchmarkResult
|
|
@@ -3080,8 +3250,8 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
|
|
|
3080
3250
|
succeeded: true,
|
|
3081
3251
|
receipt: document,
|
|
3082
3252
|
artifacts: {
|
|
3083
|
-
executorCapture,
|
|
3084
3253
|
modelSettlement: evidence.modelSettlement.artifact,
|
|
3254
|
+
executorCapture: evidence.persistedCapture.evidence,
|
|
3085
3255
|
taskOutcome: evidence.taskOutcome.evidence.artifact,
|
|
3086
3256
|
benchmarkResult: evidence.benchmarkResult.artifact,
|
|
3087
3257
|
runReceipt
|
|
@@ -3101,8 +3271,7 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
|
|
|
3101
3271
|
};
|
|
3102
3272
|
}
|
|
3103
3273
|
}
|
|
3104
|
-
function assertTraceBindings(tags,
|
|
3105
|
-
const expected = state.trace.tags;
|
|
3274
|
+
function assertTraceBindings(tags, expected) {
|
|
3106
3275
|
for (const name of Object.values(CANDIDATE_TRACE_TAGS)) {
|
|
3107
3276
|
if (tags?.[name] !== expected[name]) {
|
|
3108
3277
|
throw new Error(`protected trace is not bound to prepared execution tag ${name}`);
|
|
@@ -3126,45 +3295,30 @@ function enforceLimits(state, startedAt, endedAt, spans, settlement) {
|
|
|
3126
3295
|
for (const [actual, limit, label] of checks) {
|
|
3127
3296
|
if (actual > limit) throw new Error(`protected ${label} ${actual} exceeds ${limit}`);
|
|
3128
3297
|
}
|
|
3129
|
-
if (
|
|
3130
|
-
throw new Error(
|
|
3298
|
+
if (usage.costUsdNanos > usdToNanos(limits.maxCostUsd, "frozen maxCostUsd")) {
|
|
3299
|
+
throw new Error(
|
|
3300
|
+
`protected cost USD ${usage.costUsdNanos / 1e9} exceeds ${limits.maxCostUsd}`
|
|
3301
|
+
);
|
|
3131
3302
|
}
|
|
3132
3303
|
}
|
|
3133
|
-
async function memoryReceipt(state, capture,
|
|
3304
|
+
async function memoryReceipt(state, capture, persisted, signal) {
|
|
3134
3305
|
signal?.throwIfAborted();
|
|
3135
3306
|
if (state.memory.mode === "disabled") {
|
|
3136
|
-
if (capture.memoryAfter !== void 0) {
|
|
3307
|
+
if (capture.memoryAfter !== void 0 || persisted !== void 0) {
|
|
3137
3308
|
throw new Error("disabled memory cannot return an after-state");
|
|
3138
3309
|
}
|
|
3139
3310
|
return { mode: "disabled" };
|
|
3140
3311
|
}
|
|
3141
3312
|
if (!capture.memoryAfter) throw new Error("isolated memory is missing its protected after-state");
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
const
|
|
3145
|
-
const
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
role: "memory",
|
|
3152
|
-
snapshot: provisional.snapshot,
|
|
3153
|
-
archive: Uint8Array.from(archive),
|
|
3154
|
-
destination: root
|
|
3155
|
-
});
|
|
3156
|
-
const files = await readMaterializedWorkspaceFiles(root, afterState);
|
|
3157
|
-
for (const file of files) assertNoProtectedBytes(file.bytes, protectedValues);
|
|
3158
|
-
signal?.throwIfAborted();
|
|
3159
|
-
} finally {
|
|
3160
|
-
await rm2(root, { recursive: true, force: true });
|
|
3161
|
-
}
|
|
3162
|
-
const snapshot = await persistCandidateWorkspaceSnapshot(outputArtifacts, {
|
|
3163
|
-
executionId: state.executionId,
|
|
3164
|
-
material: afterState,
|
|
3165
|
-
archive,
|
|
3166
|
-
purpose: "memory-after",
|
|
3167
|
-
signal
|
|
3313
|
+
if (!persisted) throw new Error("isolated memory is missing persisted capture evidence");
|
|
3314
|
+
const afterState = capture.memoryAfter.afterState;
|
|
3315
|
+
const manifestBytes = canonicalCandidateBytes(afterState);
|
|
3316
|
+
const snapshot = agentCandidateWorkspaceSnapshotEvidenceSchema.parse({
|
|
3317
|
+
kind: "agent-candidate-workspace-snapshot",
|
|
3318
|
+
digest: sha256Bytes(manifestBytes),
|
|
3319
|
+
material: afterState,
|
|
3320
|
+
manifest: persisted.manifest,
|
|
3321
|
+
archive: persisted.archive
|
|
3168
3322
|
});
|
|
3169
3323
|
return {
|
|
3170
3324
|
mode: "isolated",
|
|
@@ -3194,19 +3348,20 @@ function compareStrings(a, b) {
|
|
|
3194
3348
|
}
|
|
3195
3349
|
|
|
3196
3350
|
// src/candidate-execution/outcome-evidence.ts
|
|
3197
|
-
import { mkdtemp as
|
|
3198
|
-
import { tmpdir as
|
|
3199
|
-
import { join as
|
|
3351
|
+
import { mkdtemp as mkdtemp2, rm as rm2 } from "fs/promises";
|
|
3352
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
3353
|
+
import { join as join2 } from "path";
|
|
3200
3354
|
import {
|
|
3201
3355
|
agentCandidateBenchmarkResultEvidenceSchema,
|
|
3202
3356
|
agentCandidateModelSettlementEvidenceSchema,
|
|
3203
|
-
agentCandidateTaskOutcomeEvidenceSchema
|
|
3357
|
+
agentCandidateTaskOutcomeEvidenceSchema,
|
|
3358
|
+
agentCandidateWorkspaceSnapshotEvidenceSchema as agentCandidateWorkspaceSnapshotEvidenceSchema2
|
|
3204
3359
|
} from "@tangle-network/agent-interface";
|
|
3205
3360
|
|
|
3206
3361
|
// src/candidate-execution/benchmark-grader.ts
|
|
3207
3362
|
async function runBoundCandidateBenchmarkGrader(input) {
|
|
3208
3363
|
input.signal?.throwIfAborted();
|
|
3209
|
-
const descriptor = snapshotGraderDescriptor(input.grader);
|
|
3364
|
+
const descriptor = snapshotGraderDescriptor(input.grader, input.expectedGrader);
|
|
3210
3365
|
const implementationBytes = await readVerifiedArtifact(descriptor.artifact, input.artifacts);
|
|
3211
3366
|
if (implementationBytes.byteLength === 0) {
|
|
3212
3367
|
throw new Error("candidate benchmark grader implementation cannot be empty");
|
|
@@ -3214,6 +3369,7 @@ async function runBoundCandidateBenchmarkGrader(input) {
|
|
|
3214
3369
|
const expectedImplementationDigest = sha256Bytes(implementationBytes);
|
|
3215
3370
|
const termination = immutableCandidateValue(input.termination);
|
|
3216
3371
|
const run = input.grader.run;
|
|
3372
|
+
const startedAtMs = Date.now();
|
|
3217
3373
|
const result = await run(
|
|
3218
3374
|
Object.freeze({
|
|
3219
3375
|
executionId: input.executionId,
|
|
@@ -3223,6 +3379,7 @@ async function runBoundCandidateBenchmarkGrader(input) {
|
|
|
3223
3379
|
signal: input.signal ?? new AbortController().signal
|
|
3224
3380
|
})
|
|
3225
3381
|
);
|
|
3382
|
+
const endedAtMs = Math.max(startedAtMs, Date.now());
|
|
3226
3383
|
input.signal?.throwIfAborted();
|
|
3227
3384
|
assertExactRunnerResult(result);
|
|
3228
3385
|
const evidence = Uint8Array.from(result.evidence);
|
|
@@ -3242,19 +3399,42 @@ async function runBoundCandidateBenchmarkGrader(input) {
|
|
|
3242
3399
|
}
|
|
3243
3400
|
return Object.freeze({
|
|
3244
3401
|
grader: descriptor,
|
|
3402
|
+
grading: immutableCandidateValue({
|
|
3403
|
+
usage: emptyFixedSpend(),
|
|
3404
|
+
timing: {
|
|
3405
|
+
startedAtMs,
|
|
3406
|
+
endedAtMs,
|
|
3407
|
+
durationMs: endedAtMs - startedAtMs
|
|
3408
|
+
}
|
|
3409
|
+
}),
|
|
3245
3410
|
evaluation: result.evaluation,
|
|
3246
3411
|
evidence
|
|
3247
3412
|
});
|
|
3248
3413
|
}
|
|
3249
|
-
function snapshotGraderDescriptor(grader) {
|
|
3414
|
+
function snapshotGraderDescriptor(grader, expected) {
|
|
3250
3415
|
if (!grader.name || !grader.version) {
|
|
3251
3416
|
throw new Error("candidate benchmark grader name and version must be non-empty");
|
|
3252
3417
|
}
|
|
3253
|
-
|
|
3418
|
+
const actual = {
|
|
3254
3419
|
name: grader.name,
|
|
3255
3420
|
version: grader.version,
|
|
3421
|
+
format: "tangle-grader",
|
|
3256
3422
|
artifact: grader.artifact
|
|
3257
|
-
}
|
|
3423
|
+
};
|
|
3424
|
+
if (canonicalCandidateDigest(actual) !== canonicalCandidateDigest(expected)) {
|
|
3425
|
+
throw new Error("candidate benchmark grader does not match the signed task grader");
|
|
3426
|
+
}
|
|
3427
|
+
return immutableCandidateValue(expected);
|
|
3428
|
+
}
|
|
3429
|
+
function emptyFixedSpend() {
|
|
3430
|
+
return {
|
|
3431
|
+
inputTokens: 0,
|
|
3432
|
+
outputTokens: 0,
|
|
3433
|
+
cachedInputTokens: 0,
|
|
3434
|
+
reasoningTokens: 0,
|
|
3435
|
+
modelCalls: 0,
|
|
3436
|
+
costUsdNanos: 0
|
|
3437
|
+
};
|
|
3258
3438
|
}
|
|
3259
3439
|
function detachedImplementation(bytes) {
|
|
3260
3440
|
const stored = Uint8Array.from(bytes);
|
|
@@ -3286,6 +3466,104 @@ function assertExactRunnerResult(value) {
|
|
|
3286
3466
|
}
|
|
3287
3467
|
}
|
|
3288
3468
|
|
|
3469
|
+
// src/candidate-execution/executor-capture-evidence.ts
|
|
3470
|
+
async function persistAgentCandidateExecutorCapture(identity, expected, capture, outputArtifacts, signal) {
|
|
3471
|
+
const executorEvidence = capture.evidence ? await persistCandidateOutputArtifact(outputArtifacts, {
|
|
3472
|
+
executionId: identity.executionId,
|
|
3473
|
+
purpose: "executor-native-evidence",
|
|
3474
|
+
bytes: capture.evidence,
|
|
3475
|
+
signal
|
|
3476
|
+
}) : void 0;
|
|
3477
|
+
const taskOutcome = capture.taskOutcome ? await persistTaskCapture(
|
|
3478
|
+
identity.executionId,
|
|
3479
|
+
expected,
|
|
3480
|
+
capture.taskOutcome,
|
|
3481
|
+
outputArtifacts,
|
|
3482
|
+
signal
|
|
3483
|
+
) : void 0;
|
|
3484
|
+
const memoryAfter = capture.memoryAfter ? await persistWorkspaceCapture(
|
|
3485
|
+
identity.executionId,
|
|
3486
|
+
"memory-after-manifest",
|
|
3487
|
+
"memory-after-archive",
|
|
3488
|
+
capture.memoryAfter.afterState,
|
|
3489
|
+
capture.memoryAfter.archive,
|
|
3490
|
+
outputArtifacts,
|
|
3491
|
+
signal
|
|
3492
|
+
) : void 0;
|
|
3493
|
+
const bytes = canonicalCandidateBytes({
|
|
3494
|
+
kind: "agent-candidate-executor-capture",
|
|
3495
|
+
executionPlanDigest: identity.executionPlanDigest,
|
|
3496
|
+
...executorEvidence ? { executorEvidence } : {},
|
|
3497
|
+
...taskOutcome ? { taskOutcome } : {},
|
|
3498
|
+
...memoryAfter ? { memoryAfter } : {}
|
|
3499
|
+
});
|
|
3500
|
+
const evidence = await persistCandidateOutputArtifact(outputArtifacts, {
|
|
3501
|
+
executionId: identity.executionId,
|
|
3502
|
+
purpose: "executor-capture",
|
|
3503
|
+
bytes,
|
|
3504
|
+
signal
|
|
3505
|
+
});
|
|
3506
|
+
return Object.freeze({
|
|
3507
|
+
evidence,
|
|
3508
|
+
...taskOutcome ? { taskOutcome: Object.freeze(taskOutcome) } : {},
|
|
3509
|
+
...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {}
|
|
3510
|
+
});
|
|
3511
|
+
}
|
|
3512
|
+
async function persistTaskCapture(executionId, expected, capture, outputArtifacts, signal) {
|
|
3513
|
+
if (capture.kind === "output") {
|
|
3514
|
+
if (expected.kind !== "output")
|
|
3515
|
+
throw new Error("captured output does not match the signed task");
|
|
3516
|
+
const artifact = await persistCandidateOutputArtifact(outputArtifacts, {
|
|
3517
|
+
executionId,
|
|
3518
|
+
purpose: "task-output",
|
|
3519
|
+
bytes: capture.bytes,
|
|
3520
|
+
signal
|
|
3521
|
+
});
|
|
3522
|
+
return {
|
|
3523
|
+
kind: "output",
|
|
3524
|
+
spec: { mediaType: expected.mediaType, maxBytes: expected.maxBytes },
|
|
3525
|
+
artifact
|
|
3526
|
+
};
|
|
3527
|
+
}
|
|
3528
|
+
if (expected.kind !== "workspace") {
|
|
3529
|
+
throw new Error("captured workspace does not match the signed task");
|
|
3530
|
+
}
|
|
3531
|
+
const workspace = await persistWorkspaceCapture(
|
|
3532
|
+
executionId,
|
|
3533
|
+
"task-manifest",
|
|
3534
|
+
"task-archive",
|
|
3535
|
+
capture.afterState,
|
|
3536
|
+
capture.archive,
|
|
3537
|
+
outputArtifacts,
|
|
3538
|
+
signal
|
|
3539
|
+
);
|
|
3540
|
+
const gitDiff = await persistCandidateOutputArtifact(outputArtifacts, {
|
|
3541
|
+
executionId,
|
|
3542
|
+
purpose: "task-patch",
|
|
3543
|
+
bytes: capture.gitDiff,
|
|
3544
|
+
signal
|
|
3545
|
+
});
|
|
3546
|
+
return { kind: "workspace", resultTree: capture.resultTree, ...workspace, gitDiff };
|
|
3547
|
+
}
|
|
3548
|
+
async function persistWorkspaceCapture(executionId, manifestPurpose, archivePurpose, afterState, archiveBytes, outputArtifacts, signal) {
|
|
3549
|
+
const manifestBytes = canonicalCandidateBytes(afterState);
|
|
3550
|
+
const [manifest, archive] = await Promise.all([
|
|
3551
|
+
persistCandidateOutputArtifact(outputArtifacts, {
|
|
3552
|
+
executionId,
|
|
3553
|
+
purpose: manifestPurpose,
|
|
3554
|
+
bytes: manifestBytes,
|
|
3555
|
+
signal
|
|
3556
|
+
}),
|
|
3557
|
+
persistCandidateOutputArtifact(outputArtifacts, {
|
|
3558
|
+
executionId,
|
|
3559
|
+
purpose: archivePurpose,
|
|
3560
|
+
bytes: archiveBytes,
|
|
3561
|
+
signal
|
|
3562
|
+
})
|
|
3563
|
+
]);
|
|
3564
|
+
return { afterState, manifest, archive };
|
|
3565
|
+
}
|
|
3566
|
+
|
|
3289
3567
|
// src/candidate-execution/outcome-evidence.ts
|
|
3290
3568
|
async function persistCandidateModelSettlement(state, settlement, outputArtifacts) {
|
|
3291
3569
|
return await persistCandidateModelSettlementEvidence(
|
|
@@ -3300,7 +3578,6 @@ async function persistCandidateModelSettlement(state, settlement, outputArtifact
|
|
|
3300
3578
|
}
|
|
3301
3579
|
async function persistCandidateModelSettlementEvidence(identity, settlement, outputArtifacts) {
|
|
3302
3580
|
const material = {
|
|
3303
|
-
schemaVersion: 2,
|
|
3304
3581
|
kind: "agent-candidate-model-settlement-material",
|
|
3305
3582
|
executionPlanDigest: identity.executionPlanDigest,
|
|
3306
3583
|
preparationId: settlement.value.preparationId,
|
|
@@ -3321,7 +3598,7 @@ async function persistCandidateModelSettlementEvidence(identity, settlement, out
|
|
|
3321
3598
|
reasoningTokens: call.reasoningTokens ?? 0,
|
|
3322
3599
|
costUsdNanos: call.costUsdNanos
|
|
3323
3600
|
})),
|
|
3324
|
-
usage: settlement.
|
|
3601
|
+
usage: settlement.usage
|
|
3325
3602
|
};
|
|
3326
3603
|
const bytes = canonicalCandidateBytes(material);
|
|
3327
3604
|
const digest = sha256Bytes(bytes);
|
|
@@ -3332,7 +3609,6 @@ async function persistCandidateModelSettlementEvidence(identity, settlement, out
|
|
|
3332
3609
|
});
|
|
3333
3610
|
return immutableCandidateValue(
|
|
3334
3611
|
agentCandidateModelSettlementEvidenceSchema.parse({
|
|
3335
|
-
schemaVersion: 2,
|
|
3336
3612
|
kind: "agent-candidate-model-settlement",
|
|
3337
3613
|
digest,
|
|
3338
3614
|
material,
|
|
@@ -3340,16 +3616,53 @@ async function persistCandidateModelSettlementEvidence(identity, settlement, out
|
|
|
3340
3616
|
})
|
|
3341
3617
|
);
|
|
3342
3618
|
}
|
|
3343
|
-
async function
|
|
3619
|
+
async function persistVerifiedAgentCandidateExecutorCapture(state, capture, outputArtifacts, protectedValues, signal) {
|
|
3344
3620
|
signal?.throwIfAborted();
|
|
3621
|
+
const taskCapture = capture.taskOutcome;
|
|
3622
|
+
if (!taskCapture) throw new Error("candidate final capture is missing the task outcome");
|
|
3623
|
+
if (capture.evidence) assertNoProtectedBytes(capture.evidence, protectedValues);
|
|
3624
|
+
const expected = state.benchmarkTask.outcome;
|
|
3625
|
+
if (taskCapture.kind !== expected.kind) {
|
|
3626
|
+
throw new Error(
|
|
3627
|
+
`candidate captured ${taskCapture.kind} outcome does not match expected ${expected.kind} outcome`
|
|
3628
|
+
);
|
|
3629
|
+
}
|
|
3630
|
+
const verified = taskCapture.kind === "output" && expected.kind === "output" ? verifyOutputTaskCapture(taskCapture.bytes, expected, protectedValues) : taskCapture.kind === "workspace" && expected.kind === "workspace" ? await verifyWorkspaceTaskCapture(state, taskCapture, protectedValues, signal) : void 0;
|
|
3631
|
+
if (!verified) throw new Error("candidate task outcome kind could not be narrowed");
|
|
3632
|
+
await verifyMemoryCapture(state, capture, protectedValues, signal);
|
|
3633
|
+
const persistedCapture = await persistAgentCandidateExecutorCapture(
|
|
3634
|
+
{
|
|
3635
|
+
executionId: state.executionId,
|
|
3636
|
+
executionPlanDigest: state.executionPlan.value.digest
|
|
3637
|
+
},
|
|
3638
|
+
expected,
|
|
3639
|
+
capture,
|
|
3640
|
+
outputArtifacts,
|
|
3641
|
+
signal
|
|
3642
|
+
);
|
|
3643
|
+
const persisted = persistedCapture.taskOutcome;
|
|
3644
|
+
if (!persisted || persisted.kind !== verified.kind) {
|
|
3645
|
+
throw new Error("persisted task capture kind changed");
|
|
3646
|
+
}
|
|
3647
|
+
const taskOutcome = verified.kind === "output" && persisted.kind === "output" ? await persistVerifiedOutputTaskOutcome(state, verified, persisted, outputArtifacts, signal) : verified.kind === "workspace" && persisted.kind === "workspace" ? await persistVerifiedWorkspaceTaskOutcome(
|
|
3648
|
+
state,
|
|
3649
|
+
verified,
|
|
3650
|
+
persisted,
|
|
3651
|
+
outputArtifacts,
|
|
3652
|
+
signal
|
|
3653
|
+
) : void 0;
|
|
3654
|
+
if (!taskOutcome) throw new Error("persisted task outcome kind could not be narrowed");
|
|
3655
|
+
return Object.freeze({ persistedCapture, taskOutcome });
|
|
3656
|
+
}
|
|
3657
|
+
async function verifyWorkspaceTaskCapture(state, capture, protectedValues, signal) {
|
|
3658
|
+
const repository = state.benchmarkTask.repository;
|
|
3659
|
+
if (!repository) throw new Error("workspace task outcome is missing repository identity");
|
|
3345
3660
|
const patch = Uint8Array.from(capture.gitDiff);
|
|
3346
3661
|
const archive = Uint8Array.from(capture.archive);
|
|
3347
3662
|
if (archive.byteLength === 0) throw new Error("candidate task archive cannot be empty");
|
|
3348
3663
|
assertNoProtectedBytes(patch, protectedValues);
|
|
3349
3664
|
assertNoProtectedBytes(archive, protectedValues);
|
|
3350
|
-
const
|
|
3351
|
-
const afterState = provisional.material;
|
|
3352
|
-
const repository = workspaceTaskRepository(state.executionPlan.value.material.task);
|
|
3665
|
+
const afterState = immutableCandidateValue(capture.afterState);
|
|
3353
3666
|
const verified = await verifyTaskOutcomePatch({
|
|
3354
3667
|
repositoryRoot: state.roots.staging.taskRoot,
|
|
3355
3668
|
baseCommit: repository.baseCommit,
|
|
@@ -3359,24 +3672,38 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
|
|
|
3359
3672
|
afterState
|
|
3360
3673
|
});
|
|
3361
3674
|
signal?.throwIfAborted();
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3675
|
+
const manifestBytes = canonicalCandidateBytes(afterState);
|
|
3676
|
+
assertNoProtectedBytes(manifestBytes, protectedValues);
|
|
3677
|
+
const provisionalSnapshot = agentCandidateWorkspaceSnapshotEvidenceSchema2.parse({
|
|
3678
|
+
kind: "agent-candidate-workspace-snapshot",
|
|
3679
|
+
digest: sha256Bytes(manifestBytes),
|
|
3367
3680
|
material: afterState,
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
signal
|
|
3681
|
+
manifest: embeddedCandidateArtifact(manifestBytes),
|
|
3682
|
+
archive: embeddedCandidateArtifact(archive)
|
|
3371
3683
|
});
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3684
|
+
await verifyTaskOutcomeArchive(state, provisionalSnapshot, archive, protectedValues);
|
|
3685
|
+
signal?.throwIfAborted();
|
|
3686
|
+
return {
|
|
3687
|
+
kind: "workspace",
|
|
3688
|
+
patch,
|
|
3689
|
+
archive,
|
|
3690
|
+
afterState,
|
|
3691
|
+
manifestBytes,
|
|
3692
|
+
resultCommit: verified.resultCommit,
|
|
3693
|
+
resultTree: verified.resultTree,
|
|
3694
|
+
repository
|
|
3695
|
+
};
|
|
3696
|
+
}
|
|
3697
|
+
async function persistVerifiedWorkspaceTaskOutcome(state, verified, persisted, outputArtifacts, signal) {
|
|
3698
|
+
const { afterState, manifestBytes, patch, repository } = verified;
|
|
3699
|
+
const snapshot = agentCandidateWorkspaceSnapshotEvidenceSchema2.parse({
|
|
3700
|
+
kind: "agent-candidate-workspace-snapshot",
|
|
3701
|
+
digest: sha256Bytes(manifestBytes),
|
|
3702
|
+
material: afterState,
|
|
3703
|
+
manifest: persisted.manifest,
|
|
3704
|
+
archive: persisted.archive
|
|
3377
3705
|
});
|
|
3378
3706
|
const material = {
|
|
3379
|
-
schemaVersion: 2,
|
|
3380
3707
|
kind: "agent-candidate-task-outcome-material",
|
|
3381
3708
|
executionPlanDigest: state.executionPlan.value.digest,
|
|
3382
3709
|
outcome: {
|
|
@@ -3396,10 +3723,60 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
|
|
|
3396
3723
|
afterState: snapshot,
|
|
3397
3724
|
gitDiff: {
|
|
3398
3725
|
format: "git-diff-binary",
|
|
3399
|
-
artifact: gitDiff
|
|
3726
|
+
artifact: persisted.gitDiff
|
|
3400
3727
|
}
|
|
3401
3728
|
}
|
|
3402
3729
|
};
|
|
3730
|
+
const evidence = await persistTaskOutcomeEvidence(state, material, outputArtifacts, signal);
|
|
3731
|
+
const storedPatch = Uint8Array.from(patch);
|
|
3732
|
+
return Object.freeze({
|
|
3733
|
+
kind: "workspace",
|
|
3734
|
+
evidence,
|
|
3735
|
+
get patch() {
|
|
3736
|
+
return Uint8Array.from(storedPatch);
|
|
3737
|
+
},
|
|
3738
|
+
[verifiedTaskOutcomeBrand]: true
|
|
3739
|
+
});
|
|
3740
|
+
}
|
|
3741
|
+
function verifyOutputTaskCapture(capturedBytes, expected, protectedValues) {
|
|
3742
|
+
if (capturedBytes.byteLength === 0) throw new Error("candidate task output cannot be empty");
|
|
3743
|
+
if (capturedBytes.byteLength > expected.maxBytes) {
|
|
3744
|
+
throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
|
|
3745
|
+
}
|
|
3746
|
+
const output = Uint8Array.from(capturedBytes);
|
|
3747
|
+
assertNoProtectedBytes(output, protectedValues);
|
|
3748
|
+
return {
|
|
3749
|
+
kind: "output",
|
|
3750
|
+
bytes: output,
|
|
3751
|
+
spec: { mediaType: expected.mediaType, maxBytes: expected.maxBytes }
|
|
3752
|
+
};
|
|
3753
|
+
}
|
|
3754
|
+
async function persistVerifiedOutputTaskOutcome(state, verified, persisted, outputArtifacts, signal) {
|
|
3755
|
+
if (persisted.spec.mediaType !== verified.spec.mediaType || persisted.spec.maxBytes !== verified.spec.maxBytes) {
|
|
3756
|
+
throw new Error("persisted task output changed the signed media constraints");
|
|
3757
|
+
}
|
|
3758
|
+
const material = {
|
|
3759
|
+
kind: "agent-candidate-task-outcome-material",
|
|
3760
|
+
executionPlanDigest: state.executionPlan.value.digest,
|
|
3761
|
+
outcome: {
|
|
3762
|
+
kind: "output",
|
|
3763
|
+
spec: verified.spec,
|
|
3764
|
+
artifact: persisted.artifact
|
|
3765
|
+
}
|
|
3766
|
+
};
|
|
3767
|
+
const evidence = await persistTaskOutcomeEvidence(state, material, outputArtifacts, signal);
|
|
3768
|
+
const storedOutput = Uint8Array.from(verified.bytes);
|
|
3769
|
+
return Object.freeze({
|
|
3770
|
+
kind: "output",
|
|
3771
|
+
evidence,
|
|
3772
|
+
spec: immutableCandidateValue(verified.spec),
|
|
3773
|
+
get bytes() {
|
|
3774
|
+
return Uint8Array.from(storedOutput);
|
|
3775
|
+
},
|
|
3776
|
+
[verifiedTaskOutcomeBrand]: true
|
|
3777
|
+
});
|
|
3778
|
+
}
|
|
3779
|
+
async function persistTaskOutcomeEvidence(state, material, outputArtifacts, signal) {
|
|
3403
3780
|
const bytes = canonicalCandidateBytes(material);
|
|
3404
3781
|
const digest = sha256Bytes(bytes);
|
|
3405
3782
|
const artifact = await persistCandidateOutputArtifact(outputArtifacts, {
|
|
@@ -3408,23 +3785,14 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
|
|
|
3408
3785
|
bytes,
|
|
3409
3786
|
signal
|
|
3410
3787
|
});
|
|
3411
|
-
|
|
3788
|
+
return immutableCandidateValue(
|
|
3412
3789
|
agentCandidateTaskOutcomeEvidenceSchema.parse({
|
|
3413
|
-
schemaVersion: 2,
|
|
3414
3790
|
kind: "agent-candidate-task-outcome",
|
|
3415
3791
|
digest,
|
|
3416
3792
|
material,
|
|
3417
3793
|
artifact
|
|
3418
3794
|
})
|
|
3419
3795
|
);
|
|
3420
|
-
const storedPatch = Uint8Array.from(patch);
|
|
3421
|
-
return Object.freeze({
|
|
3422
|
-
evidence,
|
|
3423
|
-
get patch() {
|
|
3424
|
-
return Uint8Array.from(storedPatch);
|
|
3425
|
-
},
|
|
3426
|
-
[verifiedTaskOutcomeBrand]: true
|
|
3427
|
-
});
|
|
3428
3796
|
}
|
|
3429
3797
|
async function persistCandidateBenchmarkResult(state, termination, outcome, grader, outputArtifacts, protectedValues, signal) {
|
|
3430
3798
|
signal?.throwIfAborted();
|
|
@@ -3433,6 +3801,7 @@ async function persistCandidateBenchmarkResult(state, termination, outcome, grad
|
|
|
3433
3801
|
executionId: state.executionId,
|
|
3434
3802
|
termination: frozenTermination,
|
|
3435
3803
|
outcome,
|
|
3804
|
+
expectedGrader: state.benchmarkTask.grader,
|
|
3436
3805
|
grader,
|
|
3437
3806
|
artifacts: outputArtifacts,
|
|
3438
3807
|
signal
|
|
@@ -3448,24 +3817,13 @@ async function persistCandidateBenchmarkResult(state, termination, outcome, grad
|
|
|
3448
3817
|
bytes: rawEvidence,
|
|
3449
3818
|
signal
|
|
3450
3819
|
});
|
|
3451
|
-
const task = state.executionPlan.value.material.task;
|
|
3452
3820
|
const material = {
|
|
3453
|
-
schemaVersion: 1,
|
|
3454
3821
|
kind: "agent-candidate-benchmark-result-material",
|
|
3455
3822
|
executionPlanDigest: state.executionPlan.value.digest,
|
|
3456
3823
|
taskOutcomeDigest: outcome.evidence.digest,
|
|
3457
|
-
|
|
3458
|
-
name: task.benchmark,
|
|
3459
|
-
version: task.benchmarkVersion,
|
|
3460
|
-
taskId: task.taskId,
|
|
3461
|
-
splitDigest: task.splitDigest
|
|
3462
|
-
},
|
|
3463
|
-
grader: {
|
|
3464
|
-
name: graded.grader.name,
|
|
3465
|
-
version: graded.grader.version,
|
|
3466
|
-
artifact: graded.grader.artifact
|
|
3467
|
-
},
|
|
3824
|
+
grader: graded.grader,
|
|
3468
3825
|
evidence: evidenceRef,
|
|
3826
|
+
grading: graded.grading,
|
|
3469
3827
|
score: evaluation.score,
|
|
3470
3828
|
passed: evaluation.passed,
|
|
3471
3829
|
dimensions: evaluation.dimensions
|
|
@@ -3480,7 +3838,6 @@ async function persistCandidateBenchmarkResult(state, termination, outcome, grad
|
|
|
3480
3838
|
});
|
|
3481
3839
|
return immutableCandidateValue(
|
|
3482
3840
|
agentCandidateBenchmarkResultEvidenceSchema.parse({
|
|
3483
|
-
schemaVersion: 1,
|
|
3484
3841
|
kind: "agent-candidate-benchmark-result",
|
|
3485
3842
|
digest,
|
|
3486
3843
|
material,
|
|
@@ -3489,7 +3846,7 @@ async function persistCandidateBenchmarkResult(state, termination, outcome, grad
|
|
|
3489
3846
|
);
|
|
3490
3847
|
}
|
|
3491
3848
|
async function verifyTaskOutcomeArchive(state, snapshot, archive, protectedValues) {
|
|
3492
|
-
const root = await
|
|
3849
|
+
const root = await mkdtemp2(join2(tmpdir2(), "agent-candidate-task-archive-"));
|
|
3493
3850
|
try {
|
|
3494
3851
|
await state.ports.workspaces.materialize({
|
|
3495
3852
|
role: "task",
|
|
@@ -3500,7 +3857,40 @@ async function verifyTaskOutcomeArchive(state, snapshot, archive, protectedValue
|
|
|
3500
3857
|
const files = await readMaterializedWorkspaceFiles(root, snapshot.material);
|
|
3501
3858
|
for (const file of files) assertNoProtectedBytes(file.bytes, protectedValues);
|
|
3502
3859
|
} finally {
|
|
3503
|
-
await
|
|
3860
|
+
await rm2(root, { recursive: true, force: true });
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
async function verifyMemoryCapture(state, capture, protectedValues, signal) {
|
|
3864
|
+
if (state.memory.mode === "disabled") {
|
|
3865
|
+
if (capture.memoryAfter) throw new Error("disabled memory cannot return an after-state");
|
|
3866
|
+
return;
|
|
3867
|
+
}
|
|
3868
|
+
const memory = capture.memoryAfter;
|
|
3869
|
+
if (!memory) throw new Error("isolated memory is missing its protected after-state");
|
|
3870
|
+
if (memory.archive.byteLength === 0) throw new Error("isolated memory archive cannot be empty");
|
|
3871
|
+
const manifestBytes = canonicalCandidateBytes(memory.afterState);
|
|
3872
|
+
assertNoProtectedBytes(manifestBytes, protectedValues);
|
|
3873
|
+
assertNoProtectedBytes(memory.archive, protectedValues);
|
|
3874
|
+
const snapshot = agentCandidateWorkspaceSnapshotEvidenceSchema2.parse({
|
|
3875
|
+
kind: "agent-candidate-workspace-snapshot",
|
|
3876
|
+
digest: sha256Bytes(manifestBytes),
|
|
3877
|
+
material: memory.afterState,
|
|
3878
|
+
manifest: embeddedCandidateArtifact(manifestBytes),
|
|
3879
|
+
archive: embeddedCandidateArtifact(memory.archive)
|
|
3880
|
+
});
|
|
3881
|
+
const root = await mkdtemp2(join2(tmpdir2(), "agent-candidate-memory-after-"));
|
|
3882
|
+
try {
|
|
3883
|
+
await state.ports.workspaces.materialize({
|
|
3884
|
+
role: "memory",
|
|
3885
|
+
snapshot,
|
|
3886
|
+
archive: Uint8Array.from(memory.archive),
|
|
3887
|
+
destination: root
|
|
3888
|
+
});
|
|
3889
|
+
const files = await readMaterializedWorkspaceFiles(root, memory.afterState);
|
|
3890
|
+
for (const file of files) assertNoProtectedBytes(file.bytes, protectedValues);
|
|
3891
|
+
signal?.throwIfAborted();
|
|
3892
|
+
} finally {
|
|
3893
|
+
await rm2(root, { recursive: true, force: true });
|
|
3504
3894
|
}
|
|
3505
3895
|
}
|
|
3506
3896
|
function normalizeEvaluation(evaluation, termination) {
|
|
@@ -3532,81 +3922,60 @@ function assertUnitScore(value, label) {
|
|
|
3532
3922
|
}
|
|
3533
3923
|
|
|
3534
3924
|
// src/candidate-execution/protected-trace-store.ts
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
protectedValues;
|
|
3543
|
-
aggregate = {
|
|
3544
|
-
version: REDACTION_VERSION3,
|
|
3545
|
-
redactionCount: 0,
|
|
3546
|
-
byRule: {}
|
|
3547
|
-
};
|
|
3548
|
-
report() {
|
|
3549
|
-
return {
|
|
3550
|
-
version: this.aggregate.version,
|
|
3551
|
-
redactionCount: this.aggregate.redactionCount,
|
|
3552
|
-
byRule: { ...this.aggregate.byRule }
|
|
3553
|
-
};
|
|
3554
|
-
}
|
|
3555
|
-
async appendRun(run) {
|
|
3556
|
-
await this.inner.appendRun(this.redact(run));
|
|
3557
|
-
}
|
|
3558
|
-
async updateRun(runId, patch) {
|
|
3559
|
-
await this.inner.updateRun(this.redact(runId), this.redact(patch));
|
|
3560
|
-
}
|
|
3561
|
-
async appendSpan(span) {
|
|
3562
|
-
if (span.kind === "llm") {
|
|
3563
|
-
throw new Error("candidate executors cannot author protected model spans");
|
|
3925
|
+
function createProtectedAgentCandidateTraceAccess(inner, protectedValues) {
|
|
3926
|
+
const redactor = createProtectedRecordRedactor(protectedValues);
|
|
3927
|
+
const pendingWrites = /* @__PURE__ */ new Set();
|
|
3928
|
+
let acceptsWrites = true;
|
|
3929
|
+
const write = (operation) => {
|
|
3930
|
+
if (!acceptsWrites) {
|
|
3931
|
+
return Promise.reject(new Error("candidate trace writes are closed"));
|
|
3564
3932
|
}
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
}
|
|
3571
|
-
await this.inner.updateSpan(this.redact(spanId), this.redact(patch));
|
|
3572
|
-
}
|
|
3573
|
-
async appendEvent(event) {
|
|
3574
|
-
await this.inner.appendEvent(this.redact(event));
|
|
3575
|
-
}
|
|
3576
|
-
async appendArtifact(artifact) {
|
|
3577
|
-
await this.inner.appendArtifact(this.redact(artifact));
|
|
3578
|
-
}
|
|
3579
|
-
async appendBudgetEntry(entry) {
|
|
3580
|
-
await this.inner.appendBudgetEntry(this.redact(entry));
|
|
3581
|
-
}
|
|
3582
|
-
getRun(...args) {
|
|
3583
|
-
return this.inner.getRun(...args);
|
|
3584
|
-
}
|
|
3585
|
-
listRuns(...args) {
|
|
3586
|
-
return this.inner.listRuns(...args);
|
|
3587
|
-
}
|
|
3588
|
-
spans(...args) {
|
|
3589
|
-
return this.inner.spans(...args);
|
|
3590
|
-
}
|
|
3591
|
-
events(...args) {
|
|
3592
|
-
return this.inner.events(...args);
|
|
3593
|
-
}
|
|
3594
|
-
budget(...args) {
|
|
3595
|
-
return this.inner.budget(...args);
|
|
3596
|
-
}
|
|
3597
|
-
artifacts(...args) {
|
|
3598
|
-
return this.inner.artifacts(...args);
|
|
3599
|
-
}
|
|
3600
|
-
redact(value) {
|
|
3601
|
-
const redacted = redactProtectedValue(value, this.protectedValues);
|
|
3602
|
-
this.aggregate.version = redacted.report.version;
|
|
3603
|
-
this.aggregate.redactionCount += redacted.report.redactionCount;
|
|
3604
|
-
for (const [rule, count] of Object.entries(redacted.report.byRule)) {
|
|
3605
|
-
this.aggregate.byRule[rule] = (this.aggregate.byRule[rule] ?? 0) + count;
|
|
3933
|
+
let started;
|
|
3934
|
+
try {
|
|
3935
|
+
started = operation();
|
|
3936
|
+
} catch (error) {
|
|
3937
|
+
return Promise.reject(error);
|
|
3606
3938
|
}
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3939
|
+
let tracked;
|
|
3940
|
+
tracked = started.finally(() => pendingWrites.delete(tracked));
|
|
3941
|
+
pendingWrites.add(tracked);
|
|
3942
|
+
return tracked;
|
|
3943
|
+
};
|
|
3944
|
+
const store = Object.freeze({
|
|
3945
|
+
appendRun: (run) => write(() => inner.appendRun(redactor.record(run))),
|
|
3946
|
+
updateRun: (runId, patch) => write(() => inner.updateRun(redactor.identifier(runId), redactor.record(patch))),
|
|
3947
|
+
appendSpan: (span) => write(async () => {
|
|
3948
|
+
if (span.kind === "llm") {
|
|
3949
|
+
throw new Error("candidate executors cannot author protected model spans");
|
|
3950
|
+
}
|
|
3951
|
+
await inner.appendSpan(redactor.record(span));
|
|
3952
|
+
}),
|
|
3953
|
+
updateSpan: (spanId, patch) => write(async () => {
|
|
3954
|
+
if (patch.kind === "llm") {
|
|
3955
|
+
throw new Error("candidate executors cannot author protected model spans");
|
|
3956
|
+
}
|
|
3957
|
+
await inner.updateSpan(redactor.identifier(spanId), redactor.record(patch));
|
|
3958
|
+
}),
|
|
3959
|
+
appendEvent: (event) => write(() => inner.appendEvent(redactor.record(event))),
|
|
3960
|
+
appendArtifact: (artifact) => write(() => inner.appendArtifact(redactor.record(artifact))),
|
|
3961
|
+
appendBudgetEntry: (entry) => write(() => inner.appendBudgetEntry(redactor.record(entry))),
|
|
3962
|
+
getRun: async (runId) => inner.getRun(redactor.identifier(runId)),
|
|
3963
|
+
listRuns: async (filter) => inner.listRuns(filter ? redactor.query(filter) : void 0),
|
|
3964
|
+
spans: async (filter) => inner.spans(filter ? redactor.query(filter) : void 0),
|
|
3965
|
+
events: async (filter) => inner.events(filter ? redactor.query(filter) : void 0),
|
|
3966
|
+
budget: async (runId) => inner.budget(redactor.identifier(runId)),
|
|
3967
|
+
artifacts: async (runId) => inner.artifacts(redactor.identifier(runId))
|
|
3968
|
+
});
|
|
3969
|
+
return Object.freeze({
|
|
3970
|
+
store,
|
|
3971
|
+
closeWrites: async () => {
|
|
3972
|
+
acceptsWrites = false;
|
|
3973
|
+
await Promise.all([...pendingWrites]);
|
|
3974
|
+
},
|
|
3975
|
+
identity: (trace) => redactor.traceIdentity(trace),
|
|
3976
|
+
report: () => redactor.report()
|
|
3977
|
+
});
|
|
3978
|
+
}
|
|
3610
3979
|
var RecoveryAgentCandidateTraceStore = class {
|
|
3611
3980
|
constructor(inner) {
|
|
3612
3981
|
this.inner = inner;
|
|
@@ -3683,9 +4052,29 @@ async function executePreparedAgentCandidate(prepared, options) {
|
|
|
3683
4052
|
} catch (error) {
|
|
3684
4053
|
return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
|
|
3685
4054
|
}
|
|
4055
|
+
let preparationEvidence;
|
|
4056
|
+
try {
|
|
4057
|
+
const [executionPlan, materializationReceipt] = await Promise.all([
|
|
4058
|
+
persistCandidateOutputArtifact(options.outputArtifacts, {
|
|
4059
|
+
executionId: state.executionId,
|
|
4060
|
+
purpose: "execution-plan",
|
|
4061
|
+
bytes: state.executionPlan.bytes
|
|
4062
|
+
}),
|
|
4063
|
+
persistCandidateOutputArtifact(options.outputArtifacts, {
|
|
4064
|
+
executionId: state.executionId,
|
|
4065
|
+
purpose: "materialization-receipt",
|
|
4066
|
+
bytes: state.materializationReceipt.bytes
|
|
4067
|
+
})
|
|
4068
|
+
]);
|
|
4069
|
+
preparationEvidence = Object.freeze({ executionPlan, materializationReceipt });
|
|
4070
|
+
} catch (error) {
|
|
4071
|
+
return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
|
|
4072
|
+
}
|
|
3686
4073
|
let acquired;
|
|
3687
4074
|
try {
|
|
3688
|
-
acquired = await options.claimStore.tryClaim(
|
|
4075
|
+
acquired = await options.claimStore.tryClaim(
|
|
4076
|
+
candidateExecutionClaim(prepared, preparationEvidence)
|
|
4077
|
+
);
|
|
3689
4078
|
} catch (error) {
|
|
3690
4079
|
return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
|
|
3691
4080
|
}
|
|
@@ -3830,25 +4219,36 @@ async function executePreparedAgentCandidate(prepared, options) {
|
|
|
3830
4219
|
);
|
|
3831
4220
|
}
|
|
3832
4221
|
const protectedValues = protectedEnvironmentValues(activation, memoryActivation);
|
|
3833
|
-
const
|
|
4222
|
+
const protectedTrace = createProtectedAgentCandidateTraceAccess(
|
|
3834
4223
|
options.traceStore,
|
|
3835
4224
|
protectedValues
|
|
3836
4225
|
);
|
|
4226
|
+
const persistedTrace = protectedTrace.identity(state.trace);
|
|
3837
4227
|
const execution = await runAndStopExecutor(
|
|
3838
4228
|
options.executor,
|
|
3839
4229
|
request,
|
|
3840
|
-
|
|
4230
|
+
state.benchmarkTask.outcome,
|
|
4231
|
+
protectedTrace.store,
|
|
3841
4232
|
deadlineAtMs,
|
|
3842
4233
|
cleanupTimeoutMs
|
|
3843
4234
|
);
|
|
3844
4235
|
beginPreparedCandidateSettlement(prepared);
|
|
3845
4236
|
const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
|
|
3846
4237
|
const accessReason = execution.kind === "timeout" || execution.termination?.kind === "timeout" ? "timeout" : execution.kind === "capture" ? "completed" : "failed";
|
|
3847
|
-
const
|
|
4238
|
+
const traceClosure = withinCandidateCleanupDeadline(
|
|
4239
|
+
() => protectedTrace.closeWrites(),
|
|
4240
|
+
cleanupDeadlineAtMs,
|
|
4241
|
+
"candidate trace write closure"
|
|
4242
|
+
).then(
|
|
4243
|
+
() => ({ closed: true, error: void 0 }),
|
|
4244
|
+
(error) => ({ closed: false, error })
|
|
4245
|
+
);
|
|
4246
|
+
const [traceClose, memoryClose, settlementResult] = await Promise.all([
|
|
4247
|
+
traceClosure,
|
|
3848
4248
|
closeMemoryAccess(state, accessReason, cleanupDeadlineAtMs),
|
|
3849
4249
|
settleModelGrant(state, accessReason, cleanupDeadlineAtMs)
|
|
3850
4250
|
]);
|
|
3851
|
-
if (!execution.processStopped || !settlementResult.settlement || !memoryClose.closed) {
|
|
4251
|
+
if (!execution.processStopped || !traceClose.closed || !settlementResult.settlement || !memoryClose.closed) {
|
|
3852
4252
|
consumePreparedCandidateExecution(prepared, "failed");
|
|
3853
4253
|
return failedAgentCandidateRun(
|
|
3854
4254
|
state,
|
|
@@ -3856,6 +4256,7 @@ async function executePreparedAgentCandidate(prepared, options) {
|
|
|
3856
4256
|
joinErrors(
|
|
3857
4257
|
execution.error,
|
|
3858
4258
|
!execution.processStopped ? new Error("candidate process termination is not proven") : void 0,
|
|
4259
|
+
traceClose.error,
|
|
3859
4260
|
memoryClose.error,
|
|
3860
4261
|
settlementResult.error ?? (!settlementResult.settlement ? new Error("model settlement failed") : void 0),
|
|
3861
4262
|
new Error("candidate claim remains recoverable until protected cleanup is proven")
|
|
@@ -3922,12 +4323,12 @@ async function executePreparedAgentCandidate(prepared, options) {
|
|
|
3922
4323
|
async (signal) => {
|
|
3923
4324
|
await appendAuthoritativeModelSettlementSpans(
|
|
3924
4325
|
options.traceStore,
|
|
3925
|
-
|
|
4326
|
+
persistedTrace.runId,
|
|
3926
4327
|
settlementResult.settlement
|
|
3927
4328
|
);
|
|
3928
|
-
const taskOutcome = await
|
|
4329
|
+
const { persistedCapture, taskOutcome } = await persistVerifiedAgentCandidateExecutorCapture(
|
|
3929
4330
|
state,
|
|
3930
|
-
execution.finalCapture
|
|
4331
|
+
execution.finalCapture,
|
|
3931
4332
|
options.outputArtifacts,
|
|
3932
4333
|
protectedValues,
|
|
3933
4334
|
signal
|
|
@@ -3945,16 +4346,18 @@ async function executePreparedAgentCandidate(prepared, options) {
|
|
|
3945
4346
|
state,
|
|
3946
4347
|
capture,
|
|
3947
4348
|
options.traceStore,
|
|
4349
|
+
persistedTrace,
|
|
3948
4350
|
settlementResult.settlement,
|
|
3949
4351
|
{
|
|
3950
4352
|
finalCapture: execution.finalCapture,
|
|
4353
|
+
persistedCapture,
|
|
3951
4354
|
modelSettlement,
|
|
3952
4355
|
taskOutcome,
|
|
3953
4356
|
benchmarkResult,
|
|
3954
4357
|
outputArtifacts: options.outputArtifacts
|
|
3955
4358
|
},
|
|
3956
4359
|
protectedValues,
|
|
3957
|
-
|
|
4360
|
+
protectedTrace.report(),
|
|
3958
4361
|
signal
|
|
3959
4362
|
);
|
|
3960
4363
|
},
|
|
@@ -3973,18 +4376,16 @@ async function executePreparedAgentCandidate(prepared, options) {
|
|
|
3973
4376
|
let terminal;
|
|
3974
4377
|
try {
|
|
3975
4378
|
terminal = result.succeeded ? {
|
|
3976
|
-
schemaVersion: 1,
|
|
3977
4379
|
status: "succeeded",
|
|
3978
|
-
usage: settlementResult.settlement.
|
|
4380
|
+
usage: settlementResult.settlement.usage,
|
|
3979
4381
|
modelSettlement: result.artifacts.modelSettlement,
|
|
3980
4382
|
taskOutcome: result.artifacts.taskOutcome,
|
|
3981
4383
|
benchmarkResult: result.artifacts.benchmarkResult,
|
|
3982
4384
|
runReceipt: result.artifacts.runReceipt
|
|
3983
4385
|
} : {
|
|
3984
|
-
schemaVersion: 1,
|
|
3985
4386
|
status: "failed",
|
|
3986
4387
|
failureClass,
|
|
3987
|
-
usage: settlementResult.settlement.
|
|
4388
|
+
usage: settlementResult.settlement.usage,
|
|
3988
4389
|
modelSettlement: modelSettlement.artifact,
|
|
3989
4390
|
failureEvidence: await withinCandidateCleanupDeadline(
|
|
3990
4391
|
() => persistFailureEvidence(
|
|
@@ -4031,7 +4432,7 @@ async function executePreparedAgentCandidate(prepared, options) {
|
|
|
4031
4432
|
settlementResult.settlement.usage
|
|
4032
4433
|
);
|
|
4033
4434
|
}
|
|
4034
|
-
async function runAndStopExecutor(executor, request, traceStore, deadlineAtMs, cleanupTimeoutMs) {
|
|
4435
|
+
async function runAndStopExecutor(executor, request, expectedOutcome, traceStore, deadlineAtMs, cleanupTimeoutMs) {
|
|
4035
4436
|
const timeoutMs = request.hardLimits.timeoutMs;
|
|
4036
4437
|
const timeoutError = new CandidateExecutionDeadlineError(timeoutMs);
|
|
4037
4438
|
if (Date.now() >= deadlineAtMs) {
|
|
@@ -4086,10 +4487,10 @@ async function runAndStopExecutor(executor, request, traceStore, deadlineAtMs, c
|
|
|
4086
4487
|
}
|
|
4087
4488
|
if (!capture || timedOut) controller.abort(executionError);
|
|
4088
4489
|
const stopReason = timedOut ? "timeout" : capture ? "completed" : "failed";
|
|
4089
|
-
|
|
4490
|
+
const cleanupDeadlineAtMs = Date.now() + cleanupTimeoutMs;
|
|
4090
4491
|
try {
|
|
4091
|
-
stopped = await withinCandidateCleanupDeadline(
|
|
4092
|
-
() => executor.
|
|
4492
|
+
const stopped = await withinCandidateCleanupDeadline(
|
|
4493
|
+
(cleanupSignal) => executor.stop(
|
|
4093
4494
|
{
|
|
4094
4495
|
executionId: request.executionId,
|
|
4095
4496
|
executionPlanDigest: request.executionPlan.value.digest
|
|
@@ -4097,35 +4498,65 @@ async function runAndStopExecutor(executor, request, traceStore, deadlineAtMs, c
|
|
|
4097
4498
|
{
|
|
4098
4499
|
traceStore,
|
|
4099
4500
|
reason: stopReason,
|
|
4100
|
-
signal:
|
|
4101
|
-
deadlineAtMs
|
|
4501
|
+
signal: cleanupSignal,
|
|
4502
|
+
deadlineAtMs: cleanupDeadlineAtMs
|
|
4102
4503
|
}
|
|
4103
4504
|
),
|
|
4104
|
-
|
|
4505
|
+
cleanupDeadlineAtMs,
|
|
4105
4506
|
"candidate process termination"
|
|
4106
4507
|
);
|
|
4107
|
-
|
|
4108
|
-
throw new Error("candidate executor did not acknowledge exact process termination");
|
|
4109
|
-
}
|
|
4508
|
+
sealAgentCandidateExecutorStopAcknowledgement(stopped);
|
|
4110
4509
|
} catch (stopError) {
|
|
4510
|
+
let disposalError2;
|
|
4511
|
+
try {
|
|
4512
|
+
await disposeExecutor(executor, request, cleanupDeadlineAtMs);
|
|
4513
|
+
} catch (error) {
|
|
4514
|
+
disposalError2 = error;
|
|
4515
|
+
}
|
|
4111
4516
|
if (timer) clearTimeout(timer);
|
|
4112
4517
|
controller.abort(stopError);
|
|
4113
4518
|
return {
|
|
4114
4519
|
kind: "error",
|
|
4115
|
-
error: new Error(joinErrors(executionError, stopError)),
|
|
4520
|
+
error: new Error(joinErrors(executionError, stopError, disposalError2)),
|
|
4116
4521
|
...timedOut ? { termination: { kind: "timeout", timeoutMs } } : {},
|
|
4117
4522
|
processStopped: false
|
|
4118
4523
|
};
|
|
4119
4524
|
}
|
|
4120
4525
|
let finalCapture;
|
|
4526
|
+
let finalCaptureError;
|
|
4121
4527
|
try {
|
|
4122
|
-
finalCapture = sealAgentCandidateExecutorFinalCapture(
|
|
4528
|
+
finalCapture = sealAgentCandidateExecutorFinalCapture(
|
|
4529
|
+
await withinCandidateCleanupDeadline(
|
|
4530
|
+
(cleanupSignal) => executor.capture(
|
|
4531
|
+
{
|
|
4532
|
+
executionId: request.executionId,
|
|
4533
|
+
executionPlanDigest: request.executionPlan.value.digest
|
|
4534
|
+
},
|
|
4535
|
+
{
|
|
4536
|
+
traceStore,
|
|
4537
|
+
signal: cleanupSignal
|
|
4538
|
+
}
|
|
4539
|
+
),
|
|
4540
|
+
cleanupDeadlineAtMs,
|
|
4541
|
+
"candidate final evidence capture"
|
|
4542
|
+
),
|
|
4543
|
+
expectedOutcome
|
|
4544
|
+
);
|
|
4123
4545
|
} catch (captureError) {
|
|
4546
|
+
finalCaptureError = captureError;
|
|
4547
|
+
}
|
|
4548
|
+
let disposalError;
|
|
4549
|
+
try {
|
|
4550
|
+
await disposeExecutor(executor, request, cleanupDeadlineAtMs);
|
|
4551
|
+
} catch (disposeError) {
|
|
4552
|
+
disposalError = disposeError;
|
|
4553
|
+
}
|
|
4554
|
+
if (finalCaptureError || disposalError || !finalCapture) {
|
|
4124
4555
|
if (timer) clearTimeout(timer);
|
|
4125
|
-
controller.abort(
|
|
4556
|
+
controller.abort(finalCaptureError ?? disposalError);
|
|
4126
4557
|
return {
|
|
4127
4558
|
kind: "error",
|
|
4128
|
-
error: new Error(joinErrors(executionError,
|
|
4559
|
+
error: new Error(joinErrors(executionError, finalCaptureError, disposalError)),
|
|
4129
4560
|
...timedOut ? { termination: { kind: "timeout", timeoutMs } } : {},
|
|
4130
4561
|
processStopped: true
|
|
4131
4562
|
};
|
|
@@ -4161,6 +4592,25 @@ async function runAndStopExecutor(executor, request, traceStore, deadlineAtMs, c
|
|
|
4161
4592
|
processStopped: true
|
|
4162
4593
|
};
|
|
4163
4594
|
}
|
|
4595
|
+
async function disposeExecutor(executor, request, cleanupDeadlineAtMs) {
|
|
4596
|
+
const dispose = executor.dispose;
|
|
4597
|
+
if (!dispose) return;
|
|
4598
|
+
const disposed = await withinCandidateCleanupDeadline(
|
|
4599
|
+
(cleanupSignal) => dispose.call(
|
|
4600
|
+
executor,
|
|
4601
|
+
{
|
|
4602
|
+
executionId: request.executionId,
|
|
4603
|
+
executionPlanDigest: request.executionPlan.value.digest
|
|
4604
|
+
},
|
|
4605
|
+
{ signal: cleanupSignal }
|
|
4606
|
+
),
|
|
4607
|
+
cleanupDeadlineAtMs,
|
|
4608
|
+
"candidate execution resource disposal"
|
|
4609
|
+
);
|
|
4610
|
+
if (!disposed || disposed.disposed !== true || Object.keys(disposed).some((key) => key !== "disposed")) {
|
|
4611
|
+
throw new Error("candidate executor did not acknowledge resource disposal");
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4164
4614
|
async function failBeforeActivation(prepared, state, error, reason, cleanupTimeoutMs) {
|
|
4165
4615
|
beginPreparedCandidateSettlement(prepared);
|
|
4166
4616
|
const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
|
|
@@ -4215,10 +4665,9 @@ async function failClaimedExecution(prepared, state, lease, claimStore, outputAr
|
|
|
4215
4665
|
claimStore,
|
|
4216
4666
|
lease,
|
|
4217
4667
|
{
|
|
4218
|
-
schemaVersion: 1,
|
|
4219
4668
|
status: "failed",
|
|
4220
4669
|
failureClass,
|
|
4221
|
-
usage: settled.settlement.
|
|
4670
|
+
usage: settled.settlement.usage,
|
|
4222
4671
|
modelSettlement: modelSettlement.artifact,
|
|
4223
4672
|
failureEvidence
|
|
4224
4673
|
},
|
|
@@ -4315,7 +4764,6 @@ async function finishClaim(store, lease, terminal, deadlineAtMs) {
|
|
|
4315
4764
|
}
|
|
4316
4765
|
async function persistFailureEvidence(state, reason, failureClass, termination, outputArtifacts) {
|
|
4317
4766
|
const bytes = canonicalCandidateBytes({
|
|
4318
|
-
schemaVersion: 1,
|
|
4319
4767
|
kind: "agent-candidate-execution-failure",
|
|
4320
4768
|
executionId: state.executionId,
|
|
4321
4769
|
bundleDigest: state.bundle.digest,
|
|
@@ -4347,10 +4795,24 @@ var CandidateExecutionDeadlineError = class extends Error {
|
|
|
4347
4795
|
};
|
|
4348
4796
|
|
|
4349
4797
|
// src/candidate-execution/verify.ts
|
|
4350
|
-
import { agentCandidateBundleSchema
|
|
4798
|
+
import { agentCandidateBundleSchema } from "@tangle-network/agent-interface";
|
|
4351
4799
|
var verifiedCandidateState = /* @__PURE__ */ new WeakMap();
|
|
4800
|
+
var AGENT_CANDIDATE_EXECUTION_SUPPORT = Object.freeze({
|
|
4801
|
+
outcomes: Object.freeze(["workspace", "output"]),
|
|
4802
|
+
code: Object.freeze(["disabled", "no-op", "git-patch"]),
|
|
4803
|
+
memory: Object.freeze(["disabled", "isolated"]),
|
|
4804
|
+
knowledge: true,
|
|
4805
|
+
profile: Object.freeze({
|
|
4806
|
+
mcpTransports: Object.freeze(["stdio"]),
|
|
4807
|
+
remoteMcp: false,
|
|
4808
|
+
tools: false,
|
|
4809
|
+
permissions: false,
|
|
4810
|
+
modes: false,
|
|
4811
|
+
confidential: false
|
|
4812
|
+
})
|
|
4813
|
+
});
|
|
4352
4814
|
async function verifyAgentCandidateBundle(input, ports) {
|
|
4353
|
-
const parsed =
|
|
4815
|
+
const parsed = agentCandidateBundleSchema.parse(input);
|
|
4354
4816
|
const withoutDigest = omitTopLevelDigest(parsed);
|
|
4355
4817
|
const actualDigest = canonicalCandidateDigest(withoutDigest);
|
|
4356
4818
|
if (actualDigest !== parsed.digest) {
|
|
@@ -4358,6 +4820,7 @@ async function verifyAgentCandidateBundle(input, ports) {
|
|
|
4358
4820
|
}
|
|
4359
4821
|
const canonicalBytes = canonicalCandidateBytes(withoutDigest);
|
|
4360
4822
|
verifyBytes(canonicalBytes, parsed.digest, canonicalBytes.byteLength, "candidate bundle");
|
|
4823
|
+
assertCandidateProfileExecutionSupport(parsed.profile);
|
|
4361
4824
|
const artifactBytes = /* @__PURE__ */ new Map();
|
|
4362
4825
|
const readArtifact = async (artifact) => {
|
|
4363
4826
|
const key = artifactCacheKey(artifact);
|
|
@@ -4454,35 +4917,29 @@ function resourceKey(resource) {
|
|
|
4454
4917
|
return canonicalCandidateDigest(resource);
|
|
4455
4918
|
}
|
|
4456
4919
|
|
|
4457
|
-
// src/candidate-execution/prepare.ts
|
|
4458
|
-
import { randomBytes as randomBytes2 } from "crypto";
|
|
4459
|
-
import { lstat as lstat2, readdir as readdir2 } from "fs/promises";
|
|
4460
|
-
import { isAbsolute, posix, relative as relative2, resolve as resolveHostPath } from "path";
|
|
4461
|
-
import {
|
|
4462
|
-
agentCandidateContainerSchema,
|
|
4463
|
-
agentCandidateExecutionLimitsSchema,
|
|
4464
|
-
agentCandidateExecutionPlanEvidenceSchema as agentCandidateExecutionPlanEvidenceSchema2,
|
|
4465
|
-
agentCandidateExecutionPlanMaterialSchema,
|
|
4466
|
-
agentCandidateMaterializationReceiptSchema as agentCandidateMaterializationReceiptSchema2,
|
|
4467
|
-
agentCandidateModelAccessNetworkSchema,
|
|
4468
|
-
agentCandidateWorkspaceSnapshotEvidenceSchema as agentCandidateWorkspaceSnapshotEvidenceSchema2,
|
|
4469
|
-
sha256DigestSchema
|
|
4470
|
-
} from "@tangle-network/agent-interface";
|
|
4471
|
-
import {
|
|
4472
|
-
applyAgentCandidateWorkspacePlan,
|
|
4473
|
-
materializeCandidateProfile
|
|
4474
|
-
} from "@tangle-network/agent-profile-materialize";
|
|
4475
|
-
|
|
4476
4920
|
// src/candidate-execution/knowledge.ts
|
|
4477
|
-
import { mkdtemp as
|
|
4478
|
-
import { tmpdir as
|
|
4479
|
-
import { join as
|
|
4480
|
-
|
|
4921
|
+
import { mkdtemp as mkdtemp3, rm as rm3 } from "fs/promises";
|
|
4922
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
4923
|
+
import { join as join3, posix } from "path";
|
|
4924
|
+
import { hashKnowledgeBase } from "@tangle-network/agent-knowledge";
|
|
4925
|
+
var CANDIDATE_KNOWLEDGE_ROOT_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_ROOT";
|
|
4926
|
+
var CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG";
|
|
4927
|
+
function candidateKnowledgeExecutionPaths(taskRoot, hasRetrievalConfig) {
|
|
4928
|
+
if (!posix.isAbsolute(taskRoot) || posix.normalize(taskRoot) !== taskRoot) {
|
|
4929
|
+
throw new Error("candidate knowledge requires a normalized absolute task root");
|
|
4930
|
+
}
|
|
4931
|
+
const parent = posix.join(taskRoot, ".tangle");
|
|
4932
|
+
return {
|
|
4933
|
+
root: posix.join(parent, "knowledge"),
|
|
4934
|
+
...hasRetrievalConfig ? { retrievalConfig: posix.join(parent, "knowledge-retrieval-config.json") } : {}
|
|
4935
|
+
};
|
|
4936
|
+
}
|
|
4937
|
+
async function prepareAgentCandidateKnowledge(candidate, ports, arm) {
|
|
4481
4938
|
const knowledge = candidate.bundle.knowledge;
|
|
4482
4939
|
if (!knowledge) return void 0;
|
|
4483
4940
|
const archive = await verifiedArtifactBytes(candidate, knowledge.snapshot.archive);
|
|
4484
4941
|
const retrievalConfig = knowledge.retrievalConfig ? await verifiedArtifactBytes(candidate, knowledge.retrievalConfig) : void 0;
|
|
4485
|
-
const root = await
|
|
4942
|
+
const root = await mkdtemp3(join3(tmpdir3(), "agent-candidate-knowledge-"));
|
|
4486
4943
|
try {
|
|
4487
4944
|
await ports.workspaces.materialize({
|
|
4488
4945
|
role: "knowledge",
|
|
@@ -4490,6 +4947,13 @@ async function prepareAgentCandidateKnowledge(candidate, ports) {
|
|
|
4490
4947
|
archive,
|
|
4491
4948
|
destination: root
|
|
4492
4949
|
});
|
|
4950
|
+
const expectedHash = arm === "baseline" ? knowledge.candidate.baseHash : knowledge.candidate.candidateHash;
|
|
4951
|
+
const actualHash = `sha256:${await hashKnowledgeBase(root)}`;
|
|
4952
|
+
if (actualHash !== expectedHash) {
|
|
4953
|
+
throw new Error(
|
|
4954
|
+
`materialized ${arm} knowledge does not match its measured content: expected ${expectedHash}, got ${actualHash}`
|
|
4955
|
+
);
|
|
4956
|
+
}
|
|
4493
4957
|
const files = await readMaterializedWorkspaceFiles(root, knowledge.snapshot.material);
|
|
4494
4958
|
return Object.freeze({
|
|
4495
4959
|
candidate: knowledge.candidate,
|
|
@@ -4502,25 +4966,32 @@ async function prepareAgentCandidateKnowledge(candidate, ports) {
|
|
|
4502
4966
|
...retrievalConfig ? { retrievalConfig: Uint8Array.from(retrievalConfig) } : {}
|
|
4503
4967
|
});
|
|
4504
4968
|
} finally {
|
|
4505
|
-
await
|
|
4969
|
+
await rm3(root, { recursive: true, force: true });
|
|
4506
4970
|
}
|
|
4507
4971
|
}
|
|
4508
4972
|
|
|
4509
4973
|
// src/candidate-execution/prepare.ts
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4974
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
4975
|
+
import { lstat as lstat2, readdir as readdir2 } from "fs/promises";
|
|
4976
|
+
import { isAbsolute, posix as posix2, relative as relative2, resolve as resolveHostPath } from "path";
|
|
4977
|
+
import {
|
|
4978
|
+
agentCandidateBenchmarkSuiteSchema as agentCandidateBenchmarkSuiteSchema2,
|
|
4979
|
+
agentCandidateBenchmarkTaskSchema as agentCandidateBenchmarkTaskSchema2,
|
|
4980
|
+
agentCandidateContainerSchema,
|
|
4981
|
+
agentCandidateExecutionLimitsSchema,
|
|
4982
|
+
agentCandidateExecutionPlanEvidenceSchema as agentCandidateExecutionPlanEvidenceSchema2,
|
|
4983
|
+
agentCandidateExecutionPlanMaterialSchema,
|
|
4984
|
+
agentCandidateMaterializationReceiptSchema as agentCandidateMaterializationReceiptSchema2,
|
|
4985
|
+
agentCandidateModelAccessNetworkSchema,
|
|
4986
|
+
agentCandidateRunCellSchema,
|
|
4987
|
+
agentCandidateTaskOutcomeSpecSchema,
|
|
4988
|
+
agentCandidateWorkspaceSnapshotEvidenceSchema as agentCandidateWorkspaceSnapshotEvidenceSchema3,
|
|
4989
|
+
sha256DigestSchema
|
|
4990
|
+
} from "@tangle-network/agent-interface";
|
|
4991
|
+
import {
|
|
4992
|
+
applyAgentCandidateWorkspacePlan,
|
|
4993
|
+
materializeCandidateProfile
|
|
4994
|
+
} from "@tangle-network/agent-profile-materialize";
|
|
4524
4995
|
var MIN_RESERVATION_TTL_MS = 15 * 6e4;
|
|
4525
4996
|
var PREPARED_HOLD_MARGIN_MS = 5 * 6e4;
|
|
4526
4997
|
async function prepareAgentCandidateExecution(candidate, task, ports, options = {}) {
|
|
@@ -4528,12 +4999,23 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4528
4999
|
const verifiedState = getVerifiedCandidateState(candidate);
|
|
4529
5000
|
assertSameVerificationPorts(verifiedState.ports, ports);
|
|
4530
5001
|
const bundle = candidate.bundle;
|
|
4531
|
-
|
|
4532
|
-
|
|
5002
|
+
if (task.runCell.bundleDigest !== bundle.digest) {
|
|
5003
|
+
throw new Error("candidate experiment cell does not bind the verified bundle");
|
|
5004
|
+
}
|
|
5005
|
+
const benchmarkTask = task.task;
|
|
5006
|
+
const attempt = {
|
|
5007
|
+
number: task.runCell.attempt,
|
|
5008
|
+
maxAttempts: benchmarkTask.attempt.maxAttempts,
|
|
5009
|
+
retryPolicy: benchmarkTask.attempt.retryPolicy
|
|
5010
|
+
};
|
|
5011
|
+
const harness = candidateMaterializerHarness(bundle.execution.harness);
|
|
4533
5012
|
assertTaskInput(task, bundle.execution.instructionDelivery);
|
|
4534
|
-
const resultTimeoutMs = candidateResultTimeout(
|
|
5013
|
+
const resultTimeoutMs = candidateResultTimeout(
|
|
5014
|
+
options.resultTimeoutMs,
|
|
5015
|
+
benchmarkTask.limits.timeoutMs
|
|
5016
|
+
);
|
|
4535
5017
|
const ownerWindowMs = candidateExecutionOwnerWindowMs(
|
|
4536
|
-
|
|
5018
|
+
benchmarkTask.limits.timeoutMs,
|
|
4537
5019
|
cleanupTimeoutMs,
|
|
4538
5020
|
resultTimeoutMs
|
|
4539
5021
|
);
|
|
@@ -4542,22 +5024,26 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4542
5024
|
throw new Error("candidate reservation window exceeds the supported timer range");
|
|
4543
5025
|
}
|
|
4544
5026
|
assertDisjointHostStagingRoots(task);
|
|
4545
|
-
const instructionBytes = Buffer.from(
|
|
4546
|
-
const
|
|
4547
|
-
|
|
5027
|
+
const instructionBytes = Buffer.from(benchmarkTask.instruction, "utf8");
|
|
5028
|
+
const taskArtifacts = await verifyWorkspaceSnapshotArtifacts(
|
|
5029
|
+
benchmarkTask.workspace,
|
|
5030
|
+
ports.artifacts
|
|
5031
|
+
);
|
|
4548
5032
|
await ports.workspaces.materialize({
|
|
4549
5033
|
role: "task",
|
|
4550
|
-
snapshot:
|
|
5034
|
+
snapshot: benchmarkTask.workspace,
|
|
4551
5035
|
archive: taskArtifacts.archive,
|
|
4552
5036
|
destination: task.stagingRoots.taskRoot
|
|
4553
5037
|
});
|
|
4554
|
-
await verifyMaterializedWorkspace(task.stagingRoots.taskRoot,
|
|
5038
|
+
await verifyMaterializedWorkspace(task.stagingRoots.taskRoot, benchmarkTask.workspace.material, {
|
|
4555
5039
|
ignoredProtectedRootEntries: [".git", ".sidecar"]
|
|
4556
5040
|
});
|
|
4557
|
-
|
|
5041
|
+
if (benchmarkTask.repository) {
|
|
5042
|
+
await verifyTaskCheckout(task.stagingRoots.taskRoot, benchmarkTask.repository);
|
|
5043
|
+
}
|
|
4558
5044
|
const taskExecutorFiles = await readMaterializedWorkspaceFiles(
|
|
4559
5045
|
task.stagingRoots.taskRoot,
|
|
4560
|
-
|
|
5046
|
+
benchmarkTask.workspace.material,
|
|
4561
5047
|
{ ignoredProtectedRootEntries: [".git", ".sidecar"] }
|
|
4562
5048
|
);
|
|
4563
5049
|
let candidateArchive;
|
|
@@ -4595,30 +5081,33 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4595
5081
|
);
|
|
4596
5082
|
await verifyMaterializedProfileWorkspace(
|
|
4597
5083
|
task.stagingRoots.profileRoot,
|
|
4598
|
-
profileApplication.profilePlan.material
|
|
5084
|
+
profileApplication.profileActivation.profilePlan.material
|
|
4599
5085
|
);
|
|
4600
5086
|
const profilePlanBytes = await readVerifiedArtifact(
|
|
4601
|
-
profileApplication.profilePlan.artifact,
|
|
5087
|
+
profileApplication.profileActivation.profilePlan.artifact,
|
|
4602
5088
|
ports.artifacts
|
|
4603
5089
|
);
|
|
4604
5090
|
if (!Buffer.from(profilePlanBytes).equals(
|
|
4605
|
-
Buffer.from(
|
|
5091
|
+
Buffer.from(
|
|
5092
|
+
canonicalCandidateBytes(profileApplication.profileActivation.profilePlan.material)
|
|
5093
|
+
)
|
|
4606
5094
|
)) {
|
|
4607
5095
|
throw new Error("profile materializer did not capture exact canonical plan bytes");
|
|
4608
5096
|
}
|
|
5097
|
+
const profileActivation = profileApplication.profileActivation;
|
|
4609
5098
|
const container = await resolveContainer(candidate, task, ports);
|
|
4610
5099
|
const resolvedModel = await resolveModel(candidate, task, ports);
|
|
4611
|
-
const preparationId = `candidate-preparation
|
|
5100
|
+
const preparationId = `candidate-preparation.${randomBytes3(32).toString("base64url")}`;
|
|
4612
5101
|
const reservationExpiresAtMs = Date.now() + Math.max(MIN_RESERVATION_TTL_MS, reservationWindowMs);
|
|
4613
5102
|
const modelReservation = await withinCandidateCleanupDeadline(
|
|
4614
5103
|
() => ports.models.reserveGrant({
|
|
4615
5104
|
executionId: task.executionId,
|
|
4616
5105
|
preparationId,
|
|
4617
5106
|
expiresAtMs: reservationExpiresAtMs,
|
|
4618
|
-
attempt
|
|
5107
|
+
attempt,
|
|
4619
5108
|
bundleDigest: bundle.digest,
|
|
4620
5109
|
resolved: resolvedModel,
|
|
4621
|
-
limits: modelLimits2(
|
|
5110
|
+
limits: modelLimits2(benchmarkTask.limits)
|
|
4622
5111
|
}),
|
|
4623
5112
|
candidateCleanupDeadline(cleanupTimeoutMs),
|
|
4624
5113
|
"protected model reservation"
|
|
@@ -4627,7 +5116,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4627
5116
|
try {
|
|
4628
5117
|
validateProtectedModelReservation(
|
|
4629
5118
|
modelReservation,
|
|
4630
|
-
|
|
5119
|
+
benchmarkTask.limits,
|
|
4631
5120
|
preparationId,
|
|
4632
5121
|
reservationExpiresAtMs
|
|
4633
5122
|
);
|
|
@@ -4640,7 +5129,11 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4640
5129
|
cleanupTimeoutMs
|
|
4641
5130
|
);
|
|
4642
5131
|
const memory = preparedMemory.value;
|
|
4643
|
-
const knowledge = await prepareAgentCandidateKnowledge(candidate, ports);
|
|
5132
|
+
const knowledge = await prepareAgentCandidateKnowledge(candidate, ports, task.runCell.arm);
|
|
5133
|
+
const knowledgePaths = knowledge ? candidateKnowledgeExecutionPaths(
|
|
5134
|
+
task.executionRoots.taskRoot,
|
|
5135
|
+
knowledge.retrievalConfig !== void 0
|
|
5136
|
+
) : void 0;
|
|
4644
5137
|
const baseLaunch = buildLaunch(candidate, task, profileApplication.flags);
|
|
4645
5138
|
const publicEnv = mergePublicEnvironment(
|
|
4646
5139
|
bundle.execution.env ?? {},
|
|
@@ -4650,30 +5143,25 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4650
5143
|
kind: "public",
|
|
4651
5144
|
value: bundle.execution.instructionDelivery.path
|
|
4652
5145
|
}
|
|
5146
|
+
} : {},
|
|
5147
|
+
knowledgePaths ? {
|
|
5148
|
+
[CANDIDATE_KNOWLEDGE_ROOT_ENV]: {
|
|
5149
|
+
kind: "public",
|
|
5150
|
+
value: knowledgePaths.root
|
|
5151
|
+
},
|
|
5152
|
+
...knowledgePaths.retrievalConfig ? {
|
|
5153
|
+
[CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV]: {
|
|
5154
|
+
kind: "public",
|
|
5155
|
+
value: knowledgePaths.retrievalConfig
|
|
5156
|
+
}
|
|
5157
|
+
} : {}
|
|
4653
5158
|
} : {}
|
|
4654
5159
|
);
|
|
4655
|
-
const routes = modelRoutes(bundle.profile,
|
|
5160
|
+
const routes = modelRoutes(bundle.profile, benchmarkTask.model.requested);
|
|
4656
5161
|
const executionMaterial = {
|
|
4657
|
-
schemaVersion: 2,
|
|
4658
5162
|
kind: "agent-candidate-execution-plan-material",
|
|
4659
|
-
|
|
5163
|
+
runCell: task.runCell,
|
|
4660
5164
|
executionId: task.executionId,
|
|
4661
|
-
attempt: task.attempt,
|
|
4662
|
-
task: {
|
|
4663
|
-
benchmark: task.benchmark,
|
|
4664
|
-
benchmarkVersion: task.benchmarkVersion,
|
|
4665
|
-
taskId: task.taskId,
|
|
4666
|
-
splitDigest: task.splitDigest,
|
|
4667
|
-
instruction: {
|
|
4668
|
-
encoding: "utf8",
|
|
4669
|
-
sha256: instructionDigest,
|
|
4670
|
-
byteLength: instructionBytes.byteLength,
|
|
4671
|
-
delivery: bundle.execution.instructionDelivery
|
|
4672
|
-
},
|
|
4673
|
-
repository: task.repository,
|
|
4674
|
-
outcome: { kind: "workspace" },
|
|
4675
|
-
workspace: task.workspace
|
|
4676
|
-
},
|
|
4677
5165
|
workspaces: {
|
|
4678
5166
|
taskRoot: task.executionRoots.taskRoot,
|
|
4679
5167
|
...task.executionRoots.candidateRoot ? { candidateRoot: task.executionRoots.candidateRoot } : {}
|
|
@@ -4683,6 +5171,8 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4683
5171
|
profile: profileApplication.application,
|
|
4684
5172
|
harness: bundle.execution.harness,
|
|
4685
5173
|
harnessVersion: bundle.execution.harnessVersion,
|
|
5174
|
+
instructionDelivery: bundle.execution.instructionDelivery,
|
|
5175
|
+
limits: benchmarkTask.limits,
|
|
4686
5176
|
container,
|
|
4687
5177
|
model: {
|
|
4688
5178
|
policy: "single",
|
|
@@ -4694,7 +5184,6 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4694
5184
|
},
|
|
4695
5185
|
routes
|
|
4696
5186
|
},
|
|
4697
|
-
grader: task.grader,
|
|
4698
5187
|
launch: {
|
|
4699
5188
|
executable: baseLaunch.executable,
|
|
4700
5189
|
args: baseLaunch.args,
|
|
@@ -4703,7 +5192,6 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4703
5192
|
},
|
|
4704
5193
|
...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
|
|
4705
5194
|
memory,
|
|
4706
|
-
limits: task.limits,
|
|
4707
5195
|
network: { mode: "disabled" }
|
|
4708
5196
|
};
|
|
4709
5197
|
agentCandidateExecutionPlanMaterialSchema.parse(executionMaterial);
|
|
@@ -4713,7 +5201,6 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4713
5201
|
throw new Error("execution plan canonical serializers disagree");
|
|
4714
5202
|
}
|
|
4715
5203
|
const executionPlan = agentCandidateExecutionPlanEvidenceSchema2.parse({
|
|
4716
|
-
schemaVersion: 2,
|
|
4717
5204
|
kind: "agent-candidate-execution-plan",
|
|
4718
5205
|
digest: executionDigest,
|
|
4719
5206
|
material: executionMaterial,
|
|
@@ -4722,11 +5209,24 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4722
5209
|
const entrypoint = candidateEntrypointReceipt(candidate);
|
|
4723
5210
|
const materializationReceipt = canonicalCandidateDocument(
|
|
4724
5211
|
{
|
|
4725
|
-
schemaVersion: 2,
|
|
4726
5212
|
kind: "agent-candidate-materialization",
|
|
4727
5213
|
digestAlgorithm: "rfc8785-sha256",
|
|
4728
5214
|
bundleDigest: bundle.digest,
|
|
4729
|
-
|
|
5215
|
+
benchmark: {
|
|
5216
|
+
suite: {
|
|
5217
|
+
digest: task.benchmarkSuite.digest,
|
|
5218
|
+
material: embeddedCandidateArtifact(
|
|
5219
|
+
canonicalCandidateBytes(omitTopLevelDigest(task.benchmarkSuite))
|
|
5220
|
+
)
|
|
5221
|
+
},
|
|
5222
|
+
task: {
|
|
5223
|
+
digest: benchmarkTask.digest,
|
|
5224
|
+
material: embeddedCandidateArtifact(
|
|
5225
|
+
canonicalCandidateBytes(omitTopLevelDigest(benchmarkTask))
|
|
5226
|
+
)
|
|
5227
|
+
}
|
|
5228
|
+
},
|
|
5229
|
+
profileActivation,
|
|
4730
5230
|
executionPlan,
|
|
4731
5231
|
...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
|
|
4732
5232
|
codeKind: bundle.code.kind,
|
|
@@ -4740,7 +5240,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4740
5240
|
}
|
|
4741
5241
|
);
|
|
4742
5242
|
agentCandidateMaterializationReceiptSchema2.parse(materializationReceipt.value);
|
|
4743
|
-
const traceRunId = `${task.executionId}:attempt-${
|
|
5243
|
+
const traceRunId = `${task.executionId}:attempt-${attempt.number}:${canonicalCandidateDigest({ preparationId }).slice(7, 23)}`;
|
|
4744
5244
|
const traceTags = {
|
|
4745
5245
|
[CANDIDATE_TRACE_TAGS.executionId]: task.executionId,
|
|
4746
5246
|
[CANDIDATE_TRACE_TAGS.bundleDigest]: bundle.digest,
|
|
@@ -4758,16 +5258,19 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4758
5258
|
return createPreparedCandidateExecution({
|
|
4759
5259
|
ports,
|
|
4760
5260
|
bundle,
|
|
5261
|
+
benchmarkSuite: task.benchmarkSuite,
|
|
5262
|
+
benchmarkTask,
|
|
4761
5263
|
executionId: task.executionId,
|
|
4762
5264
|
roots: {
|
|
4763
5265
|
execution: { ...task.executionRoots },
|
|
4764
5266
|
staging: { ...task.stagingRoots }
|
|
4765
5267
|
},
|
|
4766
5268
|
profilePlan: {
|
|
4767
|
-
value: profileApplication.profilePlan,
|
|
5269
|
+
value: profileApplication.profileActivation.profilePlan,
|
|
4768
5270
|
bytes: profilePlanBytes,
|
|
4769
5271
|
written: [...profileApplication.application.mountPaths]
|
|
4770
5272
|
},
|
|
5273
|
+
profileActivation,
|
|
4771
5274
|
executionPlan: { value: executionPlan, bytes: executionBytes },
|
|
4772
5275
|
materializationReceipt,
|
|
4773
5276
|
launch: {
|
|
@@ -4798,7 +5301,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
4798
5301
|
...candidateExecutorFiles ? { candidateFiles: candidateExecutorFiles } : {},
|
|
4799
5302
|
profileFiles: exactProfileExecutorFiles(
|
|
4800
5303
|
profileWorkspacePlan.files,
|
|
4801
|
-
profileApplication.profilePlan.material.files
|
|
5304
|
+
profileApplication.profileActivation.profilePlan.material.files
|
|
4802
5305
|
)
|
|
4803
5306
|
},
|
|
4804
5307
|
...preparedMemory.accessDigest && preparedMemory.value.mode === "isolated" ? {
|
|
@@ -4883,34 +5386,54 @@ function assertSameVerificationPorts(verified, execution) {
|
|
|
4883
5386
|
}
|
|
4884
5387
|
}
|
|
4885
5388
|
function assertTaskInput(task, delivery) {
|
|
5389
|
+
const benchmarkTask = agentCandidateBenchmarkTaskSchema2.parse(task.task);
|
|
5390
|
+
const benchmarkSuite = agentCandidateBenchmarkSuiteSchema2.parse(task.benchmarkSuite);
|
|
5391
|
+
const runCell = agentCandidateRunCellSchema.parse(task.runCell);
|
|
4886
5392
|
const requiredStrings = [
|
|
4887
5393
|
["executionId", task.executionId],
|
|
4888
|
-
["benchmark",
|
|
4889
|
-
["benchmarkVersion",
|
|
4890
|
-
["taskId",
|
|
4891
|
-
["repository identity", task.repository.identity],
|
|
4892
|
-
["repository root identity", task.repository.rootIdentity]
|
|
5394
|
+
["benchmark", benchmarkTask.benchmark.name],
|
|
5395
|
+
["benchmarkVersion", benchmarkTask.benchmark.version],
|
|
5396
|
+
["taskId", benchmarkTask.scenario.id]
|
|
4893
5397
|
];
|
|
5398
|
+
if (benchmarkTask.outcome.kind === "workspace" && !benchmarkTask.repository) {
|
|
5399
|
+
throw new Error("workspace task outcome requires repository identity");
|
|
5400
|
+
}
|
|
5401
|
+
if (benchmarkTask.repository) {
|
|
5402
|
+
requiredStrings.push(
|
|
5403
|
+
["repository identity", benchmarkTask.repository.identity],
|
|
5404
|
+
["repository root identity", benchmarkTask.repository.rootIdentity]
|
|
5405
|
+
);
|
|
5406
|
+
}
|
|
4894
5407
|
for (const [name, value] of requiredStrings) {
|
|
4895
5408
|
if (!value.trim()) throw new Error(`${name} must be non-empty`);
|
|
4896
5409
|
}
|
|
4897
5410
|
if (!/^[A-Za-z0-9._:-]{1,200}$/.test(task.executionId)) {
|
|
4898
5411
|
throw new Error("executionId must be a stable filesystem-neutral identifier");
|
|
4899
5412
|
}
|
|
4900
|
-
if (!
|
|
5413
|
+
if (!benchmarkTask.instruction || !isWellFormedUnicode(benchmarkTask.instruction)) {
|
|
4901
5414
|
throw new Error("task instruction must be non-empty well-formed Unicode");
|
|
4902
5415
|
}
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
agentCandidateExecutionLimitsSchema.parse(task.limits);
|
|
4906
|
-
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(task.repository.baseCommit)) {
|
|
4907
|
-
throw new Error("task repository base commit is not a full Git object id");
|
|
5416
|
+
if (canonicalCandidateDigest(omitTopLevelDigest(benchmarkTask)) !== benchmarkTask.digest || canonicalCandidateDigest(omitTopLevelDigest(benchmarkSuite)) !== benchmarkSuite.digest || canonicalCandidateDigest(omitTopLevelDigest(runCell)) !== runCell.digest) {
|
|
5417
|
+
throw new Error("candidate experiment cell contains an invalid content digest");
|
|
4908
5418
|
}
|
|
4909
|
-
|
|
4910
|
-
|
|
5419
|
+
const cellIndex = runCell.taskIndex * benchmarkSuite.reps + runCell.repetition;
|
|
5420
|
+
if (runCell.suiteDigest !== benchmarkSuite.digest || runCell.taskDigest !== benchmarkTask.digest || benchmarkSuite.taskDigests[runCell.taskIndex] !== benchmarkTask.digest || runCell.repetition >= benchmarkSuite.reps || benchmarkSuite.seeds[cellIndex] !== runCell.seed || runCell.attempt > benchmarkTask.attempt.maxAttempts) {
|
|
5421
|
+
throw new Error("candidate experiment cell does not match its signed suite and task");
|
|
4911
5422
|
}
|
|
4912
|
-
|
|
4913
|
-
|
|
5423
|
+
sha256DigestSchema.parse(benchmarkTask.benchmark.splitDigest);
|
|
5424
|
+
agentCandidateTaskOutcomeSpecSchema.parse(benchmarkTask.outcome);
|
|
5425
|
+
agentCandidateWorkspaceSnapshotEvidenceSchema3.parse(benchmarkTask.workspace);
|
|
5426
|
+
agentCandidateExecutionLimitsSchema.parse(benchmarkTask.limits);
|
|
5427
|
+
if (benchmarkTask.repository) {
|
|
5428
|
+
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(benchmarkTask.repository.baseCommit)) {
|
|
5429
|
+
throw new Error("task repository base commit is not a full Git object id");
|
|
5430
|
+
}
|
|
5431
|
+
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(benchmarkTask.repository.baseTree)) {
|
|
5432
|
+
throw new Error("task repository base tree is not a full Git object id");
|
|
5433
|
+
}
|
|
5434
|
+
if (benchmarkTask.repository.baseCommit.length !== benchmarkTask.repository.baseTree.length) {
|
|
5435
|
+
throw new Error("task repository Git object formats disagree");
|
|
5436
|
+
}
|
|
4914
5437
|
}
|
|
4915
5438
|
for (const [name, root] of [
|
|
4916
5439
|
["execution task root", task.executionRoots.taskRoot],
|
|
@@ -4920,34 +5443,36 @@ function assertTaskInput(task, delivery) {
|
|
|
4920
5443
|
["staging profile root", task.stagingRoots.profileRoot]
|
|
4921
5444
|
]) {
|
|
4922
5445
|
if (root === void 0) continue;
|
|
4923
|
-
const canonical = name.startsWith("execution") ?
|
|
5446
|
+
const canonical = name.startsWith("execution") ? posix2.isAbsolute(root) && posix2.normalize(root) === root : isAbsolute(root) && resolveHostPath(root) === root;
|
|
4924
5447
|
if (!canonical) throw new Error(`${name} must be a canonical absolute path`);
|
|
4925
5448
|
}
|
|
4926
|
-
if (!Number.isInteger(
|
|
5449
|
+
if (!Number.isInteger(runCell.attempt) || !Number.isInteger(benchmarkTask.attempt.maxAttempts) || runCell.attempt < 1 || runCell.attempt > benchmarkTask.attempt.maxAttempts || benchmarkTask.attempt.retryPolicy === "none" && benchmarkTask.attempt.maxAttempts !== 1) {
|
|
4927
5450
|
throw new Error("task attempt policy is invalid");
|
|
4928
5451
|
}
|
|
4929
|
-
const limits =
|
|
5452
|
+
const limits = benchmarkTask.limits;
|
|
4930
5453
|
if (!Number.isInteger(limits.timeoutMs) || limits.timeoutMs <= 0 || limits.timeoutMs > MAX_CANDIDATE_TIMER_INTERVAL_MS || !Number.isInteger(limits.maxSteps) || limits.maxSteps <= 0 || !Number.isInteger(limits.maxModelCalls) || limits.maxModelCalls < 0 || !Number.isInteger(limits.maxInputTokens) || limits.maxInputTokens < 0 || !Number.isInteger(limits.maxOutputTokens) || limits.maxOutputTokens < 0 || !Number.isFinite(limits.maxCostUsd) || limits.maxCostUsd < 0) {
|
|
4931
5454
|
throw new Error("task execution limits are invalid");
|
|
4932
5455
|
}
|
|
4933
5456
|
usdToNanos(limits.maxCostUsd, "task maxCostUsd");
|
|
4934
|
-
if (!
|
|
4935
|
-
|
|
5457
|
+
if (!benchmarkTask.model.requested.trim()) {
|
|
5458
|
+
throw new Error("evaluator model request must be non-empty");
|
|
5459
|
+
}
|
|
5460
|
+
if (!benchmarkTask.grader.name.trim() || !benchmarkTask.grader.version.trim()) {
|
|
4936
5461
|
throw new Error("evaluator benchmark grader identity must be non-empty");
|
|
4937
5462
|
}
|
|
4938
|
-
if (!Number.isInteger(
|
|
5463
|
+
if (!Number.isInteger(benchmarkTask.grader.artifact.byteLength) || benchmarkTask.grader.artifact.byteLength <= 0) {
|
|
4939
5464
|
throw new Error("evaluator benchmark grader artifact must be non-empty");
|
|
4940
5465
|
}
|
|
4941
|
-
sha256DigestSchema.parse(
|
|
4942
|
-
if (
|
|
4943
|
-
if (
|
|
5466
|
+
sha256DigestSchema.parse(benchmarkTask.grader.artifact.sha256);
|
|
5467
|
+
if (benchmarkTask.evaluatorTaskContainer) {
|
|
5468
|
+
if (benchmarkTask.evaluatorTaskContainer.source !== "evaluator-task-container" || !benchmarkTask.evaluatorTaskContainer.image.trim() || !benchmarkTask.evaluatorTaskContainer.platform.os.trim() || !benchmarkTask.evaluatorTaskContainer.platform.architecture.trim()) {
|
|
4944
5469
|
throw new Error("evaluator task container evidence is incomplete");
|
|
4945
5470
|
}
|
|
4946
|
-
sha256DigestSchema.parse(
|
|
4947
|
-
sha256DigestSchema.parse(
|
|
5471
|
+
sha256DigestSchema.parse(benchmarkTask.evaluatorTaskContainer.indexDigest);
|
|
5472
|
+
sha256DigestSchema.parse(benchmarkTask.evaluatorTaskContainer.manifestDigest);
|
|
4948
5473
|
agentCandidateContainerSchema.parse({
|
|
4949
|
-
image:
|
|
4950
|
-
indexDigest:
|
|
5474
|
+
image: benchmarkTask.evaluatorTaskContainer.image,
|
|
5475
|
+
indexDigest: benchmarkTask.evaluatorTaskContainer.indexDigest
|
|
4951
5476
|
});
|
|
4952
5477
|
}
|
|
4953
5478
|
if (delivery.kind === "utf8-file") {
|
|
@@ -4957,8 +5482,8 @@ function assertTaskInput(task, delivery) {
|
|
|
4957
5482
|
}
|
|
4958
5483
|
}
|
|
4959
5484
|
function executionPathsOverlap(left, right) {
|
|
4960
|
-
const a =
|
|
4961
|
-
const b =
|
|
5485
|
+
const a = posix2.normalize(left);
|
|
5486
|
+
const b = posix2.normalize(right);
|
|
4962
5487
|
return a === b || b.startsWith(a === "/" ? "/" : `${a}/`) || a.startsWith(b === "/" ? "/" : `${b}/`);
|
|
4963
5488
|
}
|
|
4964
5489
|
function assertDisjointHostStagingRoots(task) {
|
|
@@ -4990,51 +5515,45 @@ async function assertEmptyDirectory(path) {
|
|
|
4990
5515
|
throw new Error("profile staging root must be empty before materialization");
|
|
4991
5516
|
}
|
|
4992
5517
|
}
|
|
4993
|
-
function materializerHarness(harness) {
|
|
4994
|
-
if (!MATERIALIZER_HARNESSES.has(harness)) {
|
|
4995
|
-
throw new Error(
|
|
4996
|
-
`sealed candidate profile materialization is unsupported for harness ${harness}`
|
|
4997
|
-
);
|
|
4998
|
-
}
|
|
4999
|
-
return harness;
|
|
5000
|
-
}
|
|
5001
5518
|
async function resolveContainer(candidate, task, ports) {
|
|
5002
5519
|
const environment = candidate.bundle.execution.environment;
|
|
5520
|
+
const evaluatorTaskContainer = task.task.evaluatorTaskContainer;
|
|
5003
5521
|
const pinned = environment.kind === "pinned-container" ? environment.container : void 0;
|
|
5004
|
-
if (environment.kind === "evaluator-task-container" && !
|
|
5522
|
+
if (environment.kind === "evaluator-task-container" && !evaluatorTaskContainer) {
|
|
5005
5523
|
throw new Error("evaluator-task-container candidate requires an evaluator-owned task image");
|
|
5006
5524
|
}
|
|
5007
|
-
if (environment.kind === "pinned-container" &&
|
|
5525
|
+
if (environment.kind === "pinned-container" && evaluatorTaskContainer) {
|
|
5008
5526
|
throw new Error("pinned candidate containers cannot be replaced by a task image");
|
|
5009
5527
|
}
|
|
5010
5528
|
const resolved = await ports.containers.resolve({
|
|
5011
5529
|
candidate: pinned,
|
|
5012
|
-
evaluatorTaskContainer
|
|
5530
|
+
evaluatorTaskContainer
|
|
5013
5531
|
});
|
|
5014
5532
|
if (resolved.source !== environment.kind) throw new Error("resolved container source drifted");
|
|
5015
5533
|
if (pinned && (resolved.image !== pinned.image || resolved.indexDigest !== pinned.indexDigest)) {
|
|
5016
5534
|
throw new Error("resolved pinned container does not match the candidate image index");
|
|
5017
5535
|
}
|
|
5018
|
-
if (
|
|
5536
|
+
if (evaluatorTaskContainer && canonicalCandidateDigest(resolved) !== canonicalCandidateDigest(evaluatorTaskContainer)) {
|
|
5019
5537
|
throw new Error("resolved task container does not match evaluator-owned image evidence");
|
|
5020
5538
|
}
|
|
5021
5539
|
return resolved;
|
|
5022
5540
|
}
|
|
5023
5541
|
async function resolveModel(candidate, task, ports) {
|
|
5024
5542
|
const hints = candidate.bundle.profile.model;
|
|
5025
|
-
|
|
5543
|
+
const expected = task.task.model;
|
|
5544
|
+
if (hints?.default !== void 0 && hints.default !== expected.requested) {
|
|
5026
5545
|
throw new Error("candidate model preference conflicts with the evaluator-owned model");
|
|
5027
5546
|
}
|
|
5028
|
-
if (hints?.reasoningEffort !== void 0 && hints.reasoningEffort !==
|
|
5547
|
+
if (hints?.reasoningEffort !== void 0 && hints.reasoningEffort !== expected.reasoningEffort) {
|
|
5029
5548
|
throw new Error("candidate reasoning effort conflicts with the evaluator-owned effort");
|
|
5030
5549
|
}
|
|
5031
5550
|
const resolved = await ports.models.resolve({
|
|
5032
|
-
requested:
|
|
5551
|
+
requested: expected.requested,
|
|
5033
5552
|
harness: candidate.bundle.execution.harness,
|
|
5034
|
-
reasoningEffort:
|
|
5553
|
+
reasoningEffort: expected.reasoningEffort
|
|
5035
5554
|
});
|
|
5036
|
-
if (resolved
|
|
5037
|
-
throw new Error("model resolver drifted from the
|
|
5555
|
+
if (canonicalCandidateDigest(resolved) !== canonicalCandidateDigest(expected)) {
|
|
5556
|
+
throw new Error("model resolver drifted from the signed benchmark model");
|
|
5038
5557
|
}
|
|
5039
5558
|
return resolved;
|
|
5040
5559
|
}
|
|
@@ -5043,7 +5562,7 @@ async function prepareMemory(candidate, task, ports, preparationId, expiresAtMs,
|
|
|
5043
5562
|
if (policy.mode === "disabled") return { value: { mode: "disabled" } };
|
|
5044
5563
|
const seed = policy.seed ? await verifiedArtifactBytes(candidate, policy.seed) : void 0;
|
|
5045
5564
|
const executionSegment = canonicalCandidateDigest({ executionId: task.executionId }).slice(7);
|
|
5046
|
-
const taskSegment = canonicalCandidateDigest({
|
|
5565
|
+
const taskSegment = canonicalCandidateDigest({ taskDigest: task.task.digest }).slice(7);
|
|
5047
5566
|
const preparationSegment = canonicalCandidateDigest({ preparationId }).slice(7, 23);
|
|
5048
5567
|
const effectiveNamespace = `candidate/${candidate.bundle.digest.slice(7, 23)}/${executionSegment}/${taskSegment}/${preparationSegment}`;
|
|
5049
5568
|
const reset = await withinCandidateCleanupDeadline(
|
|
@@ -5110,7 +5629,7 @@ function buildLaunch(candidate, task, profileFlags) {
|
|
|
5110
5629
|
}
|
|
5111
5630
|
const candidateRoot = task.executionRoots.candidateRoot;
|
|
5112
5631
|
if (!candidateRoot) throw new Error("candidate entrypoint requires a container candidate root");
|
|
5113
|
-
const entrypoint =
|
|
5632
|
+
const entrypoint = posix2.join(candidateRoot, launch.entrypoint);
|
|
5114
5633
|
const candidateArgs = launch.args ?? [];
|
|
5115
5634
|
if (launch.interpreter) {
|
|
5116
5635
|
return {
|
|
@@ -5160,7 +5679,7 @@ function candidateEntrypointReceipt(candidate) {
|
|
|
5160
5679
|
function absoluteExecutionCwd(cwd, roots) {
|
|
5161
5680
|
const root = cwd.workspace === "task" ? roots.taskRoot : roots.candidateRoot;
|
|
5162
5681
|
if (!root) throw new Error("candidate cwd is missing its execution workspace root");
|
|
5163
|
-
const absolute = cwd.path === "." ? root :
|
|
5682
|
+
const absolute = cwd.path === "." ? root : posix2.join(root, cwd.path);
|
|
5164
5683
|
if (absolute !== root && !absolute.startsWith(`${root}/`)) {
|
|
5165
5684
|
throw new Error("candidate cwd escapes its execution workspace");
|
|
5166
5685
|
}
|
|
@@ -5236,20 +5755,20 @@ export {
|
|
|
5236
5755
|
canonicalCandidateDigest,
|
|
5237
5756
|
immutableCandidateValue,
|
|
5238
5757
|
canonicalCandidateDocument,
|
|
5758
|
+
verifyCanonicalCandidateDocument,
|
|
5239
5759
|
embeddedCandidateArtifact,
|
|
5240
5760
|
omitTopLevelDigest,
|
|
5241
5761
|
deepFreezeCandidate,
|
|
5242
|
-
|
|
5762
|
+
candidateMaterializerHarness,
|
|
5763
|
+
createAgentCandidateProfileActivation,
|
|
5764
|
+
parseAgentCandidateProfileActivation,
|
|
5243
5765
|
freezeGenericAgentCandidateProfile,
|
|
5244
5766
|
assertCandidateProfileBinding,
|
|
5245
5767
|
parseExactAgentProfile,
|
|
5246
5768
|
parseExactAgentProfileDiff,
|
|
5247
5769
|
applyExactAgentProfileDiff,
|
|
5248
5770
|
parseExactCandidateProfile,
|
|
5249
|
-
|
|
5250
|
-
PENDING_FORMAT_VERSION,
|
|
5251
|
-
TERMINAL_FORMAT_VERSION,
|
|
5252
|
-
PHASE_FORMAT_VERSION,
|
|
5771
|
+
agentCandidateProfileAsAgentProfile,
|
|
5253
5772
|
assertExactObjectKeys,
|
|
5254
5773
|
terminalRecord,
|
|
5255
5774
|
recoveredTerminalRecord,
|
|
@@ -5264,6 +5783,7 @@ export {
|
|
|
5264
5783
|
candidateCleanupTimeout,
|
|
5265
5784
|
candidateCleanupDeadline,
|
|
5266
5785
|
withinCandidateCleanupDeadline,
|
|
5786
|
+
readVerifiedArtifact,
|
|
5267
5787
|
verifyBytes,
|
|
5268
5788
|
verifyMaterializedWorkspace,
|
|
5269
5789
|
captureMaterializedWorkspace,
|
|
@@ -5281,12 +5801,17 @@ export {
|
|
|
5281
5801
|
candidateClaimFileInternals,
|
|
5282
5802
|
sealAgentCandidateModelSettlement,
|
|
5283
5803
|
usdToNanos,
|
|
5284
|
-
|
|
5804
|
+
sealAgentCandidateExecutorStopAcknowledgement,
|
|
5285
5805
|
persistCandidateOutputArtifact,
|
|
5286
5806
|
persistCandidateModelSettlementEvidence,
|
|
5287
5807
|
RecoveryAgentCandidateTraceStore,
|
|
5288
5808
|
executePreparedAgentCandidate,
|
|
5809
|
+
AGENT_CANDIDATE_EXECUTION_SUPPORT,
|
|
5289
5810
|
verifyAgentCandidateBundle,
|
|
5811
|
+
verifiedResourceTextByDigest,
|
|
5812
|
+
CANDIDATE_KNOWLEDGE_ROOT_ENV,
|
|
5813
|
+
CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV,
|
|
5814
|
+
candidateKnowledgeExecutionPaths,
|
|
5290
5815
|
prepareAgentCandidateExecution
|
|
5291
5816
|
};
|
|
5292
|
-
//# sourceMappingURL=chunk-
|
|
5817
|
+
//# sourceMappingURL=chunk-YOLKCWRV.js.map
|