@tangle-network/agent-runtime 0.301.0 → 0.306.2

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 (85) hide show
  1. package/dist/{activation-V6aaOlZV.js → activation-kaJzXM7Y.js} +3 -3
  2. package/dist/{activation-V6aaOlZV.js.map → activation-kaJzXM7Y.js.map} +1 -1
  3. package/dist/{activation-CRgEJutr.d.ts → activation-wZ-8vOjV.d.ts} +88 -13
  4. package/dist/agent.d.ts +2 -2
  5. package/dist/agent.js +2 -2
  6. package/dist/{bundle-C9v5TH_H.js → bundle-E6mbRX2P.js} +2 -2
  7. package/dist/{bundle-C9v5TH_H.js.map → bundle-E6mbRX2P.js.map} +1 -1
  8. package/dist/candidate-execution/index.d.ts +3 -26
  9. package/dist/candidate-execution/index.js +6 -6
  10. package/dist/{coordination-driver-vNrdQBSH.js → coordination-driver-Y2gf8pBT.js} +9 -16
  11. package/dist/coordination-driver-Y2gf8pBT.js.map +1 -0
  12. package/dist/{delegate-B-jFJcbW.js → delegate-B7bwEFQl.js} +2 -2
  13. package/dist/{delegate-B-jFJcbW.js.map → delegate-B7bwEFQl.js.map} +1 -1
  14. package/dist/durable.d.ts +3 -15
  15. package/dist/durable.js +158 -124
  16. package/dist/durable.js.map +1 -1
  17. package/dist/{graph-Dwv_hQB_.js → graph-VUwNFYff.js} +4 -5
  18. package/dist/graph-VUwNFYff.js.map +1 -0
  19. package/dist/{improvement-cycle-Cf37Kexd.js → improvement-cycle-DuIGusyA.js} +1129 -10
  20. package/dist/improvement-cycle-DuIGusyA.js.map +1 -0
  21. package/dist/{index-CxBVmgqL.d.ts → index-DflDZq_I.d.ts} +50 -688
  22. package/dist/index.d.ts +378 -12
  23. package/dist/index.js +223 -320
  24. package/dist/index.js.map +1 -1
  25. package/dist/intelligence.d.ts +5 -5
  26. package/dist/intelligence.js +7 -8
  27. package/dist/intelligence.js.map +1 -1
  28. package/dist/kernel.d.ts +4 -4
  29. package/dist/kernel.js +9 -9
  30. package/dist/{loop-runner-bin-DiTNiJNs.d.ts → loop-runner-bin-DZfRUVWy.d.ts} +3 -3
  31. package/dist/{loop-runner-bin-C8MI8N1A.js → loop-runner-bin-Dp1V3P2W.js} +3 -3
  32. package/dist/{loop-runner-bin-C8MI8N1A.js.map → loop-runner-bin-Dp1V3P2W.js.map} +1 -1
  33. package/dist/loop-runner-bin.d.ts +1 -1
  34. package/dist/loop-runner-bin.js +1 -1
  35. package/dist/mcp/bin.js +3 -3
  36. package/dist/mcp/index.d.ts +6 -35
  37. package/dist/mcp/index.js +311 -364
  38. package/dist/mcp/index.js.map +1 -1
  39. package/dist/model-policy-DydyWTQg.js.map +1 -1
  40. package/dist/{openai-tools-BeogJ6V8.d.ts → openai-tools-YO30D2s3.d.ts} +2 -2
  41. package/dist/{prepare-CGVNMb1o.js → prepare-CulUz6Wm.js} +7 -13
  42. package/dist/prepare-CulUz6Wm.js.map +1 -0
  43. package/dist/{profile-BetOB4_Q.js → profile-DY9lT3gH.js} +2 -2
  44. package/dist/{profile-BetOB4_Q.js.map → profile-DY9lT3gH.js.map} +1 -1
  45. package/dist/profiles.d.ts +2 -94
  46. package/dist/profiles.js +2 -451
  47. package/dist/profiles.js.map +1 -1
  48. package/dist/{protected-model-port-CuVHkhti.js → protected-model-port-BT2iYAsU.js} +4 -4
  49. package/dist/{protected-model-port-CuVHkhti.js.map → protected-model-port-BT2iYAsU.js.map} +1 -1
  50. package/dist/{protected-model-port-CAa0t1MT.d.ts → protected-model-port-C9QtEf3y.d.ts} +2 -2
  51. package/dist/{provision-supervisor-CS0fBIhp.js → provision-supervisor-CfK8fla-.js} +4 -3
  52. package/dist/{provision-supervisor-CS0fBIhp.js.map → provision-supervisor-CfK8fla-.js.map} +1 -1
  53. package/dist/{runtime-6VPSJVeg.js → runtime-D452tieK.js} +67 -469
  54. package/dist/runtime-D452tieK.js.map +1 -0
  55. package/dist/{search-method-wTTS7mGG.js → search-executor-D3AT8_hb.js} +239 -1132
  56. package/dist/search-executor-D3AT8_hb.js.map +1 -0
  57. package/dist/{server-BfHD5iLD.js → server-D1Tfxo-v.js} +5 -12
  58. package/dist/server-D1Tfxo-v.js.map +1 -0
  59. package/dist/{stream-agent-turn-B1ipFtOc.d.ts → stream-agent-turn-B1giFgOg.d.ts} +2 -2
  60. package/dist/{substrate-DKBMd0Dl.d.ts → substrate-L_sC7jCD.d.ts} +2 -2
  61. package/dist/{supervise-BJrEC2Mh.js → supervise-CtewGpxh.js} +14 -24
  62. package/dist/supervise-CtewGpxh.js.map +1 -0
  63. package/dist/{supervisor-DA_nvF-h.js → supervisor-DYKPbcZa.js} +488 -1407
  64. package/dist/supervisor-DYKPbcZa.js.map +1 -0
  65. package/dist/testing.d.ts +2 -2
  66. package/dist/testing.js +14 -14
  67. package/dist/tui/index.d.ts +1 -1
  68. package/dist/tui/index.js +1 -1
  69. package/dist/{types-jD9mNnJM.d.ts → types-DeuEkBhI.d.ts} +114 -258
  70. package/dist/{workspace-archive-pz8YJ1fr.d.ts → workspace-streams-CpSmt3zx.d.ts} +67 -3
  71. package/dist/{workspace-streams-D5gHJdTb.js → workspace-streams-DaQceg2p.js} +699 -2
  72. package/dist/workspace-streams-DaQceg2p.js.map +1 -0
  73. package/package.json +8 -8
  74. package/skills/generate-eval/SKILL.md +1 -1
  75. package/skills/profile-authoring/SKILL.md +2 -2
  76. package/dist/coordination-driver-vNrdQBSH.js.map +0 -1
  77. package/dist/graph-Dwv_hQB_.js.map +0 -1
  78. package/dist/improvement-cycle-Cf37Kexd.js.map +0 -1
  79. package/dist/prepare-CGVNMb1o.js.map +0 -1
  80. package/dist/runtime-6VPSJVeg.js.map +0 -1
  81. package/dist/search-method-wTTS7mGG.js.map +0 -1
  82. package/dist/server-BfHD5iLD.js.map +0 -1
  83. package/dist/supervise-BJrEC2Mh.js.map +0 -1
  84. package/dist/supervisor-DA_nvF-h.js.map +0 -1
  85. package/dist/workspace-streams-D5gHJdTb.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { c as RetainedInteractiveAdmissionError, d as RetainedRunDispatchBindingError, f as RuntimeRunStateError, i as ConfigError, l as RetainedInteractiveBindingError, m as ValidationError$1, r as BackendTransportError, t as AgentEvalError$1, u as RetainedRunAdmissionError } from "./errors-DodWX-cb.js";
2
+ import { $ as randomUuid, B as addTokenUsage, G as errorMessage, H as cloneSpend, K as fnv1a32Hex, N as deepFreezeCandidate, O as verifyWorkspaceSnapshotArtifacts, Q as randomSuffix, U as cloneTokenUsage, V as chargedTokens, W as deleteBoxSafe, X as mapWithConcurrency, Y as isAsyncIterable$1, Z as promptCacheTokenClasses, _t as armDeadlineTimer, a as verifyAgentCandidateWorkspaceArtifacts, at as unmeteredSpend, bt as singleFlightTeardown, ct as zeroTokenUsage, dt as resourceTelemetry, et as roundBoxMinutes, ft as withBudgetResources, gt as ROOT_DEADLINE_REASON, i as readAgentCandidateWorkspaceArtifactFiles, it as throwIfAborted, k as verifiedArtifactChunks, lt as addResourceSpend, mt as CHILD_DEADLINE_REASON, nt as stringifySafe, o as verifyAgentCandidateWorkspaceTree, ot as withTimeout, pt as ACCEPTED_RESULT_GRACE_MS, q as hasCompleteCacheBreakdown, rt as throwAbort, st as zeroSpend, tt as sleep, u as verifyAgentCandidateWorkspaceArchive, ut as assertResources, vt as boundedChildDeadlineAt, xt as teardownExecutor, yt as isDeadlineAbortReason, z as addSpend } from "./workspace-streams-DaQceg2p.js";
2
3
  import { runTaskQueue } from "./task-queue.js";
3
4
  import { _ as agentHarness, a as concreteProfileModel, c as profileModelExecutionSettings, d as assertRouterAutoDeclaration, f as assertRouterAutoResponse, g as observedModelMatchesDeclared, h as observedModelHasSnapshot, l as profileProviderModel, m as mergeObservedModelIdentity, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile, u as resolveRouterRetryPolicy } from "./model-policy-DydyWTQg.js";
4
- import { D as verifiedArtifactChunks, E as verifyWorkspaceSnapshotArtifacts, c as verifyAgentCandidateWorkspaceArchive, i as verifyAgentCandidateWorkspaceArtifacts, j as deepFreezeCandidate, r as readAgentCandidateWorkspaceArtifactFiles } from "./workspace-streams-D5gHJdTb.js";
5
5
  import { n as assertNoSymlinkDescendant, r as publishExclusiveDurableFile } from "./durable-file-DWQA4ooo.js";
6
6
  import { i as notifyRuntimeHookEvent } from "./runtime-hooks-tXpAarhW.js";
7
- import { AGENT_PROFILE_MATERIALIZATION_AXES, AgentEnvironmentCapabilitiesSchema, AgentExactRunControlRefSchema, AgentInteractiveSessionControlClaimAcknowledgementSchema, AgentInteractiveSessionControlClaimSchema, AgentInteractiveSessionPromptAcknowledgementSchema, AgentInteractiveSessionRefSchema, AgentInteractiveSessionStatusSchema, AgentInteractiveSessionStopAcknowledgementSchema, AgentNativeContextContinuationResultSchema, AgentRunCancellationAcknowledgementSchema, AgentRunCancellationRequestSchema, AgentTurnInputSchema, AgentTurnResultSchema, CanonicalStreamEventSchema, ContextTransferRequestSchema, InteractionAcknowledgementSchema, InteractionResponseCommandSchema, NativeContextBoundaryProofSchema, NativeContextContinuationRequestSchema, REASONING_EFFORTS, RuntimeEventEnvelopeSchema, TerminalReplayWindowSchema, TerminalSessionRefSchema, agentCandidateArtifactRefSchema, agentCandidateWorkspaceManifestMaterialSchema, agentCandidateWorkspaceSnapshotEvidenceSchema, agentInteractiveSessionControlClaimAcknowledgementMatchesRequest, agentInteractiveSessionControlClaimMatchesRef, agentInteractiveSessionPromptAcknowledgementMatchesCommand, agentInteractiveSessionRefMatchesStart, agentInteractiveSessionRunRef, agentInteractiveSessionStatusMatchesRef, agentInteractiveSessionStopAcknowledgementMatchesCommand, agentNativeContextContinuationResultMatchesRequest, agentProfileSchema, agentRunCancellationAcknowledgementMatchesRequest, agentRunCancellationRequestDigest, canonicalAgentProfileDigest, canonicalCandidateDigest, canonicalWorkspaceCwd, exactAgentInteractiveSessionStart, harnessTypeSchema, nativeContextContinuationTurnDigest, nativeReasoningControl, profileMaterializationAxes, profileMaterializationAxes as profileMaterializationAxes$1, renderInputPartsAsText, sha256DigestSchema, workspaceCheckpointRequestDigest, workspaceCheckpointResultMatchesRequest, workspaceCleanupAcknowledgementMatches, workspaceCleanupRequestDigest } from "@tangle-network/agent-interface";
7
+ import { AGENT_PROFILE_MATERIALIZATION_AXES, AgentEnvironmentCapabilitiesSchema, AgentExactRunControlRefSchema, AgentInteractiveSessionControlClaimAcknowledgementSchema, AgentInteractiveSessionControlClaimSchema, AgentInteractiveSessionPromptAcknowledgementSchema, AgentInteractiveSessionRefSchema, AgentInteractiveSessionStatusSchema, AgentInteractiveSessionStopAcknowledgementSchema, AgentNativeContextContinuationResultSchema, AgentRunCancellationAcknowledgementSchema, AgentRunCancellationRequestSchema, AgentTurnInputSchema, AgentTurnResultSchema, CanonicalStreamEventSchema, ContextTransferRequestSchema, InteractionAcknowledgementSchema, InteractionResponseCommandSchema, NativeContextBoundaryProofSchema, NativeContextContinuationRequestSchema, REASONING_EFFORTS, RuntimeEventEnvelopeSchema, TerminalReplayWindowSchema, TerminalSessionRefSchema, agentCandidateArtifactRefSchema, agentCandidateWorkspaceManifestMaterialSchema, agentCandidateWorkspaceSnapshotEvidenceSchema, agentInteractiveSessionControlClaimAcknowledgementMatchesRequest, agentInteractiveSessionControlClaimMatchesRef, agentInteractiveSessionPromptAcknowledgementMatchesCommand, agentInteractiveSessionRefMatchesStart, agentInteractiveSessionRunRef, agentInteractiveSessionStatusMatchesRef, agentInteractiveSessionStopAcknowledgementMatchesCommand, agentNativeContextContinuationResultMatchesRequest, agentProfileSchema, agentRunCancellationAcknowledgementMatchesRequest, agentRunCancellationRequestDigest, canonicalAgentProfileDigest, canonicalCandidateDigest, canonicalWorkspaceCwd, exactAgentInteractiveSessionStart, harnessTypeSchema, nativeContextContinuationTurnDigest, nativeReasoningControl, profileMaterializationAxes, profileMaterializationAxes as profileMaterializationAxes$1, renderInputPartsAsText, sha256DigestSchema, workspaceCheckpointRequestDigest, workspaceCheckpointResultMatchesRequest, workspaceCleanupAcknowledgementMatches, workspaceCleanupRequestDigest, workspaceForkRequestDigest, workspaceForkResultMatchesRequest } from "@tangle-network/agent-interface";
8
8
  import { estimateCost, isModelPriced, isToolSpan, toolSpansToTraceAnalysisStore } from "@tangle-network/agent-eval";
9
9
  import { createAgentRunOutcomeTracker } from "@tangle-network/sandbox/runtime";
10
10
  import { createHash, randomBytes, randomUUID } from "node:crypto";
@@ -102,130 +102,6 @@ function promptPartFromInputPart(part) {
102
102
  };
103
103
  }
104
104
  //#endregion
105
- //#region src/runtime/supervise/deadline.ts
106
- const MAX_TIMER_DELAY_MS = 2147483647;
107
- const DEFAULT_SUCCESSFUL_SHUTDOWN_MS = 5e3;
108
- /** The abort reason a child's own deadline carries. */
109
- const CHILD_DEADLINE_REASON = "child deadline exceeded";
110
- /** The abort reason the root's budget deadline cascades to every node. */
111
- const ROOT_DEADLINE_REASON = "root budget deadline exceeded";
112
- /**
113
- * How long an abort waits for a manager whose result was already accepted to end the turn that
114
- * submitted it. Acceptance asks the turn's harness to stop; what remains is the turn's final
115
- * session copy (a bounded native capture), metering its usage and committing its result. Its
116
- * workspace capture is not part of it: the manager's owner runs that after the result.
117
- */
118
- const ACCEPTED_RESULT_GRACE_MS = 5 * 6e4;
119
- /** Whether an abort reason is a deadline: the child's own or the root budget's. */
120
- function isDeadlineAbortReason(reason) {
121
- return reason === "child deadline exceeded" || reason === "root budget deadline exceeded";
122
- }
123
- const TEARDOWN_ACKNOWLEDGEMENT_MS = 250;
124
- /** Arm a finite wall-clock deadline in safe chunks. Resource deadlines unref by default;
125
- * a standalone wait opts into keeping the process alive until it settles or is cancelled. */
126
- function armDeadlineTimer(delayMs, onDeadline, keepAlive = false) {
127
- const deadlineAtMs = Date.now() + Math.max(0, delayMs);
128
- if (!Number.isFinite(delayMs) || !Number.isSafeInteger(Math.ceil(deadlineAtMs))) throw new ValidationError$1("timer delay must produce a finite safe deadline");
129
- let cleared = false;
130
- let timer;
131
- const arm = () => {
132
- if (cleared) return;
133
- const remainingMs = Math.max(0, deadlineAtMs - Date.now());
134
- timer = setTimeout(() => {
135
- if (cleared) return;
136
- if (Date.now() >= deadlineAtMs) onDeadline();
137
- else arm();
138
- }, Math.min(remainingMs, MAX_TIMER_DELAY_MS));
139
- if (!keepAlive && typeof timer.unref === "function") timer.unref();
140
- };
141
- arm();
142
- return () => {
143
- cleared = true;
144
- if (timer !== void 0) clearTimeout(timer);
145
- };
146
- }
147
- /**
148
- * Resolve a spawned child's duration into one absolute cutoff. An omitted child deadline inherits
149
- * the parent cutoff; an explicit child duration may shorten, but never extend, that cutoff.
150
- */
151
- function boundedChildDeadlineAt(parentDeadlineAtMs, childDeadlineMs, nowMs) {
152
- const parent = parentDeadlineAtMs > 0 ? parentDeadlineAtMs : void 0;
153
- const child = childDeadlineMs === void 0 ? void 0 : nowMs + childDeadlineMs;
154
- if (parent === void 0) return child;
155
- if (child === void 0) return parent;
156
- return Math.min(parent, child);
157
- }
158
- /** Invoke teardown once and bound how long the runtime waits for its acknowledgement. A hard
159
- * execution deadline always wins; without one, numeric grace gets a short acknowledgement
160
- * allowance and a brutal kill gets only that allowance. Explicit `infinity` remains unbounded
161
- * only when no execution deadline exists. The losing promise stays observed. `ask` issues the
162
- * request; a scope passes its per-child single-flight asker (see `singleFlightTeardown`). */
163
- async function teardownExecutor(executor, grace, deadlineAtMs, now, ask = (requested) => Promise.resolve(executor.teardown(requested))) {
164
- const work = Promise.resolve(ask(grace));
165
- const requestedWaitMs = grace === "infinity" ? void 0 : grace === "brutalKill" ? executor.teardownTimeoutMs ?? TEARDOWN_ACKNOWLEDGEMENT_MS : grace + TEARDOWN_ACKNOWLEDGEMENT_MS;
166
- const deadlineWaitMs = deadlineAtMs === void 0 ? void 0 : Math.max(0, deadlineAtMs - now()) + TEARDOWN_ACKNOWLEDGEMENT_MS;
167
- const waitMs = requestedWaitMs === void 0 ? deadlineWaitMs : deadlineWaitMs === void 0 ? requestedWaitMs : Math.min(requestedWaitMs, deadlineWaitMs);
168
- let receipt;
169
- if (waitMs === void 0) receipt = await work;
170
- else if (waitMs <= 0) {
171
- work.catch(() => void 0);
172
- throw new ValidationError$1("executor teardown did not acknowledge before its deadline");
173
- } else {
174
- let clearTimer;
175
- const timedOut = new Promise((_resolve, reject) => {
176
- clearTimer = armDeadlineTimer(waitMs, () => reject(new ValidationError$1(`executor teardown did not acknowledge within ${waitMs}ms`)), true);
177
- });
178
- try {
179
- receipt = await Promise.race([work, timedOut]);
180
- } finally {
181
- clearTimer?.();
182
- }
183
- }
184
- if (!receipt.destroyed) throw new ValidationError$1(`executor teardown reported destroyed=false${receipt.detail ? `: ${receipt.detail}` : ""}`);
185
- }
186
- /**
187
- * The optional teardown surfaces a wrapping executor forwards, so wrapping never changes how a
188
- * child is released: the acknowledgement window a remote teardown needs, the release of a
189
- * retained execution at root settlement, and the environments an unconfirmed teardown names for
190
- * a sweeper. A wrapper that dropped `releaseRetained` left every retained child it wrapped
191
- * running after settlement. Each surface is present only when the inner executor implements it.
192
- */
193
- function teardownSurfaces(inner) {
194
- return {
195
- ...inner.teardownTimeoutMs === void 0 ? {} : { teardownTimeoutMs: inner.teardownTimeoutMs },
196
- ...inner.releaseRetained === void 0 ? {} : { releaseRetained: (signal) => inner.releaseRetained(signal) },
197
- ...inner.heldEnvironments === void 0 ? {} : { heldEnvironments: () => inner.heldEnvironments() }
198
- };
199
- }
200
- /**
201
- * An asker that sends an executor at most one teardown at a time. While a request is still
202
- * running, every later ask returns that same request instead of sending another beside it.
203
- *
204
- * A settlement's own teardown has a short acknowledgement window, and a request that misses it
205
- * keeps running. Without this, the first settlement retry sent a second teardown next to the
206
- * first. An executor that does not deduplicate internally, such as one that re-issues its
207
- * cancels, then ran two teardowns at once. `onRequest` runs once for each request actually sent.
208
- */
209
- function singleFlightTeardown(executor, onRequest) {
210
- let inFlight;
211
- return (grace) => {
212
- if (inFlight !== void 0) return inFlight;
213
- onRequest();
214
- let request;
215
- try {
216
- request = Promise.resolve(executor.teardown(grace));
217
- } catch (error) {
218
- request = Promise.reject(error);
219
- }
220
- inFlight = request;
221
- const settle = () => {
222
- if (inFlight === request) inFlight = void 0;
223
- };
224
- request.then(settle, settle);
225
- return request;
226
- };
227
- }
228
- //#endregion
229
105
  //#region src/runtime/retained-run-binding.ts
