@tangle-network/agent-runtime 0.306.1 → 0.307.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 (68) hide show
  1. package/dist/{activation-wZ-8vOjV.d.ts → activation-Bdugb7li.d.ts} +3 -3
  2. package/dist/{activation-C5wesfzd.js → activation-DNZrAzZM.js} +3 -3
  3. package/dist/{activation-C5wesfzd.js.map → activation-DNZrAzZM.js.map} +1 -1
  4. package/dist/agent.d.ts +2 -2
  5. package/dist/agent.js +2 -2
  6. package/dist/{bundle-C8EO05u3.js → bundle-E6mbRX2P.js} +2 -2
  7. package/dist/{bundle-C8EO05u3.js.map → bundle-E6mbRX2P.js.map} +1 -1
  8. package/dist/candidate-execution/index.js +5 -5
  9. package/dist/{coordination-driver-yj9HPXef.js → coordination-driver-DCQUXZ54.js} +3 -3
  10. package/dist/{coordination-driver-yj9HPXef.js.map → coordination-driver-DCQUXZ54.js.map} +1 -1
  11. package/dist/{delegate-KtrL9HWq.js → delegate-BcMmgX_Y.js} +2 -2
  12. package/dist/{delegate-KtrL9HWq.js.map → delegate-BcMmgX_Y.js.map} +1 -1
  13. package/dist/durable.d.ts +2 -2
  14. package/dist/durable.js +57 -6
  15. package/dist/durable.js.map +1 -1
  16. package/dist/{graph-DcdyHbgf.js → graph-D2yO7Epi.js} +5 -4
  17. package/dist/graph-D2yO7Epi.js.map +1 -0
  18. package/dist/{improvement-cycle-DsN-TVXR.js → improvement-cycle-C6PDngmf.js} +10 -6
  19. package/dist/{improvement-cycle-DsN-TVXR.js.map → improvement-cycle-C6PDngmf.js.map} +1 -1
  20. package/dist/{index-DflDZq_I.d.ts → index-1T1fjIUs.d.ts} +72 -6
  21. package/dist/index.d.ts +6 -6
  22. package/dist/index.js +9 -9
  23. package/dist/intelligence.d.ts +3 -3
  24. package/dist/intelligence.js +7 -7
  25. package/dist/kernel.d.ts +4 -4
  26. package/dist/kernel.js +8 -8
  27. package/dist/{loop-runner-bin-DZfRUVWy.d.ts → loop-runner-bin-Be2jWumB.d.ts} +3 -3
  28. package/dist/{loop-runner-bin-rVrSX5l1.js → loop-runner-bin-Bwxtx1go.js} +3 -3
  29. package/dist/{loop-runner-bin-rVrSX5l1.js.map → loop-runner-bin-Bwxtx1go.js.map} +1 -1
  30. package/dist/loop-runner-bin.d.ts +1 -1
  31. package/dist/loop-runner-bin.js +1 -1
  32. package/dist/mcp/bin.js +3 -3
  33. package/dist/mcp/index.d.ts +5 -5
  34. package/dist/mcp/index.js +5 -5
  35. package/dist/{openai-tools-YO30D2s3.d.ts → openai-tools-C-lvIN3-.d.ts} +2 -2
  36. package/dist/{prepare--nWcazPr.js → prepare-CulUz6Wm.js} +3 -3
  37. package/dist/{prepare--nWcazPr.js.map → prepare-CulUz6Wm.js.map} +1 -1
  38. package/dist/{profile-h04LDjV6.js → profile-DY9lT3gH.js} +2 -2
  39. package/dist/{profile-h04LDjV6.js.map → profile-DY9lT3gH.js.map} +1 -1
  40. package/dist/profiles.d.ts +1 -1
  41. package/dist/{protected-model-port-wwalbyXM.js → protected-model-port-BT2iYAsU.js} +4 -4
  42. package/dist/{protected-model-port-wwalbyXM.js.map → protected-model-port-BT2iYAsU.js.map} +1 -1
  43. package/dist/{provision-supervisor-WxFEFQeJ.js → provision-supervisor-De_3kjM3.js} +4 -4
  44. package/dist/{provision-supervisor-WxFEFQeJ.js.map → provision-supervisor-De_3kjM3.js.map} +1 -1
  45. package/dist/{runtime-B9eBIyws.js → runtime-B3dR7tdY.js} +9 -9
  46. package/dist/{runtime-B9eBIyws.js.map → runtime-B3dR7tdY.js.map} +1 -1
  47. package/dist/{search-executor-2tWr38Qw.js → search-executor-H1IRkoRg.js} +3 -3
  48. package/dist/{search-executor-2tWr38Qw.js.map → search-executor-H1IRkoRg.js.map} +1 -1
  49. package/dist/{server-CpKcrOPj.js → server-DATtZ0Q9.js} +4 -4
  50. package/dist/{server-CpKcrOPj.js.map → server-DATtZ0Q9.js.map} +1 -1
  51. package/dist/{stream-agent-turn-B1giFgOg.d.ts → stream-agent-turn-Ch1g6gYE.d.ts} +2 -2
  52. package/dist/{substrate-L_sC7jCD.d.ts → substrate-Buuxd_OX.d.ts} +2 -2
  53. package/dist/{supervise-DllOHM4M.js → supervise-D1qqMFAu.js} +164 -191
  54. package/dist/supervise-D1qqMFAu.js.map +1 -0
  55. package/dist/{supervisor-gCfG6K1-.js → supervisor-Dz4XXtK1.js} +1734 -1114
  56. package/dist/supervisor-Dz4XXtK1.js.map +1 -0
  57. package/dist/testing.d.ts +2 -2
  58. package/dist/testing.js +14 -14
  59. package/dist/tui/index.d.ts +1 -1
  60. package/dist/tui/index.js +1 -1
  61. package/dist/{types-DeuEkBhI.d.ts → types-CBcc0_5y.d.ts} +48 -1
  62. package/dist/{workspace-streams-ILw0eWZ0.js → workspace-streams-DaQceg2p.js} +7 -2
  63. package/dist/{workspace-streams-ILw0eWZ0.js.map → workspace-streams-DaQceg2p.js.map} +1 -1
  64. package/package.json +3 -3
  65. package/skills/profile-authoring/SKILL.md +6 -0
  66. package/dist/graph-DcdyHbgf.js.map +0 -1
  67. package/dist/supervise-DllOHM4M.js.map +0 -1
  68. package/dist/supervisor-gCfG6K1-.js.map +0 -1
@@ -1,5 +1,5 @@
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-ILw0eWZ0.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, St as teardownSurfaces, 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";
3
3
  import { runTaskQueue } from "./task-queue.js";
4
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";
5
5
  import { n as assertNoSymlinkDescendant, r as publishExclusiveDurableFile } from "./durable-file-DWQA4ooo.js";
@@ -380,6 +380,29 @@ const decodeCodexTurnUsage = (event) => {
380
380
  ...record.cacheWriteInputTokens === void 0 ? {} : { cacheWriteInput: record.cacheWriteInputTokens }
381
381
  };
382
382
  };
383
+ /** Claude's adapter forwards one delta per response snapshot, keyed and deduplicated there. */
384
+ const decodeClaudeAssistantUsage = (event) => {
385
+ if (String(event.type ?? "") !== "raw") return void 0;
386
+ const envelope = plainRecord$2(event.data);
387
+ const data = envelope?.type === "raw" && plainRecord$2(envelope.event) !== void 0 ? plainRecord$2(envelope.event) : envelope;
388
+ if (data?.type !== "assistant.usage") return void 0;
389
+ if (typeof data.message_id !== "string" || data.message_id.length === 0) throw new ValidationError$1("claude assistant.usage: missing response identity");
390
+ const usage = plainRecord$2(data.usage);
391
+ if (!usage) throw new ValidationError$1("claude assistant.usage: usage must be an object");
392
+ const fresh = naturalNumber$1(usage.input_tokens, "input_tokens", "claude assistant.usage");
393
+ const cachedInput = naturalNumber$1(usage.cache_read_input_tokens, "cache_read_input_tokens", "claude assistant.usage");
394
+ const cacheWriteInput = naturalNumber$1(usage.cache_creation_input_tokens, "cache_creation_input_tokens", "claude assistant.usage");
395
+ const output = naturalNumber$1(usage.output_tokens, "output_tokens", "claude assistant.usage");
396
+ const input = fresh + cachedInput + cacheWriteInput;
397
+ if (!Number.isSafeInteger(input)) throw new ValidationError$1("claude assistant.usage: total input tokens exceed a safe integer");
398
+ return {
399
+ harness: "claude-code",
400
+ input,
401
+ output,
402
+ cachedInput,
403
+ cacheWriteInput
404
+ };
405
+ };
383
406
  /**
384
407
  * The harness → usage-decoder registry. Add a harness by adding one entry.
385
408
  *
@@ -387,7 +410,10 @@ const decodeCodexTurnUsage = (event) => {
387
410
  * can produce does not compile. A harness absent from this registry reports usage through the
388
411
  * canonical events or not at all.
389
412
  */
390
- const harnessUsageDecoders = { codex: decodeCodexTurnUsage };
413
+ const harnessUsageDecoders = {
414
+ codex: decodeCodexTurnUsage,
415
+ "claude-code": decodeClaudeAssistantUsage
416
+ };
391
417
  /**
392
418
  * Decode a sandbox event with one harness's adapter, or `undefined` when the event carries no
393
419
  * harness-native usage.
@@ -6635,6 +6661,30 @@ async function captureProviderCheckpointWorkspace(port, context, marker) {
6635
6661
  clearDeadline();
6636
6662
  }
6637
6663
  }
6664
+ /** Verify a running workspace copy before treating it as retained evidence. */
6665
+ async function captureProviderLiveWorkspace(port, context) {
6666
+ assertProviderWorkspaceRetentionPort(port, "provider workspace retention");
6667
+ if (port.captureLive === void 0) throw new ValidationError$1("provider workspace retention: the port has no captureLive");
6668
+ const timeoutMs = port.liveTimeoutMs ?? port.timeoutMs;
6669
+ const controller = new AbortController();
6670
+ const clearDeadline = armDeadlineTimer(timeoutMs, () => controller.abort(/* @__PURE__ */ new Error(`live workspace capture timed out after ${timeoutMs}ms`)), true);
6671
+ try {
6672
+ return await runAbortable(() => withCaptureSlot(checkpointSlots(port), controller.signal, async () => {
6673
+ const tree = detachedSnapshot(await port.captureLive({
6674
+ ...context,
6675
+ signal: controller.signal
6676
+ }), "live workspace capture tree");
6677
+ if (tree?.kind !== "agent-candidate-workspace-tree") throw new Error("live workspace capture returned no workspace tree");
6678
+ if ((await verifyAgentCandidateWorkspaceTree(tree, port.artifacts, {
6679
+ ...port.limits === void 0 ? {} : { limits: port.limits },
6680
+ signal: controller.signal
6681
+ })).files.length !== tree.files) throw new Error("live workspace capture tree misstates its file count");
6682
+ return tree;
6683
+ }), controller.signal, `live workspace capture timed out after ${timeoutMs}ms`);
6684
+ } finally {
6685
+ clearDeadline();
6686
+ }
6687
+ }
6638
6688
  /** Validate the executable retention port at the create boundary. */
