@tangle-network/agent-runtime 0.105.0 → 0.106.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/README.md +2 -2
  2. package/dist/activation-CRjVfOiy.js +203 -0
  3. package/dist/activation-CRjVfOiy.js.map +1 -0
  4. package/dist/activation-DyWB0K6E.d.ts +98 -0
  5. package/dist/agent.d.ts +216 -234
  6. package/dist/agent.js +615 -547
  7. package/dist/agent.js.map +1 -1
  8. package/dist/analyst-loop-DGdtVENg.js +517 -0
  9. package/dist/analyst-loop-DGdtVENg.js.map +1 -0
  10. package/dist/analyst-loop.d.ts +10 -43
  11. package/dist/analyst-loop.js +2 -11
  12. package/dist/backends-CiOCyRHb.js +743 -0
  13. package/dist/backends-CiOCyRHb.js.map +1 -0
  14. package/dist/candidate-execution/index.d.ts +4 -192
  15. package/dist/candidate-execution/index.js +5 -66
  16. package/dist/candidate-execution-DqMbv1rU.js +488 -0
  17. package/dist/candidate-execution-DqMbv1rU.js.map +1 -0
  18. package/dist/coder-yhVWbdWc.js +40 -0
  19. package/dist/coder-yhVWbdWc.js.map +1 -0
  20. package/dist/conversation-BpLQZGPH.js +1265 -0
  21. package/dist/conversation-BpLQZGPH.js.map +1 -0
  22. package/dist/conversation.d.ts +2 -804
  23. package/dist/conversation.js +2 -55
  24. package/dist/environment-provider-CfLUmKmf.js +1168 -0
  25. package/dist/environment-provider-CfLUmKmf.js.map +1 -0
  26. package/dist/environment-provider-IUGU3epE.d.ts +964 -0
  27. package/dist/environment-provider.d.ts +2 -78
  28. package/dist/environment-provider.js +2 -18
  29. package/dist/errors-DEAvWQPy.js +111 -0
  30. package/dist/errors-DEAvWQPy.js.map +1 -0
  31. package/dist/improvement-adapter-Cr5TBSji.d.ts +166 -0
  32. package/dist/improvement-cycle-C095kS_g.js +2624 -0
  33. package/dist/improvement-cycle-C095kS_g.js.map +1 -0
  34. package/dist/index-BGdxAwfO.d.ts +838 -0
  35. package/dist/index-C-FYUuFG.d.ts +193 -0
  36. package/dist/index-CbNM40xG.d.ts +140 -0
  37. package/dist/index-DruSKs3Z.d.ts +7224 -0
  38. package/dist/index-Efjb3nrQ.d.ts +671 -0
  39. package/dist/index.d.ts +14 -1058
  40. package/dist/index.js +2106 -2082
  41. package/dist/index.js.map +1 -1
  42. package/dist/intelligence.d.ts +768 -889
  43. package/dist/intelligence.js +1466 -1367
  44. package/dist/intelligence.js.map +1 -1
  45. package/dist/{kb-gate-CwHO0vz6.d.ts → kb-gate-C8z2juK8.d.ts} +33 -31
  46. package/dist/kb-gate-DpaSwXVx.js +80 -0
  47. package/dist/kb-gate-DpaSwXVx.js.map +1 -0
  48. package/dist/knowledge-Ku-mPP4f.js +433 -0
  49. package/dist/knowledge-Ku-mPP4f.js.map +1 -0
  50. package/dist/knowledge.d.ts +2 -150
  51. package/dist/knowledge.js +2 -40
  52. package/dist/local-harness-Dh8PJ0ot.d.ts +455 -0
  53. package/dist/loop-runner-bin-BXsFEUcf.d.ts +162 -0
  54. package/dist/loop-runner-bin-CRagyuNb.js +268 -0
  55. package/dist/loop-runner-bin-CRagyuNb.js.map +1 -0
  56. package/dist/loop-runner-bin.d.ts +2 -15
  57. package/dist/loop-runner-bin.js +2 -24
  58. package/dist/loops.d.ts +5 -4164
  59. package/dist/loops.js +8 -419
  60. package/dist/mcp/bin.d.ts +1 -1
  61. package/dist/mcp/bin.js +116 -146
  62. package/dist/mcp/bin.js.map +1 -1
  63. package/dist/mcp/index.d.ts +295 -436
  64. package/dist/mcp/index.js +1242 -1177
  65. package/dist/mcp/index.js.map +1 -1
  66. package/dist/mcp/memory-bin.d.ts +1 -1
  67. package/dist/mcp/memory-bin.js +37 -16
  68. package/dist/mcp/memory-bin.js.map +1 -1
  69. package/dist/memory-server-DL6cE2Ag.js +234 -0
  70. package/dist/memory-server-DL6cE2Ag.js.map +1 -0
  71. package/dist/model-resolution-Btd9iIKV.js +98 -0
  72. package/dist/model-resolution-Btd9iIKV.js.map +1 -0
  73. package/dist/openai-tools-B68JaOCx.d.ts +24 -0
  74. package/dist/openai-tools-CKLy1C7M.js +44 -0
  75. package/dist/openai-tools-CKLy1C7M.js.map +1 -0
  76. package/dist/otel-export-D34IQW1C.js +843 -0
  77. package/dist/otel-export-D34IQW1C.js.map +1 -0
  78. package/dist/platform.d.ts +188 -185
  79. package/dist/platform.js +185 -218
  80. package/dist/platform.js.map +1 -1
  81. package/dist/prepare-B53sPV7M.js +4292 -0
  82. package/dist/prepare-B53sPV7M.js.map +1 -0
  83. package/dist/primeintellect/index.d.ts +149 -145
  84. package/dist/primeintellect/index.js +626 -1003
  85. package/dist/primeintellect/index.js.map +1 -1
  86. package/dist/profiles.d.ts +296 -490
  87. package/dist/profiles.js +722 -749
  88. package/dist/profiles.js.map +1 -1
  89. package/dist/protected-model-port-BLPH5VVv.js +722 -0
  90. package/dist/protected-model-port-BLPH5VVv.js.map +1 -0
  91. package/dist/protected-model-port-BP6Z4eau.d.ts +283 -0
  92. package/dist/protected-redaction--F3v1oo8.js +200 -0
  93. package/dist/protected-redaction--F3v1oo8.js.map +1 -0
  94. package/dist/redact-D-u-rrcn.js +82 -0
  95. package/dist/redact-D-u-rrcn.js.map +1 -0
  96. package/dist/redact-kbIOjfjM.d.ts +452 -0
  97. package/dist/researcher-CoVqNhfI.js +433 -0
  98. package/dist/researcher-CoVqNhfI.js.map +1 -0
  99. package/dist/runtime-5zM5XxLr.js +5408 -0
  100. package/dist/runtime-5zM5XxLr.js.map +1 -0
  101. package/dist/sandbox-events-DeI5xX8P.js +316 -0
  102. package/dist/sandbox-events-DeI5xX8P.js.map +1 -0
  103. package/dist/spawn-journal-CwPvKUTa.js +456 -0
  104. package/dist/spawn-journal-CwPvKUTa.js.map +1 -0
  105. package/dist/structural-rollout-IXUEplky.js +1445 -0
  106. package/dist/structural-rollout-IXUEplky.js.map +1 -0
  107. package/dist/substrate-B0TYNrXn.js +27 -0
  108. package/dist/substrate-B0TYNrXn.js.map +1 -0
  109. package/dist/{substrate-Dyiqmd3o.d.ts → substrate-BcnuSHXm.d.ts} +57 -54
  110. package/dist/supervise-BiRutHS9.js +7321 -0
  111. package/dist/supervise-BiRutHS9.js.map +1 -0
  112. package/dist/supervisor-DTKhF-RV.js +3826 -0
  113. package/dist/supervisor-DTKhF-RV.js.map +1 -0
  114. package/dist/testing.d.ts +4 -3
  115. package/dist/testing.js +2478 -2637
  116. package/dist/testing.js.map +1 -1
  117. package/dist/tool-server-RcWgLIsL.js +141 -0
  118. package/dist/tool-server-RcWgLIsL.js.map +1 -0
  119. package/dist/trace-propagation-CJJC7SVB.js +57 -0
  120. package/dist/trace-propagation-CJJC7SVB.js.map +1 -0
  121. package/dist/types-BaIpb0XT.d.ts +492 -0
  122. package/dist/types-BevOjfTY.d.ts +765 -0
  123. package/dist/types-C9j4qg6l.d.ts +500 -0
  124. package/dist/types-Cja5OTGh.d.ts +190 -0
  125. package/dist/util-MVgdwuIS.js +145 -0
  126. package/dist/util-MVgdwuIS.js.map +1 -0
  127. package/dist/workspace-archive-BosQiotA.js +575 -0
  128. package/dist/workspace-archive-BosQiotA.js.map +1 -0
  129. package/package.json +44 -56
  130. package/skills/build-with-agent-runtime/SKILL.md +1 -0
  131. package/dist/activation-Cm-9MMX1.d.ts +0 -69
  132. package/dist/analyst-loop.js.map +0 -1
  133. package/dist/backends-BO4Jqoe2.d.ts +0 -134
  134. package/dist/candidate-execution/index.js.map +0 -1
  135. package/dist/chunk-2KGAN2HM.js +0 -1256
  136. package/dist/chunk-2KGAN2HM.js.map +0 -1
  137. package/dist/chunk-2VZYRB55.js +0 -834
  138. package/dist/chunk-2VZYRB55.js.map +0 -1
  139. package/dist/chunk-3MDZX7YU.js +0 -125
  140. package/dist/chunk-3MDZX7YU.js.map +0 -1
  141. package/dist/chunk-5IBQAPVB.js +0 -29
  142. package/dist/chunk-5IBQAPVB.js.map +0 -1
  143. package/dist/chunk-5QOB7H74.js +0 -387
  144. package/dist/chunk-5QOB7H74.js.map +0 -1
  145. package/dist/chunk-C5RTIBNZ.js +0 -48
  146. package/dist/chunk-C5RTIBNZ.js.map +0 -1
  147. package/dist/chunk-CTRA64LY.js +0 -680
  148. package/dist/chunk-CTRA64LY.js.map +0 -1
  149. package/dist/chunk-DPEUKJRO.js +0 -27
  150. package/dist/chunk-DPEUKJRO.js.map +0 -1
  151. package/dist/chunk-FD2MBMOH.js +0 -494
  152. package/dist/chunk-FD2MBMOH.js.map +0 -1
  153. package/dist/chunk-H5QPIZNX.js +0 -907
  154. package/dist/chunk-H5QPIZNX.js.map +0 -1
  155. package/dist/chunk-HLKC4UYB.js +0 -3514
  156. package/dist/chunk-HLKC4UYB.js.map +0 -1
  157. package/dist/chunk-HNP72PNU.js +0 -192
  158. package/dist/chunk-HNP72PNU.js.map +0 -1
  159. package/dist/chunk-ISPWRSEC.js +0 -408
  160. package/dist/chunk-ISPWRSEC.js.map +0 -1
  161. package/dist/chunk-KRBFHMV6.js +0 -1228
  162. package/dist/chunk-KRBFHMV6.js.map +0 -1
  163. package/dist/chunk-M22PL4GH.js +0 -171
  164. package/dist/chunk-M22PL4GH.js.map +0 -1
  165. package/dist/chunk-NURIQBJQ.js +0 -72
  166. package/dist/chunk-NURIQBJQ.js.map +0 -1
  167. package/dist/chunk-OPVWXJ2H.js +0 -75
  168. package/dist/chunk-OPVWXJ2H.js.map +0 -1
  169. package/dist/chunk-PZZKQVQV.js +0 -52
  170. package/dist/chunk-PZZKQVQV.js.map +0 -1
  171. package/dist/chunk-Q2JSAVQ3.js +0 -671
  172. package/dist/chunk-Q2JSAVQ3.js.map +0 -1
  173. package/dist/chunk-RDOAVVHY.js +0 -699
  174. package/dist/chunk-RDOAVVHY.js.map +0 -1
  175. package/dist/chunk-SGKPNBXE.js +0 -60
  176. package/dist/chunk-SGKPNBXE.js.map +0 -1
  177. package/dist/chunk-SMQXZGLZ.js +0 -351
  178. package/dist/chunk-SMQXZGLZ.js.map +0 -1
  179. package/dist/chunk-UHEZW5BU.js +0 -2918
  180. package/dist/chunk-UHEZW5BU.js.map +0 -1
  181. package/dist/chunk-UPWGXKXB.js +0 -254
  182. package/dist/chunk-UPWGXKXB.js.map +0 -1
  183. package/dist/chunk-VISA6CI3.js +0 -200
  184. package/dist/chunk-VISA6CI3.js.map +0 -1
  185. package/dist/chunk-WMTCUOQL.js +0 -474
  186. package/dist/chunk-WMTCUOQL.js.map +0 -1
  187. package/dist/chunk-WRTOVNN4.js +0 -4728
  188. package/dist/chunk-WRTOVNN4.js.map +0 -1
  189. package/dist/chunk-WSTRQZYQ.js +0 -5576
  190. package/dist/chunk-WSTRQZYQ.js.map +0 -1
  191. package/dist/chunk-XBG2W2VW.js +0 -6434
  192. package/dist/chunk-XBG2W2VW.js.map +0 -1
  193. package/dist/chunk-YEJR7IXO.js +0 -68
  194. package/dist/chunk-YEJR7IXO.js.map +0 -1
  195. package/dist/chunk-YJZA2BIK.js +0 -1338
  196. package/dist/chunk-YJZA2BIK.js.map +0 -1
  197. package/dist/completion-gate-BMy5LGoP.d.ts +0 -256
  198. package/dist/conversation.js.map +0 -1
  199. package/dist/coordination-BZZSVYpZ.d.ts +0 -2570
  200. package/dist/environment-provider.js.map +0 -1
  201. package/dist/improvement-adapter-HAZz-7vK.d.ts +0 -203
  202. package/dist/knowledge.js.map +0 -1
  203. package/dist/local-harness-BDNcl6jI.d.ts +0 -175
  204. package/dist/loop-runner-bin-68aoM9-7.d.ts +0 -199
  205. package/dist/loop-runner-bin.js.map +0 -1
  206. package/dist/loops.js.map +0 -1
  207. package/dist/openai-tools-fnj6SRVg.d.ts +0 -46
  208. package/dist/protected-model-port-B4t-OQjL.d.ts +0 -271
  209. package/dist/redact-BuFjxBUJ.d.ts +0 -481
  210. package/dist/sanitize-DEbPNtyI.d.ts +0 -328
  211. package/dist/structural-rollout-DEh6CEsa.d.ts +0 -446
  212. package/dist/supervise-4_48wwvy.d.ts +0 -379
  213. package/dist/types-BCoemcXU.d.ts +0 -802
  214. package/dist/types-BwoZWq-i.d.ts +0 -510
  215. package/dist/types-Cbp72qyu.d.ts +0 -491
  216. package/dist/types-CmYCMbFT.d.ts +0 -203
  217. package/dist/types-CvNwMzQt.d.ts +0 -957
  218. package/dist/worktree-fanout-DxhAWr5Z.d.ts +0 -999