230
106
  function exactSession(environment, controlRef) {
231
107
  if (environment.id !== controlRef.environmentId || environment.provider !== controlRef.provider) throw new Error("provider reconstructed a different retained environment");
@@ -322,7 +198,7 @@ async function awaitAbortable$1(work, signal) {
322
198
  if (signal === void 0) return await work;
323
199
  if (signal.aborted) {
324
200
  Promise.resolve(work).catch(() => void 0);
325
- throw abortError$2(signal.reason);
201
+ throw abortError$1(signal.reason);
326
202
  }
327
203
  return await new Promise((resolve, reject) => {
328
204
  let settled = false;
@@ -332,7 +208,7 @@ async function awaitAbortable$1(work, signal) {
332
208
  if (settled) return;
333
209
  settled = true;
334
210
  cleanup();
335
- reject(abortError$2(signal.reason));
211
+ reject(abortError$1(signal.reason));
336
212
  });
337
213
  };
338
214
  signal.addEventListener("abort", onAbort, { once: true });
@@ -389,7 +265,7 @@ function isRecord$3(value) {
389
265
  function assertStableText(value, label) {
390
266
  if (value.length === 0 || value.trim() !== value) throw new Error(`${label} must be non-empty and have no outer whitespace`);
391
267
  }
392
- function abortError$2(reason) {
268
+ function abortError$1(reason) {
393
269
  const error = new Error(reason instanceof Error ? reason.message : reason === void 0 ? "aborted" : String(reason));
394
270
  error.name = "AbortError";
395
271
  return error;
@@ -426,7 +302,7 @@ function isTerminalSessionStatus(status) {
426
302
  return status !== null && sessionStatusIsTerminal[status];
427
303
  }
428
304
  function delay(ms, signal) {
429
- if (signal?.aborted) return Promise.reject(abortError$2(signal.reason));
305
+ if (signal?.aborted) return Promise.reject(abortError$1(signal.reason));
430
306
  return new Promise((resolveDelay, rejectDelay) => {
431
307
  const clearTimer = armDeadlineTimer(ms, finish, true);
432
308
  function finish() {
@@ -436,7 +312,7 @@ function delay(ms, signal) {
436
312
  function onAbort() {
437
313
  clearTimer();
438
314
  signal?.removeEventListener("abort", onAbort);
439
- rejectDelay(abortError$2(signal?.reason));
315
+ rejectDelay(abortError$1(signal?.reason));
440
316
  }
441
317
  signal?.addEventListener("abort", onAbort, { once: true });
442
318
  });
@@ -661,477 +537,6 @@ function isRecord$2(value) {
661
537
  return typeof value === "object" && value !== null && !Array.isArray(value);
662
538
  }
663
539
  //#endregion
664
- //#region src/runtime/supervise/resources.ts
665
- /** Validate caller-owned names and units without assigning domain meaning to them. */
666
- function assertResources(resources, kind, label) {
667
- if (resources === void 0) return;
668
- if (resources === null || typeof resources !== "object" || Array.isArray(resources)) throw new Error(`${label} must be a resource map`);
669
- for (const [name, resource] of Object.entries(resources)) {
670
- if (!name.trim() || !resource || typeof resource !== "object" || typeof resource.unit !== "string" || !resource.unit.trim()) throw new Error(`${label}: resource names and units must be non-empty strings`);
671
- const value = kind === "limit" ? "limit" in resource ? resource.limit : void 0 : "amount" in resource ? resource.amount : void 0;
672
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw new Error(`${label}.${name}.${kind} must be a non-negative safe integer`);
673
- if (kind === "amount" && (!("known" in resource) || typeof resource.known !== "boolean")) throw new Error(`${label}.${name}.known must be a boolean`);
674
- }
675
- }
676
- /** Missing contributors are not usage claims; enforced omissions are marked before aggregation.
677
- * Overflow retains a safe lower bound and marks it unknown, preserving readable component receipts. */
678
- function addResourceSpend(...maps) {
679
- const totals = /* @__PURE__ */ new Map();
680
- for (const resources of maps) {
681
- assertResources(resources, "amount", "resource spend");
682
- for (const [name, resource] of Object.entries(resources ?? {})) {
683
- const prior = totals.get(name);
684
- if (prior && prior.unit !== resource.unit) throw new Error(`resource ${name}: unit mismatch`);
685
- const amount = (prior?.amount ?? 0) + resource.amount;
686
- totals.set(name, {
687
- unit: resource.unit,
688
- amount: Math.min(amount, Number.MAX_SAFE_INTEGER),
689
- known: (prior?.known ?? true) && resource.known && Number.isSafeInteger(amount)
690
- });
691
- }
692
- }
693
- return totals.size ? { resources: Object.fromEntries(totals) } : {};
694
- }
695
- /** A terminal omission under an enforced ceiling is unknown, never measured zero. */
696
- function withBudgetResources(spend, budget, notStarted = false) {
697
- const resources = new Map(Object.entries(addResourceSpend(spend.resources).resources ?? {}));
698
- for (const [name, limit] of Object.entries(budget.resources ?? {})) {
699
- const observed = resources.get(name);
700
- if (observed && observed.unit !== limit.unit) throw new Error(`resource ${name}: unit mismatch`);
701
- if (!observed) resources.set(name, {
702
- unit: limit.unit,
703
- amount: 0,
704
- known: notStarted
705
- });
706
- }
707
- return resources.size ? {
708
- ...spend,
709
- resources: Object.fromEntries(resources)
710
- } : spend;
711
- }
712
- /** Stream increments and a terminal total describe the same work; never sum them twice. */
713
- function resourceTelemetry(streamed, terminal) {
714
- const resources = new Map(Object.entries(addResourceSpend(terminal.resources).resources ?? {}));
715
- for (const [name, value] of Object.entries(streamed.resources ?? {})) {
716
- const other = resources.get(name);
717
- if (other && other.unit !== value.unit) throw new Error(`resource ${name}: unit mismatch`);
718
- resources.set(name, {
719
- ...value,
720
- amount: Math.max(value.amount, other?.amount ?? 0),
721
- known: value.known && (other?.known ?? true) && (other === void 0 || other.amount === value.amount)
722
- });
723
- }
724
- return addResourceSpend(Object.fromEntries(resources));
725
- }
726
- //#endregion
727
- //#region src/runtime/util.ts
728
- /**
729
- * Best-effort sandbox delete. Skips instances without a `delete` (test fakes);
730
- * swallows errors (the platform reaps on expiry). Returns `false` when delete
731
- * threw, `true` otherwise, so callers can surface a leak if they choose.
732
- */
733
- async function deleteBoxSafe(box) {
734
- if (!box || typeof box.delete !== "function") return true;
735
- try {
736
- await box.delete();
737
- return true;
738
- } catch {
739
- return false;
740
- }
741
- }
742
- /** Short base36 id for trace correlation. Not cryptographic, not collision-free. */
743
- function randomSuffix(len = 8) {
744
- return Math.random().toString(36).slice(2, 2 + len);
745
- }
746
- /** Collision-resistant id for sandbox naming (find-by-name recovery must be unique). */
747
- function randomUuid() {
748
- return crypto.randomUUID();
749
- }
750
- /** Construct an AbortError. Downstream code pattern-matches on `err.name`. */
751
- function abortError$1() {
752
- const err = /* @__PURE__ */ new Error("aborted");
753
- err.name = "AbortError";
754
- return err;
755
- }
756
- /** Throw an AbortError. */
757
- function throwAbort() {
758
- throw abortError$1();
759
- }
760
- /** Throw if the signal is already aborted; otherwise no-op. */
761
- function throwIfAborted(signal) {
762
- if (signal?.aborted) throw abortError$1();
763
- }
764
- /** True for any error whose `name` is `AbortError` (the cross-kernel abort contract). */
765
- function isAbortError$2(err) {
766
- return err instanceof Error && err.name === "AbortError";
767
- }
768
- /**
769
- * Sleep that resolves early on abort and always clears its timer so it never
770
- * keeps the event loop alive. Resolves (does not reject) on abort — callers
771
- * re-check the signal explicitly after the sleep.
772
- */
773
- function sleep(ms, signal, keepAlive = true) {
774
- if (signal?.aborted) return Promise.resolve();
775
- return new Promise((resolve) => {
776
- const done = () => {
777
- clearTimer();
778
- signal?.removeEventListener("abort", done);
779
- resolve();
780
- };
781
- const clearTimer = armDeadlineTimer(ms, done, keepAlive);
782
- signal?.addEventListener("abort", done, { once: true });
783
- });
784
- }
785
- /**
786
- * Race a promise against a timeout. Resolves with the value if it settles in
787
- * time, otherwise resolves with `undefined`. Always clears the timer.
788
- */
789
- function withTimeout(promise, ms) {
790
- return new Promise((resolve) => {
791
- const clearTimer = armDeadlineTimer(ms, () => resolve(void 0), true);
792
- promise.then((value) => {
793
- clearTimer();
794
- resolve(value);
795
- }, () => {
796
- clearTimer();
797
- resolve(void 0);
798
- });
799
- });
800
- }
801
- /**
802
- * `JSON.stringify` with a `String()` fallback on throw (cyclic / non-JSON).
803
- * Strings pass through unstringified so a preview of a string output is the
804
- * string itself, not a quoted re-encoding.
805
- */
806
- function stringifySafe(value, opts = {}) {
807
- let s;
808
- try {
809
- if (typeof value === "string") s = value;
810
- else s = (opts.pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value)) ?? String(value);
811
- } catch {
812
- s = String(value);
813
- }
814
- if (opts.max !== void 0 && s.length > opts.max) return `${s.slice(0, opts.max)}…`;
815
- return s;
816
- }
817
- /** A fresh zero token-usage accumulator. */
818
- function zeroTokenUsage() {
819
- return {
820
- input: 0,
821
- output: 0
822
- };
823
- }
824
- /**
825
- * Sum the catalog-priced part of a dollar total across spends, as a field to spread.
826
- *
827
- * Returns nothing when no input carried one. A fold of pure provider receipts must not gain a
828
- * `usdEstimated: 0`, which would read as "this runtime checked and priced none" on a path that
829
- * never prices at all.
830
- */
831
- function usdEstimatedOf(...spends) {
832
- let total = 0;
833
- let priced = false;
834
- for (const spend of spends) {
835
- if (spend.usdEstimated === void 0) continue;
836
- priced = true;
837
- total += spend.usdEstimated;
838
- }
839
- return priced ? { usdEstimated: total } : {};
840
- }
841
- /** A conserved spend with every channel at zero and no completeness claim on it. */
842
- function zeroSpend() {
843
- return {
844
- iterations: 0,
845
- tokens: zeroTokenUsage(),
846
- usd: 0,
847
- ms: 0
848
- };
849
- }
850
- /**
851
- * The spend of work that HAPPENED and reported no usage receipt.
852
- *
853
- * Not the same value as {@link zeroSpend} even though both carry `{0,0}` tokens and `$0`. A bare
854
- * zero asserts a MEASUREMENT — "this ran and cost nothing" — and every consumer downstream reads it
855
- * that way: the pool keeps reporting `readout().tokensKnown === true`, the journal totals stay
856
- * clean, the OTEL span records a priced zero, and a caller's token-denominated ceiling can never
857
- * fire no matter how much the work really burned. A ceiling that cannot fire is worse than no
858
- * ceiling, because it reads as protection.
859
- *
860
- * `tokensKnown` is the marker the substrate already threads end to end for exactly this case
861
- * (`budget.ts`, `otel-spans.ts`, `spawn-journal.ts`, `supervisor.ts`): the work is recorded, the
862
- * zero is labelled a floor rather than a total, and every rollup that touches it reports its
863
- * balance as a ceiling rather than a measurement. Use this — never a bare zero — whenever a runtime
864
- * cannot see what its worker spent.
865
- *
866
- * The same rule applies to dollars. A dollar-capped run must refuse an executor whose billed spend
867
- * is unknowable; `budgetExempt` does not authorize Runtime to relabel unknown spend as a measured
868
- * zero. Callers that require dollar accounting must use a backend with a trusted billing receipt.
869
- */
870
- function unmeteredSpend(ms) {
871
- return {
872
- iterations: 0,
873
- tokens: zeroTokenUsage(),
874
- tokensKnown: false,
875
- usd: 0,
876
- usdKnown: false,
877
- ms
878
- };
879
- }
880
- /** Copy a conserved spend without dropping a completeness marker or the catalog-priced part. */
881
- function cloneSpend(spend) {
882
- return {
883
- ...addResourceSpend(spend.resources),
884
- iterations: spend.iterations,
885
- tokens: cloneTokenUsage(spend.tokens),
886
- ...spend.tokensKnown === false ? { tokensKnown: false } : {},
887
- usd: spend.usd,
888
- ...spend.usdKnown === false ? { usdKnown: false } : {},
889
- ...spend.usdEstimated !== void 0 ? { usdEstimated: spend.usdEstimated } : {},
890
- ms: spend.ms,
891
- ...boxMinutesOf(spend),
892
- ...spend.tokensProvenance === void 0 ? {} : { tokensProvenance: spend.tokensProvenance }
893
- };
894
- }
895
- /**
896
- * Sum two conserved spends per channel. Tokens and dollars never fold into each other, an
897
- * incomplete input keeps the sum incomplete on that channel, and the catalog-priced part of the
898
- * dollar total is summed separately so `usd - usdEstimated` still names what a provider billed.
899
- */
900
- function addSpend(a, b) {
901
- const tokens = cloneTokenUsage(a.tokens);
902
- addTokenUsage(tokens, b.tokens);
903
- return {
904
- ...addResourceSpend(a.resources, b.resources),
905
- iterations: a.iterations + b.iterations,
906
- tokens,
907
- ...a.tokensKnown === false || b.tokensKnown === false ? { tokensKnown: false } : {},
908
- usd: a.usd + b.usd,
909
- ...a.usdKnown === false || b.usdKnown === false ? { usdKnown: false } : {},
910
- ...usdEstimatedOf(a, b),
911
- ms: a.ms + b.ms,
912
- ...boxMinutesOf(a, b),
913
- ...tokensProvenanceOf(a, b)
914
- };
915
- }
916
- /**
917
- * Fold the token-provenance channel across spends, as a field to spread.
918
- *
919
- * Returns nothing when no contributor stated one, because ABSENT already means "the executor's own
920
- * live stream", which is what every path reported before a harness store was readable. A
921
- * contributor that stated one and a contributor that did not therefore disagree, and the sum is
922
- * `'mixed'` — the honest answer for a tree whose spend came from two kinds of receipt.
923
- */
924
- function tokensProvenanceOf(...spends) {
925
- let folded;
926
- let sawStated = false;
927
- for (const spend of spends) {
928
- const stated = spend.tokensProvenance ?? "stream-receipt";
929
- if (spend.tokensProvenance !== void 0) sawStated = true;
930
- folded = folded === void 0 || folded === stated ? stated : "mixed";
931
- }
932
- return !sawStated || folded === void 0 || folded === "stream-receipt" ? {} : { tokensProvenance: folded };
933
- }
934
- /**
935
- * Fold the platform box-time channel across spends, as a field to spread.
936
- *
937
- * Returns nothing when no input carried the channel, so a fold over router or cli-bridge work —
938
- * which runs no box at all — never gains a `boxMinutesProvenance: 'uncaptured'` that would claim
939
- * a box ran and went unmetered.
940
- *
941
- * Three rules, one per field:
942
- * - `boxMinutes` sums the numbers that are present, and stays ABSENT when none is. A missing
943
- * measurement never enters the sum as a zero.
944
- * - `boxMinutesKnown` is sticky-false, like `tokensKnown`: one contributor that could not state
945
- * its box time makes the whole sum a floor.
946
- * - `boxMinutesProvenance` degrades. `'observed'` survives only when every contributor that
947
- * carried a number was observed; one derived number makes the sum `'estimated'`; no number at
948
- * all is `'uncaptured'`.
949
- */
950
- function boxMinutesOf(...spends) {
951
- const present = spends.filter((spend) => spend.boxMinutesProvenance !== void 0);
952
- if (present.length === 0) return {};
953
- let minutes = 0;
954
- let sawNumber = false;
955
- let known = true;
956
- let observedOnly = true;
957
- for (const spend of present) {
958
- if (typeof spend.boxMinutes === "number" && Number.isFinite(spend.boxMinutes)) {
959
- minutes += spend.boxMinutes;
960
- sawNumber = true;
961
- if (spend.boxMinutesProvenance !== "observed") observedOnly = false;
962
- }
963
- if (spend.boxMinutesKnown !== true) known = false;
964
- }
965
- return {
966
- ...sawNumber ? { boxMinutes: roundBoxMinutes(minutes) } : {},
967
- boxMinutesKnown: known,
968
- boxMinutesProvenance: sawNumber ? observedOnly ? "observed" : "estimated" : "uncaptured"
969
- };
970
- }
971
- /**
972
- * Box minutes at four decimals — a tenth of a second.
973
- *
974
- * Fine enough that a box alive for two seconds reports `0.0333` instead of a zero that would read
975
- * as a measured free box, and coarse enough that summing floats does not print
976
- * `1.5000000000000002`.
977
- */
978
- function roundBoxMinutes(minutes) {
979
- return Number(minutes.toFixed(4));
980
- }
981
- /** Copy a token subtotal without dropping optional provider cache telemetry. */
982
- function cloneTokenUsage(usage) {
983
- const cacheBreakdownUnknown = usage.cacheBreakdownKnown === false || usage.input > 0 && !hasClassifiedCacheBreakdown(usage);
984
- return {
985
- input: usage.input,
986
- output: usage.output,
987
- ...usage.tokensKnown === false ? { tokensKnown: false } : {},
988
- ...usage.freshInput !== void 0 ? { freshInput: usage.freshInput } : {},
989
- ...usage.cacheRead !== void 0 ? { cacheRead: usage.cacheRead } : {},
990
- ...usage.cacheWrite !== void 0 ? { cacheWrite: usage.cacheWrite } : {},
991
- ...cacheBreakdownUnknown ? { cacheBreakdownKnown: false } : {}
992
- };
993
- }
994
- /** True only when every positive prompt token has a consistent cache classification. */
995
- function hasCompleteCacheBreakdown(usage) {
996
- if (usage.cacheBreakdownKnown === false) return false;
997
- return hasClassifiedCacheBreakdown(usage);
998
- }
999
- function hasClassifiedCacheBreakdown(usage) {
1000
- if (usage.input === 0) return true;
1001
- if (usage.freshInput === void 0 || usage.cacheRead === void 0 || usage.cacheWrite === void 0) return false;
1002
- return usage.freshInput + usage.cacheRead + usage.cacheWrite === usage.input;
1003
- }
1004
- /**
1005
- * The token charge for one observation: every token counted ONCE, at the moment it first enters
1006
- * the context — `input − cacheRead + output`.
1007
- *
1008
- * `input` is a rolled-up prompt total that re-counts a cached prefix on every turn that reads it,
1009
- * so charging `input` makes a 100K prefix read 40 times cost 4.1M for content authored once. A
1010
- * cache read is content that was already charged when it was written, so it is the one class the
1011
- * charge subtracts. Under a complete split the result is exactly `freshInput + cacheWrite`. No
1012
- * price weight is involved: this counts work, and money is a separate channel.
1013
- *
1014
- * The subtraction form is what makes the charge ADDITIVE. `input` and `cacheRead` both accumulate
1015
- * through `addTokenUsage`, so the charge on an aggregate equals the sum of the charges on the
1016
- * records that built it — including an aggregate that mixes classified and unclassified turns,
1017
- * where the unclassified remainder is charged in full and only the reported cache reads are
1018
- * credited. A form that read `freshInput + cacheWrite` directly loses that: one unclassified turn
1019
- * would drop the whole aggregate to `input + output` and over-charge every classified turn with it.
1020
- *
1021
- * The one arithmetic guarantee: a set of classes that does not FIT inside the prompt total it
1022
- * partitions credits nothing, so the charge is never below `output` and a class that overflows its
1023
- * own total buys no tokens. It is not a guarantee against a provider that reports a cache read it
1024
- * never served — that provider can under-report `input` just as easily, and the token channel is an
1025
- * accounting unit, not a trust boundary. Prompt tokens the provider left unclassified are charged
1026
- * in full, so a spend with no readable split charges an upper bound on newly-presented work rather
1027
- * than a measurement, and every caller that enforces a ceiling must report the difference
1028
- * (`BudgetPool` does it through `readout().cacheBreakdownKnown`).
1029
- */
1030
- function chargedTokens(usage) {
1031
- return usage.input - creditedCacheRead(usage) + usage.output;
1032
- }
1033
- /** `cacheRead` if the reported classes fit inside `input`, else nothing. */
1034
- function creditedCacheRead(usage) {
1035
- const { cacheRead } = usage;
1036
- if (cacheRead === void 0) return 0;
1037
- return classifiedTotal(usage, cacheRead) > usage.input ? 0 : cacheRead;
1038
- }
1039
- function classifiedTotal(usage, cacheRead) {
1040
- return (usage.freshInput ?? 0) + cacheRead + (usage.cacheWrite ?? 0);
1041
- }
1042
- /**
1043
- * Translate one provider prompt-cache report into the prompt token classes `addTokenUsage` folds
1044
- * and `chargedTokens` credits.
1045
- *
1046
- * The input is the open `promptCache` record an `llm_call` carries, keyed by the `PromptCacheUsage`
1047
- * vocabulary (`readTokens`, `writeTokens`). Providers report that vocabulary unevenly, and the
1048
- * three outcomes are different facts that must not collapse into one another:
1049
- *
1050
- * - **Nothing reported** — no classes and no marker. The caller's own unknown handling decides,
1051
- * because a provider that says nothing about caching has not said the split is unknowable.
1052
- * - **Read and write both reported, and fitting inside `input`** — a complete partition, so
1053
- * `freshInput` is the remainder and the split is known.
1054
- * - **One counter reported, or classes that overflow `input`** — the counters that ARE measured
1055
- * pass through and `cacheBreakdownKnown` is false. A read with no write counter (OpenAI reports
1056
- * no write) still credits the read it measured, while declaring the rest unclassified so the
1057
- * charge stays a declared upper bound. An overflowing claim buys nothing: it cannot be a
1058
- * partition of a total it exceeds.
1059
- *
1060
- * A counter the provider did not report stays absent. A zero would claim the provider measured no
1061
- * cache, which is a different fact from a provider that did not report.
1062
- */
1063
- function promptCacheTokenClasses(input, promptCache) {
1064
- if (promptCache === void 0) return {};
1065
- const read = tokenCount(promptCache.readTokens);
1066
- const write = tokenCount(promptCache.writeTokens);
1067
- if (read === void 0 && write === void 0) return {};
1068
- if (input === void 0 || (read ?? 0) + (write ?? 0) > input) return { cacheBreakdownKnown: false };
1069
- if (read !== void 0 && write !== void 0) return {
1070
- freshInput: input - read - write,
1071
- cacheRead: read,
1072
- cacheWrite: write
1073
- };
1074
- return {
1075
- ...read !== void 0 ? { cacheRead: read } : {},
1076
- ...write !== void 0 ? { cacheWrite: write } : {},
1077
- cacheBreakdownKnown: false
1078
- };
1079
- }
1080
- function tokenCount(value) {
1081
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
1082
- }
1083
- /**
1084
- * Add the observed subtotal into `acc`; token and cache incompleteness are sticky.
1085
- *
1086
- * A delta whose classes do not FIT inside its own `input` contributes its prompt total and NO
1087
- * classes. Folding them in would hide the overflow: the accumulator's larger `input` can absorb a
1088
- * class total that overflowed the one delta that reported it, and `chargedTokens` would then credit
1089
- * at the aggregate a cache read it refuses at the record. That is the one way the charge could come
1090
- * out below the sum of the charges on the records that built it.
1091
- */
1092
- function addTokenUsage(acc, delta) {
1093
- acc.input += delta.input ?? 0;
1094
- acc.output += delta.output ?? 0;
1095
- if (delta.tokensKnown === false) acc.tokensKnown = false;
1096
- const input = delta.input ?? 0;
1097
- const fits = classifiedTotal(delta, delta.cacheRead ?? 0) <= input;
1098
- if (fits) {
1099
- if (delta.freshInput !== void 0) acc.freshInput = (acc.freshInput ?? 0) + delta.freshInput;
1100
- if (delta.cacheRead !== void 0) acc.cacheRead = (acc.cacheRead ?? 0) + delta.cacheRead;
1101
- if (delta.cacheWrite !== void 0) acc.cacheWrite = (acc.cacheWrite ?? 0) + delta.cacheWrite;
1102
- }
1103
- const classified = fits && delta.freshInput !== void 0 && delta.cacheRead !== void 0 && delta.cacheWrite !== void 0 && delta.freshInput + delta.cacheRead + delta.cacheWrite === input;
1104
- if (delta.cacheBreakdownKnown === false || input > 0 && !classified) acc.cacheBreakdownKnown = false;
1105
- }
1106
- /**
1107
- * Map `items` through `fn` with at most `limit` calls in flight at once,
1108
- * preserving input order in the result. On the first `fn` rejection no NEW
1109
- * items are picked up; already-in-flight calls are awaited, then the first
1110
- * error is rethrown. `limit` is clamped to ≥ 1.
1111
- *
1112
- * Used where a burst of provisioning (e.g. forking N child boxes) must respect
1113
- * the loop's concurrency bound instead of firing all N at once.
1114
- */
1115
- async function mapWithConcurrency(items, limit, fn) {
1116
- const results = new Array(items.length);
1117
- let next = 0;
1118
- for await (const settled of runTaskQueue({
1119
- concurrency: Math.max(1, Math.min(Math.floor(limit), items.length)),
1120
- take: () => {
1121
- const index = next++;
1122
- return index < items.length ? {
1123
- id: String(index),
1124
- value: index
1125
- } : void 0;
1126
- },
1127
- execute: ({ value: index }) => fn(items[index], index)
1128
- })) {
1129
- if (settled.status === "rejected") throw settled.reason;
1130
- results[settled.task.value] = settled.value;
1131
- }
1132
- return results;
1133
- }
1134
- //#endregion
1135
540
  //#region src/runtime/sandbox-events.ts
1136
541
  const CANONICAL_STREAM_EVENT_TYPES = /* @__PURE__ */ new Set([
1137
542
  "child-task",
@@ -2502,140 +1907,6 @@ function providerAttemptEvidence(model) {
2502
1907
  });
2503
1908
  }
2504
1909
  //#endregion
2505
- //#region src/durable/jsonl-file.ts
2506
- /** Read a fixed file prefix one record at a time, never allocating the whole journal as a string.
2507
- * A reader cannot chase concurrent appends forever. Missing files are empty only when requested;
2508
- * corruption, short reads, and other I/O errors remain failures. Closing the iterator closes the fd. */
2509
- async function* readCommittedJsonLines(path, options = {}) {
2510
- const fs = await import("node:fs/promises");
2511
- let handle;
2512
- try {
2513
- handle = await fs.open(path, "r");
2514
- } catch (error) {
2515
- if (options.allowMissing && isNoEntError(error)) return;
2516
- throw error;
2517
- }
2518
- try {
2519
- const { size } = await handle.stat();
2520
- if (size === 0) return;
2521
- const { StringDecoder } = await import("node:string_decoder");
2522
- const decoder = new StringDecoder("utf8");
2523
- const stream = handle.createReadStream({
2524
- autoClose: false,
2525
- end: size - 1
2526
- });
2527
- const fragments = [];
2528
- let lineNumber = 1;
2529
- try {
2530
- for await (const chunk of stream) {
2531
- options.onBytes?.(chunk);
2532
- const text = decoder.write(chunk);
2533
- let start = 0;
2534
- let end = text.indexOf("\n", start);
2535
- while (end !== -1) {
2536
- fragments.push(text.slice(start, end));
2537
- const record = parseRecord(fragments.join(""), path, lineNumber++, true);
2538
- fragments.length = 0;
2539
- if (record !== void 0) yield record.value;
2540
- start = end + 1;
2541
- end = text.indexOf("\n", start);
2542
- }
2543
- if (start < text.length) fragments.push(text.slice(start));
2544
- }
2545
- if (stream.bytesRead !== size) throw new Error(`${path}: journal changed while reading its committed prefix`);
2546
- fragments.push(decoder.end());
2547
- const record = parseRecord(fragments.join(""), path, lineNumber, false);
2548
- if (record !== void 0) yield record.value;
2549
- } finally {
2550
- stream.destroy();
2551
- }
2552
- } finally {
2553
- await handle.close();
2554
- }
2555
- }
2556
- /** An invalid unterminated tail may be a torn write; other parse failures are not evidence of one. */
2557
- function parseRecord(line, source, lineNumber, terminated) {
2558
- if (line.length === 0) return void 0;
2559
- try {
2560
- return { value: JSON.parse(line) };
2561
- } catch (cause) {
2562
- if (!(cause instanceof SyntaxError)) throw cause;
2563
- if (!terminated) return void 0;
2564
- throw new Error(`${source}: malformed JSONL record at line ${lineNumber}`, { cause });
2565
- }
2566
- }
2567
- /** FileHandle.write may legally make a short write. Loop until every byte is appended. */
2568
- async function writeAllBytes(handle, value) {
2569
- const bytes = typeof value === "string" ? Buffer.from(value) : Buffer.from(value);
2570
- let offset = 0;
2571
- while (offset < bytes.byteLength) {
2572
- const { bytesWritten } = await handle.write(bytes, offset, bytes.byteLength - offset, null);
2573
- if (bytesWritten <= 0) throw new Error(`append-only file write made no progress at byte ${offset}`);
2574
- offset += bytesWritten;
2575
- }
2576
- }
2577
- /** Prepare the tail under the journal owner's existing single-writer discipline.
2578
- * Healthy appends read one byte, regardless of history size. Only recovery scans backward,
2579
- * retaining a valid unterminated value or truncating an uncommitted torn tail. */
2580
- async function prepareJsonlAppend(path) {
2581
- const fs = await import("node:fs/promises");
2582
- let handle;
2583
- try {
2584
- handle = await fs.open(path, "r+");
2585
- } catch (error) {
2586
- if (isNoEntError(error)) return false;
2587
- throw error;
2588
- }
2589
- try {
2590
- const size = (await handle.stat()).size;
2591
- if (size === 0) return false;
2592
- const lastByte = Buffer.allocUnsafe(1);
2593
- await readAt(handle, lastByte, size - 1);
2594
- if (lastByte[0] === 10) return false;
2595
- const chunks = [];
2596
- let end = size;
2597
- let tailStart = 0;
2598
- while (end > 0) {
2599
- const start = Math.max(0, end - 65536);
2600
- const chunk = Buffer.allocUnsafe(end - start);
2601
- await readAt(handle, chunk, start);
2602
- const newline = chunk.lastIndexOf(10);
2603
- chunks.push(chunk.subarray(newline + 1));
2604
- if (newline >= 0) {
2605
- tailStart = start + newline + 1;
2606
- break;
2607
- }
2608
- end = start;
2609
- }
2610
- const tail = Buffer.concat(chunks.reverse()).toString("utf8");
2611
- try {
2612
- JSON.parse(tail);
2613
- return true;
2614
- } catch (error) {
2615
- if (!(error instanceof SyntaxError)) throw error;
2616
- await handle.truncate(tailStart);
2617
- await handle.sync();
2618
- return false;
2619
- }
2620
- } finally {
2621
- await handle.close();
2622
- }
2623
- }
2624
- /** A short read is legal; an unexpected EOF means the owner's snapshot changed. */
2625
- async function readAt(handle, buffer, position) {
2626
- let offset = 0;
2627
- while (offset < buffer.length) {
2628
- const { bytesRead } = await handle.read(buffer, offset, buffer.length - offset, position + offset);
2629
- if (bytesRead === 0) throw new Error("journal changed while preparing its append tail");
2630
- offset += bytesRead;
2631
- }
2632
- }
2633
- /** True for a filesystem error meaning "the file is not there yet" — the one condition an
2634
- * append-only reader treats as an empty log rather than a fault. */
2635
- function isNoEntError(error) {
2636
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
2637
- }
2638
- //#endregion
2639
1910
  //#region src/agent/profile-materialization.ts
2640
1911
  const KNOWN_AXIS_SET = new Set(AGENT_PROFILE_MATERIALIZATION_AXES);
2641
1912
  /**
@@ -7321,6 +6592,49 @@ function normalizeWorkerSlotBound(value) {
7321
6592
  if (!Number.isSafeInteger(value)) throw new ValidationError$1(`workerSlots must be a positive safe integer, or 0 or less for no bound, got ${String(value)}`);
7322
6593
  return value;
7323
6594
  }
6595
+ const checkpointSlotKeys = /* @__PURE__ */ new WeakMap();
6596
+ function checkpointSlots(port) {
6597
+ let key = checkpointSlotKeys.get(port);
6598
+ if (key === void 0) {
6599
+ key = Object.freeze({ maxConcurrentCaptures: port.maxConcurrentCaptures });
6600
+ checkpointSlotKeys.set(port, key);
6601
+ }
6602
+ return key;
6603
+ }
6604
+ /**
6605
+ * Capture a checkpoint through the port on its own queue and bound, then verify that the store
6606
+ * holds every file of the returned tree and, when the checkpoint took a marker, that the tree
6607
+ * holds the marker's exact bytes, which proves it read this checkpoint and no other state.
6608
+ */
6609
+ async function captureProviderCheckpointWorkspace(port, context, marker) {
6610
+ assertProviderWorkspaceRetentionPort(port, "provider workspace retention");
6611
+ const capture = port.captureCheckpoint;
6612
+ if (capture === void 0) throw new ValidationError$1("provider workspace retention: the port has no captureCheckpoint");
6613
+ const controller = new AbortController();
6614
+ const clearDeadline = armDeadlineTimer(port.timeoutMs, () => controller.abort(/* @__PURE__ */ new Error(`checkpoint capture timed out after ${port.timeoutMs}ms`)), true);
6615
+ try {
6616
+ return await runAbortable(() => withCaptureSlot(checkpointSlots(port), controller.signal, async () => {
6617
+ const tree = detachedSnapshot(await capture.call(port, {
6618
+ ...context,
6619
+ signal: controller.signal
6620
+ }), "checkpoint capture tree");
6621
+ if (tree?.kind !== "agent-candidate-workspace-tree") throw new Error("checkpoint capture returned no workspace tree");
6622
+ const material = await verifyAgentCandidateWorkspaceTree(tree, port.artifacts, {
6623
+ ...port.limits === void 0 ? {} : { limits: port.limits },
6624
+ signal: controller.signal
6625
+ });
6626
+ if (material.files.length !== tree.files) throw new Error("checkpoint capture tree misstates its file count");
6627
+ if (marker !== void 0) {
6628
+ const bytes = Buffer.from(marker.content, "utf8");
6629
+ const held = material.files.find((file) => file.path === marker.path);
6630
+ if (held === void 0 || held.byteLength !== bytes.byteLength || held.sha256 !== `sha256:${createHash("sha256").update(bytes).digest("hex")}`) throw new Error(`checkpoint capture does not hold the checkpoint's marker ${marker.path}`);
6631
+ }
6632
+ return tree;
6633
+ }), controller.signal, `checkpoint capture timed out after ${port.timeoutMs}ms`);
6634
+ } finally {
6635
+ clearDeadline();
6636
+ }
6637
+ }
7324
6638
  /** Validate the executable retention port at the create boundary. */
7325
6639
  function assertProviderWorkspaceRetentionPort(port, context) {
7326
6640
  if (!Number.isSafeInteger(port.timeoutMs) || port.timeoutMs <= 0) throw new ValidationError$1(`${context}: workspaceRetention.timeoutMs must be a positive safe integer`);
@@ -7328,6 +6642,7 @@ function assertProviderWorkspaceRetentionPort(port, context) {
7328
6642
  if (port.artifacts === null || typeof port.artifacts?.read !== "function") throw new ValidationError$1(`${context}: workspaceRetention.artifacts.read is required`);
7329
6643
  if (typeof port.capture !== "function") throw new ValidationError$1(`${context}: workspaceRetention.capture is required`);
7330
6644
  if (port.captureNative !== void 0 && typeof port.captureNative !== "function") throw new ValidationError$1(`${context}: workspaceRetention.captureNative must be a function`);
6645
+ if (port.captureCheckpoint !== void 0 && typeof port.captureCheckpoint !== "function") throw new ValidationError$1(`${context}: workspaceRetention.captureCheckpoint must be a function`);
7331
6646
  for (const key of ["nativeIntervalMs", "nativeTimeoutMs"]) {
7332
6647
  const value = port[key];
7333
6648
  if (value !== void 0 && (!Number.isSafeInteger(value) || value <= 0)) throw new ValidationError$1(`${context}: workspaceRetention.${key} must be a positive safe integer`);
@@ -7592,7 +6907,7 @@ async function environmentGone(provider, environmentId, signal) {
7592
6907
  }
7593
6908
  /** Create one environment while retaining ownership if cancellation wins the race. */
7594
6909
  async function createInteractiveEnvironment(create, signal) {
7595
- if (signal?.aborted) throw abortError$2(signal.reason);
6910
+ if (signal?.aborted) throw abortError$1(signal.reason);
7596
6911
  const creation = Promise.resolve().then(create);
7597
6912
  if (signal === void 0) return creation;
7598
6913
  return new Promise((resolve, reject) => {
@@ -7603,7 +6918,7 @@ async function createInteractiveEnvironment(create, signal) {
7603
6918
  owner = "runtime";
7604
6919
  removeAbortListener();
7605
6920
  disposeInteractiveEnvironment(creation, signal.reason);
7606
- reject(abortError$2(signal.reason));
6921
+ reject(abortError$1(signal.reason));
7607
6922
  };
7608
6923
  signal.addEventListener("abort", onAbort, { once: true });
7609
6924
  creation.then((environment) => {
@@ -7623,7 +6938,7 @@ async function createInteractiveEnvironment(create, signal) {
7623
6938
  async function startInteractiveProcess(environment, start, signal) {
7624
6939
  if (signal?.aborted) {
7625
6940
  disposeInteractiveEnvironment(Promise.resolve(environment), signal.reason);
7626
- throw abortError$2(signal.reason);
6941
+ throw abortError$1(signal.reason);
7627
6942
  }
7628
6943
  const pending = Promise.resolve().then(start);
7629
6944
  if (signal === void 0) return pending;
@@ -7635,7 +6950,7 @@ async function startInteractiveProcess(environment, start, signal) {
7635
6950
  owner = "runtime";
7636
6951
  removeAbortListener();
7637
6952
  disposeInteractiveEnvironment(Promise.resolve(environment), signal.reason);
7638
- reject(abortError$2(signal.reason));
6953
+ reject(abortError$1(signal.reason));
7639
6954
  };
7640
6955
  signal.addEventListener("abort", onAbort, { once: true });
7641
6956
  pending.then((result) => {
@@ -7770,7 +7085,7 @@ async function* retainedRunEvents(session, controlRef, options, now) {
7770
7085
  try {
7771
7086
  Promise.resolve(iterator.return?.()).catch(() => void 0);
7772
7087
  } catch {}
7773
- throw abortError$2(options.signal.reason);
7088
+ throw abortError$1(options.signal.reason);
7774
7089
  }
7775
7090
  if (error instanceof RetainedRunProviderContractError) throw error;
7776
7091
  const fromProvider = error instanceof Error && !runtimeChecks.has(error);
@@ -7821,13 +7136,13 @@ function createRetainedRunHandle(environment, session, initialControlRef, capabi
7821
7136
  }
7822
7137
  };
7823
7138
  const snapshot = async (reason, signal) => {
7824
- if (signal?.aborted) throw abortError$2(signal.reason);
7139
+ if (signal?.aborted) throw abortError$1(signal.reason);
7825
7140
  synchronizeActiveControlRef();
7826
7141
  let status;
7827
7142
  try {
7828
7143
  status = await awaitAbortable$1(Promise.resolve().then(() => session.status({ signal })), signal);
7829
7144
  } catch {
7830
- if (signal?.aborted) throw abortError$2(signal.reason);
7145
+ if (signal?.aborted) throw abortError$1(signal.reason);
7831
7146
  status = "unknown";
7832
7147
  }
7833
7148
  synchronizeActiveControlRef();
@@ -8054,7 +7369,7 @@ function createRetainedRunHandle(environment, session, initialControlRef, capabi
8054
7369
  synchronizeActiveControlRef();
8055
7370
  assertStableText(options.operationId, "retained cancellation operation id");
8056
7371
  if (options.reason !== void 0) assertStableText(options.reason, "retained cancellation reason");
8057
- if (options.signal?.aborted) throw abortError$2(options.signal.reason);
7372
+ if (options.signal?.aborted) throw abortError$1(options.signal.reason);
8058
7373
  if (!hasDurableCancel(session)) throw new Error(`provider "${activeControlRef.provider}" does not expose durable cancellation operations`);
8059
7374
  const request = cancellationRequest(activeControlRef, options.operationId, options.reason);
8060
7375
  let effect = "unknown";
@@ -8419,6 +7734,7 @@ async function recoverRetainedRun(options) {
8419
7734
  if (options.admission.provider !== options.provider.name) throw new Error("retained run intent belongs to another provider");
8420
7735
  return {
8421
7736
  outcome: "recovered",
7737
+ via: "resumed",
8422
7738
  handle: await startRetainedRun({
8423
7739
  provider: options.provider,
8424
7740
  ...options.replay,
@@ -8459,6 +7775,7 @@ async function recoverRetainedRun(options) {
8459
7775
  const exact = exactSession(environment, controlRef);
8460
7776
  return {
8461
7777
  outcome: "recovered",
7778
+ via: "reattached",
8462
7779
  handle: createRetainedRunHandle(environment, exact.session, exact.controlRef, capabilities, options.now)
8463
7780
  };
8464
7781
  }
@@ -9571,12 +8888,7 @@ function contentRef$1(prefix, value) {
9571
8888
  } catch {
9572
8889
  str = String(value);
9573
8890
  }
9574
- let h = 2166136261;
9575
- for (let i = 0; i < str.length; i += 1) {
9576
- h ^= str.charCodeAt(i);
9577
- h = Math.imul(h, 16777619);
9578
- }
9579
- return `${prefix}:${(h >>> 0).toString(16).padStart(8, "0")}`;
8891
+ return `${prefix}:${fnv1a32Hex(str)}`;
9580
8892
  }
9581
8893
  //#endregion
9582
8894
  //#region src/runtime/supervise/trace-evidence.ts
@@ -9696,6 +9008,140 @@ function runtimeOwnedNestedDriverTreeRoot(owner, parentTreeRoot, driverNodeId) {
9696
9008
  return nestedDriverTreeOwners.has(owner) ? nestedDriverTreeRoot(parentTreeRoot, driverNodeId) : void 0;
9697
9009
  }
9698
9010
  //#endregion
9011
+ //#region src/durable/jsonl-file.ts
9012
+ /** Read a fixed file prefix one record at a time, never allocating the whole journal as a string.
9013
+ * A reader cannot chase concurrent appends forever. Missing files are empty only when requested;
9014
+ * corruption, short reads, and other I/O errors remain failures. Closing the iterator closes the fd. */
9015
+ async function* readCommittedJsonLines(path, options = {}) {
9016
+ const fs = await import("node:fs/promises");
9017
+ let handle;
9018
+ try {
9019
+ handle = await fs.open(path, "r");
9020
+ } catch (error) {
9021
+ if (options.allowMissing && isNoEntError(error)) return;
9022
+ throw error;
9023
+ }
9024
+ try {
9025
+ const { size } = await handle.stat();
9026
+ if (size === 0) return;
9027
+ const { StringDecoder } = await import("node:string_decoder");
9028
+ const decoder = new StringDecoder("utf8");
9029
+ const stream = handle.createReadStream({
9030
+ autoClose: false,
9031
+ end: size - 1
9032
+ });
9033
+ const fragments = [];
9034
+ let lineNumber = 1;
9035
+ try {
9036
+ for await (const chunk of stream) {
9037
+ options.onBytes?.(chunk);
9038
+ const text = decoder.write(chunk);
9039
+ let start = 0;
9040
+ let end = text.indexOf("\n", start);
9041
+ while (end !== -1) {
9042
+ fragments.push(text.slice(start, end));
9043
+ const record = parseRecord(fragments.join(""), path, lineNumber++, true);
9044
+ fragments.length = 0;
9045
+ if (record !== void 0) yield record.value;
9046
+ start = end + 1;
9047
+ end = text.indexOf("\n", start);
9048
+ }
9049
+ if (start < text.length) fragments.push(text.slice(start));
9050
+ }
9051
+ if (stream.bytesRead !== size) throw new Error(`${path}: journal changed while reading its committed prefix`);
9052
+ fragments.push(decoder.end());
9053
+ const record = parseRecord(fragments.join(""), path, lineNumber, false);
9054
+ if (record !== void 0) yield record.value;
9055
+ } finally {
9056
+ stream.destroy();
9057
+ }
9058
+ } finally {
9059
+ await handle.close();
9060
+ }
9061
+ }
9062
+ /** An invalid unterminated tail may be a torn write; other parse failures are not evidence of one. */
9063
+ function parseRecord(line, source, lineNumber, terminated) {
9064
+ if (line.length === 0) return void 0;
9065
+ try {
9066
+ return { value: JSON.parse(line) };
9067
+ } catch (cause) {
9068
+ if (!(cause instanceof SyntaxError)) throw cause;
9069
+ if (!terminated) return void 0;
9070
+ throw new Error(`${source}: malformed JSONL record at line ${lineNumber}`, { cause });
9071
+ }
9072
+ }
9073
+ /** FileHandle.write may legally make a short write. Loop until every byte is appended. */
9074
+ async function writeAllBytes(handle, value) {
9075
+ const bytes = typeof value === "string" ? Buffer.from(value) : Buffer.from(value);
9076
+ let offset = 0;
9077
+ while (offset < bytes.byteLength) {
9078
+ const { bytesWritten } = await handle.write(bytes, offset, bytes.byteLength - offset, null);
9079
+ if (bytesWritten <= 0) throw new Error(`append-only file write made no progress at byte ${offset}`);
9080
+ offset += bytesWritten;
9081
+ }
9082
+ }
9083
+ /** Prepare the tail under the journal owner's existing single-writer discipline.
9084
+ * Healthy appends read one byte, regardless of history size. Only recovery scans backward,
9085
+ * retaining a valid unterminated value or truncating an uncommitted torn tail. */
9086
+ async function prepareJsonlAppend(path) {
9087
+ const fs = await import("node:fs/promises");
9088
+ let handle;
9089
+ try {
9090
+ handle = await fs.open(path, "r+");
9091
+ } catch (error) {
9092
+ if (isNoEntError(error)) return false;
9093
+ throw error;
9094
+ }
9095
+ try {
9096
+ const size = (await handle.stat()).size;
9097
+ if (size === 0) return false;
9098
+ const lastByte = Buffer.allocUnsafe(1);
9099
+ await readAt(handle, lastByte, size - 1);
9100
+ if (lastByte[0] === 10) return false;
9101
+ const chunks = [];
9102
+ let end = size;
9103
+ let tailStart = 0;
9104
+ while (end > 0) {
9105
+ const start = Math.max(0, end - 65536);
9106
+ const chunk = Buffer.allocUnsafe(end - start);
9107
+ await readAt(handle, chunk, start);
9108
+ const newline = chunk.lastIndexOf(10);
9109
+ chunks.push(chunk.subarray(newline + 1));
9110
+ if (newline >= 0) {
9111
+ tailStart = start + newline + 1;
9112
+ break;
9113
+ }
9114
+ end = start;
9115
+ }
9116
+ const tail = Buffer.concat(chunks.reverse()).toString("utf8");
9117
+ try {
9118
+ JSON.parse(tail);
9119
+ return true;
9120
+ } catch (error) {
9121
+ if (!(error instanceof SyntaxError)) throw error;
9122
+ await handle.truncate(tailStart);
9123
+ await handle.sync();
9124
+ return false;
9125
+ }
9126
+ } finally {
9127
+ await handle.close();
9128
+ }
9129
+ }
9130
+ /** A short read is legal; an unexpected EOF means the owner's snapshot changed. */
9131
+ async function readAt(handle, buffer, position) {
9132
+ let offset = 0;
9133
+ while (offset < buffer.length) {
9134
+ const { bytesRead } = await handle.read(buffer, offset, buffer.length - offset, position + offset);
9135
+ if (bytesRead === 0) throw new Error("journal changed while preparing its append tail");
9136
+ offset += bytesRead;
9137
+ }
9138
+ }
9139
+ /** True for a filesystem error meaning "the file is not there yet" — the one condition an
9140
+ * append-only reader treats as an empty log rather than a fault. */
9141
+ function isNoEntError(error) {
9142
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
9143
+ }
9144
+ //#endregion
9699
9145
  //#region src/durable/spawn-journal.ts
9700
9146
  /**
9701
9147
  * Mint the content-addressed `outRef` for a result artifact: `sha256:<hex>` over a
@@ -10341,17 +9787,15 @@ var SpawnEventIndex = class {
10341
9787
  }
10342
9788
  };
10343
9789
  /**
10344
- * The records that CLOSE a node's cursor slot: a settlement, a cancellation, or a wait being
10345
- * woken. The complement question to {@link outsideCursorNamespace}, and the one a resume needs —
9790
+ * The records that CLOSE a node's cursor slot: a settlement or a cancellation. The complement question to {@link outsideCursorNamespace}, and the one a resume needs —
10346
9791
  * a kind missing here leaves a finished node looking live, so its budget is never reclaimed and
10347
9792
  * its reservation is replayed as still in doubt.
10348
9793
  */
10349
9794
  function closesCursorSlot(ev) {
10350
- return ev.kind === "settled" || ev.kind === "cancelled" || ev.kind === "woken";
9795
+ return ev.kind === "settled" || ev.kind === "cancelled";
10351
9796
  }
10352
9797
  const outsideKinds = /* @__PURE__ */ new Set([
10353
9798
  "spawned",
10354
- "waiting",
10355
9799
  "metered",
10356
9800
  "materialized",
10357
9801
  "execution-bound",
@@ -10368,6 +9812,9 @@ const outsideKinds = /* @__PURE__ */ new Set([
10368
9812
  "environment-teardown",
10369
9813
  "workspace-checkpoint-requested",
10370
9814
  "workspace-checkpoint",
9815
+ "workspace-checkpoint-fork-requested",
9816
+ "workspace-checkpoint-fork-teardown",
9817
+ "workspace-checkpoint-capture",
10371
9818
  "workspace-checkpoint-cleanup",
10372
9819
  "workspace-restored",
10373
9820
  "workspace-capture",
@@ -10409,7 +9856,7 @@ async function replaySpawnTree(journal, blobs, root) {
10409
9856
  const materializations = /* @__PURE__ */ new Map();
10410
9857
  const executionBindings = /* @__PURE__ */ new Map();
10411
9858
  for (const ev of ordered) {
10412
- if (ev.kind === "spawned" || ev.kind === "waiting") labels.set(ev.id, ev.label);
9859
+ if (ev.kind === "spawned") labels.set(ev.id, ev.label);
10413
9860
  if (ev.kind === "spawned" && ev.assignmentId !== void 0) assignmentIds.set(ev.id, ev.assignmentId);
10414
9861
  if (ev.kind === "spawned" && ev.identity !== void 0) identities.set(ev.id, copyFrozenIdentity(ev.identity));
10415
9862
  if (ev.kind === "materialized") materializations.set(ev.id, ev.receipt);
@@ -10432,7 +9879,6 @@ async function replaySpawnTree(journal, blobs, root) {
10432
9879
  const settled = [];
10433
9880
  for (const ev of ordered) {
10434
9881
  if (ev.kind === "spawned") continue;
10435
- if (ev.kind === "waiting") continue;
10436
9882
  if (ev.kind === "metered") continue;
10437
9883
  if (ev.kind === "progress") continue;
10438
9884
  if (ev.kind === "reconciled") continue;
@@ -10445,6 +9891,9 @@ async function replaySpawnTree(journal, blobs, root) {
10445
9891
  if (ev.kind === "environment-teardown") continue;
10446
9892
  if (ev.kind === "workspace-checkpoint-requested") continue;
10447
9893
  if (ev.kind === "workspace-checkpoint") continue;
9894
+ if (ev.kind === "workspace-checkpoint-fork-requested") continue;
9895
+ if (ev.kind === "workspace-checkpoint-fork-teardown") continue;
9896
+ if (ev.kind === "workspace-checkpoint-capture") continue;
10448
9897
  if (ev.kind === "workspace-checkpoint-cleanup") continue;
10449
9898
  if (ev.kind === "workspace-restored") continue;
10450
9899
  if (ev.kind === "workspace-capture") continue;
@@ -10454,39 +9903,6 @@ async function replaySpawnTree(journal, blobs, root) {
10454
9903
  if (ev.kind === "node-inputs-resolved") continue;
10455
9904
  if (ev.kind === "edge-verdict") continue;
10456
9905
  if (ev.kind === "join-state") continue;
10457
- if (ev.kind === "woken") {
10458
- if (ev.by === "cancelled" || ev.outRef === void 0) {
10459
- settled.push({
10460
- kind: "down",
10461
- handle: handleFor(ev.id, "cancelled"),
10462
- reason: "wait cancelled",
10463
- infra: false,
10464
- trace: {
10465
- status: "unavailable",
10466
- reason: "not-an-executor"
10467
- },
10468
- ...settlementTime(ev.at),
10469
- seq: ev.seq
10470
- });
10471
- continue;
10472
- }
10473
- const outcome = await blobs.get(ev.outRef);
10474
- if (outcome === void 0) throw new Error(`replaySpawnTree: blob store has no wait outcome for outRef '${ev.outRef}' (node '${ev.id}', seq ${ev.seq})`);
10475
- settled.push({
10476
- kind: "done",
10477
- handle: handleFor(ev.id, "done"),
10478
- out: outcome,
10479
- outRef: ev.outRef,
10480
- spent: zeroSpend(),
10481
- trace: {
10482
- status: "unavailable",
10483
- reason: "not-an-executor"
10484
- },
10485
- ...settlementTime(ev.at),
10486
- seq: ev.seq
10487
- });
10488
- continue;
10489
- }
10490
9906
  if (ev.kind === "cancelled") {
10491
9907
  settled.push({
10492
9908
  kind: "down",
@@ -10586,24 +10002,9 @@ function copyFrozenIdentity(identity) {
10586
10002
  function materializeTreeView(events) {
10587
10003
  const nodes = /* @__PURE__ */ new Map();
10588
10004
  let root;
10589
- const spawns = events.filter((ev) => ev.kind === "spawned" || ev.kind === "waiting").sort((a, b) => a.seq - b.seq);
10005
+ const spawns = events.filter((ev) => ev.kind === "spawned").sort((a, b) => a.seq - b.seq);
10590
10006
  const settlements = events.filter((ev) => insideCursorNamespace(ev)).sort((a, b) => a.seq - b.seq);
10591
10007
  for (const ev of spawns) {
10592
- if (ev.kind === "waiting") {
10593
- nodes.set(ev.id, {
10594
- id: ev.id,
10595
- parent: ev.parent,
10596
- label: ev.label,
10597
- status: "waiting",
10598
- runtime: "wait",
10599
- budget: {
10600
- maxIterations: 0,
10601
- maxTokens: 0
10602
- },
10603
- spent: zeroSpend()
10604
- });
10605
- continue;
10606
- }
10607
10008
  if (ev.parent === void 0 && root === void 0) root = ev.id;
10608
10009
  nodes.set(ev.id, {
10609
10010
  id: ev.id,
@@ -10631,16 +10032,6 @@ function materializeTreeView(events) {
10631
10032
  if (ev.retainedPendingCause !== void 0) node.retainedPendingCause = ev.retainedPendingCause;
10632
10033
  const settledAt = Date.parse(ev.at);
10633
10034
  if (Number.isFinite(settledAt)) node.settledAt = settledAt;
10634
- } else if (ev.kind === "woken") {
10635
- const node = requireNode(nodes, ev.id);
10636
- node.status = ev.by === "cancelled" ? "cancelled" : "done";
10637
- node.outRef = ev.outRef;
10638
- node.trace = {
10639
- status: "unavailable",
10640
- reason: "not-an-executor"
10641
- };
10642
- const settledAt = Date.parse(ev.at);
10643
- if (Number.isFinite(settledAt)) node.settledAt = settledAt;
10644
10035
  } else {
10645
10036
  const node = requireNode(nodes, ev.id);
10646
10037
  node.status = "cancelled";
@@ -10682,31 +10073,9 @@ function materializeTreeView(events) {
10682
10073
  return {
10683
10074
  root: root ?? snapshots[0]?.id ?? "",
10684
10075
  nodes: snapshots,
10685
- inFlight: snapshots.filter((n) => n.status === "running" || n.status === "acquiring").length,
10686
- waiting: snapshots.filter((n) => n.status === "waiting").length
10076
+ inFlight: snapshots.filter((n) => n.status === "running" || n.status === "acquiring").length
10687
10077
  };
10688
10078
  }
10689
- /**
10690
- * The waits a journaled tree shows as ARMED but never woken — what a resumed run re-arms with the
10691
- * ORIGINAL absolute deadline. Reading it from the journal (rather than from any live state) is
10692
- * what makes "SIGKILL a waiting tree, a new process keeps waiting to the same instant" true.
10693
- */
10694
- function pendingWaits(events) {
10695
- const woken = /* @__PURE__ */ new Set();
10696
- for (const ev of events) if (ev.kind === "woken") woken.add(ev.id);
10697
- const pending = [];
10698
- for (const ev of events) {
10699
- if (ev.kind !== "waiting" || woken.has(ev.id)) continue;
10700
- pending.push({
10701
- id: ev.id,
10702
- label: ev.label,
10703
- spec: ev.spec,
10704
- armedAt: ev.armedAt,
10705
- ordinal: ev.seq
10706
- });
10707
- }
10708
- return pending.sort((a, b) => a.ordinal - b.ordinal);
10709
- }
10710
10079
  /** Copy a terminal record's overspend at the journal boundary; absent stays absent. */
10711
10080
  function budgetViolationOf(event) {
10712
10081
  if (event.budgetViolation === void 0) return {};
@@ -11234,6 +10603,9 @@ function jitteredMs(ms, random) {
11234
10603
  const WORKSPACE_CHECKPOINT_MARKER_PATH = ".agent-runtime-checkpoint";
11235
10604
  /** Bound on one checkpoint: environment lookup, marker write, and the provider operation. */
11236
10605
  const WORKSPACE_CHECKPOINT_TIMEOUT_MS = 12e4;
10606
+ /** Bound on creating and reconstructing the fork a checkpoint's capture reads: a Sandbox box
10607
+ * created from a snapshot (measured 2026-09-24: 19 s). The capture itself is bounded by its port. */
10608
+ const WORKSPACE_CHECKPOINT_FORK_TIMEOUT_MS = 10 * 6e4;
11237
10609
  /** Write the marker. False when the environment cannot take it, so no restore can be verified. */
11238
10610
  async function writeWorkspaceMarker(environment, marker, signal) {
11239
10611
  if (typeof environment.write !== "function") return false;
@@ -14606,34 +13978,6 @@ function buildBackendOptions(profile, overrides) {
14606
13978
  };
14607
13979
  }
14608
13980
  //#endregion
14609
- //#region src/runtime/sandbox-capabilities.ts
14610
- const probeCache = /* @__PURE__ */ new WeakMap();
14611
- /**
14612
- * Probe (and memoize per client) what the loop may rely on. A client without a
14613
- * `criuStatus` method, or whose probe rejects, yields `canFork = false` — a
14614
- * failed probe must never claim a capability the platform may not have. The
14615
- * promise is cached so concurrent fanout branches share one round-trip.
14616
- *
14617
- * @experimental
14618
- */
14619
- function probeSandboxCapabilities(client) {
14620
- const key = client;
14621
- const cached = probeCache.get(key);
14622
- if (cached) return cached;
14623
- const probe = resolveCapabilities(client);
14624
- probeCache.set(key, probe);
14625
- return probe;
14626
- }
14627
- async function resolveCapabilities(client) {
14628
- const criuStatus = client.criuStatus;
14629
- if (typeof criuStatus !== "function") return { canFork: false };
14630
- try {
14631
- return { canFork: (await criuStatus.call(client))?.available === true };
14632
- } catch {
14633
- return { canFork: false };
14634
- }
14635
- }
14636
- //#endregion
14637
13981
  //#region src/runtime/sandbox-lineage.ts
14638
13982
  const TEARDOWN_TIMEOUT_MS$1 = 15e3;
14639
13983
  const DEFAULT_FORK_CONCURRENCY = 4;
@@ -14699,13 +14043,11 @@ function promptEvents(streaming, box, prompt, sessionId, signal, promptOptions)
14699
14043
  });
14700
14044
  }
14701
14045
  /**
14702
- * Build a lineage bound to one client + its probed capabilities. The
14703
- * capabilities are passed in (not re-probed) so the kernel probes once per run
14704
- * and the lineage stays a pure function of "what this platform can do".
14046
+ * Build a lineage bound to one client. Branching is read from each box.
14705
14047
  *
14706
14048
  * @experimental
14707
14049
  */
14708
- function createSandboxLineage(client, capabilities, options = {}) {
14050
+ function createSandboxLineage(client, options = {}) {
14709
14051
  if (!client || typeof client.create !== "function") throw new ValidationError$1("createSandboxLineage: client.create is required");
14710
14052
  const streaming = options.streaming ?? "sse";
14711
14053
  const recordMount = options.recordMount ?? (() => {});
@@ -14795,30 +14137,10 @@ function createSandboxLineage(client, capabilities, options = {}) {
14795
14137
  };
14796
14138
  });
14797
14139
  }
14798
- const checkpointId = capabilities.canFork ? await checkpointForFork(parent.box, signal) : void 0;
14799
14140
  return mapWithConcurrency(prompts, forkConcurrency, async (prompt, i) => {
14800
14141
  throwIfAborted(signal);
14801
14142
  const spec = specs[i % specs.length];
14802
14143
  if (!spec) throw new ValidationError$1("SandboxLineage.fork: no AgentRunSpec for branch");
14803
- if (checkpointId !== void 0) {
14804
- const box = await forkFromCheckpoint(parent.box, checkpointId, signal);
14805
- owned.push(box);
14806
- const inheritedProfile = profiles.get(parent.box) ?? spec.profile;
14807
- profiles.set(box, inheritedProfile);
14808
- options.onAcquire?.(box, inheritedProfile);
14809
- await spec.prepareBox?.(box, {
14810
- signal,
14811
- recordMount
14812
- });
14813
- const sessionId = mintSessionId();
14814
- return {
14815
- handle: {
14816
- box,
14817
- sessionId
14818
- },
14819
- events: promptEvents(streaming, box, prompt, sessionId, signal, optionsFor(i))
14820
- };
14821
- }
14822
14144
  const box = await acquireFresh(spec, signal);
14823
14145
  const sessionId = mintSessionId();
14824
14146
  return {
@@ -14858,8 +14180,8 @@ function mintSessionId() {
14858
14180
  }
14859
14181
  /**
14860
14182
  * Branch a running parent through the current Sandbox SDK, in bounded waves.
14861
- * `undefined` means the box exposes only the legacy checkpoint API (or no
14862
- * branching API), so the caller may try the legacy capability-gated path.
14183
+ * `undefined` means the box exposes no branching API, so the caller starts
14184
+ * fresh boxes.
14863
14185
  */
14864
14186
  async function branchParent(box, count, concurrency, signal) {
14865
14187
  const branch = box.branch;
@@ -14880,34 +14202,6 @@ async function branchParent(box, count, concurrency, signal) {
14880
14202
  }
14881
14203
  }
14882
14204
  /**
14883
- * Checkpoint the parent leaving it running, returning the checkpoint id to fork
14884
- * from, or `undefined` when the box exposes no legacy `checkpoint` method or
14885
- * the call produced no id. `undefined` makes the caller use fresh boxes — a
14886
- * fork that cannot preserve context must not pretend to share it.
14887
- */
14888
- async function checkpointForFork(box, signal) {
14889
- const checkpoint = box.checkpoint;
14890
- if (typeof checkpoint !== "function") return void 0;
14891
- if (signal.aborted) throwAbort();
14892
- const id = (await checkpoint.call(box, { leaveRunning: true }))?.checkpointId;
14893
- return typeof id === "string" && id.length > 0 ? id : void 0;
14894
- }
14895
- /**
14896
- * Fork a child box from `checkpointId`. The box exposes `fork` whenever the
14897
- * platform advertised `canFork`; a missing `fork` here is a contract violation
14898
- * (probe said yes, box says no) and fails loud rather than silently degrading.
14899
- *
14900
- * `signal` gates entry only: the legacy SDK's `fork(checkpointId, options)`
14901
- * takes no abort signal, so an in-flight fork cannot be interrupted. The
14902
- * caller checks abort per branch, so cancellation is responsive at boundaries.
14903
- */
14904
- async function forkFromCheckpoint(box, checkpointId, signal) {
14905
- const fork = box.fork;
14906
- if (typeof fork !== "function") throw new ValidationError$1("SandboxLineage.fork: capabilities report canFork but the box has no fork() method");
14907
- if (signal.aborted) throwAbort();
14908
- return fork.call(box, checkpointId);
14909
- }
14910
- /**
14911
14205
  * Fail loud when a handle's session is no longer known to the sandbox. The real
14912
14206
  * SDK box exposes `session(id).status()` which resolves `null` for an unknown /
14913
14207
  * reaped id; a `null` here means a `continue` would run WITHOUT the prior
@@ -15151,9 +14445,8 @@ async function setUpLineage(options, maxConcurrency, recordMount, promptOptions,
15151
14445
  const lineageOpts = options.lineage;
15152
14446
  if (!lineageOpts || !lineageOpts.sessionContinuity && !lineageOpts.forkFanout) return void 0;
15153
14447
  if (options.onWorkerBox) throw new ValidationError$1("runAgentRounds: `lineage` and `onWorkerBox` both own worker boxes — pass only one");
15154
- const capabilities = await probeSandboxCapabilities(options.ctx.sandboxClient);
15155
14448
  return {
15156
- lineage: createSandboxLineage(options.ctx.sandboxClient, capabilities, {
14449
+ lineage: createSandboxLineage(options.ctx.sandboxClient, {
15157
14450
  maxConcurrency,
15158
14451
  streaming: lineageOpts.streaming,
15159
14452
  recordMount,
@@ -15798,12 +15091,7 @@ function hashJson(value) {
15798
15091
  } catch {
15799
15092
  str = String(value);
15800
15093
  }
15801
- let h = 2166136261;
15802
- for (let i = 0; i < str.length; i += 1) {
15803
- h ^= str.charCodeAt(i);
15804
- h = Math.imul(h, 16777619);
15805
- }
15806
- return (h >>> 0).toString(16).padStart(8, "0");
15094
+ return fnv1a32Hex(str);
15807
15095
  }
15808
15096
  //#endregion
15809
15097
  //#region src/runtime/sandbox-executor-output.ts
@@ -17308,9 +16596,6 @@ async function cancelBridgeRunToTerminal(seam, run, grace, stopSignal) {
17308
16596
  await new Promise((resolve) => setTimeout(resolve, 10));
17309
16597
  }
17310
16598
  }
17311
- function errorMessage(error) {
17312
- return error instanceof Error ? error.message : String(error);
17313
- }
17314
16599
  /** Read only the Router-owned one-sided field from an error body. */
17315
16600
  function providerDispatchFromErrorBody(body) {
17316
16601
  let parsed;
@@ -17326,13 +16611,7 @@ function providerDispatchFromErrorBody(body) {
17326
16611
  }
17327
16612
  //#endregion
17328
16613
  //#region src/runtime/supervise/node-status.ts
17329
- /**
17330
- * Which {@link NodeStatus} values mean the node is finished.
17331
- *
17332
- * `'waiting'` is deliberately NOT terminal: a wait-state node holds no executor, no box and no
17333
- * conserved budget, so it is neither in flight nor settled. Callers that must also exclude it say
17334
- * so at their own site, because "finished" and "not a live worker" are different questions.
17335
- */
16614
+ /** Which {@link NodeStatus} values mean the node is finished. */
17336
16615
  const terminalNodeStatuses = /* @__PURE__ */ new Set([
17337
16616
  "done",
17338
16617
  "failed",
@@ -19309,8 +18588,7 @@ function createSteerableSandboxSession(args) {
19309
18588
  let preservationFailure;
19310
18589
  let preservationError;
19311
18590
  let executionFailure;
19312
- const capabilities = await probeSandboxCapabilities(args.sandboxClient);
19313
- const lineage = createSandboxLineage(args.sandboxClient, capabilities, {
18591
+ const lineage = createSandboxLineage(args.sandboxClient, {
19314
18592
  maxConcurrency: 1,
19315
18593
  failOnDestroyError: args.failOnDestroyError
19316
18594
  });
@@ -21061,9 +20339,6 @@ function bridgeOutputText(out) {
21061
20339
  return String(out);
21062
20340
  }
21063
20341
  }
21064
- function isAsyncIterable$1(value) {
21065
- return value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
21066
- }
21067
20342
  /**
21068
20343
  * The leaf `createWorktreeCliExecutor` as a backend-as-data factory: a supervisor-authored
21069
20344
  * `AgentProfile` driving claude / codex / opencode on its own worktree. `budgetExempt` like
@@ -21875,7 +21150,13 @@ async function startRetainedInteractiveRun(options) {
21875
21150
  });
21876
21151
  return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
21877
21152
  }
21878
- /** Retry one exact start after its provider response may have been lost. @stable */
21153
+ /**
21154
+ * Retry one exact start after its provider response may have been lost.
21155
+ *
21156
+ * Resolves to the handle of the admitted process (resumed through the exact,
21157
+ * idempotent start request), or `null` when the provider no longer holds the
21158
+ * environment (not found; nothing remains to stop). @stable
21159
+ */
21879
21160
  async function recoverRetainedInteractiveRun(options) {
21880
21161
  options.signal?.throwIfAborted();
21881
21162
  if (typeof options.onAdmission !== "function") throw new Error("recoverRetainedInteractiveRun requires an awaited onAdmission durability hook");
@@ -22307,27 +21588,6 @@ function workerInteractiveAdmissionFile(eventDir, workerId, phase) {
22307
21588
  assertNoSymlinkDescendant(eventDir, dir, "interactive admission");
22308
21589
  return join(dir, `${canonicalCandidateDigest({ workerId: id }).slice(7).slice(0, 32)}.${phase}.admission.json`);
22309
21590
  }
22310
- /** Read all durable admissions for one worker, oldest phase first. */
22311
- function readWorkerInteractiveAdmissions(eventDir, workerId) {
22312
- const phases = [
22313
- "interactive_intent",
22314
- "interactive_environment",
22315
- "interactive_started"
22316
- ];
22317
- const admissions = [];
22318
- let missingPhase = false;
22319
- for (const phase of phases) {
22320
- const file = workerInteractiveAdmissionFile(eventDir, workerId, phase);
22321
- if (!existsSync(file)) {
22322
- missingPhase = true;
22323
- continue;
22324
- }
22325
- if (missingPhase) throw new Error(`interactive admission phase '${phase}' exists after a missing earlier phase`);
22326
- const parsed = JSON.parse(readFileSync(file, "utf8"));
22327
- admissions.push(parseAdmission(parsed, workerId, phase));
22328
- }
22329
- return admissions;
22330
- }
22331
21591
  /**
22332
21592
  * Persist one retained-interactive admission without retaining sensitive start material.
22333
21593
  *
@@ -22986,8 +22246,6 @@ async function prepareScopeResume(opts, events, signal, now, parentId = opts.run
22986
22246
  view: materializeTreeView(prior),
22987
22247
  maxSpawnOrdinal: maxSeqOf(prior, (event) => event.kind === "spawned"),
22988
22248
  maxCursorSeq: reservedCursorFloor(prior),
22989
- maxWaitOrdinal: maxSeqOf(prior, (event) => event.kind === "waiting"),
22990
- waits: pendingWaits(prior),
22991
22249
  keys: keyedAssignments(prior, settled),
22992
22250
  priorSpend: sumMeasuredSpendFromEvents(prior)
22993
22251
  }
@@ -23424,10 +22682,16 @@ function registerScopeRetainedOwner(scope, args) {
23424
22682
  function scopeRetainedOwnerContext(scope) {
23425
22683
  return owners.get(scope)?.context;
23426
22684
  }
23427
- /** Bind cleanup before replay can return an already accepted owner result. */
23428
- function bindScopeRetainedOwnerProvider(scope, provider) {
22685
+ /**
22686
+ * Bind cleanup before replay can return an already accepted owner result. `checkpointCapture` is
22687
+ * where each checkpoint's files are stored before the checkpoint is deleted; without it, no
22688
+ * checkpoint of this owner is deleted.
22689
+ */
22690
+ function bindScopeRetainedOwnerProvider(scope, provider, checkpointCapture) {
23429
22691
  const state = owners.get(scope);
23430
- if (state) state.provider = provider;
22692
+ if (state === void 0) return;
22693
+ state.provider = provider;
22694
+ if (checkpointCapture !== void 0) state.checkpointCapture = checkpointCapture;
23431
22695
  }
23432
22696
  /** Bind the owner cleanup policy selected by its provider executor. */
23433
22697
  function bindScopeRetainedOwnerWorkspaceRetention(scope, enabled) {
@@ -23602,7 +22866,8 @@ async function checkpointOwnerWorkspace(scope, state) {
23602
22866
  seq: state.nextSequence(),
23603
22867
  at
23604
22868
  });
23605
- await deleteCheckpoints(state, branching, pendingCheckpoints(await args.journal.loadTree(args.rootId) ?? [], state).filter((event) => event.environmentId === environment.id).slice(0, -2), signal);
22869
+ const events = await args.journal.loadTree(args.rootId) ?? [];
22870
+ await cleanCheckpoints(state, branching, pendingCheckpoints(events, state).filter((event) => event.environmentId === environment.id && state.captureRefused?.has(event.checkpoint.checkpointId) !== true).slice(0, -2), events, scope.signal);
23606
22871
  }
23607
22872
  /** Reconstruct authority for this source only; a replacement cannot own its snapshots. */
23608
22873
  async function checkpointHandle(state, sourceEnvironmentId, signal) {
@@ -23695,10 +22960,35 @@ function pendingCheckpoints(events, state) {
23695
22960
  const confirmed = new Set(events.flatMap((event) => event.kind === "workspace-checkpoint-cleanup" && event.id === state.args.nodeId && event.provider === state.provider?.name && event.confirmed ? [JSON.stringify([event.environmentId, event.checkpointId])] : []));
23696
22961
  return events.filter((event) => event.kind === "workspace-checkpoint" && event.id === state.args.nodeId && event.provider === state.provider?.name && !confirmed.has(JSON.stringify([event.environmentId, event.checkpoint.checkpointId])));
23697
22962
  }
23698
- /** Only the source-scoped handle can attest deletion, including after its source is lost. */
23699
- async function deleteCheckpoints(state, branching, checkpoints, signal) {
22963
+ /**
22964
+ * Delete checkpoints, each only after its files are captured into the run's content-addressed
22965
+ * store; a checkpoint no capture holds is kept, and the cleanup record says why. Only the
22966
+ * source-scoped handle can fork a checkpoint and attest its deletion, including after its source
22967
+ * is lost. `parent` cancels the captures (the owner's scope during rotation); each provider
22968
+ * operation also has its own bound.
22969
+ */
22970
+ async function cleanCheckpoints(state, branching, checkpoints, events, parent) {
23700
22971
  const unconfirmed = [];
22972
+ const refused = [];
23701
22973
  for (const event of checkpoints) {
22974
+ const captured = await captureBeforeCleanup(state, branching, event, events, parent);
22975
+ if ("reason" in captured) {
22976
+ (state.captureRefused ??= /* @__PURE__ */ new Set()).add(event.checkpoint.checkpointId);
22977
+ refused.push(captured);
22978
+ await state.args.journal.appendEvent(state.args.rootId, {
22979
+ kind: "workspace-checkpoint-cleanup",
22980
+ id: state.args.nodeId,
22981
+ provider: event.provider,
22982
+ environmentId: event.environmentId,
22983
+ checkpointId: event.checkpoint.checkpointId,
22984
+ confirmed: false,
22985
+ refused: captured.reason.slice(0, 1e3),
22986
+ seq: state.nextSequence(),
22987
+ at: new Date(state.args.now()).toISOString()
22988
+ });
22989
+ continue;
22990
+ }
22991
+ state.captureRefused?.delete(event.checkpoint.checkpointId);
23702
22992
  const material = {
23703
22993
  kind: "checkpoint",
23704
22994
  targetId: event.checkpoint.checkpointId,
@@ -23712,6 +23002,7 @@ async function deleteCheckpoints(state, branching, checkpoints, signal) {
23712
23002
  let confirmed = false;
23713
23003
  try {
23714
23004
  if (branching === void 0) throw new Error("source-scoped checkpoint handle unavailable");
23005
+ const signal = AbortSignal.timeout(3e4);
23715
23006
  const acknowledgement = await runAbortable(() => branching.deleteCheckpoint(request, { signal }), signal, "retained owner checkpoint cleanup timed out");
23716
23007
  confirmed = workspaceCleanupAcknowledgementMatches(request, acknowledgement) && (acknowledgement.status === "deleted" || acknowledgement.status === "already_absent");
23717
23008
  } catch {}
@@ -23723,11 +23014,178 @@ async function deleteCheckpoints(state, branching, checkpoints, signal) {
23723
23014
  environmentId: event.environmentId,
23724
23015
  checkpointId: event.checkpoint.checkpointId,
23725
23016
  confirmed,
23017
+ capturedDigest: captured.digest,
23726
23018
  seq: state.nextSequence(),
23727
23019
  at: new Date(state.args.now()).toISOString()
23728
23020
  });
23729
23021
  }
23730
- return unconfirmed;
23022
+ return {
23023
+ unconfirmed,
23024
+ refused
23025
+ };
23026
+ }
23027
+ /**
23028
+ * The digest of the tree that holds a checkpoint's files, capturing it first when no record says
23029
+ * one exists, or why it cannot be had. The files are read from a fork of the checkpoint: a box
23030
+ * created from the snapshot itself, so the capture is the checkpoint's state and not the live
23031
+ * workspace's, which has moved on. The fork request is journaled before it is made and the fork
23032
+ * destroyed once the capture is journaled, so neither a failure nor a crash leaves it running
23033
+ * unrecorded.
23034
+ */
23035
+ async function captureBeforeCleanup(state, branching, event, events, parent) {
23036
+ const { args } = state;
23037
+ const checkpointId = event.checkpoint.checkpointId;
23038
+ const recorded = events.find((prior) => prior.kind === "workspace-checkpoint-capture" && prior.id === args.nodeId && prior.provider === event.provider && prior.environmentId === event.environmentId && prior.checkpointId === checkpointId);
23039
+ if (recorded !== void 0) return { digest: recorded.tree.digest };
23040
+ const refuse = (reason, needsSource) => ({
23041
+ event,
23042
+ reason,
23043
+ needsSource
23044
+ });
23045
+ const capture = state.checkpointCapture;
23046
+ if (capture?.port.captureCheckpoint === void 0) return refuse("no checkpoint capture: the owner backend has no captureCheckpoint", false);
23047
+ const provider = state.provider;
23048
+ if (provider?.get === void 0) return refuse("the provider cannot reconstruct a fork of the checkpoint", false);
23049
+ if (branching === void 0) return refuse("source-scoped checkpoint handle unavailable", true);
23050
+ const material = {
23051
+ checkpoint: event.checkpoint,
23052
+ placement: { kind: "sandbox" }
23053
+ };
23054
+ const request = {
23055
+ ...material,
23056
+ idempotencyKey: `${event.checkpoint.idempotencyKey}:capture:${state.nextSequence()}`,
23057
+ requestDigest: workspaceForkRequestDigest(material)
23058
+ };
23059
+ const forkSignal = AbortSignal.any([...parent === void 0 ? [] : [parent], AbortSignal.timeout(WORKSPACE_CHECKPOINT_FORK_TIMEOUT_MS)]);
23060
+ let forkEnvironmentId;
23061
+ try {
23062
+ await args.journal.appendEvent(args.rootId, {
23063
+ kind: "workspace-checkpoint-fork-requested",
23064
+ id: args.nodeId,
23065
+ provider: event.provider,
23066
+ environmentId: event.environmentId,
23067
+ checkpointId,
23068
+ idempotencyKey: request.idempotencyKey,
23069
+ requestDigest: request.requestDigest,
23070
+ seq: state.nextSequence(),
23071
+ at: new Date(args.now()).toISOString()
23072
+ });
23073
+ const result = await runAbortable(() => branching.fork(request, { signal: forkSignal }), forkSignal, "checkpoint fork timed out");
23074
+ if (result.status === "created" || result.status === "replayed") forkEnvironmentId = result.environment.environmentId;
23075
+ if (result.status !== "created" && result.status !== "replayed" || !workspaceForkResultMatchesRequest(request, result)) return refuse(`fork ${result.status}${"message" in result ? `: ${result.message}` : ""}`, true);
23076
+ const forkId = result.environment.environmentId;
23077
+ const get = provider.get.bind(provider);
23078
+ const environment = await runAbortable(() => get(forkId), forkSignal, "checkpoint fork lookup timed out");
23079
+ if (environment === null || environment.id !== forkId || environment.provider !== provider.name) return refuse(`fork ${forkId} could not be reconstructed`, true);
23080
+ parent?.throwIfAborted();
23081
+ const tree = await captureProviderCheckpointWorkspace(capture.port, {
23082
+ environment,
23083
+ checkpoint: event.checkpoint,
23084
+ executionId: `${args.nodeId}:checkpoint:${checkpointId}`,
23085
+ profile: capture.profile
23086
+ }, event.marker);
23087
+ await args.journal.appendEvent(args.rootId, {
23088
+ kind: "workspace-checkpoint-capture",
23089
+ id: args.nodeId,
23090
+ provider: event.provider,
23091
+ environmentId: event.environmentId,
23092
+ checkpointId,
23093
+ fork: {
23094
+ idempotencyKey: request.idempotencyKey,
23095
+ environmentId: forkId
23096
+ },
23097
+ tree: {
23098
+ digest: tree.digest,
23099
+ manifest: tree.manifest,
23100
+ files: tree.files,
23101
+ bytes: tree.bytes,
23102
+ storedBytes: tree.storedBytes
23103
+ },
23104
+ seq: state.nextSequence(),
23105
+ at: new Date(args.now()).toISOString()
23106
+ });
23107
+ return { digest: tree.digest };
23108
+ } catch (error) {
23109
+ return refuse(`capture failed: ${errorText(error instanceof Error ? error.message : error)}`, true);
23110
+ } finally {
23111
+ if (forkEnvironmentId !== void 0) await destroyCaptureFork(state, branching, {
23112
+ provider: event.provider,
23113
+ environmentId: event.environmentId,
23114
+ checkpointId,
23115
+ fork: {
23116
+ idempotencyKey: request.idempotencyKey,
23117
+ environmentId: forkEnvironmentId
23118
+ }
23119
+ });
23120
+ }
23121
+ }
23122
+ /** Destroy a capture's fork and journal whether the provider confirmed it. */
23123
+ async function destroyCaptureFork(state, branching, target) {
23124
+ const material = {
23125
+ kind: "fork",
23126
+ targetId: target.fork.environmentId,
23127
+ provider: target.provider
23128
+ };
23129
+ const request = {
23130
+ ...material,
23131
+ operationId: `${target.fork.idempotencyKey}:destroy`,
23132
+ requestDigest: workspaceCleanupRequestDigest(material)
23133
+ };
23134
+ let destroyed = false;
23135
+ try {
23136
+ const signal = AbortSignal.timeout(3e4);
23137
+ const acknowledgement = await runAbortable(() => branching.destroyFork(request, { signal }), signal, "checkpoint capture fork cleanup timed out");
23138
+ destroyed = workspaceCleanupAcknowledgementMatches(request, acknowledgement) && (acknowledgement.status === "deleted" || acknowledgement.status === "already_absent");
23139
+ } catch {}
23140
+ await state.args.journal.appendEvent(state.args.rootId, {
23141
+ kind: "workspace-checkpoint-fork-teardown",
23142
+ id: state.args.nodeId,
23143
+ ...target,
23144
+ destroyed,
23145
+ seq: state.nextSequence(),
23146
+ at: new Date(state.args.now()).toISOString()
23147
+ });
23148
+ return destroyed;
23149
+ }
23150
+ /**
23151
+ * Destroy every capture fork the journal does not show destroyed: one a crash left between its
23152
+ * request and its teardown, or whose teardown the provider did not confirm. Returns the forks
23153
+ * still not confirmed destroyed, by environment or, when none was ever named, by request key.
23154
+ */
23155
+ async function settleCaptureForks(state) {
23156
+ const { args } = state;
23157
+ const providerName = state.provider?.name;
23158
+ const events = (await args.journal.loadTree(args.rootId) ?? []).filter((event) => event.id === args.nodeId);
23159
+ const named = (key) => {
23160
+ for (const event of events) if ((event.kind === "workspace-checkpoint-capture" || event.kind === "workspace-checkpoint-fork-teardown") && event.fork.idempotencyKey === key) return event.fork.environmentId;
23161
+ };
23162
+ const destroyed = new Set(events.flatMap((event) => event.kind === "workspace-checkpoint-fork-teardown" && event.destroyed ? [event.fork.idempotencyKey] : []));
23163
+ const unresolved = [];
23164
+ for (const request of events) {
23165
+ if (request.kind !== "workspace-checkpoint-fork-requested" || request.provider !== providerName) continue;
23166
+ if (destroyed.has(request.idempotencyKey)) continue;
23167
+ const signal = AbortSignal.timeout(3e4);
23168
+ const branching = await checkpointHandle(state, request.environmentId, signal);
23169
+ let forkEnvironmentId = named(request.idempotencyKey);
23170
+ if (forkEnvironmentId === void 0 && branching !== void 0) try {
23171
+ const found = await runAbortable(() => branching.lookupFork({
23172
+ idempotencyKey: request.idempotencyKey,
23173
+ requestDigest: request.requestDigest
23174
+ }, { signal }), signal, "checkpoint capture fork lookup timed out");
23175
+ if (found.status === "not_found") continue;
23176
+ if (found.status === "found") forkEnvironmentId = found.environment.environmentId;
23177
+ } catch {}
23178
+ if (forkEnvironmentId === void 0 || branching === void 0 || !await destroyCaptureFork(state, branching, {
23179
+ provider: request.provider,
23180
+ environmentId: request.environmentId,
23181
+ checkpointId: request.checkpointId,
23182
+ fork: {
23183
+ idempotencyKey: request.idempotencyKey,
23184
+ environmentId: forkEnvironmentId
23185
+ }
23186
+ })) unresolved.push(forkEnvironmentId ?? request.idempotencyKey);
23187
+ }
23188
+ return unresolved;
23731
23189
  }
23732
23190
  /**
23733
23191
  * The checkpoint a new environment of this owner starts from: the latest one journaled before
@@ -23860,19 +23318,23 @@ async function releaseOwnerEnvironment(state, provider) {
23860
23318
  let lastDetail;
23861
23319
  let retriable = false;
23862
23320
  const checkpointFailures = [];
23321
+ const checkpointsKept = [];
23322
+ const uncapturedSources = /* @__PURE__ */ new Set();
23863
23323
  const pending = pendingCheckpoints(events, state).filter((event) => !retentionFailures.has(event.environmentId));
23864
23324
  for (const sourceEnvironmentId of new Set(pending.map((event) => event.environmentId))) {
23865
- const signal = AbortSignal.timeout(3e4);
23866
- const branching = await checkpointHandle(state, sourceEnvironmentId, signal);
23867
- checkpointFailures.push(...await deleteCheckpoints(state, branching, pending.filter((event) => event.environmentId === sourceEnvironmentId), signal));
23325
+ const cleaned = await cleanCheckpoints(state, await checkpointHandle(state, sourceEnvironmentId, AbortSignal.timeout(3e4)), pending.filter((event) => event.environmentId === sourceEnvironmentId), events);
23326
+ checkpointFailures.push(...cleaned.unconfirmed);
23327
+ checkpointsKept.push(...cleaned.refused);
23328
+ for (const refusal of cleaned.refused) if (refusal.needsSource) uncapturedSources.add(sourceEnvironmentId);
23868
23329
  }
23330
+ const forksUnresolved = await settleCaptureForks(state);
23869
23331
  for (const event of checkpointFailures) pendingSources.add(event.environmentId);
23870
23332
  for (const environmentId of environments) {
23871
23333
  if (released.has(environmentId)) continue;
23872
23334
  let destroyed = false;
23873
23335
  let detail;
23874
- if (retentionFailures.has(environmentId) || pendingSources.has(environmentId)) {
23875
- detail = pendingSources.has(environmentId) ? "checkpoint cleanup unresolved: source preserved for exact lookup and cleanup" : "provider workspace retention: source preserved because the owner execution has no verified workspace receipt";
23336
+ if (retentionFailures.has(environmentId) || pendingSources.has(environmentId) || uncapturedSources.has(environmentId)) {
23337
+ detail = pendingSources.has(environmentId) ? "checkpoint cleanup unresolved: source preserved for exact lookup and cleanup" : uncapturedSources.has(environmentId) ? "checkpoint kept uncaptured: source preserved so its checkpoint can still be forked and captured" : "provider workspace retention: source preserved because the owner execution has no verified workspace receipt";
23876
23338
  preserved.push(environmentId);
23877
23339
  lastDetail = detail;
23878
23340
  } else {
@@ -23928,19 +23390,36 @@ async function releaseOwnerEnvironment(state, provider) {
23928
23390
  });
23929
23391
  }
23930
23392
  state.releaseRetriable = retriable;
23931
- const checkpointTeardowns = [...checkpointFailures.map((event) => ({
23932
- id: args.nodeId,
23933
- label: "scope owner workspace checkpoint",
23934
- runtime: provider.name,
23935
- status: "done",
23936
- detail: `checkpoint cleanup unconfirmed: ${event.checkpoint.checkpointId} from ${event.environmentId}`
23937
- })), ...requestFailures.map(({ event, reason }) => ({
23938
- id: args.nodeId,
23939
- label: "scope owner checkpoint request",
23940
- runtime: provider.name,
23941
- status: "done",
23942
- detail: `checkpoint request unresolved: ${event.request.idempotencyKey} from ${event.environmentId} (${reason})`
23943
- }))];
23393
+ const checkpointTeardowns = [
23394
+ ...checkpointFailures.map((event) => ({
23395
+ id: args.nodeId,
23396
+ label: "scope owner workspace checkpoint",
23397
+ runtime: provider.name,
23398
+ status: "done",
23399
+ detail: `checkpoint cleanup unconfirmed: ${event.checkpoint.checkpointId} from ${event.environmentId}`
23400
+ })),
23401
+ ...requestFailures.map(({ event, reason }) => ({
23402
+ id: args.nodeId,
23403
+ label: "scope owner checkpoint request",
23404
+ runtime: provider.name,
23405
+ status: "done",
23406
+ detail: `checkpoint request unresolved: ${event.request.idempotencyKey} from ${event.environmentId} (${reason})`
23407
+ })),
23408
+ ...checkpointsKept.map(({ event, reason }) => ({
23409
+ id: args.nodeId,
23410
+ label: "scope owner workspace checkpoint",
23411
+ runtime: provider.name,
23412
+ status: "done",
23413
+ detail: `checkpoint kept uncaptured: ${event.checkpoint.checkpointId} from ${event.environmentId} (${reason})`
23414
+ })),
23415
+ ...forksUnresolved.length === 0 ? [] : [{
23416
+ id: args.nodeId,
23417
+ label: "scope owner checkpoint capture fork",
23418
+ runtime: provider.name,
23419
+ status: "done",
23420
+ detail: `checkpoint capture fork destruction unconfirmed: ${forksUnresolved.join(", ")}`
23421
+ }]
23422
+ ];
23944
23423
  return unconfirmed.length > 0 || preserved.length > 0 ? [{
23945
23424
  id: args.nodeId,
23946
23425
  label: "scope owner",
@@ -24245,179 +23724,6 @@ function consumeScopeRetainedOwnerResult(scope) {
24245
23724
  state.acceptedConsumed = true;
24246
23725
  }
24247
23726
  //#endregion
24248
- //#region src/runtime/supervise/wait.ts
24249
- /**
24250
- *
24251
- * WAIT-STATES — a supervision-tree node that waits on wall-clock time or an external condition
24252
- * without holding a worker, an executor, a sandbox, or a single LLM turn.
24253
- *
24254
- * A long-horizon run spends most of its wall-clock NOT computing: waiting for CI to finish,
24255
- * for a nightly job to land, for a human to reply, for a rate-limit window to reopen. Before
24256
- * this, the only way to express that was to keep something alive and re-ask — which spends
24257
- * driver tokens per re-ask and pins a process to the wait.
24258
- *
24259
- * Two node kinds, both first-class:
24260
- * - `timer` — wake at an ABSOLUTE wall-clock instant (`untilMs`).
24261
- * - `poll` — re-run a named predicate every `intervalMs` until it returns true, or until an
24262
- * absolute `timeoutAtMs` passes (CI status, file existence, an HTTP probe, an
24263
- * inbox message).
24264
- *
24265
- * ── How this differs from a manager's wake (`./wake`) ──
24266
- *
24267
- * They look similar and are not the same mechanism. A wake is an IN-RUN RENDEZVOUS: a manager
24268
- * that ends its turn with work open is resumed when the coordination bus delivers its next event.
24269
- * It costs no model turn, but it lives in a process that must stay up, and nothing about that
24270
- * wait is recorded: kill the process and the wait is simply gone.
24271
- *
24272
- * A wait-state is a NODE, not a call. It has a node id in the tree, a journal record carrying its
24273
- * ABSOLUTE deadline, and it settles through the same `Scope.next()` cursor as any worker. Nobody
24274
- * is blocked on it — the driver can stop reasoning entirely, and the process can die. Cost while
24275
- * waiting: zero LLM calls, zero executor, zero sandbox, zero conserved budget (a wait reserves
24276
- * nothing from the pool). The only in-process residue is one timer entry.
24277
- *
24278
- * ── Why probes are NAMED, not passed as closures ────────────────────────────────────────────
24279
- *
24280
- * A wait must survive a process restart with its original deadline intact, and a closure cannot
24281
- * be journaled. So a `poll` names its predicate (`probe: 'ci-green'`) and the run resolves it
24282
- * through a `WaitProbeRegistry`. A brand-new process re-resolves the SAME name against its own
24283
- * registry and re-arms the wait — which is what makes "kill the box, the wait keeps waiting"
24284
- * true rather than aspirational.
24285
- *
24286
- * Absolute instants for the same reason: `untilMs` / `timeoutAtMs` are epoch ms, not durations,
24287
- * so a resumed wait counts down from the original arm, not from the restart. `timerAt`/`pollFor`
24288
- * build them from a duration when that is what the caller has.
24289
- *
24290
- * @experimental
24291
- */
24292
- /** Build a `timer` spec from a DURATION. The instant is resolved once, at arm time — a resumed
24293
- * wait re-uses the journaled instant, never a fresh `now + ms`. */
24294
- function timerAt(ms, now) {
24295
- return {
24296
- kind: "timer",
24297
- untilMs: now + ms
24298
- };
24299
- }
24300
- /** Build a bounded `poll` spec from a duration. */
24301
- function pollFor(probe, opts, now) {
24302
- return {
24303
- kind: "poll",
24304
- probe,
24305
- intervalMs: opts.intervalMs,
24306
- ...opts.timeoutMs !== void 0 ? { timeoutAtMs: now + opts.timeoutMs } : {},
24307
- ...opts.args ? { args: opts.args } : {}
24308
- };
24309
- }
24310
- /** Registry over a plain name→predicate record. */
24311
- function createWaitProbes(entries) {
24312
- const map = new Map(Object.entries(entries));
24313
- return { resolve: (name) => map.get(name) };
24314
- }
24315
- /** Narrow a settlement's `out` to a wait outcome — a wait settles on the SAME cursor as workers,
24316
- * so a driver that mixes them tags them apart with this. */
24317
- function isWaitOutcome(value) {
24318
- return typeof value === "object" && value !== null && value.waitOutcome === true;
24319
- }
24320
- /** The absolute instant a spec is bounded by, or `undefined` for an unbounded wait. */
24321
- function waitUntil(spec) {
24322
- if (spec.kind === "timer") return spec.untilMs;
24323
- if (spec.kind === "token") return spec.expiresAtMs;
24324
- return spec.timeoutAtMs;
24325
- }
24326
- /** Structural validation, independent of the run. Returns null when the spec is usable. */
24327
- function validateWaitSpec(spec) {
24328
- if (spec.kind === "timer") return Number.isFinite(spec.untilMs) ? null : "timer.untilMs must be a finite epoch-ms instant";
24329
- if (spec.kind === "token") return "token waits are graph-engine-owned; deliver them through engine resume/expire";
24330
- if (typeof spec.probe !== "string" || spec.probe.length === 0) return "poll.probe must be a non-empty probe name";
24331
- if (!Number.isFinite(spec.intervalMs) || spec.intervalMs <= 0) return "poll.intervalMs must be > 0";
24332
- if (spec.timeoutAtMs !== void 0 && !Number.isFinite(spec.timeoutAtMs)) return "poll.timeoutAtMs must be a finite epoch-ms instant";
24333
- return null;
24334
- }
24335
- /**
24336
- * A wait must not silently outlive the run's HARD wall-clock ceiling. When the conserved pool
24337
- * carries an absolute `deadlineMs`, a wait bounded past it — or an unbounded poll — is REFUSED at
24338
- * arm time (`deadline-exceeded`) rather than sleeping through a ceiling the caller already set.
24339
- * The alternative (extending the pool's deadline to cover the wait) would let a wait override a
24340
- * hard budget guard, which is exactly what mechanic D forbids; a run that intends week-long waits
24341
- * either sets a deadline that covers them or sets none.
24342
- */
24343
- function assertWaitWithinDeadline(spec, deadlineMs) {
24344
- if (deadlineMs <= 0) return true;
24345
- const until = waitUntil(spec);
24346
- if (until === void 0) return false;
24347
- return until <= deadlineMs;
24348
- }
24349
- /**
24350
- * Drive one wait to its resolution. Spends nothing: a `timer` is one sleep, a `poll` is a sleep
24351
- * between predicate checks. No LLM call, no executor, no box, no budget reservation.
24352
- */
24353
- async function runWait(args) {
24354
- const { spec, label, armedAt, resumed, signal, now } = args;
24355
- const sleep = args.sleep ?? defaultSleep$1;
24356
- if (signal.aborted) return {
24357
- kind: "cancelled",
24358
- reason: "aborted before arming"
24359
- };
24360
- if (spec.kind === "timer") {
24361
- const remaining = spec.untilMs - now();
24362
- if (remaining > 0) await sleep(remaining, signal);
24363
- if (signal.aborted) return {
24364
- kind: "cancelled",
24365
- reason: "wait aborted"
24366
- };
24367
- return {
24368
- kind: "woke",
24369
- outcome: outcome("timer", "fired", label, spec.untilMs, armedAt, now(), 0, 0, resumed)
24370
- };
24371
- }
24372
- if (spec.kind === "token") throw new ValidationError$1(`wait '${label}': token waits are graph-engine-owned; deliver them through engine resume/expire`);
24373
- const probe = args.probes?.resolve(spec.probe);
24374
- if (!probe) throw new ValidationError$1(`wait '${label}': poll probe '${spec.probe}' is not registered in this run's WaitProbeRegistry`);
24375
- let polls = 0;
24376
- let probeErrors = 0;
24377
- for (;;) {
24378
- if (signal.aborted) return {
24379
- kind: "cancelled",
24380
- reason: "wait aborted"
24381
- };
24382
- polls += 1;
24383
- let fired = false;
24384
- try {
24385
- fired = await probe(spec.args, signal);
24386
- } catch {
24387
- probeErrors += 1;
24388
- }
24389
- if (fired) return {
24390
- kind: "woke",
24391
- outcome: outcome("poll", "fired", label, spec.timeoutAtMs, armedAt, now(), polls, probeErrors, resumed)
24392
- };
24393
- if (spec.timeoutAtMs !== void 0 && now() >= spec.timeoutAtMs) return {
24394
- kind: "woke",
24395
- outcome: outcome("poll", "timeout", label, spec.timeoutAtMs, armedAt, now(), polls, probeErrors, resumed)
24396
- };
24397
- await sleep(spec.timeoutAtMs === void 0 ? spec.intervalMs : Math.min(spec.intervalMs, Math.max(0, spec.timeoutAtMs - now())), signal);
24398
- }
24399
- }
24400
- function outcome(kind, settled, label, untilMs, armedAt, wokenAt, polls, probeErrors, resumed) {
24401
- return {
24402
- waitOutcome: true,
24403
- kind,
24404
- settled,
24405
- label,
24406
- ...untilMs !== void 0 ? { untilMs } : {},
24407
- armedAt,
24408
- wokenAt,
24409
- polls,
24410
- probeErrors,
24411
- resumed
24412
- };
24413
- }
24414
- /** `setTimeout` that resolves early (and clears) when the scope aborts, so a cancelled wait
24415
- * releases the event loop immediately instead of holding the process to its deadline. */
24416
- function defaultSleep$1(ms, signal) {
24417
- if (ms <= 0 || signal?.aborted) return Promise.resolve();
24418
- return sleep(ms, signal);
24419
- }
24420
- //#endregion
24421
23727
  //#region src/runtime/supervise/scope.ts
24422
23728
  /**
24423
23729
  *
@@ -24751,13 +24057,11 @@ function createScope(args) {
24751
24057
  } : void 0;
24752
24058
  let spawnOrdinal = args.resumeFrom ? args.resumeFrom.maxSpawnOrdinal + 1 : 0;
24753
24059
  let cursorSeq = args.resumeFrom ? args.resumeFrom.maxCursorSeq + 1 : 0;
24754
- let waitOrdinal = args.resumeFrom ? args.resumeFrom.maxWaitOrdinal + 1 : 0;
24755
24060
  let meterSeq = 0;
24756
24061
  let ownerTurns = 0;
24757
24062
  let ownerLastTurnAt = 0;
24758
24063
  let progressSeq = 0;
24759
24064
  const now = args.now ?? Date.now;
24760
- const unclaimedWaits = new Map((args.resumeFrom?.waits ?? []).map((w) => [w.label, w]));
24761
24065
  const keyed = /* @__PURE__ */ new Map();
24762
24066
  for (const [key, prior] of args.resumeFrom?.keys ?? []) if (prior.state === "completed" && prior.settled?.kind === "done") {
24763
24067
  if (prior.identity === void 0) continue;
@@ -25428,165 +24732,6 @@ function createScope(args) {
25428
24732
  child.lastActivityAt = now();
25429
24733
  return true;
25430
24734
  }
25431
- /**
25432
- * Arm a wait-state node. Deliberately NOT a `spawn` with a sleeping executor: it resolves no
25433
- * `AgentSpec`, constructs no `Executor`, and — the point of the whole mechanic — reserves NOTHING
25434
- * from the conserved pool, so a week-long wait costs zero tokens and zero dollars and cannot
25435
- * starve a worker of budget.
25436
- *
25437
- * Fail-closed admission, mirroring `spawn`'s typed outcome. The deadline check is the one that
25438
- * matters: a wait may not silently sleep past the pool's hard wall-clock ceiling, and it may not
25439
- * extend that ceiling either (that would make a wait override a budget guard).
25440
- */
25441
- function wait(spec, opts) {
25442
- if (args.signal.aborted) return {
25443
- ok: false,
25444
- reason: "deadline-exceeded"
25445
- };
25446
- if (validateWaitSpec(spec) !== null) return {
25447
- ok: false,
25448
- reason: "invalid-spec"
25449
- };
25450
- if (spec.kind === "poll" && args.probes?.resolve(spec.probe) === void 0) return {
25451
- ok: false,
25452
- reason: "unknown-probe"
25453
- };
25454
- const adopted = unclaimedWaits.get(opts.label);
25455
- if (adopted) unclaimedWaits.delete(opts.label);
25456
- const effectiveSpec = adopted?.spec ?? spec;
25457
- const armedAt = adopted?.armedAt ?? now();
25458
- if (!assertWaitWithinDeadline(effectiveSpec, args.pool.readout().deadlineMs)) return {
25459
- ok: false,
25460
- reason: "deadline-exceeded"
25461
- };
25462
- const id = adopted ? adopted.id : `${args.parentId}:w${waitOrdinal}`;
25463
- const ordinal = adopted ? adopted.ordinal : waitOrdinal;
25464
- if (!adopted) waitOrdinal += 1;
25465
- const waitAbort = new AbortController();
25466
- const cascadeAbort = () => waitAbort.abort();
25467
- if (args.signal.aborted) waitAbort.abort();
25468
- else args.signal.addEventListener("abort", cascadeAbort, { once: true });
25469
- const handle = {
25470
- id,
25471
- label: opts.label,
25472
- get status() {
25473
- return children.get(id)?.status ?? "cancelled";
25474
- },
25475
- abort(reason) {
25476
- waitAbort.abort(reason);
25477
- }
25478
- };
25479
- const live = {
25480
- id,
25481
- status: "waiting",
25482
- runtime: "wait",
25483
- abortChild: (reason) => waitAbort.abort(reason),
25484
- budget: {
25485
- maxIterations: 0,
25486
- maxTokens: 0
25487
- },
25488
- label: opts.label,
25489
- spent: zeroSpend(),
25490
- settled: void 0,
25491
- delivered: false,
25492
- executorDone: false,
25493
- cleanupConfirmed: true,
25494
- teardownAttempts: 0,
25495
- executionBindings: [],
25496
- startedAt: armedAt,
25497
- lastActivityAt: now(),
25498
- wait: {
25499
- spec: effectiveSpec,
25500
- armedAt,
25501
- label: opts.label,
25502
- armCommitted: adopted !== void 0
25503
- }
25504
- };
25505
- children.set(id, live);
25506
- live.settled = (adopted ? Promise.resolve() : args.journal.appendEvent(args.root, {
25507
- kind: "waiting",
25508
- id,
25509
- parent: args.parentId,
25510
- label: opts.label,
25511
- spec: effectiveSpec,
25512
- armedAt,
25513
- seq: ordinal,
25514
- at: new Date(now()).toISOString()
25515
- })).then(() => {
25516
- if (live.wait) live.wait.armCommitted = true;
25517
- notifyRuntimeHookEvent(args.hooks, {
25518
- id: `${id}:waiting`,
25519
- runId: args.root,
25520
- target: "agent.spawn",
25521
- phase: "after",
25522
- timestamp: now(),
25523
- stepIndex: ordinal,
25524
- parentId: args.parentId,
25525
- payload: {
25526
- childId: id,
25527
- label: opts.label,
25528
- runtime: "wait",
25529
- wait: effectiveSpec,
25530
- armedAt,
25531
- resumed: adopted !== void 0
25532
- }
25533
- }, { signal: args.signal });
25534
- return runWait({
25535
- spec: effectiveSpec,
25536
- label: opts.label,
25537
- armedAt,
25538
- resumed: adopted !== void 0,
25539
- signal: waitAbort.signal,
25540
- ...args.probes ? { probes: args.probes } : {},
25541
- now,
25542
- ...args.waitSleep ? { sleep: args.waitSleep } : {}
25543
- });
25544
- }).then(async (resolution) => {
25545
- live.executorDone = true;
25546
- live.lastActivityAt = now();
25547
- if (resolution.kind === "cancelled") return {
25548
- kind: "down",
25549
- reason: resolution.reason,
25550
- infra: false,
25551
- trace: {
25552
- status: "unavailable",
25553
- reason: "not-an-executor"
25554
- }
25555
- };
25556
- const outRef = contentAddress(resolution.outcome);
25557
- await args.blobs.put(outRef, resolution.outcome);
25558
- return {
25559
- kind: "done",
25560
- out: resolution.outcome,
25561
- outRef,
25562
- spent: zeroSpend(),
25563
- trace: {
25564
- status: "unavailable",
25565
- reason: "not-an-executor"
25566
- }
25567
- };
25568
- }).catch((err) => {
25569
- live.executorDone = true;
25570
- return {
25571
- kind: "down",
25572
- reason: errMessage(err),
25573
- infra: true,
25574
- trace: {
25575
- status: "unavailable",
25576
- reason: "not-an-executor"
25577
- }
25578
- };
25579
- }).then((s) => {
25580
- live.resolved = s;
25581
- return s;
25582
- }).finally(() => {
25583
- args.signal.removeEventListener("abort", cascadeAbort);
25584
- });
25585
- return {
25586
- ok: true,
25587
- handle
25588
- };
25589
- }
25590
24735
  function progress(nodeId, opts = {}) {
25591
24736
  const child = children.get(nodeId);
25592
24737
  if (!child) return void 0;
@@ -25636,7 +24781,7 @@ function createScope(args) {
25636
24781
  function interactive(nodeId) {
25637
24782
  const child = children.get(nodeId);
25638
24783
  if (!child) return noInteractiveSession("unknown-node");
25639
- if (child.wait || child.executorDone || isTerminalNodeStatus(child.status)) return noInteractiveSession("not-live");
24784
+ if (child.executorDone || isTerminalNodeStatus(child.status)) return noInteractiveSession("not-live");
25640
24785
  const session = readInteractiveSession(child);
25641
24786
  if (args.interactiveBindingDir !== void 0 && session.status === "available") writeWorkerInteractiveBinding(args.interactiveBindingDir, child.id, child.label, args.root, session, now);
25642
24787
  return session;
@@ -25680,7 +24825,6 @@ function createScope(args) {
25680
24825
  const resume = args.resumeFrom ? {
25681
24826
  settled: args.resumeFrom.settled,
25682
24827
  view: args.resumeFrom.view,
25683
- waits: args.resumeFrom.waits,
25684
24828
  keys: args.resumeFrom.keys,
25685
24829
  priorSpend: args.resumeFrom.priorSpend
25686
24830
  } : void 0;
@@ -25689,7 +24833,6 @@ function createScope(args) {
25689
24833
  next,
25690
24834
  nextResolved,
25691
24835
  send,
25692
- wait,
25693
24836
  progress,
25694
24837
  traceSource,
25695
24838
  interactive,
@@ -26007,6 +25150,15 @@ async function publishOwnerMaterialization(state, runtime, declaration, bindingI
26007
25150
  state.publishedThisProcess = true;
26008
25151
  return;
26009
25152
  }
25153
+ if (state.receipt !== void 0 && state.receipt.status !== "known") {
25154
+ if (!state.bindingPublished) {
25155
+ const boundToCommitted = knownExecutionBindingReceipt(state.receipt, bindingInput);
25156
+ await appendOwnerBinding(state, boundToCommitted);
25157
+ state.onReceipt?.(state.receipt, boundToCommitted);
25158
+ }
25159
+ state.publishedThisProcess = true;
25160
+ return;
25161
+ }
26010
25162
  if (state.receipt !== void 0) {
26011
25163
  if (canonicalCandidateDigest(state.receipt) !== canonicalCandidateDigest(receipt)) {
26012
25164
  const changed = changedRunIdentityFields(state.receipt, receipt);
@@ -26274,7 +25426,6 @@ async function appendAcknowledged(journal, root, event) {
26274
25426
  * `PreSeqSettled` into the frozen `Settled` the driver branches on. */
26275
25427
  async function finalizeSettlement(child, settlement, seq, args, now) {
26276
25428
  const handle = frozenHandle(child);
26277
- if (child.wait) return finalizeWait(child, settlement, seq, args, now, handle);
26278
25429
  const nestedScope = child.readNestedScope?.();
26279
25430
  const subtree = nestedScope === void 0 ? void 0 : subtreeSummaryOf(nestedScope);
26280
25431
  if (subtree !== void 0) child.subtree = subtree;
@@ -26395,68 +25546,6 @@ async function finalizeSettlement(child, settlement, seq, args, now) {
26395
25546
  seq
26396
25547
  };
26397
25548
  }
26398
- /** Journal a wait-state's settlement as a `woken` event and project it onto the same `Settled`
26399
- * the driver branches on. `by` names WHY it woke — `fired` / `timeout` / `cancelled` — which is
26400
- * the fact a resumed reader needs and cannot recover from a payload it may never fetch. */
26401
- async function finalizeWait(child, settlement, seq, args, now, handle) {
26402
- const settledAt = now();
26403
- child.settledAt = settledAt;
26404
- const at = new Date(settledAt).toISOString();
26405
- if (settlement.kind === "down") {
26406
- child.status = "cancelled";
26407
- if (child.wait?.armCommitted) await args.journal.appendEvent(args.root, {
26408
- kind: "woken",
26409
- id: child.id,
26410
- by: "cancelled",
26411
- seq,
26412
- at
26413
- });
26414
- return {
26415
- kind: "down",
26416
- handle,
26417
- reason: settlement.reason,
26418
- ...settlement.infra === void 0 ? {} : { infra: settlement.infra },
26419
- trace: settlement.trace,
26420
- settledAt,
26421
- seq
26422
- };
26423
- }
26424
- child.status = "done";
26425
- child.outRef = settlement.outRef;
26426
- const out = settlement.out;
26427
- await args.journal.appendEvent(args.root, {
26428
- kind: "woken",
26429
- id: child.id,
26430
- by: out.settled,
26431
- outRef: settlement.outRef,
26432
- seq,
26433
- at
26434
- });
26435
- notifyRuntimeHookEvent(args.hooks, {
26436
- id: `${child.id}:woken`,
26437
- runId: args.root,
26438
- target: "agent.child",
26439
- phase: "after",
26440
- timestamp: settledAt,
26441
- stepIndex: seq,
26442
- parentId: args.parentId,
26443
- payload: {
26444
- childId: child.id,
26445
- status: "done",
26446
- wait: out
26447
- }
26448
- }, { signal: args.signal });
26449
- return {
26450
- kind: "done",
26451
- handle,
26452
- out: settlement.out,
26453
- outRef: settlement.outRef,
26454
- spent: settlement.spent,
26455
- trace: settlement.trace,
26456
- settledAt,
26457
- seq
26458
- };
26459
- }
26460
25549
  /**
26461
25550
  * Drive one child's `Executor` to a terminal `PreSeqSettled`, folding usage into the
26462
25551
  * conserved `Spend`, reconciling the reservation, and persisting the result blob. Both
@@ -26733,8 +25822,6 @@ function settledToIteration(settled) {
26733
25822
  tokenUsage: cloneTokenUsage(settled.spent.tokens)
26734
25823
  };
26735
25824
  }
26736
- /** Summarize one scope's children and everything below them, listing the best direct children
26737
- * and counting the rest. Wait-states are not agents and are left out. */
26738
25825
  /** The live team a child manager leads, read through the nested scope it owns. */
26739
25826
  function liveTeamOf(child) {
26740
25827
  let nested;
@@ -26769,7 +25856,6 @@ function readLiveTeam(children, ownerTurns, ownerLastTurnAt) {
26769
25856
  let down = 0;
26770
25857
  let lastActivityAt = ownerLastTurnAt;
26771
25858
  for (const child of children) {
26772
- if (child.wait) continue;
26773
25859
  agents += 1;
26774
25860
  lastActivityAt = Math.max(lastActivityAt, child.lastActivityAt, child.settledAt ?? 0, executorActivityAt(child));
26775
25861
  if (child.status === "done") done += 1;
@@ -26807,7 +25893,6 @@ function summarizeTeam(children) {
26807
25893
  let members = 0;
26808
25894
  const results = [];
26809
25895
  for (const child of children) {
26810
- if (child.wait) continue;
26811
25896
  members += 1;
26812
25897
  const below = child.subtree;
26813
25898
  agents += 1 + (below?.agents ?? 0);
@@ -26867,8 +25952,7 @@ function makeTreeView(root, children) {
26867
25952
  return {
26868
25953
  root,
26869
25954
  nodes,
26870
- inFlight: nodes.filter((n) => n.status === "running" || n.status === "acquiring" || n.status === "queued").length,
26871
- waiting: nodes.filter((n) => n.status === "waiting").length
25955
+ inFlight: nodes.filter((n) => n.status === "running" || n.status === "acquiring" || n.status === "queued").length
26872
25956
  };
26873
25957
  }
26874
25958
  function frozenHandle(child) {
@@ -27366,7 +26450,7 @@ async function closeNestedScope(scope, controller, reason) {
27366
26450
  if (!controller.signal.aborted) controller.abort(reason);
27367
26451
  for (;;) if (await scope.next() === null) break;
27368
26452
  const view = scope.view;
27369
- if (view.inFlight > 0 || view.waiting > 0) throw new ValidationError$1(`driverExecutor: nested cleanup left ${view.inFlight} running and ${view.waiting} waiting nodes`);
26453
+ if (view.inFlight > 0) throw new ValidationError$1(`driverExecutor: nested cleanup left ${view.inFlight} running nodes`);
27370
26454
  }
27371
26455
  /** The nested tree's full event list — the one evidence the spend, verdict, AND driver-inference
27372
26456
  * roll-ups read off the same journal the supervisor sums. */
@@ -28914,7 +27998,7 @@ function describeRejection(error) {
28914
27998
  function createSupervisor() {
28915
27999
  let attached;
28916
28000
  async function run(root, task, opts) {
28917
- const { budget, rootIdentity, rootMaterialization, runId, journal: journalStore, blobs: blobStore, executors: executorRegistry, recoverExecutor, probes, maxDepth, workerSlots, reservationPolicy, maxRestarts, withinMs, childSettleGraceMs, teardownConfirmMs, resume, retainedAtSettlement: requestedRetainedAtSettlement, ownerWorkspaceRetention, now: suppliedNow, signal, hooks, workerTrace, workerTraceUnpropagated, interactiveBindingDir } = opts;
28001
+ const { budget, rootIdentity, rootMaterialization, runId, journal: journalStore, blobs: blobStore, executors: executorRegistry, recoverExecutor, maxDepth, workerSlots, reservationPolicy, maxRestarts, withinMs, childSettleGraceMs, teardownConfirmMs, resume, retainedAtSettlement: requestedRetainedAtSettlement, ownerWorkspaceRetention, now: suppliedNow, signal, hooks, workerTrace, workerTraceUnpropagated, interactiveBindingDir } = opts;
28918
28002
  const input = detachedSnapshot({
28919
28003
  task,
28920
28004
  options: {
@@ -28949,7 +28033,6 @@ function createSupervisor() {
28949
28033
  blobs: persistence.blobs,
28950
28034
  executors: executorRegistry,
28951
28035
  ...recoverExecutor ? { recoverExecutor } : {},
28952
- ...probes === void 0 ? {} : { probes },
28953
28036
  ...suppliedNow === void 0 ? {} : { now: suppliedNow },
28954
28037
  ...signal === void 0 ? {} : { signal },
28955
28038
  ...hooks === void 0 ? {} : { hooks },
@@ -29067,7 +28150,6 @@ function createSupervisor() {
29067
28150
  requiredKnown: true,
29068
28151
  ...priorRootMaterialization === void 0 ? {} : { prior: priorRootMaterialization }
29069
28152
  } } : {},
29070
- ...opts.probes ? { probes: opts.probes } : {},
29071
28153
  ...opts.workerTrace ? { workerTrace: opts.workerTrace } : {},
29072
28154
  ...opts.workerTraceUnpropagated ? { workerTraceUnpropagated: opts.workerTraceUnpropagated } : {},
29073
28155
  ...opts.interactiveBindingDir ? { interactiveBindingDir: opts.interactiveBindingDir } : {},
@@ -29418,8 +28500,7 @@ function wrapJournalForBreaker(journal, breaker) {
29418
28500
  * `allSettled`'d — a stray throw here is NOT the primary error (firstError precedence).
29419
28501
  */
29420
28502
  async function drainLiveChildren(scope, controller, settleGraceMs = 0) {
29421
- const view = scope.view;
29422
- if (!(view.inFlight > 0 || view.waiting > 0)) {
28503
+ if (scope.view.inFlight === 0) {
29423
28504
  await drainCursor(scope);
29424
28505
  return unconfirmedTeardowns(scope);
29425
28506
  }
@@ -29432,7 +28513,7 @@ async function drainLiveChildren(scope, controller, settleGraceMs = 0) {
29432
28513
  clearGraceTimer?.();
29433
28514
  }
29434
28515
  const after = scope.view;
29435
- if (after.inFlight > 0 || after.waiting > 0) throw new RuntimeRunStateError(`supervisor: cleanup ended with ${after.inFlight} running, ${after.waiting} waiting, and ` + describeUnconfirmed(scope));
28516
+ if (after.inFlight > 0) throw new RuntimeRunStateError(`supervisor: cleanup ended with ${after.inFlight} running and ` + describeUnconfirmed(scope));
29436
28517
  return unconfirmedTeardowns(scope);
29437
28518
  }
29438
28519
  /** Five minutes: long enough to outlast a provider's transient delete failures and a slow
@@ -29697,6 +28778,6 @@ function isNonEmptySpend(s) {
29697
28778
  return s.iterations > 0 || s.tokens.input > 0 || s.tokens.output > 0 || s.usd > 0 || s.ms > 0 || s.tokensKnown === false || s.usdKnown === false || Object.values(s.resources ?? {}).some((resource) => resource.amount > 0 || !resource.known);
29698
28779
  }
29699
28780
  //#endregion
29700
- export { bindScopeRetainedOwnerEnvironmentId as $, executableAgentProfileSnapshot as $i, parseWorkerToolTraceArtifact as $n, sanitizeAgentRuntimeEvent as $r, claimsAuthority as $t, driverExecutorFactory as A, withTimeout as Aa, worktreeCliProfileMaterialization as Ai, resolveAgentEnvironmentProvider as An, resolveHarnessTranscriptCapture as Ar, cliInPlaceExecutor as At, recordScopeOwnerDriverAttempt as B, teardownExecutor as Ba, knownExecutionBindingReceipt as Bi, InMemoryResultBlobStore as Bn, buildLoopOtelSpans as Br, WORKER_TRACE_PROPAGATION as Bt, createContinuationKeeper as C, promptCacheTokenClasses as Ca, promptOnlyProfileMaterialization as Ci, readPromptOptions as Cn, abortError as Cr, recoverRetainedInteractiveRun as Ct, passedItems as D, throwAbort as Da, sandboxActProfileMaterialization as Di, createAgentEnvironmentProviderRegistry as Dn, harnessTranscriptArtifact as Dr, rollingDispatch as Dt, failedItems as E, stringifySafe as Ea, renderUnsupported as Ei, LEAF_CONTINUATION_TASK as En, captureHarnessTranscript as Er, queueOf as Et, beginScopeOwnerAttempt as F, decodeHarnessUsage as Fa, attestRuntimeOwnedPendingExecutor as Fi, sandboxSessionTraceSource as Fn, readTraceContextFromEnv as Fr, createWorktreeCliExecutor as Ft, settledToIteration as G, runtimeOwnedDriveHarnessProviderEvidence as Gi, insideCursorNamespace as Gn, flatOtelSpan as Gr, taskToPrompt as Gt, recordScopeOwnerPause as H, promptFromAgentTurnInput as Ha, newExecutionAttemptId as Hi, SpawnEventIndex as Hn, buildRuntimeEventOtelSpans as Hr, workerTraceEnv as Ht, createScope as I, abortError$2 as Ia, attestRuntimeOwnedScopeOwner as Ii, registerRetainedExecutorPreparation as In, traceContextToEnv as Ir, DEFAULT_SANDBOX_STEERING_MAX_TURNS as It, pollFor as J, runtimeOwnedExecutorProviderEvidence as Ji, pendingWaits as Jn, padSpanId as Jr, readWorkerProgress as Jt, createWaitProbes as K, runtimeOwnedExecutorExecutionBinding as Ki, loadSpawnForest as Kn, generateSpanId as Kr, DEFAULT_STALL_AFTER_MS as Kt, deriveNodeExecutionIdentity as L, awaitAbortable$1 as La, authoredProfileDigest as Li, retainedExecutorSeamKey as Ln, defaultRedactor as Lr, createSteerableSandboxSession as Lt, withDriverExecutor as M, addResourceSpend as Ma, prepareJsonlAppend as Mi, unavailableSignalOfFailure as Mn, contentAddress as Mr, createExecutor as Mt, SUBTREE_RESULT_LIMIT as N, resourceTelemetry as Na, readCommittedJsonLines as Ni, createPushTraceSource as Nn, createPropagatingTraceEmitter as Nr, createExecutorRegistry as Nt, verdictFromJudgeScore as O, throwIfAborted as Oa, unsupportedProfileDimensions as Oi, providerAsExecutor as On, persistHarnessTranscript as Or, bindReusableExecutorExecutionId as Ot, assertRecursiveReservationPolicy as P, withBudgetResources as Pa, writeAllBytes as Pi, decodeToolPart as Pn, mergeTraceEnv as Pr, snapshotExecutorConfig as Pt, beginScopeRetainedOwnerDrive as Q, unknownMaterializationReceipt as Qi, isTraceAnalysisStore as Qn, createRuntimeStreamEventCollector as Qr, PEER_MAIL_WIRE_KEY as Qt, meterRuntimeOwnedAccounting as R, DEFAULT_SUCCESSFUL_SHUTDOWN_MS as Ra, finalizeRuntimeOwnedPendingExecutor as Ri, FileResultBlobStore as Rn, defaultRedactorIdentityMaterial as Rr, createRouterTranscript as Rt, composeContinuationNote as S, isAbortError$2 as Sa, promptModelProfileMaterialization as Si, assertBoxlessPromptOptions as Sn, RunCancellationReason as Sr, reconnectRetainedInteractiveRun as St, expandQuestions as T, sleep as Ta, renderProfileMaterializationIssues as Ti, runBrainLoop as Tn, runAbortable as Tr, freeSlots as Tt, restoreScopeOwnerAcceptedExecution as U, promptOptionsFromAgentTurnInput as Ua, providerAttemptEvidence as Ui, assertContentAddress as Un, createOpenInferenceFileExporter as Ur, workerTraceHeaders as Ut, recordScopeOwnerMaterialization as V, teardownSurfaces as Va, knownMaterializationReceipt as Vi, InMemorySpawnJournal as Vn, buildLoopSpanNodes as Vr, readWorkerTraceContext as Vt, scopeOwnerExecutorNodeContext as W, providerMessageText as Wa, recordRuntimeOwnedDriveHarnessProviderEvidence as Wi, encodeResultBlob as Wn, createOtelExporter as Wr, workerTraceSeamKey as Wt, validateWaitSpec as X, runtimeOwnedScopeOwnerRuntime as Xi, WORKER_TOOL_TRACE_SCHEMA_VERSION as Xn, toOtelAttributes as Xr, AUTHORITY_MARKERS as Xt, timerAt as Y, runtimeOwnedPendingExecutorMaterialization as Yi, replaySpawnTree as Yn, padTraceId as Yr, createInbox as Yt, waitUntil as Z, unknownExecutionBindingReceipt as Zi, captureWorkerTraceEvidence as Zn, createRuntimeEventCollector as Zr, DEFAULT_PEER_MAIL_LIMITS as Zt, CheckUnavailableError as _, addSpend as _a, controlProfileMaterialization as _i, createSandboxLineage as _n, retainedCreateMaterial as _r, workerInteractiveAdmissionFile as _t, collectDelivered as a, assertSandboxServedModel as aa, createWorktree as ai, isTerminalNodeStatus as an, createBudgetPool as ar, scopeRetainedOwnerContext as at, bestComposite as b, deleteBoxSafe as ba, profileMaterializationAxes$1 as bi, SandboxEvidenceRetentionError as bn, createWorkerSlots as br, workerInteractiveBindingFile as bt, runTree as c, createSandboxUsageLedger as ca, LOCAL_HARNESSES as ci, addHarnessUsage as cn, spendFromUsageEvents as cr, scopeRetainedOwnerRestorePoint as ct, classifyDriverFailure as d, mapSandboxEvent as da, localHarnessExecutable as di, readCodexRolloutSession as dn, bridgeStopSignalKey as dr, SPAWN_RESOURCE_PATH_MAX_BYTES as dt, executableAgentSpecSnapshot as ea, sanitizeKnowledgeReadinessReport as ei, createPeerMailbox as en, workerTraceAnalysisStore as er, bindScopeRetainedOwnerProvider as et, runDriverWithRetry as f, mapSandboxToolEvent as fa, parseCodexTokenUsage as fi, TERMINAL_DECISIONS as fn, errMessage as fr, environmentReader as ft, CONTINUATION_FACTS as g, sumSandboxUsage as ga, assertProfileMaterialization as gi, runAgentRounds as gn, startRetainedRunInEnvironment as gr, readWorkerInteractiveAdmissions as gt, CONTINUATIONS_DIR as h, sandboxProgressEvents as ha, AGENT_PROFILE_MATERIALIZATION_AXES as hi, isTerminalDecision as hn, startRetainedRun as hr, interactiveAdmissionSeamKey as ht, bestDelivered as i, readSandboxOutcome as ia, captureWorktreeDiff as ii, isLiveNodeStatus as in, assertValidBudget as ir, reconcileScopeRetainedOwnerEnvironment as it, isDriverSpec as j, zeroSpend as ja, isNoEntError as ji, unavailablePauseMs as jn, retainHarnessTranscript as jr, cliWorktreeExecutor as jt, driverChild as k, unmeteredSpend as ka, validateProfileMaterialization as ki, providerAsSandboxClient as kn, readHarnessTranscript as kr, captureReusableExecutorConfig as kt, DriverAttemptsExhaustedError as l, extractLlmCallEvent as la, harnessInvocation as li, createCodexRolloutStoreReader as ln, spendFromUsageTotals as lr, scopeRetainedOwnerResult as lt, upstreamUnavailableSignal as m, sandboxEventServedBackend as ma, terminateProcessTreeAndConfirm as mi, defaultSelectWinner as mn, recoverRetainedRun as mr, resolveSpawnResourcePaths as mt, createRootHandle as n, detachedSnapshot as na, runSettledCommand as ni, peerMailTools as nn, BudgetReconcileFault as nr, noteScopeRetainedOwnerCoordination as nt, pickBestDelivered as o, canonicalStreamEventFromSandboxEvent as oa, removeWorktree as oi, bridgeAdmissionRefusal as on, meterUsageEvent as or, scopeRetainedOwnerPriorSpend as ot, summarizeDriverAttempts as p, notifySandboxEventObserver as pa, CodexExecutionDiagnosticError as pi, createSandboxForSpec as pn, reconnectRetainedRun as pr, hostDirectoryReader as pt, isWaitOutcome as q, runtimeOwnedExecutorMaterialization as qi, materializeTreeView as qn, loopEventToOtelSpan as qr, createActivityLog as qt, createSupervisor as r, projectSandboxOutcome as ra, runWorktreeHarness as ri, peerMailVerbNames as rn, ReservationWaitRefused as rr, prepareScopeRetainedOwnerTask as rt, runFinalizer as s, createSandboxToolPartState as sa, DEFAULT_LOCAL_HARNESS as si, bridgeModelRouteRefusal as sn, newUsageTotals as sr, scopeRetainedOwnerResourceReader as st, DEFAULT_MAX_DEPTH as t, detachedFrozen as ta, sanitizeRuntimeStreamEvent as ti, isPeerMailEnvelope as tn, executorFailure as tr, consumeScopeRetainedOwnerResult as tt, HarnessTurnFailedError as u, isSandboxTerminalEvent as ua, harnessSupportsReasoningEffort as ui, harnessUsageIsEmpty as un, bridgeRuntimeAttachmentsKey as ur, scopeRetainedOwnerTurnEnded as ut, admitContinuationPolicy as v, chargedTokens as va, defineProfileMaterializationContract as vi, probeSandboxCapabilities as vn, destroyInteractiveEnvironment as vr, attachWorker as vt, distillFindings as w, randomSuffix as wa, promptResourceProfileMaterialization as wi, routerBrain as wn, linkAbort as wr, startRetainedInteractiveRun as wt, checkVerdictOf as x, hasCompleteCacheBreakdown as xa, promptControlProfileMaterialization as xi, captureBeforeDestroy as xn, openSlotGroup as xr, workerInteractiveBindingsDir as xt, admitFinding as y, cloneSpend as ya, fullProfileMaterialization as yi, acquireSandbox as yn, environmentGone as yr, readWorkerInteractiveBinding as yt, meterRuntimeOwnedProviderAttempt as z, armDeadlineTimer as za, inheritRuntimeOwnedExecutorAttestation as zi, FileSpawnJournal as zn, resolveRedactor as zr, createInPlaceCliExecutor as zt };
28781
+ export { scopeRetainedOwnerPriorSpend as $, sandboxProgressEvents as $i, bridgeStopSignalKey as $n, localHarnessExecutable as $r, harnessUsageIsEmpty as $t, isDriverSpec as A, runtimeOwnedExecutorExecutionBinding as Ai, insideCursorNamespace as An, buildRuntimeEventOtelSpans as Ar, readWorkerTraceContext as At, recordScopeOwnerMaterialization as B, detachedSnapshot as Bi, isTraceAnalysisStore as Bn, createRuntimeStreamEventCollector as Br, DEFAULT_PEER_MAIL_LIMITS as Bt, distillFindings as C, inheritRuntimeOwnedExecutorAttestation as Ci, sandboxSessionTraceSource as Cn, readTraceContextFromEnv as Cr, snapshotExecutorConfig as Ct, verdictFromJudgeScore as D, providerAttemptEvidence as Di, FileSpawnJournal as Dn, resolveRedactor as Dr, createRouterTranscript as Dt, passedItems as E, newExecutionAttemptId as Ei, FileResultBlobStore as En, defaultRedactorIdentityMaterial as Er, createSteerableSandboxSession as Et, createScope as F, unknownExecutionBindingReceipt as Fi, prepareJsonlAppend as Fn, loopEventToOtelSpan as Fr, DEFAULT_STALL_AFTER_MS as Ft, beginScopeRetainedOwnerDrive as G, createSandboxToolPartState as Gi, ReservationWaitRefused as Gn, runWorktreeHarness as Gr, peerMailTools as Gt, restoreScopeOwnerAcceptedExecution as H, readSandboxOutcome as Hi, workerTraceAnalysisStore as Hn, sanitizeKnowledgeReadinessReport as Hr, claimsAuthority as Ht, deriveNodeExecutionIdentity as I, unknownMaterializationReceipt as Ii, readCommittedJsonLines as In, padSpanId as Ir, createActivityLog as It, consumeScopeRetainedOwnerResult as J, isSandboxTerminalEvent as Ji, meterUsageEvent as Jn, removeWorktree as Jr, isTerminalNodeStatus as Jt, bindScopeRetainedOwnerEnvironmentId as K, createSandboxUsageLedger as Ki, assertValidBudget as Kn, captureWorktreeDiff as Kr, peerMailVerbNames as Kt, meterRuntimeOwnedAccounting as L, executableAgentProfileSnapshot as Li, writeAllBytes as Ln, padTraceId as Lr, readWorkerProgress as Lt, SUBTREE_RESULT_LIMIT as M, runtimeOwnedExecutorProviderEvidence as Mi, materializeTreeView as Mn, createOtelExporter as Mr, workerTraceHeaders as Mt, assertRecursiveReservationPolicy as N, runtimeOwnedPendingExecutorMaterialization as Ni, replaySpawnTree as Nn, flatOtelSpan as Nr, workerTraceSeamKey as Nt, driverChild as O, recordRuntimeOwnedDriveHarnessProviderEvidence as Oi, InMemoryResultBlobStore as On, buildLoopOtelSpans as Or, createInPlaceCliExecutor as Ot, beginScopeOwnerAttempt as P, runtimeOwnedScopeOwnerRuntime as Pi, isNoEntError as Pn, generateSpanId as Pr, taskToPrompt as Pt, scopeRetainedOwnerContext as Q, sandboxEventServedBackend as Qi, bridgeRuntimeAttachmentsKey as Qn, harnessSupportsReasoningEffort as Qr, createCodexRolloutStoreReader as Qt, meterRuntimeOwnedProviderAttempt as R, executableAgentSpecSnapshot as Ri, WORKER_TOOL_TRACE_SCHEMA_VERSION as Rn, toOtelAttributes as Rr, createInbox as Rt, createContinuationKeeper as S, finalizeRuntimeOwnedPendingExecutor as Si, decodeToolPart as Sn, mergeTraceEnv as Sr, createExecutorRegistry as St, failedItems as T, knownMaterializationReceipt as Ti, retainedExecutorSeamKey as Tn, defaultRedactor as Tr, DEFAULT_SANDBOX_STEERING_MAX_TURNS as Tt, scopeOwnerExecutorNodeContext as U, assertSandboxServedModel as Ui, executorFailure as Un, sanitizeRuntimeStreamEvent as Ur, createPeerMailbox as Ut, recordScopeOwnerPause as V, projectSandboxOutcome as Vi, parseWorkerToolTraceArtifact as Vn, sanitizeAgentRuntimeEvent as Vr, PEER_MAIL_WIRE_KEY as Vt, settledToIteration as W, canonicalStreamEventFromSandboxEvent as Wi, BudgetReconcileFault as Wn, runSettledCommand as Wr, isPeerMailEnvelope as Wt, prepareScopeRetainedOwnerTask as X, mapSandboxToolEvent as Xi, spendFromUsageEvents as Xn, LOCAL_HARNESSES as Xr, bridgeModelRouteRefusal as Xt, noteScopeRetainedOwnerCoordination as Y, mapSandboxEvent as Yi, newUsageTotals as Yn, DEFAULT_LOCAL_HARNESS as Yr, bridgeAdmissionRefusal as Yt, reconcileScopeRetainedOwnerEnvironment as Z, notifySandboxEventObserver as Zi, spendFromUsageTotals as Zn, harnessInvocation as Zr, addHarnessUsage as Zt, CheckUnavailableError as _, validateProfileMaterialization as _i, providerAsSandboxClient as _n, readHarnessTranscript as _r, bindReusableExecutorExecutionId as _t, collectDelivered as a, promptOptionsFromAgentTurnInput as aa, controlProfileMaterialization as ai, runAgentRounds as an, retainedCreateMaterial as ar, environmentReader as at, bestComposite as b, attestRuntimeOwnedScopeOwner as bi, unavailableSignalOfFailure as bn, contentAddress as br, cliWorktreeExecutor as bt, runTree as c, profileMaterializationAxes$1 as ci, SandboxEvidenceRetentionError as cn, createWorkerSlots as cr, interactiveAdmissionSeamKey as ct, classifyDriverFailure as d, promptOnlyProfileMaterialization as di, readPromptOptions as dn, abortError as dr, reconnectRetainedInteractiveRun as dt, sumSandboxUsage as ea, parseCodexTokenUsage as ei, readCodexRolloutSession as en, errMessage as er, scopeRetainedOwnerResourceReader as et, runDriverWithRetry as f, promptResourceProfileMaterialization as fi, routerBrain as fn, linkAbort as fr, recoverRetainedInteractiveRun as ft, CONTINUATION_FACTS as g, unsupportedProfileDimensions as gi, providerAsExecutor as gn, persistHarnessTranscript as gr, rollingDispatch as gt, CONTINUATIONS_DIR as h, sandboxActProfileMaterialization as hi, createAgentEnvironmentProviderRegistry as hn, harnessTranscriptArtifact as hr, queueOf as ht, bestDelivered as i, promptFromAgentTurnInput as ia, assertProfileMaterialization as ii, isTerminalDecision as in, startRetainedRunInEnvironment as ir, SPAWN_RESOURCE_PATH_MAX_BYTES as it, withDriverExecutor as j, runtimeOwnedExecutorMaterialization as ji, loadSpawnForest as jn, createOpenInferenceFileExporter as jr, workerTraceEnv as jt, driverExecutorFactory as k, runtimeOwnedDriveHarnessProviderEvidence as ki, InMemorySpawnJournal as kn, buildLoopSpanNodes as kr, WORKER_TRACE_PROPAGATION as kt, DriverAttemptsExhaustedError as l, promptControlProfileMaterialization as li, captureBeforeDestroy as ln, openSlotGroup as lr, attachWorker as lt, upstreamUnavailableSignal as m, renderUnsupported as mi, LEAF_CONTINUATION_TASK as mn, captureHarnessTranscript as mr, freeSlots as mt, createRootHandle as n, abortError$1 as na, terminateProcessTreeAndConfirm as ni, createSandboxForSpec as nn, recoverRetainedRun as nr, scopeRetainedOwnerResult as nt, pickBestDelivered as o, providerMessageText as oa, defineProfileMaterializationContract as oi, createSandboxLineage as on, destroyInteractiveEnvironment as or, hostDirectoryReader as ot, summarizeDriverAttempts as p, renderProfileMaterializationIssues as pi, runBrainLoop as pn, runAbortable as pr, startRetainedInteractiveRun as pt, bindScopeRetainedOwnerProvider as q, extractLlmCallEvent as qi, createBudgetPool as qn, createWorktree as qr, isLiveNodeStatus as qt, createSupervisor as r, awaitAbortable$1 as ra, AGENT_PROFILE_MATERIALIZATION_AXES as ri, defaultSelectWinner as rn, startRetainedRun as rr, scopeRetainedOwnerTurnEnded as rt, runFinalizer as s, fullProfileMaterialization as si, acquireSandbox as sn, environmentGone as sr, resolveSpawnResourcePaths as st, DEFAULT_MAX_DEPTH as t, decodeHarnessUsage as ta, CodexExecutionDiagnosticError as ti, TERMINAL_DECISIONS as tn, reconnectRetainedRun as tr, scopeRetainedOwnerRestorePoint as tt, HarnessTurnFailedError as u, promptModelProfileMaterialization as ui, assertBoxlessPromptOptions as un, RunCancellationReason as ur, readWorkerInteractiveBinding as ut, admitContinuationPolicy as v, worktreeCliProfileMaterialization as vi, resolveAgentEnvironmentProvider as vn, resolveHarnessTranscriptCapture as vr, captureReusableExecutorConfig as vt, expandQuestions as w, knownExecutionBindingReceipt as wi, registerRetainedExecutorPreparation as wn, traceContextToEnv as wr, createWorktreeCliExecutor as wt, checkVerdictOf as x, authoredProfileDigest as xi, createPushTraceSource as xn, createPropagatingTraceEmitter as xr, createExecutor as xt, admitFinding as y, attestRuntimeOwnedPendingExecutor as yi, unavailablePauseMs as yn, retainHarnessTranscript as yr, cliInPlaceExecutor as yt, recordScopeOwnerDriverAttempt as z, detachedFrozen as zi, captureWorkerTraceEvidence as zn, createRuntimeEventCollector as zr, AUTHORITY_MARKERS as zt };
29701
28782
 
29702
- //# sourceMappingURL=supervisor-DA_nvF-h.js.map
28783
+ //# sourceMappingURL=supervisor-DYKPbcZa.js.map