@tangle-network/agent-runtime 0.306.2 → 0.308.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/{activation-wZ-8vOjV.d.ts → activation-5Usfsfzr.d.ts} +3 -3
  2. package/dist/{activation-kaJzXM7Y.js → activation-DbnacUhI.js} +2 -2
  3. package/dist/{activation-kaJzXM7Y.js.map → activation-DbnacUhI.js.map} +1 -1
  4. package/dist/agent.d.ts +2 -2
  5. package/dist/agent.js +2 -2
  6. package/dist/{coordination-driver-Y2gf8pBT.js → coordination-driver-BYIjecHz.js} +2 -2
  7. package/dist/{coordination-driver-Y2gf8pBT.js.map → coordination-driver-BYIjecHz.js.map} +1 -1
  8. package/dist/{delegate-B7bwEFQl.js → delegate-KCK7WdZv.js} +2 -2
  9. package/dist/{delegate-B7bwEFQl.js.map → delegate-KCK7WdZv.js.map} +1 -1
  10. package/dist/durable.d.ts +2 -2
  11. package/dist/durable.js +55 -4
  12. package/dist/durable.js.map +1 -1
  13. package/dist/{graph-VUwNFYff.js → graph-BUu0KQVW.js} +5 -4
  14. package/dist/graph-BUu0KQVW.js.map +1 -0
  15. package/dist/{improvement-cycle-DuIGusyA.js → improvement-cycle-BylwWCcl.js} +7 -3
  16. package/dist/{improvement-cycle-DuIGusyA.js.map → improvement-cycle-BylwWCcl.js.map} +1 -1
  17. package/dist/{index-DflDZq_I.d.ts → index-EibbsKsH.d.ts} +72 -6
  18. package/dist/index.d.ts +6 -6
  19. package/dist/index.js +7 -7
  20. package/dist/intelligence.d.ts +3 -3
  21. package/dist/intelligence.js +3 -3
  22. package/dist/kernel.d.ts +4 -4
  23. package/dist/kernel.js +8 -8
  24. package/dist/{loop-runner-bin-Dp1V3P2W.js → loop-runner-bin-DcF6ZEWi.js} +3 -3
  25. package/dist/{loop-runner-bin-Dp1V3P2W.js.map → loop-runner-bin-DcF6ZEWi.js.map} +1 -1
  26. package/dist/{loop-runner-bin-DZfRUVWy.d.ts → loop-runner-bin-jST1hm-z.d.ts} +3 -3
  27. package/dist/loop-runner-bin.d.ts +1 -1
  28. package/dist/loop-runner-bin.js +1 -1
  29. package/dist/mcp/bin.js +3 -3
  30. package/dist/mcp/index.d.ts +5 -5
  31. package/dist/mcp/index.js +4 -4
  32. package/dist/{openai-tools-YO30D2s3.d.ts → openai-tools-BuFqhp5i.d.ts} +2 -2
  33. package/dist/profiles.d.ts +1 -1
  34. package/dist/{provision-supervisor-CfK8fla-.js → provision-supervisor-Cvp4Nm-y.js} +3 -3
  35. package/dist/{provision-supervisor-CfK8fla-.js.map → provision-supervisor-Cvp4Nm-y.js.map} +1 -1
  36. package/dist/{runtime-D452tieK.js → runtime-Y46Lwt_d.js} +8 -8
  37. package/dist/{runtime-D452tieK.js.map → runtime-Y46Lwt_d.js.map} +1 -1
  38. package/dist/{search-executor-D3AT8_hb.js → search-executor-BPpfxu9c.js} +2 -2
  39. package/dist/{search-executor-D3AT8_hb.js.map → search-executor-BPpfxu9c.js.map} +1 -1
  40. package/dist/{server-D1Tfxo-v.js → server-DIrQYUnn.js} +3 -3
  41. package/dist/{server-D1Tfxo-v.js.map → server-DIrQYUnn.js.map} +1 -1
  42. package/dist/{stream-agent-turn-B1giFgOg.d.ts → stream-agent-turn-op3m9IEY.d.ts} +2 -2
  43. package/dist/{substrate-L_sC7jCD.d.ts → substrate-B1VzcyoB.d.ts} +2 -2
  44. package/dist/{supervise-CtewGpxh.js → supervise-CmeN8ipv.js} +164 -190
  45. package/dist/supervise-CmeN8ipv.js.map +1 -0
  46. package/dist/{supervisor-DYKPbcZa.js → supervisor-CSMb8HBU.js} +1796 -1038
  47. package/dist/supervisor-CSMb8HBU.js.map +1 -0
  48. package/dist/testing.d.ts +2 -2
  49. package/dist/testing.js +12 -12
  50. package/dist/tui/index.d.ts +1 -1
  51. package/dist/tui/index.js +1 -1
  52. package/dist/{types-DeuEkBhI.d.ts → types-B2IOlN8R.d.ts} +152 -67
  53. package/package.json +3 -3
  54. package/skills/profile-authoring/SKILL.md +6 -0
  55. package/dist/graph-VUwNFYff.js.map +0 -1
  56. package/dist/supervise-CtewGpxh.js.map +0 -1
  57. package/dist/supervisor-DYKPbcZa.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-DaQceg2p.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,41 +9763,53 @@ 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 !== "execution-abandoned" && 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,
9778
+ abandoned: false,
9717
9779
  admissions: /* @__PURE__ */ new Map(),
9718
- destroyedEnvironments: /* @__PURE__ */ new Set()
9780
+ unusableEnvironments: /* @__PURE__ */ new Set()
9719
9781
  };
9720
9782
  this.nodes.set(event.id, node);
9721
9783
  }
9722
9784
  if (event.kind === "environment-teardown") {
9723
- if (event.destroyed) node.destroyedEnvironments.add(event.environmentId);
9785
+ if (event.destroyed) node.unusableEnvironments.add(event.environmentId);
9786
+ return;
9787
+ }
9788
+ if (event.kind === "environment-terminal") {
9789
+ node.unusableEnvironments.add(event.environmentId);
9724
9790
  return;
9725
9791
  }
9726
9792
  if (event.kind === "execution-admitted" && event.admission.phase === "environment") node.lastEnvironmentId = event.admission.environmentId;
9727
9793
  if (event.kind === "spawned") node.spawned = true;
9728
- else if (event.kind === "materialized") node.materialized = true;
9794
+ else if (event.kind === "materialized") {
9795
+ node.materialized = true;
9796
+ node.authoredProfileDigest = event.receipt.authoredProfileDigest;
9797
+ } else if (event.kind === "seat-materialized") node.latestSeatMaterialization = event.segmentIndex;
9729
9798
  else if (event.kind === "execution-bound") node.bindings.add(event.binding.attemptId);
9730
9799
  else if (event.kind === "execution-input") {
9731
9800
  node.inputs.add(event.seq);
9732
9801
  node.input = true;
9802
+ node.latestInput = event.seq;
9733
9803
  node.result = false;
9804
+ node.abandoned = false;
9734
9805
  node.admissions.clear();
9735
9806
  } else if (event.kind === "execution-admitted") node.admissions.set(event.admission.phase, event.admission);
9736
9807
  else if (event.kind === "execution-result") node.result = true;
9808
+ else if (event.kind === "execution-abandoned") node.abandoned = true;
9737
9809
  if (closesCursorSlot(event)) node.closed = true;
9738
9810
  }