@@ -0,0 +1,488 @@
1
+ import { $ as parseExactAgentProfile, B as rejectedStage, F as assertTerminalAllowedInPhase, H as sealTerminalDigest, I as assertTerminalMatchesClaim, K as applyExactAgentProfileDiff, L as assertTerminalMatchesStaged, M as candidateCleanupTimeout, N as withinCandidateCleanupDeadline, O as readVerifiedArtifact, P as assertRecoveryMatchesStaged, R as recoveredTerminalRecord, U as terminalRecord, V as requireStagedTerminal, X as freezeGenericAgentCandidateProfile, a as persistCandidateOutputArtifact, b as consumePreparedCandidateExecution, et as parseExactAgentProfileDiff, g as candidateClaimFileInternals, i as persistCandidateModelSettlementEvidence, j as candidateCleanupDeadline, nt as canonicalCandidateBytes, o as sealAgentCandidateExecutorStopAcknowledgement, ot as embeddedCandidateArtifact, p as sealAgentCandidateModelSettlement, r as RecoveryAgentCandidateTraceStore, tt as parseExactCandidateProfile, v as assertPreparedCandidateIntegrity, y as beginPreparedCandidateDisposal, z as rejectedFinish } from "./prepare-B53sPV7M.js";
2
+ import { i as sealAgentCandidateBundle } from "./workspace-archive-BosQiotA.js";
3
+ import "./protected-model-port-BLPH5VVv.js";
4
+ import { verifyCodeSurface } from "@tangle-network/agent-eval/campaign";
5
+ import { agentCandidateExecutionPlanMaterialSchema, agentCandidateMaterializationReceiptSchema } from "@tangle-network/agent-interface";
6
+ import { randomUUID } from "node:crypto";
7
+ import { mkdir, open, unlink } from "node:fs/promises";
8
+ import { linkSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ //#region src/candidate-execution/builder.ts
11
+ /**
12
+ * Compile one measured profile/code candidate into the immutable execution
13
+ * contract. Code bytes are re-read and verified by agent-eval before they are
14
+ * embedded. The returned bundle is schema-validated, canonically digested, and
15
+ * deeply immutable; call `verifyAgentCandidateBundle` at the execution boundary
16
+ * to re-read external memory, repository, and workspace artifacts.
17
+ */
18
+ function buildAgentCandidateBundle(input) {
19
+ return sealAgentCandidateBundle({
20
+ kind: "agent-candidate-bundle",
21
+ digestAlgorithm: "rfc8785-sha256",
22
+ profile: compileCandidateProfile(input.profile),
23
+ code: compileCandidateCode(input.code),
24
+ execution: input.execution,
25
+ ...input.knowledge !== void 0 ? { knowledge: input.knowledge } : {},
26
+ memory: input.memory
27
+ });
28
+ }
29
+ function compileCandidateProfile(source) {
30
+ if (source.kind === "candidate-profile") return parseExactCandidateProfile(source.profile);
31
+ if (source.kind === "profile") return freezeGenericAgentCandidateProfile(source.profile);
32
+ if (source.kind !== "profile-diffs") throw new Error(`unsupported candidate profile source: ${String(source.kind)}`);
33
+ if (source.diffs.length === 0) throw new Error("profile-diffs source requires at least one AgentProfileDiff");
34
+ let profile = parseExactAgentProfile(source.base, "base profile");
35
+ for (const [index, inputDiff] of source.diffs.entries()) {
36
+ const diff = parseExactAgentProfileDiff(inputDiff, `profile diff ${index}`);
37
+ profile = applyExactAgentProfileDiff(profile, diff, `profile diff ${index}`);
38
+ }
39
+ return freezeGenericAgentCandidateProfile(profile);
40
+ }
41
+ function compileCandidateCode(source) {
42
+ if (source.kind === "disabled" || source.kind === "no-op") return source;
43
+ if (source.kind !== "code-surface") throw new Error(`unsupported candidate code source: ${String(source.kind)}`);
44
+ const patch = embeddedCandidateArtifact(verifyCodeSurface(source.surface, source.worktreeDir).patchBytes);
45
+ if (patch.sha256 !== source.surface.patch.sha256 || patch.byteLength !== source.surface.patch.byteLength) throw new Error("verified CodeSurface patch bytes do not match its content identity");
46
+ return {
47
+ kind: "git-patch",
48
+ repository: source.repository,
49
+ baseCommit: source.surface.baseCommit,
50
+ baseTree: source.surface.baseTree,
51
+ candidateTree: source.surface.candidateTree,
52
+ patch: {
53
+ format: "git-diff-binary",
54
+ artifact: patch
55
+ }
56
+ };
57
+ }
58
+ //#endregion
59
+ //#region src/candidate-execution/claim-file-store.ts
60
+ const { assertExpiredLease, assertLease, assertSameSlot, assertUnexpiredLease, attemptRecord, claimSlot, leaseDigest, newLease, readClaim, readClaimIfPresent, readTerminal, readTerminalIfPresent, readTransitionIfPresent, rejectedExistingClaim, rejectedRetry, retryRejection, sealAttemptRef, sealClaim, sealLease } = candidateClaimFileInternals;
61
+ /** Cross-process lifecycle implemented as fsynced, create-if-absent records. */
62
+ var FileAgentCandidateExecutionClaimStore = class {
63
+ directory;
64
+ now;
65
+ constructor(options) {
66
+ if (options.directory.length === 0) throw new Error("candidate execution claim directory must not be empty");
67
+ this.directory = options.directory;
68
+ this.now = options.now ?? Date.now;
69
+ }
70
+ async tryClaim(requested) {
71
+ const claim = sealClaim(requested);
72
+ await mkdir(this.directory, { recursive: true });
73
+ const claimPath = this.claimPath(claim);
74
+ const existing = await readClaimIfPresent(claimPath);
75
+ if (existing) {
76
+ assertSameSlot(existing.claim, claim, claimPath);
77
+ return rejectedExistingClaim(existing.claim, claim);
78
+ }
79
+ assertUnexpiredLease(claim.leaseExpiresAtMs, this.now());
80
+ const retryFailure = await this.retryFailure(claim);
81
+ if (retryFailure) return rejectedRetry(claim, retryFailure);
82
+ const lease = newLease(claim);
83
+ if (await writeRecordIfAbsent(this.directory, claimPath, {
84
+ ...claim,
85
+ phase: "claimed",
86
+ leaseDigest: leaseDigest(lease)
87
+ })) return Object.freeze({
88
+ acquired: true,
89
+ claim,
90
+ lease
91
+ });
92
+ const winner = await readClaim(claimPath);
93
+ assertSameSlot(winner.claim, claim, claimPath);
94
+ return rejectedExistingClaim(winner.claim, claim);
95
+ }
96
+ async getAttempt(requestedAttempt) {
97
+ return await this.storedAttempt(sealAttemptRef(requestedAttempt));
98
+ }
99
+ async markCandidateMayRun(requestedLease) {
100
+ const lease = sealLease(requestedLease);
101
+ const claimPath = this.claimPath(lease);
102
+ const stored = await readClaim(claimPath);
103
+ assertSameSlot(stored.claim, lease, claimPath);
104
+ assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease);
105
+ const state = await this.transitionState(stored.claim);
106
+ if (state.phase === "candidate-may-run") return Object.freeze({
107
+ marked: false,
108
+ phase: "candidate-may-run"
109
+ });
110
+ if (state.staged) throw new Error("candidate execution terminal was staged before candidate-may-run phase");
111
+ assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now());
112
+ if (await writeRecordIfAbsent(this.directory, this.transitionPath(stored.claim, 1), {
113
+ kind: "candidate-execution-phase",
114
+ executionId: stored.claim.executionId,
115
+ attempt: stored.claim.attempt,
116
+ executionPlanDigest: stored.claim.executionPlanDigest,
117
+ phase: "candidate-may-run"
118
+ }, this.ownerPublication(stored.claim))) return Object.freeze({
119
+ marked: true,
120
+ phase: "candidate-may-run"
121
+ });
122
+ if ((await this.transitionState(stored.claim)).phase === "candidate-may-run") return Object.freeze({
123
+ marked: false,
124
+ phase: "candidate-may-run"
125
+ });
126
+ throw new Error("candidate execution terminal was staged before candidate-may-run phase");
127
+ }
128
+ async stageTerminal(requestedLease, result) {
129
+ const lease = sealLease(requestedLease);
130
+ const claimPath = this.claimPath(lease);
131
+ const stored = await readClaim(claimPath);
132
+ assertSameSlot(stored.claim, lease, claimPath);
133
+ assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease);
134
+ const terminal = terminalRecord(stored.claim, result);
135
+ const state = await this.transitionState(stored.claim);
136
+ if (state.staged) return rejectedStage(state.staged, terminal);
137
+ assertTerminalAllowedInPhase(state.phase, terminal);
138
+ assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now());
139
+ const transition = state.phase === "claimed" ? 1 : 2;
140
+ if (await writeRecordIfAbsent(this.directory, this.transitionPath(stored.claim, transition), {
141
+ kind: "candidate-execution-pending-terminal",
142
+ terminal
143
+ }, this.ownerPublication(stored.claim))) return Object.freeze({
144
+ staged: true,
145
+ terminal
146
+ });
147
+ const winner = await this.transitionState(stored.claim);
148
+ if (!winner.staged) throw new Error("candidate execution phase transition won while staging terminal");
149
+ return rejectedStage(winner.staged, terminal);
150
+ }
151
+ async finish(requestedLease, requestedTerminalDigest) {
152
+ const lease = sealLease(requestedLease);
153
+ const terminalDigest = sealTerminalDigest(requestedTerminalDigest);
154
+ const claimPath = this.claimPath(lease);
155
+ const stored = await readClaim(claimPath);
156
+ assertSameSlot(stored.claim, lease, claimPath);
157
+ assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease);
158
+ const staged = requireStagedTerminal((await this.transitionState(stored.claim)).staged, terminalDigest);
159
+ const terminalPath = this.terminalPath(lease);
160
+ const existing = await readTerminalIfPresent(terminalPath);
161
+ if (existing) {
162
+ assertTerminalMatchesClaim(existing, stored.claim, terminalPath);
163
+ assertTerminalMatchesStaged(existing, staged, terminalPath);
164
+ return rejectedFinish(existing, terminalDigest);
165
+ }
166
+ assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now());
167
+ if (await writeRecordIfAbsent(this.directory, terminalPath, { terminal: staged }, this.ownerPublication(stored.claim))) return Object.freeze({
168
+ finished: true,
169
+ terminal: staged
170
+ });
171
+ const winner = await readTerminal(terminalPath);
172
+ assertSameSlot(winner, lease, terminalPath);
173
+ assertTerminalMatchesClaim(winner, stored.claim, terminalPath);
174
+ assertTerminalMatchesStaged(winner, staged, terminalPath);
175
+ return rejectedFinish(winner, terminalDigest);
176
+ }
177
+ async recoverExpired(requestedAttempt, evidence) {
178
+ const attempt = sealAttemptRef(requestedAttempt);
179
+ const record = await this.storedAttempt(attempt);
180
+ if (!record) throw new Error("candidate execution recovery does not name an acquired attempt");
181
+ const recovered = recoveredTerminalRecord(record.claim, record.phase, evidence);
182
+ if (record.staged) assertRecoveryMatchesStaged(record.staged, recovered);
183
+ const requestedDigest = record.staged?.terminalDigest ?? recovered.terminalDigest;
184
+ if (record.terminal) return rejectedFinish(record.terminal, requestedDigest);
185
+ assertExpiredLease(record.claim.leaseExpiresAtMs, this.now());
186
+ let staged = record.staged;
187
+ if (!staged) {
188
+ const transition = record.phase === "claimed" ? 1 : 2;
189
+ if (await writeRecordIfAbsent(this.directory, this.transitionPath(record.claim, transition), {
190
+ kind: "candidate-execution-pending-terminal",
191
+ terminal: recovered
192
+ })) staged = recovered;
193
+ else {
194
+ const winner = await this.transitionState(record.claim);
195
+ if (!winner.staged) throw new Error("candidate execution recovery lost terminal staging to a phase transition");
196
+ assertRecoveryMatchesStaged(winner.staged, recovered);
197
+ staged = winner.staged;
198
+ }
199
+ }
200
+ const terminalPath = this.terminalPath(attempt);
201
+ if (await writeRecordIfAbsent(this.directory, terminalPath, { terminal: staged })) return Object.freeze({
202
+ finished: true,
203
+ terminal: staged
204
+ });
205
+ const winner = await readTerminal(terminalPath);
206
+ assertSameSlot(winner, attempt, terminalPath);
207
+ assertTerminalMatchesClaim(winner, record.claim, terminalPath);
208
+ assertTerminalMatchesStaged(winner, staged, terminalPath);
209
+ return rejectedFinish(winner, staged.terminalDigest);
210
+ }
211
+ async storedAttempt(claim) {
212
+ const claimPath = this.claimPath(claim);
213
+ const stored = await readClaimIfPresent(claimPath);
214
+ if (!stored) return void 0;
215
+ assertSameSlot(stored.claim, claim, claimPath);
216
+ const state = await this.transitionState(stored.claim);
217
+ const terminalPath = this.terminalPath(claim);
218
+ const terminal = await readTerminalIfPresent(terminalPath);
219
+ if (terminal) {
220
+ assertTerminalMatchesClaim(terminal, stored.claim, terminalPath);
221
+ if (!state.staged) throw new Error(`candidate execution terminal record at ${terminalPath} has no staged outbox`);
222
+ assertTerminalMatchesStaged(terminal, state.staged, terminalPath);
223
+ }
224
+ return attemptRecord(stored.claim, state.phase, state.staged, terminal);
225
+ }
226
+ async transitionState(claim) {
227
+ const firstPath = this.transitionPath(claim, 1);
228
+ const first = await readTransitionIfPresent(firstPath, claim);
229
+ if (!first) return { phase: "claimed" };
230
+ if (first.kind === "pending") return {
231
+ phase: "claimed",
232
+ staged: first.terminal
233
+ };
234
+ const secondPath = this.transitionPath(claim, 2);
235
+ const second = await readTransitionIfPresent(secondPath, claim);
236
+ if (!second) return { phase: "candidate-may-run" };
237
+ if (second.kind !== "pending") throw new Error(`candidate execution transition at ${secondPath} repeats the phase marker`);
238
+ return {
239
+ phase: "candidate-may-run",
240
+ staged: second.terminal
241
+ };
242
+ }
243
+ async retryFailure(claim) {
244
+ if (claim.attempt === 1) return void 0;
245
+ return retryRejection(claim, await this.storedAttempt({
246
+ executionId: claim.executionId,
247
+ attempt: claim.attempt - 1
248
+ }));
249
+ }
250
+ ownerPublication(claim) {
251
+ return { authorizePublish: () => {
252
+ assertUnexpiredLease(claim.leaseExpiresAtMs, this.now());
253
+ return true;
254
+ } };
255
+ }
256
+ claimPath(claim) {
257
+ return join(this.directory, `${claimSlot(claim)}.claim.json`);
258
+ }
259
+ terminalPath(claim) {
260
+ return join(this.directory, `${claimSlot(claim)}.terminal.json`);
261
+ }
262
+ transitionPath(claim, ordinal) {
263
+ return join(this.directory, `${claimSlot(claim)}.transition-${ordinal}.json`);
264
+ }
265
+ };
266
+ async function writeRecordIfAbsent(directory, destination, record, options = {}) {
267
+ const temporaryPath = join(directory, `.candidate-execution-${process.pid}-${randomUUID()}.tmp`);
268
+ const handle = await open(temporaryPath, "wx", 384);
269
+ try {
270
+ await handle.writeFile(Buffer.concat([Buffer.from(canonicalCandidateBytes(record)), Buffer.from("\n")]));
271
+ await handle.sync();
272
+ } finally {
273
+ await handle.close();
274
+ }
275
+ let written = false;
276
+ try {
277
+ if (options.authorizePublish && options.authorizePublish() !== true) throw new Error("candidate execution record publication was not authorized");
278
+ linkSync(temporaryPath, destination);
279
+ written = true;
280
+ await syncDirectory(directory);
281
+ } catch (error) {
282
+ if (!isNodeError(error, "EEXIST")) throw error;
283
+ } finally {
284
+ await unlink(temporaryPath).catch((error) => {
285
+ if (!isNodeError(error, "ENOENT")) throw error;
286
+ });
287
+ }
288
+ return written;
289
+ }
290
+ async function syncDirectory(directory) {
291
+ const handle = await open(directory, "r");
292
+ try {
293
+ await handle.sync();
294
+ } finally {
295
+ await handle.close();
296
+ }
297
+ }
298
+ function isNodeError(error, code) {
299
+ return error !== null && typeof error === "object" && "code" in error && error.code === code;
300
+ }
301
+ //#endregion
302
+ //#region src/candidate-execution/dispose.ts
303
+ /** Revoke reservations held by a prepared candidate that will not be executed. */
304
+ async function disposePreparedAgentCandidateExecution(prepared, options = {}) {
305
+ const initialState = assertPreparedCandidateIntegrity(prepared);
306
+ const cleanupTimeoutMs = options.cleanupTimeoutMs ?? initialState.cleanupTimeoutMs;
307
+ if (cleanupTimeoutMs > initialState.cleanupTimeoutMs) throw new Error("disposal cleanup timeout exceeds the frozen preparation bound");
308
+ const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
309
+ const state = beginPreparedCandidateDisposal(prepared);
310
+ const cleanup = [];
311
+ if (state.memory.mode === "isolated") {
312
+ const reservation = state.memoryReservation;
313
+ if (!reservation) throw new Error("isolated memory reservation is missing");
314
+ cleanup.push(withinCandidateCleanupDeadline(async () => {
315
+ const closed = await state.ports.memory.close({
316
+ executionId: state.executionId,
317
+ preparationId: reservation.preparationId,
318
+ accessDigest: reservation.accessDigest,
319
+ effectiveNamespace: reservation.effectiveNamespace,
320
+ reason: "abandoned"
321
+ });
322
+ if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("abandoned isolated memory access did not acknowledge closure");
323
+ }, cleanupDeadlineAtMs, "isolated memory disposal"));
324
+ }
325
+ cleanup.push(withinCandidateCleanupDeadline(async () => {
326
+ if (sealAgentCandidateModelSettlement(await state.ports.models.settleGrant({
327
+ executionId: state.executionId,
328
+ preparationId: state.preparationId,
329
+ grantDigest: state.modelReservation.digest,
330
+ resolved: state.resolvedModel,
331
+ reason: "abandoned"
332
+ }), {
333
+ preparationId: state.preparationId,
334
+ grantDigest: state.modelReservation.digest,
335
+ model: state.resolvedModel.model
336
+ }).usage.modelCalls !== 0) throw new Error("unexecuted model reservation unexpectedly contains calls");
337
+ }, cleanupDeadlineAtMs, "model reservation disposal"));
338
+ const failures = (await Promise.allSettled(cleanup)).filter((result) => result.status === "rejected").map((result) => result.reason);
339
+ if (failures.length > 0) {
340
+ consumePreparedCandidateExecution(prepared, "disposal-failed");
341
+ throw new AggregateError(failures, "candidate preparation disposal failed");
342
+ }
343
+ consumePreparedCandidateExecution(prepared, "disposed");
344
+ return Object.freeze({ disposed: true });
345
+ }
346
+ //#endregion
347
+ //#region src/candidate-execution/recover.ts
348
+ /** Close an expired crashed attempt from persisted non-secret handles, then record failure. */
349
+ async function recoverExpiredAgentCandidateExecution(options) {
350
+ const record = await options.claimStore.getAttempt(options.attempt);
351
+ if (!record) throw new Error("candidate execution recovery attempt is missing");
352
+ if (record.terminal) return Object.freeze({
353
+ finished: false,
354
+ terminal: record.terminal,
355
+ exactReplay: true
356
+ });
357
+ const cleanupTimeoutMs = candidateCleanupTimeout(options.cleanupTimeoutMs ?? record.claim.cleanup.cleanupTimeoutMs);
358
+ if (cleanupTimeoutMs > record.claim.cleanup.cleanupTimeoutMs) throw new Error("recovery cleanup timeout exceeds the frozen preparation bound");
359
+ if ((options.now ?? Date.now)() < record.claim.leaseExpiresAtMs) throw new Error("candidate execution lease has not expired");
360
+ const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
361
+ const recoveryTraceStore = new RecoveryAgentCandidateTraceStore(options.traceStore);
362
+ const preparation = withinCandidateCleanupDeadline(() => readRecoveryPreparation(record.claim, options.outputArtifacts), cleanupDeadlineAtMs, "expired candidate preparation evidence read");
363
+ const processClosure = withinCandidateCleanupDeadline(async (cleanupSignal) => {
364
+ sealAgentCandidateExecutorStopAcknowledgement(await options.executor.stop({
365
+ executionId: record.claim.executionId,
366
+ executionPlanDigest: record.claim.executionPlanDigest
367
+ }, {
368
+ traceStore: recoveryTraceStore,
369
+ reason: "failed",
370
+ signal: cleanupSignal,
371
+ deadlineAtMs: cleanupDeadlineAtMs
372
+ }));
373
+ if (options.executor.dispose) {
374
+ const disposed = await options.executor.dispose({
375
+ executionId: record.claim.executionId,
376
+ executionPlanDigest: record.claim.executionPlanDigest
377
+ }, { signal: cleanupSignal });
378
+ if (disposed.disposed !== true || Object.keys(disposed).some((key) => key !== "disposed")) throw new Error("expired candidate executor did not acknowledge resource disposal");
379
+ }
380
+ return { stopped: true };
381
+ }, cleanupDeadlineAtMs, "expired candidate process termination");
382
+ const modelClosure = withinCandidateCleanupDeadline(async () => sealAgentCandidateModelSettlement(await options.ports.models.settleGrant({
383
+ executionId: record.claim.executionId,
384
+ preparationId: record.claim.cleanup.preparationId,
385
+ grantDigest: record.claim.cleanup.modelGrantDigest,
386
+ resolved: record.claim.cleanup.resolvedModel,
387
+ reason: "failed"
388
+ }), {
389
+ preparationId: record.claim.cleanup.preparationId,
390
+ grantDigest: record.claim.cleanup.modelGrantDigest,
391
+ model: record.claim.cleanup.resolvedModel.model
392
+ }), cleanupDeadlineAtMs, "expired candidate model settlement");
393
+ const memoryClosure = record.claim.cleanup.memory ? withinCandidateCleanupDeadline(async () => {
394
+ const memory = record.claim.cleanup.memory;
395
+ if (!memory) throw new Error("expired candidate memory handle is missing");
396
+ const closed = await options.ports.memory.close({
397
+ executionId: record.claim.executionId,
398
+ preparationId: record.claim.cleanup.preparationId,
399
+ accessDigest: memory.accessDigest,
400
+ effectiveNamespace: memory.effectiveNamespace,
401
+ reason: "failed"
402
+ });
403
+ if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("expired candidate memory did not acknowledge closure");
404
+ return { closed: true };
405
+ }, cleanupDeadlineAtMs, "expired candidate memory closure") : void 0;
406
+ const closureOutcomes = Promise.allSettled([modelClosure, memoryClosure ?? Promise.resolve(void 0)]);
407
+ const [preparationOutcome, processOutcome] = await Promise.allSettled([preparation, processClosure]);
408
+ const failures = [preparationOutcome, processOutcome].filter((outcome) => outcome.status === "rejected").map((outcome) => outcome.reason);
409
+ const [modelOutcome, memoryOutcome] = await closureOutcomes;
410
+ for (const outcome of [modelOutcome, memoryOutcome]) if (outcome.status === "rejected") failures.push(outcome.reason);
411
+ if (failures.length > 0) throw new AggregateError(failures, "expired candidate cleanup could not be proven");
412
+ if (modelOutcome.status !== "fulfilled") throw new Error("expired candidate model settlement was not recovered");
413
+ const model = modelOutcome.value;
414
+ const modelSettlement = await withinCandidateCleanupDeadline(() => persistCandidateModelSettlementEvidence({
415
+ executionId: record.claim.executionId,
416
+ executionPlanDigest: record.claim.executionPlanDigest,
417
+ resolvedModel: record.claim.cleanup.resolvedModel
418
+ }, model, options.outputArtifacts), cleanupDeadlineAtMs, "expired candidate model-settlement persistence");
419
+ const failureClass = record.phase === "claimed" && model.usage.modelCalls === 0 ? "pre-model-infrastructure" : "unknown";
420
+ const failureEvidence = await withinCandidateCleanupDeadline(() => persistCandidateOutputArtifact(options.outputArtifacts, {
421
+ executionId: record.claim.executionId,
422
+ purpose: "failure-evidence",
423
+ bytes: canonicalCandidateBytes({
424
+ kind: "agent-candidate-recovery-failure",
425
+ executionId: record.claim.executionId,
426
+ attempt: record.claim.attempt,
427
+ bundleDigest: record.claim.bundleDigest,
428
+ executionPlanDigest: record.claim.executionPlanDigest,
429
+ materializationReceiptDigest: record.claim.preparationEvidence.materializationReceipt.sha256,
430
+ failureClass,
431
+ processStopped: true,
432
+ modelSettlementDigest: modelSettlement.digest,
433
+ memoryClosed: record.claim.cleanup.memory !== void 0
434
+ })
435
+ }), cleanupDeadlineAtMs, "expired candidate failure-evidence persistence");
436
+ const memory = record.claim.cleanup.memory;
437
+ return await options.claimStore.recoverExpired(options.attempt, {
438
+ failureClass,
439
+ usage: model.usage,
440
+ modelSettlement: modelSettlement.artifact,
441
+ failureEvidence,
442
+ process: {
443
+ stopped: true,
444
+ executionPlanDigest: record.claim.executionPlanDigest
445
+ },
446
+ model: {
447
+ closed: true,
448
+ preparationId: record.claim.cleanup.preparationId,
449
+ grantDigest: record.claim.cleanup.modelGrantDigest
450
+ },
451
+ ...memory ? { memory: {
452
+ closed: true,
453
+ preparationId: record.claim.cleanup.preparationId,
454
+ accessDigest: memory.accessDigest,
455
+ effectiveNamespace: memory.effectiveNamespace
456
+ } } : {}
457
+ });
458
+ }
459
+ async function readRecoveryPreparation(claim, artifacts) {
460
+ const [planBytes, receiptBytes] = await Promise.all([readVerifiedArtifact(claim.preparationEvidence.executionPlan, artifacts), readVerifiedArtifact(claim.preparationEvidence.materializationReceipt, artifacts)]);
461
+ const plan = agentCandidateExecutionPlanMaterialSchema.parse(parseCanonicalBytes(planBytes, "plan"));
462
+ if (claim.preparationEvidence.executionPlan.sha256 !== claim.executionPlanDigest) throw new Error("recovery execution plan artifact does not match the claimed digest");
463
+ const receiptMaterial = parseCanonicalBytes(receiptBytes, "materialization receipt");
464
+ const receipt = agentCandidateMaterializationReceiptSchema.parse({
465
+ ...receiptMaterial,
466
+ digest: claim.preparationEvidence.materializationReceipt.sha256
467
+ });
468
+ if (receipt.bundleDigest !== claim.bundleDigest || receipt.executionPlan.digest !== claim.executionPlanDigest || plan.runCell.bundleDigest !== claim.bundleDigest || plan.executionId !== claim.executionId) throw new Error("recovery preparation evidence does not match the durable claim");
469
+ return {
470
+ plan,
471
+ receipt
472
+ };
473
+ }
474
+ function parseCanonicalBytes(bytes, label) {
475
+ let parsed;
476
+ try {
477
+ parsed = JSON.parse(Buffer.from(bytes).toString("utf8"));
478
+ } catch (error) {
479
+ throw new Error(`candidate recovery ${label} is not JSON`, { cause: error });
480
+ }
481
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`candidate recovery ${label} must be an object`);
482
+ if (!Buffer.from(canonicalCandidateBytes(parsed)).equals(Buffer.from(bytes))) throw new Error(`candidate recovery ${label} bytes are not canonical`);
483
+ return parsed;
484
+ }
485
+ //#endregion
486
+ export { buildAgentCandidateBundle as i, disposePreparedAgentCandidateExecution as n, FileAgentCandidateExecutionClaimStore as r, recoverExpiredAgentCandidateExecution as t };
487
+
488
+ //# sourceMappingURL=candidate-execution-DqMbv1rU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidate-execution-DqMbv1rU.js","names":[],"sources":["../src/candidate-execution/builder.ts","../src/candidate-execution/claim-file-store.ts","../src/candidate-execution/dispose.ts","../src/candidate-execution/recover.ts"],"sourcesContent":["import type { CodeSurface } from '@tangle-network/agent-eval/campaign'\nimport { verifyCodeSurface } from '@tangle-network/agent-eval/campaign'\nimport type {\n AgentCandidateCodeDisabled,\n AgentCandidateCodeNoOp,\n AgentCandidateExecution,\n AgentCandidateGitHubRepository,\n AgentCandidateKnowledge,\n AgentCandidateMemoryPolicy,\n AgentCandidateProfile,\n AgentProfile,\n AgentProfileDiff,\n} from '@tangle-network/agent-interface'\nimport { type AgentCandidateBundleInput, sealAgentCandidateBundle } from './bundle'\nimport { embeddedCandidateArtifact } from './digest'\nimport {\n applyExactAgentProfileDiff,\n freezeGenericAgentCandidateProfile,\n parseExactAgentProfile,\n parseExactAgentProfileDiff,\n parseExactCandidateProfile,\n} from './profile'\n\n/** A complete profile that can be frozen without losing behavior. */\nexport type AgentCandidateProfileSource =\n | {\n kind: 'profile'\n profile: AgentProfile\n }\n | {\n kind: 'profile-diffs'\n base: AgentProfile\n /** Applied in order before the resulting profile is frozen into the bundle. */\n diffs: readonly AgentProfileDiff[]\n }\n | {\n kind: 'candidate-profile'\n /** Already converted to the closed, secret-free candidate profile contract. */\n profile: AgentCandidateProfile\n }\n\n/** The only accepted path from an agent-eval code candidate to executable bytes. */\nexport interface AgentCandidateCodeSurfaceSource {\n kind: 'code-surface'\n surface: CodeSurface\n repository: AgentCandidateGitHubRepository\n /** Optional parent directory used to resolve a relative `surface.worktreeRef`. */\n worktreeDir?: string\n}\n\n/** Explicit control/no-op code or one finalized CodeSurface whose bytes must still verify. */\nexport type AgentCandidateCodeSource =\n | AgentCandidateCodeDisabled\n | AgentCandidateCodeNoOp\n | AgentCandidateCodeSurfaceSource\n\n/** Complete measured surfaces and execution policy compiled into one candidate bundle. */\nexport interface BuildAgentCandidateBundleInput {\n profile: AgentCandidateProfileSource\n code: AgentCandidateCodeSource\n execution: AgentCandidateExecution\n knowledge?: AgentCandidateKnowledge\n memory: AgentCandidateMemoryPolicy\n}\n\n/**\n * Compile one measured profile/code candidate into the immutable execution\n * contract. Code bytes are re-read and verified by agent-eval before they are\n * embedded. The returned bundle is schema-validated, canonically digested, and\n * deeply immutable; call `verifyAgentCandidateBundle` at the execution boundary\n * to re-read external memory, repository, and workspace artifacts.\n */\nexport function buildAgentCandidateBundle(\n input: BuildAgentCandidateBundleInput,\n): ReturnType<typeof sealAgentCandidateBundle> {\n const bundle: AgentCandidateBundleInput = {\n kind: 'agent-candidate-bundle',\n digestAlgorithm: 'rfc8785-sha256',\n profile: compileCandidateProfile(input.profile),\n code: compileCandidateCode(input.code),\n execution: input.execution,\n ...(input.knowledge !== undefined ? { knowledge: input.knowledge } : {}),\n memory: input.memory,\n }\n return sealAgentCandidateBundle(bundle)\n}\n\nfunction compileCandidateProfile(source: AgentCandidateProfileSource): AgentCandidateProfile {\n if (source.kind === 'candidate-profile') {\n return parseExactCandidateProfile(source.profile)\n }\n\n if (source.kind === 'profile') {\n return freezeGenericAgentCandidateProfile(source.profile)\n }\n\n if (source.kind !== 'profile-diffs') {\n throw new Error(\n `unsupported candidate profile source: ${String((source as { kind?: unknown }).kind)}`,\n )\n }\n if (source.diffs.length === 0) {\n throw new Error('profile-diffs source requires at least one AgentProfileDiff')\n }\n let profile = parseExactAgentProfile(source.base, 'base profile')\n for (const [index, inputDiff] of source.diffs.entries()) {\n const diff = parseExactAgentProfileDiff(inputDiff, `profile diff ${index}`)\n profile = applyExactAgentProfileDiff(profile, diff, `profile diff ${index}`)\n }\n return freezeGenericAgentCandidateProfile(profile)\n}\n\nfunction compileCandidateCode(source: AgentCandidateCodeSource): AgentCandidateBundleInput['code'] {\n if (source.kind === 'disabled' || source.kind === 'no-op') return source\n if (source.kind !== 'code-surface') {\n throw new Error(\n `unsupported candidate code source: ${String((source as { kind?: unknown }).kind)}`,\n )\n }\n\n const verified = verifyCodeSurface(source.surface, source.worktreeDir)\n const patch = embeddedCandidateArtifact(verified.patchBytes)\n if (\n patch.sha256 !== source.surface.patch.sha256 ||\n patch.byteLength !== source.surface.patch.byteLength\n ) {\n throw new Error('verified CodeSurface patch bytes do not match its content identity')\n }\n return {\n kind: 'git-patch',\n repository: source.repository,\n baseCommit: source.surface.baseCommit,\n baseTree: source.surface.baseTree,\n candidateTree: source.surface.candidateTree,\n patch: { format: 'git-diff-binary', artifact: patch },\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { linkSync } from 'node:fs'\nimport { mkdir, open, unlink } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { Sha256Digest } from '@tangle-network/agent-interface'\n\nimport {\n type AgentCandidateExecutionAttemptRecord,\n type AgentCandidateExecutionAttemptRef,\n type AgentCandidateExecutionClaim,\n type AgentCandidateExecutionClaimResult,\n type AgentCandidateExecutionClaimStore,\n type AgentCandidateExecutionFinishResult,\n type AgentCandidateExecutionLease,\n type AgentCandidateExecutionPhase,\n type AgentCandidateExecutionPhaseResult,\n type AgentCandidateExecutionRecoveryEvidence,\n type AgentCandidateExecutionStageResult,\n type AgentCandidateExecutionTerminalRecord,\n type AgentCandidateExecutionTerminalResult,\n type AgentCandidateRetryRejection,\n candidateClaimFileInternals,\n} from './claim'\nimport {\n assertRecoveryMatchesStaged,\n assertTerminalAllowedInPhase,\n assertTerminalMatchesClaim,\n assertTerminalMatchesStaged,\n recoveredTerminalRecord,\n rejectedFinish,\n rejectedStage,\n requireStagedTerminal,\n sealTerminalDigest,\n terminalRecord,\n} from './claim-terminal'\nimport { canonicalCandidateBytes } from './digest'\n\nconst {\n assertExpiredLease,\n assertLease,\n assertSameSlot,\n assertUnexpiredLease,\n attemptRecord,\n claimSlot,\n leaseDigest,\n newLease,\n readClaim,\n readClaimIfPresent,\n readTerminal,\n readTerminalIfPresent,\n readTransitionIfPresent,\n rejectedExistingClaim,\n rejectedRetry,\n retryRejection,\n sealAttemptRef,\n sealClaim,\n sealLease,\n} = candidateClaimFileInternals\n\nexport interface FileAgentCandidateExecutionClaimStoreOptions {\n /** Evaluator-owned directory shared by every process allowed to execute candidates. */\n directory: string\n /** Testable evaluator clock; defaults to `Date.now`. */\n now?: () => number\n}\n\n/** Cross-process lifecycle implemented as fsynced, create-if-absent records. */\nexport class FileAgentCandidateExecutionClaimStore implements AgentCandidateExecutionClaimStore {\n private readonly directory: string\n private readonly now: () => number\n\n constructor(options: FileAgentCandidateExecutionClaimStoreOptions) {\n if (options.directory.length === 0) {\n throw new Error('candidate execution claim directory must not be empty')\n }\n this.directory = options.directory\n this.now = options.now ?? Date.now\n }\n\n async tryClaim(\n requested: AgentCandidateExecutionClaim,\n ): Promise<AgentCandidateExecutionClaimResult> {\n const claim = sealClaim(requested)\n await mkdir(this.directory, { recursive: true })\n const claimPath = this.claimPath(claim)\n const existing = await readClaimIfPresent(claimPath)\n if (existing) {\n assertSameSlot(existing.claim, claim, claimPath)\n return rejectedExistingClaim(existing.claim, claim)\n }\n assertUnexpiredLease(claim.leaseExpiresAtMs, this.now())\n const retryFailure = await this.retryFailure(claim)\n if (retryFailure) return rejectedRetry(claim, retryFailure)\n\n const lease = newLease(claim)\n const acquired = await writeRecordIfAbsent(this.directory, claimPath, {\n ...claim,\n phase: 'claimed',\n leaseDigest: leaseDigest(lease),\n })\n if (acquired) return Object.freeze({ acquired: true, claim, lease })\n\n const winner = await readClaim(claimPath)\n assertSameSlot(winner.claim, claim, claimPath)\n return rejectedExistingClaim(winner.claim, claim)\n }\n\n async getAttempt(\n requestedAttempt: AgentCandidateExecutionAttemptRef,\n ): Promise<AgentCandidateExecutionAttemptRecord | undefined> {\n return await this.storedAttempt(sealAttemptRef(requestedAttempt))\n }\n\n async markCandidateMayRun(\n requestedLease: AgentCandidateExecutionLease,\n ): Promise<AgentCandidateExecutionPhaseResult> {\n const lease = sealLease(requestedLease)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const state = await this.transitionState(stored.claim)\n if (state.phase === 'candidate-may-run') {\n return Object.freeze({ marked: false, phase: 'candidate-may-run' })\n }\n if (state.staged) {\n throw new Error('candidate execution terminal was staged before candidate-may-run phase')\n }\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const marked = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(stored.claim, 1),\n {\n kind: 'candidate-execution-phase',\n executionId: stored.claim.executionId,\n attempt: stored.claim.attempt,\n executionPlanDigest: stored.claim.executionPlanDigest,\n phase: 'candidate-may-run',\n },\n this.ownerPublication(stored.claim),\n )\n if (marked) return Object.freeze({ marked: true, phase: 'candidate-may-run' })\n const winner = await this.transitionState(stored.claim)\n if (winner.phase === 'candidate-may-run') {\n return Object.freeze({ marked: false, phase: 'candidate-may-run' })\n }\n throw new Error('candidate execution terminal was staged before candidate-may-run phase')\n }\n\n async stageTerminal(\n requestedLease: AgentCandidateExecutionLease,\n result: AgentCandidateExecutionTerminalResult,\n ): Promise<AgentCandidateExecutionStageResult> {\n const lease = sealLease(requestedLease)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const terminal = terminalRecord(stored.claim, result)\n const state = await this.transitionState(stored.claim)\n if (state.staged) return rejectedStage(state.staged, terminal)\n assertTerminalAllowedInPhase(state.phase, terminal)\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const transition = state.phase === 'claimed' ? 1 : 2\n const staged = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(stored.claim, transition),\n {\n kind: 'candidate-execution-pending-terminal',\n terminal,\n },\n this.ownerPublication(stored.claim),\n )\n if (staged) return Object.freeze({ staged: true, terminal })\n const winner = await this.transitionState(stored.claim)\n if (!winner.staged) {\n throw new Error('candidate execution phase transition won while staging terminal')\n }\n return rejectedStage(winner.staged, terminal)\n }\n\n async finish(\n requestedLease: AgentCandidateExecutionLease,\n requestedTerminalDigest: Sha256Digest,\n ): Promise<AgentCandidateExecutionFinishResult> {\n const lease = sealLease(requestedLease)\n const terminalDigest = sealTerminalDigest(requestedTerminalDigest)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const state = await this.transitionState(stored.claim)\n const staged = requireStagedTerminal(state.staged, terminalDigest)\n const terminalPath = this.terminalPath(lease)\n const existing = await readTerminalIfPresent(terminalPath)\n if (existing) {\n assertTerminalMatchesClaim(existing, stored.claim, terminalPath)\n assertTerminalMatchesStaged(existing, staged, terminalPath)\n return rejectedFinish(existing, terminalDigest)\n }\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const finished = await writeRecordIfAbsent(\n this.directory,\n terminalPath,\n {\n terminal: staged,\n },\n this.ownerPublication(stored.claim),\n )\n if (finished) return Object.freeze({ finished: true, terminal: staged })\n const winner = await readTerminal(terminalPath)\n assertSameSlot(winner, lease, terminalPath)\n assertTerminalMatchesClaim(winner, stored.claim, terminalPath)\n assertTerminalMatchesStaged(winner, staged, terminalPath)\n return rejectedFinish(winner, terminalDigest)\n }\n\n async recoverExpired(\n requestedAttempt: AgentCandidateExecutionAttemptRef,\n evidence: AgentCandidateExecutionRecoveryEvidence,\n ): Promise<AgentCandidateExecutionFinishResult> {\n const attempt = sealAttemptRef(requestedAttempt)\n const record = await this.storedAttempt(attempt)\n if (!record) throw new Error('candidate execution recovery does not name an acquired attempt')\n const recovered = recoveredTerminalRecord(record.claim, record.phase, evidence)\n if (record.staged) assertRecoveryMatchesStaged(record.staged, recovered)\n const requestedDigest = record.staged?.terminalDigest ?? recovered.terminalDigest\n if (record.terminal) return rejectedFinish(record.terminal, requestedDigest)\n assertExpiredLease(record.claim.leaseExpiresAtMs, this.now())\n\n let staged = record.staged\n if (!staged) {\n const transition = record.phase === 'claimed' ? 1 : 2\n const didStage = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(record.claim, transition),\n {\n kind: 'candidate-execution-pending-terminal',\n terminal: recovered,\n },\n )\n if (didStage) {\n staged = recovered\n } else {\n const winner = await this.transitionState(record.claim)\n if (!winner.staged) {\n throw new Error(\n 'candidate execution recovery lost terminal staging to a phase transition',\n )\n }\n assertRecoveryMatchesStaged(winner.staged, recovered)\n staged = winner.staged\n }\n }\n\n const terminalPath = this.terminalPath(attempt)\n const didFinish = await writeRecordIfAbsent(this.directory, terminalPath, {\n terminal: staged,\n })\n if (didFinish) return Object.freeze({ finished: true, terminal: staged })\n const winner = await readTerminal(terminalPath)\n assertSameSlot(winner, attempt, terminalPath)\n assertTerminalMatchesClaim(winner, record.claim, terminalPath)\n assertTerminalMatchesStaged(winner, staged, terminalPath)\n return rejectedFinish(winner, staged.terminalDigest)\n }\n\n private async storedAttempt(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ): Promise<AgentCandidateExecutionAttemptRecord | undefined> {\n const claimPath = this.claimPath(claim)\n const stored = await readClaimIfPresent(claimPath)\n if (!stored) return undefined\n assertSameSlot(stored.claim, claim, claimPath)\n const state = await this.transitionState(stored.claim)\n const terminalPath = this.terminalPath(claim)\n const terminal = await readTerminalIfPresent(terminalPath)\n if (terminal) {\n assertTerminalMatchesClaim(terminal, stored.claim, terminalPath)\n if (!state.staged) {\n throw new Error(\n `candidate execution terminal record at ${terminalPath} has no staged outbox`,\n )\n }\n assertTerminalMatchesStaged(terminal, state.staged, terminalPath)\n }\n return attemptRecord(stored.claim, state.phase, state.staged, terminal)\n }\n\n private async transitionState(claim: AgentCandidateExecutionClaim): Promise<{\n phase: AgentCandidateExecutionPhase\n staged?: AgentCandidateExecutionTerminalRecord\n }> {\n const firstPath = this.transitionPath(claim, 1)\n const first = await readTransitionIfPresent(firstPath, claim)\n if (!first) return { phase: 'claimed' }\n if (first.kind === 'pending') return { phase: 'claimed', staged: first.terminal }\n const secondPath = this.transitionPath(claim, 2)\n const second = await readTransitionIfPresent(secondPath, claim)\n if (!second) return { phase: 'candidate-may-run' }\n if (second.kind !== 'pending') {\n throw new Error(`candidate execution transition at ${secondPath} repeats the phase marker`)\n }\n return { phase: 'candidate-may-run', staged: second.terminal }\n }\n\n private async retryFailure(\n claim: AgentCandidateExecutionClaim,\n ): Promise<AgentCandidateRetryRejection | undefined> {\n if (claim.attempt === 1) return undefined\n return retryRejection(\n claim,\n await this.storedAttempt({\n executionId: claim.executionId,\n attempt: claim.attempt - 1,\n }),\n )\n }\n\n private ownerPublication(claim: AgentCandidateExecutionClaim): {\n authorizePublish: () => true\n } {\n return {\n authorizePublish: () => {\n assertUnexpiredLease(claim.leaseExpiresAtMs, this.now())\n return true\n },\n }\n }\n\n private claimPath(claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>): string {\n return join(this.directory, `${claimSlot(claim)}.claim.json`)\n }\n\n private terminalPath(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ): string {\n return join(this.directory, `${claimSlot(claim)}.terminal.json`)\n }\n\n private transitionPath(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ordinal: 1 | 2,\n ): string {\n return join(this.directory, `${claimSlot(claim)}.transition-${ordinal}.json`)\n }\n}\n\nasync function writeRecordIfAbsent(\n directory: string,\n destination: string,\n record: object,\n options: {\n /** Synchronous authorization checked after temp fsync, immediately before atomic publication. */\n authorizePublish?: () => true\n } = {},\n): Promise<boolean> {\n const temporaryPath = join(directory, `.candidate-execution-${process.pid}-${randomUUID()}.tmp`)\n const handle = await open(temporaryPath, 'wx', 0o600)\n try {\n await handle.writeFile(\n Buffer.concat([Buffer.from(canonicalCandidateBytes(record)), Buffer.from('\\n')]),\n )\n await handle.sync()\n } finally {\n await handle.close()\n }\n\n let written = false\n try {\n if (options.authorizePublish && options.authorizePublish() !== true) {\n throw new Error('candidate execution record publication was not authorized')\n }\n // Authorization and the atomic filesystem call are one synchronous critical\n // section so the event loop cannot advance an injected lease clock between them.\n linkSync(temporaryPath, destination)\n written = true\n await syncDirectory(directory)\n } catch (error) {\n if (!isNodeError(error, 'EEXIST')) throw error\n } finally {\n await unlink(temporaryPath).catch((error: unknown) => {\n if (!isNodeError(error, 'ENOENT')) throw error\n })\n }\n return written\n}\n\nasync function syncDirectory(directory: string): Promise<void> {\n const handle = await open(directory, 'r')\n try {\n await handle.sync()\n } finally {\n await handle.close()\n }\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return (\n error !== null &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as { code?: unknown }).code === code\n )\n}\n","import { candidateCleanupDeadline, withinCandidateCleanupDeadline } from './cleanup'\nimport { sealAgentCandidateModelSettlement } from './model-settlement'\nimport {\n assertPreparedCandidateIntegrity,\n beginPreparedCandidateDisposal,\n consumePreparedCandidateExecution,\n} from './prepared-state'\nimport type { PreparedAgentCandidateExecution } from './types'\n\nexport interface DisposePreparedAgentCandidateOptions {\n cleanupTimeoutMs?: number\n}\n\n/** Revoke reservations held by a prepared candidate that will not be executed. */\nexport async function disposePreparedAgentCandidateExecution(\n prepared: PreparedAgentCandidateExecution,\n options: DisposePreparedAgentCandidateOptions = {},\n): Promise<{ disposed: true }> {\n const initialState = assertPreparedCandidateIntegrity(prepared)\n const cleanupTimeoutMs = options.cleanupTimeoutMs ?? initialState.cleanupTimeoutMs\n if (cleanupTimeoutMs > initialState.cleanupTimeoutMs) {\n throw new Error('disposal cleanup timeout exceeds the frozen preparation bound')\n }\n const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs)\n const state = beginPreparedCandidateDisposal(prepared)\n const cleanup: Array<Promise<unknown>> = []\n\n if (state.memory.mode === 'isolated') {\n const reservation = state.memoryReservation\n if (!reservation) throw new Error('isolated memory reservation is missing')\n cleanup.push(\n withinCandidateCleanupDeadline(\n async () => {\n const closed = await state.ports.memory.close({\n executionId: state.executionId,\n preparationId: reservation.preparationId,\n accessDigest: reservation.accessDigest,\n effectiveNamespace: reservation.effectiveNamespace,\n reason: 'abandoned',\n })\n if (closed.closed !== true || Object.keys(closed).some((key) => key !== 'closed')) {\n throw new Error('abandoned isolated memory access did not acknowledge closure')\n }\n },\n cleanupDeadlineAtMs,\n 'isolated memory disposal',\n ),\n )\n }\n\n cleanup.push(\n withinCandidateCleanupDeadline(\n async () => {\n const settlement = sealAgentCandidateModelSettlement(\n await state.ports.models.settleGrant({\n executionId: state.executionId,\n preparationId: state.preparationId,\n grantDigest: state.modelReservation.digest,\n resolved: state.resolvedModel,\n reason: 'abandoned',\n }),\n {\n preparationId: state.preparationId,\n grantDigest: state.modelReservation.digest,\n model: state.resolvedModel.model,\n },\n )\n if (settlement.usage.modelCalls !== 0) {\n throw new Error('unexecuted model reservation unexpectedly contains calls')\n }\n },\n cleanupDeadlineAtMs,\n 'model reservation disposal',\n ),\n )\n\n const results = await Promise.allSettled(cleanup)\n const failures = results\n .filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n .map((result) => result.reason)\n if (failures.length > 0) {\n consumePreparedCandidateExecution(prepared, 'disposal-failed')\n throw new AggregateError(failures, 'candidate preparation disposal failed')\n }\n\n consumePreparedCandidateExecution(prepared, 'disposed')\n return Object.freeze({ disposed: true as const })\n}\n","import type { TraceStore } from '@tangle-network/agent-eval'\nimport type {\n AgentCandidateExecutionPlanMaterial,\n AgentCandidateMaterializationReceipt,\n} from '@tangle-network/agent-interface'\nimport {\n agentCandidateExecutionPlanMaterialSchema,\n agentCandidateMaterializationReceiptSchema,\n} from '@tangle-network/agent-interface'\n\nimport { readVerifiedArtifact } from './artifacts'\nimport type {\n AgentCandidateExecutionAttemptRef,\n AgentCandidateExecutionClaim,\n AgentCandidateExecutionClaimStore,\n AgentCandidateExecutionFinishResult,\n} from './claim'\nimport {\n candidateCleanupDeadline,\n candidateCleanupTimeout,\n withinCandidateCleanupDeadline,\n} from './cleanup'\nimport { canonicalCandidateBytes } from './digest'\nimport { sealAgentCandidateExecutorStopAcknowledgement } from './executor-capture'\nimport { sealAgentCandidateModelSettlement } from './model-settlement'\nimport { persistCandidateModelSettlementEvidence } from './outcome-evidence'\nimport { persistCandidateOutputArtifact } from './output-artifacts'\nimport { RecoveryAgentCandidateTraceStore } from './protected-trace-store'\nimport type {\n AgentCandidateExecutionPorts,\n AgentCandidateExecutorPort,\n AgentCandidateOutputArtifactPort,\n} from './types'\n\nexport interface RecoverExpiredAgentCandidateOptions {\n attempt: AgentCandidateExecutionAttemptRef\n claimStore: AgentCandidateExecutionClaimStore\n executor: AgentCandidateExecutorPort\n traceStore: TraceStore\n ports: Pick<AgentCandidateExecutionPorts, 'models' | 'memory'>\n outputArtifacts: AgentCandidateOutputArtifactPort\n cleanupTimeoutMs?: number\n /** Evaluator clock; must be the same clock used by the claim store. */\n now?: () => number\n}\n\n/** Close an expired crashed attempt from persisted non-secret handles, then record failure. */\nexport async function recoverExpiredAgentCandidateExecution(\n options: RecoverExpiredAgentCandidateOptions,\n): Promise<AgentCandidateExecutionFinishResult> {\n const record = await options.claimStore.getAttempt(options.attempt)\n if (!record) throw new Error('candidate execution recovery attempt is missing')\n if (record.terminal) {\n return Object.freeze({ finished: false, terminal: record.terminal, exactReplay: true })\n }\n const cleanupTimeoutMs = candidateCleanupTimeout(\n options.cleanupTimeoutMs ?? record.claim.cleanup.cleanupTimeoutMs,\n )\n if (cleanupTimeoutMs > record.claim.cleanup.cleanupTimeoutMs) {\n throw new Error('recovery cleanup timeout exceeds the frozen preparation bound')\n }\n\n const now = options.now ?? Date.now\n if (now() < record.claim.leaseExpiresAtMs) {\n throw new Error('candidate execution lease has not expired')\n }\n\n const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs)\n const recoveryTraceStore = new RecoveryAgentCandidateTraceStore(options.traceStore)\n const preparation = withinCandidateCleanupDeadline(\n () => readRecoveryPreparation(record.claim, options.outputArtifacts),\n cleanupDeadlineAtMs,\n 'expired candidate preparation evidence read',\n )\n const processClosure = withinCandidateCleanupDeadline(\n async (cleanupSignal) => {\n const stopped = await options.executor.stop(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n {\n traceStore: recoveryTraceStore,\n reason: 'failed',\n signal: cleanupSignal,\n deadlineAtMs: cleanupDeadlineAtMs,\n },\n )\n sealAgentCandidateExecutorStopAcknowledgement(stopped)\n if (options.executor.dispose) {\n const disposed = await options.executor.dispose(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n { signal: cleanupSignal },\n )\n if (disposed.disposed !== true || Object.keys(disposed).some((key) => key !== 'disposed')) {\n throw new Error('expired candidate executor did not acknowledge resource disposal')\n }\n }\n return { stopped: true as const }\n },\n cleanupDeadlineAtMs,\n 'expired candidate process termination',\n )\n\n const modelClosure = withinCandidateCleanupDeadline(\n async () =>\n sealAgentCandidateModelSettlement(\n await options.ports.models.settleGrant({\n executionId: record.claim.executionId,\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n resolved: record.claim.cleanup.resolvedModel,\n reason: 'failed',\n }),\n {\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n model: record.claim.cleanup.resolvedModel.model,\n },\n ),\n cleanupDeadlineAtMs,\n 'expired candidate model settlement',\n )\n\n const memoryClosure = record.claim.cleanup.memory\n ? withinCandidateCleanupDeadline(\n async () => {\n const memory = record.claim.cleanup.memory\n if (!memory) throw new Error('expired candidate memory handle is missing')\n const closed = await options.ports.memory.close({\n executionId: record.claim.executionId,\n preparationId: record.claim.cleanup.preparationId,\n accessDigest: memory.accessDigest,\n effectiveNamespace: memory.effectiveNamespace,\n reason: 'failed',\n })\n if (closed.closed !== true || Object.keys(closed).some((key) => key !== 'closed')) {\n throw new Error('expired candidate memory did not acknowledge closure')\n }\n return { closed: true as const }\n },\n cleanupDeadlineAtMs,\n 'expired candidate memory closure',\n )\n : undefined\n\n const closureOutcomes = Promise.allSettled([\n modelClosure,\n memoryClosure ?? Promise.resolve(undefined),\n ] as const)\n const [preparationOutcome, processOutcome] = await Promise.allSettled([\n preparation,\n processClosure,\n ] as const)\n const failures: unknown[] = [preparationOutcome, processOutcome]\n .filter((outcome): outcome is PromiseRejectedResult => outcome.status === 'rejected')\n .map((outcome) => outcome.reason)\n const [modelOutcome, memoryOutcome] = await closureOutcomes\n for (const outcome of [modelOutcome, memoryOutcome]) {\n if (outcome.status === 'rejected') failures.push(outcome.reason)\n }\n if (failures.length > 0) {\n throw new AggregateError(failures, 'expired candidate cleanup could not be proven')\n }\n\n if (modelOutcome.status !== 'fulfilled') {\n throw new Error('expired candidate model settlement was not recovered')\n }\n const model = modelOutcome.value\n const modelSettlement = await withinCandidateCleanupDeadline(\n () =>\n persistCandidateModelSettlementEvidence(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n resolvedModel: record.claim.cleanup.resolvedModel,\n },\n model,\n options.outputArtifacts,\n ),\n cleanupDeadlineAtMs,\n 'expired candidate model-settlement persistence',\n )\n const failureClass =\n record.phase === 'claimed' && model.usage.modelCalls === 0\n ? 'pre-model-infrastructure'\n : 'unknown'\n const failureEvidence = await withinCandidateCleanupDeadline(\n () =>\n persistCandidateOutputArtifact(options.outputArtifacts, {\n executionId: record.claim.executionId,\n purpose: 'failure-evidence',\n bytes: canonicalCandidateBytes({\n kind: 'agent-candidate-recovery-failure',\n executionId: record.claim.executionId,\n attempt: record.claim.attempt,\n bundleDigest: record.claim.bundleDigest,\n executionPlanDigest: record.claim.executionPlanDigest,\n materializationReceiptDigest:\n record.claim.preparationEvidence.materializationReceipt.sha256,\n failureClass,\n processStopped: true,\n modelSettlementDigest: modelSettlement.digest,\n memoryClosed: record.claim.cleanup.memory !== undefined,\n }),\n }),\n cleanupDeadlineAtMs,\n 'expired candidate failure-evidence persistence',\n )\n const memory = record.claim.cleanup.memory\n return await options.claimStore.recoverExpired(options.attempt, {\n failureClass,\n usage: model.usage,\n modelSettlement: modelSettlement.artifact,\n failureEvidence,\n process: {\n stopped: true,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n model: {\n closed: true,\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n },\n ...(memory\n ? {\n memory: {\n closed: true,\n preparationId: record.claim.cleanup.preparationId,\n accessDigest: memory.accessDigest,\n effectiveNamespace: memory.effectiveNamespace,\n },\n }\n : {}),\n })\n}\n\nasync function readRecoveryPreparation(\n claim: AgentCandidateExecutionClaim,\n artifacts: AgentCandidateOutputArtifactPort,\n): Promise<{\n plan: AgentCandidateExecutionPlanMaterial\n receipt: AgentCandidateMaterializationReceipt\n}> {\n const [planBytes, receiptBytes] = await Promise.all([\n readVerifiedArtifact(claim.preparationEvidence.executionPlan, artifacts),\n readVerifiedArtifact(claim.preparationEvidence.materializationReceipt, artifacts),\n ])\n const plan = agentCandidateExecutionPlanMaterialSchema.parse(\n parseCanonicalBytes(planBytes, 'plan'),\n )\n if (claim.preparationEvidence.executionPlan.sha256 !== claim.executionPlanDigest) {\n throw new Error('recovery execution plan artifact does not match the claimed digest')\n }\n const receiptMaterial = parseCanonicalBytes(receiptBytes, 'materialization receipt')\n const receipt = agentCandidateMaterializationReceiptSchema.parse({\n ...receiptMaterial,\n digest: claim.preparationEvidence.materializationReceipt.sha256,\n })\n if (\n receipt.bundleDigest !== claim.bundleDigest ||\n receipt.executionPlan.digest !== claim.executionPlanDigest ||\n plan.runCell.bundleDigest !== claim.bundleDigest ||\n plan.executionId !== claim.executionId\n ) {\n throw new Error('recovery preparation evidence does not match the durable claim')\n }\n return { plan, receipt }\n}\n\nfunction parseCanonicalBytes(bytes: Uint8Array, label: string): Record<string, unknown> {\n let parsed: unknown\n try {\n parsed = JSON.parse(Buffer.from(bytes).toString('utf8'))\n } catch (error) {\n throw new Error(`candidate recovery ${label} is not JSON`, { cause: error })\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`candidate recovery ${label} must be an object`)\n }\n if (!Buffer.from(canonicalCandidateBytes(parsed)).equals(Buffer.from(bytes))) {\n throw new Error(`candidate recovery ${label} bytes are not canonical`)\n }\n return parsed as Record<string, unknown>\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwEA,SAAgB,0BACd,OAC6C;CAU7C,OAAO,yBAAyB;EAR9B,MAAM;EACN,iBAAiB;EACjB,SAAS,wBAAwB,MAAM,OAAO;EAC9C,MAAM,qBAAqB,MAAM,IAAI;EACrC,WAAW,MAAM;EACjB,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;EACtE,QAAQ,MAAM;CAEqB,CAAC;AACxC;AAEA,SAAS,wBAAwB,QAA4D;CAC3F,IAAI,OAAO,SAAS,qBAClB,OAAO,2BAA2B,OAAO,OAAO;CAGlD,IAAI,OAAO,SAAS,WAClB,OAAO,mCAAmC,OAAO,OAAO;CAG1D,IAAI,OAAO,SAAS,iBAClB,MAAM,IAAI,MACR,yCAAyC,OAAQ,OAA8B,IAAI,GACrF;CAEF,IAAI,OAAO,MAAM,WAAW,GAC1B,MAAM,IAAI,MAAM,6DAA6D;CAE/E,IAAI,UAAU,uBAAuB,OAAO,MAAM,cAAc;CAChE,KAAK,MAAM,CAAC,OAAO,cAAc,OAAO,MAAM,QAAQ,GAAG;EACvD,MAAM,OAAO,2BAA2B,WAAW,gBAAgB,OAAO;EAC1E,UAAU,2BAA2B,SAAS,MAAM,gBAAgB,OAAO;CAC7E;CACA,OAAO,mCAAmC,OAAO;AACnD;AAEA,SAAS,qBAAqB,QAAqE;CACjG,IAAI,OAAO,SAAS,cAAc,OAAO,SAAS,SAAS,OAAO;CAClE,IAAI,OAAO,SAAS,gBAClB,MAAM,IAAI,MACR,sCAAsC,OAAQ,OAA8B,IAAI,GAClF;CAIF,MAAM,QAAQ,0BADG,kBAAkB,OAAO,SAAS,OAAO,WACX,CAAC,CAAC,UAAU;CAC3D,IACE,MAAM,WAAW,OAAO,QAAQ,MAAM,UACtC,MAAM,eAAe,OAAO,QAAQ,MAAM,YAE1C,MAAM,IAAI,MAAM,oEAAoE;CAEtF,OAAO;EACL,MAAM;EACN,YAAY,OAAO;EACnB,YAAY,OAAO,QAAQ;EAC3B,UAAU,OAAO,QAAQ;EACzB,eAAe,OAAO,QAAQ;EAC9B,OAAO;GAAE,QAAQ;GAAmB,UAAU;EAAM;CACtD;AACF;;;ACnGA,MAAM,EACJ,oBACA,aACA,gBACA,sBACA,eACA,WACA,aACA,UACA,WACA,oBACA,cACA,uBACA,yBACA,uBACA,eACA,gBACA,gBACA,WACA,cACE;;AAUJ,IAAa,wCAAb,MAAgG;CAC9F;CACA;CAEA,YAAY,SAAuD;EACjE,IAAI,QAAQ,UAAU,WAAW,GAC/B,MAAM,IAAI,MAAM,uDAAuD;EAEzE,KAAK,YAAY,QAAQ;EACzB,KAAK,MAAM,QAAQ,OAAO,KAAK;CACjC;CAEA,MAAM,SACJ,WAC6C;EAC7C,MAAM,QAAQ,UAAU,SAAS;EACjC,MAAM,MAAM,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;EAC/C,MAAM,YAAY,KAAK,UAAU,KAAK;EACtC,MAAM,WAAW,MAAM,mBAAmB,SAAS;EACnD,IAAI,UAAU;GACZ,eAAe,SAAS,OAAO,OAAO,SAAS;GAC/C,OAAO,sBAAsB,SAAS,OAAO,KAAK;EACpD;EACA,qBAAqB,MAAM,kBAAkB,KAAK,IAAI,CAAC;EACvD,MAAM,eAAe,MAAM,KAAK,aAAa,KAAK;EAClD,IAAI,cAAc,OAAO,cAAc,OAAO,YAAY;EAE1D,MAAM,QAAQ,SAAS,KAAK;EAM5B,IAAI,MALmB,oBAAoB,KAAK,WAAW,WAAW;GACpE,GAAG;GACH,OAAO;GACP,aAAa,YAAY,KAAK;EAChC,CAAC,GACa,OAAO,OAAO,OAAO;GAAE,UAAU;GAAM;GAAO;EAAM,CAAC;EAEnE,MAAM,SAAS,MAAM,UAAU,SAAS;EACxC,eAAe,OAAO,OAAO,OAAO,SAAS;EAC7C,OAAO,sBAAsB,OAAO,OAAO,KAAK;CAClD;CAEA,MAAM,WACJ,kBAC2D;EAC3D,OAAO,MAAM,KAAK,cAAc,eAAe,gBAAgB,CAAC;CAClE;CAEA,MAAM,oBACJ,gBAC6C;EAC7C,MAAM,QAAQ,UAAU,cAAc;EACtC,MAAM,YAAY,KAAK,UAAU,KAAK;EACtC,MAAM,SAAS,MAAM,UAAU,SAAS;EACxC,eAAe,OAAO,OAAO,OAAO,SAAS;EAC7C,YAAY,OAAO,aAAa,OAAO,MAAM,kBAAkB,KAAK;EACpE,MAAM,QAAQ,MAAM,KAAK,gBAAgB,OAAO,KAAK;EACrD,IAAI,MAAM,UAAU,qBAClB,OAAO,OAAO,OAAO;GAAE,QAAQ;GAAO,OAAO;EAAoB,CAAC;EAEpE,IAAI,MAAM,QACR,MAAM,IAAI,MAAM,wEAAwE;EAE1F,qBAAqB,OAAO,MAAM,kBAAkB,KAAK,IAAI,CAAC;EAa9D,IAAI,MAZiB,oBACnB,KAAK,WACL,KAAK,eAAe,OAAO,OAAO,CAAC,GACnC;GACE,MAAM;GACN,aAAa,OAAO,MAAM;GAC1B,SAAS,OAAO,MAAM;GACtB,qBAAqB,OAAO,MAAM;GAClC,OAAO;EACT,GACA,KAAK,iBAAiB,OAAO,KAAK,CACpC,GACY,OAAO,OAAO,OAAO;GAAE,QAAQ;GAAM,OAAO;EAAoB,CAAC;EAE7E,KAAI,MADiB,KAAK,gBAAgB,OAAO,KAAK,EAAA,CAC3C,UAAU,qBACnB,OAAO,OAAO,OAAO;GAAE,QAAQ;GAAO,OAAO;EAAoB,CAAC;EAEpE,MAAM,IAAI,MAAM,wEAAwE;CAC1F;CAEA,MAAM,cACJ,gBACA,QAC6C;EAC7C,MAAM,QAAQ,UAAU,cAAc;EACtC,MAAM,YAAY,KAAK,UAAU,KAAK;EACtC,MAAM,SAAS,MAAM,UAAU,SAAS;EACxC,eAAe,OAAO,OAAO,OAAO,SAAS;EAC7C,YAAY,OAAO,aAAa,OAAO,MAAM,kBAAkB,KAAK;EACpE,MAAM,WAAW,eAAe,OAAO,OAAO,MAAM;EACpD,MAAM,QAAQ,MAAM,KAAK,gBAAgB,OAAO,KAAK;EACrD,IAAI,MAAM,QAAQ,OAAO,cAAc,MAAM,QAAQ,QAAQ;EAC7D,6BAA6B,MAAM,OAAO,QAAQ;EAClD,qBAAqB,OAAO,MAAM,kBAAkB,KAAK,IAAI,CAAC;EAC9D,MAAM,aAAa,MAAM,UAAU,YAAY,IAAI;EAUnD,IAAI,MATiB,oBACnB,KAAK,WACL,KAAK,eAAe,OAAO,OAAO,UAAU,GAC5C;GACE,MAAM;GACN;EACF,GACA,KAAK,iBAAiB,OAAO,KAAK,CACpC,GACY,OAAO,OAAO,OAAO;GAAE,QAAQ;GAAM;EAAS,CAAC;EAC3D,MAAM,SAAS,MAAM,KAAK,gBAAgB,OAAO,KAAK;EACtD,IAAI,CAAC,OAAO,QACV,MAAM,IAAI,MAAM,iEAAiE;EAEnF,OAAO,cAAc,OAAO,QAAQ,QAAQ;CAC9C;CAEA,MAAM,OACJ,gBACA,yBAC8C;EAC9C,MAAM,QAAQ,UAAU,cAAc;EACtC,MAAM,iBAAiB,mBAAmB,uBAAuB;EACjE,MAAM,YAAY,KAAK,UAAU,KAAK;EACtC,MAAM,SAAS,MAAM,UAAU,SAAS;EACxC,eAAe,OAAO,OAAO,OAAO,SAAS;EAC7C,YAAY,OAAO,aAAa,OAAO,MAAM,kBAAkB,KAAK;EAEpE,MAAM,SAAS,uBAAsB,MADjB,KAAK,gBAAgB,OAAO,KAAK,EAAA,CACV,QAAQ,cAAc;EACjE,MAAM,eAAe,KAAK,aAAa,KAAK;EAC5C,MAAM,WAAW,MAAM,sBAAsB,YAAY;EACzD,IAAI,UAAU;GACZ,2BAA2B,UAAU,OAAO,OAAO,YAAY;GAC/D,4BAA4B,UAAU,QAAQ,YAAY;GAC1D,OAAO,eAAe,UAAU,cAAc;EAChD;EACA,qBAAqB,OAAO,MAAM,kBAAkB,KAAK,IAAI,CAAC;EAS9D,IAAI,MARmB,oBACrB,KAAK,WACL,cACA,EACE,UAAU,OACZ,GACA,KAAK,iBAAiB,OAAO,KAAK,CACpC,GACc,OAAO,OAAO,OAAO;GAAE,UAAU;GAAM,UAAU;EAAO,CAAC;EACvE,MAAM,SAAS,MAAM,aAAa,YAAY;EAC9C,eAAe,QAAQ,OAAO,YAAY;EAC1C,2BAA2B,QAAQ,OAAO,OAAO,YAAY;EAC7D,4BAA4B,QAAQ,QAAQ,YAAY;EACxD,OAAO,eAAe,QAAQ,cAAc;CAC9C;CAEA,MAAM,eACJ,kBACA,UAC8C;EAC9C,MAAM,UAAU,eAAe,gBAAgB;EAC/C,MAAM,SAAS,MAAM,KAAK,cAAc,OAAO;EAC/C,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,gEAAgE;EAC7F,MAAM,YAAY,wBAAwB,OAAO,OAAO,OAAO,OAAO,QAAQ;EAC9E,IAAI,OAAO,QAAQ,4BAA4B,OAAO,QAAQ,SAAS;EACvE,MAAM,kBAAkB,OAAO,QAAQ,kBAAkB,UAAU;EACnE,IAAI,OAAO,UAAU,OAAO,eAAe,OAAO,UAAU,eAAe;EAC3E,mBAAmB,OAAO,MAAM,kBAAkB,KAAK,IAAI,CAAC;EAE5D,IAAI,SAAS,OAAO;EACpB,IAAI,CAAC,QAAQ;GACX,MAAM,aAAa,OAAO,UAAU,YAAY,IAAI;GASpD,IAAI,MARmB,oBACrB,KAAK,WACL,KAAK,eAAe,OAAO,OAAO,UAAU,GAC5C;IACE,MAAM;IACN,UAAU;GACZ,CACF,GAEE,SAAS;QACJ;IACL,MAAM,SAAS,MAAM,KAAK,gBAAgB,OAAO,KAAK;IACtD,IAAI,CAAC,OAAO,QACV,MAAM,IAAI,MACR,0EACF;IAEF,4BAA4B,OAAO,QAAQ,SAAS;IACpD,SAAS,OAAO;GAClB;EACF;EAEA,MAAM,eAAe,KAAK,aAAa,OAAO;EAI9C,IAAI,MAHoB,oBAAoB,KAAK,WAAW,cAAc,EACxE,UAAU,OACZ,CAAC,GACc,OAAO,OAAO,OAAO;GAAE,UAAU;GAAM,UAAU;EAAO,CAAC;EACxE,MAAM,SAAS,MAAM,aAAa,YAAY;EAC9C,eAAe,QAAQ,SAAS,YAAY;EAC5C,2BAA2B,QAAQ,OAAO,OAAO,YAAY;EAC7D,4BAA4B,QAAQ,QAAQ,YAAY;EACxD,OAAO,eAAe,QAAQ,OAAO,cAAc;CACrD;CAEA,MAAc,cACZ,OAC2D;EAC3D,MAAM,YAAY,KAAK,UAAU,KAAK;EACtC,MAAM,SAAS,MAAM,mBAAmB,SAAS;EACjD,IAAI,CAAC,QAAQ,OAAO,KAAA;EACpB,eAAe,OAAO,OAAO,OAAO,SAAS;EAC7C,MAAM,QAAQ,MAAM,KAAK,gBAAgB,OAAO,KAAK;EACrD,MAAM,eAAe,KAAK,aAAa,KAAK;EAC5C,MAAM,WAAW,MAAM,sBAAsB,YAAY;EACzD,IAAI,UAAU;GACZ,2BAA2B,UAAU,OAAO,OAAO,YAAY;GAC/D,IAAI,CAAC,MAAM,QACT,MAAM,IAAI,MACR,0CAA0C,aAAa,sBACzD;GAEF,4BAA4B,UAAU,MAAM,QAAQ,YAAY;EAClE;EACA,OAAO,cAAc,OAAO,OAAO,MAAM,OAAO,MAAM,QAAQ,QAAQ;CACxE;CAEA,MAAc,gBAAgB,OAG3B;EACD,MAAM,YAAY,KAAK,eAAe,OAAO,CAAC;EAC9C,MAAM,QAAQ,MAAM,wBAAwB,WAAW,KAAK;EAC5D,IAAI,CAAC,OAAO,OAAO,EAAE,OAAO,UAAU;EACtC,IAAI,MAAM,SAAS,WAAW,OAAO;GAAE,OAAO;GAAW,QAAQ,MAAM;EAAS;EAChF,MAAM,aAAa,KAAK,eAAe,OAAO,CAAC;EAC/C,MAAM,SAAS,MAAM,wBAAwB,YAAY,KAAK;EAC9D,IAAI,CAAC,QAAQ,OAAO,EAAE,OAAO,oBAAoB;EACjD,IAAI,OAAO,SAAS,WAClB,MAAM,IAAI,MAAM,qCAAqC,WAAW,0BAA0B;EAE5F,OAAO;GAAE,OAAO;GAAqB,QAAQ,OAAO;EAAS;CAC/D;CAEA,MAAc,aACZ,OACmD;EACnD,IAAI,MAAM,YAAY,GAAG,OAAO,KAAA;EAChC,OAAO,eACL,OACA,MAAM,KAAK,cAAc;GACvB,aAAa,MAAM;GACnB,SAAS,MAAM,UAAU;EAC3B,CAAC,CACH;CACF;CAEA,iBAAyB,OAEvB;EACA,OAAO,EACL,wBAAwB;GACtB,qBAAqB,MAAM,kBAAkB,KAAK,IAAI,CAAC;GACvD,OAAO;EACT,EACF;CACF;CAEA,UAAkB,OAA8E;EAC9F,OAAO,KAAK,KAAK,WAAW,GAAG,UAAU,KAAK,EAAE,YAAY;CAC9D;CAEA,aACE,OACQ;EACR,OAAO,KAAK,KAAK,WAAW,GAAG,UAAU,KAAK,EAAE,eAAe;CACjE;CAEA,eACE,OACA,SACQ;EACR,OAAO,KAAK,KAAK,WAAW,GAAG,UAAU,KAAK,EAAE,cAAc,QAAQ,MAAM;CAC9E;AACF;AAEA,eAAe,oBACb,WACA,aACA,QACA,UAGI,CAAC,GACa;CAClB,MAAM,gBAAgB,KAAK,WAAW,wBAAwB,QAAQ,IAAI,GAAG,WAAW,EAAE,KAAK;CAC/F,MAAM,SAAS,MAAM,KAAK,eAAe,MAAM,GAAK;CACpD,IAAI;EACF,MAAM,OAAO,UACX,OAAO,OAAO,CAAC,OAAO,KAAK,wBAAwB,MAAM,CAAC,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CACjF;EACA,MAAM,OAAO,KAAK;CACpB,UAAU;EACR,MAAM,OAAO,MAAM;CACrB;CAEA,IAAI,UAAU;CACd,IAAI;EACF,IAAI,QAAQ,oBAAoB,QAAQ,iBAAiB,MAAM,MAC7D,MAAM,IAAI,MAAM,2DAA2D;EAI7E,SAAS,eAAe,WAAW;EACnC,UAAU;EACV,MAAM,cAAc,SAAS;CAC/B,SAAS,OAAO;EACd,IAAI,CAAC,YAAY,OAAO,QAAQ,GAAG,MAAM;CAC3C,UAAU;EACR,MAAM,OAAO,aAAa,CAAC,CAAC,OAAO,UAAmB;GACpD,IAAI,CAAC,YAAY,OAAO,QAAQ,GAAG,MAAM;EAC3C,CAAC;CACH;CACA,OAAO;AACT;AAEA,eAAe,cAAc,WAAkC;CAC7D,MAAM,SAAS,MAAM,KAAK,WAAW,GAAG;CACxC,IAAI;EACF,MAAM,OAAO,KAAK;CACpB,UAAU;EACR,MAAM,OAAO,MAAM;CACrB;AACF;AAEA,SAAS,YAAY,OAAgB,MAAuB;CAC1D,OACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACT,MAA6B,SAAS;AAE3C;;;;ACtYA,eAAsB,uCACpB,UACA,UAAgD,CAAC,GACpB;CAC7B,MAAM,eAAe,iCAAiC,QAAQ;CAC9D,MAAM,mBAAmB,QAAQ,oBAAoB,aAAa;CAClE,IAAI,mBAAmB,aAAa,kBAClC,MAAM,IAAI,MAAM,+DAA+D;CAEjF,MAAM,sBAAsB,yBAAyB,gBAAgB;CACrE,MAAM,QAAQ,+BAA+B,QAAQ;CACrD,MAAM,UAAmC,CAAC;CAE1C,IAAI,MAAM,OAAO,SAAS,YAAY;EACpC,MAAM,cAAc,MAAM;EAC1B,IAAI,CAAC,aAAa,MAAM,IAAI,MAAM,wCAAwC;EAC1E,QAAQ,KACN,+BACE,YAAY;GACV,MAAM,SAAS,MAAM,MAAM,MAAM,OAAO,MAAM;IAC5C,aAAa,MAAM;IACnB,eAAe,YAAY;IAC3B,cAAc,YAAY;IAC1B,oBAAoB,YAAY;IAChC,QAAQ;GACV,CAAC;GACD,IAAI,OAAO,WAAW,QAAQ,OAAO,KAAK,MAAM,CAAC,CAAC,MAAM,QAAQ,QAAQ,QAAQ,GAC9E,MAAM,IAAI,MAAM,8DAA8D;EAElF,GACA,qBACA,0BACF,CACF;CACF;CAEA,QAAQ,KACN,+BACE,YAAY;EAeV,IAdmB,kCACjB,MAAM,MAAM,MAAM,OAAO,YAAY;GACnC,aAAa,MAAM;GACnB,eAAe,MAAM;GACrB,aAAa,MAAM,iBAAiB;GACpC,UAAU,MAAM;GAChB,QAAQ;EACV,CAAC,GACD;GACE,eAAe,MAAM;GACrB,aAAa,MAAM,iBAAiB;GACpC,OAAO,MAAM,cAAc;EAC7B,CAEW,CAAC,CAAC,MAAM,eAAe,GAClC,MAAM,IAAI,MAAM,0DAA0D;CAE9E,GACA,qBACA,4BACF,CACF;CAGA,MAAM,YAAW,MADK,QAAQ,WAAW,OAAO,EAAA,CAE7C,QAAQ,WAA4C,OAAO,WAAW,UAAU,CAAC,CACjF,KAAK,WAAW,OAAO,MAAM;CAChC,IAAI,SAAS,SAAS,GAAG;EACvB,kCAAkC,UAAU,iBAAiB;EAC7D,MAAM,IAAI,eAAe,UAAU,uCAAuC;CAC5E;CAEA,kCAAkC,UAAU,UAAU;CACtD,OAAO,OAAO,OAAO,EAAE,UAAU,KAAc,CAAC;AAClD;;;;ACxCA,eAAsB,sCACpB,SAC8C;CAC9C,MAAM,SAAS,MAAM,QAAQ,WAAW,WAAW,QAAQ,OAAO;CAClE,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,iDAAiD;CAC9E,IAAI,OAAO,UACT,OAAO,OAAO,OAAO;EAAE,UAAU;EAAO,UAAU,OAAO;EAAU,aAAa;CAAK,CAAC;CAExF,MAAM,mBAAmB,wBACvB,QAAQ,oBAAoB,OAAO,MAAM,QAAQ,gBACnD;CACA,IAAI,mBAAmB,OAAO,MAAM,QAAQ,kBAC1C,MAAM,IAAI,MAAM,+DAA+D;CAIjF,KADY,QAAQ,OAAO,KAAK,IAAA,CACxB,IAAI,OAAO,MAAM,kBACvB,MAAM,IAAI,MAAM,2CAA2C;CAG7D,MAAM,sBAAsB,yBAAyB,gBAAgB;CACrE,MAAM,qBAAqB,IAAI,iCAAiC,QAAQ,UAAU;CAClF,MAAM,cAAc,qCACZ,wBAAwB,OAAO,OAAO,QAAQ,eAAe,GACnE,qBACA,6CACF;CACA,MAAM,iBAAiB,+BACrB,OAAO,kBAAkB;EAavB,8CAA8C,MAZxB,QAAQ,SAAS,KACrC;GACE,aAAa,OAAO,MAAM;GAC1B,qBAAqB,OAAO,MAAM;EACpC,GACA;GACE,YAAY;GACZ,QAAQ;GACR,QAAQ;GACR,cAAc;EAChB,CACF,CACqD;EACrD,IAAI,QAAQ,SAAS,SAAS;GAC5B,MAAM,WAAW,MAAM,QAAQ,SAAS,QACtC;IACE,aAAa,OAAO,MAAM;IAC1B,qBAAqB,OAAO,MAAM;GACpC,GACA,EAAE,QAAQ,cAAc,CAC1B;GACA,IAAI,SAAS,aAAa,QAAQ,OAAO,KAAK,QAAQ,CAAC,CAAC,MAAM,QAAQ,QAAQ,UAAU,GACtF,MAAM,IAAI,MAAM,kEAAkE;EAEtF;EACA,OAAO,EAAE,SAAS,KAAc;CAClC,GACA,qBACA,uCACF;CAEA,MAAM,eAAe,+BACnB,YACE,kCACE,MAAM,QAAQ,MAAM,OAAO,YAAY;EACrC,aAAa,OAAO,MAAM;EAC1B,eAAe,OAAO,MAAM,QAAQ;EACpC,aAAa,OAAO,MAAM,QAAQ;EAClC,UAAU,OAAO,MAAM,QAAQ;EAC/B,QAAQ;CACV,CAAC,GACD;EACE,eAAe,OAAO,MAAM,QAAQ;EACpC,aAAa,OAAO,MAAM,QAAQ;EAClC,OAAO,OAAO,MAAM,QAAQ,cAAc;CAC5C,CACF,GACF,qBACA,oCACF;CAEA,MAAM,gBAAgB,OAAO,MAAM,QAAQ,SACvC,+BACE,YAAY;EACV,MAAM,SAAS,OAAO,MAAM,QAAQ;EACpC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,4CAA4C;EACzE,MAAM,SAAS,MAAM,QAAQ,MAAM,OAAO,MAAM;GAC9C,aAAa,OAAO,MAAM;GAC1B,eAAe,OAAO,MAAM,QAAQ;GACpC,cAAc,OAAO;GACrB,oBAAoB,OAAO;GAC3B,QAAQ;EACV,CAAC;EACD,IAAI,OAAO,WAAW,QAAQ,OAAO,KAAK,MAAM,CAAC,CAAC,MAAM,QAAQ,QAAQ,QAAQ,GAC9E,MAAM,IAAI,MAAM,sDAAsD;EAExE,OAAO,EAAE,QAAQ,KAAc;CACjC,GACA,qBACA,kCACF,IACA,KAAA;CAEJ,MAAM,kBAAkB,QAAQ,WAAW,CACzC,cACA,iBAAiB,QAAQ,QAAQ,KAAA,CAAS,CAC5C,CAAU;CACV,MAAM,CAAC,oBAAoB,kBAAkB,MAAM,QAAQ,WAAW,CACpE,aACA,cACF,CAAU;CACV,MAAM,WAAsB,CAAC,oBAAoB,cAAc,CAAC,CAC7D,QAAQ,YAA8C,QAAQ,WAAW,UAAU,CAAC,CACpF,KAAK,YAAY,QAAQ,MAAM;CAClC,MAAM,CAAC,cAAc,iBAAiB,MAAM;CAC5C,KAAK,MAAM,WAAW,CAAC,cAAc,aAAa,GAChD,IAAI,QAAQ,WAAW,YAAY,SAAS,KAAK,QAAQ,MAAM;CAEjE,IAAI,SAAS,SAAS,GACpB,MAAM,IAAI,eAAe,UAAU,+CAA+C;CAGpF,IAAI,aAAa,WAAW,aAC1B,MAAM,IAAI,MAAM,sDAAsD;CAExE,MAAM,QAAQ,aAAa;CAC3B,MAAM,kBAAkB,MAAM,qCAE1B,wCACE;EACE,aAAa,OAAO,MAAM;EAC1B,qBAAqB,OAAO,MAAM;EAClC,eAAe,OAAO,MAAM,QAAQ;CACtC,GACA,OACA,QAAQ,eACV,GACF,qBACA,gDACF;CACA,MAAM,eACJ,OAAO,UAAU,aAAa,MAAM,MAAM,eAAe,IACrD,6BACA;CACN,MAAM,kBAAkB,MAAM,qCAE1B,+BAA+B,QAAQ,iBAAiB;EACtD,aAAa,OAAO,MAAM;EAC1B,SAAS;EACT,OAAO,wBAAwB;GAC7B,MAAM;GACN,aAAa,OAAO,MAAM;GAC1B,SAAS,OAAO,MAAM;GACtB,cAAc,OAAO,MAAM;GAC3B,qBAAqB,OAAO,MAAM;GAClC,8BACE,OAAO,MAAM,oBAAoB,uBAAuB;GAC1D;GACA,gBAAgB;GAChB,uBAAuB,gBAAgB;GACvC,cAAc,OAAO,MAAM,QAAQ,WAAW,KAAA;EAChD,CAAC;CACH,CAAC,GACH,qBACA,gDACF;CACA,MAAM,SAAS,OAAO,MAAM,QAAQ;CACpC,OAAO,MAAM,QAAQ,WAAW,eAAe,QAAQ,SAAS;EAC9D;EACA,OAAO,MAAM;EACb,iBAAiB,gBAAgB;EACjC;EACA,SAAS;GACP,SAAS;GACT,qBAAqB,OAAO,MAAM;EACpC;EACA,OAAO;GACL,QAAQ;GACR,eAAe,OAAO,MAAM,QAAQ;GACpC,aAAa,OAAO,MAAM,QAAQ;EACpC;EACA,GAAI,SACA,EACE,QAAQ;GACN,QAAQ;GACR,eAAe,OAAO,MAAM,QAAQ;GACpC,cAAc,OAAO;GACrB,oBAAoB,OAAO;EAC7B,EACF,IACA,CAAC;CACP,CAAC;AACH;AAEA,eAAe,wBACb,OACA,WAIC;CACD,MAAM,CAAC,WAAW,gBAAgB,MAAM,QAAQ,IAAI,CAClD,qBAAqB,MAAM,oBAAoB,eAAe,SAAS,GACvE,qBAAqB,MAAM,oBAAoB,wBAAwB,SAAS,CAClF,CAAC;CACD,MAAM,OAAO,0CAA0C,MACrD,oBAAoB,WAAW,MAAM,CACvC;CACA,IAAI,MAAM,oBAAoB,cAAc,WAAW,MAAM,qBAC3D,MAAM,IAAI,MAAM,oEAAoE;CAEtF,MAAM,kBAAkB,oBAAoB,cAAc,yBAAyB;CACnF,MAAM,UAAU,2CAA2C,MAAM;EAC/D,GAAG;EACH,QAAQ,MAAM,oBAAoB,uBAAuB;CAC3D,CAAC;CACD,IACE,QAAQ,iBAAiB,MAAM,gBAC/B,QAAQ,cAAc,WAAW,MAAM,uBACvC,KAAK,QAAQ,iBAAiB,MAAM,gBACpC,KAAK,gBAAgB,MAAM,aAE3B,MAAM,IAAI,MAAM,gEAAgE;CAElF,OAAO;EAAE;EAAM;CAAQ;AACzB;AAEA,SAAS,oBAAoB,OAAmB,OAAwC;CACtF,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC;CACzD,SAAS,OAAO;EACd,MAAM,IAAI,MAAM,sBAAsB,MAAM,eAAe,EAAE,OAAO,MAAM,CAAC;CAC7E;CACA,IAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAC/D,MAAM,IAAI,MAAM,sBAAsB,MAAM,mBAAmB;CAEjE,IAAI,CAAC,OAAO,KAAK,wBAAwB,MAAM,CAAC,CAAC,CAAC,OAAO,OAAO,KAAK,KAAK,CAAC,GACzE,MAAM,IAAI,MAAM,sBAAsB,MAAM,yBAAyB;CAEvE,OAAO;AACT"}
@@ -0,0 +1,40 @@
1
+ //#region src/profiles/coder.ts
2
+ /**
3
+ *
4
+ * `CoderTask` + `coderTaskToPrompt` — the per-task DATA + pure formatter for code-modification tasks
5
+ * (§1.5: the system authors profiles; there is no hardcoded coder profile constant). A domain
6
+ * customizes the worker by authoring its own `AgentProfile` and handing it to a leaf executor
7
+ * (`createWorktreeCliExecutor`) or a fanout (`worktreeFanout`); "is it delivered" is a
8
+ * `DeliverableSpec` (`patchDelivered`), not a bundled validator. This formatter renders a `CoderTask`
9
+ * into the per-task instruction that profile receives.
10
+ *
11
+ * @experimental
12
+ */
13
+ const DEFAULT_MAX_DIFF_LINES = 400;
14
+ /** Render a `CoderTask` into the per-task instruction handed to the coder profile. @experimental */
15
+ function coderTaskToPrompt(task) {
16
+ const base = task.baseBranch ?? "main";
17
+ const testCmd = task.testCmd ?? "pnpm test --run";
18
+ const typecheckCmd = task.typecheckCmd ?? "pnpm typecheck";
19
+ const maxDiff = task.maxDiffLines ?? DEFAULT_MAX_DIFF_LINES;
20
+ const forbidden = task.forbiddenPaths?.length ? task.forbiddenPaths.join(", ") : "(none)";
21
+ const context = task.contextFiles?.length ? task.contextFiles.map((f) => ` - ${f}`).join("\n") : " (none)";
22
+ return [
23
+ `Goal: ${task.goal}`,
24
+ `Repo: ${task.repoRoot}`,
25
+ `Base branch: ${base}`,
26
+ `Run tests with: ${testCmd}`,
27
+ `Run typecheck with: ${typecheckCmd}`,
28
+ `Forbidden paths: ${forbidden}`,
29
+ `Max diff lines: ${maxDiff}`,
30
+ "Context files:",
31
+ context,
32
+ "",
33
+ "Produce a minimal patch on a fresh branch. Run tests and typecheck before",
34
+ "returning. Emit the final JSON result block exactly as instructed."
35
+ ].join("\n");
36
+ }
37
+ //#endregion
38
+ export { coderTaskToPrompt as t };
39
+
40
+ //# sourceMappingURL=coder-yhVWbdWc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coder-yhVWbdWc.js","names":[],"sources":["../src/profiles/coder.ts"],"sourcesContent":["/**\n *\n * `CoderTask` + `coderTaskToPrompt` — the per-task DATA + pure formatter for code-modification tasks\n * (§1.5: the system authors profiles; there is no hardcoded coder profile constant). A domain\n * customizes the worker by authoring its own `AgentProfile` and handing it to a leaf executor\n * (`createWorktreeCliExecutor`) or a fanout (`worktreeFanout`); \"is it delivered\" is a\n * `DeliverableSpec` (`patchDelivered`), not a bundled validator. This formatter renders a `CoderTask`\n * into the per-task instruction that profile receives.\n *\n * @experimental\n */\n\nconst DEFAULT_MAX_DIFF_LINES = 400\n\n/** @experimental The per-task inputs `coderTaskToPrompt` renders + the worktree gate enforces. */\nexport interface CoderTask {\n /** What the agent must accomplish. Free-form prose. */\n goal: string\n /** Absolute path inside the sandbox where the repo lives. */\n repoRoot: string\n /** Default `main`. The branch the agent diffs against. */\n baseBranch?: string\n /** Default `pnpm test --run`. */\n testCmd?: string\n /** Default `pnpm typecheck`. */\n typecheckCmd?: string\n /** Files the agent may inspect for context. Surfaced verbatim in the prompt. */\n contextFiles?: string[]\n /**\n * Paths the agent must not touch. The mechanical gate hard-fails on any match.\n * Use glob-free literal path prefixes for unambiguous enforcement.\n */\n forbiddenPaths?: string[]\n /** Default 400. Hard cap; the gate hard-fails when exceeded. */\n maxDiffLines?: number\n}\n\n/** Render a `CoderTask` into the per-task instruction handed to the coder profile. @experimental */\nexport function coderTaskToPrompt(task: CoderTask): string {\n const base = task.baseBranch ?? 'main'\n const testCmd = task.testCmd ?? 'pnpm test --run'\n const typecheckCmd = task.typecheckCmd ?? 'pnpm typecheck'\n const maxDiff = task.maxDiffLines ?? DEFAULT_MAX_DIFF_LINES\n const forbidden = task.forbiddenPaths?.length ? task.forbiddenPaths.join(', ') : '(none)'\n const context = task.contextFiles?.length\n ? task.contextFiles.map((f) => ` - ${f}`).join('\\n')\n : ' (none)'\n return [\n `Goal: ${task.goal}`,\n `Repo: ${task.repoRoot}`,\n `Base branch: ${base}`,\n `Run tests with: ${testCmd}`,\n `Run typecheck with: ${typecheckCmd}`,\n `Forbidden paths: ${forbidden}`,\n `Max diff lines: ${maxDiff}`,\n 'Context files:',\n context,\n '',\n 'Produce a minimal patch on a fresh branch. Run tests and typecheck before',\n 'returning. Emit the final JSON result block exactly as instructed.',\n ].join('\\n')\n}\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,yBAAyB;;AA0B/B,SAAgB,kBAAkB,MAAyB;CACzD,MAAM,OAAO,KAAK,cAAc;CAChC,MAAM,UAAU,KAAK,WAAW;CAChC,MAAM,eAAe,KAAK,gBAAgB;CAC1C,MAAM,UAAU,KAAK,gBAAgB;CACrC,MAAM,YAAY,KAAK,gBAAgB,SAAS,KAAK,eAAe,KAAK,IAAI,IAAI;CACjF,MAAM,UAAU,KAAK,cAAc,SAC/B,KAAK,aAAa,KAAK,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,IAAI,IAClD;CACJ,OAAO;EACL,SAAS,KAAK;EACd,SAAS,KAAK;EACd,gBAAgB;EAChB,mBAAmB;EACnB,uBAAuB;EACvB,oBAAoB;EACpB,mBAAmB;EACnB;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb"}