@tangle-network/agent-runtime 0.94.13 → 0.95.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/agent.d.ts +2 -25
  2. package/dist/agent.js +9 -12
  3. package/dist/agent.js.map +1 -1
  4. package/dist/{agentic-generator-DDMM45kZ.d.ts → agentic-generator-hCaQRAes.d.ts} +0 -1
  5. package/dist/analyst-loop.d.ts +1 -1
  6. package/dist/candidate-execution/index.d.ts +43 -16
  7. package/dist/candidate-execution/index.js +18 -8
  8. package/dist/{chunk-VYA2YEKA.js → chunk-2KGAN2HM.js} +83 -14
  9. package/dist/chunk-2KGAN2HM.js.map +1 -0
  10. package/dist/{chunk-TVJQAYQM.js → chunk-6YBA64Z2.js} +120 -716
  11. package/dist/chunk-6YBA64Z2.js.map +1 -0
  12. package/dist/{chunk-HGRW27YY.js → chunk-AP7CPGMZ.js} +139 -19
  13. package/dist/chunk-AP7CPGMZ.js.map +1 -0
  14. package/dist/{chunk-XP5KDM3R.js → chunk-BPGXIKK7.js} +3 -3
  15. package/dist/{chunk-D3H7F6L2.js → chunk-DHCHL6OG.js} +2 -3
  16. package/dist/chunk-DHCHL6OG.js.map +1 -0
  17. package/dist/{chunk-PCURO3DL.js → chunk-G55QE4IQ.js} +512 -36
  18. package/dist/chunk-G55QE4IQ.js.map +1 -0
  19. package/dist/{chunk-C3UKLQ54.js → chunk-IADLKE7I.js} +14 -4
  20. package/dist/chunk-IADLKE7I.js.map +1 -0
  21. package/dist/{chunk-WIPGQ4GT.js → chunk-IMSNJSXH.js} +1 -1
  22. package/dist/{chunk-WIPGQ4GT.js.map → chunk-IMSNJSXH.js.map} +1 -1
  23. package/dist/{chunk-VSWBYWFK.js → chunk-M6MD6JBS.js} +20 -27
  24. package/dist/chunk-M6MD6JBS.js.map +1 -0
  25. package/dist/chunk-MKGRLDWB.js +684 -0
  26. package/dist/chunk-MKGRLDWB.js.map +1 -0
  27. package/dist/{chunk-AEG3NGJ2.js → chunk-Q2JSAVQ3.js} +34 -2
  28. package/dist/chunk-Q2JSAVQ3.js.map +1 -0
  29. package/dist/{chunk-CNH7DF7Z.js → chunk-WTZ37EQY.js} +922 -504
  30. package/dist/chunk-WTZ37EQY.js.map +1 -0
  31. package/dist/{chunk-U33YZ7B2.js → chunk-YLUOTX6U.js} +4 -4
  32. package/dist/{chunk-33OG2NN3.js → chunk-Z5I642SY.js} +2 -2
  33. package/dist/{completion-gate-D1gX1-hg.d.ts → completion-gate-C80jiRfN.d.ts} +1 -1
  34. package/dist/conversation.d.ts +12 -1
  35. package/dist/conversation.js +2 -2
  36. package/dist/{coordination-Dr_axlAf.d.ts → coordination-BFE3Den7.d.ts} +10 -11
  37. package/dist/environment-provider.d.ts +2 -2
  38. package/dist/environment-provider.js +1 -1
  39. package/dist/{improve-BN3HyXIO.d.ts → improve-B-UYaEH5.d.ts} +3 -3
  40. package/dist/index.d.ts +22 -25
  41. package/dist/index.js +45 -50
  42. package/dist/index.js.map +1 -1
  43. package/dist/intelligence.d.ts +177 -119
  44. package/dist/intelligence.js +501 -342
  45. package/dist/intelligence.js.map +1 -1
  46. package/dist/knowledge.d.ts +22 -11
  47. package/dist/knowledge.js +9 -4
  48. package/dist/lifecycle.d.ts +2 -2
  49. package/dist/lifecycle.js +1 -1
  50. package/dist/{loop-runner-bin-BRQSQdHa.d.ts → loop-runner-bin-BIQldFS8.d.ts} +2 -2
  51. package/dist/loop-runner-bin.d.ts +5 -5
  52. package/dist/loop-runner-bin.js +6 -6
  53. package/dist/loops.d.ts +12 -12
  54. package/dist/loops.js +5 -5
  55. package/dist/mcp/bin.js +3 -3
  56. package/dist/mcp/index.d.ts +6 -6
  57. package/dist/mcp/index.js +6 -6
  58. package/dist/{mcp-serve-verifier-DQQDbuyz.d.ts → mcp-serve-verifier-Bs_n0xPc.d.ts} +1 -1
  59. package/dist/primeintellect/index.js +1 -1
  60. package/dist/profile-DbfaMTdk.d.ts +233 -0
  61. package/dist/profiles.d.ts +1 -1
  62. package/dist/{supervise-DmYOug5f.d.ts → supervise-BLPI50-w.d.ts} +3 -3
  63. package/dist/{types-ByAYqlVb.d.ts → types-B3vAW0Oq.d.ts} +1 -1
  64. package/dist/{prepare-CtdtsFNG.d.ts → types-CWqfCO8s.d.ts} +67 -298
  65. package/dist/{types-1d5QGK3t.d.ts → types-CmnA2iL3.d.ts} +3 -3
  66. package/dist/{worktree-fanout-CPprU-qI.d.ts → worktree-fanout-DCA3G4bO.d.ts} +3 -3
  67. package/package.json +13 -10
  68. package/dist/chunk-AEG3NGJ2.js.map +0 -1
  69. package/dist/chunk-C3UKLQ54.js.map +0 -1
  70. package/dist/chunk-CNH7DF7Z.js.map +0 -1
  71. package/dist/chunk-D3H7F6L2.js.map +0 -1
  72. package/dist/chunk-HGRW27YY.js.map +0 -1
  73. package/dist/chunk-PCURO3DL.js.map +0 -1
  74. package/dist/chunk-TVJQAYQM.js.map +0 -1
  75. package/dist/chunk-VSWBYWFK.js.map +0 -1
  76. package/dist/chunk-VYA2YEKA.js.map +0 -1
  77. /package/dist/{chunk-XP5KDM3R.js.map → chunk-BPGXIKK7.js.map} +0 -0
  78. /package/dist/{chunk-U33YZ7B2.js.map → chunk-YLUOTX6U.js.map} +0 -0
  79. /package/dist/{chunk-33OG2NN3.js.map → chunk-Z5I642SY.js.map} +0 -0
@@ -1,9 +1,15 @@
1
1
  import {
2
2
  contentAddress
3
- } from "./chunk-WIPGQ4GT.js";
3
+ } from "./chunk-IMSNJSXH.js";
4
4
 