9739
9811
  assertRetained(node, event) {
9740
- if (event.kind !== "execution-input" && event.kind !== "execution-admitted" && event.kind !== "execution-result") return;
9812
+ if (event.kind !== "execution-input" && event.kind !== "execution-admitted" && event.kind !== "execution-result" && event.kind !== "execution-abandoned") return;
9741
9813
  function fail(reason) {
9742
9814
  throw new Error(`spawn journal corrupted: retained execution '${event.id}' ${reason}`);
9743
9815
  }
@@ -9748,10 +9820,18 @@ var SpawnEventIndex = class {
9748
9820
  if (node.inputs.has(event.seq)) fail("has duplicate input sequence");
9749
9821
  const environment = node.admissions.get("environment");
9750
9822
  const ranIn = environment?.phase === "environment" ? environment.environmentId : node.lastEnvironmentId;
9751
- const abandoned = ranIn !== void 0 && node.destroyedEnvironments.has(ranIn);
9752
- if (node.input && !node.result && !abandoned) fail("input replaces an unfinished invocation");
9823
+ const closed = node.abandoned || ranIn !== void 0 && node.unusableEnvironments.has(ranIn);
9824
+ if (node.input && !node.result && !closed) fail("input replaces an unfinished invocation");
9825
+ return;
9826
+ }
9827
+ if (event.kind === "execution-abandoned") {
9828
+ if (!node.input || node.latestInput !== event.inputSeq) fail("abandons an invocation that is not its latest");
9829
+ if (node.result) fail("abandons an invocation that has a result");
9830
+ if (node.abandoned) fail("abandons an invocation twice");
9831
+ if (!Number.isSafeInteger(event.failures) || event.failures < 1) fail("abandons without a failure count");
9753
9832
  return;
9754
9833
  }
9834
+ if (node.abandoned) fail(`${event.kind} follows its abandonment`);
9755
9835
  if (event.kind === "execution-result") {
9756
9836
  if (node.result) fail("has duplicate result");
9757
9837
  if (!node.admissions.has("dispatched")) fail("result precedes dispatch");
@@ -9802,6 +9882,7 @@ const outsideKinds = /* @__PURE__ */ new Set([
9802
9882
  "execution-input",
9803
9883
  "execution-admitted",
9804
9884
  "execution-result",
9885
+ "execution-abandoned",
9805
9886
  "execution-evidence",
9806
9887
  "progress",
9807
9888
  "reconciled",
@@ -9810,6 +9891,7 @@ const outsideKinds = /* @__PURE__ */ new Set([
9810
9891
  "teardown-pending",
9811
9892
  "teardown-confirmed",
9812
9893
  "environment-teardown",
9894
+ "environment-terminal",
9813
9895
  "workspace-checkpoint-requested",
9814
9896
  "workspace-checkpoint",
9815
9897
  "workspace-checkpoint-fork-requested",
@@ -9819,6 +9901,9 @@ const outsideKinds = /* @__PURE__ */ new Set([
9819
9901
  "workspace-restored",
9820
9902
  "workspace-capture",
9821
9903
  "trace-unpropagated",
9904
+ "seat-segment",
9905
+ "seat-materialized",
9906
+ "seat-paused",
9822
9907
  "paused",
9823
9908
  "driver-attempt",
9824
9909
  "node-inputs-resolved",
@@ -9884,11 +9969,12 @@ async function replaySpawnTree(journal, blobs, root) {
9884
9969
  if (ev.kind === "reconciled") continue;
9885
9970
  if (ev.kind === "materialized") continue;
9886
9971
  if (ev.kind === "execution-bound") continue;
9887
- if (ev.kind === "execution-input" || ev.kind === "execution-admitted" || ev.kind === "execution-result" || ev.kind === "execution-evidence") continue;
9972
+ if (ev.kind === "execution-input" || ev.kind === "execution-admitted" || ev.kind === "execution-result" || ev.kind === "execution-abandoned" || ev.kind === "execution-evidence") continue;
9888
9973
  if (ev.kind === "edge") continue;
9889
9974
  if (ev.kind === "teardown-unconfirmed") continue;
9890
9975
  if (ev.kind === "teardown-pending" || ev.kind === "teardown-confirmed") continue;
9891
9976
  if (ev.kind === "environment-teardown") continue;
9977
+ if (ev.kind === "environment-terminal") continue;
9892
9978
  if (ev.kind === "workspace-checkpoint-requested") continue;
9893
9979
  if (ev.kind === "workspace-checkpoint") continue;
9894
9980
  if (ev.kind === "workspace-checkpoint-fork-requested") continue;
@@ -9898,6 +9984,7 @@ async function replaySpawnTree(journal, blobs, root) {
9898
9984
  if (ev.kind === "workspace-restored") continue;
9899
9985
  if (ev.kind === "workspace-capture") continue;
9900
9986
  if (ev.kind === "trace-unpropagated") continue;
9987
+ if (ev.kind === "seat-segment" || ev.kind === "seat-materialized" || ev.kind === "seat-paused") continue;
9901
9988
  if (ev.kind === "paused") continue;
9902
9989
  if (ev.kind === "driver-attempt") continue;
9903
9990
  if (ev.kind === "node-inputs-resolved") continue;
@@ -10049,7 +10136,7 @@ function materializeTreeView(events) {
10049
10136
  if (Number.isFinite(settledAt)) node.settledAt = settledAt;
10050
10137
  }
10051
10138
  for (const ev of events) {
10052
- if (ev.kind !== "materialized") continue;
10139
+ if (ev.kind !== "materialized" && ev.kind !== "seat-materialized") continue;
10053
10140
  const node = requireNode(nodes, ev.id);
10054
10141
  node.materialization = ev.receipt;
10055
10142
  node.runtime = ev.receipt.runtime;
@@ -10141,6 +10228,87 @@ function traceEvidenceFor(event) {
10141
10228
  };
10142
10229
  }
10143
10230
  //#endregion
10231
+ //#region src/runtime/supervise/upstream-unavailable.ts
10232
+ /**
10233
+ * An upstream that cannot serve NOW: how Runtime recognizes one, and how long an agent waits for it.
10234
+ *
10235
+ * A model provider's exhausted quota, a rate limit, an overload, or the router's own refused
10236
+ * credential is not a fault in the agent: the same request succeeds when capacity returns. A
10237
+ * driver that meets one re-enters after a pause (`runDriverWithRetry`), and a leaf continues in
10238
+ * its environment after the same pause (`providerAsExecutor`). Both read the refusal and the pause
10239
+ * from here, so an outage costs a director and its workers the same number of turns.
10240
+ *
10241
+ * This module imports nothing, so the provider executor can read it without the error classes of
10242
+ * `../../errors`.
10243
+ */
10244
+ /**
10245
+ * Machine codes that say the upstream cannot serve now rather than that the request is wrong.
10246
+ * Each is a code an upstream publishes, not prose: the router's
10247
+ * (`lib/model-substitution.ts`, `lib/upstream-error-triage.ts`) and the OpenAI- and Anthropic-shaped
10248
+ * error types a relayed body carries.
10249
+ */
10250
+ const UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
10251
+ "provider_quota_exhausted",
10252
+ "provider_quota_exceeded",
10253
+ "provider_rate_limit",
10254
+ "upstream_unavailable",
10255
+ "provider_key_invalid",
10256
+ "rate_limit_exceeded",
10257
+ "rate_limit_error",
10258
+ "overloaded_error"
10259
+ ]);
10260
+ /** 429 Too Many Requests, 503 Service Unavailable, and 529, which Anthropic uses for overload. */
10261
+ const UNAVAILABLE_STATUSES = /* @__PURE__ */ new Set([
10262
+ 429,
10263
+ 503,
10264
+ 529
10265
+ ]);
10266
+ /**
10267
+ * A harness that flattens the router's JSON body into its own failure text leaves the router's
10268
+ * code in that text: `opencode execution failed: No provider served model "..."
10269
+ * (provider_quota_exhausted)`. The code is matched as a whole token, and a status only in the
10270
+ * `status code <n>` framing a harness prints, so prose that merely mentions a quota does not match.
10271
+ */
10272
+ function unavailableSignalInText(text) {
10273
+ for (const token of text.toLowerCase().matchAll(/[a-z_]+/gu)) if (UNAVAILABLE_CODES.has(token[0])) return token[0];
10274
+ const status = text.match(/\bstatus code (\d{3})\b/u)?.[1];
10275
+ return status !== void 0 && UNAVAILABLE_STATUSES.has(Number(status)) ? `http-${status}` : void 0;
10276
+ }
10277
+ /**
10278
+ * The code or status that marks a failed turn outcome as an upstream capacity refusal, or
10279
+ * `undefined`. The outcome's own `errorCode` decides first; the failure text is read only when no
10280
+ * code or numeric status decided, because a harness CLI can report the router's refusal as text.
10281
+ */
10282
+ function unavailableSignalOfFailure(failure) {
10283
+ const code = failure.errorCode?.toLowerCase();
10284
+ if (code !== void 0 && UNAVAILABLE_CODES.has(code)) return code;
10285
+ if (failure.statusCode !== void 0) return UNAVAILABLE_STATUSES.has(failure.statusCode) ? `http-${failure.statusCode}` : void 0;
10286
+ return unavailableSignalInText(failure.error);
10287
+ }
10288
+ const DEFAULT_UNAVAILABLE_PAUSE_MS = 15e3;
10289
+ const DEFAULT_MAX_UNAVAILABLE_PAUSE_MS = 3e5;
10290
+ /**
10291
+ * The pause after the `consecutive`-th refusal in a row (1-based): the first pause, doubled per
10292
+ * earlier refusal, up to the ceiling. The one rule for a driver that re-enters and a leaf that
10293
+ * continues in its environment, so an outage costs both the same number of turns.
10294
+ */
10295
+ function unavailablePauseMs(consecutive, policy = {}) {
10296
+ return cappedDoublingMs(consecutive, policy.unavailablePauseMs ?? DEFAULT_UNAVAILABLE_PAUSE_MS, policy.maxUnavailablePauseMs ?? DEFAULT_MAX_UNAVAILABLE_PAUSE_MS);
10297
+ }
10298
+ /** `first` doubled per earlier consecutive wait (`consecutive` is 1-based), up to `ceiling`. */
10299
+ function cappedDoublingMs(consecutive, first, ceiling) {
10300
+ const start = Math.max(0, first);
10301
+ return Math.min(Math.max(start, ceiling), start * 2 ** Math.max(0, consecutive - 1));
10302
+ }
10303
+ /**
10304
+ * Spread a wait over `[ms / 2, ms]`. Every driver a Platform restart cut off fails within the same
10305
+ * seconds; without jitter their doubling schedules stay aligned and they all re-enter together
10306
+ * when the service returns. `random` returns a value in `[0, 1)`; 0 keeps the full wait.
10307
+ */
10308
+ function jitteredMs(ms, random) {
10309
+ return ms - Math.floor(ms / 2 * Math.min(1, Math.max(0, random())));
10310
+ }
10311
+ //#endregion
10144
10312
  //#region src/runtime/supervise/retained-executor.ts
10145
10313
  /** Scope owns the durable writer; provider executors only publish sanitized admissions. */
10146
10314
  const retainedExecutorSeamKey = "runtime.retainedExecutor";
@@ -10239,6 +10407,7 @@ function classifyRetainedPendingCause(cause, phase = "execution") {
10239
10407
  if (name === "ZodError" || Array.isArray(Reflect.get(value, "issues")) || code === "JSON_BOUND_VIOLATION") return at === "admission" ? "request-rejected" : "provider-contract";
10240
10408
  if (code !== void 0 && transportCodes.has(code)) return "transport";
10241
10409
  if (name === "NetworkError" || name === "ServerError") return "transport";
10410
+ if (status === void 0 && at === "admission" && code !== void 0 && UNAVAILABLE_CODES.has(code.toLowerCase())) return "request-rejected";
10242
10411
  if (status !== void 0) {
10243
10412
  if (status >= 500) return "transport";
10244
10413
  if (at === "admission" && status !== 408) return "request-rejected";
@@ -10517,87 +10686,6 @@ function sandboxSessionTraceSource(box, sessionId, opts = {}) {
10517
10686
  });
10518
10687
  }
10519
10688
  //#endregion
10520
- //#region src/runtime/supervise/upstream-unavailable.ts
10521
- /**
10522
- * An upstream that cannot serve NOW: how Runtime recognizes one, and how long an agent waits for it.
10523
- *
10524
- * A model provider's exhausted quota, a rate limit, an overload, or the router's own refused
10525
- * credential is not a fault in the agent: the same request succeeds when capacity returns. A
10526
- * driver that meets one re-enters after a pause (`runDriverWithRetry`), and a leaf continues in
10527
- * its environment after the same pause (`providerAsExecutor`). Both read the refusal and the pause
10528
- * from here, so an outage costs a director and its workers the same number of turns.
10529
- *
10530
- * This module imports nothing, so the provider executor can read it without the error classes of
10531
- * `../../errors`.
10532
- */
10533
- /**
10534
- * Machine codes that say the upstream cannot serve now rather than that the request is wrong.
10535
- * Each is a code an upstream publishes, not prose: the router's
10536
- * (`lib/model-substitution.ts`, `lib/upstream-error-triage.ts`) and the OpenAI- and Anthropic-shaped
10537
- * error types a relayed body carries.
10538
- */
10539
- const UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
10540
- "provider_quota_exhausted",
10541
- "provider_quota_exceeded",
10542
- "provider_rate_limit",
10543
- "upstream_unavailable",
10544
- "provider_key_invalid",
10545
- "rate_limit_exceeded",
10546
- "rate_limit_error",
10547
- "overloaded_error"
10548
- ]);
10549
- /** 429 Too Many Requests, 503 Service Unavailable, and 529, which Anthropic uses for overload. */
10550
- const UNAVAILABLE_STATUSES = /* @__PURE__ */ new Set([
10551
- 429,
10552
- 503,
10553
- 529
10554
- ]);
10555
- /**
10556
- * A harness that flattens the router's JSON body into its own failure text leaves the router's
10557
- * code in that text: `opencode execution failed: No provider served model "..."
10558
- * (provider_quota_exhausted)`. The code is matched as a whole token, and a status only in the
10559
- * `status code <n>` framing a harness prints, so prose that merely mentions a quota does not match.
10560
- */
10561
- function unavailableSignalInText(text) {
10562
- for (const token of text.toLowerCase().matchAll(/[a-z_]+/gu)) if (UNAVAILABLE_CODES.has(token[0])) return token[0];
10563
- const status = text.match(/\bstatus code (\d{3})\b/u)?.[1];
10564
- return status !== void 0 && UNAVAILABLE_STATUSES.has(Number(status)) ? `http-${status}` : void 0;
10565
- }
10566
- /**
10567
- * The code or status that marks a failed turn outcome as an upstream capacity refusal, or
10568
- * `undefined`. The outcome's own `errorCode` decides first; the failure text is read only when no
10569
- * code or numeric status decided, because a harness CLI can report the router's refusal as text.
10570
- */
10571
- function unavailableSignalOfFailure(failure) {
10572
- const code = failure.errorCode?.toLowerCase();
10573
- if (code !== void 0 && UNAVAILABLE_CODES.has(code)) return code;
10574
- if (failure.statusCode !== void 0) return UNAVAILABLE_STATUSES.has(failure.statusCode) ? `http-${failure.statusCode}` : void 0;
10575
- return unavailableSignalInText(failure.error);
10576
- }
10577
- const DEFAULT_UNAVAILABLE_PAUSE_MS = 15e3;
10578
- const DEFAULT_MAX_UNAVAILABLE_PAUSE_MS = 3e5;
10579
- /**
10580
- * The pause after the `consecutive`-th refusal in a row (1-based): the first pause, doubled per
10581
- * earlier refusal, up to the ceiling. The one rule for a driver that re-enters and a leaf that
10582
- * continues in its environment, so an outage costs both the same number of turns.
10583
- */
10584
- function unavailablePauseMs(consecutive, policy = {}) {
10585
- return cappedDoublingMs(consecutive, policy.unavailablePauseMs ?? DEFAULT_UNAVAILABLE_PAUSE_MS, policy.maxUnavailablePauseMs ?? DEFAULT_MAX_UNAVAILABLE_PAUSE_MS);
10586
- }
10587
- /** `first` doubled per earlier consecutive wait (`consecutive` is 1-based), up to `ceiling`. */
10588
- function cappedDoublingMs(consecutive, first, ceiling) {
10589
- const start = Math.max(0, first);
10590
- return Math.min(Math.max(start, ceiling), start * 2 ** Math.max(0, consecutive - 1));
10591
- }
10592
- /**
10593
- * Spread a wait over `[ms / 2, ms]`. Every driver a Platform restart cut off fails within the same
10594
- * seconds; without jitter their doubling schedules stay aligned and they all re-enter together
10595
- * when the service returns. `random` returns a value in `[0, 1)`; 0 keeps the full wait.
10596
- */
10597
- function jitteredMs(ms, random) {
10598
- return ms - Math.floor(ms / 2 * Math.min(1, Math.max(0, random())));
10599
- }
10600
- //#endregion
10601
10689
  //#region src/runtime/supervise/workspace-checkpoint.ts
10602
10690
  /** Workspace-relative path of the marker Runtime writes before every checkpoint. */
10603
10691
  const WORKSPACE_CHECKPOINT_MARKER_PATH = ".agent-runtime-checkpoint";
@@ -10930,6 +11018,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
10930
11018
  if (workspaceSnapshot !== void 0) return workspaceSnapshot;
10931
11019
  if (workspaceCapturePromise === void 0) {
10932
11020
  workspaceOutcome = outcome;
11021
+ stopLiveMirror();
10933
11022
  if (nativeTimer !== void 0) clearTimeout(nativeTimer);
10934
11023
  nativeTimer = void 0;
10935
11024
  const captureContext = {
@@ -10945,7 +11034,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
10945
11034
  const reportTiming = retention?.onWorkspaceCapture;
10946
11035
  let timing;
10947
11036
  const capturedExecutionId = workspaceExecutionId;
10948
- workspaceCapturePromise = (nativeInFlight ?? Promise.resolve()).then(() => captureProviderWorkspaceSnapshot(workspaceRetention, captureContext, "environment", reportTiming === void 0 ? void 0 : (measured) => {
11037
+ workspaceCapturePromise = Promise.all([nativeInFlight, liveInFlight]).then(() => captureProviderWorkspaceSnapshot(workspaceRetention, captureContext, "environment", reportTiming === void 0 ? void 0 : (measured) => {
10949
11038
  timing = measured;
10950
11039
  })).finally(async () => {
10951
11040
  if (timing === void 0 || reportTiming === void 0) return;
@@ -10998,6 +11087,38 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
10998
11087
  const nativePort = options.workspaceRetention?.captureNative === void 0 ? void 0 : options.workspaceRetention;
10999
11088
  let nativeInFlight;
11000
11089
  let nativeTimer;
11090
+ const livePort = options.workspaceRetention?.captureLive === void 0 ? void 0 : options.workspaceRetention;
11091
+ let liveInFlight;
11092
+ let liveTimer;
11093
+ const stopLiveMirror = () => {
11094
+ if (liveTimer !== void 0) clearTimeout(liveTimer);
11095
+ liveTimer = void 0;
11096
+ };
11097
+ const startLiveMirror = (next) => {
11098
+ if (livePort?.liveIntervalMs === void 0) return;
11099
+ stopLiveMirror();
11100
+ const schedule = () => {
11101
+ liveTimer = setTimeout(() => {
11102
+ if (liveInFlight === void 0 && workspaceCapturePromise === void 0) {
11103
+ const tracked = captureProviderLiveWorkspace(livePort, {
11104
+ environment: next,
11105
+ executionId: workspaceExecutionId,
11106
+ ...workspaceControlRef === void 0 ? {} : { controlRef: workspaceControlRef },
11107
+ ...node === void 0 ? {} : { node },
11108
+ providerSessionId,
11109
+ nativeSessionId: null,
11110
+ profile: createProfile
11111
+ }).then(() => void 0, () => void 0).finally(() => {
11112
+ if (liveInFlight === tracked) liveInFlight = void 0;
11113
+ });
11114
+ liveInFlight = tracked;
11115
+ }
11116
+ schedule();
11117
+ }, livePort.liveIntervalMs);
11118
+ liveTimer.unref?.();
11119
+ };
11120
+ schedule();
11121
+ };
11001
11122
  let nativeHoldsTranscript = false;
11002
11123
  const stopNativeMirror = async () => {
11003
11124
  if (nativeTimer !== void 0) clearTimeout(nativeTimer);
@@ -11052,6 +11173,7 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
11052
11173
  return tracked;
11053
11174
  };
11054
11175
  const startNativeMirror = (next) => {
11176
+ startLiveMirror(next);
11055
11177
  if (nativePort === void 0) return;
11056
11178
  if (nativeTimer !== void 0) clearTimeout(nativeTimer);
11057
11179
  const interval = nativePort.nativeIntervalMs ?? 12e4;
@@ -11699,6 +11821,7 @@ async function* streamProviderExecutor(args) {
11699
11821
  handCaptureToOwner(settledResult, outcome, true);
11700
11822
  }
11701
11823
  } catch (error) {
11824
+ yield* creditUsage(usageLedger.settleTurn(args.profile.name ?? "agent"));
11702
11825
  failure = source.retained ? new RetainedExecutionPendingError(error) : error;
11703
11826
  failed = true;
11704
11827
  if (args.options.workspaceRetention !== void 0) args.onUnsettledFailure();
@@ -20886,337 +21009,984 @@ function singleShotDriver(maxIterations) {
20886
21009
  };
20887
21010
  }
20888
21011
  //#endregion
20889
- //#region src/runtime/supervise/dispatch.ts
21012
+ //#region src/runtime/supervise/continuation.ts
20890
21013
  /**
21014
+ * The continuation: what a manager with a completion check is told when its turn ends and the
21015
+ * check is unmet, and the one rule that decides whether it is sent back.
20891
21016
  *
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.
21017
+ * Measured on discovery-lab before this module (2026-09-24, 670 settled runs, 1,596 re-entries):
21018
+ * 1,565 re-entries followed a failed turn and resent the original task, and 31 carried note text.
21019
+ * The note Runtime wrote itself held seven fixed lines and no field for the check's verdict. Of 40
21020
+ * episodes where the director ended on its own and the outside check disagreed, 33 were told
21021
+ * nothing before they ended. 100 of 236 resubmits sent the identical packet. So the director
21022
+ * mostly graded itself, and when it was wrong it heard nothing it could use.
20913
21023
  *
20914
- * ── Why this is not a copy of the kernel's batch loop ──────────────────────────────────────────
21024
+ * The design (discovery `docs/38-one-loop-and-continuation.md`) makes three things single, and
21025
+ * this module holds the part Runtime owns:
20915
21026
  *
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.
21027
+ * - ONE CHECK. A check reading is a {@link CheckVerdict}: pass, the items it read, the composite,
21028
+ * and one `FAIL <item> <where>: <reason>` line per failed item. The same check decides
21029
+ * `submit_result`, runs when a turn ends without an accepted result, scores the finished run,
21030
+ * and ranks versions. A check that could not run gives no verdict ({@link CheckUnavailableError}),
21031
+ * and the loop pauses instead of blaming the director.
21032
+ * - ONE RESEND RULE. {@link ContinuationPolicy} is required for a manager with a check. It holds a
21033
+ * deadline and `maxBarren`, the re-entered turns in a row that may end without progress. There
21034
+ * is no re-prompt count and no default: a retry default in source is a research decision.
21035
+ * - ONE NOTE. {@link composeContinuationNote} writes it. Runtime owns the facts and their order;
21036
+ * the {@link ContinuationProfile} owns every instruction word, so an optimizer can change the
21037
+ * words without touching code. A play may append a section, never remove or rewrite one.
20925
21038
  *
20926
- * @experimental
21039
+ * Evidence behind the note's shape: located errors help (given the first mistake's true location,
21040
+ * fix rates rose 23.5 to 43.9 points, Tyen 2023); unsupported pressure does not (threats and tips
21041
+ * had no significant effect, Wharton 2025; challenges without evidence flipped correct answers,
21042
+ * FlipFlop); repeated summaries drop detail while itemized additions do not (ACE). So the note is
21043
+ * a list of located facts, findings are added and marked resolved rather than rewritten, and the
21044
+ * profile, not this file, decides how blunt the words are.
20927
21045
  */
20928
21046
  /**
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.
21047
+ * The check could not run: its box did not start, its judge's provider refused, its program
21048
+ * crashed. It is not a verdict on the result. Inside a run the loop pauses, as it does for an
21049
+ * unavailable upstream, and the refusal tells the director its result was not judged.
20935
21050
  */
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();
21051
+ var CheckUnavailableError = class extends Error {
21052
+ constructor(message, options) {
21053
+ super(message, options);
21054
+ this.name = "CheckUnavailableError";
20983
21055
  }
20984
- return {
20985
- settled,
20986
- admitted,
20987
- rejected,
20988
- stopReason,
20989
- peakLive
20990
- };
21056
+ };
21057
+ /** Read a check function's return value into a verdict. Anything but `true` or a passing verdict
21058
+ * is a failure: a check fails closed. */
21059
+ function checkVerdictOf(outcome) {
21060
+ if (outcome === true) return { pass: true };
21061
+ if (typeof outcome !== "object" || outcome === null || Array.isArray(outcome)) return { pass: false };
21062
+ const raw = outcome;
21063
+ 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;
21064
+ const failures = Array.isArray(raw.failures) ? raw.failures.filter((line) => typeof line === "string" && line.trim() !== "") : void 0;
21065
+ return Object.freeze({
21066
+ pass: raw.pass === true,
21067
+ ...items === void 0 ? {} : { items: Object.freeze(items) },
21068
+ ...finite(raw.composite) ? { composite: raw.composite } : {},
21069
+ ...finite(raw.threshold) ? { threshold: raw.threshold } : {},
21070
+ ...failures === void 0 ? {} : { failures: Object.freeze(failures) },
21071
+ ...typeof raw.review === "string" && raw.review.trim() !== "" ? { review: raw.review.trim() } : {}
21072
+ });
20991
21073
  }
20992
21074
  /**
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.
21075
+ * Read an agent-eval `JudgeScore` from a check program into a verdict.
21076
+ *
21077
+ * Each dimension is a checked item. `notes` lines that start with `FAIL ` are the failures; the
21078
+ * remaining lines are the check's review. The verdict passes when `composite >= threshold` and the
21079
+ * score is not marked `failed`; a `failed` score means the judge itself did not run, which is
21080
+ * {@link CheckUnavailableError}, not a verdict.
20996
21081
  */
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)
21082
+ function verdictFromJudgeScore(score, threshold) {
21083
+ if (score.failed === true) throw new CheckUnavailableError(`the check's judge did not run: ${score.notes}`);
21084
+ const lines = score.notes.split("\n").map((line) => line.trimEnd());
21085
+ const failures = lines.filter((line) => line.startsWith("FAIL "));
21086
+ const review = lines.filter((line) => !line.startsWith("FAIL ") && line.trim() !== "").join("\n");
21087
+ return checkVerdictOf({
21088
+ pass: score.composite >= threshold,
21089
+ items: score.dimensions,
21090
+ composite: score.composite,
21091
+ threshold,
21092
+ failures,
21093
+ ...review === "" ? {} : { review }
21034
21094
  });
21035
21095
  }
21036
- function freezeInteractiveRef(value) {
21037
- return detachedSnapshot(AgentInteractiveSessionRefSchema.parse(value), "interactive session ref");
21038
- }
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;
21044
- }
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;
21096
+ /** Items that fail in `verdict`: every item below 1, or the named items of its FAIL lines. */
21097
+ function failedItems(verdict) {
21098
+ if (verdict.items !== void 0) return Object.entries(verdict.items).filter(([, value]) => value < 1).map(([name]) => name);
21099
+ return (verdict.failures ?? []).map((line) => line.slice(5).split(/[\s:]/u)[0] ?? "");
21050
21100
  }
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;
21101
+ /** Items that pass in `verdict`. */
21102
+ function passedItems(verdict) {
21103
+ return Object.entries(verdict.items ?? {}).filter(([, value]) => value >= 1).map(([name]) => name);
21056
21104
  }
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`);
21105
+ /** Resolve and check a policy before any compute. Returns the deadline in epoch ms. */
21106
+ function admitContinuationPolicy(policy, context) {
21107
+ if (typeof policy !== "object" || policy === null) throw new ValidationError$1(`${context}: continuation must be an object`);
21108
+ const deadlineMs = typeof policy.deadline === "string" ? Date.parse(policy.deadline) : policy.deadline;
21109
+ 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)`);
21110
+ if (!Number.isInteger(policy.maxBarren) || policy.maxBarren < 1) throw new ValidationError$1(`${context}: continuation.maxBarren must be an integer >= 1`);
21111
+ if (policy.failures !== "verbatim" && policy.failures !== "off") throw new ValidationError$1(`${context}: continuation.failures must be 'verbatim' or 'off'`);
21112
+ if (policy.panel !== "on" && policy.panel !== "off") throw new ValidationError$1(`${context}: continuation.panel must be 'on' or 'off'`);
21113
+ if (policy.bar !== "on" && policy.bar !== "off") throw new ValidationError$1(`${context}: continuation.bar must be 'on' or 'off'`);
21114
+ if (policy.panel === "on") {
21115
+ if (typeof policy.runPanel !== "function") throw new ValidationError$1(`${context}: continuation.panel 'on' needs runPanel`);
21116
+ const usd = policy.panelUsd;
21117
+ 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
21118
  }
21119
+ if (policy.append !== void 0 && typeof policy.append !== "function") throw new ValidationError$1(`${context}: continuation.append must be a function`);
21120
+ admitContinuationProfile(policy.profile, context);
21121
+ return deadlineMs;
21063
21122
  }
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 });
21123
+ /** The facts a profile template may name. */
21124
+ const CONTINUATION_FACTS = [
21125
+ "composite",
21126
+ "threshold",
21127
+ "failed",
21128
+ "total",
21129
+ "reads",
21130
+ "owed",
21131
+ "settled",
21132
+ "delivered",
21133
+ "continuation"
21134
+ ];
21135
+ const factNames = new Set(CONTINUATION_FACTS);
21136
+ const placeholder = /\{([a-zA-Z]+)\}/gu;
21137
+ function admitContinuationProfile(profile, context) {
21138
+ if (typeof profile !== "object" || profile === null) throw new ValidationError$1(`${context}: continuation.profile must be an object`);
21139
+ if (typeof profile.id !== "string" || profile.id.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.id must be non-empty`);
21140
+ const texts = [
21141
+ ["opening", profile.opening],
21142
+ ["plan", profile.plan],
21143
+ ["rules", profile.rules],
21144
+ ...Object.entries(profile.headings ?? {}).map(([key, value]) => [`headings.${key}`, value]),
21145
+ ...profile.barRule === void 0 ? [] : [["barRule", profile.barRule]]
21146
+ ];
21147
+ for (const key of [
21148
+ "failures",
21149
+ "protected",
21150
+ "changed",
21151
+ "findings",
21152
+ "bar",
21153
+ "plan",
21154
+ "rules"
21155
+ ]) if (typeof profile.headings?.[key] !== "string") throw new ValidationError$1(`${context}: continuation.profile.headings.${key} must be a string`);
21156
+ for (const [key, text] of texts) {
21157
+ if (typeof text !== "string") throw new ValidationError$1(`${context}: continuation.profile.${key} must be a string`);
21158
+ 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
21159
  }
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");
21160
+ if (profile.review !== void 0) {
21161
+ if (typeof profile.review !== "string" || profile.review.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.review must be non-empty`);
21162
+ for (const match of profile.review.matchAll(placeholder)) if (![
21163
+ "version",
21164
+ "path",
21165
+ "score"
21166
+ ].includes(match[1] ?? "")) throw new ValidationError$1(`${context}: continuation.profile.review names {${match[1]}}; it may name {version}, {path} and {score}`);
21075
21167
  }
21076
- return status;
21168
+ if (profile.opening.trim() === "") throw new ValidationError$1(`${context}: continuation.profile.opening must be non-empty`);
21169
+ 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`);
21077
21170
  }
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);
21171
+ /** Findings reach the note only when every citation resolves, at least two distinct spans are
21172
+ * cited, and the independent verifier agreed. The best method in Who&When found the failing step
21173
+ * 14.2% of the time, so an unverified finding is noise with a citation. */
21174
+ function admitFinding(finding) {
21175
+ if (!finding.verified) return false;
21176
+ if (finding.citations.length === 0) return false;
21177
+ if (!finding.citations.every((citation) => citation.resolved)) return false;
21178
+ return new Set(finding.citations.map((citation) => citation.uri)).size >= 2;
21089
21179
  }
21090
- //#endregion
21091
- //#region src/runtime/retained-interactive.ts
21180
+ /** About 1,500 tokens of findings. */
21181
+ const FINDINGS_CHAR_CAP = 6e3;
21092
21182
  /**
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
21183
+ * Rank the admitted findings by how many failed items they explain, drop repeats, and keep them
21184
+ * within the note's cap. Earlier findings stay as they were written (ACE: itemized additions keep
21185
+ * detail that repeated rewrites lose); a finding whose items all pass now is marked resolved.
21097
21186
  */
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;
21187
+ function distillFindings(prior, proposed, failing, continuation) {
21188
+ const key = (claim) => claim.toLowerCase().replace(/\s+/gu, " ").trim();
21189
+ const known = new Set(prior.map((finding) => key(finding.claim)));
21190
+ const carried = prior.map((finding) => finding.resolvedAt === void 0 && (finding.items?.length ?? 0) > 0 && (finding.items ?? []).every((item) => !failing.has(item)) ? {
21191
+ ...finding,
21192
+ resolvedAt: continuation
21193
+ } : finding);
21194
+ const fresh = proposed.filter(admitFinding).filter((finding) => {
21195
+ const k = key(finding.claim);
21196
+ if (known.has(k)) return false;
21197
+ known.add(k);
21198
+ return true;
21199
+ }).map((finding) => ({
21200
+ finding,
21201
+ links: (finding.items ?? []).filter((item) => failing.has(item)).length
21202
+ })).sort((a, b) => b.links - a.links);
21203
+ const out = [...carried];
21204
+ let used = carried.filter((finding) => finding.resolvedAt === void 0).reduce((sum, finding) => sum + finding.claim.length, 0);
21205
+ for (const { finding } of fresh) {
21206
+ if (used + finding.claim.length > FINDINGS_CHAR_CAP) break;
21207
+ used += finding.claim.length;
21208
+ out.push({
21209
+ ...finding,
21210
+ admittedAt: continuation
21211
+ });
21134
21212
  }
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);
21213
+ return out;
21214
+ }
21215
+ /** Expand the profile's question templates over the failed items and the settled workers. */
21216
+ function expandQuestions(templates, failing, workers) {
21217
+ const out = [];
21218
+ for (const template of templates) {
21219
+ const hasItem = template.includes("{item}");
21220
+ const hasWorker = template.includes("{worker}");
21221
+ if (!hasItem && !hasWorker) {
21222
+ out.push(template);
21223
+ continue;
21224
+ }
21225
+ const items = hasItem ? failing : [""];
21226
+ const each = hasWorker ? workers.map((worker) => `${worker.id} (${worker.label})`) : [""];
21227
+ for (const item of items) for (const worker of each) out.push(template.replaceAll("{item}", item).replaceAll("{worker}", worker));
21228
+ }
21229
+ return out;
21152
21230
  }
21153
21231
  /**
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
21232
+ * Write one continuation note, sections 1 to 8 of docs/38. Section 9, the run's state, is
21233
+ * `composeReentryTask`, which wraps this text. Pure: the same input writes the same note.
21159
21234
  */
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
- });
21235
+ function composeContinuationNote(input) {
21236
+ const { profile, verdict } = input;
21237
+ const items = verdict?.items ?? {};
21238
+ const total = Object.keys(items).length;
21239
+ const failing = verdict === void 0 ? [] : failedItems(verdict);
21240
+ const facts = {
21241
+ composite: verdict?.composite === void 0 ? "unknown" : format(verdict.composite),
21242
+ threshold: verdict?.threshold === void 0 ? "unknown" : format(verdict.threshold),
21243
+ failed: verdict === void 0 || total === 0 && (verdict.failures?.length ?? 0) === 0 ? "unknown" : String(failing.length),
21244
+ total: total === 0 ? "unknown" : String(total),
21245
+ reads: String(input.reads),
21246
+ owed: input.owed?.trim() || "not described",
21247
+ settled: String(input.progress.settledCount),
21248
+ delivered: String(input.progress.deliveredCount ?? 0),
21249
+ continuation: String(input.continuation)
21250
+ };
21251
+ const fill = (text) => text.replace(placeholder, (_, name) => facts[name] ?? `{${name}}`);
21252
+ 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()];
21253
+ const section = (heading, body) => {
21254
+ if (body.length === 0) return;
21255
+ sections.push([...heading.trim() === "" ? [] : [`## ${fill(heading)}`], ...body].join("\n"));
21256
+ };
21257
+ if (input.failures === "verbatim" && verdict !== void 0) {
21258
+ const lines = verdict.failures ?? [];
21259
+ const shown = lines.slice(0, 40);
21260
+ const more = lines.length - shown.length;
21261
+ 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.`] : []]);
21262
+ const passing = passedItems(verdict);
21263
+ section(profile.headings.protected, passing.length === 0 ? [] : [passing.join(", ")]);
21264
+ if (input.previous !== void 0) {
21265
+ const before = new Set(failedItems(input.previous));
21266
+ const now = new Set(failing);
21267
+ const fixed = [...before].filter((item) => !now.has(item));
21268
+ const broke = [...now].filter((item) => !before.has(item));
21269
+ section(profile.headings.changed, [
21270
+ ...fixed.length === 0 ? [] : [`Now passing: ${fixed.join(", ")}.`],
21271
+ ...broke.length === 0 ? [] : [`Newly failing: ${broke.join(", ")}.`],
21272
+ ...fixed.length === 0 && broke.length === 0 ? ["No item changed since the last note."] : [],
21273
+ ...input.previous.composite !== void 0 && verdict.composite !== void 0 ? [`Composite: ${format(input.previous.composite)} then ${format(verdict.composite)}.`] : []
21274
+ ]);
21275
+ }
21174
21276
  }
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);
21186
- }
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;
21277
+ if (input.findings !== void 0) {
21278
+ const open = input.findings.filter((finding) => finding.resolvedAt === void 0);
21279
+ const resolved = input.findings.filter((finding) => finding.resolvedAt === input.continuation);
21280
+ 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}`)]);
21281
+ }
21282
+ if (input.bar !== void 0 && verdict !== void 0) {
21283
+ const body = [];
21284
+ if (profile.barRule?.trim()) body.push(fill(profile.barRule).trim());
21285
+ for (const [item, value] of Object.entries(items)) {
21286
+ const best = input.bar.best?.verdict.items?.[item];
21287
+ body.push(`- ${item}: ${value >= 1 ? "passes" : `fails (${format(value)})`}` + (best === void 0 ? "" : ` / ${input.bar.best?.label}: ${best >= 1 ? "passes" : `fails (${format(best)})`}`));
21288
+ }
21289
+ if (input.bar.best?.verdict.composite !== void 0) body.push(`Best version ${input.bar.best.label}: composite ${format(input.bar.best.verdict.composite)}.`);
21290
+ if (input.bar.reference?.trim()) body.push(`Reference result: ${input.bar.reference.trim()}`);
21291
+ if (verdict.review?.trim()) body.push(`The check's review: ${verdict.review.trim()}`);
21292
+ section(profile.headings.bar, body);
21293
+ }
21294
+ section(profile.headings.plan, profile.plan.trim() === "" ? [] : [fill(profile.plan).trim()]);
21295
+ section(profile.headings.rules, [...profile.rules.trim() === "" ? [] : [fill(profile.rules).trim()], ...input.sealed ? ["The score comes from cases you cannot see."] : []]);
21296
+ for (const appended of input.appended ?? []) section(appended.heading, appended.text.trim() === "" ? [] : [appended.text.trim()]);
21297
+ return sections.join("\n\n");
21195
21298
  }
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}`;
21299
+ function summarizeVerdict(verdict) {
21300
+ if (verdict === void 0) return null;
21301
+ const total = Object.keys(verdict.items ?? {}).length;
21302
+ return {
21303
+ pass: verdict.pass,
21304
+ ...verdict.composite === void 0 ? {} : { composite: verdict.composite },
21305
+ ...total === 0 ? {} : {
21306
+ failed: failedItems(verdict).length,
21307
+ total
21308
+ }
21205
21309
  };
21206
- return request.run.sessionId === historicalId("retained-session") && request.run.executionId === historicalId("retained-execution");
21207
21310
  }
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;
21311
+ function noteDigest(note) {
21312
+ return `sha256:${createHash("sha256").update(note).digest("hex")}`;
21218
21313
  }
21219
- function interactiveRequest(options, environment, profile, requestedProfileDigest, identity) {
21314
+ /** A run directory's continuation files: the root's at `<runDir>/continuations/<n>/`, a nested
21315
+ * manager's at `<runDir>/continuations/managers/<owner>/<n>/`. */
21316
+ const CONTINUATIONS_DIR = "continuations";
21317
+ /**
21318
+ * Write one continuation's files under `<dir>/<n>/`: `note.md`, `verdict.json`, and
21319
+ * `panel.jsonl` when the panel ran. The director reads them through `read_continuation`, because
21320
+ * its box cannot read the driver's run directory.
21321
+ */
21322
+ async function writeContinuationFiles(dir, continuation, files) {
21323
+ const at = join(dir, String(continuation));
21324
+ await mkdir(at, { recursive: true });
21325
+ await writeFile(join(at, "note.md"), `${files.note}\n`, "utf8");
21326
+ await writeFile(join(at, "verdict.json"), `${JSON.stringify(files.verdict ?? null, null, 2)}\n`, "utf8");
21327
+ 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");
21328
+ }
21329
+ /** The best composite across `reads`, or `undefined` when no read scored. */
21330
+ function bestComposite(reads) {
21331
+ let best;
21332
+ for (const read of reads) {
21333
+ const value = read.verdict?.composite;
21334
+ if (value !== void 0 && (best === void 0 || value > best)) best = value;
21335
+ }
21336
+ return best;
21337
+ }
21338
+ function finite(value) {
21339
+ return typeof value === "number" && Number.isFinite(value);
21340
+ }
21341
+ function format(value) {
21342
+ return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/u, "");
21343
+ }
21344
+ /** Build the continuation state for one manager with a check. */
21345
+ function createContinuationKeeper(input) {
21346
+ const { policy } = input;
21347
+ const failures = input.feedback === "pass-only" ? "off" : policy.failures;
21348
+ const entries = [];
21349
+ const notes = [];
21350
+ let findings = [];
21351
+ let panelUsd = 0;
21352
+ let panelUsdKnown = true;
21353
+ const latestVerdict = () => {
21354
+ const reads = input.reads();
21355
+ for (let i = reads.length - 1; i >= 0; i -= 1) {
21356
+ const read = reads[i];
21357
+ if (read?.verdict !== void 0) return {
21358
+ verdict: read.verdict,
21359
+ read: read.read
21360
+ };
21361
+ }
21362
+ return { read: 0 };
21363
+ };
21364
+ const closePrevious = () => {
21365
+ const last = entries.at(-1);
21366
+ const lastNote = notes.at(-1);
21367
+ if (last === void 0 || lastNote === void 0) return;
21368
+ const latest = latestVerdict();
21369
+ entries[entries.length - 1] = {
21370
+ ...last,
21371
+ after: latest.read > lastNote.read ? summarizeVerdict(latest.verdict) : null
21372
+ };
21373
+ };
21374
+ return {
21375
+ async compose(context) {
21376
+ closePrevious();
21377
+ const continuation = entries.length + 1;
21378
+ const { verdict, read } = latestVerdict();
21379
+ const failing = verdict === void 0 ? [] : failedItems(verdict);
21380
+ let panelRecord;
21381
+ let panelLines;
21382
+ if (policy.panel === "on" && policy.runPanel !== void 0 && policy.panelUsd !== void 0) {
21383
+ const workers = input.workers();
21384
+ const questions = expandQuestions(policy.profile.questions ?? [], failing, workers);
21385
+ const left = policy.panelUsd.perRun - panelUsd;
21386
+ const usdCap = Math.min(policy.panelUsd.perContinuation, left);
21387
+ const asking = questions.length > 0 && usdCap > 0 && panelUsdKnown;
21388
+ let traces;
21389
+ let unavailable;
21390
+ if (asking) try {
21391
+ traces = await input.traces?.();
21392
+ if (traces === void 0) unavailable = "the run has recorded no trace yet";
21393
+ } catch (error) {
21394
+ unavailable = `the run's traces could not be read: ${error instanceof Error ? error.message : String(error)}`;
21395
+ }
21396
+ if (asking && traces !== void 0) {
21397
+ const result = await policy.runPanel({
21398
+ continuation,
21399
+ task: input.task,
21400
+ ...verdict === void 0 ? {} : { verdict },
21401
+ reads: input.reads(),
21402
+ questions,
21403
+ traces,
21404
+ workers,
21405
+ ...policy.best === void 0 ? {} : { bar: policy.best },
21406
+ ...policy.reference === void 0 ? {} : { reference: policy.reference },
21407
+ usdCap,
21408
+ signal: context.signal
21409
+ });
21410
+ if (result.usd === null) panelUsdKnown = false;
21411
+ else panelUsd += result.usd;
21412
+ findings = distillFindings(findings, result.findings, new Set(failing), continuation);
21413
+ panelRecord = {
21414
+ asked: questions.length,
21415
+ proposed: result.findings.length,
21416
+ admitted: findings.filter((finding) => finding.admittedAt === continuation).length,
21417
+ usd: result.usd
21418
+ };
21419
+ panelLines = [...result.findings.map((finding) => ({
21420
+ kind: "finding",
21421
+ admitted: admitFinding(finding),
21422
+ ...finding
21423
+ })), ...result.receipts === void 0 ? [] : [{
21424
+ kind: "receipts",
21425
+ receipts: result.receipts
21426
+ }]];
21427
+ } else panelRecord = {
21428
+ asked: 0,
21429
+ proposed: 0,
21430
+ admitted: 0,
21431
+ usd: 0,
21432
+ ...unavailable === void 0 ? {} : { unavailable }
21433
+ };
21434
+ }
21435
+ const appended = policy.append ? await policy.append({
21436
+ continuation,
21437
+ ...verdict === void 0 ? {} : { verdict },
21438
+ reads: input.reads(),
21439
+ signal: context.signal
21440
+ }) : void 0;
21441
+ const note = composeContinuationNote({
21442
+ profile: policy.profile,
21443
+ continuation,
21444
+ ...verdict === void 0 ? {} : { verdict },
21445
+ ...notes.at(-1)?.verdict === void 0 ? {} : { previous: notes.at(-1)?.verdict },
21446
+ reads: input.reads().length,
21447
+ failures,
21448
+ ...policy.panel === "on" ? { findings } : {},
21449
+ ...policy.bar === "on" ? { bar: {
21450
+ ...policy.best === void 0 ? {} : { best: policy.best },
21451
+ ...policy.reference === void 0 ? {} : { reference: policy.reference }
21452
+ } } : {},
21453
+ ...appended === void 0 ? {} : { appended: [appended] },
21454
+ ...input.owed === void 0 ? {} : { owed: input.owed },
21455
+ progress: context.progress,
21456
+ canReadMore: input.canReadMore,
21457
+ canSubmitResult: input.canSubmitResult === true,
21458
+ ...input.sealed === true ? { sealed: true } : {}
21459
+ });
21460
+ notes.push({
21461
+ note,
21462
+ ...verdict === void 0 ? {} : { verdict },
21463
+ ...panelLines === void 0 ? {} : { panel: panelLines },
21464
+ read
21465
+ });
21466
+ entries.push({
21467
+ continuation,
21468
+ attempt: context.attempt,
21469
+ noteDigest: noteDigest(note),
21470
+ profile: policy.profile.id,
21471
+ switches: {
21472
+ failures,
21473
+ panel: policy.panel,
21474
+ bar: policy.bar
21475
+ },
21476
+ before: summarizeVerdict(verdict),
21477
+ after: null,
21478
+ ...panelRecord === void 0 ? {} : { panel: panelRecord },
21479
+ appended: appended === void 0 ? 0 : 1
21480
+ });
21481
+ if (input.dir !== void 0) await writeContinuationFiles(input.dir, continuation, {
21482
+ note,
21483
+ ...verdict === void 0 ? {} : { verdict },
21484
+ ...panelLines === void 0 ? {} : { panel: panelLines }
21485
+ });
21486
+ return note;
21487
+ },
21488
+ read(continuation) {
21489
+ const index = continuation === void 0 ? notes.length - 1 : continuation - 1;
21490
+ const entry = notes[index];
21491
+ if (entry === void 0) return {
21492
+ found: false,
21493
+ reason: notes.length === 0 ? "no continuation has been sent in this run" : `continuations run from 1 to ${notes.length}`
21494
+ };
21495
+ return {
21496
+ found: true,
21497
+ continuation: index + 1,
21498
+ note: entry.note,
21499
+ verdict: failures === "off" && entry.verdict !== void 0 ? { pass: entry.verdict.pass } : entry.verdict ?? null,
21500
+ findings: findings.filter((finding) => finding.admittedAt <= index + 1)
21501
+ };
21502
+ },
21503
+ entries() {
21504
+ closePrevious();
21505
+ return entries.map((entry) => ({ ...entry }));
21506
+ }
21507
+ };
21508
+ }
21509
+ //#endregion
21510
+ //#region src/runtime/supervise/completion-gate.ts
21511
+ /**
21512
+ *
21513
+ * The completion-oracle: **settled ⟺ DELIVERED.**
21514
+ *
21515
+ * Foreman's one hard lesson (0/18 self-improvement deliverables) — "done" must mean a check
21516
+ * PASSED, not the agent's say-so. `gateOnDeliverable` wraps an `Executor` so its settlement
21517
+ * is `valid` ONLY when the deliverable check passes. The child still RUNS and settles (its
21518
+ * spend is conserved into the pool either way), but a child that ran WITHOUT delivering
21519
+ * settles `valid:false` — so a keep-best driver never counts it as done, and a gate never
21520
+ * inflates with self-judged wins.
21521
+ *
21522
+ * Dual-purpose by construction:
21523
+ * - product: the agent fleet only advances on real, checked deliverables.
21524
+ * - proof: the gate's `valid` is the honest settle — equal-k comparisons can't be gamed by an
21525
+ * arm that "ran" without producing the artifact.
21526
+ *
21527
+ * The check is a DEPLOYABLE oracle — a test command, a state verifier, the commit0 judge —
21528
+ * read off the child's output, never the model judging itself. A throwing check is
21529
+ * fail-closed (not delivered), never a crash.
21530
+ *
21531
+ * @experimental
21532
+ */
21533
+ /**
21534
+ * Wrap an `Executor` so its settlement `valid` reflects the deliverable check, not the
21535
+ * inner verdict. Handles both `execute` shapes (one-shot `Promise<ExecutorResult>` and
21536
+ * streaming `AsyncIterable<UsageEvent>` + `resultArtifact()`); the check runs once the inner
21537
+ * executor has produced its output. The inner `score` is preserved; only `valid` is gated.
21538
+ */
21539
+ function gateOnDeliverable(inner, deliverable) {
21540
+ let gated;
21541
+ const check = async (out, baseScore) => {
21542
+ let delivered;
21543
+ try {
21544
+ delivered = checkVerdictOf(await deliverable.check(out)).pass;
21545
+ } catch {
21546
+ delivered = false;
21547
+ }
21548
+ return {
21549
+ valid: delivered,
21550
+ score: baseScore ?? (delivered ? 1 : 0)
21551
+ };
21552
+ };
21553
+ /**
21554
+ * Ask the delivery question once, from whatever the inner executor managed to produce.
21555
+ *
21556
+ * Fail-closed on the artifact being unavailable: an executor that never produced one delivered
21557
+ * nothing, and leaving `gated` unset keeps the existing invalid-by-default reading.
21558
+ */
21559
+ const settleVerdict = async () => {
21560
+ let art;
21561
+ try {
21562
+ art = inner.resultArtifact();
21563
+ } catch {
21564
+ return;
21565
+ }
21566
+ gated = await check(art.out, art.verdict?.score);
21567
+ };
21568
+ const gateExecution = (r) => {
21569
+ if (isAsyncIterable$1(r)) return (async function* () {
21570
+ try {
21571
+ for await (const ev of r) yield ev;
21572
+ } finally {
21573
+ await settleVerdict();
21574
+ }
21575
+ })();
21576
+ return (async () => {
21577
+ let res;
21578
+ try {
21579
+ res = await r;
21580
+ } catch (error) {
21581
+ await settleVerdict();
21582
+ throw error;
21583
+ }
21584
+ gated = await check(res.out, res.verdict?.score);
21585
+ return {
21586
+ ...res,
21587
+ verdict: gated
21588
+ };
21589
+ })();
21590
+ };
21591
+ return inheritRuntimeOwnedExecutorAttestation(inner, {
21592
+ runtime: inner.runtime,
21593
+ ...inner.budgetExempt !== void 0 ? { budgetExempt: inner.budgetExempt } : {},
21594
+ ...inner.deliver ? { deliver: (m) => inner.deliver?.(m) } : {},
21595
+ ...inner.progress ? { progress: () => inner.progress?.() } : {},
21596
+ ...inner.traceSource ? { traceSource: () => inner.traceSource?.() } : {},
21597
+ ...inner.metered ? { metered: () => inner.metered?.() } : {},
21598
+ ...inner.accounting ? { accounting: () => inner.accounting?.() } : {},
21599
+ ...inner.harnessTranscript ? { harnessTranscript: () => inner.harnessTranscript?.() } : {},
21600
+ ...inner.harnessTranscriptSettled ? { harnessTranscriptSettled: () => inner.harnessTranscriptSettled?.() ?? Promise.resolve() } : {},
21601
+ execute: (task, signal) => gateExecution(inner.execute(task, signal)),
21602
+ ...inner.recover ? { recover: (task, signal) => gateExecution(inner.recover(task, signal)) } : {},
21603
+ teardown: (grace) => inner.teardown(grace),
21604
+ ...teardownSurfaces(inner),
21605
+ resultArtifact() {
21606
+ const art = inner.resultArtifact();
21607
+ return {
21608
+ ...art,
21609
+ verdict: gated ?? art.verdict
21610
+ };
21611
+ }
21612
+ });
21613
+ }
21614
+ /**
21615
+ * Transform a Runtime executor's terminal artifact without losing its private
21616
+ * profile-materialization attestation or altering its measured spend. This is
21617
+ * the composition point for deterministic post-processing and grading; callers
21618
+ * must not rebuild an Executor around a model transport merely to change `out`.
21619
+ */
21620
+ function mapExecutorResult(inner, map) {
21621
+ let mapped;
21622
+ const settle = async (result, task) => {
21623
+ const transformed = await map(result, task);
21624
+ mapped = {
21625
+ outRef: transformed.outRef,
21626
+ out: transformed.out,
21627
+ ...transformed.verdict ? { verdict: transformed.verdict } : {},
21628
+ spent: result.spent
21629
+ };
21630
+ return mapped;
21631
+ };
21632
+ return inheritRuntimeOwnedExecutorAttestation(inner, {
21633
+ runtime: inner.runtime,
21634
+ ...inner.budgetExempt !== void 0 ? { budgetExempt: inner.budgetExempt } : {},
21635
+ ...inner.deliver ? { deliver: (message) => inner.deliver?.(message) } : {},
21636
+ ...inner.progress ? { progress: () => inner.progress?.() } : {},
21637
+ ...inner.traceSource ? { traceSource: () => inner.traceSource?.() } : {},
21638
+ ...inner.accounting ? { accounting: () => inner.accounting?.() } : {},
21639
+ ...inner.metered ? { metered: () => inner.metered?.() } : {},
21640
+ ...inner.harnessTranscript ? { harnessTranscript: () => inner.harnessTranscript?.() } : {},
21641
+ ...inner.harnessTranscriptSettled ? { harnessTranscriptSettled: () => inner.harnessTranscriptSettled?.() ?? Promise.resolve() } : {},
21642
+ execute(task, signal) {
21643
+ const execution = inner.execute(task, signal);
21644
+ if (isAsyncIterable$1(execution)) return (async function* () {
21645
+ for await (const event of execution) yield event;
21646
+ await settle(inner.resultArtifact(), task);
21647
+ })();
21648
+ return (async () => settle(await execution, task))();
21649
+ },
21650
+ teardown: (grace) => inner.teardown(grace),
21651
+ ...teardownSurfaces(inner),
21652
+ resultArtifact() {
21653
+ if (!mapped) throw new Error("mapExecutorResult: resultArtifact() read before execute()");
21654
+ return mapped;
21655
+ }
21656
+ });
21657
+ }
21658
+ //#endregion
21659
+ //#region src/runtime/supervise/dispatch.ts
21660
+ /**
21661
+ *
21662
+ * `rollingDispatch` — the REFILLING dispatch policy over a `Scope`. It keeps `width` children in
21663
+ * flight and admits the next queued unit of work the instant one settles, instead of waiting for
21664
+ * a whole round to drain (`fanout`) or for a driver to decide again (`spawn → await → spawn`).
21665
+ *
21666
+ * The gap it closes: `fanout` opens every item at once and then drains — one round, no refill —
21667
+ * and a driver brain's manual loop opens one worker per model turn. Between those two there was
21668
+ * nothing that holds N slots full, which is why a 5-worker run can peak at 2 live workers and sit
21669
+ * ~50% idle. This is a policy over the EXISTING `Scope.spawn` / `Scope.next` primitives: it adds
21670
+ * no second admission path, so the conserved budget pool stays the only fence on total work and
21671
+ * `width` is only a fence on simultaneous work.
21672
+ *
21673
+ * Fail-closed by construction: an admission rejection (`budget-exhausted` / `depth-exceeded`) is
21674
+ * recorded and STOPS further admission — the loop then drains what is already live and returns.
21675
+ * It never retries a rejected spawn against the same pool, and it never spawns past `width`.
21676
+ *
21677
+ * ── Concurrency ────────────────────────────────────────────────────────────────────────────────
21678
+ *
21679
+ * `width` bounds the children THIS dispatcher holds in flight. The tree-wide bound on working
21680
+ * agents is `SuperviseOptions.workerSlots` (`./worker-slots`): a spawn past it is queued by the
21681
+ * scope, not refused, so a `width` above the free slots only lengthens the allocator's queue.
21682
+ * `SandboxLineage`'s fork concurrency bounds boxes inside ONE leaf's fork wave, a different unit.
21683
+ *
21684
+ * ── Why this is not a copy of the kernel's batch loop ──────────────────────────────────────────
21685
+ *
21686
+ * `runBatch` (`src/runtime/run-loop.ts`) runs the same hold-N-slots-full shape over the KERNEL's
21687
+ * substrate: bare promises in a `Set`, raced with `Promise.race`, bounded by `maxConcurrency`.
21688
+ * This one runs it over the SUPERVISOR's substrate — `Scope.spawn`'s atomic reservation against
21689
+ * the conserved pool, `Scope.next`'s journaled settlement cursor, and the blob store behind each
21690
+ * result. Neither can be expressed in the other's terms without dragging its whole substrate
21691
+ * along: the kernel loop has no budget to reserve and no cursor to order settlements by, and this
21692
+ * one cannot race raw promises because a settlement is only real once it is journaled. The shape
21693
+ * repeating across the two deliberate layers is resonance, not duplication — do not "unify" them
21694
+ * into a shared helper that would have to know about both.
21695
+ *
21696
+ * @experimental
21697
+ */
21698
+ /**
21699
+ * Run the refilling dispatch loop over `scope` until the queue is dry (or a stop fires) and every
21700
+ * admitted child has settled. Returns the settlements in cursor order plus the admission ledger.
21701
+ *
21702
+ * The loop is: fill free slots from `nextUnit` → `await scope.next()` → deliver the settlement →
21703
+ * refill → repeat. Because the refill happens immediately after each settlement rather than after
21704
+ * a whole round, a slow child never idles the other slots.
21705
+ */
21706
+ async function rollingDispatch(scope, opts) {
21707
+ if (!Number.isInteger(opts.width) || opts.width < 1) throw new ValidationError$1(`rollingDispatch: width must be a positive integer, got ${String(opts.width)}`);
21708
+ const settled = [];
21709
+ const rejected = [];
21710
+ const live = /* @__PURE__ */ new Set();
21711
+ let admitted = 0;
21712
+ let peakLive = 0;
21713
+ let queueDry = false;
21714
+ let stopReason = "drained";
21715
+ const fill = async () => {
21716
+ while (live.size < opts.width) {
21717
+ if (queueDry) return;
21718
+ if (scope.signal.aborted) {
21719
+ stopReason = "aborted";
21720
+ queueDry = true;
21721
+ return;
21722
+ }
21723
+ if (opts.shouldStop?.() === true) {
21724
+ stopReason = "stopped";
21725
+ queueDry = true;
21726
+ return;
21727
+ }
21728
+ const unit = await opts.nextUnit();
21729
+ if (unit === void 0) {
21730
+ queueDry = true;
21731
+ return;
21732
+ }
21733
+ const res = scope.spawn(unit.agent, unit.task, unit.opts);
21734
+ if (!res.ok) {
21735
+ rejected.push(`${unit.opts.label}: ${res.reason}`);
21736
+ stopReason = "not-admitted";
21737
+ queueDry = true;
21738
+ return;
21739
+ }
21740
+ live.add(res.handle.id);
21741
+ admitted += 1;
21742
+ if (live.size > peakLive) peakLive = live.size;
21743
+ }
21744
+ };
21745
+ await fill();
21746
+ while (live.size > 0) {
21747
+ const s = await scope.next();
21748
+ if (s === null) break;
21749
+ live.delete(s.handle.id);
21750
+ settled.push(s);
21751
+ await opts.onSettled?.(s);
21752
+ await fill();
21753
+ }
21754
+ return {
21755
+ settled,
21756
+ admitted,
21757
+ rejected,
21758
+ stopReason,
21759
+ peakLive
21760
+ };
21761
+ }
21762
+ /**
21763
+ * Free worker slots under a simultaneity cap: `cap - live`, floored at 0, or `null` when there is
21764
+ * no cap (the conserved pool is then the only fence and "free slots" is not a finite number).
21765
+ * The one place the answer is computed, so the driver-facing tool payload and a dispatcher agree.
21766
+ */
21767
+ function freeSlots(liveCount, cap) {
21768
+ if (cap === void 0 || cap <= 0) return null;
21769
+ return Math.max(0, cap - liveCount);
21770
+ }
21771
+ /** Convenience: a `DispatchUnit` factory over a fixed array of tasks, for the common case where
21772
+ * the queue is known up front and only the refill behavior is wanted. */
21773
+ function queueOf(units, budget) {
21774
+ let i = 0;
21775
+ return () => {
21776
+ const u = units[i];
21777
+ if (u === void 0) return void 0;
21778
+ i += 1;
21779
+ return {
21780
+ agent: u.agent,
21781
+ task: u.task,
21782
+ opts: {
21783
+ budget,
21784
+ label: u.label
21785
+ }
21786
+ };
21787
+ };
21788
+ }
21789
+ //#endregion
21790
+ //#region src/runtime/retained-interactive-handle.ts
21791
+ function createRetainedInteractiveRunHandle(environment, inputRef, capabilities, requestedStart) {
21792
+ const ref = freezeInteractiveRef(inputRef);
21793
+ const source = environment.interactive(ref);
21794
+ if (!sameInteractiveRef(source.ref, ref)) throw new Error("provider reconstructed a different interactive process");
21795
+ if (!source.sendPrompt) throw new Error("provider declared interactive prompt support but exposed no prompt method");
21796
+ return Object.freeze({
21797
+ ref,
21798
+ capabilities,
21799
+ claimControl: async (request, options) => exactClaim(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.claimControl(request, options)), options?.signal)),
21800
+ status: async (options) => exactStatus(ref, await awaitAbortable$1(Promise.resolve().then(() => source.status(options)), options?.signal), requestedStart),
21801
+ attach: async (request, options) => exactTerminal(ref, request, await awaitAbortable$1(Promise.resolve().then(() => source.attach(request, options)), options?.signal)),
21802
+ sendPrompt: async (command, options) => exactPrompt(ref, await awaitAbortable$1(Promise.resolve().then(() => source.sendPrompt(command, options)), options?.signal), command),
21803
+ stop: async (command, options) => exactStop(ref, await awaitAbortable$1(Promise.resolve().then(() => source.stop(command, options)), options?.signal), command)
21804
+ });
21805
+ }
21806
+ function freezeInteractiveRef(value) {
21807
+ return detachedSnapshot(AgentInteractiveSessionRefSchema.parse(value), "interactive session ref");
21808
+ }
21809
+ function exactClaim(ref, request, value) {
21810
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionControlClaimAcknowledgementSchema, value, "control claim");
21811
+ if (!agentInteractiveSessionControlClaimAcknowledgementMatchesRequest(request, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a control claim acknowledgement for another request");
21812
+ if (acknowledgement.control && !agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a control claim for another interactive process");
21813
+ return acknowledgement;
21814
+ }
21815
+ function exactPrompt(ref, value, command) {
21816
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionPromptAcknowledgementSchema, value, "prompt");
21817
+ if (!agentInteractiveSessionPromptAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another request");
21818
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another interactive process");
21819
+ return acknowledgement;
21820
+ }
21821
+ function exactStop(ref, value, command) {
21822
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionStopAcknowledgementSchema, value, "stop");
21823
+ if (!agentInteractiveSessionStopAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another request");
21824
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another interactive process");
21825
+ return acknowledgement;
21826
+ }
21827
+ function parseProviderAcknowledgement(schema, value, operation) {
21828
+ try {
21829
+ return schema.parse(value);
21830
+ } catch {
21831
+ throw new RetainedRunProviderContractError(`provider returned an invalid interactive ${operation} acknowledgement`);
21832
+ }
21833
+ }
21834
+ function exactStatus(ref, value, requestedStart) {
21835
+ let status;
21836
+ try {
21837
+ status = AgentInteractiveSessionStatusSchema.parse(value);
21838
+ } catch (error) {
21839
+ if (requestedStart === void 0) throw error;
21840
+ throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), {}, { cause: error });
21841
+ }
21842
+ if (!agentInteractiveSessionStatusMatchesRef(ref, status)) {
21843
+ 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") });
21844
+ throw new Error("provider returned status for another interactive process");
21845
+ }
21846
+ return status;
21847
+ }
21848
+ function exactTerminal(ref, request, terminal) {
21849
+ const terminalRef = TerminalSessionRefSchema.parse(terminal.ref);
21850
+ TerminalReplayWindowSchema.parse(terminal.cursors);
21851
+ if (terminalRef.parentExecutionId !== ref.run.executionId) throw new Error("provider attached a terminal from another interactive run");
21852
+ AgentInteractiveSessionControlClaimSchema.parse(terminal.control);
21853
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, terminal.control)) throw new Error("provider attached a terminal with a claim for another interactive process");
21854
+ if (canonicalCandidateDigest(terminal.control) !== canonicalCandidateDigest(request.control)) throw new Error("provider attached a terminal with a different interactive control claim");
21855
+ return terminal;
21856
+ }
21857
+ function sameInteractiveRef(left, right) {
21858
+ return canonicalCandidateDigest(left) === canonicalCandidateDigest(right);
21859
+ }
21860
+ //#endregion
21861
+ //#region src/runtime/retained-interactive.ts
21862
+ /**
21863
+ * Start one retry-safe native coding-agent TUI without dispatching a headless turn.
21864
+ * The intent admission is durable before provider.create; the environment and
21865
+ * process admissions follow only after their exact provider coordinates exist.
21866
+ * @stable
21867
+ */
21868
+ async function startRetainedInteractiveRun(options) {
21869
+ options.signal?.throwIfAborted();
21870
+ const startOptions = options;
21871
+ assertStableText(startOptions.environment.idempotencyKey, "environment idempotency key");
21872
+ assertStableText(startOptions.interactiveIdempotencyKey, "interactive idempotency key");
21873
+ if (typeof startOptions.onAdmission !== "function") throw new Error("startRetainedInteractiveRun requires an awaited onAdmission durability hook");
21874
+ if (!startOptions.provider.get) throw new Error(`provider "${startOptions.provider.name}" cannot reconstruct an environment by id`);
21875
+ const profile = agentProfileSchema.parse(startOptions.environment.profile);
21876
+ if (profile.harness === void 0) throw new Error("retained interactive runs require AgentProfile.harness");
21877
+ const requestedProfileDigest = canonicalAgentProfileDigest(profile);
21878
+ const identity = startOptions.intent === void 0 ? mintRetainedIdentity(startOptions.environment.idempotencyKey, startOptions.interactiveIdempotencyKey) : {
21879
+ sessionId: startOptions.intent.sessionId,
21880
+ executionId: startOptions.intent.executionId
21881
+ };
21882
+ assertStableText(identity.sessionId, "retained session id");
21883
+ assertStableText(identity.executionId, "retained execution id");
21884
+ const intent = interactiveIntent(startOptions, profile, identity);
21885
+ if (startOptions.intent === void 0) await admitDurably(startOptions.onAdmission, intent);
21886
+ else assertExactInteractiveIntent(startOptions.intent, intent);
21887
+ const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable$1(Promise.resolve().then(() => startOptions.provider.capabilities()), startOptions.signal));
21888
+ assertInteractiveCapabilities(startOptions.provider.name, providerCapabilities);
21889
+ const environment = await createInteractiveEnvironment(() => startOptions.provider.create({
21890
+ ...startOptions.environment,
21891
+ profile,
21892
+ signal: startOptions.signal,
21893
+ metadata: retainedEnvironmentMetadata(startOptions.environment.metadata, startOptions.environment.idempotencyKey)
21894
+ }), startOptions.signal);
21895
+ let capabilities;
21896
+ try {
21897
+ assertExactEnvironment(startOptions.provider.name, environment);
21898
+ startOptions.signal?.throwIfAborted();
21899
+ capabilities = interactiveCapabilitiesForEnvironment(startOptions.provider.name, providerCapabilities, environment);
21900
+ assertInteractiveMethods(startOptions.provider.name, environment);
21901
+ } catch (error) {
21902
+ await destroyUnusedEnvironment(environment, error);
21903
+ throw error;
21904
+ }
21905
+ const request = interactiveRequest(startOptions, environment, profile, requestedProfileDigest, identity);
21906
+ await admitDurably(startOptions.onAdmission, {
21907
+ phase: "interactive_environment",
21908
+ provider: startOptions.provider.name,
21909
+ environmentId: environment.id,
21910
+ idempotencyKey: startOptions.environment.idempotencyKey,
21911
+ interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
21912
+ request
21913
+ });
21914
+ const ref = exactStartedRef(request, await startInteractiveProcess(environment, () => environment.startInteractive(request, { signal: startOptions.signal }), startOptions.signal));
21915
+ await admitDurably(startOptions.onAdmission, {
21916
+ phase: "interactive_started",
21917
+ idempotencyKey: startOptions.environment.idempotencyKey,
21918
+ interactiveIdempotencyKey: startOptions.interactiveIdempotencyKey,
21919
+ ref
21920
+ });
21921
+ return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
21922
+ }
21923
+ /**
21924
+ * Retry one exact start after its provider response may have been lost.
21925
+ *
21926
+ * Resolves to the handle of the admitted process (resumed through the exact,
21927
+ * idempotent start request), or `null` when the provider no longer holds the
21928
+ * environment (not found; nothing remains to stop). @stable
21929
+ */
21930
+ async function recoverRetainedInteractiveRun(options) {
21931
+ options.signal?.throwIfAborted();
21932
+ if (typeof options.onAdmission !== "function") throw new Error("recoverRetainedInteractiveRun requires an awaited onAdmission durability hook");
21933
+ const admission = options.admission;
21934
+ if (admission.provider !== options.provider.name) throw new Error("interactive admission belongs to another provider");
21935
+ if (admission.phase === "interactive_intent") {
21936
+ if (options.replay === void 0) throw new Error("recoverRetainedInteractiveRun requires the original start material for an interactive intent");
21937
+ return startRetainedInteractiveRun({
21938
+ provider: options.provider,
21939
+ ...options.replay,
21940
+ intent: admission,
21941
+ onAdmission: options.onAdmission,
21942
+ signal: options.signal
21943
+ });
21944
+ }
21945
+ const request = exactRecoveryRequest(admission);
21946
+ const { environment, capabilities } = await reconstructEnvironment(options.provider, admission.environmentId, options.signal);
21947
+ if (!environment || !capabilities) return null;
21948
+ const ref = exactStartedRef(request, await awaitAbortable$1(Promise.resolve().then(() => environment.startInteractive(request, { signal: options.signal })), options.signal));
21949
+ await admitDurably(options.onAdmission, {
21950
+ phase: "interactive_started",
21951
+ idempotencyKey: admission.idempotencyKey,
21952
+ interactiveIdempotencyKey: admission.interactiveIdempotencyKey,
21953
+ ref
21954
+ });
21955
+ return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
21956
+ }
21957
+ function exactRecoveryRequest(admission) {
21958
+ assertStableText(admission.environmentId, "interactive environment id");
21959
+ assertStableText(admission.idempotencyKey, "environment idempotency key");
21960
+ assertStableText(admission.interactiveIdempotencyKey, "interactive idempotency key");
21961
+ const request = exactAgentInteractiveSessionStart(admission.request);
21962
+ const identity = mintRetainedIdentity(admission.idempotencyKey, admission.interactiveIdempotencyKey);
21963
+ 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");
21964
+ return request;
21965
+ }
21966
+ function matchesHistoricalInteractiveIdentity(admission, request) {
21967
+ const base = `${encodeURIComponent(admission.idempotencyKey)}:${encodeURIComponent(admission.interactiveIdempotencyKey)}`;
21968
+ const digest = canonicalCandidateDigest({
21969
+ kind: "retained-identity.v1",
21970
+ base
21971
+ }).slice(7);
21972
+ const historicalId = (prefix) => {
21973
+ const readable = `${prefix}:${base}`;
21974
+ return readable.length <= 128 ? readable : `${prefix}:${digest}`;
21975
+ };
21976
+ return request.run.sessionId === historicalId("retained-session") && request.run.executionId === historicalId("retained-execution");
21977
+ }
21978
+ /** Rebuild controls for one exact provider-owned coding-agent process. @stable */
21979
+ async function reconnectRetainedInteractiveRun(options) {
21980
+ options.signal?.throwIfAborted();
21981
+ const ref = AgentInteractiveSessionRefSchema.parse(options.ref);
21982
+ if (ref.run.provider !== options.provider.name) throw new Error("interactive session reference belongs to another provider");
21983
+ const { environment, capabilities } = await reconstructEnvironment(options.provider, ref.run.environmentId, options.signal);
21984
+ if (!environment || !capabilities) return null;
21985
+ const handle = createRetainedInteractiveRunHandle(environment, ref, capabilities);
21986
+ await handle.status({ signal: options.signal });
21987
+ return handle;
21988
+ }
21989
+ function interactiveRequest(options, environment, profile, requestedProfileDigest, identity) {
21220
21990
  const start = {
21221
21991
  profile,
21222
21992
  requestedProfileDigest,
@@ -21798,6 +22568,25 @@ function stableText(value, label) {
21798
22568
  return text;
21799
22569
  }
21800
22570
  //#endregion
22571
+ //#region src/runtime/supervise/provider-visible-profile.ts
22572
+ /** Runtime-owned coordination is mounted under this MCP alias. */
22573
+ const coordinationMcpAlias = "agent-runtime-coordination";
22574
+ /** A profile declares Runtime-owned tools with this provider-neutral prefix. */
22575
+ const coordinationProfileToolPrefix = `${coordinationMcpAlias.replaceAll("-", "_")}_`;
22576
+ /** Remove Runtime-only grants and seat policy from the provider-facing profile. */
22577
+ function providerVisibleProfile(profile) {
22578
+ const { seats: _seats, ...withoutSeats } = profile;
22579
+ if (profile.tools === void 0) return withoutSeats;
22580
+ const providerTools = Object.fromEntries(Object.entries(profile.tools).filter(([name]) => !name.startsWith(coordinationProfileToolPrefix)));
22581
+ if (Object.keys(providerTools).length === Object.keys(profile.tools).length) return withoutSeats;
22582
+ if (Object.keys(providerTools).length > 0) return {
22583
+ ...withoutSeats,
22584
+ tools: providerTools
22585
+ };
22586
+ const { tools: _runtimeTools, ...withoutTools } = withoutSeats;
22587
+ return withoutTools;
22588
+ }
22589
+ //#endregion
21801
22590
  //#region src/runtime/supervise/terminal-record.ts
21802
22591
  /** The settlement fields every writer copies, in the terminal record's key order. The
21803
22592
  * `reconciled` record is built from this same spread so it and the terminal record can never
@@ -21950,7 +22739,7 @@ async function healReleasedSlots(opts, signal, now) {
21950
22739
  };
21951
22740
  await opts.journal.appendEvent(tree.root, terminalDownEvent(subject, settlement, settledSeq, floor.at, "released"));
21952
22741
  healed += 1;
21953
- const materialized = owned.find((event) => event.kind === "materialized");
22742
+ const materialized = [...owned].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized");
21954
22743
  const lastReceipt = receipts[receipts.length - 1];
21955
22744
  notifyRuntimeHookEvent(opts.hooks, {
21956
22745
  id: `${spawned.id}:released`,
@@ -22032,7 +22821,7 @@ async function prepareInterruptedExecutors(opts, events, signal, now, parentId =
22032
22821
  });
22033
22822
  if (!prepared) continue;
22034
22823
  }
22035
- const priorMaterialization = owned.find((event) => event.kind === "materialized")?.receipt;
22824
+ const priorMaterialization = [...owned].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized")?.receipt;
22036
22825
  const continuation = latestInput !== void 0 && inputs.length > 1 && node.ownedTreeRoot === void 0 ? await leafContinuation(node, owned, latestInput, opts) : void 0;
22037
22826
  recoveries.push({
22038
22827
  ...detachedSnapshot({
@@ -22100,7 +22889,7 @@ async function leafContinuation(node, owned, latestInput, opts) {
22100
22889
  }
22101
22890
  async function assertRecordedResult(node, result, events, opts) {
22102
22891
  const before = events.slice(0, events.indexOf(result));
22103
- const receipt = before.find((event) => event.kind === "materialized")?.receipt;
22892
+ const receipt = [...before].reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized")?.receipt;
22104
22893
  const binding = [...before].reverse().find((event) => event.kind === "execution-bound")?.binding;
22105
22894
  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
22895
  assertValidSpend(result.spent, `retained result '${result.id}'`);
@@ -22570,13 +23359,9 @@ function registerScopeRetainedOwner(scope, args) {
22570
23359
  const taskEvent = [...events].reverse().find((event) => event.kind === "execution-input");
22571
23360
  const start = taskEvent === void 0 ? 0 : events.indexOf(taskEvent);
22572
23361
  const attempt = events.slice(start);
22573
- const beforeInput = taskEvent === void 0 ? [] : events.slice(0, start);
22574
- const priorInput = [...beforeInput].reverse().find((event) => event.kind === "execution-input");
22575
- const priorAttempt = priorInput === void 0 ? [] : beforeInput.slice(beforeInput.indexOf(priorInput));
22576
23362
  const admissions = attempt.flatMap((event) => event.kind === "execution-admitted" ? [event.admission] : []);
22577
23363
  const acceptedRef = [...attempt].reverse().find((event) => event.kind === "execution-result");
22578
- const priorResult = [...priorAttempt].reverse().find((event) => event.kind === "execution-result");
22579
- const priorSession = priorResult?.kind === "execution-result" ? priorAttempt.slice(0, priorAttempt.indexOf(priorResult)).reverse().flatMap((event) => event.kind === "execution-admitted" && event.admission.phase === "environment" ? [event.admission] : [])[0] : void 0;
23364
+ const priorSession = taskEvent === void 0 ? void 0 : committedSession(events, start);
22580
23365
  let sequence = Math.max(0, ...events.map((event) => "seq" in event ? event.seq : 0));
22581
23366
  const state = {
22582
23367
  args,
@@ -22679,9 +23464,81 @@ function registerScopeRetainedOwner(scope, args) {
22679
23464
  };
22680
23465
  owners.set(scope, state);
22681
23466
  }
23467
+ /**
23468
+ * The environment admission an invocation that starts at `before` continues in: that of the
23469
+ * latest earlier invocation with a committed result, looking past invocations Runtime abandoned,
23470
+ * which never committed one. A live process keeps the same session across an abandonment, so a
23471
+ * resumed one must derive it the same way or its replay of the next invocation would not match
23472
+ * the material that invocation admitted.
23473
+ */
23474
+ function committedSession(events, before) {
23475
+ let end = before;
23476
+ for (;;) {
23477
+ const head = events.slice(0, end);
23478
+ const input = [...head].reverse().find((event) => event.kind === "execution-input");
23479
+ if (input === void 0) return void 0;
23480
+ const start = head.indexOf(input);
23481
+ const attempt = head.slice(start);
23482
+ const result = [...attempt].reverse().find((event) => event.kind === "execution-result");
23483
+ if (result !== void 0) return attempt.slice(0, attempt.indexOf(result)).reverse().flatMap((event) => event.kind === "execution-admitted" && event.admission.phase === "environment" ? [event.admission] : [])[0];
23484
+ if (!attempt.some((event) => event.kind === "execution-abandoned")) return void 0;
23485
+ end = start;
23486
+ }
23487
+ }
23488
+ /** Bounds the stop Runtime asks for before abandoning a dispatched invocation. */
23489
+ const ABANDON_STOP_TIMEOUT_MS = 3e4;
23490
+ /**
23491
+ * Abandon the owner's in-flight invocation, which the driver retry loop asks for when the same
23492
+ * reconciliation keeps failing the same way (`DriverRetryRun.resolvePending`).
23493
+ *
23494
+ * Runtime stops the invocation at the provider when it had dispatched, then journals what the
23495
+ * provider confirmed. The journal refuses every later admission or result of the invocation, so
23496
+ * only the replacement the next {@link prepareScopeRetainedOwnerTask} starts can commit a result.
23497
+ * Answers `false`, journaling nothing, when this owner has no unfinished invocation to abandon.
23498
+ */
23499
+ async function abandonScopeRetainedOwnerInvocation(scope, failure, failures) {
23500
+ const state = owners.get(scope);
23501
+ if (state === void 0 || state.inputSequence === void 0) return false;
23502
+ const { args } = state;
23503
+ const owned = (await args.journal.loadTree(args.rootId) ?? []).filter((event) => event.id === args.nodeId);
23504
+ const latestInput = [...owned].reverse().find((event) => event.kind === "execution-input");
23505
+ if (latestInput?.kind !== "execution-input" || latestInput.seq !== state.inputSequence) return false;
23506
+ const attempt = owned.slice(owned.indexOf(latestInput));
23507
+ if (attempt.some((event) => event.kind === "execution-result" || event.kind === "execution-abandoned")) return false;
23508
+ const dispatched = [...attempt].reverse().flatMap((event) => event.kind === "execution-admitted" && event.admission.phase === "dispatched" ? [event.admission] : [])[0];
23509
+ const stop = dispatched === void 0 || state.provider === void 0 ? void 0 : await stopRetainedNativeExecution({
23510
+ provider: state.provider,
23511
+ controlRef: dispatched.controlRef,
23512
+ signal: AbortSignal.any([scope.signal, AbortSignal.timeout(ABANDON_STOP_TIMEOUT_MS)]),
23513
+ now: args.now
23514
+ });
23515
+ scope.signal.throwIfAborted();
23516
+ const stopped = stop?.effect === "cancelled" || stop?.effect === "not_live";
23517
+ await args.journal.appendEvent(args.rootId, {
23518
+ kind: "execution-abandoned",
23519
+ id: args.nodeId,
23520
+ inputSeq: latestInput.seq,
23521
+ pendingCause: failure.pendingCause,
23522
+ failures,
23523
+ detail: errorText(errMessage(failure)).slice(0, 2048),
23524
+ outcome: stopped ? "stopped" : "uncertain",
23525
+ ...stop === void 0 ? {} : { stop: {
23526
+ executionId: stop.executionId,
23527
+ effect: stop.effect,
23528
+ ...stop.error === void 0 ? {} : { error: stop.error }
23529
+ } },
23530
+ seq: state.nextSequence(),
23531
+ at: new Date(args.now()).toISOString()
23532
+ });
23533
+ return true;
23534
+ }
22682
23535
  function scopeRetainedOwnerContext(scope) {
22683
23536
  return owners.get(scope)?.context;
22684
23537
  }
23538
+ /** The journal tree that owns this manager turn, including nested driver children. */
23539
+ function scopeRetainedOwnerJournalRoot(scope) {
23540
+ return owners.get(scope)?.args.rootId;
23541
+ }
22685
23542
  /**
22686
23543
  * Bind cleanup before replay can return an already accepted owner result. `checkpointCapture` is
22687
23544
  * where each checkpoint's files are stored before the checkpoint is deleted; without it, no
@@ -22796,6 +23653,59 @@ function noteScopeRetainedOwnerCoordination(scope) {
22796
23653
  delete state.checkpointing;
22797
23654
  });
22798
23655
  }
23656
+ /** A committed turn is the seat boundary. Keep its native home for a same-harness provider
23657
+ * continuation; only a provider/harness change needs a new environment. */
23658
+ async function prepareScopeRetainedOwnerSeatSwitch(scope, mode) {
23659
+ const state = owners.get(scope);
23660
+ if (!state?.acceptedRef || !state.acceptedConsumed) throw new ValidationError$1("seat switch requires a committed owner turn");
23661
+ const accepted = state.acceptedRef;
23662
+ await scopeRetainedOwnerTurnEnded(scope);
23663
+ await state.checkpointing;
23664
+ await checkpointOwnerWorkspace(scope, state);
23665
+ const owned = (await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId);
23666
+ const acceptedIndex = owned.findIndex((event) => event.kind === "execution-result" && event.seq === accepted.seq && event.outRef === accepted.outRef);
23667
+ if (acceptedIndex < 0) throw new ValidationError$1("seat switch has no committed result in its journal");
23668
+ const source = owned.slice(0, acceptedIndex).reverse().find((event) => event.kind === "execution-admitted" && event.admission.phase === "environment");
23669
+ const sourceEnvironmentId = source?.kind === "execution-admitted" && source.admission.phase === "environment" ? source.admission.environmentId : void 0;
23670
+ const checkpoint = sourceEnvironmentId !== void 0 ? owned.slice(acceptedIndex + 1).reverse().find((event) => event.kind === "workspace-checkpoint" && event.environmentId === sourceEnvironmentId) : void 0;
23671
+ if (checkpoint?.kind !== "workspace-checkpoint") throw new ValidationError$1("seat switch requires a checkpoint of the committed source environment");
23672
+ if (mode === "replace-environment") {
23673
+ await retireSeatEnvironment(scope, state);
23674
+ state.forceNewSession = true;
23675
+ }
23676
+ return {
23677
+ checkpointAt: checkpoint.at,
23678
+ checkpointId: checkpoint.checkpoint.checkpointId,
23679
+ sourceEnvironmentId: checkpoint.environmentId
23680
+ };
23681
+ }
23682
+ /** The next seat receives fresh create-time credentials. Release the stopped source only after
23683
+ * its checkpoint exists, then commit the teardown so recovery never tries its old session. */
23684
+ async function retireSeatEnvironment(scope, state) {
23685
+ const { provider, args } = state;
23686
+ if (!provider?.get) throw new ValidationError$1("seat switch requires a provider with exact environment lookup");
23687
+ const owned = (await args.journal.loadTree(args.rootId) ?? []).filter((event) => event.id === args.nodeId);
23688
+ const admitted = [...owned].reverse().find((event) => event.kind === "execution-admitted" && event.admission.phase === "environment");
23689
+ if (admitted?.kind !== "execution-admitted" || admitted.admission.phase !== "environment") throw new ValidationError$1("seat switch has no committed source environment");
23690
+ const environmentId = admitted.admission.environmentId;
23691
+ if (owned.some((event) => event.kind === "environment-teardown" && event.destroyed && event.environmentId === environmentId)) return;
23692
+ const signal = AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]);
23693
+ const environment = await runAbortable(() => provider.get(environmentId), signal, "seat switch environment lookup timed out");
23694
+ if (environment !== null) {
23695
+ if (environment.id !== environmentId || environment.provider !== provider.name || !environment.destroy) throw new ValidationError$1("seat switch cannot retire the exact source environment");
23696
+ await runAbortable(() => environment.destroy(), signal, "seat switch environment retirement timed out");
23697
+ }
23698
+ await args.journal.appendEvent(args.rootId, {
23699
+ kind: "environment-teardown",
23700
+ id: args.nodeId,
23701
+ provider: provider.name,
23702
+ environmentId,
23703
+ destroyed: true,
23704
+ detail: "seat changed after a committed turn",
23705
+ seq: state.nextSequence(),
23706
+ at: new Date(args.now()).toISOString()
23707
+ });
23708
+ }
22799
23709
  async function checkpointOwnerWorkspace(scope, state) {
22800
23710
  const { provider, args } = state;
22801
23711
  if (provider === void 0) return;
@@ -22973,7 +23883,8 @@ async function cleanCheckpoints(state, branching, checkpoints, events, parent) {
22973
23883
  for (const event of checkpoints) {
22974
23884
  const captured = await captureBeforeCleanup(state, branching, event, events, parent);
22975
23885
  if ("reason" in captured) {
22976
- (state.captureRefused ??= /* @__PURE__ */ new Set()).add(event.checkpoint.checkpointId);
23886
+ state.captureRefused ??= /* @__PURE__ */ new Set();
23887
+ state.captureRefused.add(event.checkpoint.checkpointId);
22977
23888
  refused.push(captured);
22978
23889
  await state.args.journal.appendEvent(state.args.rootId, {
22979
23890
  kind: "workspace-checkpoint-cleanup",
@@ -23193,8 +24104,8 @@ async function settleCaptureForks(state) {
23193
24104
  * environment needs one; a live environment is continued, never copied.
23194
24105
  */
23195
24106
  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);
24107
+ const unusable = unusableEnvironmentIds(owned);
24108
+ return owned.slice(0, inputIndex < 0 ? owned.length : inputIndex).filter((event) => event.kind === "workspace-checkpoint" && unusable.has(event.environmentId)).at(-1);
23198
24109
  }
23199
24110
  async function restoreCapable(provider) {
23200
24111
  if (provider === void 0) return false;
@@ -23215,7 +24126,8 @@ async function scopeRetainedOwnerRestorePoint(scope) {
23215
24126
  const latest = restoreBefore((await state.args.journal.loadTree(state.args.rootId) ?? []).filter((event) => event.id === state.args.nodeId), -1);
23216
24127
  return latest === void 0 ? void 0 : {
23217
24128
  checkpointId: latest.checkpoint.checkpointId,
23218
- takenAt: latest.at
24129
+ takenAt: latest.at,
24130
+ sourceEnvironmentId: latest.checkpoint.source.environmentId
23219
24131
  };
23220
24132
  }
23221
24133
  /** @internal Whether another owner release could still destroy what the last one left. */
@@ -23539,9 +24451,9 @@ function hasDurableWorkspaceCapture(output, snapshot, environmentId, executionId
23539
24451
  const linked = agentCandidateWorkspaceSnapshotEvidenceSchema.safeParse(receipt.snapshot);
23540
24452
  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
24453
  }
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] : []));
24454
+ /** Environments that cannot execute another turn, whether absent or terminal at the provider. */
24455
+ function unusableEnvironmentIds(owned) {
24456
+ return new Set(owned.flatMap((event) => event.kind === "environment-terminal" || event.kind === "environment-teardown" && event.destroyed ? [event.environmentId] : []));
23545
24457
  }
23546
24458
  /** The environment the owner's next invocation would continue in, when there is one: the latest
23547
24459
  * environment admission of this owner, which is either the current invocation's own (recovered
@@ -23570,8 +24482,9 @@ function continuedEnvironment(owned) {
23570
24482
  * commissioned settled `done` two minutes later, unread.
23571
24483
  *
23572
24484
  * 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.
24485
+ * An environment the provider no longer holds or reports terminal runs nothing. Runtime records
24486
+ * the provider's exact observation before the next prepare starts a new invocation. A terminal
24487
+ * record still requires cleanup at settlement; it is not a teardown receipt.
23575
24488
  */
23576
24489
  async function reconcileScopeRetainedOwnerEnvironment(scope) {
23577
24490
  const state = owners.get(scope);
@@ -23581,7 +24494,7 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
23581
24494
  const continued = continuedEnvironment(owned);
23582
24495
  if (continued === void 0) return { state: "none" };
23583
24496
  const environmentId = continued.admission.environmentId;
23584
- if (destroyedEnvironmentIds(owned).has(environmentId)) return {
24497
+ if (unusableEnvironmentIds(owned).has(environmentId)) return {
23585
24498
  state: "lost",
23586
24499
  environmentId
23587
24500
  };
@@ -23590,21 +24503,31 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
23590
24503
  environmentId
23591
24504
  };
23592
24505
  let environment;
24506
+ let terminalStatus;
23593
24507
  try {
23594
24508
  environment = await runAbortable(() => provider.get(environmentId), AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]), "retained owner environment check timed out");
24509
+ if (environment !== null) {
24510
+ const found = environment;
24511
+ if (found.id !== environmentId || found.provider !== provider.name) return {
24512
+ state: "unknown",
24513
+ environmentId
24514
+ };
24515
+ const status = await runAbortable(() => found.status(), AbortSignal.any([scope.signal, AbortSignal.timeout(3e4)]), "retained owner environment status timed out");
24516
+ if (status === "failed" || status === "expired") terminalStatus = status;
24517
+ }
23595
24518
  } catch {
23596
24519
  return {
23597
24520
  state: "unknown",
23598
24521
  environmentId
23599
24522
  };
23600
24523
  }
23601
- if (environment !== null) return {
24524
+ if (environment !== null && terminalStatus === void 0) return {
23602
24525
  state: "live",
23603
24526
  environmentId,
23604
24527
  inFlight: continued.inFlight
23605
24528
  };
23606
24529
  scope.signal.throwIfAborted();
23607
- await args.journal.appendEvent(args.rootId, {
24530
+ await args.journal.appendEvent(args.rootId, terminalStatus === void 0 ? {
23608
24531
  kind: "environment-teardown",
23609
24532
  id: args.nodeId,
23610
24533
  provider: provider.name,
@@ -23613,6 +24536,14 @@ async function reconcileScopeRetainedOwnerEnvironment(scope) {
23613
24536
  detail: "lost: the provider no longer holds this environment, so the next invocation starts in a new one",
23614
24537
  seq: state.nextSequence(),
23615
24538
  at: new Date(args.now()).toISOString()
24539
+ } : {
24540
+ kind: "environment-terminal",
24541
+ id: args.nodeId,
24542
+ provider: provider.name,
24543
+ environmentId,
24544
+ status: terminalStatus,
24545
+ seq: state.nextSequence(),
24546
+ at: new Date(args.now()).toISOString()
23616
24547
  });
23617
24548
  return {
23618
24549
  state: "lost",
@@ -23635,14 +24566,19 @@ async function prepareScopeRetainedOwnerTask(scope, task) {
23635
24566
  const accepted = [...attempt].reverse().find((event) => event.kind === "execution-result");
23636
24567
  if (accepted?.kind === "execution-result") state.acceptedRef = accepted;
23637
24568
  }
23638
- const destroyed = destroyedEnvironmentIds(owned);
24569
+ const unusable = unusableEnvironmentIds(owned);
23639
24570
  const inFlight = continuedEnvironment(owned);
23640
- if (inFlight?.inFlight && destroyed.has(inFlight.admission.environmentId)) {
24571
+ if (inFlight?.inFlight && unusable.has(inFlight.admission.environmentId)) {
23641
24572
  delete state.inputSequence;
23642
24573
  delete state.taskRef;
23643
24574
  state.admissions.length = 0;
23644
24575
  delete state.priorSession;
23645
24576
  }
24577
+ if (latestInput?.kind === "execution-input" && state.inputSequence === latestInput.seq && owned.slice(owned.indexOf(latestInput)).some((event) => event.kind === "execution-abandoned")) {
24578
+ delete state.inputSequence;
24579
+ delete state.taskRef;
24580
+ state.admissions.length = 0;
24581
+ }
23646
24582
  if (state.prepared && state.acceptedRef && state.acceptedConsumed) {
23647
24583
  const currentEnvironment = [...state.admissions].reverse().find((admission) => admission.phase === "environment");
23648
24584
  if (currentEnvironment?.phase === "environment") state.priorSession = currentEnvironment;
@@ -23653,7 +24589,15 @@ async function prepareScopeRetainedOwnerTask(scope, task) {
23653
24589
  state.admissions.length = 0;
23654
24590
  delete state.acceptedConsumed;
23655
24591
  }
23656
- if (state.priorSession !== void 0 && destroyed.has(state.priorSession.environmentId)) delete state.priorSession;
24592
+ if (state.priorSession !== void 0 && unusable.has(state.priorSession.environmentId)) delete state.priorSession;
24593
+ const segmentStarts = owned.filter((event) => event.kind === "seat-segment" && event.phase === "started");
24594
+ const latestSeat = segmentStarts.at(-1);
24595
+ const previousSeat = segmentStarts.at(-2);
24596
+ if (latestSeat && previousSeat && latestSeat.provider !== previousSeat.provider && owned.indexOf(latestSeat) > owned.indexOf(latestInput)) state.forceNewSession = true;
24597
+ if (state.forceNewSession) {
24598
+ delete state.priorSession;
24599
+ delete state.forceNewSession;
24600
+ }
23657
24601
  state.prepared = true;
23658
24602
  const capable = await restoreCapable(state.provider);
23659
24603
  const restoreFor = (inputIndex) => {
@@ -23724,6 +24668,227 @@ function consumeScopeRetainedOwnerResult(scope) {
23724
24668
  state.acceptedConsumed = true;
23725
24669
  }
23726
24670
  //#endregion
24671
+ //#region src/runtime/supervise/seat-chain.ts
24672
+ var SeatChainExhaustedError = class extends Error {
24673
+ resumeAt;
24674
+ constructor(resumeAt) {
24675
+ super(`authored subscription seat chain exhausted; resume at ${resumeAt}`);
24676
+ this.name = "SeatChainExhaustedError";
24677
+ this.resumeAt = resumeAt;
24678
+ }
24679
+ };
24680
+ /** One logical node's durable chain. The spawn journal is the sole transition authority. */
24681
+ var SeatChain = class {
24682
+ profile;
24683
+ nodeId;
24684
+ rootId;
24685
+ journal;
24686
+ select;
24687
+ now;
24688
+ onSegment;
24689
+ beforeStart;
24690
+ observedThrough = -1;
24691
+ constructor(profile, nodeId, rootId, journal, select, now = Date.now, onSegment, beforeStart) {
24692
+ this.profile = profile;
24693
+ this.nodeId = nodeId;
24694
+ this.rootId = rootId;
24695
+ this.journal = journal;
24696
+ this.select = select;
24697
+ this.now = now;
24698
+ this.onSegment = onSegment;
24699
+ this.beforeStart = beforeStart;
24700
+ }
24701
+ async next(afterUsageLimit = false, afterRecheck = false) {
24702
+ const stages = authoredSeatStages(this.profile);
24703
+ if (!stages) throw new ValidationError$1("SeatChain requires authored AgentProfile.seats");
24704
+ const allEvents = await this.journal.loadTree(this.rootId) ?? [];
24705
+ const events = allEvents.filter((event) => event.kind === "seat-segment" && event.id === this.nodeId);
24706
+ const destroyed = new Set(allEvents.filter((event) => event.kind === "environment-teardown" && event.id === this.nodeId && event.destroyed).map((event) => event.environmentId));
24707
+ let admittedEnvironmentId;
24708
+ for (const event of allEvents) if (event.kind === "execution-admitted" && event.id === this.nodeId && event.admission.phase === "environment") admittedEnvironmentId = event.admission.environmentId;
24709
+ const retainedEnvironmentId = admittedEnvironmentId !== void 0 && !destroyed.has(admittedEnvironmentId) ? admittedEnvironmentId : void 0;
24710
+ await this.reconcile(events);
24711
+ const starts = events.filter((event) => event.phase === "started");
24712
+ const last = starts.at(-1);
24713
+ const closed = last && events.some((event) => event.phase === "ended" && event.segmentIndex === last.segmentIndex);
24714
+ if (last && !closed && afterUsageLimit) await this.end(last, "usage-limit");
24715
+ const resume = last && !closed && !afterUsageLimit;
24716
+ const segmentIndex = resume ? last.segmentIndex : (last?.segmentIndex ?? -1) + 1;
24717
+ const firstStageIndex = afterRecheck ? 0 : last?.stageIndex ?? 0;
24718
+ let earliestReset;
24719
+ for (let stageIndex = firstStageIndex; stageIndex < stages.length; stageIndex += 1) {
24720
+ const stage = stages[stageIndex];
24721
+ const excludedSeatIds = (afterRecheck ? [] : starts).filter((event) => event.stageIndex === stageIndex && (!resume || event.seat !== last.seat)).map((event) => event.seat);
24722
+ const prior = last === void 0 ? void 0 : {
24723
+ seat: last.seat,
24724
+ harness: last.harness,
24725
+ provider: last.provider,
24726
+ model: last.model
24727
+ };
24728
+ const preceding = resume ? starts.at(-2) : last;
24729
+ const requiresNativeTurnGrant = Boolean(preceding && preceding.provider === stage.provider && preceding.harness === stage.harness && (!resume || preceding.seat !== last.seat));
24730
+ const selection = checkedSeatSelection(stage, await this.select({
24731
+ profile: this.profile,
24732
+ nodeId: this.nodeId,
24733
+ stage,
24734
+ stageIndex,
24735
+ segmentIndex,
24736
+ excludedSeatIds,
24737
+ requiresNativeTurnGrant,
24738
+ ...retainedEnvironmentId === void 0 ? {} : { retainedEnvironmentId },
24739
+ ...prior === void 0 ? {} : { previous: prior },
24740
+ ...resume ? { resumeSeatId: last.seat } : {}
24741
+ }));
24742
+ if ("resumeAt" in selection) {
24743
+ const reset = Date.parse(selection.resumeAt);
24744
+ earliestReset = earliestReset === void 0 ? reset : Math.min(earliestReset, reset);
24745
+ if (resume) break;
24746
+ continue;
24747
+ }
24748
+ if (resume && selection.seat !== last.seat) throw new ValidationError$1("selectSeat: resume changed the committed seat");
24749
+ if (excludedSeatIds.includes(selection.seat)) throw new ValidationError$1("selectSeat: selected an exhausted seat");
24750
+ 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");
24751
+ const active = {
24752
+ seat: selection.seat,
24753
+ stageIndex,
24754
+ segmentIndex,
24755
+ stage,
24756
+ backend: selection.backend,
24757
+ ...selection.nativeTurnGrant === true ? { nativeTurnGrant: true } : {},
24758
+ ...preceding === void 0 ? {} : { previous: {
24759
+ seat: preceding.seat,
24760
+ harness: preceding.harness,
24761
+ provider: preceding.provider,
24762
+ model: preceding.model
24763
+ } }
24764
+ };
24765
+ if (!resume) {
24766
+ await this.beforeStart?.(active, prior);
24767
+ const at = new Date(this.now()).toISOString();
24768
+ await this.journal.appendEvent(this.rootId, {
24769
+ kind: "seat-segment",
24770
+ id: this.nodeId,
24771
+ segmentIndex,
24772
+ stageIndex,
24773
+ phase: "started",
24774
+ seat: selection.seat,
24775
+ harness: stage.harness,
24776
+ provider: stage.provider,
24777
+ model: stage.model,
24778
+ seq: segmentIndex,
24779
+ at
24780
+ });
24781
+ await this.onSegment?.({
24782
+ seat: selection.seat,
24783
+ harness: stage.harness,
24784
+ provider: stage.provider,
24785
+ model: stage.model,
24786
+ startedAt: at
24787
+ }, "started");
24788
+ this.observedThrough = events.length;
24789
+ return active;
24790
+ }
24791
+ return active;
24792
+ }
24793
+ const recheckAt = Math.max(earliestReset ?? 0, this.now() + 12e4);
24794
+ throw new SeatChainExhaustedError(new Date(recheckAt).toISOString());
24795
+ }
24796
+ async close(reason) {
24797
+ const events = (await this.journal.loadTree(this.rootId) ?? []).filter((event) => event.kind === "seat-segment" && event.id === this.nodeId);
24798
+ await this.reconcile(events);
24799
+ const last = events.filter((event) => event.phase === "started").at(-1);
24800
+ if (last && !events.some((event) => event.phase === "ended" && event.segmentIndex === last.segmentIndex)) await this.end(last, reason);
24801
+ }
24802
+ async end(start, reason) {
24803
+ const at = new Date(this.now()).toISOString();
24804
+ await this.journal.appendEvent(this.rootId, {
24805
+ ...start,
24806
+ phase: "ended",
24807
+ reason,
24808
+ at
24809
+ });
24810
+ await this.onSegment?.({
24811
+ seat: start.seat,
24812
+ harness: start.harness,
24813
+ provider: start.provider,
24814
+ model: start.model,
24815
+ startedAt: start.at,
24816
+ endedAt: at,
24817
+ reason
24818
+ }, "ended");
24819
+ this.observedThrough += 1;
24820
+ }
24821
+ /** A crash may land between the authoritative journal append and observer delivery. On
24822
+ * reconstruction, deliver every unobserved boundary again; the observer projection folds
24823
+ * repeated boundaries by seat and start time, so a callback never decides execution identity. */
24824
+ async reconcile(events) {
24825
+ const starts = /* @__PURE__ */ new Map();
24826
+ for (let index = 0; index < events.length; index += 1) {
24827
+ const event = events[index];
24828
+ if (event.phase === "started") starts.set(event.segmentIndex, event);
24829
+ if (index <= this.observedThrough) continue;
24830
+ const start = event.phase === "started" ? event : starts.get(event.segmentIndex);
24831
+ if (!start) throw new ValidationError$1("seat segment ended without a committed start");
24832
+ await this.onSegment?.({
24833
+ seat: start.seat,
24834
+ harness: start.harness,
24835
+ provider: start.provider,
24836
+ model: start.model,
24837
+ startedAt: start.at,
24838
+ ...event.phase === "ended" ? {
24839
+ endedAt: event.at,
24840
+ reason: event.reason
24841
+ } : {}
24842
+ }, event.phase);
24843
+ this.observedThrough = index;
24844
+ }
24845
+ }
24846
+ };
24847
+ /** Preserve the authored profile for identity; only the provider-facing copy changes stages. */
24848
+ function seatExecutionProfile(profile, stage) {
24849
+ const { seats: _seats, ...withoutSeats } = profile;
24850
+ return {
24851
+ ...withoutSeats,
24852
+ harness: stage.harness,
24853
+ ...stage.tools === void 0 ? {} : { tools: stage.tools },
24854
+ ...stage.permissions === void 0 ? {} : { permissions: stage.permissions },
24855
+ model: {
24856
+ ...profile.model,
24857
+ default: stage.model,
24858
+ provider: stage.provider
24859
+ }
24860
+ };
24861
+ }
24862
+ function authoredSeatStages(profile) {
24863
+ const seats = profile.seats;
24864
+ if (seats === void 0) return void 0;
24865
+ if (!Array.isArray(seats) || seats.length === 0) throw new ValidationError$1("AgentProfile.seats must be a nonempty ordered chain");
24866
+ return seats;
24867
+ }
24868
+ const USAGE_LIMIT_CODES = /* @__PURE__ */ new Set([
24869
+ "subscription_usage_limit",
24870
+ "usage_limit_reached",
24871
+ "usage_limit_exceeded",
24872
+ "weekly_limit_reached",
24873
+ "session_limit_reached"
24874
+ ]);
24875
+ /** Normalize a native harness refusal into a typed limit. A plain HTTP 429 is insufficient. */
24876
+ function subscriptionUsageLimitSignal(failure) {
24877
+ if (failure.errorCode && USAGE_LIMIT_CODES.has(failure.errorCode.toLowerCase())) return "subscription-usage-limit";
24878
+ if (/\bYou've hit your (?:usage|weekly|session) limit\b/iu.test(failure.error)) return "subscription-usage-limit";
24879
+ }
24880
+ /** An ineligible or misconfigured account must never turn an authored stage into another model. */
24881
+ function checkedSeatSelection(stage, selected) {
24882
+ if ("resumeAt" in selected) {
24883
+ if (!Number.isFinite(Date.parse(selected.resumeAt))) throw new ValidationError$1("selectSeat: resumeAt must be an ISO timestamp");
24884
+ return selected;
24885
+ }
24886
+ if (!selected.seat.trim()) throw new ValidationError$1("selectSeat: seat must be nonempty");
24887
+ if (stage.selector.kind === "seat" && stage.selector.id !== selected.seat) throw new ValidationError$1("selectSeat: selection does not match the authored seat");
24888
+ if (selected.backend.backend !== "provider") throw new ValidationError$1("selectSeat: selection must use a provider backend");
24889
+ return selected;
24890
+ }
24891
+ //#endregion
23727
24892
  //#region src/runtime/supervise/scope.ts
23728
24893
  /**
23729
24894
  *
@@ -25139,7 +26304,23 @@ async function publishOwnerMaterialization(state, runtime, declaration, bindingI
25139
26304
  await rejectOwnerMaterialization(state);
25140
26305
  throw new ValidationError$1("scope owner returned invalid materialization evidence", { cause: error });
25141
26306
  }
25142
- if (state.prior !== void 0) {
26307
+ const committed = state.receipt ?? state.prior;
26308
+ if (committed?.status === "known" && canonicalCandidateDigest(committed) !== canonicalCandidateDigest(receipt)) {
26309
+ const events = await state.journal.loadTree(state.retainedRoot) ?? [];
26310
+ const started = [...events].reverse().find((event) => event.id === state.nodeId && event.kind === "seat-segment" && event.phase === "started");
26311
+ const latestMaterialization = [...events].reverse().find((event) => event.id === state.nodeId && (event.kind === "materialized" || event.kind === "seat-materialized"));
26312
+ const lastSegmentIndex = latestMaterialization?.kind === "seat-materialized" ? latestMaterialization.segmentIndex : 0;
26313
+ const authored = agentProfileSchema.safeParse(state.authoredProfile);
26314
+ const authoredProfile = authored.success ? authored.data : void 0;
26315
+ const stage = authoredProfile && started?.kind === "seat-segment" ? authoredSeatStages(authoredProfile)?.[started.stageIndex] : void 0;
26316
+ 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) {
26317
+ await appendOwnerSeatMaterialization(state, started.segmentIndex, receipt, binding);
26318
+ state.onReceipt?.(receipt, binding);
26319
+ state.publishedThisProcess = true;
26320
+ return;
26321
+ }
26322
+ }
26323
+ if (state.prior !== void 0 && state.receipt === void 0) {
25143
26324
  if (canonicalCandidateDigest(state.prior) !== canonicalCandidateDigest(receipt)) {
25144
26325
  await rejectOwnerMaterialization(state);
25145
26326
  throw new ValidationError$1("scope owner materialization changed across resume; backend, model, execution identity, and plan must match");
@@ -25221,12 +26402,12 @@ async function restoreScopeOwnerAcceptedExecution(scope) {
25221
26402
  const resultIndex = latestResult === void 0 ? -1 : owned.indexOf(latestResult);
25222
26403
  const result = owned[resultIndex];
25223
26404
  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");
26405
+ const receiptEvent = owned.slice(0, resultIndex).reverse().find((event) => event.kind === "materialized" || event.kind === "seat-materialized");
25225
26406
  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");
26407
+ 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
26408
  const { receipt } = receiptEvent;
25228
26409
  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");
26410
+ 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
26411
  assertValidSpend(result.spent, "accepted scope owner result");
25231
26412
  const output = await state.blobs.get(result.outRef);
25232
26413
  if (output === void 0 || contentAddress(output) !== result.outRef) throw new ValidationError$1("accepted scope owner output is missing or corrupt");
@@ -25318,6 +26499,18 @@ async function appendOwnerMaterialization(state, receipt, binding) {
25318
26499
  state.receipt = receipt;
25319
26500
  await appendOwnerBinding(state, binding);
25320
26501
  }
26502
+ async function appendOwnerSeatMaterialization(state, segmentIndex, receipt, binding) {
26503
+ await appendOwnerEvidence(state, {
26504
+ kind: "seat-materialized",
26505
+ id: state.nodeId,
26506
+ segmentIndex,
26507
+ receipt,
26508
+ seq: segmentIndex,
26509
+ at: new Date(state.now()).toISOString()
26510
+ });
26511
+ state.receipt = receipt;
26512
+ await appendOwnerBinding(state, binding);
26513
+ }
25321
26514
  async function appendOwnerBinding(state, binding) {
25322
26515
  await appendOwnerEvidence(state, {
25323
26516
  kind: "execution-bound",
@@ -25332,10 +26525,10 @@ async function appendOwnerEvidence(state, event) {
25332
26525
  for (const root of /* @__PURE__ */ new Set([state.root, state.retainedRoot])) await appendExactMaterializationEvent(state.journal, root, event);
25333
26526
  }
25334
26527
  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;
26528
+ 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));
26529
+ if (prior?.kind === "materialized" || prior?.kind === "seat-materialized" || prior?.kind === "execution-bound") {
26530
+ const previous = prior.kind === "execution-bound" ? prior.binding : prior.receipt;
26531
+ const next = event.kind === "execution-bound" ? event.binding : event.receipt;
25339
26532
  if (canonicalCandidateDigest(previous) !== canonicalCandidateDigest(next)) throw new ValidationError$1("scope execution evidence conflicts with its committed record");
25340
26533
  return;
25341
26534
  }
@@ -26213,7 +27406,7 @@ function isInfraError(err) {
26213
27406
  * journal so the executor can run its `act` inside a nested scope. `act` fails loud if
26214
27407
  * called directly — a driver child runs THROUGH its nested-scope executor, never as a root.
26215
27408
  */
26216
- function driverChild(profile, driver, journal, execution, acceptedSubmission, recoverExecutor, unassessedOutput) {
27409
+ function driverChild(profile, driver, journal, execution, acceptedSubmission, recoverExecutor, unassessedOutput, leafDeliverable) {
26217
27410
  const name = profile.name ?? driver.name;
26218
27411
  const traceSource = driver.traceSource;
26219
27412
  const progress = driver.progress;
@@ -26228,6 +27421,7 @@ function driverChild(profile, driver, journal, execution, acceptedSubmission, re
26228
27421
  journal,
26229
27422
  ...acceptedSubmission ? { acceptedSubmission } : {},
26230
27423
  ...unassessedOutput ? { unassessedOutput } : {},
27424
+ ...leafDeliverable ? { leafDeliverable } : {},
26231
27425
  ...recoverExecutor ? { recoverExecutor } : {},
26232
27426
  ...traceSource ? { traceSource } : {},
26233
27427
  ...progress ? { progress } : {},
@@ -26435,7 +27629,7 @@ function withDriverExecutor(base) {
26435
27629
  const spec = executableAgentSpecSnapshot(rawSpec, "driver executor registry");
26436
27630
  if (spec.driverRuntime === "driver" && !spec.executor) return {
26437
27631
  succeeded: true,
26438
- value: ((_ignored, context) => driverExecutorFactory(spec, context))
27632
+ value: ((_ignored, context) => isDriverSpec(spec) && spec.leafDeliverable ? attestNestedDriverTreeOwner(gateOnDeliverable(driverExecutorFactory(spec, context), spec.leafDeliverable)) : driverExecutorFactory(spec, context))
26439
27633
  };
26440
27634
  const resolved = base.resolve(spec);
26441
27635
  if (!resolved.succeeded) return resolved;
@@ -26454,623 +27648,125 @@ async function closeNestedScope(scope, controller, reason) {
26454
27648
  }
26455
27649
  /** The nested tree's full event list — the one evidence the spend, verdict, AND driver-inference
26456
27650
  * 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
- });
26662
- }
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] ?? "");
27651
+ async function loadTreeEvents(journal, nestedRoot) {
27652
+ const events = await journal.loadTree(nestedRoot);
27653
+ if (events === void 0) throw new ValidationError$1(`driverExecutor: nested tree '${nestedRoot}' missing from the journal after run (corrupted log)`);
27654
+ return events;
26667
27655
  }
26668
- /** Items that pass in `verdict`. */
26669
- function passedItems(verdict) {
26670
- return Object.entries(verdict.items ?? {}).filter(([, value]) => value >= 1).map(([name]) => name);
27656
+ function isSettled(ev) {
27657
+ return ev.kind === "settled" || ev.kind === "cancelled" && ev.spent !== void 0;
26671
27658
  }
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;
27659
+ /** Sum the conserved spend over the nested tree's settled events — the honest per-channel
27660
+ * roll-up of the whole sub-tree's child WORK. */
27661
+ function sumSpend(settled) {
27662
+ return settled.reduce((total, ev) => addSpend(total, ev.spent), zeroSpend());
26689
27663
  }
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`);
27664
+ /** Sum the nested tree's `metered` events — the sub-tree's whole driver INFERENCE (this driver's
27665
+ * own turns + any sub-driver inference already re-homed into this tree). Re-homed up to the parent
27666
+ * as one `metered` event; never reconciled (already pool-debited live via `observe`). */
27667
+ function sumMetered(events) {
27668
+ return events.reduce((total, ev) => ev.kind === "metered" ? addSpend(total, ev.spend) : total, zeroSpend());
26737
27669
  }
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;
27670
+ /** An all-zero spend that carries an UNKNOWN marker counts as non-zero: a sub-driver whose turns
27671
+ * went unmeasured did real work, and dropping its `metered` event here would re-hide upstream the
27672
+ * very turn the driver refused to skip. */
27673
+ function isNonZeroSpend(s) {
27674
+ 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;
26746
27675
  }
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;
27676
+ /** A spend, or `undefined` when it is all-zero — so `metered()` returns undefined for a driver
27677
+ * whose sub-tree did no inference (and the parent journals no empty `metered` event). */
27678
+ function nonZeroOrUndef(s) {
27679
+ return isNonZeroSpend(s) ? s : void 0;
26781
27680
  }
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));
27681
+ /** Sum the nested tree's metered events, tolerating a missing tree (a crash before `beginTree`
27682
+ * landed) — never throw here, or it would mask the original `act` error on the crash path. */
27683
+ async function safeRollup(journal, nestedRoot) {
27684
+ try {
27685
+ const events = await loadTreeEvents(journal, nestedRoot);
27686
+ const childWork = sumSpend(events.filter(isSettled));
27687
+ const metered = nonZeroOrUndef(sumMetered(events));
27688
+ return {
27689
+ metered,
27690
+ accounting: {
27691
+ reported: childWork,
27692
+ reservation: addSpend(childWork, metered ?? zeroSpend())
27693
+ }
27694
+ };
27695
+ } catch {
27696
+ return;
26795
27697
  }
26796
- return out;
26797
27698
  }
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"));
27699
+ /** Derive the driver child's delivery verdict from an accepted direct submission, or from its
27700
+ * DIRECT children's settlements and the manager's actual finalized output: `valid` iff the
27701
+ * manager's own assignment check accepted a submission, or a direct child delivered AND the
27702
+ * finalizer returned a defined output;
27703
+ * `score` = the best delivered score. Returns `undefined` when no child settled at all (the
27704
+ * driver itself produced nothing to bubble a verdict from). Fail-closed: a child whose verdict
27705
+ * carried no `valid` counts as not-delivered. */
27706
+ function deriveDeliveryVerdict(settled, finalizedOutput, acceptedSubmission) {
27707
+ if (acceptedSubmission) return {
27708
+ valid: true,
27709
+ score: 1
26823
27710
  };
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)})`}`));
26855
- }
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
- }
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;
26869
- return {
26870
- pass: verdict.pass,
26871
- ...verdict.composite === void 0 ? {} : { composite: verdict.composite },
26872
- ...total === 0 ? {} : {
26873
- failed: failedItems(verdict).length,
26874
- total
27711
+ let sawChild = false;
27712
+ let anyValid = false;
27713
+ let bestValidScore;
27714
+ let bestDoneScore;
27715
+ for (const ev of settled) {
27716
+ sawChild = true;
27717
+ if (ev.status !== "done") continue;
27718
+ const score = ev.verdict?.score;
27719
+ if (score !== void 0 && (bestDoneScore === void 0 || score > bestDoneScore)) bestDoneScore = score;
27720
+ if (ev.verdict?.valid === true) {
27721
+ anyValid = true;
27722
+ if (score !== void 0 && (bestValidScore === void 0 || score > bestValidScore)) bestValidScore = score;
26875
27723
  }
27724
+ }
27725
+ if (!sawChild) return void 0;
27726
+ const accepted = anyValid && finalizedOutput !== void 0;
27727
+ return {
27728
+ valid: accepted,
27729
+ score: accepted ? bestValidScore ?? 1 : bestDoneScore ?? 0
26876
27730
  };
26877
27731
  }
26878
- function noteDigest(note) {
26879
- return `sha256:${createHash("sha256").update(note).digest("hex")}`;
27732
+ function readNestedScopeSeam(ctx) {
27733
+ const seam = ctx.seams[nestedScopeSeamKey];
27734
+ 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)`);
27735
+ return seam;
26880
27736
  }
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");
27737
+ function isAgent(value) {
27738
+ return typeof value === "object" && value !== null && typeof value.act === "function" && typeof value.name === "string";
26895
27739
  }
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;
27740
+ /** Parent journals may already contain an interrupted driver's inference prefix. */
27741
+ function unreportedSpend(total, prior) {
27742
+ const tokens = { ...total.tokens };
27743
+ for (const key of [
27744
+ "input",
27745
+ "output",
27746
+ "freshInput",
27747
+ "cacheRead",
27748
+ "cacheWrite"
27749
+ ]) {
27750
+ const value = total.tokens[key];
27751
+ if (value !== void 0) tokens[key] = Math.max(0, value - (prior.tokens[key] ?? 0));
26902
27752
  }
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
27753
  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
- }
27754
+ ...total,
27755
+ ...addResourceSpend(total.resources === void 0 ? void 0 : Object.fromEntries(Object.entries(total.resources).map(([name, value]) => {
27756
+ const previous = prior.resources?.[name];
27757
+ if (previous && previous.unit !== value.unit) throw new ValidationError$1(`resource ${name}: unit mismatch`);
27758
+ return [name, {
27759
+ ...value,
27760
+ amount: Math.max(0, value.amount - (previous?.amount ?? 0)),
27761
+ known: value.known && (previous?.known ?? true)
27762
+ }];
27763
+ }))),
27764
+ iterations: Math.max(0, total.iterations - prior.iterations),
27765
+ tokens,
27766
+ usd: Math.max(0, total.usd - prior.usd),
27767
+ ms: Math.max(0, total.ms - prior.ms),
27768
+ ...total.usdEstimated === void 0 ? {} : { usdEstimated: Math.max(0, total.usdEstimated - (prior.usdEstimated ?? 0)) },
27769
+ ...total.boxMinutes === void 0 ? {} : { boxMinutes: Math.max(0, total.boxMinutes - (prior.boxMinutes ?? 0)) }
27074
27770
  };
27075
27771
  }
27076
27772
  //#endregion
@@ -27167,6 +27863,19 @@ const DEFAULT_MAX_ATTEMPTS = Number.POSITIVE_INFINITY;
27167
27863
  const DEFAULT_INITIAL_BACKOFF_MS = 2e3;
27168
27864
  const DEFAULT_MAX_BACKOFF_MS = 3e4;
27169
27865
  const DEFAULT_TRANSIENT_OUTAGE_MS = 9e5;
27866
+ /** Consecutive identical reconciliation failures of one pending invocation that resolve it. */
27867
+ const SAME_PENDING_LIMIT = 2;
27868
+ /**
27869
+ * The pending invocation a failure left, when abandoning it is the resolution: the provider
27870
+ * answered and could not resolve the execution (`unobservable`), or a nested manager's recovery
27871
+ * could not be rebuilt (`nested-recovery`). A lost transport waits for the provider instead, in
27872
+ * the outage window: abandoning during a provider outage would start a second execution beside
27873
+ * one that may still run. A request refused before it ran has nothing to abandon: a capacity
27874
+ * refusal pauses and any other refusal is terminal. A contract violation stays terminal (#1204).
27875
+ */
27876
+ function abandonablePending(error) {
27877
+ return error instanceof RetainedExecutionPendingError && (error.pendingCause === "unobservable" || error.pendingCause === "nested-recovery") ? error : void 0;
27878
+ }
27170
27879
  /**
27171
27880
  * Bridge error classes the bridge itself never retries: a request that fails identically on
27172
27881
  * every attempt, mapped below 5xx on its HTTP path (`parse_error` 400, the other two 501). On the
@@ -27229,11 +27938,18 @@ function upstreamUnavailableSignal(error) {
27229
27938
  if (!(error instanceof Error)) return void 0;
27230
27939
  if (isProviderSchemaRejection(error)) return void 0;
27231
27940
  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
- });
27941
+ if (error instanceof HarnessTurnFailedError) {
27942
+ const usageLimit = subscriptionUsageLimitSignal({
27943
+ error: error.message,
27944
+ ...error.errorCode === void 0 ? {} : { errorCode: error.errorCode }
27945
+ });
27946
+ if (usageLimit !== void 0) return usageLimit;
27947
+ return unavailableSignalOfFailure({
27948
+ error: error.message,
27949
+ ...error.errorCode === void 0 ? {} : { errorCode: error.errorCode },
27950
+ ...error.statusCode === void 0 ? {} : { statusCode: error.statusCode }
27951
+ });
27952
+ }
27237
27953
  if (error instanceof BackendTransportError) {
27238
27954
  const code = error.upstreamCode?.toLowerCase();
27239
27955
  if (code !== void 0 && UNAVAILABLE_CODES.has(code)) return code;
@@ -27241,10 +27957,29 @@ function upstreamUnavailableSignal(error) {
27241
27957
  return unavailableSignalInText(errorProperty(error, "message") ?? "");
27242
27958
  }
27243
27959
  if (error instanceof AgentEvalError$1) return void 0;
27960
+ const code = capacityCode(error);
27961
+ if (code !== void 0) return code;
27244
27962
  const status = errorHttpStatus(error);
27245
27963
  if (status !== void 0) return UNAVAILABLE_STATUSES.has(status) ? `http-${status}` : void 0;
27246
27964
  return unavailableSignalInText(errorProperty(error, "message") ?? "");
27247
27965
  }
27966
+ /**
27967
+ * The upstream capacity code an error carries as its own `code` field, or `undefined`. A provider
27968
+ * SDK names a capacity refusal with the router's code when no HTTP response exists to carry a
27969
+ * status: agent-provider-tangle's `TangleCredentialCapacityError` (`provider_quota_exhausted`,
27970
+ * `upstream_unavailable`) when the subscription account owner has no account with room.
27971
+ */
27972
+ function capacityCode(error) {
27973
+ let code;
27974
+ try {
27975
+ code = Reflect.get(error, "code");
27976
+ } catch {
27977
+ return;
27978
+ }
27979
+ if (typeof code !== "string") return void 0;
27980
+ const normalized = code.toLowerCase();
27981
+ return UNAVAILABLE_CODES.has(normalized) ? normalized : void 0;
27982
+ }
27248
27983
  /** True when the upstream refused for capacity and the same request will succeed later. */
27249
27984
  function isUpstreamUnavailable(error) {
27250
27985
  return upstreamUnavailableSignal(error) !== void 0;
@@ -27305,7 +28040,7 @@ function retainedAdmissionCause(error) {
27305
28040
  if (errorProperty(value, "name") === "RetainedRunProviderContractError") return void 0;
27306
28041
  const status = errorHttpStatus(value);
27307
28042
  if (status !== void 0 && status >= 400) return error.pendingCause === "request-rejected" || UNAVAILABLE_STATUSES.has(status) ? value : void 0;
27308
- if (error.pendingCause === "request-rejected" && (value instanceof AgentEvalError$1 || isProviderSchemaRejection(value))) return value;
28043
+ if (error.pendingCause === "request-rejected" && (value instanceof AgentEvalError$1 || isProviderSchemaRejection(value) || capacityCode(value) !== void 0)) return value;
27309
28044
  const members = Reflect.get(value, "errors");
27310
28045
  if (Array.isArray(members)) queue.push(...members.slice(0, 12 - steps));
27311
28046
  queue.push(value.cause);
@@ -27435,6 +28170,8 @@ async function runDriverWithRetry(run) {
27435
28170
  let chargedFailures = 0;
27436
28171
  let outageSince;
27437
28172
  let consecutivePauses = 0;
28173
+ let samePending;
28174
+ let abandonments = 0;
27438
28175
  let pauses = 0;
27439
28176
  let continuations = 0;
27440
28177
  let wakes = 0;
@@ -27493,6 +28230,12 @@ async function runDriverWithRetry(run) {
27493
28230
  const classification = classifyDriverFailure(error, run.signal);
27494
28231
  const after = run.progress();
27495
28232
  const progressed = madeProgress(before, after);
28233
+ if (progressed) abandonments = 0;
28234
+ const pending = abandonablePending(error);
28235
+ samePending = pending === void 0 || classification !== "transient" ? void 0 : {
28236
+ cause: pending.pendingCause,
28237
+ count: samePending?.cause === pending.pendingCause ? samePending.count + 1 : 1
28238
+ };
27496
28239
  if (classification === "unavailable") {
27497
28240
  if (progressed) barrenReentries = 0;
27498
28241
  const stop = (() => {
@@ -27531,6 +28274,7 @@ async function runDriverWithRetry(run) {
27531
28274
  pause: pauses
27532
28275
  };
27533
28276
  await sleep(pause, run.signal);
28277
+ if (outageSince !== void 0) outageSince += now() - startedAt;
27534
28278
  if (run.signal.aborted) throw new DriverAttemptsExhaustedError(error, attempts, "aborted");
27535
28279
  const afterPause = budgetStop(run.budget(), now());
27536
28280
  if (afterPause) throw new DriverAttemptsExhaustedError(error, attempts, afterPause);
@@ -27555,19 +28299,30 @@ async function runDriverWithRetry(run) {
27555
28299
  if (progressed) return void 0;
27556
28300
  return consecutiveBarren + 1 >= maxConsecutive ? "no-progress" : void 0;
27557
28301
  })();
28302
+ let abandoned = false;
28303
+ if (pending !== void 0 && samePending !== void 0 && run.resolvePending !== void 0 && retryEnabled && !run.signal.aborted && abandonments < maxConsecutive && (stop === "no-progress" || stop === void 0 && samePending.count >= SAME_PENDING_LIMIT)) {
28304
+ abandoned = await run.resolvePending(pending, samePending.count);
28305
+ if (abandoned) {
28306
+ abandonments += 1;
28307
+ samePending = void 0;
28308
+ consecutiveBarren = 0;
28309
+ outageSince = void 0;
28310
+ }
28311
+ }
28312
+ const retryStop = abandoned ? void 0 : stop;
27558
28313
  if (progressed) barrenReentries = 0;
27559
- if (stop !== void 0) {
28314
+ if (retryStop !== void 0) {
27560
28315
  await emit({
27561
28316
  attempt,
27562
28317
  durationMs,
27563
28318
  error: errMessage(error),
27564
28319
  classification,
27565
28320
  madeProgress: progressed,
27566
- stop
28321
+ stop: retryStop
27567
28322
  });
27568
- throw new DriverAttemptsExhaustedError(error, attempts, stop);
28323
+ throw new DriverAttemptsExhaustedError(error, attempts, retryStop);
27569
28324
  }
27570
- consecutiveBarren = progressed ? 0 : consecutiveBarren + 1;
28325
+ if (!abandoned) consecutiveBarren = progressed ? 0 : consecutiveBarren + 1;
27571
28326
  const backoff = jitteredMs(cappedDoublingMs(consecutiveBarren, initialBackoff, maxBackoff), random);
27572
28327
  await emit({
27573
28328
  attempt,
@@ -27575,6 +28330,7 @@ async function runDriverWithRetry(run) {
27575
28330
  error: errMessage(error),
27576
28331
  classification,
27577
28332
  madeProgress: progressed,
28333
+ ...abandoned ? { abandoned: true } : {},
27578
28334
  retryInMs: backoff
27579
28335
  });
27580
28336
  reentry = {
@@ -27591,6 +28347,8 @@ async function runDriverWithRetry(run) {
27591
28347
  consecutiveBarren = 0;
27592
28348
  consecutivePauses = 0;
27593
28349
  outageSince = void 0;
28350
+ samePending = void 0;
28351
+ abandonments = 0;
27594
28352
  const durationMs = now() - startedAt;
27595
28353
  const after = run.progress();
27596
28354
  const progressed = madeProgress(before, after);
@@ -28778,6 +29536,6 @@ function isNonEmptySpend(s) {
28778
29536
  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
29537
  }
28780
29538
  //#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 };
29539
+ export { environmentReader as $, projectSandboxOutcome as $i, parseWorkerToolTraceArtifact as $n, sanitizeAgentRuntimeEvent as $r, PEER_MAIL_WIRE_KEY as $t, scopeOwnerExecutorNodeContext as A, worktreeCliProfileMaterialization as Ai, resolveAgentEnvironmentProvider as An, resolveHarnessTranscriptCapture as Ar, captureReusableExecutorConfig as At, consumeScopeRetainedOwnerResult as B, recordRuntimeOwnedDriveHarnessProviderEvidence as Bi, InMemoryResultBlobStore as Bn, buildLoopOtelSpans as Br, createInPlaceCliExecutor as Bt, deriveNodeExecutionIdentity as C, promptOnlyProfileMaterialization as Ci, readPromptOptions as Cn, abortError as Cr, createContinuationKeeper as Ct, recordScopeOwnerMaterialization as D, sandboxActProfileMaterialization as Di, createAgentEnvironmentProviderRegistry as Dn, harnessTranscriptArtifact as Dr, passedItems as Dt, recordScopeOwnerDriverAttempt as E, renderUnsupported as Ei, LEAF_CONTINUATION_TASK as En, captureHarnessTranscript as Er, failedItems as Et, seatExecutionProfile as F, inheritRuntimeOwnedExecutorAttestation as Fi, retainedExecutorSeamKey as Fn, readTraceContextFromEnv as Fr, snapshotExecutorConfig as Ft, scopeRetainedOwnerContext as G, runtimeOwnedPendingExecutorMaterialization as Gi, replaySpawnTree as Gn, flatOtelSpan as Gr, workerTraceSeamKey as Gt, prepareScopeRetainedOwnerSeatSwitch as H, runtimeOwnedExecutorExecutionBinding as Hi, insideCursorNamespace as Hn, buildRuntimeEventOtelSpans as Hr, readWorkerTraceContext as Ht, abandonScopeRetainedOwnerInvocation as I, knownExecutionBindingReceipt as Ii, unavailablePauseMs as In, traceContextToEnv as Ir, createWorktreeCliExecutor as It, scopeRetainedOwnerResourceReader as J, unknownMaterializationReceipt as Ji, readCommittedJsonLines as Jn, padSpanId as Jr, createActivityLog as Jt, scopeRetainedOwnerJournalRoot as K, runtimeOwnedScopeOwnerRuntime as Ki, isNoEntError as Kn, generateSpanId as Kr, taskToPrompt as Kt, beginScopeRetainedOwnerDrive as L, knownMaterializationReceipt as Li, unavailableSignalOfFailure as Ln, defaultRedactor as Lr, DEFAULT_SANDBOX_STEERING_MAX_TURNS as Lt, SeatChain as M, attestRuntimeOwnedScopeOwner as Mi, decodeToolPart as Mn, contentAddress as Mr, cliWorktreeExecutor as Mt, SeatChainExhaustedError as N, authoredProfileDigest as Ni, sandboxSessionTraceSource as Nn, createPropagatingTraceEmitter as Nr, createExecutor as Nt, recordScopeOwnerPause as O, unsupportedProfileDimensions as Oi, providerAsExecutor as On, persistHarnessTranscript as Or, verdictFromJudgeScore as Ot, authoredSeatStages as P, finalizeRuntimeOwnedPendingExecutor as Pi, registerRetainedExecutorPreparation as Pn, mergeTraceEnv as Pr, createExecutorRegistry as Pt, SPAWN_RESOURCE_PATH_MAX_BYTES as Q, detachedSnapshot as Qi, isTraceAnalysisStore as Qn, createRuntimeStreamEventCollector as Qr, DEFAULT_PEER_MAIL_LIMITS as Qt, bindScopeRetainedOwnerEnvironmentId as R, newExecutionAttemptId as Ri, FileResultBlobStore as Rn, defaultRedactorIdentityMaterial as Rr, createSteerableSandboxSession as Rt, createScope as S, promptModelProfileMaterialization as Si, assertBoxlessPromptOptions as Sn, RunCancellationReason as Sr, checkVerdictOf as St, meterRuntimeOwnedProviderAttempt as T, renderProfileMaterializationIssues as Ti, runBrainLoop as Tn, runAbortable as Tr, expandQuestions as Tt, prepareScopeRetainedOwnerTask as U, runtimeOwnedExecutorMaterialization as Ui, loadSpawnForest as Un, createOpenInferenceFileExporter as Ur, workerTraceEnv as Ut, noteScopeRetainedOwnerCoordination as V, runtimeOwnedDriveHarnessProviderEvidence as Vi, InMemorySpawnJournal as Vn, buildLoopSpanNodes as Vr, WORKER_TRACE_PROPAGATION as Vt, reconcileScopeRetainedOwnerEnvironment as W, runtimeOwnedExecutorProviderEvidence as Wi, materializeTreeView as Wn, createOtelExporter as Wr, workerTraceHeaders as Wt, scopeRetainedOwnerResult as X, executableAgentSpecSnapshot as Xi, WORKER_TOOL_TRACE_SCHEMA_VERSION as Xn, toOtelAttributes as Xr, createInbox as Xt, scopeRetainedOwnerRestorePoint as Y, executableAgentProfileSnapshot as Yi, writeAllBytes as Yn, padTraceId as Yr, readWorkerProgress as Yt, scopeRetainedOwnerTurnEnded as Z, detachedFrozen as Zi, captureWorkerTraceEvidence as Zn, createRuntimeEventCollector as Zr, AUTHORITY_MARKERS as Zt, isDriverSpec as _, promptOptionsFromAgentTurnInput as _a, controlProfileMaterialization as _i, runAgentRounds as _n, retainedCreateMaterial as _r, CONTINUATION_FACTS as _t, collectDelivered as a, extractLlmCallEvent as aa, createWorktree as ai, isLiveNodeStatus as an, createBudgetPool as ar, interactiveAdmissionSeamKey as at, assertRecursiveReservationPolicy as b, profileMaterializationAxes$1 as bi, SandboxEvidenceRetentionError as bn, createWorkerSlots as br, admitFinding as bt, runTree as c, mapSandboxToolEvent as ca, LOCAL_HARNESSES as ci, bridgeModelRouteRefusal as cn, spendFromUsageEvents as cr, reconnectRetainedInteractiveRun as ct, classifyDriverFailure as d, sandboxProgressEvents as da, localHarnessExecutable as di, harnessUsageIsEmpty as dn, bridgeStopSignalKey as dr, freeSlots as dt, readSandboxOutcome as ea, sanitizeKnowledgeReadinessReport as ei, claimsAuthority as en, workerTraceAnalysisStore as er, hostDirectoryReader as et, runDriverWithRetry as f, sumSandboxUsage as fa, parseCodexTokenUsage as fi, readCodexRolloutSession as fn, errMessage as fr, queueOf as ft, driverExecutorFactory as g, promptFromAgentTurnInput as ga, assertProfileMaterialization as gi, isTerminalDecision as gn, startRetainedRunInEnvironment as gr, CONTINUATIONS_DIR as gt, driverChild as h, awaitAbortable$1 as ha, AGENT_PROFILE_MATERIALIZATION_AXES as hi, defaultSelectWinner as hn, startRetainedRun as hr, mapExecutorResult as ht, bestDelivered as i, createSandboxUsageLedger as ia, captureWorktreeDiff as ii, peerMailVerbNames as in, assertValidBudget as ir, providerVisibleProfile as it, settledToIteration as j, attestRuntimeOwnedPendingExecutor as ji, createPushTraceSource as jn, retainHarnessTranscript as jr, cliInPlaceExecutor as jt, restoreScopeOwnerAcceptedExecution as k, validateProfileMaterialization as ki, providerAsSandboxClient as kn, readHarnessTranscript as kr, bindReusableExecutorExecutionId as kt, DriverAttemptsExhaustedError as l, notifySandboxEventObserver as la, harnessInvocation as li, addHarnessUsage as ln, spendFromUsageTotals as lr, recoverRetainedInteractiveRun as lt, upstreamUnavailableSignal as m, abortError$1 as ma, terminateProcessTreeAndConfirm as mi, createSandboxForSpec as mn, recoverRetainedRun as mr, gateOnDeliverable as mt, createRootHandle as n, canonicalStreamEventFromSandboxEvent as na, runSettledCommand as ni, isPeerMailEnvelope as nn, BudgetReconcileFault as nr, coordinationMcpAlias as nt, pickBestDelivered as o, isSandboxTerminalEvent as oa, removeWorktree as oi, isTerminalNodeStatus as on, meterUsageEvent as or, attachWorker as ot, summarizeDriverAttempts as p, decodeHarnessUsage as pa, CodexExecutionDiagnosticError as pi, TERMINAL_DECISIONS as pn, reconnectRetainedRun as pr, rollingDispatch as pt, scopeRetainedOwnerPriorSpend as q, unknownExecutionBindingReceipt as qi, prepareJsonlAppend as qn, loopEventToOtelSpan as qr, DEFAULT_STALL_AFTER_MS as qt, createSupervisor as r, createSandboxToolPartState as ra, runWorktreeHarness as ri, peerMailTools as rn, ReservationWaitRefused as rr, coordinationProfileToolPrefix as rt, runFinalizer as s, mapSandboxEvent as sa, DEFAULT_LOCAL_HARNESS as si, bridgeAdmissionRefusal as sn, newUsageTotals as sr, readWorkerInteractiveBinding as st, DEFAULT_MAX_DEPTH as t, assertSandboxServedModel as ta, sanitizeRuntimeStreamEvent as ti, createPeerMailbox as tn, executorFailure as tr, resolveSpawnResourcePaths as tt, HarnessTurnFailedError as u, sandboxEventServedBackend as ua, harnessSupportsReasoningEffort as ui, createCodexRolloutStoreReader as un, bridgeRuntimeAttachmentsKey as ur, startRetainedInteractiveRun as ut, withDriverExecutor as v, providerMessageText as va, defineProfileMaterializationContract as vi, createSandboxLineage as vn, destroyInteractiveEnvironment as vr, CheckUnavailableError as vt, meterRuntimeOwnedAccounting as w, promptResourceProfileMaterialization as wi, routerBrain as wn, linkAbort as wr, distillFindings as wt, beginScopeOwnerAttempt as x, promptControlProfileMaterialization as xi, captureBeforeDestroy as xn, openSlotGroup as xr, bestComposite as xt, SUBTREE_RESULT_LIMIT as y, fullProfileMaterialization as yi, acquireSandbox as yn, environmentGone as yr, admitContinuationPolicy as yt, bindScopeRetainedOwnerProvider as z, providerAttemptEvidence as zi, FileSpawnJournal as zn, resolveRedactor as zr, createRouterTranscript as zt };
28782
29540
 
28783
- //# sourceMappingURL=supervisor-DYKPbcZa.js.map
29541
+ //# sourceMappingURL=supervisor-CSMb8HBU.js.map