6639
6689
  function assertProviderWorkspaceRetentionPort(port, context) {
6640
6690
  if (!Number.isSafeInteger(port.timeoutMs) || port.timeoutMs <= 0) throw new ValidationError$1(`${context}: workspaceRetention.timeoutMs must be a positive safe integer`);
@@ -6643,7 +6693,14 @@ function assertProviderWorkspaceRetentionPort(port, context) {
6643
6693
  if (typeof port.capture !== "function") throw new ValidationError$1(`${context}: workspaceRetention.capture is required`);
6644
6694
  if (port.captureNative !== void 0 && typeof port.captureNative !== "function") throw new ValidationError$1(`${context}: workspaceRetention.captureNative must be a function`);
6645
6695
  if (port.captureCheckpoint !== void 0 && typeof port.captureCheckpoint !== "function") throw new ValidationError$1(`${context}: workspaceRetention.captureCheckpoint must be a function`);
6646
- for (const key of ["nativeIntervalMs", "nativeTimeoutMs"]) {
6696
+ if (port.captureLive !== void 0 && typeof port.captureLive !== "function") throw new ValidationError$1(`${context}: workspaceRetention.captureLive must be a function`);
6697
+ if (port.liveIntervalMs !== void 0 && port.captureLive === void 0) throw new ValidationError$1(`${context}: workspaceRetention.liveIntervalMs requires captureLive`);
6698
+ for (const key of [
6699
+ "nativeIntervalMs",
6700
+ "nativeTimeoutMs",
6701
+ "liveIntervalMs",
6702
+ "liveTimeoutMs"
6703
+ ]) {
6647
6704
  const value = port[key];
6648
6705
  if (value !== void 0 && (!Number.isSafeInteger(value) || value <= 0)) throw new ValidationError$1(`${context}: workspaceRetention.${key} must be a positive safe integer`);
6649
6706
  }
@@ -9694,6 +9751,9 @@ var SpawnEventIndex = class {
9694
9751
  if (node?.materialized) throw new Error(`spawn journal corrupted: duplicate materialization receipt for node '${event.id}' in tree '${this.root}'`);
9695
9752
  if (!node?.spawned) throw new Error(`spawn journal corrupted: materialization for node '${event.id}' precedes its spawn in tree '${this.root}'`);
9696
9753
  }
9754
+ if (event.kind === "seat-materialized") {
9755
+ if (!node?.materialized || node.authoredProfileDigest === void 0 || event.receipt.status !== "known" || event.receipt.authoredProfileDigest !== node.authoredProfileDigest || !Number.isSafeInteger(event.segmentIndex) || event.segmentIndex <= node.latestSeatMaterialization) throw new Error(`spawn journal corrupted: invalid seat materialization for node '${event.id}' in tree '${this.root}'`);
9756
+ }
9697
9757
  if (event.kind === "execution-bound") {
9698
9758
  if (node?.bindings.has(event.binding.attemptId)) throw new Error(`spawn journal corrupted: duplicate execution binding for node '${event.id}' attempt '${event.binding.attemptId}' in tree '${this.root}'`);
9699
9759
  if (!node?.materialized) throw new Error(`spawn journal corrupted: execution binding for node '${event.id}' precedes materialization in tree '${this.root}'`);
@@ -9703,29 +9763,37 @@ var SpawnEventIndex = class {
9703
9763
  /** Called only after validation and, for the file writer, a successful durable append. */
9704
9764
  add(event) {
9705
9765
  if (!outsideCursorNamespace(event)) this.cursors.add(event.seq);
9706
- if (event.kind !== "spawned" && event.kind !== "materialized" && event.kind !== "execution-bound" && event.kind !== "execution-input" && event.kind !== "execution-admitted" && event.kind !== "execution-result" && event.kind !== "environment-teardown" && !closesCursorSlot(event)) return;
9766
+ if (event.kind !== "spawned" && event.kind !== "materialized" && event.kind !== "seat-materialized" && event.kind !== "execution-bound" && event.kind !== "execution-input" && event.kind !== "execution-admitted" && event.kind !== "execution-result" && event.kind !== "environment-teardown" && event.kind !== "environment-terminal" && !closesCursorSlot(event)) return;
9707
9767
  let node = this.nodes.get(event.id);
9708
9768
  if (!node) {
9709
9769
  node = {
9710
9770
  spawned: false,
9711
9771
  closed: false,
9712
9772
  materialized: false,
9773
+ latestSeatMaterialization: 0,
9713
9774
  bindings: /* @__PURE__ */ new Set(),
9714
9775
  inputs: /* @__PURE__ */ new Set(),
9715
9776
  input: false,
9716
9777
  result: false,
9717
9778
  admissions: /* @__PURE__ */ new Map(),
9718
- destroyedEnvironments: /* @__PURE__ */ new Set()
9779
+ unusableEnvironments: /* @__PURE__ */ new Set()
9719
9780
  };
9720
9781
  this.nodes.set(event.id, node);
9721
9782
  }
9722
9783
  if (event.kind === "environment-teardown") {
9723
- if (event.destroyed) node.destroyedEnvironments.add(event.environmentId);
9784
+ if (event.destroyed) node.unusableEnvironments.add(event.environmentId);
9785
+ return;
9786
+ }
9787
+ if (event.kind === "environment-terminal") {
9788
+ node.unusableEnvironments.add(event.environmentId);
9724
9789
  return;
9725
9790
  }
9726
9791
  if (event.kind === "execution-admitted" && event.admission.phase === "environment") node.lastEnvironmentId = event.admission.environmentId;
9727
9792
  if (event.kind === "spawned") node.spawned = true;
9728
- else if (event.kind === "materialized") node.materialized = true;
9793
+ else if (event.kind === "materialized") {
9794
+ node.materialized = true;
9795
+ node.authoredProfileDigest = event.receipt.authoredProfileDigest;
9796
+ } else if (event.kind === "seat-materialized") node.latestSeatMaterialization = event.segmentIndex;
9729
9797
  else if (event.kind === "execution-bound") node.bindings.add(event.binding.attemptId);
9730
9798
  else if (event.kind === "execution-input") {
9731
9799
  node.inputs.add(event.seq);
@@ -9748,7 +9816,7 @@ var SpawnEventIndex = class {
9748
9816
  if (node.inputs.has(event.seq)) fail("has duplicate input sequence");
9749
9817
  const environment = node.admissions.get("environment");
9750
9818
  const ranIn = environment?.phase === "environment" ? environment.environmentId : node.lastEnvironmentId;
9751
- const abandoned = ranIn !== void 0 && node.destroyedEnvironments.has(ranIn);
9819
+ const abandoned = ranIn !== void 0 && node.unusableEnvironments.has(ranIn);
9752
9820
  if (node.input && !node.result && !abandoned) fail("input replaces an unfinished invocation");
9753
9821
  return;
9754
9822
  }
@@ -9810,6 +9878,7 @@ const outsideKinds = /* @__PURE__ */ new Set([
9810
9878
  "teardown-pending",
9811
9879
  "teardown-confirmed",
9812
9880
  "environment-teardown",
9881
+ "environment-terminal",
9813
9882
  "workspace-checkpoint-requested",
9814
9883
  "workspace-checkpoint",
9815
9884
  "workspace-checkpoint-fork-requested",
@@ -9819,6 +9888,9 @@ const outsideKinds = /* @__PURE__ */ new Set([
9819
9888
  "workspace-restored",
9820
9889
  "workspace-capture",
9821
9890
  "trace-unpropagated",
9891
+ "seat-segment",
9892
+ "seat-materialized",
9893
+ "seat-paused",
9822
9894
  "paused",
9823
9895
  "driver-attempt",
9824
9896
  "node-inputs-resolved",
@@ -9889,6 +9961,7 @@ async function replaySpawnTree(journal, blobs, root) {
9889
9961
  if (ev.kind === "teardown-unconfirmed") continue;
9890
9962
  if (ev.kind === "teardown-pending" || ev.kind === "teardown-confirmed") continue;
9891
9963
  if (ev.kind === "environment-teardown") continue;
9964
+ if (ev.kind === "environment-terminal") continue;
9892
9965
  if (ev.kind === "workspace-checkpoint-requested") continue;
9893
9966
  if (ev.kind === "workspace-checkpoint") continue;
9894
9967
  if (ev.kind === "workspace-checkpoint-fork-requested") continue;
@@ -9898,6 +9971,7 @@ async function replaySpawnTree(journal, blobs, root) {
9898
9971
  if (ev.kind === "workspace-restored") continue;
9899
9972
  if (ev.kind === "workspace-capture") continue;
9900
9973
  if (ev.kind === "trace-unpropagated") continue;
9974
+ if (ev.kind === "seat-segment" || ev.kind === "seat-materialized" || ev.kind === "seat-paused") continue;
9901
9975
  if (ev.kind === "paused") continue;
9902
9976
  if (ev.kind === "driver-attempt") continue;
9903
9977
  if (ev.kind === "node-inputs-resolved") continue;
@@ -10049,7 +10123,7 @@ function materializeTreeView(events) {
10049
10123
  if (Number.isFinite(settledAt)) node.settledAt = settledAt;
10050
10124
  }
10051
10125
  for (const ev of events) {
10052
- if (ev.kind !== "materialized") continue;
10126
+ if (ev.kind !== "materialized" && ev.kind !== "seat-materialized") continue;
10053
10127
  const node = requireNode(nodes, ev.id);
10054
10128
  node.materialization = ev.receipt;
10055
10129
  node.runtime = ev.receipt.runtime;
@@ -10930,6 +11004,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
10930
11004
  if (workspaceSnapshot !== void 0) return workspaceSnapshot;
10931
11005
  if (workspaceCapturePromise === void 0) {
10932
11006
  workspaceOutcome = outcome;
11007
+ stopLiveMirror();
10933
11008
  if (nativeTimer !== void 0) clearTimeout(nativeTimer);
10934
11009
  nativeTimer = void 0;
10935
11010
  const captureContext = {
@@ -10945,7 +11020,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
10945
11020
  const reportTiming = retention?.onWorkspaceCapture;
10946
11021
  let timing;
10947
11022
  const capturedExecutionId = workspaceExecutionId;
10948
- workspaceCapturePromise = (nativeInFlight ?? Promise.resolve()).then(() => captureProviderWorkspaceSnapshot(workspaceRetention, captureContext, "environment", reportTiming === void 0 ? void 0 : (measured) => {
11023
+ workspaceCapturePromise = Promise.all([nativeInFlight, liveInFlight]).then(() => captureProviderWorkspaceSnapshot(workspaceRetention, captureContext, "environment", reportTiming === void 0 ? void 0 : (measured) => {
10949
11024
  timing = measured;
10950
11025
  })).finally(async () => {
10951
11026
  if (timing === void 0 || reportTiming === void 0) return;
@@ -10998,6 +11073,38 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
10998
11073
  const nativePort = options.workspaceRetention?.captureNative === void 0 ? void 0 : options.workspaceRetention;
10999
11074
  let nativeInFlight;
11000
11075
  let nativeTimer;
11076
+ const livePort = options.workspaceRetention?.captureLive === void 0 ? void 0 : options.workspaceRetention;
11077
+ let liveInFlight;
11078
+ let liveTimer;
11079
+ const stopLiveMirror = () => {
11080
+ if (liveTimer !== void 0) clearTimeout(liveTimer);
11081
+ liveTimer = void 0;
11082
+ };
11083
+ const startLiveMirror = (next) => {
11084
+ if (livePort?.liveIntervalMs === void 0) return;
11085
+ stopLiveMirror();
11086
+ const schedule = () => {
11087
+ liveTimer = setTimeout(() => {
11088
+ if (liveInFlight === void 0 && workspaceCapturePromise === void 0) {
11089
+ const tracked = captureProviderLiveWorkspace(livePort, {
11090
+ environment: next,
11091
+ executionId: workspaceExecutionId,
11092
+ ...workspaceControlRef === void 0 ? {} : { controlRef: workspaceControlRef },
11093
+ ...node === void 0 ? {} : { node },
11094
+ providerSessionId,
11095
+ nativeSessionId: null,
11096
+ profile: createProfile
11097
+ }).then(() => void 0, () => void 0).finally(() => {
11098
+ if (liveInFlight === tracked) liveInFlight = void 0;
11099
+ });
11100
+ liveInFlight = tracked;
11101
+ }
11102
+ schedule();
11103
+ }, livePort.liveIntervalMs);
11104
+ liveTimer.unref?.();
11105
+ };
11106
+ schedule();
11107
+ };
11001
11108
  let nativeHoldsTranscript = false;
11002
11109
  const stopNativeMirror = async () => {
11003
11110
  if (nativeTimer !== void 0) clearTimeout(nativeTimer);
@@ -11052,6 +11159,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
11052
11159
  return tracked;
11053
11160
  };
11054
11161
  const startNativeMirror = (next) => {
11162
+ startLiveMirror(next);
11055
11163
  if (nativePort === void 0) return;
11056
11164
  if (nativeTimer !== void 0) clearTimeout(nativeTimer);
11057
11165
  const interval = nativePort.nativeIntervalMs ?? 12e4;
@@ -11699,6 +11807,7 @@ async function* streamProviderExecutor(args) {
11699
11807
  handCaptureToOwner(settledResult, outcome, true);
11700
11808
  }
11701
11809
  } catch (error) {
11810
+ yield* creditUsage(usageLedger.settleTurn(args.profile.name ?? "agent"));
11702
11811
  failure = source.retained ? new RetainedExecutionPendingError(error) : error;
11703
11812
  failed = true;
11704
11813
  if (args.options.workspaceRetention !== void 0) args.onUnsettledFailure();
@@ -20886,487 +20995,1134 @@ function singleShotDriver(maxIterations) {
20886
20995
  };
20887
20996
  }
20888
20997
  //#endregion
20889
- //#region src/runtime/supervise/dispatch.ts
20998
+ //#region src/runtime/supervise/continuation.ts
20890
20999
  /**
21000
+ * The continuation: what a manager with a completion check is told when its turn ends and the
21001
+ * check is unmet, and the one rule that decides whether it is sent back.
20891
21002
  *
20892
- * `rollingDispatch` — the REFILLING dispatch policy over a `Scope`. It keeps `width` children in
20893
- * flight and admits the next queued unit of work the instant one settles, instead of waiting for
20894
- * a whole round to drain (`fanout`) or for a driver to decide again (`spawn → await → spawn`).
20895
- *
20896
- * The gap it closes: `fanout` opens every item at once and then drains — one round, no refill —
20897
- * and a driver brain's manual loop opens one worker per model turn. Between those two there was
20898
- * nothing that holds N slots full, which is why a 5-worker run can peak at 2 live workers and sit
20899
- * ~50% idle. This is a policy over the EXISTING `Scope.spawn` / `Scope.next` primitives: it adds
20900
- * no second admission path, so the conserved budget pool stays the only fence on total work and
20901
- * `width` is only a fence on simultaneous work.
20902
- *
20903
- * Fail-closed by construction: an admission rejection (`budget-exhausted` / `depth-exceeded`) is
20904
- * recorded and STOPS further admission — the loop then drains what is already live and returns.
20905
- * It never retries a rejected spawn against the same pool, and it never spawns past `width`.
20906
- *
20907
- * ── Concurrency ────────────────────────────────────────────────────────────────────────────────
20908
- *
20909
- * `width` bounds the children THIS dispatcher holds in flight. The tree-wide bound on working
20910
- * agents is `SuperviseOptions.workerSlots` (`./worker-slots`): a spawn past it is queued by the
20911
- * scope, not refused, so a `width` above the free slots only lengthens the allocator's queue.
20912
- * `SandboxLineage`'s fork concurrency bounds boxes inside ONE leaf's fork wave, a different unit.
21003
+ * Measured on discovery-lab before this module (2026-09-24, 670 settled runs, 1,596 re-entries):
21004
+ * 1,565 re-entries followed a failed turn and resent the original task, and 31 carried note text.
21005
+ * The note Runtime wrote itself held seven fixed lines and no field for the check's verdict. Of 40
21006
+ * episodes where the director ended on its own and the outside check disagreed, 33 were told
21007
+ * nothing before they ended. 100 of 236 resubmits sent the identical packet. So the director
21008
+ * mostly graded itself, and when it was wrong it heard nothing it could use.
20913
21009
  *
20914
- * ── Why this is not a copy of the kernel's batch loop ──────────────────────────────────────────
21010
+ * The design (discovery `docs/38-one-loop-and-continuation.md`) makes three things single, and
21011
+ * this module holds the part Runtime owns:
20915
21012
  *
20916
- * `runBatch` (`src/runtime/run-loop.ts`) runs the same hold-N-slots-full shape over the KERNEL's
20917
- * substrate: bare promises in a `Set`, raced with `Promise.race`, bounded by `maxConcurrency`.
20918
- * This one runs it over the SUPERVISOR's substrate — `Scope.spawn`'s atomic reservation against
20919
- * the conserved pool, `Scope.next`'s journaled settlement cursor, and the blob store behind each
20920
- * result. Neither can be expressed in the other's terms without dragging its whole substrate
20921
- * along: the kernel loop has no budget to reserve and no cursor to order settlements by, and this
20922
- * one cannot race raw promises because a settlement is only real once it is journaled. The shape
20923
- * repeating across the two deliberate layers is resonance, not duplication — do not "unify" them
20924
- * into a shared helper that would have to know about both.
21013
+ * - ONE CHECK. A check reading is a {@link CheckVerdict}: pass, the items it read, the composite,
21014
+ * and one `FAIL <item> <where>: <reason>` line per failed item. The same check decides
21015
+ * `submit_result`, runs when a turn ends without an accepted result, scores the finished run,
21016
+ * and ranks versions. A check that could not run gives no verdict ({@link CheckUnavailableError}),
21017
+ * and the loop pauses instead of blaming the director.
21018
+ * - ONE RESEND RULE. {@link ContinuationPolicy} is required for a manager with a check. It holds a
21019
+ * deadline and `maxBarren`, the re-entered turns in a row that may end without progress. There
21020
+ * is no re-prompt count and no default: a retry default in source is a research decision.
21021
+ * - ONE NOTE. {@link composeContinuationNote} writes it. Runtime owns the facts and their order;
21022
+ * the {@link ContinuationProfile} owns every instruction word, so an optimizer can change the
21023
+ * words without touching code. A play may append a section, never remove or rewrite one.
20925
21024
  *
20926
- * @experimental
21025
+ * Evidence behind the note's shape: located errors help (given the first mistake's true location,
21026
+ * fix rates rose 23.5 to 43.9 points, Tyen 2023); unsupported pressure does not (threats and tips
21027
+ * had no significant effect, Wharton 2025; challenges without evidence flipped correct answers,
21028
+ * FlipFlop); repeated summaries drop detail while itemized additions do not (ACE). So the note is
21029
+ * a list of located facts, findings are added and marked resolved rather than rewritten, and the
21030
+ * profile, not this file, decides how blunt the words are.
20927
21031
  */
20928
21032
  /**
20929
- * Run the refilling dispatch loop over `scope` until the queue is dry (or a stop fires) and every
20930
- * admitted child has settled. Returns the settlements in cursor order plus the admission ledger.
20931
- *
20932
- * The loop is: fill free slots from `nextUnit` → `await scope.next()` → deliver the settlement →
20933
- * refill → repeat. Because the refill happens immediately after each settlement rather than after
20934
- * a whole round, a slow child never idles the other slots.
21033
+ * The check could not run: its box did not start, its judge's provider refused, its program
21034
+ * crashed. It is not a verdict on the result. Inside a run the loop pauses, as it does for an
21035
+ * unavailable upstream, and the refusal tells the director its result was not judged.
20935
21036
  */
20936
- async function rollingDispatch(scope, opts) {
20937
- if (!Number.isInteger(opts.width) || opts.width < 1) throw new ValidationError$1(`rollingDispatch: width must be a positive integer, got ${String(opts.width)}`);
20938
- const settled = [];
20939
- const rejected = [];
20940
- const live = /* @__PURE__ */ new Set();
20941
- let admitted = 0;
20942
- let peakLive = 0;
20943
- let queueDry = false;
20944
- let stopReason = "drained";
20945
- const fill = async () => {
20946
- while (live.size < opts.width) {
20947
- if (queueDry) return;
20948
- if (scope.signal.aborted) {
20949
- stopReason = "aborted";
20950
- queueDry = true;
20951
- return;
20952
- }
20953
- if (opts.shouldStop?.() === true) {
20954
- stopReason = "stopped";
20955
- queueDry = true;
20956
- return;
20957
- }
20958
- const unit = await opts.nextUnit();
20959
- if (unit === void 0) {
20960
- queueDry = true;
20961
- return;
20962
- }
20963
- const res = scope.spawn(unit.agent, unit.task, unit.opts);
20964
- if (!res.ok) {
20965
- rejected.push(`${unit.opts.label}: ${res.reason}`);
20966
- stopReason = "not-admitted";
20967
- queueDry = true;
20968
- return;
20969
- }
20970
- live.add(res.handle.id);
20971
- admitted += 1;
20972
- if (live.size > peakLive) peakLive = live.size;
20973
- }
20974
- };
20975
- await fill();
20976
- while (live.size > 0) {
20977
- const s = await scope.next();
20978
- if (s === null) break;
20979
- live.delete(s.handle.id);
20980
- settled.push(s);
20981
- await opts.onSettled?.(s);
20982
- await fill();
21037
+ var CheckUnavailableError = class extends Error {
21038
+ constructor(message, options) {
21039
+ super(message, options);
21040
+ this.name = "CheckUnavailableError";
20983
21041
  }
20984
- return {
20985
- settled,
20986
- admitted,
20987
- rejected,
20988
- stopReason,
20989
- peakLive
20990
- };
21042
+ };
21043
+ /** Read a check function's return value into a verdict. Anything but `true` or a passing verdict
21044
+ * is a failure: a check fails closed. */
21045
+ function checkVerdictOf(outcome) {
21046
+ if (outcome === true) return { pass: true };
21047
+ if (typeof outcome !== "object" || outcome === null || Array.isArray(outcome)) return { pass: false };
21048
+ const raw = outcome;
21049
+ const items = typeof raw.items === "object" && raw.items !== null && !Array.isArray(raw.items) ? Object.fromEntries(Object.entries(raw.items).filter((entry) => typeof entry[1] === "number" && Number.isFinite(entry[1]))) : void 0;
21050
+ const failures = Array.isArray(raw.failures) ? raw.failures.filter((line) => typeof line === "string" && line.trim() !== "") : void 0;
21051
+ return Object.freeze({
21052
+ pass: raw.pass === true,
21053
+ ...items === void 0 ? {} : { items: Object.freeze(items) },
21054
+ ...finite(raw.composite) ? { composite: raw.composite } : {},
21055
+ ...finite(raw.threshold) ? { threshold: raw.threshold } : {},
21056
+ ...failures === void 0 ? {} : { failures: Object.freeze(failures) },
21057
+ ...typeof raw.review === "string" && raw.review.trim() !== "" ? { review: raw.review.trim() } : {}
21058
+ });
20991
21059
  }
20992
21060
  /**
20993
- * Free worker slots under a simultaneity cap: `cap - live`, floored at 0, or `null` when there is
20994
- * no cap (the conserved pool is then the only fence and "free slots" is not a finite number).
20995
- * The one place the answer is computed, so the driver-facing tool payload and a dispatcher agree.
21061
+ * Read an agent-eval `JudgeScore` from a check program into a verdict.
21062
+ *
21063
+ * Each dimension is a checked item. `notes` lines that start with `FAIL ` are the failures; the
21064
+ * remaining lines are the check's review. The verdict passes when `composite >= threshold` and the
21065
+ * score is not marked `failed`; a `failed` score means the judge itself did not run, which is
21066
+ * {@link CheckUnavailableError}, not a verdict.
20996
21067
  */
20997
- function freeSlots(liveCount, cap) {
20998
- if (cap === void 0 || cap <= 0) return null;
20999
- return Math.max(0, cap - liveCount);
21000
- }
21001
- /** Convenience: a `DispatchUnit` factory over a fixed array of tasks, for the common case where
21002
- * the queue is known up front and only the refill behavior is wanted. */
21003
- function queueOf(units, budget) {
21004
- let i = 0;
21005
- return () => {
21006
- const u = units[i];
21007
- if (u === void 0) return void 0;
21008
- i += 1;
21009
- return {
21010
- agent: u.agent,
21011
- task: u.task,
21012
- opts: {
21013
- budget,
21014
- label: u.label
21015
- }
21016
- };
21017
- };
21018
- }
21019
- //#endregion
21020
- //#region src/runtime/retained-interactive-handle.ts
21021
- function createRetainedInteractiveRunHandle(environment, inputRef, capabilities, requestedStart) {
21022
- const ref = freezeInteractiveRef(inputRef);
21023
- const source = environment.interactive(ref);
21024
- if (!sameInteractiveRef(source.ref, ref)) throw new Error("provider reconstructed a different interactive process");
21025
- if (!source.sendPrompt) throw new Error("provider declared interactive prompt support but exposed no prompt method");
21026
- return Object.freeze({
21027
- ref,
21028
- capabilities,
21029
- claimControl: async (request, options) => exactClaim(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.claimControl(request, options)), options?.signal)),
21030
- status: async (options) => exactStatus(ref, await awaitAbortable$1(Promise.resolve().then(() => source.status(options)), options?.signal), requestedStart),
21031
- attach: async (request, options) => exactTerminal(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.attach(request, options)), options?.signal)),
21032
- sendPrompt: async (command, options) => exactPrompt(ref, await awaitAbortable$1(Promise.resolve().then(() => source.sendPrompt(command, options)), options?.signal), command),
21033
- stop: async (command, options) => exactStop(ref, await awaitAbortable$1(Promise.resolve().then(() => source.stop(command, options)), options?.signal), command)
21068
+ function verdictFromJudgeScore(score, threshold) {
21069
+ if (score.failed === true) throw new CheckUnavailableError(`the check's judge did not run: ${score.notes}`);
21070
+ const lines = score.notes.split("\n").map((line) => line.trimEnd());
21071
+ const failures = lines.filter((line) => line.startsWith("FAIL "));
21072
+ const review = lines.filter((line) => !line.startsWith("FAIL ") && line.trim() !== "").join("\n");
21073
+ return checkVerdictOf({
21074
+ pass: score.composite >= threshold,
21075
+ items: score.dimensions,
21076
+ composite: score.composite,
21077
+ threshold,
21078
+ failures,
21079
+ ...review === "" ? {} : { review }
21034
21080
  });
21035
21081
  }
21036
- function freezeInteractiveRef(value) {
21037
- return detachedSnapshot(AgentInteractiveSessionRefSchema.parse(value), "interactive session ref");
21082
+ /** Items that fail in `verdict`: every item below 1, or the named items of its FAIL lines. */
21083
+ function failedItems(verdict) {
21084
+ if (verdict.items !== void 0) return Object.entries(verdict.items).filter(([, value]) => value < 1).map(([name]) => name);
21085
+ return (verdict.failures ?? []).map((line) => line.slice(5).split(/[\s:]/u)[0] ?? "");
21038
21086
  }
21039
- function exactClaim(ref, request, value) {
21040
- const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionControlClaimAcknowledgementSchema, value, "control claim");
21041
- if (!agentInteractiveSessionControlClaimAcknowledgementMatchesRequest(request, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a control claim acknowledgement for another request");
21042
- if (acknowledgement.control && !agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a control claim for another interactive process");
21043
- return acknowledgement;
21087
+ /** Items that pass in `verdict`. */
21088
+ function passedItems(verdict) {
21089
+ return Object.entries(verdict.items ?? {}).filter(([, value]) => value >= 1).map(([name]) => name);
21044
21090
  }
21045
- function exactPrompt(ref, value, command) {
21046
- const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionPromptAcknowledgementSchema, value, "prompt");
21047
- if (!agentInteractiveSessionPromptAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another request");
21048
- if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another interactive process");
21049
- return acknowledgement;
21050
- }
21051
- function exactStop(ref, value, command) {
21052
- const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionStopAcknowledgementSchema, value, "stop");
21053
- if (!agentInteractiveSessionStopAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another request");
21054
- if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another interactive process");
21055
- return acknowledgement;
21056
- }
21057
- function parseProviderAcknowledgement(schema, value, operation) {
21058
- try {
21059
- return schema.parse(value);
21060
- } catch {
21061
- throw new RetainedRunProviderContractError(`provider returned an invalid interactive ${operation} acknowledgement`);
21091
+ /** Resolve and check a policy before any compute. Returns the deadline in epoch ms. */
21092
+ function admitContinuationPolicy(policy, context) {
21093
+ if (typeof policy !== "object" || policy === null) throw new ValidationError$1(`${context}: continuation must be an object`);
21094
+ const deadlineMs = typeof policy.deadline === "string" ? Date.parse(policy.deadline) : policy.deadline;
21095
+ if (typeof deadlineMs !== "number" || !Number.isFinite(deadlineMs) || deadlineMs <= 0) throw new ValidationError$1(`${context}: continuation.deadline must be a finite time (epoch ms or ISO 8601)`);
21096
+ if (!Number.isInteger(policy.maxBarren) || policy.maxBarren < 1) throw new ValidationError$1(`${context}: continuation.maxBarren must be an integer >= 1`);
21097
+ if (policy.failures !== "verbatim" && policy.failures !== "off") throw new ValidationError$1(`${context}: continuation.failures must be 'verbatim' or 'off'`);
21098
+ if (policy.panel !== "on" && policy.panel !== "off") throw new ValidationError$1(`${context}: continuation.panel must be 'on' or 'off'`);
21099
+ if (policy.bar !== "on" && policy.bar !== "off") throw new ValidationError$1(`${context}: continuation.bar must be 'on' or 'off'`);
21100
+ if (policy.panel === "on") {
21101
+ if (typeof policy.runPanel !== "function") throw new ValidationError$1(`${context}: continuation.panel 'on' needs runPanel`);
21102
+ const usd = policy.panelUsd;
21103
+ if (usd === void 0 || !finite(usd.perContinuation) || !finite(usd.perRun) || usd.perContinuation <= 0 || usd.perRun < usd.perContinuation) throw new ValidationError$1(`${context}: continuation.panel 'on' needs panelUsd with 0 < perContinuation <= perRun`);
21062
21104
  }
21105
+ if (policy.append !== void 0 && typeof policy.append !== "function") throw new ValidationError$1(`${context}: continuation.append must be a function`);
21106
+ admitContinuationProfile(policy.profile, context);
21107
+ return deadlineMs;
21063
21108
  }
21064
- function exactStatus(ref, value, requestedStart) {
21065
- let status;
21066
- try {
21067
- status = AgentInteractiveSessionStatusSchema.parse(value);
21068
- } catch (error) {
21069
- if (requestedStart === void 0) throw error;
21070
- throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), {}, { cause: error });
21109
+ /** The facts a profile template may name. */
21110
+ const CONTINUATION_FACTS = [
21111
+ "composite",
21112
+ "threshold",
21113
+ "failed",
21114
+ "total",
21115
+ "reads",
21116
+ "owed",
21117
+ "settled",
21118
+ "delivered",
21119
+ "continuation"
21120
+ ];
21121
+ const factNames = new Set(CONTINUATION_FACTS);
21122
+ const placeholder = /\{([a-zA-Z]+)\}/gu;
21123
+ function admitContinuationProfile(profile, context) {
21124
+ if (typeof profile !== "object" || profile === null) throw new ValidationError$1(`${context}: continuation.profile must be an object`);
21125
+ if (typeof profile.id !== "string" || profile.id.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.id must be non-empty`);
21126
+ const texts = [
21127
+ ["opening", profile.opening],
21128
+ ["plan", profile.plan],
21129
+ ["rules", profile.rules],
21130
+ ...Object.entries(profile.headings ?? {}).map(([key, value]) => [`headings.${key}`, value]),
21131
+ ...profile.barRule === void 0 ? [] : [["barRule", profile.barRule]]
21132
+ ];
21133
+ for (const key of [
21134
+ "failures",
21135
+ "protected",
21136
+ "changed",
21137
+ "findings",
21138
+ "bar",
21139
+ "plan",
21140
+ "rules"
21141
+ ]) if (typeof profile.headings?.[key] !== "string") throw new ValidationError$1(`${context}: continuation.profile.headings.${key} must be a string`);
21142
+ for (const [key, text] of texts) {
21143
+ if (typeof text !== "string") throw new ValidationError$1(`${context}: continuation.profile.${key} must be a string`);
21144
+ for (const match of text.matchAll(placeholder)) if (!factNames.has(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.${key} names {${match[1]}}, which is not a fact Runtime supplies (${CONTINUATION_FACTS.join(", ")})`);
21071
21145
  }
21072
- if (!agentInteractiveSessionStatusMatchesRef(ref, status)) {
21073
- if (requestedStart !== void 0) throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), detachedSnapshot({ status: detachedSnapshot(status, "interactive provider status") }, "interactive provider status result"), { cause: /* @__PURE__ */ new Error("provider returned status for another interactive process") });
21074
- throw new Error("provider returned status for another interactive process");
21146
+ if (profile.review !== void 0) {
21147
+ if (typeof profile.review !== "string" || profile.review.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.review must be non-empty`);
21148
+ for (const match of profile.review.matchAll(placeholder)) if (![
21149
+ "version",
21150
+ "path",
21151
+ "score"
21152
+ ].includes(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.review names {${match[1]}}; it may name {version}, {path} and {score}`);
21075
21153
  }
21076
- return status;
21077
- }
21078
- function exactTerminal(ref, request, terminal) {
21079
- const terminalRef = TerminalSessionRefSchema.parse(terminal.ref);
21080
- TerminalReplayWindowSchema.parse(terminal.cursors);
21081
- if (terminalRef.parentExecutionId !== ref.run.executionId) throw new Error("provider attached a terminal from another interactive run");
21082
- AgentInteractiveSessionControlClaimSchema.parse(terminal.control);
21083
- if (!agentInteractiveSessionControlClaimMatchesRef(ref, terminal.control)) throw new Error("provider attached a terminal with a claim for another interactive process");
21084
- if (canonicalCandidateDigest(terminal.control) !== canonicalCandidateDigest(request.control)) throw new Error("provider attached a terminal with a different interactive control claim");
21085
- return terminal;
21086
- }
21087
- function sameInteractiveRef(left, right) {
21088
- return canonicalCandidateDigest(left) === canonicalCandidateDigest(right);
21154
+ if (profile.opening.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.opening must be non-empty`);
21155
+ for (const [index, question] of (profile.questions ?? []).entries()) if (typeof question !== "string" || question.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.questions[${index}] must be a non-empty string`);
21089
21156
  }
21090
- //#endregion
21091
- //#region src/runtime/retained-interactive.ts
21092
- /**
21093
- * Start one retry-safe native coding-agent TUI without dispatching a headless turn.
21094
- * The intent admission is durable before provider.create; the environment and
21095
- * process admissions follow only after their exact provider coordinates exist.
21096
- * @stable
21097
- */
21098
- async function startRetainedInteractiveRun(options) {
21099
- options.signal?.throwIfAborted();
21100
- const startOptions = options;
21101
- assertStableText(startOptions.environment.idempotencyKey, "environment idempotency key");
21102
- assertStableText(startOptions.interactiveIdempotencyKey, "interactive idempotency key");
21103
- if (typeof startOptions.onAdmission !== "function") throw new Error("startRetainedInteractiveRun requires an awaited onAdmission durability hook");
21104
- if (!startOptions.provider.get) throw new Error(`provider "${startOptions.provider.name}" cannot reconstruct an environment by id`);
21105
- const profile = agentProfileSchema.parse(startOptions.environment.profile);
21106
- if (profile.harness === void 0) throw new Error("retained interactive runs require AgentProfile.harness");
21107
- const requestedProfileDigest = canonicalAgentProfileDigest(profile);
21108
- const identity = startOptions.intent === void 0 ? mintRetainedIdentity(startOptions.environment.idempotencyKey, startOptions.interactiveIdempotencyKey) : {
21109
- sessionId: startOptions.intent.sessionId,
21110
- executionId: startOptions.intent.executionId
21111
- };
21112
- assertStableText(identity.sessionId, "retained session id");
21113
- assertStableText(identity.executionId, "retained execution id");
21114
- const intent = interactiveIntent(startOptions, profile, identity);
21115
- if (startOptions.intent === void 0) await admitDurably(startOptions.onAdmission, intent);
21116
- else assertExactInteractiveIntent(startOptions.intent, intent);
21117
- const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => startOptions.provider.capabilities()), startOptions.signal));
21118
- assertInteractiveCapabilities(startOptions.provider.name, providerCapabilities);
21119
- const environment = await createInteractiveEnvironment(() => startOptions.provider.create({
21120
- ...startOptions.environment,
21121
- profile,
21122
- signal: startOptions.signal,
21123
- metadata: retainedEnvironmentMetadata(startOptions.environment.metadata, startOptions.environment.idempotencyKey)
21124
- }), startOptions.signal);
21125
- let capabilities;
21126
- try {
21127
- assertExactEnvironment(startOptions.provider.name, environment);
21128
- startOptions.signal?.throwIfAborted();
21129
- capabilities = interactiveCapabilitiesForEnvironment(startOptions.provider.name, providerCapabilities, environment);
21130
- assertInteractiveMethods(startOptions.provider.name, environment);
21131
- } catch (error) {
21132
- await destroyUnusedEnvironment(environment, error);
21133
- throw error;
21134
- }
21135
- const request = interactiveRequest(startOptions, environment, profile, requestedProfileDigest, identity);
21136
- await admitDurably(startOptions.onAdmission, {
21137
- phase: "interactive_environment",
21138
- provider: startOptions.provider.name,
21139
- environmentId: environment.id,
21140
- idempotencyKey: startOptions.environment.idempotencyKey,
21141
- interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
21142
- request
21143
- });
21144
- const ref = exactStartedRef(request, await startInteractiveProcess(environment, () => environment.startInteractive(request, { signal: startOptions.signal }), startOptions.signal));
21145
- await admitDurably(startOptions.onAdmission, {
21146
- phase: "interactive_started",
21147
- idempotencyKey: startOptions.environment.idempotencyKey,
21148
- interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
21149
- ref
21150
- });
21151
- return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
21157
+ /** Findings reach the note only when every citation resolves, at least two distinct spans are
21158
+ * cited, and the independent verifier agreed. The best method in Who&When found the failing step
21159
+ * 14.2% of the time, so an unverified finding is noise with a citation. */
21160
+ function admitFinding(finding) {
21161
+ if (!finding.verified) return false;
21162
+ if (finding.citations.length === 0) return false;
21163
+ if (!finding.citations.every((citation) => citation.resolved)) return false;
21164
+ return new Set(finding.citations.map((citation) => citation.uri)).size >= 2;
21152
21165
  }
21166
+ /** About 1,500 tokens of findings. */
21167
+ const FINDINGS_CHAR_CAP = 6e3;
21153
21168
  /**
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
21169
+ * Rank the admitted findings by how many failed items they explain, drop repeats, and keep them
21170
+ * within the note's cap. Earlier findings stay as they were written (ACE: itemized additions keep
21171
+ * detail that repeated rewrites lose); a finding whose items all pass now is marked resolved.
21159
21172
  */
21160
- async function recoverRetainedInteractiveRun(options) {
21161
- options.signal?.throwIfAborted();
21162
- if (typeof options.onAdmission !== "function") throw new Error("recoverRetainedInteractiveRun requires an awaited onAdmission durability hook");
21163
- const admission = options.admission;
21164
- if (admission.provider !== options.provider.name) throw new Error("interactive admission belongs to another provider");
21165
- if (admission.phase === "interactive_intent") {
21166
- if (options.replay === void 0) throw new Error("recoverRetainedInteractiveRun requires the original start material for an interactive intent");
21167
- return startRetainedInteractiveRun({
21168
- provider: options.provider,
21169
- ...options.replay,
21170
- intent: admission,
21171
- onAdmission: options.onAdmission,
21172
- signal: options.signal
21173
+ function distillFindings(prior, proposed, failing, continuation) {
21174
+ const key = (claim) => claim.toLowerCase().replace(/\s+/gu, " ").trim();
21175
+ const known = new Set(prior.map((finding) => key(finding.claim)));
21176
+ const carried = prior.map((finding) => finding.resolvedAt === void 0 && (finding.items?.length ?? 0) > 0 && (finding.items ?? []).every((item) => !failing.has(item)) ? {
21177
+ ...finding,
21178
+ resolvedAt: continuation
21179
+ } : finding);
21180
+ const fresh = proposed.filter(admitFinding).filter((finding) => {
21181
+ const k = key(finding.claim);
21182
+ if (known.has(k)) return false;
21183
+ known.add(k);
21184
+ return true;
21185
+ }).map((finding) => ({
21186
+ finding,
21187
+ links: (finding.items ?? []).filter((item) => failing.has(item)).length
21188
+ })).sort((a, b) => b.links - a.links);
21189
+ const out = [...carried];
21190
+ let used = carried.filter((finding) => finding.resolvedAt === void 0).reduce((sum, finding) => sum + finding.claim.length, 0);
21191
+ for (const { finding } of fresh) {
21192
+ if (used + finding.claim.length > FINDINGS_CHAR_CAP) break;
21193
+ used += finding.claim.length;
21194
+ out.push({
21195
+ ...finding,
21196
+ admittedAt: continuation
21173
21197
  });
21174
21198
  }
21175
- const request = exactRecoveryRequest(admission);
21176
- const { environment, capabilities } = await reconstructEnvironment(options.provider, admission.environmentId, options.signal);
21177
- if (!environment || !capabilities) return null;
21178
- const ref = exactStartedRef(request, await awaitAbortable$1(Promise.resolve().then(() => environment.startInteractive(request, { signal: options.signal })), options.signal));
21179
- await admitDurably(options.onAdmission, {
21180
- phase: "interactive_started",
21181
- idempotencyKey: admission.idempotencyKey,
21182
- interactiveIdempotencyKey: admission.interactiveIdempotencyKey,
21183
- ref
21184
- });
21185
- return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
21199
+ return out;
21186
21200
  }
21187
- function exactRecoveryRequest(admission) {
21188
- assertStableText(admission.environmentId, "interactive environment id");
21189
- assertStableText(admission.idempotencyKey, "environment idempotency key");
21190
- assertStableText(admission.interactiveIdempotencyKey, "interactive idempotency key");
21191
- const request = exactAgentInteractiveSessionStart(admission.request);
21192
- const identity = mintRetainedIdentity(admission.idempotencyKey, admission.interactiveIdempotencyKey);
21193
- if (request.run.provider !== admission.provider || request.run.environmentId !== admission.environmentId || (request.run.sessionId !== identity.sessionId || request.run.executionId !== identity.executionId) && !matchesHistoricalInteractiveIdentity(admission, request)) throw new Error("interactive admission does not match its recovery coordinates");
21194
- return request;
21201
+ /** Expand the profile's question templates over the failed items and the settled workers. */
21202
+ function expandQuestions(templates, failing, workers) {
21203
+ const out = [];
21204
+ for (const template of templates) {
21205
+ const hasItem = template.includes("{item}");
21206
+ const hasWorker = template.includes("{worker}");
21207
+ if (!hasItem && !hasWorker) {
21208
+ out.push(template);
21209
+ continue;
21210
+ }
21211
+ const items = hasItem ? failing : [""];
21212
+ const each = hasWorker ? workers.map((worker) => `${worker.id} (${worker.label})`) : [""];
21213
+ for (const item of items) for (const worker of each) out.push(template.replaceAll("{item}", item).replaceAll("{worker}", worker));
21214
+ }
21215
+ return out;
21195
21216
  }
21196
- function matchesHistoricalInteractiveIdentity(admission, request) {
21197
- const base = `${encodeURIComponent(admission.idempotencyKey)}:${encodeURIComponent(admission.interactiveIdempotencyKey)}`;
21198
- const digest = canonicalCandidateDigest({
21199
- kind: "retained-identity.v1",
21200
- base
21201
- }).slice(7);
21202
- const historicalId = (prefix) => {
21203
- const readable = `${prefix}:${base}`;
21204
- return readable.length <= 128 ? readable : `${prefix}:${digest}`;
21205
- };
21206
- return request.run.sessionId === historicalId("retained-session") && request.run.executionId === historicalId("retained-execution");
21207
- }
21208
- /** Rebuild controls for one exact provider-owned coding-agent process. @stable */
21209
- async function reconnectRetainedInteractiveRun(options) {
21210
- options.signal?.throwIfAborted();
21211
- const ref = AgentInteractiveSessionRefSchema.parse(options.ref);
21212
- if (ref.run.provider !== options.provider.name) throw new Error("interactive session reference belongs to another provider");
21213
- const { environment, capabilities } = await reconstructEnvironment(options.provider, ref.run.environmentId, options.signal);
21214
- if (!environment || !capabilities) return null;
21215
- const handle = createRetainedInteractiveRunHandle(environment, ref, capabilities);
21216
- await handle.status({ signal: options.signal });
21217
- return handle;
21218
- }
21219
- function interactiveRequest(options, environment, profile, requestedProfileDigest, identity) {
21220
- const start = {
21221
- profile,
21222
- requestedProfileDigest,
21223
- ...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
21224
- ...options.cwd === void 0 ? {} : { cwd: options.cwd },
21225
- ...options.cols === void 0 ? {} : { cols: options.cols },
21226
- ...options.rows === void 0 ? {} : { rows: options.rows }
21227
- };
21228
- return exactAgentInteractiveSessionStart({
21229
- run: agentInteractiveSessionRunRef({
21230
- provider: options.provider.name,
21231
- environmentId: environment.id,
21232
- ...identity
21233
- }, start),
21234
- ...start
21235
- });
21236
- }
21237
- function interactiveIntent(options, profile, identity) {
21238
- const requestedProfileDigest = canonicalAgentProfileDigest(profile);
21239
- const requestDigest = canonicalCandidateDigest({
21240
- kind: "retained-interactive-intent.v1",
21241
- provider: options.provider.name,
21242
- idempotencyKey: options.environment.idempotencyKey,
21243
- interactiveIdempotencyKey: options.interactiveIdempotencyKey,
21244
- sessionId: identity.sessionId,
21245
- executionId: identity.executionId,
21246
- requestedProfileDigest,
21247
- create: retainedCreateMaterial(options.environment),
21248
- start: sanitizedStartMaterial(options)
21249
- });
21250
- return {
21251
- phase: "interactive_intent",
21252
- provider: options.provider.name,
21253
- idempotencyKey: options.environment.idempotencyKey,
21254
- interactiveIdempotencyKey: options.interactiveIdempotencyKey,
21255
- sessionId: identity.sessionId,
21256
- executionId: identity.executionId,
21257
- runId: `interactive-intent-run:${requestDigest.slice(7)}`,
21258
- requestedProfileDigest,
21259
- requestDigest
21217
+ /**
21218
+ * Write one continuation note, sections 1 to 8 of docs/38. Section 9, the run's state, is
21219
+ * `composeReentryTask`, which wraps this text. Pure: the same input writes the same note.
21220
+ */
21221
+ function composeContinuationNote(input) {
21222
+ const { profile, verdict } = input;
21223
+ const items = verdict?.items ?? {};
21224
+ const total = Object.keys(items).length;
21225
+ const failing = verdict === void 0 ? [] : failedItems(verdict);
21226
+ const facts = {
21227
+ composite: verdict?.composite === void 0 ? "unknown" : format(verdict.composite),
21228
+ threshold: verdict?.threshold === void 0 ? "unknown" : format(verdict.threshold),
21229
+ failed: verdict === void 0 || total === 0 && (verdict.failures?.length ?? 0) === 0 ? "unknown" : String(failing.length),
21230
+ total: total === 0 ? "unknown" : String(total),
21231
+ reads: String(input.reads),
21232
+ owed: input.owed?.trim() || "not described",
21233
+ settled: String(input.progress.settledCount),
21234
+ delivered: String(input.progress.deliveredCount ?? 0),
21235
+ continuation: String(input.continuation)
21260
21236
  };
21261
- }
21262
- function sanitizedStartMaterial(options) {
21263
- return {
21264
- ...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
21265
- ...options.cwd === void 0 ? {} : { cwd: options.cwd },
21266
- ...options.cols === void 0 ? {} : { cols: options.cols },
21267
- ...options.rows === void 0 ? {} : { rows: options.rows }
21237
+ const fill = (text) => text.replace(placeholder, (_, name) => facts[name] ?? `{${name}}`);
21238
+ const sections = [verdict === void 0 ? "No check verdict is available yet." + (input.canSubmitResult === true ? " Submit a result through submit_result to request the check." : "") : verdict.pass ? "The check passes on the current state, but no result has been accepted." + (input.canSubmitResult === true ? " Call submit_result to request acceptance." : "") : fill(profile.opening).trim()];
21239
+ const section = (heading, body) => {
21240
+ if (body.length === 0) return;
21241
+ sections.push([...heading.trim() === "" ? [] : [`## ${fill(heading)}`], ...body].join("\n"));
21268
21242
  };
21269
- }
21270
- function assertExactInteractiveIntent(received, expected) {
21271
- if (canonicalCandidateDigest(parseInteractiveIntent(received)) !== canonicalCandidateDigest(expected)) throw new Error("interactive intent conflicts with replay material");
21272
- }
21273
- function parseInteractiveIntent(value) {
21274
- const stable = detachedSnapshot(value, "interactive intent");
21275
- if (stable === null || typeof stable !== "object" || Array.isArray(stable)) throw new Error("interactive intent is malformed");
21276
- const record = stable;
21277
- const allowed = /* @__PURE__ */ new Set([
21278
- "phase",
21279
- "provider",
21280
- "idempotencyKey",
21281
- "interactiveIdempotencyKey",
21282
- "sessionId",
21283
- "executionId",
21284
- "runId",
21285
- "requestedProfileDigest",
21286
- "requestDigest"
21287
- ]);
21288
- if (Object.keys(record).some((key) => !allowed.has(key))) throw new Error("interactive intent contains unsupported material");
21289
- if (record.phase !== "interactive_intent") throw new Error("interactive intent has an invalid phase");
21290
- for (const [key, value] of Object.entries(record)) {
21291
- if (key === "phase") continue;
21292
- if (typeof value !== "string" || value.length === 0) throw new Error(`interactive intent field "${key}" is invalid`);
21243
+ if (input.failures === "verbatim" && verdict !== void 0) {
21244
+ const lines = verdict.failures ?? [];
21245
+ const shown = lines.slice(0, 40);
21246
+ const more = lines.length - shown.length;
21247
+ section(profile.headings.failures, [...shown, ...more > 0 ? [input.canReadMore ? `${more} more failure lines: call read_continuation with continuation ${input.continuation}.` : `${more} more failure lines are not shown.`] : []]);
21248
+ const passing = passedItems(verdict);
21249
+ section(profile.headings.protected, passing.length === 0 ? [] : [passing.join(", ")]);
21250
+ if (input.previous !== void 0) {
21251
+ const before = new Set(failedItems(input.previous));
21252
+ const now = new Set(failing);
21253
+ const fixed = [...before].filter((item) => !now.has(item));
21254
+ const broke = [...now].filter((item) => !before.has(item));
21255
+ section(profile.headings.changed, [
21256
+ ...fixed.length === 0 ? [] : [`Now passing: ${fixed.join(", ")}.`],
21257
+ ...broke.length === 0 ? [] : [`Newly failing: ${broke.join(", ")}.`],
21258
+ ...fixed.length === 0 && broke.length === 0 ? ["No item changed since the last note."] : [],
21259
+ ...input.previous.composite !== void 0 && verdict.composite !== void 0 ? [`Composite: ${format(input.previous.composite)} then ${format(verdict.composite)}.`] : []
21260
+ ]);
21261
+ }
21293
21262
  }
21294
- assertDigest$1(record.requestedProfileDigest, "interactive intent profile digest");
21295
- assertDigest$1(record.requestDigest, "interactive intent request digest");
21296
- return stable;
21297
- }
21298
- function assertDigest$1(value, label) {
21299
- if (typeof value !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(value)) throw new Error(`${label} is invalid`);
21263
+ if (input.findings !== void 0) {
21264
+ const open = input.findings.filter((finding) => finding.resolvedAt === void 0);
21265
+ const resolved = input.findings.filter((finding) => finding.resolvedAt === input.continuation);
21266
+ section(profile.headings.findings, [...open.map((finding) => `- [hypothesis] ${finding.claim}` + (finding.items?.length ? ` (items: ${finding.items.join(", ")})` : "") + ` Evidence: ${finding.citations.map((citation) => citation.uri).join(", ")}`), ...resolved.map((finding) => `- [resolved] ${finding.claim}`)]);
21267
+ }
21268
+ if (input.bar !== void 0 && verdict !== void 0) {
21269
+ const body = [];
21270
+ if (profile.barRule?.trim()) body.push(fill(profile.barRule).trim());
21271
+ for (const [item, value] of Object.entries(items)) {
21272
+ const best = input.bar.best?.verdict.items?.[item];
21273
+ body.push(`- ${item}: ${value >= 1 ? "passes" : `fails (${format(value)})`}` + (best === void 0 ? "" : ` / ${input.bar.best?.label}: ${best >= 1 ? "passes" : `fails (${format(best)})`}`));
21274
+ }
21275
+ if (input.bar.best?.verdict.composite !== void 0) body.push(`Best version ${input.bar.best.label}: composite ${format(input.bar.best.verdict.composite)}.`);
21276
+ if (input.bar.reference?.trim()) body.push(`Reference result: ${input.bar.reference.trim()}`);
21277
+ if (verdict.review?.trim()) body.push(`The check's review: ${verdict.review.trim()}`);
21278
+ section(profile.headings.bar, body);
21279
+ }
21280
+ section(profile.headings.plan, profile.plan.trim() === "" ? [] : [fill(profile.plan).trim()]);
21281
+ section(profile.headings.rules, [...profile.rules.trim() === "" ? [] : [fill(profile.rules).trim()], ...input.sealed ? ["The score comes from cases you cannot see."] : []]);
21282
+ for (const appended of input.appended ?? []) section(appended.heading, appended.text.trim() === "" ? [] : [appended.text.trim()]);
21283
+ return sections.join("\n\n");
21300
21284
  }
21301
- async function reconstructEnvironment(provider, environmentId, signal) {
21302
- if (!provider.get) throw new Error(`provider "${provider.name}" cannot reconstruct an environment by id`);
21303
- const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => provider.capabilities()), signal));
21304
- assertInteractiveCapabilities(provider.name, providerCapabilities);
21305
- const environment = await awaitAbortable$1(Promise.resolve().then(() => provider.get(environmentId, { signal })), signal);
21306
- if (!environment) return {
21307
- environment: null,
21308
- capabilities: null
21309
- };
21310
- assertExactEnvironment(provider.name, environment, environmentId);
21311
- const capabilities = interactiveCapabilitiesForEnvironment(provider.name, providerCapabilities, environment);
21312
- assertInteractiveMethods(provider.name, environment);
21285
+ function summarizeVerdict(verdict) {
21286
+ if (verdict === void 0) return null;
21287
+ const total = Object.keys(verdict.items ?? {}).length;
21313
21288
  return {
21314
- environment,
21315
- capabilities
21289
+ pass: verdict.pass,
21290
+ ...verdict.composite === void 0 ? {} : { composite: verdict.composite },
21291
+ ...total === 0 ? {} : {
21292
+ failed: failedItems(verdict).length,
21293
+ total
21294
+ }
21316
21295
  };
21317
21296
  }
21318
- function exactStartedRef(request, value) {
21319
- const stableRequest = detachedSnapshot(request, "interactive start binding request");
21320
- let ref;
21321
- try {
21322
- ref = AgentInteractiveSessionRefSchema.parse(value);
21323
- } catch (error) {
21324
- throw new RetainedInteractiveBindingError(stableRequest, {}, { cause: error });
21325
- }
21326
- if (!agentInteractiveSessionRefMatchesStart(request, ref)) throw new RetainedInteractiveBindingError(stableRequest, detachedSnapshot({ ref: detachedSnapshot(ref, "interactive provider start reference") }, "interactive provider start result"), { cause: /* @__PURE__ */ new Error("provider started another interactive run than requested") });
21327
- return freezeInteractiveRef(ref);
21328
- }
21329
- function assertExactEnvironment(providerName, environment, environmentId) {
21330
- if (environment.provider !== providerName || environmentId && environment.id !== environmentId) throw new Error("provider returned another interactive environment");
21331
- assertStableText(environment.id, "interactive environment id");
21332
- }
21333
- function interactiveCapabilitiesForEnvironment(providerName, providerCapabilities, environment) {
21334
- const capabilities = environment.capabilities === void 0 ? providerCapabilities : AgentEnvironmentCapabilitiesSchema.parse(environment.capabilities);
21335
- assertInteractiveCapabilities(providerName, capabilities);
21336
- return capabilities;
21337
- }
21338
- function assertInteractiveCapabilities(providerName, capabilities) {
21339
- const interactive = capabilities.interactiveAgent;
21340
- if (!interactive?.start || !interactive.control || !interactive.status || !interactive.attach || !interactive.reattach || !interactive.sendPrompt || !interactive.input || !interactive.resize || !interactive.stop) throw new Error(`provider "${providerName}" cannot control an exact interactive agent`);
21297
+ function noteDigest(note) {
21298
+ return `sha256:${createHash("sha256").update(note).digest("hex")}`;
21341
21299
  }
21342
- function assertInteractiveMethods(providerName, environment) {
21343
- if (!environment.startInteractive || !environment.interactive) throw new Error(`provider "${providerName}" exposes incomplete interactive agent controls`);
21300
+ /** A run directory's continuation files: the root's at `<runDir>/continuations/<n>/`, a nested
21301
+ * manager's at `<runDir>/continuations/managers/<owner>/<n>/`. */
21302
+ const CONTINUATIONS_DIR = "continuations";
21303
+ /**
21304
+ * Write one continuation's files under `<dir>/<n>/`: `note.md`, `verdict.json`, and
21305
+ * `panel.jsonl` when the panel ran. The director reads them through `read_continuation`, because
21306
+ * its box cannot read the driver's run directory.
21307
+ */
21308
+ async function writeContinuationFiles(dir, continuation, files) {
21309
+ const at = join(dir, String(continuation));
21310
+ await mkdir(at, { recursive: true });
21311
+ await writeFile(join(at, "note.md"), `${files.note}\n`, "utf8");
21312
+ await writeFile(join(at, "verdict.json"), `${JSON.stringify(files.verdict ?? null, null, 2)}\n`, "utf8");
21313
+ if (files.panel !== void 0) await writeFile(join(at, "panel.jsonl"), files.panel.map((line) => JSON.stringify(line)).join("\n") + (files.panel.length ? "\n" : ""), "utf8");
21344
21314
  }
21345
- async function destroyUnusedEnvironment(environment, cause) {
21346
- try {
21347
- await destroyInteractiveEnvironment(environment);
21348
- } catch (cleanupError) {
21349
- throw new AggregateError([cause, cleanupError], "interactive environment was invalid and could not be destroyed");
21315
+ /** The best composite across `reads`, or `undefined` when no read scored. */
21316
+ function bestComposite(reads) {
21317
+ let best;
21318
+ for (const read of reads) {
21319
+ const value = read.verdict?.composite;
21320
+ if (value !== void 0 && (best === void 0 || value > best)) best = value;
21350
21321
  }
21322
+ return best;
21351
21323
  }
21352
- //#endregion
21353
- //#region src/runtime/supervise/worker-interactive.ts
21354
- const WORKER_BINDING_SCHEMA_VERSION = 1;
21355
- const SPAWN_JOURNAL_FILE = "spawn-journal.jsonl";
21356
- /** Directory containing exact per-worker interactive binding records. @stable */
21357
- function workerInteractiveBindingsDir(eventDir) {
21358
- return join(eventDir, "interactive-workers");
21324
+ function finite(value) {
21325
+ return typeof value === "number" && Number.isFinite(value);
21359
21326
  }
21360
- /** Exact durable binding file for one worker id. @stable */
21361
- function workerInteractiveBindingFile(eventDir, workerId) {
21362
- const id = stableText$1(workerId, "worker id");
21363
- const stem = createHash("sha256").update(id).digest("hex");
21364
- return join(workerInteractiveBindingsDir(eventDir), `${stem}.json`);
21327
+ function format(value) {
21328
+ return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/u, "");
21365
21329
  }
21366
- /** Read and validate one exact durable worker binding. @stable */
21367
- function readWorkerInteractiveBinding(eventDir, workerId) {
21368
- const id = stableText$1(workerId, "worker id");
21369
- const file = workerInteractiveBindingFile(eventDir, id);
21330
+ /** Build the continuation state for one manager with a check. */
21331
+ function createContinuationKeeper(input) {
21332
+ const { policy } = input;
21333
+ const failures = input.feedback === "pass-only" ? "off" : policy.failures;
21334
+ const entries = [];
21335
+ const notes = [];
21336
+ let findings = [];
21337
+ let panelUsd = 0;
21338
+ let panelUsdKnown = true;
21339
+ const latestVerdict = () => {
21340
+ const reads = input.reads();
21341
+ for (let i = reads.length - 1; i >= 0; i -= 1) {
21342
+ const read = reads[i];
21343
+ if (read?.verdict !== void 0) return {
21344
+ verdict: read.verdict,
21345
+ read: read.read
21346
+ };
21347
+ }
21348
+ return { read: 0 };
21349
+ };
21350
+ const closePrevious = () => {
21351
+ const last = entries.at(-1);
21352
+ const lastNote = notes.at(-1);
21353
+ if (last === void 0 || lastNote === void 0) return;
21354
+ const latest = latestVerdict();
21355
+ entries[entries.length - 1] = {
21356
+ ...last,
21357
+ after: latest.read > lastNote.read ? summarizeVerdict(latest.verdict) : null
21358
+ };
21359
+ };
21360
+ return {
21361
+ async compose(context) {
21362
+ closePrevious();
21363
+ const continuation = entries.length + 1;
21364
+ const { verdict, read } = latestVerdict();
21365
+ const failing = verdict === void 0 ? [] : failedItems(verdict);
21366
+ let panelRecord;
21367
+ let panelLines;
21368
+ if (policy.panel === "on" && policy.runPanel !== void 0 && policy.panelUsd !== void 0) {
21369
+ const workers = input.workers();
21370
+ const questions = expandQuestions(policy.profile.questions ?? [], failing, workers);
21371
+ const left = policy.panelUsd.perRun - panelUsd;
21372
+ const usdCap = Math.min(policy.panelUsd.perContinuation, left);
21373
+ const asking = questions.length > 0 && usdCap > 0 && panelUsdKnown;
21374
+ let traces;
21375
+ let unavailable;
21376
+ if (asking) try {
21377
+ traces = await input.traces?.();
21378
+ if (traces === void 0) unavailable = "the run has recorded no trace yet";
21379
+ } catch (error) {
21380
+ unavailable = `the run's traces could not be read: ${error instanceof Error ? error.message : String(error)}`;
21381
+ }
21382
+ if (asking && traces !== void 0) {
21383
+ const result = await policy.runPanel({
21384
+ continuation,
21385
+ task: input.task,
21386
+ ...verdict === void 0 ? {} : { verdict },
21387
+ reads: input.reads(),
21388
+ questions,
21389
+ traces,
21390
+ workers,
21391
+ ...policy.best === void 0 ? {} : { bar: policy.best },
21392
+ ...policy.reference === void 0 ? {} : { reference: policy.reference },
21393
+ usdCap,
21394
+ signal: context.signal
21395
+ });
21396
+ if (result.usd === null) panelUsdKnown = false;
21397
+ else panelUsd += result.usd;
21398
+ findings = distillFindings(findings, result.findings, new Set(failing), continuation);
21399
+ panelRecord = {
21400
+ asked: questions.length,
21401
+ proposed: result.findings.length,
21402
+ admitted: findings.filter((finding) => finding.admittedAt === continuation).length,
21403
+ usd: result.usd
21404
+ };
21405
+ panelLines = [...result.findings.map((finding) => ({
21406
+ kind: "finding",
21407
+ admitted: admitFinding(finding),
21408
+ ...finding
21409
+ })), ...result.receipts === void 0 ? [] : [{
21410
+ kind: "receipts",
21411
+ receipts: result.receipts
21412
+ }]];
21413
+ } else panelRecord = {
21414
+ asked: 0,
21415
+ proposed: 0,
21416
+ admitted: 0,
21417
+ usd: 0,
21418
+ ...unavailable === void 0 ? {} : { unavailable }
21419
+ };
21420
+ }
21421
+ const appended = policy.append ? await policy.append({
21422
+ continuation,
21423
+ ...verdict === void 0 ? {} : { verdict },
21424
+ reads: input.reads(),
21425
+ signal: context.signal
21426
+ }) : void 0;
21427
+ const note = composeContinuationNote({
21428
+ profile: policy.profile,
21429
+ continuation,
21430
+ ...verdict === void 0 ? {} : { verdict },
21431
+ ...notes.at(-1)?.verdict === void 0 ? {} : { previous: notes.at(-1)?.verdict },
21432
+ reads: input.reads().length,
21433
+ failures,
21434
+ ...policy.panel === "on" ? { findings } : {},
21435
+ ...policy.bar === "on" ? { bar: {
21436
+ ...policy.best === void 0 ? {} : { best: policy.best },
21437
+ ...policy.reference === void 0 ? {} : { reference: policy.reference }
21438
+ } } : {},
21439
+ ...appended === void 0 ? {} : { appended: [appended] },
21440
+ ...input.owed === void 0 ? {} : { owed: input.owed },
21441
+ progress: context.progress,
21442
+ canReadMore: input.canReadMore,
21443
+ canSubmitResult: input.canSubmitResult === true,
21444
+ ...input.sealed === true ? { sealed: true } : {}
21445
+ });
21446
+ notes.push({
21447
+ note,
21448
+ ...verdict === void 0 ? {} : { verdict },
21449
+ ...panelLines === void 0 ? {} : { panel: panelLines },
21450
+ read
21451
+ });
21452
+ entries.push({
21453
+ continuation,
21454
+ attempt: context.attempt,
21455
+ noteDigest: noteDigest(note),
21456
+ profile: policy.profile.id,
21457
+ switches: {
21458
+ failures,
21459
+ panel: policy.panel,
21460
+ bar: policy.bar
21461
+ },
21462
+ before: summarizeVerdict(verdict),
21463
+ after: null,
21464
+ ...panelRecord === void 0 ? {} : { panel: panelRecord },
21465
+ appended: appended === void 0 ? 0 : 1
21466
+ });
21467
+ if (input.dir !== void 0) await writeContinuationFiles(input.dir, continuation, {
21468
+ note,
21469
+ ...verdict === void 0 ? {} : { verdict },
21470
+ ...panelLines === void 0 ? {} : { panel: panelLines }
21471
+ });
21472
+ return note;
21473
+ },
21474
+ read(continuation) {
21475
+ const index = continuation === void 0 ? notes.length - 1 : continuation - 1;
21476
+ const entry = notes[index];
21477
+ if (entry === void 0) return {
21478
+ found: false,
21479
+ reason: notes.length === 0 ? "no continuation has been sent in this run" : `continuations run from 1 to ${notes.length}`
21480
+ };
21481
+ return {
21482
+ found: true,
21483
+ continuation: index + 1,
21484
+ note: entry.note,
21485
+ verdict: failures === "off" && entry.verdict !== void 0 ? { pass: entry.verdict.pass } : entry.verdict ?? null,
21486
+ findings: findings.filter((finding) => finding.admittedAt <= index + 1)
21487
+ };
21488
+ },
21489
+ entries() {
21490
+ closePrevious();
21491
+ return entries.map((entry) => ({ ...entry }));
21492
+ }
21493
+ };
21494
+ }
21495
+ //#endregion
21496
+ //#region src/runtime/supervise/completion-gate.ts
21497
+ /**
21498
+ *
21499
+ * The completion-oracle: **settled ⟺ DELIVERED.**
21500
+ *
21501
+ * Foreman's one hard lesson (0/18 self-improvement deliverables) — "done" must mean a check
21502
+ * PASSED, not the agent's say-so. `gateOnDeliverable` wraps an `Executor` so its settlement
21503
+ * is `valid` ONLY when the deliverable check passes. The child still RUNS and settles (its
21504
+ * spend is conserved into the pool either way), but a child that ran WITHOUT delivering
21505
+ * settles `valid:false` — so a keep-best driver never counts it as done, and a gate never
21506
+ * inflates with self-judged wins.
21507
+ *
21508
+ * Dual-purpose by construction:
21509
+ * - product: the agent fleet only advances on real, checked deliverables.
21510
+ * - proof: the gate's `valid` is the honest settle — equal-k comparisons can't be gamed by an
21511
+ * arm that "ran" without producing the artifact.
21512
+ *
21513
+ * The check is a DEPLOYABLE oracle — a test command, a state verifier, the commit0 judge —
21514
+ * read off the child's output, never the model judging itself. A throwing check is
21515
+ * fail-closed (not delivered), never a crash.
21516
+ *
21517
+ * @experimental
21518
+ */
21519
+ /**
21520
+ * Wrap an `Executor` so its settlement `valid` reflects the deliverable check, not the
21521
+ * inner verdict. Handles both `execute` shapes (one-shot `Promise<ExecutorResult>` and
21522
+ * streaming `AsyncIterable<UsageEvent>` + `resultArtifact()`); the check runs once the inner
21523
+ * executor has produced its output. The inner `score` is preserved; only `valid` is gated.
21524
+ */
21525
+ function gateOnDeliverable(inner, deliverable) {
21526
+ let gated;
21527
+ const check = async (out, baseScore) => {
21528
+ let delivered;
21529
+ try {
21530
+ delivered = checkVerdictOf(await deliverable.check(out)).pass;
21531
+ } catch {
21532
+ delivered = false;
21533
+ }
21534
+ return {
21535
+ valid: delivered,
21536
+ score: baseScore ?? (delivered ? 1 : 0)
21537
+ };
21538
+ };
21539
+ /**
21540
+ * Ask the delivery question once, from whatever the inner executor managed to produce.
21541
+ *
21542
+ * Fail-closed on the artifact being unavailable: an executor that never produced one delivered
21543
+ * nothing, and leaving `gated` unset keeps the existing invalid-by-default reading.
21544
+ */
21545
+ const settleVerdict = async () => {
21546
+ let art;
21547
+ try {
21548
+ art = inner.resultArtifact();
21549
+ } catch {
21550
+ return;
21551
+ }
21552
+ gated = await check(art.out, art.verdict?.score);
21553
+ };
21554
+ const gateExecution = (r) => {
21555
+ if (isAsyncIterable$1(r)) return (async function* () {
21556
+ try {
21557
+ for await (const ev of r) yield ev;
21558
+ } finally {
21559
+ await settleVerdict();
21560
+ }
21561
+ })();
21562
+ return (async () => {
21563
+ let res;
21564
+ try {
21565
+ res = await r;
21566
+ } catch (error) {
21567
+ await settleVerdict();
21568
+ throw error;
21569
+ }
21570
+ gated = await check(res.out, res.verdict?.score);
21571
+ return {
21572
+ ...res,
21573
+ verdict: gated
21574
+ };
21575
+ })();
21576
+ };
21577
+ return inheritRuntimeOwnedExecutorAttestation(inner, {
21578
+ runtime: inner.runtime,
21579
+ ...inner.budgetExempt !== void 0 ? { budgetExempt: inner.budgetExempt } : {},
21580
+ ...inner.deliver ? { deliver: (m) => inner.deliver?.(m) } : {},
21581
+ ...inner.progress ? { progress: () => inner.progress?.() } : {},
21582
+ ...inner.traceSource ? { traceSource: () => inner.traceSource?.() } : {},
21583
+ ...inner.metered ? { metered: () => inner.metered?.() } : {},
21584
+ ...inner.accounting ? { accounting: () => inner.accounting?.() } : {},
21585
+ ...inner.harnessTranscript ? { harnessTranscript: () => inner.harnessTranscript?.() } : {},
21586
+ ...inner.harnessTranscriptSettled ? { harnessTranscriptSettled: () => inner.harnessTranscriptSettled?.() ?? Promise.resolve() } : {},
21587
+ execute: (task, signal) => gateExecution(inner.execute(task, signal)),
21588
+ ...inner.recover ? { recover: (task, signal) => gateExecution(inner.recover(task, signal)) } : {},
21589
+ teardown: (grace) => inner.teardown(grace),
21590
+ ...teardownSurfaces(inner),
21591
+ resultArtifact() {
21592
+ const art = inner.resultArtifact();
21593
+ return {
21594
+ ...art,
21595
+ verdict: gated ?? art.verdict
21596
+ };
21597
+ }
21598
+ });
21599
+ }
21600
+ /**
21601
+ * Transform a Runtime executor's terminal artifact without losing its private
21602
+ * profile-materialization attestation or altering its measured spend. This is
21603
+ * the composition point for deterministic post-processing and grading; callers
21604
+ * must not rebuild an Executor around a model transport merely to change `out`.
21605
+ */
21606
+ function mapExecutorResult(inner, map) {
21607
+ let mapped;
21608
+ const settle = async (result, task) => {
21609
+ const transformed = await map(result, task);
21610
+ mapped = {
21611
+ outRef: transformed.outRef,
21612
+ out: transformed.out,
21613
+ ...transformed.verdict ? { verdict: transformed.verdict } : {},
21614
+ spent: result.spent
21615
+ };
21616
+ return mapped;
21617
+ };
21618
+ return inheritRuntimeOwnedExecutorAttestation(inner, {
21619
+ runtime: inner.runtime,
21620
+ ...inner.budgetExempt !== void 0 ? { budgetExempt: inner.budgetExempt } : {},
21621
+ ...inner.deliver ? { deliver: (message) => inner.deliver?.(message) } : {},
21622
+ ...inner.progress ? { progress: () => inner.progress?.() } : {},
21623
+ ...inner.traceSource ? { traceSource: () => inner.traceSource?.() } : {},
21624
+ ...inner.accounting ? { accounting: () => inner.accounting?.() } : {},
21625
+ ...inner.metered ? { metered: () => inner.metered?.() } : {},
21626
+ ...inner.harnessTranscript ? { harnessTranscript: () => inner.harnessTranscript?.() } : {},
21627
+ ...inner.harnessTranscriptSettled ? { harnessTranscriptSettled: () => inner.harnessTranscriptSettled?.() ?? Promise.resolve() } : {},
21628
+ execute(task, signal) {
21629
+ const execution = inner.execute(task, signal);
21630
+ if (isAsyncIterable$1(execution)) return (async function* () {
21631
+ for await (const event of execution) yield event;
21632
+ await settle(inner.resultArtifact(), task);
21633
+ })();
21634
+ return (async () => settle(await execution, task))();
21635
+ },
21636
+ teardown: (grace) => inner.teardown(grace),
21637
+ ...teardownSurfaces(inner),
21638
+ resultArtifact() {
21639
+ if (!mapped) throw new Error("mapExecutorResult: resultArtifact() read before execute()");
21640
+ return mapped;
21641
+ }
21642
+ });
21643
+ }
21644
+ //#endregion
21645
+ //#region src/runtime/supervise/dispatch.ts
21646
+ /**
21647
+ *
21648
+ * `rollingDispatch` — the REFILLING dispatch policy over a `Scope`. It keeps `width` children in
21649
+ * flight and admits the next queued unit of work the instant one settles, instead of waiting for
21650
+ * a whole round to drain (`fanout`) or for a driver to decide again (`spawn → await → spawn`).
21651
+ *
21652
+ * The gap it closes: `fanout` opens every item at once and then drains — one round, no refill —
21653
+ * and a driver brain's manual loop opens one worker per model turn. Between those two there was
21654
+ * nothing that holds N slots full, which is why a 5-worker run can peak at 2 live workers and sit
21655
+ * ~50% idle. This is a policy over the EXISTING `Scope.spawn` / `Scope.next` primitives: it adds
21656
+ * no second admission path, so the conserved budget pool stays the only fence on total work and
21657
+ * `width` is only a fence on simultaneous work.
21658
+ *
21659
+ * Fail-closed by construction: an admission rejection (`budget-exhausted` / `depth-exceeded`) is
21660
+ * recorded and STOPS further admission — the loop then drains what is already live and returns.
21661
+ * It never retries a rejected spawn against the same pool, and it never spawns past `width`.
21662
+ *
21663
+ * ── Concurrency ────────────────────────────────────────────────────────────────────────────────
21664
+ *
21665
+ * `width` bounds the children THIS dispatcher holds in flight. The tree-wide bound on working
21666
+ * agents is `SuperviseOptions.workerSlots` (`./worker-slots`): a spawn past it is queued by the
21667
+ * scope, not refused, so a `width` above the free slots only lengthens the allocator's queue.
21668
+ * `SandboxLineage`'s fork concurrency bounds boxes inside ONE leaf's fork wave, a different unit.
21669
+ *
21670
+ * ── Why this is not a copy of the kernel's batch loop ──────────────────────────────────────────
21671
+ *
21672
+ * `runBatch` (`src/runtime/run-loop.ts`) runs the same hold-N-slots-full shape over the KERNEL's
21673
+ * substrate: bare promises in a `Set`, raced with `Promise.race`, bounded by `maxConcurrency`.
21674
+ * This one runs it over the SUPERVISOR's substrate — `Scope.spawn`'s atomic reservation against
21675
+ * the conserved pool, `Scope.next`'s journaled settlement cursor, and the blob store behind each
21676
+ * result. Neither can be expressed in the other's terms without dragging its whole substrate
21677
+ * along: the kernel loop has no budget to reserve and no cursor to order settlements by, and this
21678
+ * one cannot race raw promises because a settlement is only real once it is journaled. The shape
21679
+ * repeating across the two deliberate layers is resonance, not duplication — do not "unify" them
21680
+ * into a shared helper that would have to know about both.
21681
+ *
21682
+ * @experimental
21683
+ */
21684
+ /**
21685
+ * Run the refilling dispatch loop over `scope` until the queue is dry (or a stop fires) and every
21686
+ * admitted child has settled. Returns the settlements in cursor order plus the admission ledger.
21687
+ *
21688
+ * The loop is: fill free slots from `nextUnit` → `await scope.next()` → deliver the settlement →
21689
+ * refill → repeat. Because the refill happens immediately after each settlement rather than after
21690
+ * a whole round, a slow child never idles the other slots.
21691
+ */
21692
+ async function rollingDispatch(scope, opts) {
21693
+ if (!Number.isInteger(opts.width) || opts.width < 1) throw new ValidationError$1(`rollingDispatch: width must be a positive integer, got ${String(opts.width)}`);
21694
+ const settled = [];
21695
+ const rejected = [];
21696
+ const live = /* @__PURE__ */ new Set();
21697
+ let admitted = 0;
21698
+ let peakLive = 0;
21699
+ let queueDry = false;
21700
+ let stopReason = "drained";
21701
+ const fill = async () => {
21702
+ while (live.size < opts.width) {
21703
+ if (queueDry) return;
21704
+ if (scope.signal.aborted) {
21705
+ stopReason = "aborted";
21706
+ queueDry = true;
21707
+ return;
21708
+ }
21709
+ if (opts.shouldStop?.() === true) {
21710
+ stopReason = "stopped";
21711
+ queueDry = true;
21712
+ return;
21713
+ }
21714
+ const unit = await opts.nextUnit();
21715
+ if (unit === void 0) {
21716
+ queueDry = true;
21717
+ return;
21718
+ }
21719
+ const res = scope.spawn(unit.agent, unit.task, unit.opts);
21720
+ if (!res.ok) {
21721
+ rejected.push(`${unit.opts.label}: ${res.reason}`);
21722
+ stopReason = "not-admitted";
21723
+ queueDry = true;
21724
+ return;
21725
+ }
21726
+ live.add(res.handle.id);
21727
+ admitted += 1;
21728
+ if (live.size > peakLive) peakLive = live.size;
21729
+ }
21730
+ };
21731
+ await fill();
21732
+ while (live.size > 0) {
21733
+ const s = await scope.next();
21734
+ if (s === null) break;
21735
+ live.delete(s.handle.id);
21736
+ settled.push(s);
21737
+ await opts.onSettled?.(s);
21738
+ await fill();
21739
+ }
21740
+ return {
21741
+ settled,
21742
+ admitted,
21743
+ rejected,
21744
+ stopReason,
21745
+ peakLive
21746
+ };
21747
+ }
21748
+ /**
21749
+ * Free worker slots under a simultaneity cap: `cap - live`, floored at 0, or `null` when there is
21750
+ * no cap (the conserved pool is then the only fence and "free slots" is not a finite number).
21751
+ * The one place the answer is computed, so the driver-facing tool payload and a dispatcher agree.
21752
+ */
21753
+ function freeSlots(liveCount, cap) {
21754
+ if (cap === void 0 || cap <= 0) return null;
21755
+ return Math.max(0, cap - liveCount);
21756
+ }
21757
+ /** Convenience: a `DispatchUnit` factory over a fixed array of tasks, for the common case where
21758
+ * the queue is known up front and only the refill behavior is wanted. */
21759
+ function queueOf(units, budget) {
21760
+ let i = 0;
21761
+ return () => {
21762
+ const u = units[i];
21763
+ if (u === void 0) return void 0;
21764
+ i += 1;
21765
+ return {
21766
+ agent: u.agent,
21767
+ task: u.task,
21768
+ opts: {
21769
+ budget,
21770
+ label: u.label
21771
+ }
21772
+ };
21773
+ };
21774
+ }
21775
+ //#endregion
21776
+ //#region src/runtime/retained-interactive-handle.ts
21777
+ function createRetainedInteractiveRunHandle(environment, inputRef, capabilities, requestedStart) {
21778
+ const ref = freezeInteractiveRef(inputRef);
21779
+ const source = environment.interactive(ref);
21780
+ if (!sameInteractiveRef(source.ref, ref)) throw new Error("provider reconstructed a different interactive process");
21781
+ if (!source.sendPrompt) throw new Error("provider declared interactive prompt support but exposed no prompt method");
21782
+ return Object.freeze({
21783
+ ref,
21784
+ capabilities,
21785
+ claimControl: async (request, options) => exactClaim(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.claimControl(request, options)), options?.signal)),
21786
+ status: async (options) => exactStatus(ref, await awaitAbortable$1(Promise.resolve().then(() => source.status(options)), options?.signal), requestedStart),
21787
+ attach: async (request, options) => exactTerminal(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.attach(request, options)), options?.signal)),
21788
+ sendPrompt: async (command, options) => exactPrompt(ref, await awaitAbortable$1(Promise.resolve().then(() => source.sendPrompt(command, options)), options?.signal), command),
21789
+ stop: async (command, options) => exactStop(ref, await awaitAbortable$1(Promise.resolve().then(() => source.stop(command, options)), options?.signal), command)
21790
+ });
21791
+ }
21792
+ function freezeInteractiveRef(value) {
21793
+ return detachedSnapshot(AgentInteractiveSessionRefSchema.parse(value), "interactive session ref");
21794
+ }
21795
+ function exactClaim(ref, request, value) {
21796
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionControlClaimAcknowledgementSchema, value, "control claim");
21797
+ if (!agentInteractiveSessionControlClaimAcknowledgementMatchesRequest(request, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a control claim acknowledgement for another request");
21798
+ if (acknowledgement.control && !agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a control claim for another interactive process");
21799
+ return acknowledgement;
21800
+ }
21801
+ function exactPrompt(ref, value, command) {
21802
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionPromptAcknowledgementSchema, value, "prompt");
21803
+ if (!agentInteractiveSessionPromptAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another request");
21804
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another interactive process");
21805
+ return acknowledgement;
21806
+ }
21807
+ function exactStop(ref, value, command) {
21808
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionStopAcknowledgementSchema, value, "stop");
21809
+ if (!agentInteractiveSessionStopAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another request");
21810
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another interactive process");
21811
+ return acknowledgement;
21812
+ }
21813
+ function parseProviderAcknowledgement(schema, value, operation) {
21814
+ try {
21815
+ return schema.parse(value);
21816
+ } catch {
21817
+ throw new RetainedRunProviderContractError(`provider returned an invalid interactive ${operation} acknowledgement`);
21818
+ }
21819
+ }
21820
+ function exactStatus(ref, value, requestedStart) {
21821
+ let status;
21822
+ try {
21823
+ status = AgentInteractiveSessionStatusSchema.parse(value);
21824
+ } catch (error) {
21825
+ if (requestedStart === void 0) throw error;
21826
+ throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), {}, { cause: error });
21827
+ }
21828
+ if (!agentInteractiveSessionStatusMatchesRef(ref, status)) {
21829
+ if (requestedStart !== void 0) throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), detachedSnapshot({ status: detachedSnapshot(status, "interactive provider status") }, "interactive provider status result"), { cause: /* @__PURE__ */ new Error("provider returned status for another interactive process") });
21830
+ throw new Error("provider returned status for another interactive process");
21831
+ }
21832
+ return status;
21833
+ }
21834
+ function exactTerminal(ref, request, terminal) {
21835
+ const terminalRef = TerminalSessionRefSchema.parse(terminal.ref);
21836
+ TerminalReplayWindowSchema.parse(terminal.cursors);
21837
+ if (terminalRef.parentExecutionId !== ref.run.executionId) throw new Error("provider attached a terminal from another interactive run");
21838
+ AgentInteractiveSessionControlClaimSchema.parse(terminal.control);
21839
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, terminal.control)) throw new Error("provider attached a terminal with a claim for another interactive process");
21840
+ if (canonicalCandidateDigest(terminal.control) !== canonicalCandidateDigest(request.control)) throw new Error("provider attached a terminal with a different interactive control claim");
21841
+ return terminal;
21842
+ }
21843
+ function sameInteractiveRef(left, right) {
21844
+ return canonicalCandidateDigest(left) === canonicalCandidateDigest(right);
21845
+ }
21846
+ //#endregion
21847
+ //#region src/runtime/retained-interactive.ts
21848
+ /**
21849
+ * Start one retry-safe native coding-agent TUI without dispatching a headless turn.
21850
+ * The intent admission is durable before provider.create; the environment and
21851
+ * process admissions follow only after their exact provider coordinates exist.
21852
+ * @stable
21853
+ */
21854
+ async function startRetainedInteractiveRun(options) {
21855
+ options.signal?.throwIfAborted();
21856
+ const startOptions = options;
21857
+ assertStableText(startOptions.environment.idempotencyKey, "environment idempotency key");
21858
+ assertStableText(startOptions.interactiveIdempotencyKey, "interactive idempotency key");
21859
+ if (typeof startOptions.onAdmission !== "function") throw new Error("startRetainedInteractiveRun requires an awaited onAdmission durability hook");
21860
+ if (!startOptions.provider.get) throw new Error(`provider "${startOptions.provider.name}" cannot reconstruct an environment by id`);
21861
+ const profile = agentProfileSchema.parse(startOptions.environment.profile);
21862
+ if (profile.harness === void 0) throw new Error("retained interactive runs require AgentProfile.harness");
21863
+ const requestedProfileDigest = canonicalAgentProfileDigest(profile);
21864
+ const identity = startOptions.intent === void 0 ? mintRetainedIdentity(startOptions.environment.idempotencyKey, startOptions.interactiveIdempotencyKey) : {
21865
+ sessionId: startOptions.intent.sessionId,
21866
+ executionId: startOptions.intent.executionId
21867
+ };
21868
+ assertStableText(identity.sessionId, "retained session id");
21869
+ assertStableText(identity.executionId, "retained execution id");
21870
+ const intent = interactiveIntent(startOptions, profile, identity);
21871
+ if (startOptions.intent === void 0) await admitDurably(startOptions.onAdmission, intent);
21872
+ else assertExactInteractiveIntent(startOptions.intent, intent);
21873
+ const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => startOptions.provider.capabilities()), startOptions.signal));
21874
+ assertInteractiveCapabilities(startOptions.provider.name, providerCapabilities);
21875
+ const environment = await createInteractiveEnvironment(() => startOptions.provider.create({
21876
+ ...startOptions.environment,
21877
+ profile,
21878
+ signal: startOptions.signal,
21879
+ metadata: retainedEnvironmentMetadata(startOptions.environment.metadata, startOptions.environment.idempotencyKey)
21880
+ }), startOptions.signal);
21881
+ let capabilities;
21882
+ try {
21883
+ assertExactEnvironment(startOptions.provider.name, environment);
21884
+ startOptions.signal?.throwIfAborted();
21885
+ capabilities = interactiveCapabilitiesForEnvironment(startOptions.provider.name, providerCapabilities, environment);
21886
+ assertInteractiveMethods(startOptions.provider.name, environment);
21887
+ } catch (error) {
21888
+ await destroyUnusedEnvironment(environment, error);
21889
+ throw error;
21890
+ }
21891
+ const request = interactiveRequest(startOptions, environment, profile, requestedProfileDigest, identity);
21892
+ await admitDurably(startOptions.onAdmission, {
21893
+ phase: "interactive_environment",
21894
+ provider: startOptions.provider.name,
21895
+ environmentId: environment.id,
21896
+ idempotencyKey: startOptions.environment.idempotencyKey,
21897
+ interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
21898
+ request
21899
+ });
21900
+ const ref = exactStartedRef(request, await startInteractiveProcess(environment, () => environment.startInteractive(request, { signal: startOptions.signal }), startOptions.signal));
21901
+ await admitDurably(startOptions.onAdmission, {
21902
+ phase: "interactive_started",
21903
+ idempotencyKey: startOptions.environment.idempotencyKey,
21904
+ interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
21905
+ ref
21906
+ });
21907
+ return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
21908
+ }
21909
+ /**
21910
+ * Retry one exact start after its provider response may have been lost.
21911
+ *
21912
+ * Resolves to the handle of the admitted process (resumed through the exact,
21913
+ * idempotent start request), or `null` when the provider no longer holds the
21914
+ * environment (not found; nothing remains to stop). @stable
21915
+ */
21916
+ async function recoverRetainedInteractiveRun(options) {
21917
+ options.signal?.throwIfAborted();
21918
+ if (typeof options.onAdmission !== "function") throw new Error("recoverRetainedInteractiveRun requires an awaited onAdmission durability hook");
21919
+ const admission = options.admission;
21920
+ if (admission.provider !== options.provider.name) throw new Error("interactive admission belongs to another provider");
21921
+ if (admission.phase === "interactive_intent") {
21922
+ if (options.replay === void 0) throw new Error("recoverRetainedInteractiveRun requires the original start material for an interactive intent");
21923
+ return startRetainedInteractiveRun({
21924
+ provider: options.provider,
21925
+ ...options.replay,
21926
+ intent: admission,
21927
+ onAdmission: options.onAdmission,
21928
+ signal: options.signal
21929
+ });
21930
+ }
21931
+ const request = exactRecoveryRequest(admission);
21932
+ const { environment, capabilities } = await reconstructEnvironment(options.provider, admission.environmentId, options.signal);
21933
+ if (!environment || !capabilities) return null;
21934
+ const ref = exactStartedRef(request, await awaitAbortable$1(Promise.resolve().then(() => environment.startInteractive(request, { signal: options.signal })), options.signal));
21935
+ await admitDurably(options.onAdmission, {
21936
+ phase: "interactive_started",
21937
+ idempotencyKey: admission.idempotencyKey,
21938
+ interactiveIdempotencyKey: admission.interactiveIdempotencyKey,
21939
+ ref
21940
+ });
21941
+ return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
21942
+ }
21943
+ function exactRecoveryRequest(admission) {
21944
+ assertStableText(admission.environmentId, "interactive environment id");
21945
+ assertStableText(admission.idempotencyKey, "environment idempotency key");
21946
+ assertStableText(admission.interactiveIdempotencyKey, "interactive idempotency key");
21947
+ const request = exactAgentInteractiveSessionStart(admission.request);
21948
+ const identity = mintRetainedIdentity(admission.idempotencyKey, admission.interactiveIdempotencyKey);
21949
+ if (request.run.provider !== admission.provider || request.run.environmentId !== admission.environmentId || (request.run.sessionId !== identity.sessionId || request.run.executionId !== identity.executionId) && !matchesHistoricalInteractiveIdentity(admission, request)) throw new Error("interactive admission does not match its recovery coordinates");
21950
+ return request;
21951
+ }
21952
+ function matchesHistoricalInteractiveIdentity(admission, request) {
21953
+ const base = `${encodeURIComponent(admission.idempotencyKey)}:${encodeURIComponent(admission.interactiveIdempotencyKey)}`;
21954
+ const digest = canonicalCandidateDigest({
21955
+ kind: "retained-identity.v1",
21956
+ base
21957
+ }).slice(7);
21958
+ const historicalId = (prefix) => {
21959
+ const readable = `${prefix}:${base}`;
21960
+ return readable.length <= 128 ? readable : `${prefix}:${digest}`;
21961
+ };
21962
+ return request.run.sessionId === historicalId("retained-session") && request.run.executionId === historicalId("retained-execution");
21963
+ }
21964
+ /** Rebuild controls for one exact provider-owned coding-agent process. @stable */
21965
+ async function reconnectRetainedInteractiveRun(options) {
21966
+ options.signal?.throwIfAborted();
21967
+ const ref = AgentInteractiveSessionRefSchema.parse(options.ref);
21968
+ if (ref.run.provider !== options.provider.name) throw new Error("interactive session reference belongs to another provider");
21969
+ const { environment, capabilities } = await reconstructEnvironment(options.provider, ref.run.environmentId, options.signal);
21970
+ if (!environment || !capabilities) return null;
21971
+ const handle = createRetainedInteractiveRunHandle(environment, ref, capabilities);
21972
+ await handle.status({ signal: options.signal });
21973
+ return handle;
21974
+ }
21975
+ function interactiveRequest(options, environment, profile, requestedProfileDigest, identity) {
21976
+ const start = {
21977
+ profile,
21978
+ requestedProfileDigest,
21979
+ ...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
21980
+ ...options.cwd === void 0 ? {} : { cwd: options.cwd },
21981
+ ...options.cols === void 0 ? {} : { cols: options.cols },
21982
+ ...options.rows === void 0 ? {} : { rows: options.rows }
21983
+ };
21984
+ return exactAgentInteractiveSessionStart({
21985
+ run: agentInteractiveSessionRunRef({
21986
+ provider: options.provider.name,
21987
+ environmentId: environment.id,
21988
+ ...identity
21989
+ }, start),
21990
+ ...start
21991
+ });
21992
+ }
21993
+ function interactiveIntent(options, profile, identity) {
21994
+ const requestedProfileDigest = canonicalAgentProfileDigest(profile);
21995
+ const requestDigest = canonicalCandidateDigest({
21996
+ kind: "retained-interactive-intent.v1",
21997
+ provider: options.provider.name,
21998
+ idempotencyKey: options.environment.idempotencyKey,
21999
+ interactiveIdempotencyKey: options.interactiveIdempotencyKey,
22000
+ sessionId: identity.sessionId,
22001
+ executionId: identity.executionId,
22002
+ requestedProfileDigest,
22003
+ create: retainedCreateMaterial(options.environment),
22004
+ start: sanitizedStartMaterial(options)
22005
+ });
22006
+ return {
22007
+ phase: "interactive_intent",
22008
+ provider: options.provider.name,
22009
+ idempotencyKey: options.environment.idempotencyKey,
22010
+ interactiveIdempotencyKey: options.interactiveIdempotencyKey,
22011
+ sessionId: identity.sessionId,
22012
+ executionId: identity.executionId,
22013
+ runId: `interactive-intent-run:${requestDigest.slice(7)}`,
22014
+ requestedProfileDigest,
22015
+ requestDigest
22016
+ };
22017
+ }
22018
+ function sanitizedStartMaterial(options) {
22019
+ return {
22020
+ ...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
22021
+ ...options.cwd === void 0 ? {} : { cwd: options.cwd },
22022
+ ...options.cols === void 0 ? {} : { cols: options.cols },
22023
+ ...options.rows === void 0 ? {} : { rows: options.rows }
22024
+ };
22025
+ }
22026
+ function assertExactInteractiveIntent(received, expected) {
22027
+ if (canonicalCandidateDigest(parseInteractiveIntent(received)) !== canonicalCandidateDigest(expected)) throw new Error("interactive intent conflicts with replay material");
22028
+ }
22029
+ function parseInteractiveIntent(value) {
22030
+ const stable = detachedSnapshot(value, "interactive intent");
22031
+ if (stable === null || typeof stable !== "object" || Array.isArray(stable)) throw new Error("interactive intent is malformed");
22032
+ const record = stable;
22033
+ const allowed = /* @__PURE__ */ new Set([
22034
+ "phase",
22035
+ "provider",
22036
+ "idempotencyKey",
22037
+ "interactiveIdempotencyKey",
22038
+ "sessionId",
22039
+ "executionId",
22040
+ "runId",
22041
+ "requestedProfileDigest",
22042
+ "requestDigest"
22043
+ ]);
22044
+ if (Object.keys(record).some((key) => !allowed.has(key))) throw new Error("interactive intent contains unsupported material");
22045
+ if (record.phase !== "interactive_intent") throw new Error("interactive intent has an invalid phase");
22046
+ for (const [key, value] of Object.entries(record)) {
22047
+ if (key === "phase") continue;
22048
+ if (typeof value !== "string" || value.length === 0) throw new Error(`interactive intent field "${key}" is invalid`);
22049
+ }
22050
+ assertDigest$1(record.requestedProfileDigest, "interactive intent profile digest");
22051
+ assertDigest$1(record.requestDigest, "interactive intent request digest");
22052
+ return stable;
22053
+ }
22054
+ function assertDigest$1(value, label) {
22055
+ if (typeof value !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(value)) throw new Error(`${label} is invalid`);
22056
+ }
22057
+ async function reconstructEnvironment(provider, environmentId, signal) {
22058
+ if (!provider.get) throw new Error(`provider "${provider.name}" cannot reconstruct an environment by id`);
22059
+ const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => provider.capabilities()), signal));
22060
+ assertInteractiveCapabilities(provider.name, providerCapabilities);
22061
+ const environment = await awaitAbortable$1(Promise.resolve().then(() => provider.get(environmentId, { signal })), signal);
22062
+ if (!environment) return {
22063
+ environment: null,
22064
+ capabilities: null
22065
+ };
22066
+ assertExactEnvironment(provider.name, environment, environmentId);
22067
+ const capabilities = interactiveCapabilitiesForEnvironment(provider.name, providerCapabilities, environment);
22068
+ assertInteractiveMethods(provider.name, environment);
22069
+ return {
22070
+ environment,
22071
+ capabilities
22072
+ };
22073
+ }
22074
+ function exactStartedRef(request, value) {
22075
+ const stableRequest = detachedSnapshot(request, "interactive start binding request");
22076
+ let ref;
22077
+ try {
22078
+ ref = AgentInteractiveSessionRefSchema.parse(value);
22079
+ } catch (error) {
22080
+ throw new RetainedInteractiveBindingError(stableRequest, {}, { cause: error });
22081
+ }
22082
+ if (!agentInteractiveSessionRefMatchesStart(request, ref)) throw new RetainedInteractiveBindingError(stableRequest, detachedSnapshot({ ref: detachedSnapshot(ref, "interactive provider start reference") }, "interactive provider start result"), { cause: /* @__PURE__ */ new Error("provider started another interactive run than requested") });
22083
+ return freezeInteractiveRef(ref);
22084
+ }
22085
+ function assertExactEnvironment(providerName, environment, environmentId) {
22086
+ if (environment.provider !== providerName || environmentId && environment.id !== environmentId) throw new Error("provider returned another interactive environment");
22087
+ assertStableText(environment.id, "interactive environment id");
22088
+ }
22089
+ function interactiveCapabilitiesForEnvironment(providerName, providerCapabilities, environment) {
22090
+ const capabilities = environment.capabilities === void 0 ? providerCapabilities : AgentEnvironmentCapabilitiesSchema.parse(environment.capabilities);
22091
+ assertInteractiveCapabilities(providerName, capabilities);
22092
+ return capabilities;
22093
+ }
22094
+ function assertInteractiveCapabilities(providerName, capabilities) {
22095
+ const interactive = capabilities.interactiveAgent;
22096
+ if (!interactive?.start || !interactive.control || !interactive.status || !interactive.attach || !interactive.reattach || !interactive.sendPrompt || !interactive.input || !interactive.resize || !interactive.stop) throw new Error(`provider "${providerName}" cannot control an exact interactive agent`);
22097
+ }
22098
+ function assertInteractiveMethods(providerName, environment) {
22099
+ if (!environment.startInteractive || !environment.interactive) throw new Error(`provider "${providerName}" exposes incomplete interactive agent controls`);
22100
+ }
22101
+ async function destroyUnusedEnvironment(environment, cause) {
22102
+ try {
22103
+ await destroyInteractiveEnvironment(environment);
22104
+ } catch (cleanupError) {
22105
+ throw new AggregateError([cause, cleanupError], "interactive environment was invalid and could not be destroyed");
22106
+ }
22107
+ }
22108
+ //#endregion
22109
+ //#region src/runtime/supervise/worker-interactive.ts
22110
+ const WORKER_BINDING_SCHEMA_VERSION = 1;
22111
+ const SPAWN_JOURNAL_FILE = "spawn-journal.jsonl";
22112
+ /** Directory containing exact per-worker interactive binding records. @stable */
22113
+ function workerInteractiveBindingsDir(eventDir) {
22114
+ return join(eventDir, "interactive-workers");
22115
+ }
22116
+ /** Exact durable binding file for one worker id. @stable */
22117
+ function workerInteractiveBindingFile(eventDir, workerId) {
22118
+ const id = stableText$1(workerId, "worker id");
22119
+ const stem = createHash("sha256").update(id).digest("hex");
22120
+ return join(workerInteractiveBindingsDir(eventDir), `${stem}.json`);
22121
+ }
22122
+ /** Read and validate one exact durable worker binding. @stable */
22123
+ function readWorkerInteractiveBinding(eventDir, workerId) {
22124
+ const id = stableText$1(workerId, "worker id");
22125
+ const file = workerInteractiveBindingFile(eventDir, id);
21370
22126
  assertNoSymlinkDescendant(eventDir, file, "worker interactive");
21371
22127
  if (!existsSync(file)) return void 0;
21372
22128
  const binding = parseBinding(JSON.parse(readFileSync(file, "utf8")));
@@ -21798,6 +22554,25 @@ function stableText(value, label) {
21798
22554
  return text;
21799
22555
  }
21800
22556
  //#endregion
22557
+ //#region src/runtime/supervise/provider-visible-profile.ts
22558
+ /** Runtime-owned coordination is mounted under this MCP alias. */
22559
+ const coordinationMcpAlias = "agent-runtime-coordination";
22560
+ /** A profile declares Runtime-owned tools with this provider-neutral prefix. */
22561
+ const coordinationProfileToolPrefix = `${coordinationMcpAlias.replaceAll("-", "_")}_`;
22562
+ /** Remove Runtime-only grants and seat policy from the provider-facing profile. */
22563
+ function providerVisibleProfile(profile) {
22564
+ const { seats: _seats, ...withoutSeats } = profile;
22565
+ if (profile.tools === void 0) return withoutSeats;
22566
+ const providerTools = Object.fromEntries(Object.entries(profile.tools).filter(([name]) => !name.startsWith(coordinationProfileToolPrefix)));
22567
+ if (Object.keys(providerTools).length === Object.keys(profile.tools).length) return withoutSeats;
22568
+ if (Object.keys(providerTools).length > 0) return {
22569
+ ...withoutSeats,
22570
+ tools: providerTools
22571
+ };
22572
+ const { tools: _runtimeTools, ...withoutTools } = withoutSeats;
22573
+ return withoutTools;
22574
+ }
22575
+ //#endregion
21801
22576
  //#region src/runtime/supervise/terminal-record.ts
21802
22577
  /** The settlement fields every writer copies, in the terminal record's key order. The
21803
22578
  * `reconciled` record is built from this same spread so it and the terminal record can never
@@ -21950,7 +22725,7 @@ async function healReleasedSlots(opts, signal, now) {
21950
22725
  };
21951
22726
  await opts.journal.appendEvent(tree.root, terminalDownEvent(subject, settlement, settledSeq, floor.at, "released"));
21952
22727
  healed += 1;
21953
- const materialized = owned.find((event) => event.kind === "materialized");
22728
+ const materialized = [...owned].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized");
21954
22729
  const lastReceipt = receipts[receipts.length - 1];
21955
22730
  notifyRuntimeHookEvent(opts.hooks, {
21956
22731
  id: `${spawned.id}:released`,
@@ -22032,7 +22807,7 @@ async function prepareInterruptedExecutors(opts, events, signal, now, parentId =
22032
22807
  });
22033
22808
  if (!prepared) continue;
22034
22809
  }
22035
- const priorMaterialization = owned.find((event) => event.kind === "materialized")?.receipt;
22810
+ const priorMaterialization = [...owned].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized")?.receipt;
22036
22811
  const continuation = latestInput !== void 0 && inputs.length > 1 && node.ownedTreeRoot === void 0 ? await leafContinuation(node, owned, latestInput, opts) : void 0;
22037
22812
  recoveries.push({
22038
22813
  ...detachedSnapshot({
@@ -22100,7 +22875,7 @@ async function leafContinuation(node, owned, latestInput, opts) {
22100
22875
  }
22101
22876
  async function assertRecordedResult(node, result, events, opts) {
22102
22877
  const before = events.slice(0, events.indexOf(result));
22103
- const receipt = before.find((event) => event.kind === "materialized")?.receipt;
22878
+ const receipt = [...before].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized")?.receipt;
22104
22879
  const binding = [...before].reverse().find((event) => event.kind === "execution-bound")?.binding;
22105
22880
  if (receipt?.status !== "known" || binding?.status !== "known" || receipt.runtime !== node.runtime || receipt.authoredProfileDigest !== node.identity?.profileDigest || binding.materializationReceiptDigest !== canonicalCandidateDigest(receipt)) throw new RuntimeRunStateError(`retained result '${node.id}' has no matching execution evidence`);
22106
22881
  assertValidSpend(result.spent, `retained result '${result.id}'`);
@@ -22682,6 +23457,10 @@ function registerScopeRetainedOwner(scope, args) {
22682
23457
  function scopeRetainedOwnerContext(scope) {
22683
23458
  return owners.get(scope)?.context;
22684
23459
  }
23460
+ /** The journal tree that owns this manager turn, including nested driver children. */
23461
+ function scopeRetainedOwnerJournalRoot(scope) {
23462
+ return owners.get(scope)?.args.rootId;
23463
+ }
22685
23464
  /**
22686
23465
  * Bind cleanup before replay can return an already accepted owner result. `checkpointCapture` is
22687
23466
  * where each checkpoint's files are stored before the checkpoint is deleted; without it, no
@@ -22796,6 +23575,59 @@ function noteScopeRetainedOwnerCoordination(scope) {
22796
23575
  delete state.checkpointing;
22797
23576
  });
22798
23577
  }
23578
+ /** A committed turn is the seat boundary. Keep its native home for a same-harness provider
23579
+ * continuation; only a provider/harness change needs a new environment. */
23580
+ async function prepareScopeRetainedOwnerSeatSwitch(scope, mode) {
23581
+ const state = owners.get(scope);
23582
+ if (!state?.acceptedRef || !state.acceptedConsumed) throw new ValidationError$1("seat switch requires a committed owner turn");
23583
+ const accepted = state.acceptedRef;
23584
+ await scopeRetainedOwnerTurnEnded(scope);
23585
+ await state.checkpointing;
23586
+ await checkpointOwnerWorkspace(scope, state);
23587
+ const owned = (await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId);
23588
+ const acceptedIndex = owned.findIndex((event) => event.kind === "execution-result" && event.seq === accepted.seq && event.outRef === accepted.outRef);
23589
+ if (acceptedIndex < 0) throw new ValidationError$1("seat switch has no committed result in its journal");
23590
+ const source = owned.slice(0, acceptedIndex).reverse().find((event) => event.kind === "execution-admitted" && event.admission.phase === "environment");
23591
+ const sourceEnvironmentId = source?.kind === "execution-admitted" && source.admission.phase === "environment" ? source.admission.environmentId : void 0;
23592
+ const checkpoint = sourceEnvironmentId !== void 0 ? owned.slice(acceptedIndex + 1).reverse().find((event) => event.kind === "workspace-checkpoint" && event.environmentId === sourceEnvironmentId) : void 0;
23593
+ if (checkpoint?.kind !== "workspace-checkpoint") throw new ValidationError$1("seat switch requires a checkpoint of the committed source environment");
23594
+ if (mode === "replace-environment") {
23595
+ await retireSeatEnvironment(scope, state);
23596
+ state.forceNewSession = true;
23597
+ }
23598
+ return {
23599
+ checkpointAt: checkpoint.at,
23600
+ checkpointId: checkpoint.checkpoint.checkpointId,
23601
+ sourceEnvironmentId: checkpoint.environmentId
23602
+ };
23603
+ }
23604
+ /** The next seat receives fresh create-time credentials. Release the stopped source only after
23605
+ * its checkpoint exists, then commit the teardown so recovery never tries its old session. */
23606
+ async function retireSeatEnvironment(scope, state) {
23607
+ const { provider, args } = state;
23608
+ if (!provider?.get) throw new ValidationError$1("seat switch requires a provider with exact environment lookup");
23609
+ const owned = (await args.journal.loadTree(args.rootId) ?? []).filter((event) => event.id === args.nodeId);
23610
+ const admitted = [...owned].reverse().find((event) => event.kind === "execution-admitted" && event.admission.phase === "environment");
23611
+ if (admitted?.kind !== "execution-admitted" || admitted.admission.phase !== "environment") throw new ValidationError$1("seat switch has no committed source environment");
23612
+ const environmentId = admitted.admission.environmentId;
23613
+ if (owned.some((event) => event.kind === "environment-teardown" && event.destroyed && event.environmentId === environmentId)) return;
23614
+ const signal = AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]);
23615
+ const environment = await runAbortable(() => provider.get(environmentId), signal, "seat switch environment lookup timed out");
23616
+ if (environment !== null) {
23617
+ if (environment.id !== environmentId || environment.provider !== provider.name || !environment.destroy) throw new ValidationError$1("seat switch cannot retire the exact source environment");
23618
+ await runAbortable(() => environment.destroy(), signal, "seat switch environment retirement timed out");
23619
+ }
23620
+ await args.journal.appendEvent(args.rootId, {
23621
+ kind: "environment-teardown",
23622
+ id: args.nodeId,
23623
+ provider: provider.name,
23624
+ environmentId,
23625
+ destroyed: true,
23626
+ detail: "seat changed after a committed turn",
23627
+ seq: state.nextSequence(),
23628
+ at: new Date(args.now()).toISOString()
23629
+ });
23630
+ }
22799
23631
  async function checkpointOwnerWorkspace(scope, state) {
22800
23632
  const { provider, args } = state;
22801
23633
  if (provider === void 0) return;
@@ -22973,7 +23805,8 @@ async function cleanCheckpoints(state, branching, checkpoints, events, parent) {
22973
23805
  for (const event of checkpoints) {
22974
23806
  const captured = await captureBeforeCleanup(state, branching, event, events, parent);
22975
23807
  if ("reason" in captured) {
22976
- (state.captureRefused ??= /* @__PURE__ */ new Set()).add(event.checkpoint.checkpointId);
23808
+ state.captureRefused ??= /* @__PURE__ */ new Set();
23809
+ state.captureRefused.add(event.checkpoint.checkpointId);
22977
23810
  refused.push(captured);
22978
23811
  await state.args.journal.appendEvent(state.args.rootId, {
22979
23812
  kind: "workspace-checkpoint-cleanup",
@@ -23193,8 +24026,8 @@ async function settleCaptureForks(state) {
23193
24026
  * environment needs one; a live environment is continued, never copied.
23194
24027
  */
23195
24028
  function restoreBefore(owned, inputIndex) {
23196
- const destroyed = destroyedEnvironmentIds(owned);
23197
- return owned.slice(0, inputIndex < 0 ? owned.length : inputIndex).filter((event) => event.kind === "workspace-checkpoint" && destroyed.has(event.environmentId)).at(-1);
24029
+ const unusable = unusableEnvironmentIds(owned);
24030
+ return owned.slice(0, inputIndex < 0 ? owned.length : inputIndex).filter((event) => event.kind === "workspace-checkpoint" && unusable.has(event.environmentId)).at(-1);
23198
24031
  }
23199
24032
  async function restoreCapable(provider) {
23200
24033
  if (provider === void 0) return false;
@@ -23215,7 +24048,8 @@ async function scopeRetainedOwnerRestorePoint(scope) {
23215
24048
  const latest = restoreBefore((await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId), -1);
23216
24049
  return latest === void 0 ? void 0 : {
23217
24050
  checkpointId: latest.checkpoint.checkpointId,
23218
- takenAt: latest.at
24051
+ takenAt: latest.at,
24052
+ sourceEnvironmentId: latest.checkpoint.source.environmentId
23219
24053
  };
23220
24054
  }
23221
24055
  /** @internal Whether another owner release could still destroy what the last one left. */
@@ -23539,9 +24373,9 @@ function hasDurableWorkspaceCapture(output, snapshot, environmentId, executionId
23539
24373
  const linked = agentCandidateWorkspaceSnapshotEvidenceSchema.safeParse(receipt.snapshot);
23540
24374
  return linked.success && linked.data.digest === parsed.data.digest && JSON.stringify(linked.data.manifest) === JSON.stringify(parsed.data.manifest) && JSON.stringify(linked.data.archive) === JSON.stringify(parsed.data.archive);
23541
24375
  }
23542
- /** Environment ids this owner's provider confirmed gone, from their teardown receipts. */
23543
- function destroyedEnvironmentIds(owned) {
23544
- return new Set(owned.flatMap((event) => event.kind === "environment-teardown" && event.destroyed ? [event.environmentId] : []));
24376
+ /** Environments that cannot execute another turn, whether absent or terminal at the provider. */
24377
+ function unusableEnvironmentIds(owned) {
24378
+ return new Set(owned.flatMap((event) => event.kind === "environment-terminal" || event.kind === "environment-teardown" && event.destroyed ? [event.environmentId] : []));
23545
24379
  }
23546
24380
  /** The environment the owner's next invocation would continue in, when there is one: the latest
23547
24381
  * environment admission of this owner, which is either the current invocation's own (recovered
@@ -23570,8 +24404,9 @@ function continuedEnvironment(owned) {
23570
24404
  * commissioned settled `done` two minutes later, unread.
23571
24405
  *
23572
24406
  * The reconciliation refusal protects against paying twice for an execution that may still run.
23573
- * An environment the provider no longer holds runs nothing, so there is nothing to reconcile: the
23574
- * loss is journaled as a destroyed teardown receipt, and the next prepare starts a new invocation.
24407
+ * An environment the provider no longer holds or reports terminal runs nothing. Runtime records
24408
+ * the provider's exact observation before the next prepare starts a new invocation. A terminal
24409
+ * record still requires cleanup at settlement; it is not a teardown receipt.
23575
24410
  */
23576
24411
  async function reconcileScopeRetainedOwnerEnvironment(scope) {
23577
24412
  const state = owners.get(scope);
@@ -23581,7 +24416,7 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
23581
24416
  const continued = continuedEnvironment(owned);
23582
24417
  if (continued === void 0) return { state: "none" };
23583
24418
  const environmentId = continued.admission.environmentId;
23584
- if (destroyedEnvironmentIds(owned).has(environmentId)) return {
24419
+ if (unusableEnvironmentIds(owned).has(environmentId)) return {
23585
24420
  state: "lost",
23586
24421
  environmentId
23587
24422
  };
@@ -23590,21 +24425,31 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
23590
24425
  environmentId
23591
24426
  };
23592
24427
  let environment;
24428
+ let terminalStatus;
23593
24429
  try {
23594
24430
  environment = await runAbortable(() => provider.get(environmentId), AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]), "retained owner environment check timed out");
24431
+ if (environment !== null) {
24432
+ const found = environment;
24433
+ if (found.id !== environmentId || found.provider !== provider.name) return {
24434
+ state: "unknown",
24435
+ environmentId
24436
+ };
24437
+ const status = await runAbortable(() => found.status(), AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]), "retained owner environment status timed out");
24438
+ if (status === "failed" || status === "expired") terminalStatus = status;
24439
+ }
23595
24440
  } catch {
23596
24441
  return {
23597
24442
  state: "unknown",
23598
24443
  environmentId
23599
24444
  };
23600
24445
  }
23601
- if (environment !== null) return {
24446
+ if (environment !== null && terminalStatus === void 0) return {
23602
24447
  state: "live",
23603
24448
  environmentId,
23604
24449
  inFlight: continued.inFlight
23605
24450
  };
23606
24451
  scope.signal.throwIfAborted();
23607
- await args.journal.appendEvent(args.rootId, {
24452
+ await args.journal.appendEvent(args.rootId, terminalStatus === void 0 ? {
23608
24453
  kind: "environment-teardown",
23609
24454
  id: args.nodeId,
23610
24455
  provider: provider.name,
@@ -23613,6 +24458,14 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
23613
24458
  detail: "lost: the provider no longer holds this environment, so the next invocation starts in a new one",
23614
24459
  seq: state.nextSequence(),
23615
24460
  at: new Date(args.now()).toISOString()
24461
+ } : {
24462
+ kind: "environment-terminal",
24463
+ id: args.nodeId,
24464
+ provider: provider.name,
24465
+ environmentId,
24466
+ status: terminalStatus,
24467
+ seq: state.nextSequence(),
24468
+ at: new Date(args.now()).toISOString()
23616
24469
  });
23617
24470
  return {
23618
24471
  state: "lost",
@@ -23635,9 +24488,9 @@ async function prepareScopeRetainedOwnerTask(scope, task) {
23635
24488
  const accepted = [...attempt].reverse().find((event) => event.kind === "execution-result");
23636
24489
  if (accepted?.kind === "execution-result") state.acceptedRef = accepted;
23637
24490
  }
23638
- const destroyed = destroyedEnvironmentIds(owned);
24491
+ const unusable = unusableEnvironmentIds(owned);
23639
24492
  const inFlight = continuedEnvironment(owned);
23640
- if (inFlight?.inFlight && destroyed.has(inFlight.admission.environmentId)) {
24493
+ if (inFlight?.inFlight && unusable.has(inFlight.admission.environmentId)) {
23641
24494
  delete state.inputSequence;
23642
24495
  delete state.taskRef;
23643
24496
  state.admissions.length = 0;
@@ -23653,7 +24506,15 @@ async function prepareScopeRetainedOwnerTask(scope, task) {
23653
24506
  state.admissions.length = 0;
23654
24507
  delete state.acceptedConsumed;
23655
24508
  }
23656
- if (state.priorSession !== void 0 && destroyed.has(state.priorSession.environmentId)) delete state.priorSession;
24509
+ if (state.priorSession !== void 0 && unusable.has(state.priorSession.environmentId)) delete state.priorSession;
24510
+ const segmentStarts = owned.filter((event) => event.kind === "seat-segment" && event.phase === "started");
24511
+ const latestSeat = segmentStarts.at(-1);
24512
+ const previousSeat = segmentStarts.at(-2);
24513
+ if (latestSeat && previousSeat && latestSeat.provider !== previousSeat.provider && owned.indexOf(latestSeat) > owned.indexOf(latestInput)) state.forceNewSession = true;
24514
+ if (state.forceNewSession) {
24515
+ delete state.priorSession;
24516
+ delete state.forceNewSession;
24517
+ }
23657
24518
  state.prepared = true;
23658
24519
  const capable = await restoreCapable(state.provider);
23659
24520
  const restoreFor = (inputIndex) => {
@@ -23702,26 +24563,247 @@ async function scopeRetainedOwnerResult(scope) {
23702
24563
  if (out === void 0 || contentAddress(out) !== event.outRef) throw new ValidationError$1("retained owner result is missing or corrupt");
23703
24564
  assertValidSpend(event.spent, "replayed retained owner result");
23704
24565
  return {
23705
- outRef: event.outRef,
23706
- out,
23707
- spent: event.spent,
23708
- ...event.verdict ? { verdict: event.verdict } : {},
23709
- ...event.outcome ? { outcome: event.outcome } : {}
24566
+ outRef: event.outRef,
24567
+ out,
24568
+ spent: event.spent,
24569
+ ...event.verdict ? { verdict: event.verdict } : {},
24570
+ ...event.outcome ? { outcome: event.outcome } : {}
24571
+ };
24572
+ }
24573
+ async function scopeRetainedOwnerPriorSpend(scope) {
24574
+ const state = owners.get(scope);
24575
+ if (!state) return zeroSpend();
24576
+ const events = (await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId);
24577
+ const input = [...events].reverse().find((event) => event.kind === "execution-input");
24578
+ if (!input) return zeroSpend();
24579
+ return events.slice(events.indexOf(input)).reduce((total, event) => event.kind === "metered" ? addSpend(total, event.spend) : total, zeroSpend());
24580
+ }
24581
+ /** Called only after the scope verifies the accepted invocation's materialization. */
24582
+ function consumeScopeRetainedOwnerResult(scope) {
24583
+ const state = owners.get(scope);
24584
+ if (!state?.acceptedRef) throw new ValidationError$1("retained owner has no accepted result");
24585
+ state.acceptedConsumed = true;
24586
+ }
24587
+ //#endregion
24588
+ //#region src/runtime/supervise/seat-chain.ts
24589
+ var SeatChainExhaustedError = class extends Error {
24590
+ resumeAt;
24591
+ constructor(resumeAt) {
24592
+ super(`authored subscription seat chain exhausted; resume at ${resumeAt}`);
24593
+ this.name = "SeatChainExhaustedError";
24594
+ this.resumeAt = resumeAt;
24595
+ }
24596
+ };
24597
+ /** One logical node's durable chain. The spawn journal is the sole transition authority. */
24598
+ var SeatChain = class {
24599
+ profile;
24600
+ nodeId;
24601
+ rootId;
24602
+ journal;
24603
+ select;
24604
+ now;
24605
+ onSegment;
24606
+ beforeStart;
24607
+ observedThrough = -1;
24608
+ constructor(profile, nodeId, rootId, journal, select, now = Date.now, onSegment, beforeStart) {
24609
+ this.profile = profile;
24610
+ this.nodeId = nodeId;
24611
+ this.rootId = rootId;
24612
+ this.journal = journal;
24613
+ this.select = select;
24614
+ this.now = now;
24615
+ this.onSegment = onSegment;
24616
+ this.beforeStart = beforeStart;
24617
+ }
24618
+ async next(afterUsageLimit = false, afterRecheck = false) {
24619
+ const stages = authoredSeatStages(this.profile);
24620
+ if (!stages) throw new ValidationError$1("SeatChain requires authored AgentProfile.seats");
24621
+ const allEvents = await this.journal.loadTree(this.rootId) ?? [];
24622
+ const events = allEvents.filter((event) => event.kind === "seat-segment" && event.id === this.nodeId);
24623
+ const destroyed = new Set(allEvents.filter((event) => event.kind === "environment-teardown" && event.id === this.nodeId && event.destroyed).map((event) => event.environmentId));
24624
+ let admittedEnvironmentId;
24625
+ for (const event of allEvents) if (event.kind === "execution-admitted" && event.id === this.nodeId && event.admission.phase === "environment") admittedEnvironmentId = event.admission.environmentId;
24626
+ const retainedEnvironmentId = admittedEnvironmentId !== void 0 && !destroyed.has(admittedEnvironmentId) ? admittedEnvironmentId : void 0;
24627
+ await this.reconcile(events);
24628
+ const starts = events.filter((event) => event.phase === "started");
24629
+ const last = starts.at(-1);
24630
+ const closed = last && events.some((event) => event.phase === "ended" && event.segmentIndex === last.segmentIndex);
24631
+ if (last && !closed && afterUsageLimit) await this.end(last, "usage-limit");
24632
+ const resume = last && !closed && !afterUsageLimit;
24633
+ const segmentIndex = resume ? last.segmentIndex : (last?.segmentIndex ?? -1) + 1;
24634
+ const firstStageIndex = afterRecheck ? 0 : last?.stageIndex ?? 0;
24635
+ let earliestReset;
24636
+ for (let stageIndex = firstStageIndex; stageIndex < stages.length; stageIndex += 1) {
24637
+ const stage = stages[stageIndex];
24638
+ const excludedSeatIds = (afterRecheck ? [] : starts).filter((event) => event.stageIndex === stageIndex && (!resume || event.seat !== last.seat)).map((event) => event.seat);
24639
+ const prior = last === void 0 ? void 0 : {
24640
+ seat: last.seat,
24641
+ harness: last.harness,
24642
+ provider: last.provider,
24643
+ model: last.model
24644
+ };
24645
+ const preceding = resume ? starts.at(-2) : last;
24646
+ const requiresNativeTurnGrant = Boolean(preceding && preceding.provider === stage.provider && preceding.harness === stage.harness && (!resume || preceding.seat !== last.seat));
24647
+ const selection = checkedSeatSelection(stage, await this.select({
24648
+ profile: this.profile,
24649
+ nodeId: this.nodeId,
24650
+ stage,
24651
+ stageIndex,
24652
+ segmentIndex,
24653
+ excludedSeatIds,
24654
+ requiresNativeTurnGrant,
24655
+ ...retainedEnvironmentId === void 0 ? {} : { retainedEnvironmentId },
24656
+ ...prior === void 0 ? {} : { previous: prior },
24657
+ ...resume ? { resumeSeatId: last.seat } : {}
24658
+ }));
24659
+ if ("resumeAt" in selection) {
24660
+ const reset = Date.parse(selection.resumeAt);
24661
+ earliestReset = earliestReset === void 0 ? reset : Math.min(earliestReset, reset);
24662
+ if (resume) break;
24663
+ continue;
24664
+ }
24665
+ if (resume && selection.seat !== last.seat) throw new ValidationError$1("selectSeat: resume changed the committed seat");
24666
+ if (excludedSeatIds.includes(selection.seat)) throw new ValidationError$1("selectSeat: selected an exhausted seat");
24667
+ if (preceding && preceding.seat !== selection.seat && preceding.provider === stage.provider && preceding.harness === stage.harness && selection.nativeTurnGrant !== true) throw new ValidationError$1("selectSeat: same-environment seat requires a verified native turn grant");
24668
+ const active = {
24669
+ seat: selection.seat,
24670
+ stageIndex,
24671
+ segmentIndex,
24672
+ stage,
24673
+ backend: selection.backend,
24674
+ ...selection.nativeTurnGrant === true ? { nativeTurnGrant: true } : {},
24675
+ ...preceding === void 0 ? {} : { previous: {
24676
+ seat: preceding.seat,
24677
+ harness: preceding.harness,
24678
+ provider: preceding.provider,
24679
+ model: preceding.model
24680
+ } }
24681
+ };
24682
+ if (!resume) {
24683
+ await this.beforeStart?.(active, prior);
24684
+ const at = new Date(this.now()).toISOString();
24685
+ await this.journal.appendEvent(this.rootId, {
24686
+ kind: "seat-segment",
24687
+ id: this.nodeId,
24688
+ segmentIndex,
24689
+ stageIndex,
24690
+ phase: "started",
24691
+ seat: selection.seat,
24692
+ harness: stage.harness,
24693
+ provider: stage.provider,
24694
+ model: stage.model,
24695
+ seq: segmentIndex,
24696
+ at
24697
+ });
24698
+ await this.onSegment?.({
24699
+ seat: selection.seat,
24700
+ harness: stage.harness,
24701
+ provider: stage.provider,
24702
+ model: stage.model,
24703
+ startedAt: at
24704
+ }, "started");
24705
+ this.observedThrough = events.length;
24706
+ return active;
24707
+ }
24708
+ return active;
24709
+ }
24710
+ const recheckAt = Math.max(earliestReset ?? 0, this.now() + 12e4);
24711
+ throw new SeatChainExhaustedError(new Date(recheckAt).toISOString());
24712
+ }
24713
+ async close(reason) {
24714
+ const events = (await this.journal.loadTree(this.rootId) ?? []).filter((event) => event.kind === "seat-segment" && event.id === this.nodeId);
24715
+ await this.reconcile(events);
24716
+ const last = events.filter((event) => event.phase === "started").at(-1);
24717
+ if (last && !events.some((event) => event.phase === "ended" && event.segmentIndex === last.segmentIndex)) await this.end(last, reason);
24718
+ }
24719
+ async end(start, reason) {
24720
+ const at = new Date(this.now()).toISOString();
24721
+ await this.journal.appendEvent(this.rootId, {
24722
+ ...start,
24723
+ phase: "ended",
24724
+ reason,
24725
+ at
24726
+ });
24727
+ await this.onSegment?.({
24728
+ seat: start.seat,
24729
+ harness: start.harness,
24730
+ provider: start.provider,
24731
+ model: start.model,
24732
+ startedAt: start.at,
24733
+ endedAt: at,
24734
+ reason
24735
+ }, "ended");
24736
+ this.observedThrough += 1;
24737
+ }
24738
+ /** A crash may land between the authoritative journal append and observer delivery. On
24739
+ * reconstruction, deliver every unobserved boundary again; the observer projection folds
24740
+ * repeated boundaries by seat and start time, so a callback never decides execution identity. */
24741
+ async reconcile(events) {
24742
+ const starts = /* @__PURE__ */ new Map();
24743
+ for (let index = 0; index < events.length; index += 1) {
24744
+ const event = events[index];
24745
+ if (event.phase === "started") starts.set(event.segmentIndex, event);
24746
+ if (index <= this.observedThrough) continue;
24747
+ const start = event.phase === "started" ? event : starts.get(event.segmentIndex);
24748
+ if (!start) throw new ValidationError$1("seat segment ended without a committed start");
24749
+ await this.onSegment?.({
24750
+ seat: start.seat,
24751
+ harness: start.harness,
24752
+ provider: start.provider,
24753
+ model: start.model,
24754
+ startedAt: start.at,
24755
+ ...event.phase === "ended" ? {
24756
+ endedAt: event.at,
24757
+ reason: event.reason
24758
+ } : {}
24759
+ }, event.phase);
24760
+ this.observedThrough = index;
24761
+ }
24762
+ }
24763
+ };
24764
+ /** Preserve the authored profile for identity; only the provider-facing copy changes stages. */
24765
+ function seatExecutionProfile(profile, stage) {
24766
+ const { seats: _seats, ...withoutSeats } = profile;
24767
+ return {
24768
+ ...withoutSeats,
24769
+ harness: stage.harness,
24770
+ ...stage.tools === void 0 ? {} : { tools: stage.tools },
24771
+ ...stage.permissions === void 0 ? {} : { permissions: stage.permissions },
24772
+ model: {
24773
+ ...profile.model,
24774
+ default: stage.model,
24775
+ provider: stage.provider
24776
+ }
23710
24777
  };
23711
24778
  }
23712
- async function scopeRetainedOwnerPriorSpend(scope) {
23713
- const state = owners.get(scope);
23714
- if (!state) return zeroSpend();
23715
- const events = (await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId);
23716
- const input = [...events].reverse().find((event) => event.kind === "execution-input");
23717
- if (!input) return zeroSpend();
23718
- return events.slice(events.indexOf(input)).reduce((total, event) => event.kind === "metered" ? addSpend(total, event.spend) : total, zeroSpend());
24779
+ function authoredSeatStages(profile) {
24780
+ const seats = profile.seats;
24781
+ if (seats === void 0) return void 0;
24782
+ if (!Array.isArray(seats) || seats.length === 0) throw new ValidationError$1("AgentProfile.seats must be a nonempty ordered chain");
24783
+ return seats;
23719
24784
  }
23720
- /** Called only after the scope verifies the accepted invocation's materialization. */
23721
- function consumeScopeRetainedOwnerResult(scope) {
23722
- const state = owners.get(scope);
23723
- if (!state?.acceptedRef) throw new ValidationError$1("retained owner has no accepted result");
23724
- state.acceptedConsumed = true;
24785
+ const USAGE_LIMIT_CODES = /* @__PURE__ */ new Set([
24786
+ "subscription_usage_limit",
24787
+ "usage_limit_reached",
24788
+ "usage_limit_exceeded",
24789
+ "weekly_limit_reached",
24790
+ "session_limit_reached"
24791
+ ]);
24792
+ /** Normalize a native harness refusal into a typed limit. A plain HTTP 429 is insufficient. */
24793
+ function subscriptionUsageLimitSignal(failure) {
24794
+ if (failure.errorCode && USAGE_LIMIT_CODES.has(failure.errorCode.toLowerCase())) return "subscription-usage-limit";
24795
+ if (/\bYou've hit your (?:usage|weekly|session) limit\b/iu.test(failure.error)) return "subscription-usage-limit";
24796
+ }
24797
+ /** An ineligible or misconfigured account must never turn an authored stage into another model. */
24798
+ function checkedSeatSelection(stage, selected) {
24799
+ if ("resumeAt" in selected) {
24800
+ if (!Number.isFinite(Date.parse(selected.resumeAt))) throw new ValidationError$1("selectSeat: resumeAt must be an ISO timestamp");
24801
+ return selected;
24802
+ }
24803
+ if (!selected.seat.trim()) throw new ValidationError$1("selectSeat: seat must be nonempty");
24804
+ if (stage.selector.kind === "seat" && stage.selector.id !== selected.seat) throw new ValidationError$1("selectSeat: selection does not match the authored seat");
24805
+ if (selected.backend.backend !== "provider") throw new ValidationError$1("selectSeat: selection must use a provider backend");
24806
+ return selected;
23725
24807
  }
23726
24808
  //#endregion
23727
24809
  //#region src/runtime/supervise/scope.ts
@@ -25139,7 +26221,23 @@ async function publishOwnerMaterialization(state, runtime, declaration, bindingI
25139
26221
  await rejectOwnerMaterialization(state);
25140
26222
  throw new ValidationError$1("scope owner returned invalid materialization evidence", { cause: error });
25141
26223
  }
25142
- if (state.prior !== void 0) {
26224
+ const committed = state.receipt ?? state.prior;
26225
+ if (committed?.status === "known" && canonicalCandidateDigest(committed) !== canonicalCandidateDigest(receipt)) {
26226
+ const events = await state.journal.loadTree(state.retainedRoot) ?? [];
26227
+ const started = [...events].reverse().find((event) => event.id === state.nodeId && event.kind === "seat-segment" && event.phase === "started");
26228
+ const latestMaterialization = [...events].reverse().find((event) => event.id === state.nodeId && (event.kind === "materialized" || event.kind === "seat-materialized"));
26229
+ const lastSegmentIndex = latestMaterialization?.kind === "seat-materialized" ? latestMaterialization.segmentIndex : 0;
26230
+ const authored = agentProfileSchema.safeParse(state.authoredProfile);
26231
+ const authoredProfile = authored.success ? authored.data : void 0;
26232
+ const stage = authoredProfile && started?.kind === "seat-segment" ? authoredSeatStages(authoredProfile)?.[started.stageIndex] : void 0;
26233
+ if (authoredProfile && stage && started?.kind === "seat-segment" && started.segmentIndex > lastSegmentIndex && started.harness === stage.harness && started.provider === stage.provider && started.model === stage.model && receipt.status === "known" && receipt.effectiveProfileDigest === canonicalAgentProfileDigest(providerVisibleProfile(seatExecutionProfile(authoredProfile, stage))) && receipt.model.status === "known" && receipt.model.id === stage.model) {
26234
+ await appendOwnerSeatMaterialization(state, started.segmentIndex, receipt, binding);
26235
+ state.onReceipt?.(receipt, binding);
26236
+ state.publishedThisProcess = true;
26237
+ return;
26238
+ }
26239
+ }
26240
+ if (state.prior !== void 0 && state.receipt === void 0) {
25143
26241
  if (canonicalCandidateDigest(state.prior) !== canonicalCandidateDigest(receipt)) {
25144
26242
  await rejectOwnerMaterialization(state);
25145
26243
  throw new ValidationError$1("scope owner materialization changed across resume; backend, model, execution identity, and plan must match");
@@ -25221,12 +26319,12 @@ async function restoreScopeOwnerAcceptedExecution(scope) {
25221
26319
  const resultIndex = latestResult === void 0 ? -1 : owned.indexOf(latestResult);
25222
26320
  const result = owned[resultIndex];
25223
26321
  if (inputIndex < 0 || resultIndex <= inputIndex || result?.kind !== "execution-result") throw new ValidationError$1("scope owner has no accepted retained invocation");
25224
- const receiptEvent = owned.slice(0, resultIndex).reverse().find((event) => event.kind === "materialized");
26322
+ const receiptEvent = owned.slice(0, resultIndex).reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized");
25225
26323
  const bindingEvent = owned.slice(inputIndex, resultIndex).reverse().find((event) => event.kind === "execution-bound");
25226
- if (receiptEvent?.kind !== "materialized" || bindingEvent?.kind !== "execution-bound") throw new ValidationError$1("accepted scope owner result has no preceding materialization evidence");
26324
+ if (receiptEvent?.kind !== "materialized" && receiptEvent?.kind !== "seat-materialized" || bindingEvent?.kind !== "execution-bound") throw new ValidationError$1("accepted scope owner result has no preceding materialization evidence");
25227
26325
  const { receipt } = receiptEvent;
25228
26326
  const { binding } = bindingEvent;
25229
- if (receipt.status !== "known" || binding.status !== "known" || receipt.runtime !== state.runtime || receipt.authoredProfileDigest !== state.authoredProfileDigest || binding.materializationReceiptDigest !== canonicalCandidateDigest(receipt) || state.prior !== void 0 && canonicalCandidateDigest(state.prior) !== canonicalCandidateDigest(receipt)) throw new ValidationError$1("accepted scope owner materialization does not match the resumed owner");
26327
+ if (receipt.status !== "known" || binding.status !== "known" || receipt.runtime !== state.runtime || receipt.authoredProfileDigest !== state.authoredProfileDigest || binding.materializationReceiptDigest !== canonicalCandidateDigest(receipt) || (state.receipt ?? state.prior) !== void 0 && canonicalCandidateDigest(state.receipt ?? state.prior) !== canonicalCandidateDigest(receipt)) throw new ValidationError$1("accepted scope owner materialization does not match the resumed owner");
25230
26328
  assertValidSpend(result.spent, "accepted scope owner result");
25231
26329
  const output = await state.blobs.get(result.outRef);
25232
26330
  if (output === void 0 || contentAddress(output) !== result.outRef) throw new ValidationError$1("accepted scope owner output is missing or corrupt");
@@ -25318,6 +26416,18 @@ async function appendOwnerMaterialization(state, receipt, binding) {
25318
26416
  state.receipt = receipt;
25319
26417
  await appendOwnerBinding(state, binding);
25320
26418
  }
26419
+ async function appendOwnerSeatMaterialization(state, segmentIndex, receipt, binding) {
26420
+ await appendOwnerEvidence(state, {
26421
+ kind: "seat-materialized",
26422
+ id: state.nodeId,
26423
+ segmentIndex,
26424
+ receipt,
26425
+ seq: segmentIndex,
26426
+ at: new Date(state.now()).toISOString()
26427
+ });
26428
+ state.receipt = receipt;
26429
+ await appendOwnerBinding(state, binding);
26430
+ }
25321
26431
  async function appendOwnerBinding(state, binding) {
25322
26432
  await appendOwnerEvidence(state, {
25323
26433
  kind: "execution-bound",
@@ -25332,10 +26442,10 @@ async function appendOwnerEvidence(state, event) {
25332
26442
  for (const root of /* @__PURE__ */ new Set([state.root, state.retainedRoot])) await appendExactMaterializationEvent(state.journal, root, event);
25333
26443
  }
25334
26444
  async function appendExactMaterializationEvent(journal, root, event) {
25335
- const prior = (await journal.loadTree(root))?.find((item) => item.id === event.id && (event.kind === "materialized" ? item.kind === "materialized" : item.kind === "execution-bound" && item.binding.attemptId === event.binding.attemptId));
25336
- if (prior?.kind === "materialized" || prior?.kind === "execution-bound") {
25337
- const previous = prior.kind === "materialized" ? prior.receipt : prior.binding;
25338
- const next = event.kind === "materialized" ? event.receipt : event.binding;
26445
+ const prior = (await journal.loadTree(root))?.find((item) => item.id === event.id && (event.kind === "materialized" ? item.kind === "materialized" : event.kind === "seat-materialized" ? item.kind === "seat-materialized" && item.segmentIndex === event.segmentIndex : item.kind === "execution-bound" && item.binding.attemptId === event.binding.attemptId));
26446
+ if (prior?.kind === "materialized" || prior?.kind === "seat-materialized" || prior?.kind === "execution-bound") {
26447
+ const previous = prior.kind === "execution-bound" ? prior.binding : prior.receipt;
26448
+ const next = event.kind === "execution-bound" ? event.binding : event.receipt;
25339
26449
  if (canonicalCandidateDigest(previous) !== canonicalCandidateDigest(next)) throw new ValidationError$1("scope execution evidence conflicts with its committed record");
25340
26450
  return;
25341
26451
  }
@@ -26213,7 +27323,7 @@ function isInfraError(err) {
26213
27323
  * journal so the executor can run its `act` inside a nested scope. `act` fails loud if
26214
27324
  * called directly — a driver child runs THROUGH its nested-scope executor, never as a root.
26215
27325
  */
26216
- function driverChild(profile, driver, journal, execution, acceptedSubmission, recoverExecutor, unassessedOutput) {
27326
+ function driverChild(profile, driver, journal, execution, acceptedSubmission, recoverExecutor, unassessedOutput, leafDeliverable) {
26217
27327
  const name = profile.name ?? driver.name;
26218
27328
  const traceSource = driver.traceSource;
26219
27329
  const progress = driver.progress;
@@ -26228,6 +27338,7 @@ function driverChild(profile, driver, journal, execution, acceptedSubmission, re
26228
27338
  journal,
26229
27339
  ...acceptedSubmission ? { acceptedSubmission } : {},
26230
27340
  ...unassessedOutput ? { unassessedOutput } : {},
27341
+ ...leafDeliverable ? { leafDeliverable } : {},
26231
27342
  ...recoverExecutor ? { recoverExecutor } : {},
26232
27343
  ...traceSource ? { traceSource } : {},
26233
27344
  ...progress ? { progress } : {},
@@ -26435,642 +27546,144 @@ function withDriverExecutor(base) {
26435
27546
  const spec = executableAgentSpecSnapshot(rawSpec, "driver executor registry");
26436
27547
  if (spec.driverRuntime === "driver" && !spec.executor) return {
26437
27548
  succeeded: true,
26438
- value: ((_ignored, context) => driverExecutorFactory(spec, context))
27549
+ value: ((_ignored, context) => isDriverSpec(spec) && spec.leafDeliverable ? attestNestedDriverTreeOwner(gateOnDeliverable(driverExecutorFactory(spec, context), spec.leafDeliverable)) : driverExecutorFactory(spec, context))
26439
27550
  };
26440
27551
  const resolved = base.resolve(spec);
26441
27552
  if (!resolved.succeeded) return resolved;
26442
27553
  return {
26443
- succeeded: true,
26444
- value: (_ignored, context) => resolved.value(spec, context)
26445
- };
26446
- }
26447
- };
26448
- }
26449
- async function closeNestedScope(scope, controller, reason) {
26450
- if (!controller.signal.aborted) controller.abort(reason);
26451
- for (;;) if (await scope.next() === null) break;
26452
- const view = scope.view;
26453
- if (view.inFlight > 0) throw new ValidationError$1(`driverExecutor: nested cleanup left ${view.inFlight} running nodes`);
26454
- }
26455
- /** The nested tree's full event list — the one evidence the spend, verdict, AND driver-inference
26456
- * roll-ups read off the same journal the supervisor sums. */
26457
- async function loadTreeEvents(journal, nestedRoot) {
26458
- const events = await journal.loadTree(nestedRoot);
26459
- if (events === void 0) throw new ValidationError$1(`driverExecutor: nested tree '${nestedRoot}' missing from the journal after run (corrupted log)`);
26460
- return events;
26461
- }
26462
- function isSettled(ev) {
26463
- return ev.kind === "settled" || ev.kind === "cancelled" && ev.spent !== void 0;
26464
- }
26465
- /** Sum the conserved spend over the nested tree's settled events — the honest per-channel
26466
- * roll-up of the whole sub-tree's child WORK. */
26467
- function sumSpend(settled) {
26468
- return settled.reduce((total, ev) => addSpend(total, ev.spent), zeroSpend());
26469
- }
26470
- /** Sum the nested tree's `metered` events — the sub-tree's whole driver INFERENCE (this driver's
26471
- * own turns + any sub-driver inference already re-homed into this tree). Re-homed up to the parent
26472
- * as one `metered` event; never reconciled (already pool-debited live via `observe`). */
26473
- function sumMetered(events) {
26474
- return events.reduce((total, ev) => ev.kind === "metered" ? addSpend(total, ev.spend) : total, zeroSpend());
26475
- }
26476
- /** An all-zero spend that carries an UNKNOWN marker counts as non-zero: a sub-driver whose turns
26477
- * went unmeasured did real work, and dropping its `metered` event here would re-hide upstream the
26478
- * very turn the driver refused to skip. */
26479
- function isNonZeroSpend(s) {
26480
- 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.keys(s.resources ?? {}).length > 0;
26481
- }
26482
- /** A spend, or `undefined` when it is all-zero — so `metered()` returns undefined for a driver
26483
- * whose sub-tree did no inference (and the parent journals no empty `metered` event). */
26484
- function nonZeroOrUndef(s) {
26485
- return isNonZeroSpend(s) ? s : void 0;
26486
- }
26487
- /** Sum the nested tree's metered events, tolerating a missing tree (a crash before `beginTree`
26488
- * landed) — never throw here, or it would mask the original `act` error on the crash path. */
26489
- async function safeRollup(journal, nestedRoot) {
26490
- try {
26491
- const events = await loadTreeEvents(journal, nestedRoot);
26492
- const childWork = sumSpend(events.filter(isSettled));
26493
- const metered = nonZeroOrUndef(sumMetered(events));
26494
- return {
26495
- metered,
26496
- accounting: {
26497
- reported: childWork,
26498
- reservation: addSpend(childWork, metered ?? zeroSpend())
26499
- }
26500
- };
26501
- } catch {
26502
- return;
26503
- }
26504
- }
26505
- /** Derive the driver child's delivery verdict from an accepted direct submission, or from its
26506
- * DIRECT children's settlements and the manager's actual finalized output: `valid` iff the
26507
- * manager's own assignment check accepted a submission, or a direct child delivered AND the
26508
- * finalizer returned a defined output;
26509
- * `score` = the best delivered score. Returns `undefined` when no child settled at all (the
26510
- * driver itself produced nothing to bubble a verdict from). Fail-closed: a child whose verdict
26511
- * carried no `valid` counts as not-delivered. */
26512
- function deriveDeliveryVerdict(settled, finalizedOutput, acceptedSubmission) {
26513
- if (acceptedSubmission) return {
26514
- valid: true,
26515
- score: 1
26516
- };
26517
- let sawChild = false;
26518
- let anyValid = false;
26519
- let bestValidScore;
26520
- let bestDoneScore;
26521
- for (const ev of settled) {
26522
- sawChild = true;
26523
- if (ev.status !== "done") continue;
26524
- const score = ev.verdict?.score;
26525
- if (score !== void 0 && (bestDoneScore === void 0 || score > bestDoneScore)) bestDoneScore = score;
26526
- if (ev.verdict?.valid === true) {
26527
- anyValid = true;
26528
- if (score !== void 0 && (bestValidScore === void 0 || score > bestValidScore)) bestValidScore = score;
26529
- }
26530
- }
26531
- if (!sawChild) return void 0;
26532
- const accepted = anyValid && finalizedOutput !== void 0;
26533
- return {
26534
- valid: accepted,
26535
- score: accepted ? bestValidScore ?? 1 : bestDoneScore ?? 0
26536
- };
26537
- }
26538
- function readNestedScopeSeam(ctx) {
26539
- const seam = ctx.seams[nestedScopeSeamKey];
26540
- if (!seam || typeof seam.mount !== "function") throw new ValidationError$1(`driverExecutor: missing required seam "${nestedScopeSeamKey}" — a driver child must be spawned through a Scope that seeds it (the keystone scope does)`);
26541
- return seam;
26542
- }
26543
- function isAgent(value) {
26544
- return typeof value === "object" && value !== null && typeof value.act === "function" && typeof value.name === "string";
26545
- }
26546
- /** Parent journals may already contain an interrupted driver's inference prefix. */
26547
- function unreportedSpend(total, prior) {
26548
- const tokens = { ...total.tokens };
26549
- for (const key of [
26550
- "input",
26551
- "output",
26552
- "freshInput",
26553
- "cacheRead",
26554
- "cacheWrite"
26555
- ]) {
26556
- const value = total.tokens[key];
26557
- if (value !== void 0) tokens[key] = Math.max(0, value - (prior.tokens[key] ?? 0));
26558
- }
26559
- return {
26560
- ...total,
26561
- ...addResourceSpend(total.resources === void 0 ? void 0 : Object.fromEntries(Object.entries(total.resources).map(([name, value]) => {
26562
- const previous = prior.resources?.[name];
26563
- if (previous && previous.unit !== value.unit) throw new ValidationError$1(`resource ${name}: unit mismatch`);
26564
- return [name, {
26565
- ...value,
26566
- amount: Math.max(0, value.amount - (previous?.amount ?? 0)),
26567
- known: value.known && (previous?.known ?? true)
26568
- }];
26569
- }))),
26570
- iterations: Math.max(0, total.iterations - prior.iterations),
26571
- tokens,
26572
- usd: Math.max(0, total.usd - prior.usd),
26573
- ms: Math.max(0, total.ms - prior.ms),
26574
- ...total.usdEstimated === void 0 ? {} : { usdEstimated: Math.max(0, total.usdEstimated - (prior.usdEstimated ?? 0)) },
26575
- ...total.boxMinutes === void 0 ? {} : { boxMinutes: Math.max(0, total.boxMinutes - (prior.boxMinutes ?? 0)) }
26576
- };
26577
- }
26578
- //#endregion
26579
- //#region src/runtime/supervise/continuation.ts
26580
- /**
26581
- * The continuation: what a manager with a completion check is told when its turn ends and the
26582
- * check is unmet, and the one rule that decides whether it is sent back.
26583
- *
26584
- * Measured on discovery-lab before this module (2026-09-24, 670 settled runs, 1,596 re-entries):
26585
- * 1,565 re-entries followed a failed turn and resent the original task, and 31 carried note text.
26586
- * The note Runtime wrote itself held seven fixed lines and no field for the check's verdict. Of 40
26587
- * episodes where the director ended on its own and the outside check disagreed, 33 were told
26588
- * nothing before they ended. 100 of 236 resubmits sent the identical packet. So the director
26589
- * mostly graded itself, and when it was wrong it heard nothing it could use.
26590
- *
26591
- * The design (discovery `docs/38-one-loop-and-continuation.md`) makes three things single, and
26592
- * this module holds the part Runtime owns:
26593
- *
26594
- * - ONE CHECK. A check reading is a {@link CheckVerdict}: pass, the items it read, the composite,
26595
- * and one `FAIL <item> <where>: <reason>` line per failed item. The same check decides
26596
- * `submit_result`, runs when a turn ends without an accepted result, scores the finished run,
26597
- * and ranks versions. A check that could not run gives no verdict ({@link CheckUnavailableError}),
26598
- * and the loop pauses instead of blaming the director.
26599
- * - ONE RESEND RULE. {@link ContinuationPolicy} is required for a manager with a check. It holds a
26600
- * deadline and `maxBarren`, the re-entered turns in a row that may end without progress. There
26601
- * is no re-prompt count and no default: a retry default in source is a research decision.
26602
- * - ONE NOTE. {@link composeContinuationNote} writes it. Runtime owns the facts and their order;
26603
- * the {@link ContinuationProfile} owns every instruction word, so an optimizer can change the
26604
- * words without touching code. A play may append a section, never remove or rewrite one.
26605
- *
26606
- * Evidence behind the note's shape: located errors help (given the first mistake's true location,
26607
- * fix rates rose 23.5 to 43.9 points, Tyen 2023); unsupported pressure does not (threats and tips
26608
- * had no significant effect, Wharton 2025; challenges without evidence flipped correct answers,
26609
- * FlipFlop); repeated summaries drop detail while itemized additions do not (ACE). So the note is
26610
- * a list of located facts, findings are added and marked resolved rather than rewritten, and the
26611
- * profile, not this file, decides how blunt the words are.
26612
- */
26613
- /**
26614
- * The check could not run: its box did not start, its judge's provider refused, its program
26615
- * crashed. It is not a verdict on the result. Inside a run the loop pauses, as it does for an
26616
- * unavailable upstream, and the refusal tells the director its result was not judged.
26617
- */
26618
- var CheckUnavailableError = class extends Error {
26619
- constructor(message, options) {
26620
- super(message, options);
26621
- this.name = "CheckUnavailableError";
26622
- }
26623
- };
26624
- /** Read a check function's return value into a verdict. Anything but `true` or a passing verdict
26625
- * is a failure: a check fails closed. */
26626
- function checkVerdictOf(outcome) {
26627
- if (outcome === true) return { pass: true };
26628
- if (typeof outcome !== "object" || outcome === null || Array.isArray(outcome)) return { pass: false };
26629
- const raw = outcome;
26630
- const items = typeof raw.items === "object" && raw.items !== null && !Array.isArray(raw.items) ? Object.fromEntries(Object.entries(raw.items).filter((entry) => typeof entry[1] === "number" && Number.isFinite(entry[1]))) : void 0;
26631
- const failures = Array.isArray(raw.failures) ? raw.failures.filter((line) => typeof line === "string" && line.trim() !== "") : void 0;
26632
- return Object.freeze({
26633
- pass: raw.pass === true,
26634
- ...items === void 0 ? {} : { items: Object.freeze(items) },
26635
- ...finite(raw.composite) ? { composite: raw.composite } : {},
26636
- ...finite(raw.threshold) ? { threshold: raw.threshold } : {},
26637
- ...failures === void 0 ? {} : { failures: Object.freeze(failures) },
26638
- ...typeof raw.review === "string" && raw.review.trim() !== "" ? { review: raw.review.trim() } : {}
26639
- });
26640
- }
26641
- /**
26642
- * Read an agent-eval `JudgeScore` from a check program into a verdict.
26643
- *
26644
- * Each dimension is a checked item. `notes` lines that start with `FAIL ` are the failures; the
26645
- * remaining lines are the check's review. The verdict passes when `composite >= threshold` and the
26646
- * score is not marked `failed`; a `failed` score means the judge itself did not run, which is
26647
- * {@link CheckUnavailableError}, not a verdict.
26648
- */
26649
- function verdictFromJudgeScore(score, threshold) {
26650
- if (score.failed === true) throw new CheckUnavailableError(`the check's judge did not run: ${score.notes}`);
26651
- const lines = score.notes.split("\n").map((line) => line.trimEnd());
26652
- const failures = lines.filter((line) => line.startsWith("FAIL "));
26653
- const review = lines.filter((line) => !line.startsWith("FAIL ") && line.trim() !== "").join("\n");
26654
- return checkVerdictOf({
26655
- pass: score.composite >= threshold,
26656
- items: score.dimensions,
26657
- composite: score.composite,
26658
- threshold,
26659
- failures,
26660
- ...review === "" ? {} : { review }
26661
- });
27554
+ succeeded: true,
27555
+ value: (_ignored, context) => resolved.value(spec, context)
27556
+ };
27557
+ }
27558
+ };
26662
27559
  }
26663
- /** Items that fail in `verdict`: every item below 1, or the named items of its FAIL lines. */
26664
- function failedItems(verdict) {
26665
- if (verdict.items !== void 0) return Object.entries(verdict.items).filter(([, value]) => value < 1).map(([name]) => name);
26666
- return (verdict.failures ?? []).map((line) => line.slice(5).split(/[\s:]/u)[0] ?? "");
27560
+ async function closeNestedScope(scope, controller, reason) {
27561
+ if (!controller.signal.aborted) controller.abort(reason);
27562
+ for (;;) if (await scope.next() === null) break;
27563
+ const view = scope.view;
27564
+ if (view.inFlight > 0) throw new ValidationError$1(`driverExecutor: nested cleanup left ${view.inFlight} running nodes`);
26667
27565
  }
26668
- /** Items that pass in `verdict`. */
26669
- function passedItems(verdict) {
26670
- return Object.entries(verdict.items ?? {}).filter(([, value]) => value >= 1).map(([name]) => name);
27566
+ /** The nested tree's full event list — the one evidence the spend, verdict, AND driver-inference
27567
+ * roll-ups read off the same journal the supervisor sums. */
27568
+ async function loadTreeEvents(journal, nestedRoot) {
27569
+ const events = await journal.loadTree(nestedRoot);
27570
+ if (events === void 0) throw new ValidationError$1(`driverExecutor: nested tree '${nestedRoot}' missing from the journal after run (corrupted log)`);
27571
+ return events;
26671
27572
  }
26672
- /** Resolve and check a policy before any compute. Returns the deadline in epoch ms. */
26673
- function admitContinuationPolicy(policy, context) {
26674
- if (typeof policy !== "object" || policy === null) throw new ValidationError$1(`${context}: continuation must be an object`);
26675
- const deadlineMs = typeof policy.deadline === "string" ? Date.parse(policy.deadline) : policy.deadline;
26676
- if (typeof deadlineMs !== "number" || !Number.isFinite(deadlineMs) || deadlineMs <= 0) throw new ValidationError$1(`${context}: continuation.deadline must be a finite time (epoch ms or ISO 8601)`);
26677
- if (!Number.isInteger(policy.maxBarren) || policy.maxBarren < 1) throw new ValidationError$1(`${context}: continuation.maxBarren must be an integer >= 1`);
26678
- if (policy.failures !== "verbatim" && policy.failures !== "off") throw new ValidationError$1(`${context}: continuation.failures must be 'verbatim' or 'off'`);
26679
- if (policy.panel !== "on" && policy.panel !== "off") throw new ValidationError$1(`${context}: continuation.panel must be 'on' or 'off'`);
26680
- if (policy.bar !== "on" && policy.bar !== "off") throw new ValidationError$1(`${context}: continuation.bar must be 'on' or 'off'`);
26681
- if (policy.panel === "on") {
26682
- if (typeof policy.runPanel !== "function") throw new ValidationError$1(`${context}: continuation.panel 'on' needs runPanel`);
26683
- const usd = policy.panelUsd;
26684
- if (usd === void 0 || !finite(usd.perContinuation) || !finite(usd.perRun) || usd.perContinuation <= 0 || usd.perRun < usd.perContinuation) throw new ValidationError$1(`${context}: continuation.panel 'on' needs panelUsd with 0 < perContinuation <= perRun`);
26685
- }
26686
- if (policy.append !== void 0 && typeof policy.append !== "function") throw new ValidationError$1(`${context}: continuation.append must be a function`);
26687
- admitContinuationProfile(policy.profile, context);
26688
- return deadlineMs;
27573
+ function isSettled(ev) {
27574
+ return ev.kind === "settled" || ev.kind === "cancelled" && ev.spent !== void 0;
26689
27575
  }
26690
- /** The facts a profile template may name. */
26691
- const CONTINUATION_FACTS = [
26692
- "composite",
26693
- "threshold",
26694
- "failed",
26695
- "total",
26696
- "reads",
26697
- "owed",
26698
- "settled",
26699
- "delivered",
26700
- "continuation"
26701
- ];
26702
- const factNames = new Set(CONTINUATION_FACTS);
26703
- const placeholder = /\{([a-zA-Z]+)\}/gu;
26704
- function admitContinuationProfile(profile, context) {
26705
- if (typeof profile !== "object" || profile === null) throw new ValidationError$1(`${context}: continuation.profile must be an object`);
26706
- if (typeof profile.id !== "string" || profile.id.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.id must be non-empty`);
26707
- const texts = [
26708
- ["opening", profile.opening],
26709
- ["plan", profile.plan],
26710
- ["rules", profile.rules],
26711
- ...Object.entries(profile.headings ?? {}).map(([key, value]) => [`headings.${key}`, value]),
26712
- ...profile.barRule === void 0 ? [] : [["barRule", profile.barRule]]
26713
- ];
26714
- for (const key of [
26715
- "failures",
26716
- "protected",
26717
- "changed",
26718
- "findings",
26719
- "bar",
26720
- "plan",
26721
- "rules"
26722
- ]) if (typeof profile.headings?.[key] !== "string") throw new ValidationError$1(`${context}: continuation.profile.headings.${key} must be a string`);
26723
- for (const [key, text] of texts) {
26724
- if (typeof text !== "string") throw new ValidationError$1(`${context}: continuation.profile.${key} must be a string`);
26725
- for (const match of text.matchAll(placeholder)) if (!factNames.has(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.${key} names {${match[1]}}, which is not a fact Runtime supplies (${CONTINUATION_FACTS.join(", ")})`);
26726
- }
26727
- if (profile.review !== void 0) {
26728
- if (typeof profile.review !== "string" || profile.review.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.review must be non-empty`);
26729
- for (const match of profile.review.matchAll(placeholder)) if (![
26730
- "version",
26731
- "path",
26732
- "score"
26733
- ].includes(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.review names {${match[1]}}; it may name {version}, {path} and {score}`);
26734
- }
26735
- if (profile.opening.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.opening must be non-empty`);
26736
- for (const [index, question] of (profile.questions ?? []).entries()) if (typeof question !== "string" || question.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.questions[${index}] must be a non-empty string`);
27576
+ /** Sum the conserved spend over the nested tree's settled events — the honest per-channel
27577
+ * roll-up of the whole sub-tree's child WORK. */
27578
+ function sumSpend(settled) {
27579
+ return settled.reduce((total, ev) => addSpend(total, ev.spent), zeroSpend());
26737
27580
  }
26738
- /** Findings reach the note only when every citation resolves, at least two distinct spans are
26739
- * cited, and the independent verifier agreed. The best method in Who&When found the failing step
26740
- * 14.2% of the time, so an unverified finding is noise with a citation. */
26741
- function admitFinding(finding) {
26742
- if (!finding.verified) return false;
26743
- if (finding.citations.length === 0) return false;
26744
- if (!finding.citations.every((citation) => citation.resolved)) return false;
26745
- return new Set(finding.citations.map((citation) => citation.uri)).size >= 2;
27581
+ /** Sum the nested tree's `metered` events — the sub-tree's whole driver INFERENCE (this driver's
27582
+ * own turns + any sub-driver inference already re-homed into this tree). Re-homed up to the parent
27583
+ * as one `metered` event; never reconciled (already pool-debited live via `observe`). */
27584
+ function sumMetered(events) {
27585
+ return events.reduce((total, ev) => ev.kind === "metered" ? addSpend(total, ev.spend) : total, zeroSpend());
26746
27586
  }
26747
- /** About 1,500 tokens of findings. */
26748
- const FINDINGS_CHAR_CAP = 6e3;
26749
- /**
26750
- * Rank the admitted findings by how many failed items they explain, drop repeats, and keep them
26751
- * within the note's cap. Earlier findings stay as they were written (ACE: itemized additions keep
26752
- * detail that repeated rewrites lose); a finding whose items all pass now is marked resolved.
26753
- */
26754
- function distillFindings(prior, proposed, failing, continuation) {
26755
- const key = (claim) => claim.toLowerCase().replace(/\s+/gu, " ").trim();
26756
- const known = new Set(prior.map((finding) => key(finding.claim)));
26757
- const carried = prior.map((finding) => finding.resolvedAt === void 0 && (finding.items?.length ?? 0) > 0 && (finding.items ?? []).every((item) => !failing.has(item)) ? {
26758
- ...finding,
26759
- resolvedAt: continuation
26760
- } : finding);
26761
- const fresh = proposed.filter(admitFinding).filter((finding) => {
26762
- const k = key(finding.claim);
26763
- if (known.has(k)) return false;
26764
- known.add(k);
26765
- return true;
26766
- }).map((finding) => ({
26767
- finding,
26768
- links: (finding.items ?? []).filter((item) => failing.has(item)).length
26769
- })).sort((a, b) => b.links - a.links);
26770
- const out = [...carried];
26771
- let used = carried.filter((finding) => finding.resolvedAt === void 0).reduce((sum, finding) => sum + finding.claim.length, 0);
26772
- for (const { finding } of fresh) {
26773
- if (used + finding.claim.length > FINDINGS_CHAR_CAP) break;
26774
- used += finding.claim.length;
26775
- out.push({
26776
- ...finding,
26777
- admittedAt: continuation
26778
- });
26779
- }
26780
- return out;
27587
+ /** An all-zero spend that carries an UNKNOWN marker counts as non-zero: a sub-driver whose turns
27588
+ * went unmeasured did real work, and dropping its `metered` event here would re-hide upstream the
27589
+ * very turn the driver refused to skip. */
27590
+ function isNonZeroSpend(s) {
27591
+ 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.keys(s.resources ?? {}).length > 0;
26781
27592
  }
26782
- /** Expand the profile's question templates over the failed items and the settled workers. */
26783
- function expandQuestions(templates, failing, workers) {
26784
- const out = [];
26785
- for (const template of templates) {
26786
- const hasItem = template.includes("{item}");
26787
- const hasWorker = template.includes("{worker}");
26788
- if (!hasItem && !hasWorker) {
26789
- out.push(template);
26790
- continue;
26791
- }
26792
- const items = hasItem ? failing : [""];
26793
- const each = hasWorker ? workers.map((worker) => `${worker.id} (${worker.label})`) : [""];
26794
- for (const item of items) for (const worker of each) out.push(template.replaceAll("{item}", item).replaceAll("{worker}", worker));
27593
+ /** A spend, or `undefined` when it is all-zero — so `metered()` returns undefined for a driver
27594
+ * whose sub-tree did no inference (and the parent journals no empty `metered` event). */
27595
+ function nonZeroOrUndef(s) {
27596
+ return isNonZeroSpend(s) ? s : void 0;
27597
+ }
27598
+ /** Sum the nested tree's metered events, tolerating a missing tree (a crash before `beginTree`
27599
+ * landed) — never throw here, or it would mask the original `act` error on the crash path. */
27600
+ async function safeRollup(journal, nestedRoot) {
27601
+ try {
27602
+ const events = await loadTreeEvents(journal, nestedRoot);
27603
+ const childWork = sumSpend(events.filter(isSettled));
27604
+ const metered = nonZeroOrUndef(sumMetered(events));
27605
+ return {
27606
+ metered,
27607
+ accounting: {
27608
+ reported: childWork,
27609
+ reservation: addSpend(childWork, metered ?? zeroSpend())
27610
+ }
27611
+ };
27612
+ } catch {
27613
+ return;
26795
27614
  }
26796
- return out;
26797
27615
  }
26798
- /**
26799
- * Write one continuation note, sections 1 to 8 of docs/38. Section 9, the run's state, is
26800
- * `composeReentryTask`, which wraps this text. Pure: the same input writes the same note.
26801
- */
26802
- function composeContinuationNote(input) {
26803
- const { profile, verdict } = input;
26804
- const items = verdict?.items ?? {};
26805
- const total = Object.keys(items).length;
26806
- const failing = verdict === void 0 ? [] : failedItems(verdict);
26807
- const facts = {
26808
- composite: verdict?.composite === void 0 ? "unknown" : format(verdict.composite),
26809
- threshold: verdict?.threshold === void 0 ? "unknown" : format(verdict.threshold),
26810
- failed: verdict === void 0 || total === 0 && (verdict.failures?.length ?? 0) === 0 ? "unknown" : String(failing.length),
26811
- total: total === 0 ? "unknown" : String(total),
26812
- reads: String(input.reads),
26813
- owed: input.owed?.trim() || "not described",
26814
- settled: String(input.progress.settledCount),
26815
- delivered: String(input.progress.deliveredCount ?? 0),
26816
- continuation: String(input.continuation)
26817
- };
26818
- const fill = (text) => text.replace(placeholder, (_, name) => facts[name] ?? `{${name}}`);
26819
- const sections = [verdict === void 0 ? "No check verdict is available yet." + (input.canSubmitResult === true ? " Submit a result through submit_result to request the check." : "") : verdict.pass ? "The check passes on the current state, but no result has been accepted." + (input.canSubmitResult === true ? " Call submit_result to request acceptance." : "") : fill(profile.opening).trim()];
26820
- const section = (heading, body) => {
26821
- if (body.length === 0) return;
26822
- sections.push([...heading.trim() === "" ? [] : [`## ${fill(heading)}`], ...body].join("\n"));
27616
+ /** Derive the driver child's delivery verdict from an accepted direct submission, or from its
27617
+ * DIRECT children's settlements and the manager's actual finalized output: `valid` iff the
27618
+ * manager's own assignment check accepted a submission, or a direct child delivered AND the
27619
+ * finalizer returned a defined output;
27620
+ * `score` = the best delivered score. Returns `undefined` when no child settled at all (the
27621
+ * driver itself produced nothing to bubble a verdict from). Fail-closed: a child whose verdict
27622
+ * carried no `valid` counts as not-delivered. */
27623
+ function deriveDeliveryVerdict(settled, finalizedOutput, acceptedSubmission) {
27624
+ if (acceptedSubmission) return {
27625
+ valid: true,
27626
+ score: 1
26823
27627
  };
26824
- if (input.failures === "verbatim" && verdict !== void 0) {
26825
- const lines = verdict.failures ?? [];
26826
- const shown = lines.slice(0, 40);
26827
- const more = lines.length - shown.length;
26828
- section(profile.headings.failures, [...shown, ...more > 0 ? [input.canReadMore ? `${more} more failure lines: call read_continuation with continuation ${input.continuation}.` : `${more} more failure lines are not shown.`] : []]);
26829
- const passing = passedItems(verdict);
26830
- section(profile.headings.protected, passing.length === 0 ? [] : [passing.join(", ")]);
26831
- if (input.previous !== void 0) {
26832
- const before = new Set(failedItems(input.previous));
26833
- const now = new Set(failing);
26834
- const fixed = [...before].filter((item) => !now.has(item));
26835
- const broke = [...now].filter((item) => !before.has(item));
26836
- section(profile.headings.changed, [
26837
- ...fixed.length === 0 ? [] : [`Now passing: ${fixed.join(", ")}.`],
26838
- ...broke.length === 0 ? [] : [`Newly failing: ${broke.join(", ")}.`],
26839
- ...fixed.length === 0 && broke.length === 0 ? ["No item changed since the last note."] : [],
26840
- ...input.previous.composite !== void 0 && verdict.composite !== void 0 ? [`Composite: ${format(input.previous.composite)} then ${format(verdict.composite)}.`] : []
26841
- ]);
26842
- }
26843
- }
26844
- if (input.findings !== void 0) {
26845
- const open = input.findings.filter((finding) => finding.resolvedAt === void 0);
26846
- const resolved = input.findings.filter((finding) => finding.resolvedAt === input.continuation);
26847
- section(profile.headings.findings, [...open.map((finding) => `- [hypothesis] ${finding.claim}` + (finding.items?.length ? ` (items: ${finding.items.join(", ")})` : "") + ` Evidence: ${finding.citations.map((citation) => citation.uri).join(", ")}`), ...resolved.map((finding) => `- [resolved] ${finding.claim}`)]);
26848
- }
26849
- if (input.bar !== void 0 && verdict !== void 0) {
26850
- const body = [];
26851
- if (profile.barRule?.trim()) body.push(fill(profile.barRule).trim());
26852
- for (const [item, value] of Object.entries(items)) {
26853
- const best = input.bar.best?.verdict.items?.[item];
26854
- body.push(`- ${item}: ${value >= 1 ? "passes" : `fails (${format(value)})`}` + (best === void 0 ? "" : ` / ${input.bar.best?.label}: ${best >= 1 ? "passes" : `fails (${format(best)})`}`));
27628
+ let sawChild = false;
27629
+ let anyValid = false;
27630
+ let bestValidScore;
27631
+ let bestDoneScore;
27632
+ for (const ev of settled) {
27633
+ sawChild = true;
27634
+ if (ev.status !== "done") continue;
27635
+ const score = ev.verdict?.score;
27636
+ if (score !== void 0 && (bestDoneScore === void 0 || score > bestDoneScore)) bestDoneScore = score;
27637
+ if (ev.verdict?.valid === true) {
27638
+ anyValid = true;
27639
+ if (score !== void 0 && (bestValidScore === void 0 || score > bestValidScore)) bestValidScore = score;
26855
27640
  }
26856
- if (input.bar.best?.verdict.composite !== void 0) body.push(`Best version ${input.bar.best.label}: composite ${format(input.bar.best.verdict.composite)}.`);
26857
- if (input.bar.reference?.trim()) body.push(`Reference result: ${input.bar.reference.trim()}`);
26858
- if (verdict.review?.trim()) body.push(`The check's review: ${verdict.review.trim()}`);
26859
- section(profile.headings.bar, body);
26860
27641
  }
26861
- section(profile.headings.plan, profile.plan.trim() === "" ? [] : [fill(profile.plan).trim()]);
26862
- section(profile.headings.rules, [...profile.rules.trim() === "" ? [] : [fill(profile.rules).trim()], ...input.sealed ? ["The score comes from cases you cannot see."] : []]);
26863
- for (const appended of input.appended ?? []) section(appended.heading, appended.text.trim() === "" ? [] : [appended.text.trim()]);
26864
- return sections.join("\n\n");
26865
- }
26866
- function summarizeVerdict(verdict) {
26867
- if (verdict === void 0) return null;
26868
- const total = Object.keys(verdict.items ?? {}).length;
27642
+ if (!sawChild) return void 0;
27643
+ const accepted = anyValid && finalizedOutput !== void 0;
26869
27644
  return {
26870
- pass: verdict.pass,
26871
- ...verdict.composite === void 0 ? {} : { composite: verdict.composite },
26872
- ...total === 0 ? {} : {
26873
- failed: failedItems(verdict).length,
26874
- total
26875
- }
27645
+ valid: accepted,
27646
+ score: accepted ? bestValidScore ?? 1 : bestDoneScore ?? 0
26876
27647
  };
26877
27648
  }
26878
- function noteDigest(note) {
26879
- return `sha256:${createHash("sha256").update(note).digest("hex")}`;
27649
+ function readNestedScopeSeam(ctx) {
27650
+ const seam = ctx.seams[nestedScopeSeamKey];
27651
+ if (!seam || typeof seam.mount !== "function") throw new ValidationError$1(`driverExecutor: missing required seam "${nestedScopeSeamKey}" — a driver child must be spawned through a Scope that seeds it (the keystone scope does)`);
27652
+ return seam;
26880
27653
  }
26881
- /** A run directory's continuation files: the root's at `<runDir>/continuations/<n>/`, a nested
26882
- * manager's at `<runDir>/continuations/managers/<owner>/<n>/`. */
26883
- const CONTINUATIONS_DIR = "continuations";
26884
- /**
26885
- * Write one continuation's files under `<dir>/<n>/`: `note.md`, `verdict.json`, and
26886
- * `panel.jsonl` when the panel ran. The director reads them through `read_continuation`, because
26887
- * its box cannot read the driver's run directory.
26888
- */
26889
- async function writeContinuationFiles(dir, continuation, files) {
26890
- const at = join(dir, String(continuation));
26891
- await mkdir(at, { recursive: true });
26892
- await writeFile(join(at, "note.md"), `${files.note}\n`, "utf8");
26893
- await writeFile(join(at, "verdict.json"), `${JSON.stringify(files.verdict ?? null, null, 2)}\n`, "utf8");
26894
- if (files.panel !== void 0) await writeFile(join(at, "panel.jsonl"), files.panel.map((line) => JSON.stringify(line)).join("\n") + (files.panel.length ? "\n" : ""), "utf8");
27654
+ function isAgent(value) {
27655
+ return typeof value === "object" && value !== null && typeof value.act === "function" && typeof value.name === "string";
26895
27656
  }
26896
- /** The best composite across `reads`, or `undefined` when no read scored. */
26897
- function bestComposite(reads) {
26898
- let best;
26899
- for (const read of reads) {
26900
- const value = read.verdict?.composite;
26901
- if (value !== void 0 && (best === void 0 || value > best)) best = value;
27657
+ /** Parent journals may already contain an interrupted driver's inference prefix. */
27658
+ function unreportedSpend(total, prior) {
27659
+ const tokens = { ...total.tokens };
27660
+ for (const key of [
27661
+ "input",
27662
+ "output",
27663
+ "freshInput",
27664
+ "cacheRead",
27665
+ "cacheWrite"
27666
+ ]) {
27667
+ const value = total.tokens[key];
27668
+ if (value !== void 0) tokens[key] = Math.max(0, value - (prior.tokens[key] ?? 0));
26902
27669
  }
26903
- return best;
26904
- }
26905
- function finite(value) {
26906
- return typeof value === "number" && Number.isFinite(value);
26907
- }
26908
- function format(value) {
26909
- return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/u, "");
26910
- }
26911
- /** Build the continuation state for one manager with a check. */
26912
- function createContinuationKeeper(input) {
26913
- const { policy } = input;
26914
- const failures = input.feedback === "pass-only" ? "off" : policy.failures;
26915
- const entries = [];
26916
- const notes = [];
26917
- let findings = [];
26918
- let panelUsd = 0;
26919
- let panelUsdKnown = true;
26920
- const latestVerdict = () => {
26921
- const reads = input.reads();
26922
- for (let i = reads.length - 1; i >= 0; i -= 1) {
26923
- const read = reads[i];
26924
- if (read?.verdict !== void 0) return {
26925
- verdict: read.verdict,
26926
- read: read.read
26927
- };
26928
- }
26929
- return { read: 0 };
26930
- };
26931
- const closePrevious = () => {
26932
- const last = entries.at(-1);
26933
- const lastNote = notes.at(-1);
26934
- if (last === void 0 || lastNote === void 0) return;
26935
- const latest = latestVerdict();
26936
- entries[entries.length - 1] = {
26937
- ...last,
26938
- after: latest.read > lastNote.read ? summarizeVerdict(latest.verdict) : null
26939
- };
26940
- };
26941
27670
  return {
26942
- async compose(context) {
26943
- closePrevious();
26944
- const continuation = entries.length + 1;
26945
- const { verdict, read } = latestVerdict();
26946
- const failing = verdict === void 0 ? [] : failedItems(verdict);
26947
- let panelRecord;
26948
- let panelLines;
26949
- if (policy.panel === "on" && policy.runPanel !== void 0 && policy.panelUsd !== void 0) {
26950
- const workers = input.workers();
26951
- const questions = expandQuestions(policy.profile.questions ?? [], failing, workers);
26952
- const left = policy.panelUsd.perRun - panelUsd;
26953
- const usdCap = Math.min(policy.panelUsd.perContinuation, left);
26954
- const asking = questions.length > 0 && usdCap > 0 && panelUsdKnown;
26955
- let traces;
26956
- let unavailable;
26957
- if (asking) try {
26958
- traces = await input.traces?.();
26959
- if (traces === void 0) unavailable = "the run has recorded no trace yet";
26960
- } catch (error) {
26961
- unavailable = `the run's traces could not be read: ${error instanceof Error ? error.message : String(error)}`;
26962
- }
26963
- if (asking && traces !== void 0) {
26964
- const result = await policy.runPanel({
26965
- continuation,
26966
- task: input.task,
26967
- ...verdict === void 0 ? {} : { verdict },
26968
- reads: input.reads(),
26969
- questions,
26970
- traces,
26971
- workers,
26972
- ...policy.best === void 0 ? {} : { bar: policy.best },
26973
- ...policy.reference === void 0 ? {} : { reference: policy.reference },
26974
- usdCap,
26975
- signal: context.signal
26976
- });
26977
- if (result.usd === null) panelUsdKnown = false;
26978
- else panelUsd += result.usd;
26979
- findings = distillFindings(findings, result.findings, new Set(failing), continuation);
26980
- panelRecord = {
26981
- asked: questions.length,
26982
- proposed: result.findings.length,
26983
- admitted: findings.filter((finding) => finding.admittedAt === continuation).length,
26984
- usd: result.usd
26985
- };
26986
- panelLines = [...result.findings.map((finding) => ({
26987
- kind: "finding",
26988
- admitted: admitFinding(finding),
26989
- ...finding
26990
- })), ...result.receipts === void 0 ? [] : [{
26991
- kind: "receipts",
26992
- receipts: result.receipts
26993
- }]];
26994
- } else panelRecord = {
26995
- asked: 0,
26996
- proposed: 0,
26997
- admitted: 0,
26998
- usd: 0,
26999
- ...unavailable === void 0 ? {} : { unavailable }
27000
- };
27001
- }
27002
- const appended = policy.append ? await policy.append({
27003
- continuation,
27004
- ...verdict === void 0 ? {} : { verdict },
27005
- reads: input.reads(),
27006
- signal: context.signal
27007
- }) : void 0;
27008
- const note = composeContinuationNote({
27009
- profile: policy.profile,
27010
- continuation,
27011
- ...verdict === void 0 ? {} : { verdict },
27012
- ...notes.at(-1)?.verdict === void 0 ? {} : { previous: notes.at(-1)?.verdict },
27013
- reads: input.reads().length,
27014
- failures,
27015
- ...policy.panel === "on" ? { findings } : {},
27016
- ...policy.bar === "on" ? { bar: {
27017
- ...policy.best === void 0 ? {} : { best: policy.best },
27018
- ...policy.reference === void 0 ? {} : { reference: policy.reference }
27019
- } } : {},
27020
- ...appended === void 0 ? {} : { appended: [appended] },
27021
- ...input.owed === void 0 ? {} : { owed: input.owed },
27022
- progress: context.progress,
27023
- canReadMore: input.canReadMore,
27024
- canSubmitResult: input.canSubmitResult === true,
27025
- ...input.sealed === true ? { sealed: true } : {}
27026
- });
27027
- notes.push({
27028
- note,
27029
- ...verdict === void 0 ? {} : { verdict },
27030
- ...panelLines === void 0 ? {} : { panel: panelLines },
27031
- read
27032
- });
27033
- entries.push({
27034
- continuation,
27035
- attempt: context.attempt,
27036
- noteDigest: noteDigest(note),
27037
- profile: policy.profile.id,
27038
- switches: {
27039
- failures,
27040
- panel: policy.panel,
27041
- bar: policy.bar
27042
- },
27043
- before: summarizeVerdict(verdict),
27044
- after: null,
27045
- ...panelRecord === void 0 ? {} : { panel: panelRecord },
27046
- appended: appended === void 0 ? 0 : 1
27047
- });
27048
- if (input.dir !== void 0) await writeContinuationFiles(input.dir, continuation, {
27049
- note,
27050
- ...verdict === void 0 ? {} : { verdict },
27051
- ...panelLines === void 0 ? {} : { panel: panelLines }
27052
- });
27053
- return note;
27054
- },
27055
- read(continuation) {
27056
- const index = continuation === void 0 ? notes.length - 1 : continuation - 1;
27057
- const entry = notes[index];
27058
- if (entry === void 0) return {
27059
- found: false,
27060
- reason: notes.length === 0 ? "no continuation has been sent in this run" : `continuations run from 1 to ${notes.length}`
27061
- };
27062
- return {
27063
- found: true,
27064
- continuation: index + 1,
27065
- note: entry.note,
27066
- verdict: failures === "off" && entry.verdict !== void 0 ? { pass: entry.verdict.pass } : entry.verdict ?? null,
27067
- findings: findings.filter((finding) => finding.admittedAt <= index + 1)
27068
- };
27069
- },
27070
- entries() {
27071
- closePrevious();
27072
- return entries.map((entry) => ({ ...entry }));
27073
- }
27671
+ ...total,
27672
+ ...addResourceSpend(total.resources === void 0 ? void 0 : Object.fromEntries(Object.entries(total.resources).map(([name, value]) => {
27673
+ const previous = prior.resources?.[name];
27674
+ if (previous && previous.unit !== value.unit) throw new ValidationError$1(`resource ${name}: unit mismatch`);
27675
+ return [name, {
27676
+ ...value,
27677
+ amount: Math.max(0, value.amount - (previous?.amount ?? 0)),
27678
+ known: value.known && (previous?.known ?? true)
27679
+ }];
27680
+ }))),
27681
+ iterations: Math.max(0, total.iterations - prior.iterations),
27682
+ tokens,
27683
+ usd: Math.max(0, total.usd - prior.usd),
27684
+ ms: Math.max(0, total.ms - prior.ms),
27685
+ ...total.usdEstimated === void 0 ? {} : { usdEstimated: Math.max(0, total.usdEstimated - (prior.usdEstimated ?? 0)) },
27686
+ ...total.boxMinutes === void 0 ? {} : { boxMinutes: Math.max(0, total.boxMinutes - (prior.boxMinutes ?? 0)) }
27074
27687
  };
27075
27688
  }
27076
27689
  //#endregion
@@ -27229,11 +27842,18 @@ function upstreamUnavailableSignal(error) {
27229
27842
  if (!(error instanceof Error)) return void 0;
27230
27843
  if (isProviderSchemaRejection(error)) return void 0;
27231
27844
  if (error instanceof CheckUnavailableError) return "check-unavailable";
27232
- if (error instanceof HarnessTurnFailedError) return unavailableSignalOfFailure({
27233
- error: error.message,
27234
- ...error.errorCode === void 0 ? {} : { errorCode: error.errorCode },
27235
- ...error.statusCode === void 0 ? {} : { statusCode: error.statusCode }
27236
- });
27845
+ if (error instanceof HarnessTurnFailedError) {
27846
+ const usageLimit = subscriptionUsageLimitSignal({
27847
+ error: error.message,
27848
+ ...error.errorCode === void 0 ? {} : { errorCode: error.errorCode }
27849
+ });
27850
+ if (usageLimit !== void 0) return usageLimit;
27851
+ return unavailableSignalOfFailure({
27852
+ error: error.message,
27853
+ ...error.errorCode === void 0 ? {} : { errorCode: error.errorCode },
27854
+ ...error.statusCode === void 0 ? {} : { statusCode: error.statusCode }
27855
+ });
27856
+ }
27237
27857
  if (error instanceof BackendTransportError) {
27238
27858
  const code = error.upstreamCode?.toLowerCase();
27239
27859
  if (code !== void 0 && UNAVAILABLE_CODES.has(code)) return code;
@@ -28778,6 +29398,6 @@ function isNonEmptySpend(s) {
28778
29398
  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);
28779
29399
  }
28780
29400
  //#endregion
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 };
29401
+ export { hostDirectoryReader as $, readSandboxOutcome as $i, workerTraceAnalysisStore as $n, sanitizeKnowledgeReadinessReport as $r, claimsAuthority as $t, scopeOwnerExecutorNodeContext as A, attestRuntimeOwnedPendingExecutor as Ai, unavailablePauseMs as An, retainHarnessTranscript as Ar, cliInPlaceExecutor as At, noteScopeRetainedOwnerCoordination as B, runtimeOwnedDriveHarnessProviderEvidence as Bi, InMemorySpawnJournal as Bn, buildLoopSpanNodes as Br, WORKER_TRACE_PROPAGATION as Bt, deriveNodeExecutionIdentity as C, promptResourceProfileMaterialization as Ci, routerBrain as Cn, linkAbort as Cr, distillFindings as Ct, recordScopeOwnerMaterialization as D, unsupportedProfileDimensions as Di, providerAsExecutor as Dn, persistHarnessTranscript as Dr, verdictFromJudgeScore as Dt, recordScopeOwnerDriverAttempt as E, sandboxActProfileMaterialization as Ei, createAgentEnvironmentProviderRegistry as En, harnessTranscriptArtifact as Er, passedItems as Et, seatExecutionProfile as F, knownExecutionBindingReceipt as Fi, registerRetainedExecutorPreparation as Fn, traceContextToEnv as Fr, createWorktreeCliExecutor as Ft, scopeRetainedOwnerJournalRoot as G, runtimeOwnedScopeOwnerRuntime as Gi, isNoEntError as Gn, generateSpanId as Gr, taskToPrompt as Gt, prepareScopeRetainedOwnerTask as H, runtimeOwnedExecutorMaterialization as Hi, loadSpawnForest as Hn, createOpenInferenceFileExporter as Hr, workerTraceEnv as Ht, beginScopeRetainedOwnerDrive as I, knownMaterializationReceipt as Ii, retainedExecutorSeamKey as In, defaultRedactor as Ir, DEFAULT_SANDBOX_STEERING_MAX_TURNS as It, scopeRetainedOwnerRestorePoint as J, executableAgentProfileSnapshot as Ji, writeAllBytes as Jn, padTraceId as Jr, readWorkerProgress as Jt, scopeRetainedOwnerPriorSpend as K, unknownExecutionBindingReceipt as Ki, prepareJsonlAppend as Kn, loopEventToOtelSpan as Kr, DEFAULT_STALL_AFTER_MS as Kt, bindScopeRetainedOwnerEnvironmentId as L, newExecutionAttemptId as Li, FileResultBlobStore as Ln, defaultRedactorIdentityMaterial as Lr, createSteerableSandboxSession as Lt, SeatChain as M, authoredProfileDigest as Mi, createPushTraceSource as Mn, createPropagatingTraceEmitter as Mr, createExecutor as Mt, SeatChainExhaustedError as N, finalizeRuntimeOwnedPendingExecutor as Ni, decodeToolPart as Nn, mergeTraceEnv as Nr, createExecutorRegistry as Nt, recordScopeOwnerPause as O, validateProfileMaterialization as Oi, providerAsSandboxClient as On, readHarnessTranscript as Or, bindReusableExecutorExecutionId as Ot, authoredSeatStages as P, inheritRuntimeOwnedExecutorAttestation as Pi, sandboxSessionTraceSource as Pn, readTraceContextFromEnv as Pr, snapshotExecutorConfig as Pt, environmentReader as Q, projectSandboxOutcome as Qi, parseWorkerToolTraceArtifact as Qn, sanitizeAgentRuntimeEvent as Qr, PEER_MAIL_WIRE_KEY as Qt, bindScopeRetainedOwnerProvider as R, providerAttemptEvidence as Ri, FileSpawnJournal as Rn, resolveRedactor as Rr, createRouterTranscript as Rt, createScope as S, promptOnlyProfileMaterialization as Si, readPromptOptions as Sn, abortError as Sr, createContinuationKeeper as St, meterRuntimeOwnedProviderAttempt as T, renderUnsupported as Ti, LEAF_CONTINUATION_TASK as Tn, captureHarnessTranscript as Tr, failedItems as Tt, reconcileScopeRetainedOwnerEnvironment as U, runtimeOwnedExecutorProviderEvidence as Ui, materializeTreeView as Un, createOtelExporter as Ur, workerTraceHeaders as Ut, prepareScopeRetainedOwnerSeatSwitch as V, runtimeOwnedExecutorExecutionBinding as Vi, insideCursorNamespace as Vn, buildRuntimeEventOtelSpans as Vr, readWorkerTraceContext as Vt, scopeRetainedOwnerContext as W, runtimeOwnedPendingExecutorMaterialization as Wi, replaySpawnTree as Wn, flatOtelSpan as Wr, workerTraceSeamKey as Wt, scopeRetainedOwnerTurnEnded as X, detachedFrozen as Xi, captureWorkerTraceEvidence as Xn, createRuntimeEventCollector as Xr, AUTHORITY_MARKERS as Xt, scopeRetainedOwnerResult as Y, executableAgentSpecSnapshot as Yi, WORKER_TOOL_TRACE_SCHEMA_VERSION as Yn, toOtelAttributes as Yr, createInbox as Yt, SPAWN_RESOURCE_PATH_MAX_BYTES as Z, detachedSnapshot as Zi, isTraceAnalysisStore as Zn, createRuntimeStreamEventCollector as Zr, DEFAULT_PEER_MAIL_LIMITS as Zt, isDriverSpec as _, providerMessageText as _a, defineProfileMaterializationContract as _i, createSandboxLineage as _n, destroyInteractiveEnvironment as _r, CheckUnavailableError as _t, collectDelivered as a, isSandboxTerminalEvent as aa, removeWorktree as ai, isTerminalNodeStatus as an, meterUsageEvent as ar, attachWorker as at, assertRecursiveReservationPolicy as b, promptControlProfileMaterialization as bi, captureBeforeDestroy as bn, openSlotGroup as br, bestComposite as bt, runTree as c, notifySandboxEventObserver as ca, harnessInvocation as ci, addHarnessUsage as cn, spendFromUsageTotals as cr, recoverRetainedInteractiveRun as ct, classifyDriverFailure as d, sumSandboxUsage as da, parseCodexTokenUsage as di, readCodexRolloutSession as dn, errMessage as dr, queueOf as dt, assertSandboxServedModel as ea, sanitizeRuntimeStreamEvent as ei, createPeerMailbox as en, executorFailure as er, resolveSpawnResourcePaths as et, runDriverWithRetry as f, decodeHarnessUsage as fa, CodexExecutionDiagnosticError as fi, TERMINAL_DECISIONS as fn, reconnectRetainedRun as fr, rollingDispatch as ft, driverExecutorFactory as g, promptOptionsFromAgentTurnInput as ga, controlProfileMaterialization as gi, runAgentRounds as gn, retainedCreateMaterial as gr, CONTINUATION_FACTS as gt, driverChild as h, promptFromAgentTurnInput as ha, assertProfileMaterialization as hi, isTerminalDecision as hn, startRetainedRunInEnvironment as hr, CONTINUATIONS_DIR as ht, bestDelivered as i, extractLlmCallEvent as ia, createWorktree as ii, isLiveNodeStatus as in, createBudgetPool as ir, interactiveAdmissionSeamKey as it, settledToIteration as j, attestRuntimeOwnedScopeOwner as ji, unavailableSignalOfFailure as jn, contentAddress as jr, cliWorktreeExecutor as jt, restoreScopeOwnerAcceptedExecution as k, worktreeCliProfileMaterialization as ki, resolveAgentEnvironmentProvider as kn, resolveHarnessTranscriptCapture as kr, captureReusableExecutorConfig as kt, DriverAttemptsExhaustedError as l, sandboxEventServedBackend as la, harnessSupportsReasoningEffort as li, createCodexRolloutStoreReader as ln, bridgeRuntimeAttachmentsKey as lr, startRetainedInteractiveRun as lt, upstreamUnavailableSignal as m, awaitAbortable$1 as ma, AGENT_PROFILE_MATERIALIZATION_AXES as mi, defaultSelectWinner as mn, startRetainedRun as mr, mapExecutorResult as mt, createRootHandle as n, createSandboxToolPartState as na, runWorktreeHarness as ni, peerMailTools as nn, ReservationWaitRefused as nr, coordinationProfileToolPrefix as nt, pickBestDelivered as o, mapSandboxEvent as oa, DEFAULT_LOCAL_HARNESS as oi, bridgeAdmissionRefusal as on, newUsageTotals as or, readWorkerInteractiveBinding as ot, summarizeDriverAttempts as p, abortError$1 as pa, terminateProcessTreeAndConfirm as pi, createSandboxForSpec as pn, recoverRetainedRun as pr, gateOnDeliverable as pt, scopeRetainedOwnerResourceReader as q, unknownMaterializationReceipt as qi, readCommittedJsonLines as qn, padSpanId as qr, createActivityLog as qt, createSupervisor as r, createSandboxUsageLedger as ra, captureWorktreeDiff as ri, peerMailVerbNames as rn, assertValidBudget as rr, providerVisibleProfile as rt, runFinalizer as s, mapSandboxToolEvent as sa, LOCAL_HARNESSES as si, bridgeModelRouteRefusal as sn, spendFromUsageEvents as sr, reconnectRetainedInteractiveRun as st, DEFAULT_MAX_DEPTH as t, canonicalStreamEventFromSandboxEvent as ta, runSettledCommand as ti, isPeerMailEnvelope as tn, BudgetReconcileFault as tr, coordinationMcpAlias as tt, HarnessTurnFailedError as u, sandboxProgressEvents as ua, localHarnessExecutable as ui, harnessUsageIsEmpty as un, bridgeStopSignalKey as ur, freeSlots as ut, withDriverExecutor as v, fullProfileMaterialization as vi, acquireSandbox as vn, environmentGone as vr, admitContinuationPolicy as vt, meterRuntimeOwnedAccounting as w, renderProfileMaterializationIssues as wi, runBrainLoop as wn, runAbortable as wr, expandQuestions as wt, beginScopeOwnerAttempt as x, promptModelProfileMaterialization as xi, assertBoxlessPromptOptions as xn, RunCancellationReason as xr, checkVerdictOf as xt, SUBTREE_RESULT_LIMIT as y, profileMaterializationAxes$1 as yi, SandboxEvidenceRetentionError as yn, createWorkerSlots as yr, admitFinding as yt, consumeScopeRetainedOwnerResult as z, recordRuntimeOwnedDriveHarnessProviderEvidence as zi, InMemoryResultBlobStore as zn, buildLoopOtelSpans as zr, createInPlaceCliExecutor as zt };
28782
29402
 
28783
- //# sourceMappingURL=supervisor-gCfG6K1-.js.map
29403
+ //# sourceMappingURL=supervisor-Dz4XXtK1.js.map