5
- // src/candidate-execution/bundle.ts
6
- import { agentCandidateBundleSchema } from "@tangle-network/agent-interface";
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/bundle.ts
65
- function sealAgentCandidateBundle(input) {
66
- const digest = canonicalCandidateDigest(input);
67
- const parsed = agentCandidateBundleSchema.parse({ ...input, digest });
68
- const parsedDigest = canonicalCandidateDigest(omitTopLevelDigest(parsed));
69
- if (parsedDigest !== digest) {
70
- throw new Error("candidate bundle changed while validating its canonical wire shape");
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 immutableCandidateValue(parsed);
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 = candidateProfileAsAgentProfile(bundled);
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
- const parsed = agentProfileSchema.parse(input);
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
- const parsed = agentProfileDiffSchema.parse(input);
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 candidateProfileAsAgentProfile(candidate) {
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
- var CLAIM_FORMAT_VERSION = 7;
379
- var PENDING_FORMAT_VERSION = 1;
380
- var TERMINAL_FORMAT_VERSION = 3;
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: requireString(
505
- value.executionPlanDigest,
506
- label,
507
- "executionPlanDigest"
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 = agentCandidateArtifactRefSchema.parse(ref);
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
- const remainingMs = deadlineAtMs - Date.now();
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 new CandidateResultTimeoutError(label);
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-v1\.[A-Za-z0-9_-]{43}$/;
953
- var PREPARATION_ID_PATTERN = /^candidate-preparation-v1\.[A-Za-z0-9_-]{43}$/;
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-v1.${randomBytes(32).toString("base64url")}`,
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
- if (record.version !== TERMINAL_FORMAT_VERSION) {
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
- ["version", "kind", "executionId", "attempt", "executionPlanDigest", "phase"],
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
- if (record.version !== PENDING_FORMAT_VERSION) {
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(material.task.workspace, state.executorInputs.taskFiles),
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(state.roots.staging.taskRoot, plan.task.workspace.material, {
2052
- ignoredProtectedRootEntries: [".git", ".sidecar"]
2053
- });
2054
- await verifyTaskCheckout(state.roots.staging.taskRoot, workspaceTaskRepository(plan.task));
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: Object.freeze(
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
- const instruction = state.executionPlan.value.material.task.instruction;
2147
- if (sha256Bytes(state.instruction.bytes) !== instruction.sha256 || state.instruction.bytes.byteLength !== instruction.byteLength || JSON.stringify(state.instruction.delivery) !== JSON.stringify(instruction.delivery)) {
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-v1\.[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))) {
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.number}:`
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) => profileFileView(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(state.executorInputs.taskFiles, material.task.workspace.material);
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 = material.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
- attempt: { ...material.attempt, number: 0 },
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 agentCandidateArtifactRefSchema2
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 = agentCandidateArtifactRefSchema2.parse(
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, ["stopped"], "candidate final capture", ["taskOutcome", "memoryAfter"]);
2464
- if (capture.stopped !== true) {
2465
- throw new Error("candidate final capture does not prove process death");
2466
- }
2467
- const taskOutcome = capture.taskOutcome ? sealTaskOutcomeCapture(capture.taskOutcome) : void 0;
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 encodeAgentCandidateExecutorCapture(input) {
2476
- return canonicalCandidateBytes({
2477
- schemaVersion: 1,
2478
- kind: "agent-candidate-executor-capture",
2479
- executionId: input.executionId,
2480
- executionPlanDigest: input.executionPlanDigest,
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 { agentCandidateRunReceiptSchema } from "@tangle-network/agent-interface";
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) {
@@ -2904,66 +3030,15 @@ function escapeRegularExpression(value) {
2904
3030
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2905
3031
  }
2906
3032
 
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
3033
  // src/candidate-execution/finalize.ts
2958
3034
  async function finalizeAgentCandidateRun(state, capture, traceStore, settlement, evidence, protectedValues, writeRedactionReport, signal) {
2959
3035
  let termination;
2960
3036
  try {
2961
3037
  signal?.throwIfAborted();
2962
- const protectedCapture = sealAgentCandidateProtectedRunCapture(capture);
2963
- if (protectedCapture.executionId !== state.executionId) {
3038
+ if (capture.executionId !== state.executionId) {
2964
3039
  throw new Error("protected capture execution id does not match the prepared execution");
2965
3040
  }
2966
- termination = protectedCapture.termination;
3041
+ termination = capture.termination;
2967
3042
  if (termination.kind === "timeout" && termination.timeoutMs !== state.executionPlan.value.material.limits.timeoutMs) {
2968
3043
  throw new Error("timeout termination does not match the frozen execution limit");
2969
3044
  }
@@ -2994,31 +3069,14 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
2994
3069
  const modelSpans = orderedSpans.filter(isLlmSpan2);
2995
3070
  assertTraceMatchesModelSettlement(modelSpans, settlement);
2996
3071
  enforceLimits(state, run.startedAt, run.endedAt, orderedSpans, settlement);
2997
- const finalCapture = sealAgentCandidateExecutorFinalCapture(evidence.finalCapture);
2998
3072
  const memory = await memoryReceipt(
2999
3073
  state,
3000
- finalCapture,
3001
- evidence.outputArtifacts,
3002
- protectedValues,
3074
+ evidence.finalCapture,
3075
+ evidence.persistedCapture.memoryAfter,
3003
3076
  signal
3004
3077
  );
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
3078
  const redacted = redactProtectedValue(
3020
3079
  {
3021
- schemaVersion: 1,
3022
3080
  run: { ...run, redactionVersion: REDACTION_VERSION2 },
3023
3081
  spans: orderedSpans,
3024
3082
  events: orderedEvents,
@@ -3049,22 +3107,26 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
3049
3107
  signal
3050
3108
  });
3051
3109
  const trace = {
3052
- schemaVersion: 1,
3053
3110
  artifact: traceArtifact,
3054
3111
  eventCount: 1 + orderedSpans.length + orderedEvents.length + orderedBudget.length + orderedArtifacts.length,
3055
3112
  modelCallCount: modelSpans.length
3056
3113
  };
3057
3114
  const document = canonicalCandidateDocument({
3058
- schemaVersion: 3,
3059
3115
  kind: "agent-candidate-run",
3060
3116
  digestAlgorithm: "rfc8785-sha256",
3061
3117
  bundleDigest: state.bundle.digest,
3118
+ runCellDigest: state.executionPlan.value.material.runCell.digest,
3062
3119
  materializationReceiptDigest: state.materializationReceipt.digest,
3063
3120
  executionPlanDigest: state.executionPlan.value.digest,
3121
+ timing: {
3122
+ startedAtMs: run.startedAt,
3123
+ endedAtMs: run.endedAt,
3124
+ durationMs: run.endedAt - run.startedAt
3125
+ },
3064
3126
  memory,
3065
3127
  trace,
3066
3128
  termination,
3067
- executorCapture,
3129
+ executorCapture: evidence.persistedCapture.evidence,
3068
3130
  modelSettlement: evidence.modelSettlement,
3069
3131
  taskOutcome: evidence.taskOutcome.evidence,
3070
3132
  benchmarkResult: evidence.benchmarkResult
@@ -3080,8 +3142,8 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
3080
3142
  succeeded: true,
3081
3143
  receipt: document,
3082
3144
  artifacts: {
3083
- executorCapture,
3084
3145
  modelSettlement: evidence.modelSettlement.artifact,
3146
+ executorCapture: evidence.persistedCapture.evidence,
3085
3147
  taskOutcome: evidence.taskOutcome.evidence.artifact,
3086
3148
  benchmarkResult: evidence.benchmarkResult.artifact,
3087
3149
  runReceipt
@@ -3126,45 +3188,30 @@ function enforceLimits(state, startedAt, endedAt, spans, settlement) {
3126
3188
  for (const [actual, limit, label] of checks) {
3127
3189
  if (actual > limit) throw new Error(`protected ${label} ${actual} exceeds ${limit}`);
3128
3190
  }
3129
- if (settlement.costUsdNanos > usdToNanos(limits.maxCostUsd, "frozen maxCostUsd")) {
3130
- throw new Error(`protected cost USD ${usage.costUsd} exceeds ${limits.maxCostUsd}`);
3191
+ if (usage.costUsdNanos > usdToNanos(limits.maxCostUsd, "frozen maxCostUsd")) {
3192
+ throw new Error(
3193
+ `protected cost USD ${usage.costUsdNanos / 1e9} exceeds ${limits.maxCostUsd}`
3194
+ );
3131
3195
  }
3132
3196
  }
3133
- async function memoryReceipt(state, capture, outputArtifacts, protectedValues, signal) {
3197
+ async function memoryReceipt(state, capture, persisted, signal) {
3134
3198
  signal?.throwIfAborted();
3135
3199
  if (state.memory.mode === "disabled") {
3136
- if (capture.memoryAfter !== void 0) {
3200
+ if (capture.memoryAfter !== void 0 || persisted !== void 0) {
3137
3201
  throw new Error("disabled memory cannot return an after-state");
3138
3202
  }
3139
3203
  return { mode: "disabled" };
3140
3204
  }
3141
3205
  if (!capture.memoryAfter) throw new Error("isolated memory is missing its protected after-state");
3142
- const archive = Uint8Array.from(capture.memoryAfter.archive);
3143
- if (archive.byteLength === 0) throw new Error("isolated memory archive cannot be empty");
3144
- const provisional = provisionalCandidateWorkspaceSnapshot(capture.memoryAfter.afterState, archive);
3145
- const afterState = provisional.material;
3146
- assertNoProtectedBytes(provisional.manifestBytes, protectedValues);
3147
- assertNoProtectedBytes(archive, protectedValues);
3148
- const root = await mkdtemp2(join2(tmpdir2(), "agent-candidate-memory-after-"));
3149
- try {
3150
- await state.ports.workspaces.materialize({
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,
3206
+ if (!persisted) throw new Error("isolated memory is missing persisted capture evidence");
3207
+ const afterState = capture.memoryAfter.afterState;
3208
+ const manifestBytes = canonicalCandidateBytes(afterState);
3209
+ const snapshot = agentCandidateWorkspaceSnapshotEvidenceSchema.parse({
3210
+ kind: "agent-candidate-workspace-snapshot",
3211
+ digest: sha256Bytes(manifestBytes),
3164
3212
  material: afterState,
3165
- archive,
3166
- purpose: "memory-after",
3167
- signal
3213
+ manifest: persisted.manifest,
3214
+ archive: persisted.archive
3168
3215
  });
3169
3216
  return {
3170
3217
  mode: "isolated",
@@ -3194,19 +3241,20 @@ function compareStrings(a, b) {
3194
3241
  }
3195
3242
 
3196
3243
  // src/candidate-execution/outcome-evidence.ts
3197
- import { mkdtemp as mkdtemp3, rm as rm3 } from "fs/promises";
3198
- import { tmpdir as tmpdir3 } from "os";
3199
- import { join as join3 } from "path";
3244
+ import { mkdtemp as mkdtemp2, rm as rm2 } from "fs/promises";
3245
+ import { tmpdir as tmpdir2 } from "os";
3246
+ import { join as join2 } from "path";
3200
3247
  import {
3201
3248
  agentCandidateBenchmarkResultEvidenceSchema,
3202
3249
  agentCandidateModelSettlementEvidenceSchema,
3203
- agentCandidateTaskOutcomeEvidenceSchema
3250
+ agentCandidateTaskOutcomeEvidenceSchema,
3251
+ agentCandidateWorkspaceSnapshotEvidenceSchema as agentCandidateWorkspaceSnapshotEvidenceSchema2
3204
3252
  } from "@tangle-network/agent-interface";
3205
3253
 
3206
3254
  // src/candidate-execution/benchmark-grader.ts
3207
3255
  async function runBoundCandidateBenchmarkGrader(input) {
3208
3256
  input.signal?.throwIfAborted();
3209
- const descriptor = snapshotGraderDescriptor(input.grader);
3257
+ const descriptor = snapshotGraderDescriptor(input.grader, input.expectedGrader);
3210
3258
  const implementationBytes = await readVerifiedArtifact(descriptor.artifact, input.artifacts);
3211
3259
  if (implementationBytes.byteLength === 0) {
3212
3260
  throw new Error("candidate benchmark grader implementation cannot be empty");
@@ -3214,6 +3262,7 @@ async function runBoundCandidateBenchmarkGrader(input) {
3214
3262
  const expectedImplementationDigest = sha256Bytes(implementationBytes);
3215
3263
  const termination = immutableCandidateValue(input.termination);
3216
3264
  const run = input.grader.run;
3265
+ const startedAtMs = Date.now();
3217
3266
  const result = await run(
3218
3267
  Object.freeze({
3219
3268
  executionId: input.executionId,
@@ -3223,6 +3272,7 @@ async function runBoundCandidateBenchmarkGrader(input) {
3223
3272
  signal: input.signal ?? new AbortController().signal
3224
3273
  })
3225
3274
  );
3275
+ const endedAtMs = Math.max(startedAtMs, Date.now());
3226
3276
  input.signal?.throwIfAborted();
3227
3277
  assertExactRunnerResult(result);
3228
3278
  const evidence = Uint8Array.from(result.evidence);
@@ -3242,19 +3292,42 @@ async function runBoundCandidateBenchmarkGrader(input) {
3242
3292
  }
3243
3293
  return Object.freeze({
3244
3294
  grader: descriptor,
3295
+ grading: immutableCandidateValue({
3296
+ usage: emptyFixedSpend(),
3297
+ timing: {
3298
+ startedAtMs,
3299
+ endedAtMs,
3300
+ durationMs: endedAtMs - startedAtMs
3301
+ }
3302
+ }),
3245
3303
  evaluation: result.evaluation,
3246
3304
  evidence
3247
3305
  });
3248
3306
  }
3249
- function snapshotGraderDescriptor(grader) {
3307
+ function snapshotGraderDescriptor(grader, expected) {
3250
3308
  if (!grader.name || !grader.version) {
3251
3309
  throw new Error("candidate benchmark grader name and version must be non-empty");
3252
3310
  }
3253
- return immutableCandidateValue({
3311
+ const actual = {
3254
3312
  name: grader.name,
3255
3313
  version: grader.version,
3314
+ format: "tangle-grader",
3256
3315
  artifact: grader.artifact
3257
- });
3316
+ };
3317
+ if (canonicalCandidateDigest(actual) !== canonicalCandidateDigest(expected)) {
3318
+ throw new Error("candidate benchmark grader does not match the signed task grader");
3319
+ }
3320
+ return immutableCandidateValue(expected);
3321
+ }
3322
+ function emptyFixedSpend() {
3323
+ return {
3324
+ inputTokens: 0,
3325
+ outputTokens: 0,
3326
+ cachedInputTokens: 0,
3327
+ reasoningTokens: 0,
3328
+ modelCalls: 0,
3329
+ costUsdNanos: 0
3330
+ };
3258
3331
  }
3259
3332
  function detachedImplementation(bytes) {
3260
3333
  const stored = Uint8Array.from(bytes);
@@ -3286,6 +3359,104 @@ function assertExactRunnerResult(value) {
3286
3359
  }
3287
3360
  }
3288
3361
 
3362
+ // src/candidate-execution/executor-capture-evidence.ts
3363
+ async function persistAgentCandidateExecutorCapture(identity, expected, capture, outputArtifacts, signal) {
3364
+ const executorEvidence = capture.evidence ? await persistCandidateOutputArtifact(outputArtifacts, {
3365
+ executionId: identity.executionId,
3366
+ purpose: "executor-native-evidence",
3367
+ bytes: capture.evidence,
3368
+ signal
3369
+ }) : void 0;
3370
+ const taskOutcome = capture.taskOutcome ? await persistTaskCapture(
3371
+ identity.executionId,
3372
+ expected,
3373
+ capture.taskOutcome,
3374
+ outputArtifacts,
3375
+ signal
3376
+ ) : void 0;
3377
+ const memoryAfter = capture.memoryAfter ? await persistWorkspaceCapture(
3378
+ identity.executionId,
3379
+ "memory-after-manifest",
3380
+ "memory-after-archive",
3381
+ capture.memoryAfter.afterState,
3382
+ capture.memoryAfter.archive,
3383
+ outputArtifacts,
3384
+ signal
3385
+ ) : void 0;
3386
+ const bytes = canonicalCandidateBytes({
3387
+ kind: "agent-candidate-executor-capture",
3388
+ executionPlanDigest: identity.executionPlanDigest,
3389
+ ...executorEvidence ? { executorEvidence } : {},
3390
+ ...taskOutcome ? { taskOutcome } : {},
3391
+ ...memoryAfter ? { memoryAfter } : {}
3392
+ });
3393
+ const evidence = await persistCandidateOutputArtifact(outputArtifacts, {
3394
+ executionId: identity.executionId,
3395
+ purpose: "executor-capture",
3396
+ bytes,
3397
+ signal
3398
+ });
3399
+ return Object.freeze({
3400
+ evidence,
3401
+ ...taskOutcome ? { taskOutcome: Object.freeze(taskOutcome) } : {},
3402
+ ...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {}
3403
+ });
3404
+ }
3405
+ async function persistTaskCapture(executionId, expected, capture, outputArtifacts, signal) {
3406
+ if (capture.kind === "output") {
3407
+ if (expected.kind !== "output")
3408
+ throw new Error("captured output does not match the signed task");
3409
+ const artifact = await persistCandidateOutputArtifact(outputArtifacts, {
3410
+ executionId,
3411
+ purpose: "task-output",
3412
+ bytes: capture.bytes,
3413
+ signal
3414
+ });
3415
+ return {
3416
+ kind: "output",
3417
+ spec: { mediaType: expected.mediaType, maxBytes: expected.maxBytes },
3418
+ artifact
3419
+ };
3420
+ }
3421
+ if (expected.kind !== "workspace") {
3422
+ throw new Error("captured workspace does not match the signed task");
3423
+ }
3424
+ const workspace = await persistWorkspaceCapture(
3425
+ executionId,
3426
+ "task-manifest",
3427
+ "task-archive",
3428
+ capture.afterState,
3429
+ capture.archive,
3430
+ outputArtifacts,
3431
+ signal
3432
+ );
3433
+ const gitDiff = await persistCandidateOutputArtifact(outputArtifacts, {
3434
+ executionId,
3435
+ purpose: "task-patch",
3436
+ bytes: capture.gitDiff,
3437
+ signal
3438
+ });
3439
+ return { kind: "workspace", resultTree: capture.resultTree, ...workspace, gitDiff };
3440
+ }
3441
+ async function persistWorkspaceCapture(executionId, manifestPurpose, archivePurpose, afterState, archiveBytes, outputArtifacts, signal) {
3442
+ const manifestBytes = canonicalCandidateBytes(afterState);
3443
+ const [manifest, archive] = await Promise.all([
3444
+ persistCandidateOutputArtifact(outputArtifacts, {
3445
+ executionId,
3446
+ purpose: manifestPurpose,
3447
+ bytes: manifestBytes,
3448
+ signal
3449
+ }),
3450
+ persistCandidateOutputArtifact(outputArtifacts, {
3451
+ executionId,
3452
+ purpose: archivePurpose,
3453
+ bytes: archiveBytes,
3454
+ signal
3455
+ })
3456
+ ]);
3457
+ return { afterState, manifest, archive };
3458
+ }
3459
+
3289
3460
  // src/candidate-execution/outcome-evidence.ts
3290
3461
  async function persistCandidateModelSettlement(state, settlement, outputArtifacts) {
3291
3462
  return await persistCandidateModelSettlementEvidence(
@@ -3300,7 +3471,6 @@ async function persistCandidateModelSettlement(state, settlement, outputArtifact
3300
3471
  }
3301
3472
  async function persistCandidateModelSettlementEvidence(identity, settlement, outputArtifacts) {
3302
3473
  const material = {
3303
- schemaVersion: 2,
3304
3474
  kind: "agent-candidate-model-settlement-material",
3305
3475
  executionPlanDigest: identity.executionPlanDigest,
3306
3476
  preparationId: settlement.value.preparationId,
@@ -3321,7 +3491,7 @@ async function persistCandidateModelSettlementEvidence(identity, settlement, out
3321
3491
  reasoningTokens: call.reasoningTokens ?? 0,
3322
3492
  costUsdNanos: call.costUsdNanos
3323
3493
  })),
3324
- usage: settlement.fixedUsage
3494
+ usage: settlement.usage
3325
3495
  };
3326
3496
  const bytes = canonicalCandidateBytes(material);
3327
3497
  const digest = sha256Bytes(bytes);
@@ -3332,7 +3502,6 @@ async function persistCandidateModelSettlementEvidence(identity, settlement, out
3332
3502
  });
3333
3503
  return immutableCandidateValue(
3334
3504
  agentCandidateModelSettlementEvidenceSchema.parse({
3335
- schemaVersion: 2,
3336
3505
  kind: "agent-candidate-model-settlement",
3337
3506
  digest,
3338
3507
  material,
@@ -3340,16 +3509,53 @@ async function persistCandidateModelSettlementEvidence(identity, settlement, out
3340
3509
  })
3341
3510
  );
3342
3511
  }
3343
- async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifacts, protectedValues, signal) {
3512
+ async function persistVerifiedAgentCandidateExecutorCapture(state, capture, outputArtifacts, protectedValues, signal) {
3344
3513
  signal?.throwIfAborted();
3514
+ const taskCapture = capture.taskOutcome;
3515
+ if (!taskCapture) throw new Error("candidate final capture is missing the task outcome");
3516
+ if (capture.evidence) assertNoProtectedBytes(capture.evidence, protectedValues);
3517
+ const expected = state.benchmarkTask.outcome;
3518
+ if (taskCapture.kind !== expected.kind) {
3519
+ throw new Error(
3520
+ `candidate captured ${taskCapture.kind} outcome does not match expected ${expected.kind} outcome`
3521
+ );
3522
+ }
3523
+ 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;
3524
+ if (!verified) throw new Error("candidate task outcome kind could not be narrowed");
3525
+ await verifyMemoryCapture(state, capture, protectedValues, signal);
3526
+ const persistedCapture = await persistAgentCandidateExecutorCapture(
3527
+ {
3528
+ executionId: state.executionId,
3529
+ executionPlanDigest: state.executionPlan.value.digest
3530
+ },
3531
+ expected,
3532
+ capture,
3533
+ outputArtifacts,
3534
+ signal
3535
+ );
3536
+ const persisted = persistedCapture.taskOutcome;
3537
+ if (!persisted || persisted.kind !== verified.kind) {
3538
+ throw new Error("persisted task capture kind changed");
3539
+ }
3540
+ const taskOutcome = verified.kind === "output" && persisted.kind === "output" ? await persistVerifiedOutputTaskOutcome(state, verified, persisted, outputArtifacts, signal) : verified.kind === "workspace" && persisted.kind === "workspace" ? await persistVerifiedWorkspaceTaskOutcome(
3541
+ state,
3542
+ verified,
3543
+ persisted,
3544
+ outputArtifacts,
3545
+ signal
3546
+ ) : void 0;
3547
+ if (!taskOutcome) throw new Error("persisted task outcome kind could not be narrowed");
3548
+ return Object.freeze({ persistedCapture, taskOutcome });
3549
+ }
3550
+ async function verifyWorkspaceTaskCapture(state, capture, protectedValues, signal) {
3551
+ const repository = state.benchmarkTask.repository;
3552
+ if (!repository) throw new Error("workspace task outcome is missing repository identity");
3345
3553
  const patch = Uint8Array.from(capture.gitDiff);
3346
3554
  const archive = Uint8Array.from(capture.archive);
3347
3555
  if (archive.byteLength === 0) throw new Error("candidate task archive cannot be empty");
3348
3556
  assertNoProtectedBytes(patch, protectedValues);
3349
3557
  assertNoProtectedBytes(archive, protectedValues);
3350
- const provisional = provisionalCandidateWorkspaceSnapshot(capture.afterState, archive);
3351
- const afterState = provisional.material;
3352
- const repository = workspaceTaskRepository(state.executionPlan.value.material.task);
3558
+ const afterState = immutableCandidateValue(capture.afterState);
3353
3559
  const verified = await verifyTaskOutcomePatch({
3354
3560
  repositoryRoot: state.roots.staging.taskRoot,
3355
3561
  baseCommit: repository.baseCommit,
@@ -3359,24 +3565,38 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
3359
3565
  afterState
3360
3566
  });
3361
3567
  signal?.throwIfAborted();
3362
- assertNoProtectedBytes(provisional.manifestBytes, protectedValues);
3363
- await verifyTaskOutcomeArchive(state, provisional.snapshot, archive, protectedValues);
3364
- signal?.throwIfAborted();
3365
- const snapshot = await persistCandidateWorkspaceSnapshot(outputArtifacts, {
3366
- executionId: state.executionId,
3568
+ const manifestBytes = canonicalCandidateBytes(afterState);
3569
+ assertNoProtectedBytes(manifestBytes, protectedValues);
3570
+ const provisionalSnapshot = agentCandidateWorkspaceSnapshotEvidenceSchema2.parse({
3571
+ kind: "agent-candidate-workspace-snapshot",
3572
+ digest: sha256Bytes(manifestBytes),
3367
3573
  material: afterState,
3368
- archive,
3369
- purpose: "task",
3370
- signal
3574
+ manifest: embeddedCandidateArtifact(manifestBytes),
3575
+ archive: embeddedCandidateArtifact(archive)
3371
3576
  });
3372
- const gitDiff = await persistCandidateOutputArtifact(outputArtifacts, {
3373
- executionId: state.executionId,
3374
- purpose: "task-patch",
3375
- bytes: patch,
3376
- signal
3577
+ await verifyTaskOutcomeArchive(state, provisionalSnapshot, archive, protectedValues);
3578
+ signal?.throwIfAborted();
3579
+ return {
3580
+ kind: "workspace",
3581
+ patch,
3582
+ archive,
3583
+ afterState,
3584
+ manifestBytes,
3585
+ resultCommit: verified.resultCommit,
3586
+ resultTree: verified.resultTree,
3587
+ repository
3588
+ };
3589
+ }
3590
+ async function persistVerifiedWorkspaceTaskOutcome(state, verified, persisted, outputArtifacts, signal) {
3591
+ const { afterState, manifestBytes, patch, repository } = verified;
3592
+ const snapshot = agentCandidateWorkspaceSnapshotEvidenceSchema2.parse({
3593
+ kind: "agent-candidate-workspace-snapshot",
3594
+ digest: sha256Bytes(manifestBytes),
3595
+ material: afterState,
3596
+ manifest: persisted.manifest,
3597
+ archive: persisted.archive
3377
3598
  });
3378
3599
  const material = {
3379
- schemaVersion: 2,
3380
3600
  kind: "agent-candidate-task-outcome-material",
3381
3601
  executionPlanDigest: state.executionPlan.value.digest,
3382
3602
  outcome: {
@@ -3396,10 +3616,60 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
3396
3616
  afterState: snapshot,
3397
3617
  gitDiff: {
3398
3618
  format: "git-diff-binary",
3399
- artifact: gitDiff
3619
+ artifact: persisted.gitDiff
3400
3620
  }
3401
3621
  }
3402
3622
  };
3623
+ const evidence = await persistTaskOutcomeEvidence(state, material, outputArtifacts, signal);
3624
+ const storedPatch = Uint8Array.from(patch);
3625
+ return Object.freeze({
3626
+ kind: "workspace",
3627
+ evidence,
3628
+ get patch() {
3629
+ return Uint8Array.from(storedPatch);
3630
+ },
3631
+ [verifiedTaskOutcomeBrand]: true
3632
+ });
3633
+ }
3634
+ function verifyOutputTaskCapture(capturedBytes, expected, protectedValues) {
3635
+ if (capturedBytes.byteLength === 0) throw new Error("candidate task output cannot be empty");
3636
+ if (capturedBytes.byteLength > expected.maxBytes) {
3637
+ throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
3638
+ }
3639
+ const output = Uint8Array.from(capturedBytes);
3640
+ assertNoProtectedBytes(output, protectedValues);
3641
+ return {
3642
+ kind: "output",
3643
+ bytes: output,
3644
+ spec: { mediaType: expected.mediaType, maxBytes: expected.maxBytes }
3645
+ };
3646
+ }
3647
+ async function persistVerifiedOutputTaskOutcome(state, verified, persisted, outputArtifacts, signal) {
3648
+ if (persisted.spec.mediaType !== verified.spec.mediaType || persisted.spec.maxBytes !== verified.spec.maxBytes) {
3649
+ throw new Error("persisted task output changed the signed media constraints");
3650
+ }
3651
+ const material = {
3652
+ kind: "agent-candidate-task-outcome-material",
3653
+ executionPlanDigest: state.executionPlan.value.digest,
3654
+ outcome: {
3655
+ kind: "output",
3656
+ spec: verified.spec,
3657
+ artifact: persisted.artifact
3658
+ }
3659
+ };
3660
+ const evidence = await persistTaskOutcomeEvidence(state, material, outputArtifacts, signal);
3661
+ const storedOutput = Uint8Array.from(verified.bytes);
3662
+ return Object.freeze({
3663
+ kind: "output",
3664
+ evidence,
3665
+ spec: immutableCandidateValue(verified.spec),
3666
+ get bytes() {
3667
+ return Uint8Array.from(storedOutput);
3668
+ },
3669
+ [verifiedTaskOutcomeBrand]: true
3670
+ });
3671
+ }
3672
+ async function persistTaskOutcomeEvidence(state, material, outputArtifacts, signal) {
3403
3673
  const bytes = canonicalCandidateBytes(material);
3404
3674
  const digest = sha256Bytes(bytes);
3405
3675
  const artifact = await persistCandidateOutputArtifact(outputArtifacts, {
@@ -3408,23 +3678,14 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
3408
3678
  bytes,
3409
3679
  signal
3410
3680
  });
3411
- const evidence = immutableCandidateValue(
3681
+ return immutableCandidateValue(
3412
3682
  agentCandidateTaskOutcomeEvidenceSchema.parse({
3413
- schemaVersion: 2,
3414
3683
  kind: "agent-candidate-task-outcome",
3415
3684
  digest,
3416
3685
  material,
3417
3686
  artifact
3418
3687
  })
3419
3688
  );
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
3689
  }
3429
3690
  async function persistCandidateBenchmarkResult(state, termination, outcome, grader, outputArtifacts, protectedValues, signal) {
3430
3691
  signal?.throwIfAborted();
@@ -3433,6 +3694,7 @@ async function persistCandidateBenchmarkResult(state, termination, outcome, grad
3433
3694
  executionId: state.executionId,
3434
3695
  termination: frozenTermination,
3435
3696
  outcome,
3697
+ expectedGrader: state.benchmarkTask.grader,
3436
3698
  grader,
3437
3699
  artifacts: outputArtifacts,
3438
3700
  signal
@@ -3448,24 +3710,13 @@ async function persistCandidateBenchmarkResult(state, termination, outcome, grad
3448
3710
  bytes: rawEvidence,
3449
3711
  signal
3450
3712
  });
3451
- const task = state.executionPlan.value.material.task;
3452
3713
  const material = {
3453
- schemaVersion: 1,
3454
3714
  kind: "agent-candidate-benchmark-result-material",
3455
3715
  executionPlanDigest: state.executionPlan.value.digest,
3456
3716
  taskOutcomeDigest: outcome.evidence.digest,
3457
- benchmark: {
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
- },
3717
+ grader: graded.grader,
3468
3718
  evidence: evidenceRef,
3719
+ grading: graded.grading,
3469
3720
  score: evaluation.score,
3470
3721
  passed: evaluation.passed,
3471
3722
  dimensions: evaluation.dimensions
@@ -3480,7 +3731,6 @@ async function persistCandidateBenchmarkResult(state, termination, outcome, grad
3480
3731
  });
3481
3732
  return immutableCandidateValue(
3482
3733
  agentCandidateBenchmarkResultEvidenceSchema.parse({
3483
- schemaVersion: 1,
3484
3734
  kind: "agent-candidate-benchmark-result",
3485
3735
  digest,
3486
3736
  material,
@@ -3489,7 +3739,7 @@ async function persistCandidateBenchmarkResult(state, termination, outcome, grad
3489
3739
  );
3490
3740
  }
3491
3741
  async function verifyTaskOutcomeArchive(state, snapshot, archive, protectedValues) {
3492
- const root = await mkdtemp3(join3(tmpdir3(), "agent-candidate-task-archive-"));
3742
+ const root = await mkdtemp2(join2(tmpdir2(), "agent-candidate-task-archive-"));
3493
3743
  try {
3494
3744
  await state.ports.workspaces.materialize({
3495
3745
  role: "task",
@@ -3500,7 +3750,40 @@ async function verifyTaskOutcomeArchive(state, snapshot, archive, protectedValue
3500
3750
  const files = await readMaterializedWorkspaceFiles(root, snapshot.material);
3501
3751
  for (const file of files) assertNoProtectedBytes(file.bytes, protectedValues);
3502
3752
  } finally {
3503
- await rm3(root, { recursive: true, force: true });
3753
+ await rm2(root, { recursive: true, force: true });
3754
+ }
3755
+ }
3756
+ async function verifyMemoryCapture(state, capture, protectedValues, signal) {
3757
+ if (state.memory.mode === "disabled") {
3758
+ if (capture.memoryAfter) throw new Error("disabled memory cannot return an after-state");
3759
+ return;
3760
+ }
3761
+ const memory = capture.memoryAfter;
3762
+ if (!memory) throw new Error("isolated memory is missing its protected after-state");
3763
+ if (memory.archive.byteLength === 0) throw new Error("isolated memory archive cannot be empty");
3764
+ const manifestBytes = canonicalCandidateBytes(memory.afterState);
3765
+ assertNoProtectedBytes(manifestBytes, protectedValues);
3766
+ assertNoProtectedBytes(memory.archive, protectedValues);
3767
+ const snapshot = agentCandidateWorkspaceSnapshotEvidenceSchema2.parse({
3768
+ kind: "agent-candidate-workspace-snapshot",
3769
+ digest: sha256Bytes(manifestBytes),
3770
+ material: memory.afterState,
3771
+ manifest: embeddedCandidateArtifact(manifestBytes),
3772
+ archive: embeddedCandidateArtifact(memory.archive)
3773
+ });
3774
+ const root = await mkdtemp2(join2(tmpdir2(), "agent-candidate-memory-after-"));
3775
+ try {
3776
+ await state.ports.workspaces.materialize({
3777
+ role: "memory",
3778
+ snapshot,
3779
+ archive: Uint8Array.from(memory.archive),
3780
+ destination: root
3781
+ });
3782
+ const files = await readMaterializedWorkspaceFiles(root, memory.afterState);
3783
+ for (const file of files) assertNoProtectedBytes(file.bytes, protectedValues);
3784
+ signal?.throwIfAborted();
3785
+ } finally {
3786
+ await rm2(root, { recursive: true, force: true });
3504
3787
  }
3505
3788
  }
3506
3789
  function normalizeEvaluation(evaluation, termination) {
@@ -3683,9 +3966,29 @@ async function executePreparedAgentCandidate(prepared, options) {
3683
3966
  } catch (error) {
3684
3967
  return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
3685
3968
  }
3969
+ let preparationEvidence;
3970
+ try {
3971
+ const [executionPlan, materializationReceipt] = await Promise.all([
3972
+ persistCandidateOutputArtifact(options.outputArtifacts, {
3973
+ executionId: state.executionId,
3974
+ purpose: "execution-plan",
3975
+ bytes: state.executionPlan.bytes
3976
+ }),
3977
+ persistCandidateOutputArtifact(options.outputArtifacts, {
3978
+ executionId: state.executionId,
3979
+ purpose: "materialization-receipt",
3980
+ bytes: state.materializationReceipt.bytes
3981
+ })
3982
+ ]);
3983
+ preparationEvidence = Object.freeze({ executionPlan, materializationReceipt });
3984
+ } catch (error) {
3985
+ return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
3986
+ }
3686
3987
  let acquired;
3687
3988
  try {
3688
- acquired = await options.claimStore.tryClaim(candidateExecutionClaim(prepared));
3989
+ acquired = await options.claimStore.tryClaim(
3990
+ candidateExecutionClaim(prepared, preparationEvidence)
3991
+ );
3689
3992
  } catch (error) {
3690
3993
  return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
3691
3994
  }
@@ -3837,6 +4140,7 @@ async function executePreparedAgentCandidate(prepared, options) {
3837
4140
  const execution = await runAndStopExecutor(
3838
4141
  options.executor,
3839
4142
  request,
4143
+ state.benchmarkTask.outcome,
3840
4144
  protectedTraceStore,
3841
4145
  deadlineAtMs,
3842
4146
  cleanupTimeoutMs
@@ -3925,9 +4229,9 @@ async function executePreparedAgentCandidate(prepared, options) {
3925
4229
  state.trace.runId,
3926
4230
  settlementResult.settlement
3927
4231
  );
3928
- const taskOutcome = await persistVerifiedCandidateTaskOutcome(
4232
+ const { persistedCapture, taskOutcome } = await persistVerifiedAgentCandidateExecutorCapture(
3929
4233
  state,
3930
- execution.finalCapture.taskOutcome,
4234
+ execution.finalCapture,
3931
4235
  options.outputArtifacts,
3932
4236
  protectedValues,
3933
4237
  signal
@@ -3948,6 +4252,7 @@ async function executePreparedAgentCandidate(prepared, options) {
3948
4252
  settlementResult.settlement,
3949
4253
  {
3950
4254
  finalCapture: execution.finalCapture,
4255
+ persistedCapture,
3951
4256
  modelSettlement,
3952
4257
  taskOutcome,
3953
4258
  benchmarkResult,
@@ -3973,18 +4278,16 @@ async function executePreparedAgentCandidate(prepared, options) {
3973
4278
  let terminal;
3974
4279
  try {
3975
4280
  terminal = result.succeeded ? {
3976
- schemaVersion: 1,
3977
4281
  status: "succeeded",
3978
- usage: settlementResult.settlement.fixedUsage,
4282
+ usage: settlementResult.settlement.usage,
3979
4283
  modelSettlement: result.artifacts.modelSettlement,
3980
4284
  taskOutcome: result.artifacts.taskOutcome,
3981
4285
  benchmarkResult: result.artifacts.benchmarkResult,
3982
4286
  runReceipt: result.artifacts.runReceipt
3983
4287
  } : {
3984
- schemaVersion: 1,
3985
4288
  status: "failed",
3986
4289
  failureClass,
3987
- usage: settlementResult.settlement.fixedUsage,
4290
+ usage: settlementResult.settlement.usage,
3988
4291
  modelSettlement: modelSettlement.artifact,
3989
4292
  failureEvidence: await withinCandidateCleanupDeadline(
3990
4293
  () => persistFailureEvidence(
@@ -4031,7 +4334,7 @@ async function executePreparedAgentCandidate(prepared, options) {
4031
4334
  settlementResult.settlement.usage
4032
4335
  );
4033
4336
  }
4034
- async function runAndStopExecutor(executor, request, traceStore, deadlineAtMs, cleanupTimeoutMs) {
4337
+ async function runAndStopExecutor(executor, request, expectedOutcome, traceStore, deadlineAtMs, cleanupTimeoutMs) {
4035
4338
  const timeoutMs = request.hardLimits.timeoutMs;
4036
4339
  const timeoutError = new CandidateExecutionDeadlineError(timeoutMs);
4037
4340
  if (Date.now() >= deadlineAtMs) {
@@ -4086,10 +4389,10 @@ async function runAndStopExecutor(executor, request, traceStore, deadlineAtMs, c
4086
4389
  }
4087
4390
  if (!capture || timedOut) controller.abort(executionError);
4088
4391
  const stopReason = timedOut ? "timeout" : capture ? "completed" : "failed";
4089
- let stopped;
4392
+ const cleanupDeadlineAtMs = Date.now() + cleanupTimeoutMs;
4090
4393
  try {
4091
- stopped = await withinCandidateCleanupDeadline(
4092
- () => executor.stopAndCapture(
4394
+ const stopped = await withinCandidateCleanupDeadline(
4395
+ (cleanupSignal) => executor.stop(
4093
4396
  {
4094
4397
  executionId: request.executionId,
4095
4398
  executionPlanDigest: request.executionPlan.value.digest
@@ -4097,35 +4400,65 @@ async function runAndStopExecutor(executor, request, traceStore, deadlineAtMs, c
4097
4400
  {
4098
4401
  traceStore,
4099
4402
  reason: stopReason,
4100
- signal: controller.signal,
4101
- deadlineAtMs
4403
+ signal: cleanupSignal,
4404
+ deadlineAtMs: cleanupDeadlineAtMs
4102
4405
  }
4103
4406
  ),
4104
- Date.now() + cleanupTimeoutMs,
4407
+ cleanupDeadlineAtMs,
4105
4408
  "candidate process termination"
4106
4409
  );
4107
- if (!stopped || typeof stopped !== "object" || stopped.stopped !== true) {
4108
- throw new Error("candidate executor did not acknowledge exact process termination");
4109
- }
4410
+ sealAgentCandidateExecutorStopAcknowledgement(stopped);
4110
4411
  } catch (stopError) {
4412
+ let disposalError2;
4413
+ try {
4414
+ await disposeExecutor(executor, request, cleanupDeadlineAtMs);
4415
+ } catch (error) {
4416
+ disposalError2 = error;
4417
+ }
4111
4418
  if (timer) clearTimeout(timer);
4112
4419
  controller.abort(stopError);
4113
4420
  return {
4114
4421
  kind: "error",
4115
- error: new Error(joinErrors(executionError, stopError)),
4422
+ error: new Error(joinErrors(executionError, stopError, disposalError2)),
4116
4423
  ...timedOut ? { termination: { kind: "timeout", timeoutMs } } : {},
4117
4424
  processStopped: false
4118
4425
  };
4119
4426
  }
4120
4427
  let finalCapture;
4428
+ let finalCaptureError;
4121
4429
  try {
4122
- finalCapture = sealAgentCandidateExecutorFinalCapture(stopped);
4430
+ finalCapture = sealAgentCandidateExecutorFinalCapture(
4431
+ await withinCandidateCleanupDeadline(
4432
+ (cleanupSignal) => executor.capture(
4433
+ {
4434
+ executionId: request.executionId,
4435
+ executionPlanDigest: request.executionPlan.value.digest
4436
+ },
4437
+ {
4438
+ traceStore,
4439
+ signal: cleanupSignal
4440
+ }
4441
+ ),
4442
+ cleanupDeadlineAtMs,
4443
+ "candidate final evidence capture"
4444
+ ),
4445
+ expectedOutcome
4446
+ );
4123
4447
  } catch (captureError) {
4448
+ finalCaptureError = captureError;
4449
+ }
4450
+ let disposalError;
4451
+ try {
4452
+ await disposeExecutor(executor, request, cleanupDeadlineAtMs);
4453
+ } catch (disposeError) {
4454
+ disposalError = disposeError;
4455
+ }
4456
+ if (finalCaptureError || disposalError || !finalCapture) {
4124
4457
  if (timer) clearTimeout(timer);
4125
- controller.abort(captureError);
4458
+ controller.abort(finalCaptureError ?? disposalError);
4126
4459
  return {
4127
4460
  kind: "error",
4128
- error: new Error(joinErrors(executionError, captureError)),
4461
+ error: new Error(joinErrors(executionError, finalCaptureError, disposalError)),
4129
4462
  ...timedOut ? { termination: { kind: "timeout", timeoutMs } } : {},
4130
4463
  processStopped: true
4131
4464
  };
@@ -4161,6 +4494,25 @@ async function runAndStopExecutor(executor, request, traceStore, deadlineAtMs, c
4161
4494
  processStopped: true
4162
4495
  };
4163
4496
  }
4497
+ async function disposeExecutor(executor, request, cleanupDeadlineAtMs) {
4498
+ const dispose = executor.dispose;
4499
+ if (!dispose) return;
4500
+ const disposed = await withinCandidateCleanupDeadline(
4501
+ (cleanupSignal) => dispose.call(
4502
+ executor,
4503
+ {
4504
+ executionId: request.executionId,
4505
+ executionPlanDigest: request.executionPlan.value.digest
4506
+ },
4507
+ { signal: cleanupSignal }
4508
+ ),
4509
+ cleanupDeadlineAtMs,
4510
+ "candidate execution resource disposal"
4511
+ );
4512
+ if (!disposed || disposed.disposed !== true || Object.keys(disposed).some((key) => key !== "disposed")) {
4513
+ throw new Error("candidate executor did not acknowledge resource disposal");
4514
+ }
4515
+ }
4164
4516
  async function failBeforeActivation(prepared, state, error, reason, cleanupTimeoutMs) {
4165
4517
  beginPreparedCandidateSettlement(prepared);
4166
4518
  const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
@@ -4215,10 +4567,9 @@ async function failClaimedExecution(prepared, state, lease, claimStore, outputAr
4215
4567
  claimStore,
4216
4568
  lease,
4217
4569
  {
4218
- schemaVersion: 1,
4219
4570
  status: "failed",
4220
4571
  failureClass,
4221
- usage: settled.settlement.fixedUsage,
4572
+ usage: settled.settlement.usage,
4222
4573
  modelSettlement: modelSettlement.artifact,
4223
4574
  failureEvidence
4224
4575
  },
@@ -4315,7 +4666,6 @@ async function finishClaim(store, lease, terminal, deadlineAtMs) {
4315
4666
  }
4316
4667
  async function persistFailureEvidence(state, reason, failureClass, termination, outputArtifacts) {
4317
4668
  const bytes = canonicalCandidateBytes({
4318
- schemaVersion: 1,
4319
4669
  kind: "agent-candidate-execution-failure",
4320
4670
  executionId: state.executionId,
4321
4671
  bundleDigest: state.bundle.digest,
@@ -4347,10 +4697,24 @@ var CandidateExecutionDeadlineError = class extends Error {
4347
4697
  };
4348
4698
 
4349
4699
  // src/candidate-execution/verify.ts
4350
- import { agentCandidateBundleSchema as agentCandidateBundleSchema2 } from "@tangle-network/agent-interface";
4700
+ import { agentCandidateBundleSchema } from "@tangle-network/agent-interface";
4351
4701
  var verifiedCandidateState = /* @__PURE__ */ new WeakMap();
4702
+ var AGENT_CANDIDATE_EXECUTION_SUPPORT = Object.freeze({
4703
+ outcomes: Object.freeze(["workspace", "output"]),
4704
+ code: Object.freeze(["disabled", "no-op", "git-patch"]),
4705
+ memory: Object.freeze(["disabled", "isolated"]),
4706
+ knowledge: true,
4707
+ profile: Object.freeze({
4708
+ mcpTransports: Object.freeze(["stdio"]),
4709
+ remoteMcp: false,
4710
+ tools: false,
4711
+ permissions: false,
4712
+ modes: false,
4713
+ confidential: false
4714
+ })
4715
+ });
4352
4716
  async function verifyAgentCandidateBundle(input, ports) {
4353
- const parsed = agentCandidateBundleSchema2.parse(input);
4717
+ const parsed = agentCandidateBundleSchema.parse(input);
4354
4718
  const withoutDigest = omitTopLevelDigest(parsed);
4355
4719
  const actualDigest = canonicalCandidateDigest(withoutDigest);
4356
4720
  if (actualDigest !== parsed.digest) {
@@ -4358,6 +4722,7 @@ async function verifyAgentCandidateBundle(input, ports) {
4358
4722
  }
4359
4723
  const canonicalBytes = canonicalCandidateBytes(withoutDigest);
4360
4724
  verifyBytes(canonicalBytes, parsed.digest, canonicalBytes.byteLength, "candidate bundle");
4725
+ assertCandidateProfileExecutionSupport(parsed.profile);
4361
4726
  const artifactBytes = /* @__PURE__ */ new Map();
4362
4727
  const readArtifact = async (artifact) => {
4363
4728
  const key = artifactCacheKey(artifact);
@@ -4454,35 +4819,28 @@ function resourceKey(resource) {
4454
4819
  return canonicalCandidateDigest(resource);
4455
4820
  }
4456
4821
 
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
4822
  // src/candidate-execution/knowledge.ts
4477
- import { mkdtemp as mkdtemp4, rm as rm4 } from "fs/promises";
4478
- import { tmpdir as tmpdir4 } from "os";
4479
- import { join as join4 } from "path";
4823
+ import { mkdtemp as mkdtemp3, rm as rm3 } from "fs/promises";
4824
+ import { tmpdir as tmpdir3 } from "os";
4825
+ import { join as join3, posix } from "path";
4826
+ var CANDIDATE_KNOWLEDGE_ROOT_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_ROOT";
4827
+ var CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG";
4828
+ function candidateKnowledgeExecutionPaths(taskRoot, hasRetrievalConfig) {
4829
+ if (!posix.isAbsolute(taskRoot) || posix.normalize(taskRoot) !== taskRoot) {
4830
+ throw new Error("candidate knowledge requires a normalized absolute task root");
4831
+ }
4832
+ const parent = posix.join(taskRoot, ".tangle");
4833
+ return {
4834
+ root: posix.join(parent, "knowledge"),
4835
+ ...hasRetrievalConfig ? { retrievalConfig: posix.join(parent, "knowledge-retrieval-config.json") } : {}
4836
+ };
4837
+ }
4480
4838
  async function prepareAgentCandidateKnowledge(candidate, ports) {
4481
4839
  const knowledge = candidate.bundle.knowledge;
4482
4840
  if (!knowledge) return void 0;
4483
4841
  const archive = await verifiedArtifactBytes(candidate, knowledge.snapshot.archive);
4484
4842
  const retrievalConfig = knowledge.retrievalConfig ? await verifiedArtifactBytes(candidate, knowledge.retrievalConfig) : void 0;
4485
- const root = await mkdtemp4(join4(tmpdir4(), "agent-candidate-knowledge-"));
4843
+ const root = await mkdtemp3(join3(tmpdir3(), "agent-candidate-knowledge-"));
4486
4844
  try {
4487
4845
  await ports.workspaces.materialize({
4488
4846
  role: "knowledge",
@@ -4502,25 +4860,32 @@ async function prepareAgentCandidateKnowledge(candidate, ports) {
4502
4860
  ...retrievalConfig ? { retrievalConfig: Uint8Array.from(retrievalConfig) } : {}
4503
4861
  });
4504
4862
  } finally {
4505
- await rm4(root, { recursive: true, force: true });
4863
+ await rm3(root, { recursive: true, force: true });
4506
4864
  }
4507
4865
  }
4508
4866
 
4509
4867
  // src/candidate-execution/prepare.ts
4510
- var MATERIALIZER_HARNESSES = /* @__PURE__ */ new Set([
4511
- "claude-code",
4512
- "claude",
4513
- "claudish",
4514
- "nanoclaw",
4515
- "codex",
4516
- "opencode",
4517
- "kimi-code",
4518
- "kimi",
4519
- "pi",
4520
- "gemini",
4521
- "hermes",
4522
- "openclaw"
4523
- ]);
4868
+ import { randomBytes as randomBytes2 } from "crypto";
4869
+ import { lstat as lstat2, readdir as readdir2 } from "fs/promises";
4870
+ import { isAbsolute, posix as posix2, relative as relative2, resolve as resolveHostPath } from "path";
4871
+ import {
4872
+ agentCandidateBenchmarkSuiteSchema as agentCandidateBenchmarkSuiteSchema2,
4873
+ agentCandidateBenchmarkTaskSchema as agentCandidateBenchmarkTaskSchema2,
4874
+ agentCandidateContainerSchema,
4875
+ agentCandidateExecutionLimitsSchema,
4876
+ agentCandidateExecutionPlanEvidenceSchema as agentCandidateExecutionPlanEvidenceSchema2,
4877
+ agentCandidateExecutionPlanMaterialSchema,
4878
+ agentCandidateMaterializationReceiptSchema as agentCandidateMaterializationReceiptSchema2,
4879
+ agentCandidateModelAccessNetworkSchema,
4880
+ agentCandidateRunCellSchema,
4881
+ agentCandidateTaskOutcomeSpecSchema,
4882
+ agentCandidateWorkspaceSnapshotEvidenceSchema as agentCandidateWorkspaceSnapshotEvidenceSchema3,
4883
+ sha256DigestSchema
4884
+ } from "@tangle-network/agent-interface";
4885
+ import {
4886
+ applyAgentCandidateWorkspacePlan,
4887
+ materializeCandidateProfile
4888
+ } from "@tangle-network/agent-profile-materialize";
4524
4889
  var MIN_RESERVATION_TTL_MS = 15 * 6e4;
4525
4890
  var PREPARED_HOLD_MARGIN_MS = 5 * 6e4;
4526
4891
  async function prepareAgentCandidateExecution(candidate, task, ports, options = {}) {
@@ -4528,12 +4893,23 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4528
4893
  const verifiedState = getVerifiedCandidateState(candidate);
4529
4894
  assertSameVerificationPorts(verifiedState.ports, ports);
4530
4895
  const bundle = candidate.bundle;
4531
- assertCandidateProfileExecutionSupport(bundle.profile);
4532
- const harness = materializerHarness(bundle.execution.harness);
4896
+ if (task.runCell.bundleDigest !== bundle.digest) {
4897
+ throw new Error("candidate experiment cell does not bind the verified bundle");
4898
+ }
4899
+ const benchmarkTask = task.task;
4900
+ const attempt = {
4901
+ number: task.runCell.attempt,
4902
+ maxAttempts: benchmarkTask.attempt.maxAttempts,
4903
+ retryPolicy: benchmarkTask.attempt.retryPolicy
4904
+ };
4905
+ const harness = candidateMaterializerHarness(bundle.execution.harness);
4533
4906
  assertTaskInput(task, bundle.execution.instructionDelivery);
4534
- const resultTimeoutMs = candidateResultTimeout(options.resultTimeoutMs, task.limits.timeoutMs);
4907
+ const resultTimeoutMs = candidateResultTimeout(
4908
+ options.resultTimeoutMs,
4909
+ benchmarkTask.limits.timeoutMs
4910
+ );
4535
4911
  const ownerWindowMs = candidateExecutionOwnerWindowMs(
4536
- task.limits.timeoutMs,
4912
+ benchmarkTask.limits.timeoutMs,
4537
4913
  cleanupTimeoutMs,
4538
4914
  resultTimeoutMs
4539
4915
  );
@@ -4542,22 +4918,26 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4542
4918
  throw new Error("candidate reservation window exceeds the supported timer range");
4543
4919
  }
4544
4920
  assertDisjointHostStagingRoots(task);
4545
- const instructionBytes = Buffer.from(task.instruction, "utf8");
4546
- const instructionDigest = sha256Bytes(instructionBytes);
4547
- const taskArtifacts = await verifyWorkspaceSnapshotArtifacts(task.workspace, ports.artifacts);
4921
+ const instructionBytes = Buffer.from(benchmarkTask.instruction, "utf8");
4922
+ const taskArtifacts = await verifyWorkspaceSnapshotArtifacts(
4923
+ benchmarkTask.workspace,
4924
+ ports.artifacts
4925
+ );
4548
4926
  await ports.workspaces.materialize({
4549
4927
  role: "task",
4550
- snapshot: task.workspace,
4928
+ snapshot: benchmarkTask.workspace,
4551
4929
  archive: taskArtifacts.archive,
4552
4930
  destination: task.stagingRoots.taskRoot
4553
4931
  });
4554
- await verifyMaterializedWorkspace(task.stagingRoots.taskRoot, task.workspace.material, {
4932
+ await verifyMaterializedWorkspace(task.stagingRoots.taskRoot, benchmarkTask.workspace.material, {
4555
4933
  ignoredProtectedRootEntries: [".git", ".sidecar"]
4556
4934
  });
4557
- await verifyTaskCheckout(task.stagingRoots.taskRoot, task.repository);
4935
+ if (benchmarkTask.repository) {
4936
+ await verifyTaskCheckout(task.stagingRoots.taskRoot, benchmarkTask.repository);
4937
+ }
4558
4938
  const taskExecutorFiles = await readMaterializedWorkspaceFiles(
4559
4939
  task.stagingRoots.taskRoot,
4560
- task.workspace.material,
4940
+ benchmarkTask.workspace.material,
4561
4941
  { ignoredProtectedRootEntries: [".git", ".sidecar"] }
4562
4942
  );
4563
4943
  let candidateArchive;
@@ -4595,30 +4975,33 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4595
4975
  );
4596
4976
  await verifyMaterializedProfileWorkspace(
4597
4977
  task.stagingRoots.profileRoot,
4598
- profileApplication.profilePlan.material
4978
+ profileApplication.profileActivation.profilePlan.material
4599
4979
  );
4600
4980
  const profilePlanBytes = await readVerifiedArtifact(
4601
- profileApplication.profilePlan.artifact,
4981
+ profileApplication.profileActivation.profilePlan.artifact,
4602
4982
  ports.artifacts
4603
4983
  );
4604
4984
  if (!Buffer.from(profilePlanBytes).equals(
4605
- Buffer.from(canonicalCandidateBytes(profileApplication.profilePlan.material))
4985
+ Buffer.from(
4986
+ canonicalCandidateBytes(profileApplication.profileActivation.profilePlan.material)
4987
+ )
4606
4988
  )) {
4607
4989
  throw new Error("profile materializer did not capture exact canonical plan bytes");
4608
4990
  }
4991
+ const profileActivation = profileApplication.profileActivation;
4609
4992
  const container = await resolveContainer(candidate, task, ports);
4610
4993
  const resolvedModel = await resolveModel(candidate, task, ports);
4611
- const preparationId = `candidate-preparation-v1.${randomBytes2(32).toString("base64url")}`;
4994
+ const preparationId = `candidate-preparation.${randomBytes2(32).toString("base64url")}`;
4612
4995
  const reservationExpiresAtMs = Date.now() + Math.max(MIN_RESERVATION_TTL_MS, reservationWindowMs);
4613
4996
  const modelReservation = await withinCandidateCleanupDeadline(
4614
4997
  () => ports.models.reserveGrant({
4615
4998
  executionId: task.executionId,
4616
4999
  preparationId,
4617
5000
  expiresAtMs: reservationExpiresAtMs,
4618
- attempt: task.attempt,
5001
+ attempt,
4619
5002
  bundleDigest: bundle.digest,
4620
5003
  resolved: resolvedModel,
4621
- limits: modelLimits2(task.limits)
5004
+ limits: modelLimits2(benchmarkTask.limits)
4622
5005
  }),
4623
5006
  candidateCleanupDeadline(cleanupTimeoutMs),
4624
5007
  "protected model reservation"
@@ -4627,7 +5010,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4627
5010
  try {
4628
5011
  validateProtectedModelReservation(
4629
5012
  modelReservation,
4630
- task.limits,
5013
+ benchmarkTask.limits,
4631
5014
  preparationId,
4632
5015
  reservationExpiresAtMs
4633
5016
  );
@@ -4641,6 +5024,10 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4641
5024
  );
4642
5025
  const memory = preparedMemory.value;
4643
5026
  const knowledge = await prepareAgentCandidateKnowledge(candidate, ports);
5027
+ const knowledgePaths = knowledge ? candidateKnowledgeExecutionPaths(
5028
+ task.executionRoots.taskRoot,
5029
+ knowledge.retrievalConfig !== void 0
5030
+ ) : void 0;
4644
5031
  const baseLaunch = buildLaunch(candidate, task, profileApplication.flags);
4645
5032
  const publicEnv = mergePublicEnvironment(
4646
5033
  bundle.execution.env ?? {},
@@ -4650,30 +5037,25 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4650
5037
  kind: "public",
4651
5038
  value: bundle.execution.instructionDelivery.path
4652
5039
  }
5040
+ } : {},
5041
+ knowledgePaths ? {
5042
+ [CANDIDATE_KNOWLEDGE_ROOT_ENV]: {
5043
+ kind: "public",
5044
+ value: knowledgePaths.root
5045
+ },
5046
+ ...knowledgePaths.retrievalConfig ? {
5047
+ [CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV]: {
5048
+ kind: "public",
5049
+ value: knowledgePaths.retrievalConfig
5050
+ }
5051
+ } : {}
4653
5052
  } : {}
4654
5053
  );
4655
- const routes = modelRoutes(bundle.profile, task.model.requested);
5054
+ const routes = modelRoutes(bundle.profile, benchmarkTask.model.requested);
4656
5055
  const executionMaterial = {
4657
- schemaVersion: 2,
4658
5056
  kind: "agent-candidate-execution-plan-material",
4659
- bundleDigest: bundle.digest,
5057
+ runCell: task.runCell,
4660
5058
  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
5059
  workspaces: {
4678
5060
  taskRoot: task.executionRoots.taskRoot,
4679
5061
  ...task.executionRoots.candidateRoot ? { candidateRoot: task.executionRoots.candidateRoot } : {}
@@ -4683,6 +5065,8 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4683
5065
  profile: profileApplication.application,
4684
5066
  harness: bundle.execution.harness,
4685
5067
  harnessVersion: bundle.execution.harnessVersion,
5068
+ instructionDelivery: bundle.execution.instructionDelivery,
5069
+ limits: benchmarkTask.limits,
4686
5070
  container,
4687
5071
  model: {
4688
5072
  policy: "single",
@@ -4694,7 +5078,6 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4694
5078
  },
4695
5079
  routes
4696
5080
  },
4697
- grader: task.grader,
4698
5081
  launch: {
4699
5082
  executable: baseLaunch.executable,
4700
5083
  args: baseLaunch.args,
@@ -4703,7 +5086,6 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4703
5086
  },
4704
5087
  ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
4705
5088
  memory,
4706
- limits: task.limits,
4707
5089
  network: { mode: "disabled" }
4708
5090
  };
4709
5091
  agentCandidateExecutionPlanMaterialSchema.parse(executionMaterial);
@@ -4713,7 +5095,6 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4713
5095
  throw new Error("execution plan canonical serializers disagree");
4714
5096
  }
4715
5097
  const executionPlan = agentCandidateExecutionPlanEvidenceSchema2.parse({
4716
- schemaVersion: 2,
4717
5098
  kind: "agent-candidate-execution-plan",
4718
5099
  digest: executionDigest,
4719
5100
  material: executionMaterial,
@@ -4722,11 +5103,24 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4722
5103
  const entrypoint = candidateEntrypointReceipt(candidate);
4723
5104
  const materializationReceipt = canonicalCandidateDocument(
4724
5105
  {
4725
- schemaVersion: 2,
4726
5106
  kind: "agent-candidate-materialization",
4727
5107
  digestAlgorithm: "rfc8785-sha256",
4728
5108
  bundleDigest: bundle.digest,
4729
- profilePlan: profileApplication.profilePlan,
5109
+ benchmark: {
5110
+ suite: {
5111
+ digest: task.benchmarkSuite.digest,
5112
+ material: embeddedCandidateArtifact(
5113
+ canonicalCandidateBytes(omitTopLevelDigest(task.benchmarkSuite))
5114
+ )
5115
+ },
5116
+ task: {
5117
+ digest: benchmarkTask.digest,
5118
+ material: embeddedCandidateArtifact(
5119
+ canonicalCandidateBytes(omitTopLevelDigest(benchmarkTask))
5120
+ )
5121
+ }
5122
+ },
5123
+ profileActivation,
4730
5124
  executionPlan,
4731
5125
  ...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
4732
5126
  codeKind: bundle.code.kind,
@@ -4740,7 +5134,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4740
5134
  }
4741
5135
  );
4742
5136
  agentCandidateMaterializationReceiptSchema2.parse(materializationReceipt.value);
4743
- const traceRunId = `${task.executionId}:attempt-${task.attempt.number}:${canonicalCandidateDigest({ preparationId }).slice(7, 23)}`;
5137
+ const traceRunId = `${task.executionId}:attempt-${attempt.number}:${canonicalCandidateDigest({ preparationId }).slice(7, 23)}`;
4744
5138
  const traceTags = {
4745
5139
  [CANDIDATE_TRACE_TAGS.executionId]: task.executionId,
4746
5140
  [CANDIDATE_TRACE_TAGS.bundleDigest]: bundle.digest,
@@ -4758,16 +5152,19 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4758
5152
  return createPreparedCandidateExecution({
4759
5153
  ports,
4760
5154
  bundle,
5155
+ benchmarkSuite: task.benchmarkSuite,
5156
+ benchmarkTask,
4761
5157
  executionId: task.executionId,
4762
5158
  roots: {
4763
5159
  execution: { ...task.executionRoots },
4764
5160
  staging: { ...task.stagingRoots }
4765
5161
  },
4766
5162
  profilePlan: {
4767
- value: profileApplication.profilePlan,
5163
+ value: profileApplication.profileActivation.profilePlan,
4768
5164
  bytes: profilePlanBytes,
4769
5165
  written: [...profileApplication.application.mountPaths]
4770
5166
  },
5167
+ profileActivation,
4771
5168
  executionPlan: { value: executionPlan, bytes: executionBytes },
4772
5169
  materializationReceipt,
4773
5170
  launch: {
@@ -4798,7 +5195,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4798
5195
  ...candidateExecutorFiles ? { candidateFiles: candidateExecutorFiles } : {},
4799
5196
  profileFiles: exactProfileExecutorFiles(
4800
5197
  profileWorkspacePlan.files,
4801
- profileApplication.profilePlan.material.files
5198
+ profileApplication.profileActivation.profilePlan.material.files
4802
5199
  )
4803
5200
  },
4804
5201
  ...preparedMemory.accessDigest && preparedMemory.value.mode === "isolated" ? {
@@ -4883,34 +5280,54 @@ function assertSameVerificationPorts(verified, execution) {
4883
5280
  }
4884
5281
  }
4885
5282
  function assertTaskInput(task, delivery) {
5283
+ const benchmarkTask = agentCandidateBenchmarkTaskSchema2.parse(task.task);
5284
+ const benchmarkSuite = agentCandidateBenchmarkSuiteSchema2.parse(task.benchmarkSuite);
5285
+ const runCell = agentCandidateRunCellSchema.parse(task.runCell);
4886
5286
  const requiredStrings = [
4887
5287
  ["executionId", task.executionId],
4888
- ["benchmark", task.benchmark],
4889
- ["benchmarkVersion", task.benchmarkVersion],
4890
- ["taskId", task.taskId],
4891
- ["repository identity", task.repository.identity],
4892
- ["repository root identity", task.repository.rootIdentity]
5288
+ ["benchmark", benchmarkTask.benchmark.name],
5289
+ ["benchmarkVersion", benchmarkTask.benchmark.version],
5290
+ ["taskId", benchmarkTask.scenario.id]
4893
5291
  ];
5292
+ if (benchmarkTask.outcome.kind === "workspace" && !benchmarkTask.repository) {
5293
+ throw new Error("workspace task outcome requires repository identity");
5294
+ }
5295
+ if (benchmarkTask.repository) {
5296
+ requiredStrings.push(
5297
+ ["repository identity", benchmarkTask.repository.identity],
5298
+ ["repository root identity", benchmarkTask.repository.rootIdentity]
5299
+ );
5300
+ }
4894
5301
  for (const [name, value] of requiredStrings) {
4895
5302
  if (!value.trim()) throw new Error(`${name} must be non-empty`);
4896
5303
  }
4897
5304
  if (!/^[A-Za-z0-9._:-]{1,200}$/.test(task.executionId)) {
4898
5305
  throw new Error("executionId must be a stable filesystem-neutral identifier");
4899
5306
  }
4900
- if (!task.instruction || !isWellFormedUnicode(task.instruction)) {
5307
+ if (!benchmarkTask.instruction || !isWellFormedUnicode(benchmarkTask.instruction)) {
4901
5308
  throw new Error("task instruction must be non-empty well-formed Unicode");
4902
5309
  }
4903
- sha256DigestSchema.parse(task.splitDigest);
4904
- agentCandidateWorkspaceSnapshotEvidenceSchema2.parse(task.workspace);
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");
5310
+ if (canonicalCandidateDigest(omitTopLevelDigest(benchmarkTask)) !== benchmarkTask.digest || canonicalCandidateDigest(omitTopLevelDigest(benchmarkSuite)) !== benchmarkSuite.digest || canonicalCandidateDigest(omitTopLevelDigest(runCell)) !== runCell.digest) {
5311
+ throw new Error("candidate experiment cell contains an invalid content digest");
4908
5312
  }
4909
- if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(task.repository.baseTree)) {
4910
- throw new Error("task repository base tree is not a full Git object id");
5313
+ const cellIndex = runCell.taskIndex * benchmarkSuite.reps + runCell.repetition;
5314
+ 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) {
5315
+ throw new Error("candidate experiment cell does not match its signed suite and task");
4911
5316
  }
4912
- if (task.repository.baseCommit.length !== task.repository.baseTree.length) {
4913
- throw new Error("task repository Git object formats disagree");
5317
+ sha256DigestSchema.parse(benchmarkTask.benchmark.splitDigest);
5318
+ agentCandidateTaskOutcomeSpecSchema.parse(benchmarkTask.outcome);
5319
+ agentCandidateWorkspaceSnapshotEvidenceSchema3.parse(benchmarkTask.workspace);
5320
+ agentCandidateExecutionLimitsSchema.parse(benchmarkTask.limits);
5321
+ if (benchmarkTask.repository) {
5322
+ if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(benchmarkTask.repository.baseCommit)) {
5323
+ throw new Error("task repository base commit is not a full Git object id");
5324
+ }
5325
+ if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(benchmarkTask.repository.baseTree)) {
5326
+ throw new Error("task repository base tree is not a full Git object id");
5327
+ }
5328
+ if (benchmarkTask.repository.baseCommit.length !== benchmarkTask.repository.baseTree.length) {
5329
+ throw new Error("task repository Git object formats disagree");
5330
+ }
4914
5331
  }
4915
5332
  for (const [name, root] of [
4916
5333
  ["execution task root", task.executionRoots.taskRoot],
@@ -4920,34 +5337,36 @@ function assertTaskInput(task, delivery) {
4920
5337
  ["staging profile root", task.stagingRoots.profileRoot]
4921
5338
  ]) {
4922
5339
  if (root === void 0) continue;
4923
- const canonical = name.startsWith("execution") ? posix.isAbsolute(root) && posix.normalize(root) === root : isAbsolute(root) && resolveHostPath(root) === root;
5340
+ const canonical = name.startsWith("execution") ? posix2.isAbsolute(root) && posix2.normalize(root) === root : isAbsolute(root) && resolveHostPath(root) === root;
4924
5341
  if (!canonical) throw new Error(`${name} must be a canonical absolute path`);
4925
5342
  }
4926
- if (!Number.isInteger(task.attempt.number) || !Number.isInteger(task.attempt.maxAttempts) || task.attempt.number < 1 || task.attempt.number > task.attempt.maxAttempts || task.attempt.retryPolicy === "none" && task.attempt.maxAttempts !== 1) {
5343
+ 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
5344
  throw new Error("task attempt policy is invalid");
4928
5345
  }
4929
- const limits = task.limits;
5346
+ const limits = benchmarkTask.limits;
4930
5347
  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
5348
  throw new Error("task execution limits are invalid");
4932
5349
  }
4933
5350
  usdToNanos(limits.maxCostUsd, "task maxCostUsd");
4934
- if (!task.model.requested.trim()) throw new Error("evaluator model request must be non-empty");
4935
- if (!task.grader.name.trim() || !task.grader.version.trim()) {
5351
+ if (!benchmarkTask.model.requested.trim()) {
5352
+ throw new Error("evaluator model request must be non-empty");
5353
+ }
5354
+ if (!benchmarkTask.grader.name.trim() || !benchmarkTask.grader.version.trim()) {
4936
5355
  throw new Error("evaluator benchmark grader identity must be non-empty");
4937
5356
  }
4938
- if (!Number.isInteger(task.grader.artifact.byteLength) || task.grader.artifact.byteLength <= 0) {
5357
+ if (!Number.isInteger(benchmarkTask.grader.artifact.byteLength) || benchmarkTask.grader.artifact.byteLength <= 0) {
4939
5358
  throw new Error("evaluator benchmark grader artifact must be non-empty");
4940
5359
  }
4941
- sha256DigestSchema.parse(task.grader.artifact.sha256);
4942
- if (task.evaluatorTaskContainer) {
4943
- if (task.evaluatorTaskContainer.source !== "evaluator-task-container" || !task.evaluatorTaskContainer.image.trim() || !task.evaluatorTaskContainer.platform.os.trim() || !task.evaluatorTaskContainer.platform.architecture.trim()) {
5360
+ sha256DigestSchema.parse(benchmarkTask.grader.artifact.sha256);
5361
+ if (benchmarkTask.evaluatorTaskContainer) {
5362
+ if (benchmarkTask.evaluatorTaskContainer.source !== "evaluator-task-container" || !benchmarkTask.evaluatorTaskContainer.image.trim() || !benchmarkTask.evaluatorTaskContainer.platform.os.trim() || !benchmarkTask.evaluatorTaskContainer.platform.architecture.trim()) {
4944
5363
  throw new Error("evaluator task container evidence is incomplete");
4945
5364
  }
4946
- sha256DigestSchema.parse(task.evaluatorTaskContainer.indexDigest);
4947
- sha256DigestSchema.parse(task.evaluatorTaskContainer.manifestDigest);
5365
+ sha256DigestSchema.parse(benchmarkTask.evaluatorTaskContainer.indexDigest);
5366
+ sha256DigestSchema.parse(benchmarkTask.evaluatorTaskContainer.manifestDigest);
4948
5367
  agentCandidateContainerSchema.parse({
4949
- image: task.evaluatorTaskContainer.image,
4950
- indexDigest: task.evaluatorTaskContainer.indexDigest
5368
+ image: benchmarkTask.evaluatorTaskContainer.image,
5369
+ indexDigest: benchmarkTask.evaluatorTaskContainer.indexDigest
4951
5370
  });
4952
5371
  }
4953
5372
  if (delivery.kind === "utf8-file") {
@@ -4957,8 +5376,8 @@ function assertTaskInput(task, delivery) {
4957
5376
  }
4958
5377
  }
4959
5378
  function executionPathsOverlap(left, right) {
4960
- const a = posix.normalize(left);
4961
- const b = posix.normalize(right);
5379
+ const a = posix2.normalize(left);
5380
+ const b = posix2.normalize(right);
4962
5381
  return a === b || b.startsWith(a === "/" ? "/" : `${a}/`) || a.startsWith(b === "/" ? "/" : `${b}/`);
4963
5382
  }
4964
5383
  function assertDisjointHostStagingRoots(task) {
@@ -4990,51 +5409,45 @@ async function assertEmptyDirectory(path) {
4990
5409
  throw new Error("profile staging root must be empty before materialization");
4991
5410
  }
4992
5411
  }
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
5412
  async function resolveContainer(candidate, task, ports) {
5002
5413
  const environment = candidate.bundle.execution.environment;
5414
+ const evaluatorTaskContainer = task.task.evaluatorTaskContainer;
5003
5415
  const pinned = environment.kind === "pinned-container" ? environment.container : void 0;
5004
- if (environment.kind === "evaluator-task-container" && !task.evaluatorTaskContainer) {
5416
+ if (environment.kind === "evaluator-task-container" && !evaluatorTaskContainer) {
5005
5417
  throw new Error("evaluator-task-container candidate requires an evaluator-owned task image");
5006
5418
  }
5007
- if (environment.kind === "pinned-container" && task.evaluatorTaskContainer) {
5419
+ if (environment.kind === "pinned-container" && evaluatorTaskContainer) {
5008
5420
  throw new Error("pinned candidate containers cannot be replaced by a task image");
5009
5421
  }
5010
5422
  const resolved = await ports.containers.resolve({
5011
5423
  candidate: pinned,
5012
- evaluatorTaskContainer: task.evaluatorTaskContainer
5424
+ evaluatorTaskContainer
5013
5425
  });
5014
5426
  if (resolved.source !== environment.kind) throw new Error("resolved container source drifted");
5015
5427
  if (pinned && (resolved.image !== pinned.image || resolved.indexDigest !== pinned.indexDigest)) {
5016
5428
  throw new Error("resolved pinned container does not match the candidate image index");
5017
5429
  }
5018
- if (task.evaluatorTaskContainer && JSON.stringify(resolved) !== JSON.stringify(task.evaluatorTaskContainer)) {
5430
+ if (evaluatorTaskContainer && canonicalCandidateDigest(resolved) !== canonicalCandidateDigest(evaluatorTaskContainer)) {
5019
5431
  throw new Error("resolved task container does not match evaluator-owned image evidence");
5020
5432
  }
5021
5433
  return resolved;
5022
5434
  }
5023
5435
  async function resolveModel(candidate, task, ports) {
5024
5436
  const hints = candidate.bundle.profile.model;
5025
- if (hints?.default !== void 0 && hints.default !== task.model.requested) {
5437
+ const expected = task.task.model;
5438
+ if (hints?.default !== void 0 && hints.default !== expected.requested) {
5026
5439
  throw new Error("candidate model preference conflicts with the evaluator-owned model");
5027
5440
  }
5028
- if (hints?.reasoningEffort !== void 0 && hints.reasoningEffort !== task.model.reasoningEffort) {
5441
+ if (hints?.reasoningEffort !== void 0 && hints.reasoningEffort !== expected.reasoningEffort) {
5029
5442
  throw new Error("candidate reasoning effort conflicts with the evaluator-owned effort");
5030
5443
  }
5031
5444
  const resolved = await ports.models.resolve({
5032
- requested: task.model.requested,
5445
+ requested: expected.requested,
5033
5446
  harness: candidate.bundle.execution.harness,
5034
- reasoningEffort: task.model.reasoningEffort
5447
+ reasoningEffort: expected.reasoningEffort
5035
5448
  });
5036
- if (resolved.requested !== task.model.requested || resolved.reasoningEffort !== task.model.reasoningEffort) {
5037
- throw new Error("model resolver drifted from the evaluator-owned request");
5449
+ if (canonicalCandidateDigest(resolved) !== canonicalCandidateDigest(expected)) {
5450
+ throw new Error("model resolver drifted from the signed benchmark model");
5038
5451
  }
5039
5452
  return resolved;
5040
5453
  }
@@ -5043,7 +5456,7 @@ async function prepareMemory(candidate, task, ports, preparationId, expiresAtMs,
5043
5456
  if (policy.mode === "disabled") return { value: { mode: "disabled" } };
5044
5457
  const seed = policy.seed ? await verifiedArtifactBytes(candidate, policy.seed) : void 0;
5045
5458
  const executionSegment = canonicalCandidateDigest({ executionId: task.executionId }).slice(7);
5046
- const taskSegment = canonicalCandidateDigest({ taskId: task.taskId }).slice(7);
5459
+ const taskSegment = canonicalCandidateDigest({ taskDigest: task.task.digest }).slice(7);
5047
5460
  const preparationSegment = canonicalCandidateDigest({ preparationId }).slice(7, 23);
5048
5461
  const effectiveNamespace = `candidate/${candidate.bundle.digest.slice(7, 23)}/${executionSegment}/${taskSegment}/${preparationSegment}`;
5049
5462
  const reset = await withinCandidateCleanupDeadline(
@@ -5110,7 +5523,7 @@ function buildLaunch(candidate, task, profileFlags) {
5110
5523
  }
5111
5524
  const candidateRoot = task.executionRoots.candidateRoot;
5112
5525
  if (!candidateRoot) throw new Error("candidate entrypoint requires a container candidate root");
5113
- const entrypoint = posix.join(candidateRoot, launch.entrypoint);
5526
+ const entrypoint = posix2.join(candidateRoot, launch.entrypoint);
5114
5527
  const candidateArgs = launch.args ?? [];
5115
5528
  if (launch.interpreter) {
5116
5529
  return {
@@ -5160,7 +5573,7 @@ function candidateEntrypointReceipt(candidate) {
5160
5573
  function absoluteExecutionCwd(cwd, roots) {
5161
5574
  const root = cwd.workspace === "task" ? roots.taskRoot : roots.candidateRoot;
5162
5575
  if (!root) throw new Error("candidate cwd is missing its execution workspace root");
5163
- const absolute = cwd.path === "." ? root : posix.join(root, cwd.path);
5576
+ const absolute = cwd.path === "." ? root : posix2.join(root, cwd.path);
5164
5577
  if (absolute !== root && !absolute.startsWith(`${root}/`)) {
5165
5578
  throw new Error("candidate cwd escapes its execution workspace");
5166
5579
  }
@@ -5236,20 +5649,19 @@ export {
5236
5649
  canonicalCandidateDigest,
5237
5650
  immutableCandidateValue,
5238
5651
  canonicalCandidateDocument,
5652
+ verifyCanonicalCandidateDocument,
5239
5653
  embeddedCandidateArtifact,
5240
5654
  omitTopLevelDigest,
5241
5655
  deepFreezeCandidate,
5242
- sealAgentCandidateBundle,
5656
+ candidateMaterializerHarness,
5657
+ createAgentCandidateProfileActivation,
5658
+ parseAgentCandidateProfileActivation,
5243
5659
  freezeGenericAgentCandidateProfile,
5244
- assertCandidateProfileBinding,
5245
5660
  parseExactAgentProfile,
5246
5661
  parseExactAgentProfileDiff,
5247
5662
  applyExactAgentProfileDiff,
5248
5663
  parseExactCandidateProfile,
5249
- CLAIM_FORMAT_VERSION,
5250
- PENDING_FORMAT_VERSION,
5251
- TERMINAL_FORMAT_VERSION,
5252
- PHASE_FORMAT_VERSION,
5664
+ agentCandidateProfileAsAgentProfile,
5253
5665
  assertExactObjectKeys,
5254
5666
  terminalRecord,
5255
5667
  recoveredTerminalRecord,
@@ -5264,6 +5676,7 @@ export {
5264
5676
  candidateCleanupTimeout,
5265
5677
  candidateCleanupDeadline,
5266
5678
  withinCandidateCleanupDeadline,
5679
+ readVerifiedArtifact,
5267
5680
  verifyBytes,
5268
5681
  verifyMaterializedWorkspace,
5269
5682
  captureMaterializedWorkspace,
@@ -5281,12 +5694,17 @@ export {
5281
5694
  candidateClaimFileInternals,
5282
5695
  sealAgentCandidateModelSettlement,
5283
5696
  usdToNanos,
5284
- sealAgentCandidateExecutorFinalCapture,
5697
+ sealAgentCandidateExecutorStopAcknowledgement,
5285
5698
  persistCandidateOutputArtifact,
5286
5699
  persistCandidateModelSettlementEvidence,
5287
5700
  RecoveryAgentCandidateTraceStore,
5288
5701
  executePreparedAgentCandidate,
5702
+ AGENT_CANDIDATE_EXECUTION_SUPPORT,
5289
5703
  verifyAgentCandidateBundle,
5704
+ verifiedResourceTextByDigest,
5705
+ CANDIDATE_KNOWLEDGE_ROOT_ENV,
5706
+ CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV,
5707
+ candidateKnowledgeExecutionPaths,
5290
5708
  prepareAgentCandidateExecution
5291
5709
  };
5292
- //# sourceMappingURL=chunk-CNH7DF7Z.js.map
5710
+ //# sourceMappingURL=chunk-WTZ37EQY.js.map