@tangle-network/agent-runtime 0.252.1 → 0.254.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/{activation-CXrrtB5m.js → activation-Btw2npV2.js} +2 -2
  2. package/dist/{activation-CXrrtB5m.js.map → activation-Btw2npV2.js.map} +1 -1
  3. package/dist/{activation-CVMjsBM2.d.ts → activation-Cus2oZaT.d.ts} +2 -2
  4. package/dist/agent.d.ts +2 -2
  5. package/dist/agent.js +2 -2
  6. package/dist/{coordination-driver-D_LHrYiF.js → coordination-driver-Ct2hwxe6.js} +6 -5
  7. package/dist/coordination-driver-Ct2hwxe6.js.map +1 -0
  8. package/dist/{delegate-C8qzIpfB.js → delegate-DZZxeNKi.js} +2 -2
  9. package/dist/{delegate-C8qzIpfB.js.map → delegate-DZZxeNKi.js.map} +1 -1
  10. package/dist/durable.d.ts +2 -2
  11. package/dist/durable.js +4 -2
  12. package/dist/durable.js.map +1 -1
  13. package/dist/{graph-xWtpPhOj.js → graph-CP0OGyFP.js} +11 -5
  14. package/dist/graph-CP0OGyFP.js.map +1 -0
  15. package/dist/{improvement-cycle-blUuLwtN.js → improvement-cycle-D0Os0Hg_.js} +3 -3
  16. package/dist/{improvement-cycle-blUuLwtN.js.map → improvement-cycle-D0Os0Hg_.js.map} +1 -1
  17. package/dist/{index-BOyxiPdv.d.ts → index-DC_zQGpn.d.ts} +47 -5
  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-HOQO-Bc5.js → loop-runner-bin-BA7RtYGu.js} +3 -3
  25. package/dist/{loop-runner-bin-HOQO-Bc5.js.map → loop-runner-bin-BA7RtYGu.js.map} +1 -1
  26. package/dist/{loop-runner-bin-CEjfP-9b.d.ts → loop-runner-bin-BMcM1Nhf.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-8E1xkqPd.d.ts → openai-tools-BsqD1_Zr.d.ts} +2 -2
  33. package/dist/profiles.d.ts +2 -2
  34. package/dist/{provision-supervisor-D72s82K_.js → provision-supervisor-4e3sTnHl.js} +24 -6
  35. package/dist/provision-supervisor-4e3sTnHl.js.map +1 -0
  36. package/dist/{runtime-DuE9T9fQ.js → runtime-CthBzf7g.js} +9 -8
  37. package/dist/runtime-CthBzf7g.js.map +1 -0
  38. package/dist/{server-BRcoetaI.js → server-2qhN_mFT.js} +3 -3
  39. package/dist/{server-BRcoetaI.js.map → server-2qhN_mFT.js.map} +1 -1
  40. package/dist/{stream-agent-turn-vHFw9Cjl.d.ts → stream-agent-turn-DRTFLphI.d.ts} +2 -2
  41. package/dist/{structural-rollout-DwklJEOU.js → structural-rollout-BIBxgW64.js} +4 -3
  42. package/dist/{structural-rollout-DwklJEOU.js.map → structural-rollout-BIBxgW64.js.map} +1 -1
  43. package/dist/{substrate-Dtw3KmTi.d.ts → substrate-BToFBpfh.d.ts} +2 -2
  44. package/dist/{supervise-IBkXPk1z.js → supervise-ByEnDAOW.js} +56 -19
  45. package/dist/supervise-ByEnDAOW.js.map +1 -0
  46. package/dist/{supervisor-BlDW3u0y.js → supervisor-CJyzUjc7.js} +705 -166
  47. package/dist/supervisor-CJyzUjc7.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-DKeaex8Q.d.ts → types-ChewVlpE.d.ts} +120 -18
  53. package/package.json +5 -5
  54. package/dist/coordination-driver-D_LHrYiF.js.map +0 -1
  55. package/dist/graph-xWtpPhOj.js.map +0 -1
  56. package/dist/provision-supervisor-D72s82K_.js.map +0 -1
  57. package/dist/runtime-DuE9T9fQ.js.map +0 -1
  58. package/dist/supervise-IBkXPk1z.js.map +0 -1
  59. package/dist/supervisor-BlDW3u0y.js.map +0 -1
@@ -8,11 +8,11 @@ import { estimateCost, isModelPriced, isToolSpan, toolSpansToTraceAnalysisStore
8
8
  import { createAgentRunOutcomeTracker } from "@tangle-network/sandbox/runtime";
9
9
  import { createHash, randomBytes, randomUUID } from "node:crypto";
10
10
  import { spawn } from "node:child_process";
11
- import { appendFileSync, constants, createReadStream, existsSync, mkdirSync, readFileSync } from "node:fs";
11
+ import { appendFileSync, closeSync, constants, createReadStream, existsSync, mkdirSync, openSync, readFileSync } from "node:fs";
12
12
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep, win32 } from "node:path";
13
13
  import { access, chmod, copyFile, mkdir, mkdtemp, open, readFile, readdir, realpath, rm, rmdir, stat, symlink, writeFile } from "node:fs/promises";
14
14
  import { applyWorkspacePlan, hashWorkspacePlan, materializeProfile, resolveAgentProfileResources } from "@tangle-network/agent-profile-materialize";
15
- import { homedir, tmpdir } from "node:os";
15
+ import { homedir, hostname, tmpdir } from "node:os";
16
16
  import { stripVTControlCharacters } from "node:util";
17
17
  import { deriveHexId, isW3CSpanId, isW3CTraceId } from "@tangle-network/agent-trace-contract";
18
18
  import { SDKError, generateIdempotencyKey, withRetry } from "@tangle-network/agent-core";
@@ -136,9 +136,10 @@ function boundedChildDeadlineAt(parentDeadlineAtMs, childDeadlineMs, nowMs) {
136
136
  /** Invoke teardown once and bound how long the runtime waits for its acknowledgement. A hard
137
137
  * execution deadline always wins; without one, numeric grace gets a short acknowledgement
138
138
  * allowance and a brutal kill gets only that allowance. Explicit `infinity` remains unbounded
139
- * only when no execution deadline exists. The losing promise stays observed. */
140
- async function teardownExecutor(executor, grace, deadlineAtMs, now) {
141
- const work = Promise.resolve(executor.teardown(grace));
139
+ * only when no execution deadline exists. The losing promise stays observed. `ask` issues the
140
+ * request; a scope passes its per-child single-flight asker (see `singleFlightTeardown`). */
141
+ async function teardownExecutor(executor, grace, deadlineAtMs, now, ask = (requested) => Promise.resolve(executor.teardown(requested))) {
142
+ const work = Promise.resolve(ask(grace));
142
143
  const requestedWaitMs = grace === "infinity" ? void 0 : grace === "brutalKill" ? executor.teardownTimeoutMs ?? TEARDOWN_ACKNOWLEDGEMENT_MS : grace + TEARDOWN_ACKNOWLEDGEMENT_MS;
143
144
  const deadlineWaitMs = deadlineAtMs === void 0 ? void 0 : Math.max(0, deadlineAtMs - now()) + TEARDOWN_ACKNOWLEDGEMENT_MS;
144
145
  const waitMs = requestedWaitMs === void 0 ? deadlineWaitMs : deadlineWaitMs === void 0 ? requestedWaitMs : Math.min(requestedWaitMs, deadlineWaitMs);
@@ -160,6 +161,48 @@ async function teardownExecutor(executor, grace, deadlineAtMs, now) {
160
161
  }
161
162
  if (!receipt.destroyed) throw new ValidationError$1(`executor teardown reported destroyed=false${receipt.detail ? `: ${receipt.detail}` : ""}`);
162
163
  }
164
+ /**
165
+ * The optional teardown surfaces a wrapping executor forwards, so wrapping never changes how a
166
+ * child is released: the acknowledgement window a remote teardown needs, the release of a
167
+ * retained execution at root settlement, and the environments an unconfirmed teardown names for
168
+ * a sweeper. A wrapper that dropped `releaseRetained` left every retained child it wrapped
169
+ * running after settlement. Each surface is present only when the inner executor implements it.
170
+ */
171
+ function teardownSurfaces(inner) {
172
+ return {
173
+ ...inner.teardownTimeoutMs === void 0 ? {} : { teardownTimeoutMs: inner.teardownTimeoutMs },
174
+ ...inner.releaseRetained === void 0 ? {} : { releaseRetained: (signal) => inner.releaseRetained(signal) },
175
+ ...inner.heldEnvironments === void 0 ? {} : { heldEnvironments: () => inner.heldEnvironments() }
176
+ };
177
+ }
178
+ /**
179
+ * An asker that sends an executor at most one teardown at a time. While a request is still
180
+ * running, every later ask returns that same request instead of sending another beside it.
181
+ *
182
+ * A settlement's own teardown has a short acknowledgement window, and a request that misses it
183
+ * keeps running. Without this, the first settlement retry sent a second teardown next to the
184
+ * first. An executor that does not deduplicate internally, such as one that re-issues its
185
+ * cancels, then ran two teardowns at once. `onRequest` runs once for each request actually sent.
186
+ */
187
+ function singleFlightTeardown(executor, onRequest) {
188
+ let inFlight;
189
+ return (grace) => {
190
+ if (inFlight !== void 0) return inFlight;
191
+ onRequest();
192
+ let request;
193
+ try {
194
+ request = Promise.resolve(executor.teardown(grace));
195
+ } catch (error) {
196
+ request = Promise.reject(error);
197
+ }
198
+ inFlight = request;
199
+ const settle = () => {
200
+ if (inFlight === request) inFlight = void 0;
201
+ };
202
+ request.then(settle, settle);
203
+ return request;
204
+ };
205
+ }
163
206
  //#endregion
164
207
  //#region src/runtime/retained-run-binding.ts
165
208
  function exactSession(environment, controlRef) {
@@ -6468,6 +6511,117 @@ function isDurableArtifact(artifact) {
6468
6511
  return "locator" in artifact;
6469
6512
  }
6470
6513
  //#endregion
6514
+ //#region src/runtime/retained-interactive-lifecycle.ts
6515
+ const INTERACTIVE_CLEANUP_TIMEOUT_MS = 3e4;
6516
+ /** Bound on one lookup that asks the provider whether it still holds an environment. */
6517
+ const ENVIRONMENT_LOOKUP_TIMEOUT_MS = 3e4;
6518
+ /**
6519
+ * Whether the provider no longer holds `environmentId`, asked after a destroy failed.
6520
+ *
6521
+ * A delete that ran on the server but whose answer was lost, or that a cancel aborted in flight,
6522
+ * fails on every later delete with not-found: the Tangle SDK throws `NotFoundError` on a 404. A
6523
+ * retry that only re-sends the delete then never confirms, and names for a sweeper an environment
6524
+ * that no longer exists. The provider's lookup is the confirmation left: `get` answering `null`
6525
+ * means the environment is gone, the same rule a retained release applies. A lookup that fails,
6526
+ * times out or finds the environment confirms nothing.
6527
+ */
6528
+ async function environmentGone(provider, environmentId, signal) {
6529
+ if (provider.get === void 0) return false;
6530
+ const bound = AbortSignal.timeout(ENVIRONMENT_LOOKUP_TIMEOUT_MS);
6531
+ try {
6532
+ return await awaitAbortable$1(Promise.resolve().then(() => provider.get(environmentId)), signal === void 0 ? bound : AbortSignal.any([signal, bound])) === null;
6533
+ } catch {
6534
+ return false;
6535
+ }
6536
+ }
6537
+ /** Create one environment while retaining ownership if cancellation wins the race. */
6538
+ async function createInteractiveEnvironment(create, signal) {
6539
+ if (signal?.aborted) throw abortError$2(signal.reason);
6540
+ const creation = Promise.resolve().then(create);
6541
+ if (signal === void 0) return creation;
6542
+ return new Promise((resolve, reject) => {
6543
+ let owner = "pending";
6544
+ const removeAbortListener = () => signal.removeEventListener("abort", onAbort);
6545
+ const onAbort = () => {
6546
+ if (owner !== "pending") return;
6547
+ owner = "runtime";
6548
+ removeAbortListener();
6549
+ disposeInteractiveEnvironment(creation, signal.reason);
6550
+ reject(abortError$2(signal.reason));
6551
+ };
6552
+ signal.addEventListener("abort", onAbort, { once: true });
6553
+ creation.then((environment) => {
6554
+ if (owner !== "pending") return;
6555
+ owner = "caller";
6556
+ removeAbortListener();
6557
+ resolve(environment);
6558
+ }, (error) => {
6559
+ if (owner !== "pending") return;
6560
+ owner = "runtime";
6561
+ removeAbortListener();
6562
+ reject(error);
6563
+ });
6564
+ });
6565
+ }
6566
+ /** Start one process while destroying its unreturned environment on cancellation. */
6567
+ async function startInteractiveProcess(environment, start, signal) {
6568
+ if (signal?.aborted) {
6569
+ disposeInteractiveEnvironment(Promise.resolve(environment), signal.reason);
6570
+ throw abortError$2(signal.reason);
6571
+ }
6572
+ const pending = Promise.resolve().then(start);
6573
+ if (signal === void 0) return pending;
6574
+ return new Promise((resolve, reject) => {
6575
+ let owner = "pending";
6576
+ const removeAbortListener = () => signal.removeEventListener("abort", onAbort);
6577
+ const onAbort = () => {
6578
+ if (owner !== "pending") return;
6579
+ owner = "runtime";
6580
+ removeAbortListener();
6581
+ disposeInteractiveEnvironment(Promise.resolve(environment), signal.reason);
6582
+ reject(abortError$2(signal.reason));
6583
+ };
6584
+ signal.addEventListener("abort", onAbort, { once: true });
6585
+ pending.then((result) => {
6586
+ if (owner !== "pending") return;
6587
+ owner = "caller";
6588
+ removeAbortListener();
6589
+ resolve(result);
6590
+ }, (error) => {
6591
+ if (owner !== "pending") return;
6592
+ owner = "runtime";
6593
+ removeAbortListener();
6594
+ reject(error);
6595
+ });
6596
+ });
6597
+ }
6598
+ /** Destroy an environment with fresh, bounded cleanup authority. */
6599
+ async function destroyInteractiveEnvironment(environment) {
6600
+ if (!environment.destroy) throw new Error(`provider environment "${environment.id}" does not expose destroy()`);
6601
+ const controller = new AbortController();
6602
+ const timeout = /* @__PURE__ */ new Error("interactive environment cleanup timed out");
6603
+ let timer;
6604
+ const destruction = Promise.resolve().then(() => environment.destroy?.({ signal: controller.signal }));
6605
+ destruction.catch(() => void 0);
6606
+ try {
6607
+ await Promise.race([destruction, new Promise((_resolve, reject) => {
6608
+ timer = setTimeout(() => {
6609
+ controller.abort(timeout);
6610
+ reject(timeout);
6611
+ }, INTERACTIVE_CLEANUP_TIMEOUT_MS);
6612
+ })]);
6613
+ } finally {
6614
+ if (timer !== void 0) clearTimeout(timer);
6615
+ }
6616
+ }
6617
+ function disposeInteractiveEnvironment(environment, abortReason) {
6618
+ environment.then(destroyInteractiveEnvironment, () => void 0).catch((cleanupError) => {
6619
+ const reason = abortReason instanceof Error ? abortReason : new Error(String(abortReason));
6620
+ const failure = new AggregateError([reason, cleanupError], "cancelled interactive environment cleanup failed");
6621
+ process.emitWarning(failure, { code: "AGENT_RUNTIME_INTERACTIVE_CLEANUP_FAILED" });
6622
+ });
6623
+ }
6624
+ //#endregion
6471
6625
  //#region src/runtime/interaction-capabilities.ts
6472
6626
  /**
6473
6627
  * Check one turn's interaction request before the provider can dispatch it.
@@ -8018,7 +8172,8 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
8018
8172
  if (target === void 0) return { destroyed: true };
8019
8173
  if (workspacePreservationRequired) return {
8020
8174
  destroyed: false,
8021
- detail: "provider workspace retention: source preserved because execution failed before a retrievable settled workspace receipt existed"
8175
+ detail: "provider workspace retention: source preserved because execution failed before a retrievable settled workspace receipt existed",
8176
+ permanent: true
8022
8177
  };
8023
8178
  if (options.workspaceRetention !== void 0) try {
8024
8179
  const currentSnapshot = await captureWorkspace(target, workspaceOutcome);
@@ -8026,13 +8181,15 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
8026
8181
  workspacePreservationRequired = true;
8027
8182
  return {
8028
8183
  destroyed: false,
8029
- detail: "provider workspace retention: live workspace changed after the published receipt; source preserved"
8184
+ detail: "provider workspace retention: live workspace changed after the published receipt; source preserved",
8185
+ permanent: true
8030
8186
  };
8031
8187
  }
8032
8188
  } catch {
8033
8189
  return {
8034
8190
  destroyed: false,
8035
- detail: workspaceFailureDetail()
8191
+ detail: workspaceFailureDetail(),
8192
+ permanent: true
8036
8193
  };
8037
8194
  }
8038
8195
  if (destroyed) return { destroyed: true };
@@ -8041,6 +8198,10 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
8041
8198
  destroyed = true;
8042
8199
  return { destroyed: true };
8043
8200
  } catch (error) {
8201
+ if (await environmentGone(provider, target.id, cleanupSignal)) {
8202
+ destroyed = true;
8203
+ return { destroyed: true };
8204
+ }
8044
8205
  return {
8045
8206
  destroyed: false,
8046
8207
  detail: `providerAsExecutor(${provider.name}): environment.destroy() failed — ${error instanceof Error ? error.message : String(error)}`
@@ -8200,39 +8361,52 @@ function createProviderExecutor(provider, profile, ctx, options, placement) {
8200
8361
  };
8201
8362
  if (pending) return {
8202
8363
  destroyed: false,
8203
- detail: "retained execution requires reconciliation"
8364
+ detail: "retained execution requires reconciliation",
8365
+ permanent: true
8204
8366
  };
8205
8367
  return await destroyEnvironment();
8206
8368
  },
8369
+ heldEnvironments() {
8370
+ if (destroyed) return [];
8371
+ const environmentId = environment?.id ?? retained?.controlRef.environmentId ?? admittedEnvironmentId(retention);
8372
+ if (environmentId === void 0) return [];
8373
+ const preserved = workspacePreservationRequired || workspaceCaptureFailure !== void 0;
8374
+ return [{
8375
+ provider: provider.name,
8376
+ environmentId,
8377
+ ...preserved ? { keptFor: "evidence" } : {}
8378
+ }];
8379
+ },
8207
8380
  async releaseRetained(signal) {
8208
8381
  controller.abort();
8209
8382
  if (!pending) return [];
8210
8383
  const environmentId = retained?.controlRef.environmentId ?? environment?.id ?? admittedEnvironmentId(retention);
8211
8384
  if (environmentId === void 0) return [];
8212
- const receipt = (destroyed, detail) => ({
8385
+ const receipt = (destroyed, detail, permanent) => ({
8213
8386
  provider: provider.name,
8214
8387
  environmentId,
8215
8388
  destroyed,
8216
- ...detail === void 0 ? {} : { detail }
8389
+ ...detail === void 0 ? {} : { detail },
8390
+ ...permanent === true ? { permanent } : {}
8217
8391
  });
8218
8392
  if (options.workspaceRetention !== void 0 && workspaceRunActive) return [receipt(false, "provider workspace retention: source preserved while execution is still active")];
8219
8393
  if (retainedReleasePromise !== void 0) return await retainedReleasePromise;
8220
8394
  const releasePromise = (async () => {
8221
8395
  try {
8222
8396
  const target = environment ?? (provider.get === void 0 ? void 0 : await awaitAbortable$1(provider.get(environmentId), signal));
8223
- if (target === void 0) return [receipt(false, `providerAsExecutor(${provider.name}): no environment handle and the provider exposes no get()`)];
8397
+ if (target === void 0) return [receipt(false, `providerAsExecutor(${provider.name}): no environment handle and the provider exposes no get()`, true)];
8224
8398
  if (target === null) {
8225
8399
  pending = false;
8226
8400
  destroyed = true;
8227
8401
  return [receipt(true)];
8228
8402
  }
8229
- if (target.destroy === void 0) return [receipt(false, `providerAsExecutor(${provider.name}): environment exposes no destroy()`)];
8403
+ if (target.destroy === void 0) return [receipt(false, `providerAsExecutor(${provider.name}): environment exposes no destroy()`, true)];
8230
8404
  if (environment === void 0) {
8231
8405
  environment = target;
8232
8406
  resetWorkspaceState(target);
8233
8407
  }
8234
8408
  const result = await destroyEnvironment(signal);
8235
- if (!result.destroyed) return [receipt(false, result.detail)];
8409
+ if (!result.destroyed) return [receipt(false, result.detail, result.permanent)];
8236
8410
  pending = false;
8237
8411
  return [receipt(true)];
8238
8412
  } catch (error) {
@@ -14327,6 +14501,181 @@ function taskToPrompt(task) {
14327
14501
  return JSON.stringify(task);
14328
14502
  }
14329
14503
  //#endregion
14504
+ //#region src/runtime/supervise/worker-lineage.ts
14505
+ /**
14506
+ * Session lineage handed DOWN to a spawned worker: the `TANGLE_*` ids the operator's `lineage` tool
14507
+ * (tangle-tools `lineage/`) stamps at every launch, so a supervised tree shows up in the cross-box
14508
+ * session graph with each worker under the supervisor that spawned it.
14509
+ *
14510
+ * WHY NOT THE TRACE SEAM. `worker-trace.ts` joins a worker's SPANS to the supervisor's trace, and is
14511
+ * off unless the run exports spans. Lineage is a different question — which session started which —
14512
+ * and has to hold when tracing is off. It keys on the supervisor process's OWN lineage instead: the
14513
+ * ambient `TANGLE_RUN_ID` a launcher stamped on this process.
14514
+ *
14515
+ * OFF WHEN THE SUPERVISOR IS UNSTAMPED. No ambient `TANGLE_RUN_ID` ⇒ every function here returns an
14516
+ * empty record and writes nothing, so a runtime used outside a lineage-stamped launcher spawns
14517
+ * byte-identical environments to before this module existed.
14518
+ *
14519
+ * THE WIRE (contract v1, tangle-tools `lineage/README.md`):
14520
+ * env TANGLE_RUN_ID (fresh `run_<32 hex>` per worker), TANGLE_PARENT_RUN_ID (this process),
14521
+ * TANGLE_ROOT_RUN_ID, TANGLE_EDGE_KIND=spawned, TANGLE_OPERATOR / TANGLE_PROJECT /
14522
+ * TANGLE_ACCOUNT (inherited), TANGLE_HARNESS, TANGLE_HOST (local children only),
14523
+ * OTEL_RESOURCE_ATTRIBUTES with the `tangle.*` keys replaced, and TANGLE_CLAUDE_SESSION
14524
+ * cleared so a Claude Code worker takes the stamped run as its own.
14525
+ * headers `x-tangle-run-id` and siblings on the cli-bridge turn POST; the bridge stamps them into
14526
+ * the harness child it spawns.
14527
+ * event one `node` line plus one `spawned` edge appended to
14528
+ * `$LINEAGE_HOME/events/<host>.jsonl` (default `~/.local/state/lineage`), only when that
14529
+ * directory already exists — the runtime never creates operator state on its own.
14530
+ *
14531
+ * Every failure to record is swallowed: lineage is observability and must never fail a spawn.
14532
+ */
14533
+ /** Inherited from the supervisor process to every worker unchanged. */
14534
+ const INHERITED = [
14535
+ "TANGLE_OPERATOR",
14536
+ "TANGLE_PROJECT",
14537
+ "TANGLE_ACCOUNT"
14538
+ ];
14539
+ const OTEL_KEYS = {
14540
+ TANGLE_RUN_ID: "tangle.run.id",
14541
+ TANGLE_PARENT_RUN_ID: "tangle.parent_run.id",
14542
+ TANGLE_ROOT_RUN_ID: "tangle.root_run.id",
14543
+ TANGLE_EDGE_KIND: "tangle.edge.kind",
14544
+ TANGLE_OPERATOR: "tangle.operator",
14545
+ TANGLE_PROJECT: "tangle.project",
14546
+ TANGLE_ACCOUNT: "tangle.account",
14547
+ TANGLE_HARNESS: "tangle.harness",
14548
+ TANGLE_HOST: "host.name"
14549
+ };
14550
+ /** Harness names the lineage contract accepts, from a backend type or a CLI binary name. */
14551
+ const HARNESS_ALIASES = {
14552
+ claude: "claude-code",
14553
+ "claude-code": "claude-code",
14554
+ codex: "codex",
14555
+ opencode: "opencode",
14556
+ pi: "pi",
14557
+ kimi: "kimi",
14558
+ "kimi-code": "kimi"
14559
+ };
14560
+ const EMPTY = {
14561
+ env: {},
14562
+ headers: {}
14563
+ };
14564
+ function lineageHost(env = process.env) {
14565
+ const name = (env.LINEAGE_HOST || hostname()).trim().toLowerCase();
14566
+ return name.endsWith(".local") ? name.slice(0, -6) : name;
14567
+ }
14568
+ function lineageHarness(harness) {
14569
+ if (!harness) return "agent-runtime";
14570
+ const base = harness.split(/[\\/]/).pop() ?? harness;
14571
+ return HARNESS_ALIASES[base] ?? HARNESS_ALIASES[harness] ?? "agent-runtime";
14572
+ }
14573
+ /** Merge lineage ids into an OTEL_RESOURCE_ATTRIBUTES value, replacing earlier lineage keys. */
14574
+ function lineageOtelAttributes(existing, ids) {
14575
+ const ours = new Set(Object.values(OTEL_KEYS));
14576
+ const kept = (existing ?? "").split(",").map((pair) => pair.trim()).filter((pair) => pair.length > 0 && !ours.has((pair.split("=", 1)[0] ?? "").trim()));
14577
+ for (const [envKey, attr] of Object.entries(OTEL_KEYS)) {
14578
+ const value = ids[envKey];
14579
+ if (value) kept.push(`${attr}=${encodeURIComponent(value)}`);
14580
+ }
14581
+ return kept.join(",");
14582
+ }
14583
+ /**
14584
+ * Mint the lineage ids for one worker and record its launch. Empty when the supervisor process
14585
+ * carries no `TANGLE_RUN_ID`.
14586
+ */
14587
+ function workerLineage(options) {
14588
+ const env = options.env ?? process.env;
14589
+ const parent = env.TANGLE_RUN_ID;
14590
+ if (!parent) return EMPTY;
14591
+ const run = `run_${randomBytes(16).toString("hex")}`;
14592
+ const harness = lineageHarness(options.harness);
14593
+ const ids = {
14594
+ TANGLE_RUN_ID: run,
14595
+ TANGLE_PARENT_RUN_ID: parent,
14596
+ TANGLE_ROOT_RUN_ID: env.TANGLE_ROOT_RUN_ID || parent,
14597
+ TANGLE_EDGE_KIND: "spawned",
14598
+ TANGLE_HARNESS: harness
14599
+ };
14600
+ for (const key of INHERITED) {
14601
+ const value = env[key];
14602
+ if (value) ids[key] = value;
14603
+ }
14604
+ if (options.local) ids.TANGLE_HOST = lineageHost(env);
14605
+ const workerEnv = {
14606
+ ...ids,
14607
+ OTEL_RESOURCE_ATTRIBUTES: lineageOtelAttributes(env.OTEL_RESOURCE_ATTRIBUTES, ids),
14608
+ TANGLE_CLAUDE_SESSION: ""
14609
+ };
14610
+ const headers = {};
14611
+ for (const [key, value] of Object.entries(ids)) headers[`x-${key.toLowerCase().replace(/_/g, "-")}`] = value;
14612
+ recordLaunch(env, ids, options);
14613
+ return {
14614
+ env: workerEnv,
14615
+ headers
14616
+ };
14617
+ }
14618
+ function eventLine(event) {
14619
+ const body = sortKeys(event);
14620
+ const id = createHash("sha256").update(JSON.stringify(body)).digest("hex").slice(0, 16);
14621
+ return `${JSON.stringify(sortKeys({
14622
+ ...body,
14623
+ id
14624
+ }))}\n`;
14625
+ }
14626
+ function sortKeys(value) {
14627
+ const out = {};
14628
+ for (const key of Object.keys(value).sort()) {
14629
+ const item = value[key];
14630
+ if (item === void 0 || item === "") continue;
14631
+ out[key] = item !== null && typeof item === "object" && !Array.isArray(item) ? sortKeys(item) : item;
14632
+ }
14633
+ return out;
14634
+ }
14635
+ function recordLaunch(env, ids, options) {
14636
+ try {
14637
+ const dir = join(env.LINEAGE_HOME || join(homedir(), ".local", "state", "lineage"), "events");
14638
+ if (!existsSync(dir)) return;
14639
+ const host = lineageHost(env);
14640
+ const common = {
14641
+ v: 1,
14642
+ ts: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
14643
+ host,
14644
+ source: "runtime"
14645
+ };
14646
+ const node = eventLine({
14647
+ ...common,
14648
+ type: "node",
14649
+ run: ids.TANGLE_RUN_ID,
14650
+ parent: ids.TANGLE_PARENT_RUN_ID,
14651
+ root: ids.TANGLE_ROOT_RUN_ID,
14652
+ harness: ids.TANGLE_HARNESS,
14653
+ project: ids.TANGLE_PROJECT,
14654
+ operator: ids.TANGLE_OPERATOR,
14655
+ account: ids.TANGLE_ACCOUNT,
14656
+ native: options.nodeId ? `runtime:${options.nodeId}` : void 0,
14657
+ label: options.label?.slice(0, 80),
14658
+ cwd: process.cwd(),
14659
+ attrs: options.local ? {} : { placement: "remote" }
14660
+ });
14661
+ const edge = eventLine({
14662
+ ...common,
14663
+ type: "edge",
14664
+ kind: "spawned",
14665
+ src: ids.TANGLE_PARENT_RUN_ID,
14666
+ dst: ids.TANGLE_RUN_ID,
14667
+ attrs: {}
14668
+ });
14669
+ const fd = openSync(join(dir, `${host}.jsonl`), "a", 384);
14670
+ try {
14671
+ appendFileSync(fd, node);
14672
+ appendFileSync(fd, edge);
14673
+ } finally {
14674
+ closeSync(fd);
14675
+ }
14676
+ } catch {}
14677
+ }
14678
+ //#endregion
14330
14679
  //#region src/runtime/supervise/worker-trace.ts
14331
14680
  /**
14332
14681
  * Trace context handed DOWN to a spawned worker, so one supervised tree spans machines.
@@ -14499,7 +14848,15 @@ const bridgeExecutor = (spec, ctx) => {
14499
14848
  const maxReconnects = seam.maxReconnects ?? 3;
14500
14849
  const sessionId = seam.sessionId ?? `bridge-${spec.profile.name ?? "worker"}-${randomUUID()}`;
14501
14850
  const attemptId = ctx.node?.attemptId ?? newExecutionAttemptId(sessionId);
14502
- const traceHeaders = workerTraceHeaders(ctx);
14851
+ const traceHeaders = {
14852
+ ...workerLineage({
14853
+ harness: harness ?? null,
14854
+ nodeId: ctx.node?.nodeId,
14855
+ label: spec.profile.name,
14856
+ local: false
14857
+ }).headers,
14858
+ ...workerTraceHeaders(ctx)
14859
+ };
14503
14860
  const controller = linkAbort(ctx.signal);
14504
14861
  const inbox = createInbox();
14505
14862
  let artifact;
@@ -16502,6 +16859,8 @@ const outsideKinds = /* @__PURE__ */ new Set([
16502
16859
  "reconciled",
16503
16860
  "edge",
16504
16861
  "teardown-unconfirmed",
16862
+ "teardown-pending",
16863
+ "teardown-confirmed",
16505
16864
  "environment-teardown",
16506
16865
  "trace-unpropagated",
16507
16866
  "node-inputs-resolved",
@@ -16571,6 +16930,7 @@ async function replaySpawnTree(journal, blobs, root) {
16571
16930
  if (ev.kind === "execution-input" || ev.kind === "execution-admitted" || ev.kind === "execution-result") continue;
16572
16931
  if (ev.kind === "edge") continue;
16573
16932
  if (ev.kind === "teardown-unconfirmed") continue;
16933
+ if (ev.kind === "teardown-pending" || ev.kind === "teardown-confirmed") continue;
16574
16934
  if (ev.kind === "environment-teardown") continue;
16575
16935
  if (ev.kind === "trace-unpropagated") continue;
16576
16936
  if (ev.kind === "node-inputs-resolved") continue;
@@ -18141,7 +18501,15 @@ const sandboxExecutor = (spec, ctx) => {
18141
18501
  const maxIterations = seam.maxIterations ?? 1;
18142
18502
  if (!Number.isFinite(maxIterations) || maxIterations <= 0) throw new ValidationError$1("sandboxExecutor: maxIterations must be > 0");
18143
18503
  const sandboxTokenLimits = enforceTokenLimits(profileModelExecutionSettings(spec.profile, "sandboxExecutor").tokenLimits, "sandbox", "sandboxExecutor");
18144
- const traceEnv = workerTraceEnv(ctx);
18504
+ const traceEnv = {
18505
+ ...workerLineage({
18506
+ harness,
18507
+ nodeId: ctx.node?.nodeId,
18508
+ label: spec.profile.name,
18509
+ local: false
18510
+ }).env,
18511
+ ...workerTraceEnv(ctx)
18512
+ };
18145
18513
  const controller = linkAbort(ctx.signal);
18146
18514
  let artifact;
18147
18515
  const executionId = ctx.node?.nodeId ?? `sandbox-run-${randomUUID()}`;
@@ -18427,10 +18795,18 @@ function verdictForOutputMarker(marker) {
18427
18795
  * `0` is indistinguishable from one that measured zero, and every ceiling downstream then reads
18428
18796
  * as enforced while enforcing nothing.
18429
18797
  */
18430
- const cliExecutor = (_spec, ctx) => {
18798
+ const cliExecutor = (spec, ctx) => {
18431
18799
  const seam = readSeam(ctx, cliSeamKey, "cli");
18432
18800
  if (!seam.bin) throw new ValidationError$1("cliExecutor: CliSeam.bin required");
18433
- const traceEnv = workerTraceEnv(ctx);
18801
+ const traceEnv = {
18802
+ ...workerLineage({
18803
+ harness: seam.bin,
18804
+ nodeId: ctx.node?.nodeId,
18805
+ label: spec.profile.name,
18806
+ local: true
18807
+ }).env,
18808
+ ...workerTraceEnv(ctx)
18809
+ };
18434
18810
  const controller = linkAbort(ctx.signal);
18435
18811
  let proc;
18436
18812
  let artifact;
@@ -18468,7 +18844,7 @@ const cliExecutor = (_spec, ctx) => {
18468
18844
  return artifact;
18469
18845
  }
18470
18846
  }, {
18471
- effectiveProfile: _spec.profile,
18847
+ effectiveProfile: spec.profile,
18472
18848
  backend: "cli",
18473
18849
  model: {
18474
18850
  status: "unknown",
@@ -19590,96 +19966,6 @@ function sameInteractiveRef(left, right) {
19590
19966
  return canonicalCandidateDigest(left) === canonicalCandidateDigest(right);
19591
19967
  }
19592
19968
  //#endregion
19593
- //#region src/runtime/retained-interactive-lifecycle.ts
19594
- const INTERACTIVE_CLEANUP_TIMEOUT_MS = 3e4;
19595
- /** Create one environment while retaining ownership if cancellation wins the race. */
19596
- async function createInteractiveEnvironment(create, signal) {
19597
- if (signal?.aborted) throw abortError$2(signal.reason);
19598
- const creation = Promise.resolve().then(create);
19599
- if (signal === void 0) return creation;
19600
- return new Promise((resolve, reject) => {
19601
- let owner = "pending";
19602
- const removeAbortListener = () => signal.removeEventListener("abort", onAbort);
19603
- const onAbort = () => {
19604
- if (owner !== "pending") return;
19605
- owner = "runtime";
19606
- removeAbortListener();
19607
- disposeInteractiveEnvironment(creation, signal.reason);
19608
- reject(abortError$2(signal.reason));
19609
- };
19610
- signal.addEventListener("abort", onAbort, { once: true });
19611
- creation.then((environment) => {
19612
- if (owner !== "pending") return;
19613
- owner = "caller";
19614
- removeAbortListener();
19615
- resolve(environment);
19616
- }, (error) => {
19617
- if (owner !== "pending") return;
19618
- owner = "runtime";
19619
- removeAbortListener();
19620
- reject(error);
19621
- });
19622
- });
19623
- }
19624
- /** Start one process while destroying its unreturned environment on cancellation. */
19625
- async function startInteractiveProcess(environment, start, signal) {
19626
- if (signal?.aborted) {
19627
- disposeInteractiveEnvironment(Promise.resolve(environment), signal.reason);
19628
- throw abortError$2(signal.reason);
19629
- }
19630
- const pending = Promise.resolve().then(start);
19631
- if (signal === void 0) return pending;
19632
- return new Promise((resolve, reject) => {
19633
- let owner = "pending";
19634
- const removeAbortListener = () => signal.removeEventListener("abort", onAbort);
19635
- const onAbort = () => {
19636
- if (owner !== "pending") return;
19637
- owner = "runtime";
19638
- removeAbortListener();
19639
- disposeInteractiveEnvironment(Promise.resolve(environment), signal.reason);
19640
- reject(abortError$2(signal.reason));
19641
- };
19642
- signal.addEventListener("abort", onAbort, { once: true });
19643
- pending.then((result) => {
19644
- if (owner !== "pending") return;
19645
- owner = "caller";
19646
- removeAbortListener();
19647
- resolve(result);
19648
- }, (error) => {
19649
- if (owner !== "pending") return;
19650
- owner = "runtime";
19651
- removeAbortListener();
19652
- reject(error);
19653
- });
19654
- });
19655
- }
19656
- /** Destroy an environment with fresh, bounded cleanup authority. */
19657
- async function destroyInteractiveEnvironment(environment) {
19658
- if (!environment.destroy) throw new Error(`provider environment "${environment.id}" does not expose destroy()`);
19659
- const controller = new AbortController();
19660
- const timeout = /* @__PURE__ */ new Error("interactive environment cleanup timed out");
19661
- let timer;
19662
- const destruction = Promise.resolve().then(() => environment.destroy?.({ signal: controller.signal }));
19663
- destruction.catch(() => void 0);
19664
- try {
19665
- await Promise.race([destruction, new Promise((_resolve, reject) => {
19666
- timer = setTimeout(() => {
19667
- controller.abort(timeout);
19668
- reject(timeout);
19669
- }, INTERACTIVE_CLEANUP_TIMEOUT_MS);
19670
- })]);
19671
- } finally {
19672
- if (timer !== void 0) clearTimeout(timer);
19673
- }
19674
- }
19675
- function disposeInteractiveEnvironment(environment, abortReason) {
19676
- environment.then(destroyInteractiveEnvironment, () => void 0).catch((cleanupError) => {
19677
- const reason = abortReason instanceof Error ? abortReason : new Error(String(abortReason));
19678
- const failure = new AggregateError([reason, cleanupError], "cancelled interactive environment cleanup failed");
19679
- process.emitWarning(failure, { code: "AGENT_RUNTIME_INTERACTIVE_CLEANUP_FAILED" });
19680
- });
19681
- }
19682
- //#endregion
19683
19969
  //#region src/runtime/retained-interactive.ts
19684
19970
  /**
19685
19971
  * Start one retry-safe native coding-agent TUI without dispatching a headless turn.
@@ -21303,6 +21589,10 @@ function scopeRetainedOwnerResourceReader(scope) {
21303
21589
  }
21304
21590
  };
21305
21591
  }
21592
+ /** @internal Whether another owner release could still destroy what the last one left. */
21593
+ function retainedOwnerReleaseRetriable(scope) {
21594
+ return owners.get(scope)?.releaseRetriable ?? false;
21595
+ }
21306
21596
  /** The existing scope settlement barrier releases the owner's environment after all its turns. */
21307
21597
  async function releaseScopeRetainedOwnerEnvironment(scope) {
21308
21598
  const state = owners.get(scope);
@@ -21312,27 +21602,45 @@ async function releaseScopeRetainedOwnerEnvironment(scope) {
21312
21602
  const released = new Set(events.flatMap((event) => event.kind === "environment-teardown" && event.id === args.nodeId && event.provider === provider.name && event.destroyed ? [event.environmentId] : []));
21313
21603
  const environments = new Set(events.flatMap((event) => event.id === args.nodeId && event.kind === "execution-admitted" && event.admission.phase === "environment" ? [event.admission.environmentId] : []));
21314
21604
  const retentionFailures = state.workspaceRetention || events.some((event) => event.kind === "execution-input" && event.id === args.nodeId && event.workspaceRetention === true) ? await ownerWorkspaceRetentionFailures(events, args.nodeId, args.blobs) : /* @__PURE__ */ new Set();
21315
- let unconfirmed = false;
21605
+ const unconfirmed = [];
21606
+ const preserved = [];
21607
+ let lastDetail;
21608
+ let retriable = false;
21316
21609
  for (const environmentId of environments) {
21317
21610
  if (released.has(environmentId)) continue;
21318
21611
  let destroyed = false;
21319
21612
  let detail;
21320
21613
  if (retentionFailures.has(environmentId)) {
21321
21614
  detail = "provider workspace retention: source preserved because the owner execution has no verified workspace receipt";
21322
- unconfirmed = true;
21323
- } else try {
21324
- await runAbortable(async () => {
21325
- if (!provider.get) throw new Error("provider cannot reconstruct the retained environment");
21326
- const environment = await provider.get(environmentId);
21327
- if (environment === null) return;
21328
- if (environment.id !== environmentId || environment.provider !== provider.name) throw new Error("provider returned another retained environment");
21329
- if (!environment.destroy) throw new Error("provider cannot destroy the retained environment");
21330
- await environment.destroy();
21331
- }, AbortSignal.timeout(3e4), "retained owner cleanup timed out");
21332
- destroyed = true;
21333
- } catch {
21334
- detail = "retained owner environment cleanup was not confirmed";
21335
- unconfirmed = true;
21615
+ preserved.push(environmentId);
21616
+ lastDetail = detail;
21617
+ } else {
21618
+ let permanent = false;
21619
+ try {
21620
+ await runAbortable(async () => {
21621
+ if (!provider.get) {
21622
+ permanent = true;
21623
+ throw new Error("provider cannot reconstruct the retained environment");
21624
+ }
21625
+ const environment = await provider.get(environmentId);
21626
+ if (environment === null) return;
21627
+ if (environment.id !== environmentId || environment.provider !== provider.name) {
21628
+ permanent = true;
21629
+ throw new Error("provider returned another retained environment");
21630
+ }
21631
+ if (!environment.destroy) {
21632
+ permanent = true;
21633
+ throw new Error("provider cannot destroy the retained environment");
21634
+ }
21635
+ await environment.destroy();
21636
+ }, AbortSignal.timeout(3e4), "retained owner cleanup timed out");
21637
+ destroyed = true;
21638
+ } catch {
21639
+ detail = "retained owner environment cleanup was not confirmed";
21640
+ unconfirmed.push(environmentId);
21641
+ lastDetail = detail;
21642
+ if (!permanent) retriable = true;
21643
+ }
21336
21644
  }
21337
21645
  await args.journal.appendEvent(args.rootId, {
21338
21646
  kind: "environment-teardown",
@@ -21345,11 +21653,22 @@ async function releaseScopeRetainedOwnerEnvironment(scope) {
21345
21653
  at: new Date(args.now()).toISOString()
21346
21654
  });
21347
21655
  }
21348
- return unconfirmed ? [{
21656
+ state.releaseRetriable = retriable;
21657
+ return unconfirmed.length > 0 || preserved.length > 0 ? [{
21349
21658
  id: args.nodeId,
21350
21659
  label: "scope owner",
21351
21660
  runtime: provider.name,
21352
- status: "done"
21661
+ status: "done",
21662
+ ...unconfirmed.length === 0 ? {} : { environments: unconfirmed.map((environmentId) => ({
21663
+ provider: provider.name,
21664
+ environmentId
21665
+ })) },
21666
+ ...preserved.length === 0 ? {} : { kept: preserved.map((environmentId) => ({
21667
+ provider: provider.name,
21668
+ environmentId,
21669
+ keptFor: "evidence"
21670
+ })) },
21671
+ ...lastDetail === void 0 ? {} : { detail: lastDetail }
21353
21672
  }] : [];
21354
21673
  }
21355
21674
  /** Group owner admissions by input and require a verified workspace receipt before deletion. */
@@ -21689,9 +22008,55 @@ function defaultSleep$1(ms, signal) {
21689
22008
  const runtimeOwnedProviderMeters = /* @__PURE__ */ new WeakMap();
21690
22009
  const recoveryStarters = /* @__PURE__ */ new WeakMap();
21691
22010
  const retainedReleasers = /* @__PURE__ */ new WeakMap();
22011
+ const teardownRetriers = /* @__PURE__ */ new WeakMap();
22012
+ const teardownRetriable = /* @__PURE__ */ new WeakMap();
22013
+ /** The retained owner environments a scope's last release could not confirm destroyed. */
22014
+ const ownerUnconfirmedByScope = /* @__PURE__ */ new WeakMap();
22015
+ /** The scope a recursive executor owns, so the settlement retry reaches its descendants. */
22016
+ const nestedTeardownScopes = /* @__PURE__ */ new WeakMap();
22017
+ /** Scopes whose settlement released retained environments: none of their retained children is
22018
+ * kept for a resume any longer. */
22019
+ const releasingScopes = /* @__PURE__ */ new WeakSet();
21692
22020
  const admissionSeals = /* @__PURE__ */ new WeakMap();
21693
22021
  /** Per-child bound on a retained release: one remote destroy, answered or abandoned. */
21694
22022
  const RETAINED_RELEASE_TIMEOUT_MS = 3e4;
22023
+ /**
22024
+ * One unconfirmed child as the run names it: the node, the environments its executor still
22025
+ * reports holding, and what the last teardown attempt answered.
22026
+ *
22027
+ * Environments split by intent. Those kept on purpose go in `kept`, so a sweeper that deletes
22028
+ * `environments` never destroys work a resume would recover or evidence preserved on purpose.
22029
+ * The executor marks what it preserves as evidence. A retained-pending child is kept for a resume
22030
+ * until its scope releases retained environments at settlement: `releasing` says whether it has.
22031
+ * After a release, a retained environment still held is a leak like any other.
22032
+ */
22033
+ function unconfirmedTeardownOf(child, releasing) {
22034
+ const keptForResume = child.recoveryPending === true && !releasing;
22035
+ const environments = [];
22036
+ const kept = [];
22037
+ try {
22038
+ for (const environment of child.readHeldEnvironments?.() ?? []) {
22039
+ const keptFor = environment.keptFor ?? (keptForResume ? "resume" : void 0);
22040
+ const named = Object.freeze({
22041
+ provider: environment.provider,
22042
+ environmentId: environment.environmentId,
22043
+ ...keptFor === void 0 ? {} : { keptFor }
22044
+ });
22045
+ if (keptFor === void 0) environments.push(named);
22046
+ else kept.push(named);
22047
+ }
22048
+ } catch {}
22049
+ return Object.freeze({
22050
+ id: child.id,
22051
+ label: child.label,
22052
+ runtime: child.runtime,
22053
+ status: child.status,
22054
+ ...environments.length === 0 ? {} : { environments: Object.freeze(environments) },
22055
+ ...kept.length === 0 ? {} : { kept: Object.freeze(kept) },
22056
+ ...child.teardownAttempts > 0 ? { attempts: child.teardownAttempts } : {},
22057
+ ...child.teardownDetail === void 0 ? {} : { detail: child.teardownDetail }
22058
+ });
22059
+ }
21695
22060
  /** @internal Admit original children before the parent acts; do not wait for their results. */
21696
22061
  async function startScopeRecoveries(scope) {
21697
22062
  const start = recoveryStarters.get(scope);
@@ -21712,10 +22077,50 @@ async function startScopeRecoveries(scope) {
21712
22077
  * `Executor.releaseRetained`, and its nested scope journals theirs.
21713
22078
  */
21714
22079
  async function releaseRetainedEnvironments(scope) {
22080
+ releasingScopes.add(scope);
21715
22081
  const release = retainedReleasers.get(scope);
21716
22082
  if (release) await release();
21717
- const ownerUnconfirmed = await releaseScopeRetainedOwnerEnvironment(scope);
21718
- return [...scope.workerCapacity.unconfirmed, ...ownerUnconfirmed];
22083
+ ownerUnconfirmedByScope.set(scope, await releaseScopeRetainedOwnerEnvironment(scope));
22084
+ return unconfirmedTeardowns(scope);
22085
+ }
22086
+ /**
22087
+ * @internal Everything this scope cannot prove destroyed: its settled children whose teardown is
22088
+ * unconfirmed and, after a release, the retained owner environment that release could not
22089
+ * confirm. Read live, so a later retry that confirms a node removes it.
22090
+ */
22091
+ function unconfirmedTeardowns(scope) {
22092
+ return [...scope.workerCapacity.unconfirmed, ...ownerUnconfirmedByScope.get(scope) ?? []];
22093
+ }
22094
+ /** @internal Let the settlement retry reach the scope a recursive executor owns. */
22095
+ function registerNestedTeardownScope(executor, read) {
22096
+ nestedTeardownScopes.set(executor, read);
22097
+ }
22098
+ /**
22099
+ * @internal Ask each settled child whose teardown is still unconfirmed to tear down once more,
22100
+ * and resolve when every attempt has answered.
22101
+ *
22102
+ * A child's first teardown runs inside its settlement with a short acknowledgement window, and a
22103
+ * provider delete that fails once or answers late then leaves its sandbox running for good. This
22104
+ * is one retry pass; the supervisor paces passes with backoff inside a bounded window, and a
22105
+ * nested manager runs one pass over its own scope each time its teardown is asked again, so the
22106
+ * retry reaches every level of the tree.
22107
+ *
22108
+ * A retained-pending child is skipped: its executor answers `destroyed: false` by construction
22109
+ * while a resume may still reconcile it, and `releaseRetainedEnvironments` owns its release. An
22110
+ * attempt still in flight from an earlier pass is awaited, never duplicated. Never rejects.
22111
+ */
22112
+ async function retryUnconfirmedTeardowns(scope) {
22113
+ const retry = teardownRetriers.get(scope);
22114
+ if (retry) await retry();
22115
+ }
22116
+ /**
22117
+ * @internal Whether another retry can still change this scope's unconfirmed set. With `release`
22118
+ * the run releases retained environments at settlement, so a retained child or owner whose
22119
+ * release failed can still be released again; without it those are kept for a resume, and only
22120
+ * an ordinary unconfirmed teardown counts.
22121
+ */
22122
+ function hasRetriableTeardowns(scope, release) {
22123
+ return teardownRetriable.get(scope)?.(release) ?? false;
21719
22124
  }
21720
22125
  /**
21721
22126
  * @internal Close this scope to NEW children. Idempotent, synchronous, and irreversible.
@@ -22100,6 +22505,9 @@ function createScope(args) {
22100
22505
  controller.abort(new RunCancellationReason("worker-handle", reason ?? "worker cancelled"));
22101
22506
  }
22102
22507
  };
22508
+ const askTeardown = singleFlightTeardown(executor, () => {
22509
+ live.teardownAttempts += 1;
22510
+ });
22103
22511
  const live = {
22104
22512
  id,
22105
22513
  status: "acquiring",
@@ -22129,8 +22537,12 @@ function createScope(args) {
22129
22537
  ...executor.cancel ? { requestCancel: executor.cancel.bind(executor) } : {},
22130
22538
  ...executor.releaseRetained ? {
22131
22539
  releaseRetained: executor.releaseRetained.bind(executor),
22132
- confirmTeardown: () => teardownExecutor(executor, "brutalKill", void 0, now)
22540
+ confirmTeardown: () => teardownExecutor(executor, "brutalKill", void 0, now, askTeardown)
22133
22541
  } : {},
22542
+ askTeardown,
22543
+ ...executor.heldEnvironments ? { readHeldEnvironments: executor.heldEnvironments.bind(executor) } : {},
22544
+ ...nestedTeardownScopes.has(executor) ? { readNestedScope: nestedTeardownScopes.get(executor) } : {},
22545
+ teardownAttempts: 0,
22134
22546
  abortChild: (reason) => controller.abort(reason)
22135
22547
  };
22136
22548
  const recordCancellation = () => {
@@ -22461,6 +22873,7 @@ function createScope(args) {
22461
22873
  delivered: false,
22462
22874
  executorDone: false,
22463
22875
  cleanupConfirmed: true,
22876
+ teardownAttempts: 0,
22464
22877
  executionBindings: [],
22465
22878
  startedAt: armedAt,
22466
22879
  lastActivityAt: now(),
@@ -22672,12 +23085,7 @@ function createScope(args) {
22672
23085
  return {
22673
23086
  live: liveWorkerCapacity.live,
22674
23087
  freeSlots: freeSlots(liveWorkerCapacity.live, liveWorkerCapacity.max),
22675
- unconfirmed: Object.freeze([...children.values()].filter((child) => isTerminalNodeStatus(child.status) && !child.cleanupConfirmed).map((child) => Object.freeze({
22676
- id: child.id,
22677
- label: child.label,
22678
- runtime: child.runtime,
22679
- status: child.status
22680
- })))
23088
+ unconfirmed: Object.freeze([...children.values()].filter((child) => isTerminalNodeStatus(child.status) && !child.cleanupConfirmed).map((child) => unconfirmedTeardownOf(child, releasingScopes.has(scope))))
22681
23089
  };
22682
23090
  }
22683
23091
  };
@@ -22741,18 +23149,55 @@ function createScope(args) {
22741
23149
  throw error;
22742
23150
  }
22743
23151
  });
23152
+ const retainedHeld = () => [...children.values()].filter((child) => isTerminalNodeStatus(child.status) && !child.cleanupConfirmed && (child.recoveryPending === true || child.ownedTreeRoot !== void 0) && child.teardownPermanent !== true && child.releaseRetained !== void 0 && child.confirmTeardown !== void 0);
23153
+ const retriableTeardowns = () => [...children.values()].filter((child) => {
23154
+ if (!isTerminalNodeStatus(child.status) || child.cleanupConfirmed || child.recoveryPending === true || child.teardownPermanent === true || child.askTeardown === void 0) return false;
23155
+ const nested = child.readNestedScope?.();
23156
+ return nested === void 0 || unconfirmedTeardowns(nested).length === 0 || hasRetriableTeardowns(nested, false);
23157
+ });
23158
+ const releasable = () => retainedHeld().filter((child) => {
23159
+ const nested = child.readNestedScope?.();
23160
+ return child.ownedTreeRoot === void 0 || nested === void 0 || hasRetriableTeardowns(nested, true);
23161
+ });
23162
+ teardownRetriable.set(scope, (release) => retriableTeardowns().length > 0 || release && (releasable().length > 0 || retainedOwnerReleaseRetriable(scope)));
23163
+ teardownRetriers.set(scope, async () => {
23164
+ await Promise.all(retriableTeardowns().map((child) => {
23165
+ child.teardownRetry ??= (async () => {
23166
+ try {
23167
+ const nested = child.readNestedScope?.();
23168
+ if (nested !== void 0) await retryUnconfirmedTeardowns(nested);
23169
+ const receipt = await child.askTeardown("brutalKill");
23170
+ if (receipt.destroyed) {
23171
+ child.cleanupConfirmed = true;
23172
+ child.teardownDetail = void 0;
23173
+ } else {
23174
+ child.teardownDetail = `executor teardown reported destroyed=false${receipt.detail ? `: ${receipt.detail}` : ""}`;
23175
+ if (receipt.permanent === true) child.teardownPermanent = true;
23176
+ }
23177
+ } catch (error) {
23178
+ child.teardownDetail = errMessage(error);
23179
+ } finally {
23180
+ child.teardownRetry = void 0;
23181
+ }
23182
+ })();
23183
+ return child.teardownRetry;
23184
+ }));
23185
+ });
22744
23186
  retainedReleasers.set(scope, async () => {
22745
- const held = [...children.values()].filter((child) => isTerminalNodeStatus(child.status) && !child.cleanupConfirmed && (child.recoveryPending === true || child.ownedTreeRoot !== void 0) && child.releaseRetained !== void 0 && child.confirmTeardown !== void 0);
23187
+ const held = retainedHeld();
22746
23188
  const released = await Promise.all(held.map(async (child) => {
22747
23189
  const bound = new AbortController();
22748
23190
  const timer = setTimeout(() => bound.abort(new ValidationError$1(`retained release did not acknowledge within ${RETAINED_RELEASE_TIMEOUT_MS}ms`)), RETAINED_RELEASE_TIMEOUT_MS);
22749
23191
  timer.unref?.();
22750
23192
  try {
22751
23193
  const receipts = await child.releaseRetained(bound.signal);
23194
+ if (receipts.some((receipt) => !receipt.destroyed && receipt.permanent === true)) child.teardownPermanent = true;
22752
23195
  if (receipts.every((receipt) => receipt.destroyed)) try {
22753
23196
  await child.confirmTeardown();
22754
23197
  child.cleanupConfirmed = true;
22755
- } catch {}
23198
+ } catch {
23199
+ if (receipts.length === 0 && child.ownedTreeRoot === void 0) child.teardownPermanent = true;
23200
+ }
22756
23201
  return {
22757
23202
  child,
22758
23203
  receipts
@@ -23344,10 +23789,11 @@ async function runChild(live, executor, childAbort, task, opts, pool, ticket, bl
23344
23789
  if (teardownStarted) return;
23345
23790
  teardownStarted = true;
23346
23791
  try {
23347
- await teardownExecutor(executor, grace, deadlineAtMs, now);
23792
+ await teardownExecutor(executor, grace, deadlineAtMs, now, live.askTeardown);
23348
23793
  live.cleanupConfirmed = true;
23349
23794
  } catch (error) {
23350
23795
  teardownFailure = error;
23796
+ live.teardownDetail = errMessage(error);
23351
23797
  throw error;
23352
23798
  }
23353
23799
  };
@@ -23944,16 +24390,14 @@ const driverExecutorFactory = (rawSpec, ctx) => {
23944
24390
  let recovering = false;
23945
24391
  let previouslyMetered = zeroSpend();
23946
24392
  let cleanupFailure;
23947
- let unconfirmedDescendants = [];
23948
24393
  let active;
23949
24394
  let nestedScopeHeld;
24395
+ const unconfirmedDescendants = () => nestedScopeHeld === void 0 ? [] : unconfirmedTeardowns(nestedScopeHeld);
23950
24396
  const closeActive = (reason) => {
23951
24397
  if (active === void 0) return Promise.resolve();
23952
24398
  if (!active.close) {
23953
24399
  const { scope, controller } = active;
23954
- active.close = closeNestedScope(scope, controller, reason).then(() => {
23955
- unconfirmedDescendants = scope.workerCapacity.unconfirmed.map((node) => node.id);
23956
- }, (error) => {
24400
+ active.close = closeNestedScope(scope, controller, reason).then(() => void 0, (error) => {
23957
24401
  cleanupFailure = error;
23958
24402
  throw error;
23959
24403
  });
@@ -24051,14 +24495,18 @@ const driverExecutorFactory = (rawSpec, ctx) => {
24051
24495
  async teardown() {
24052
24496
  await closeActive("driver executor teardown");
24053
24497
  if (cleanupFailure !== void 0) throw cleanupFailure;
24054
- return unconfirmedDescendants.length > 0 ? {
24498
+ const unconfirmed = unconfirmedDescendants();
24499
+ return unconfirmed.length > 0 ? {
24055
24500
  destroyed: false,
24056
- detail: `Nested executor cleanup is unconfirmed: ${unconfirmedDescendants.join(", ")}`
24501
+ detail: `Nested executor cleanup is unconfirmed: ${unconfirmed.map((node) => node.id).join(", ")}`
24057
24502
  } : { destroyed: true };
24058
24503
  },
24504
+ heldEnvironments() {
24505
+ return unconfirmedDescendants().flatMap((node) => [...node.environments ?? [], ...node.kept ?? []]);
24506
+ },
24059
24507
  async releaseRetained() {
24060
24508
  if (nestedScopeHeld === void 0) return [];
24061
- unconfirmedDescendants = (await releaseRetainedEnvironments(nestedScopeHeld)).map((node) => node.id);
24509
+ await releaseRetainedEnvironments(nestedScopeHeld);
24062
24510
  return [];
24063
24511
  },
24064
24512
  resultArtifact() {
@@ -24066,6 +24514,7 @@ const driverExecutorFactory = (rawSpec, ctx) => {
24066
24514
  return artifact;
24067
24515
  }
24068
24516
  };
24517
+ registerNestedTeardownScope(executor, () => nestedScopeHeld);
24069
24518
  const treeOwner = attestNestedDriverTreeOwner(executor);
24070
24519
  const ownerRuntime = runtimeOwnedScopeOwnerRuntime(driver);
24071
24520
  return ownerRuntime === void 0 ? treeOwner : attestRuntimeOwnedDeferredExecutor(treeOwner, ownerRuntime);
@@ -24711,8 +25160,10 @@ async function runFinalizer(finalizer, args) {
24711
25160
  * - Join barrier: when `act()` settles (resolve OR reject), every still-live child is
24712
25161
  * torn down before `run` returns — the generalization of the kernel's
24713
25162
  * `finally{ Promise.allSettled(destroy) }` barrier (run-loop.ts) from boxes to the
24714
- * whole sub-tree. A teardown failure is `allSettled`'d and journaled per node as a
24715
- * `teardown-unconfirmed` event; it NEVER masks act()'s own outcome. act()'s rejection is the
25163
+ * whole sub-tree. An unconfirmed teardown is retried with backoff for `teardownConfirmMs`.
25164
+ * Each node pending when the window opens is journaled first as `teardown-pending`, then as
25165
+ * `teardown-confirmed` or, still unconfirmed when the window closes, `teardown-unconfirmed`
25166
+ * naming its provider environments; it NEVER masks act()'s own outcome. act()'s rejection is the
24716
25167
  * PRIMARY error (the kernel's firstError precedence), so a teardown throw during the
24717
25168
  * barrier can never overwrite the real failure.
24718
25169
  * - Abort cascade: a root abort (caller signal, `RootHandle.abort`, a tripped breaker,
@@ -24861,7 +25312,7 @@ function describeRejection(error) {
24861
25312
  function createSupervisor() {
24862
25313
  let attached;
24863
25314
  async function run(root, task, opts) {
24864
- const { budget, rootIdentity, rootMaterialization, runId, journal: journalStore, blobs: blobStore, executors: executorRegistry, recoverExecutor, probes, maxDepth, maxLiveWorkers, maxRestarts, withinMs, childSettleGraceMs, resume, retainedAtSettlement: requestedRetainedAtSettlement, ownerWorkspaceRetention, now: suppliedNow, signal, hooks, workerTrace, workerTraceUnpropagated, interactiveBindingDir } = opts;
25315
+ const { budget, rootIdentity, rootMaterialization, runId, journal: journalStore, blobs: blobStore, executors: executorRegistry, recoverExecutor, probes, maxDepth, maxLiveWorkers, maxRestarts, withinMs, childSettleGraceMs, teardownConfirmMs, resume, retainedAtSettlement: requestedRetainedAtSettlement, ownerWorkspaceRetention, now: suppliedNow, signal, hooks, workerTrace, workerTraceUnpropagated, interactiveBindingDir } = opts;
24865
25316
  const input = detachedSnapshot({
24866
25317
  task,
24867
25318
  options: {
@@ -24874,12 +25325,14 @@ function createSupervisor() {
24874
25325
  ...maxRestarts === void 0 ? {} : { maxRestarts },
24875
25326
  ...withinMs === void 0 ? {} : { withinMs },
24876
25327
  ...childSettleGraceMs === void 0 ? {} : { childSettleGraceMs },
25328
+ ...teardownConfirmMs === void 0 ? {} : { teardownConfirmMs },
24877
25329
  ...resume === void 0 ? {} : { resume },
24878
25330
  ...requestedRetainedAtSettlement === void 0 ? {} : { retainedAtSettlement: requestedRetainedAtSettlement },
24879
25331
  ...ownerWorkspaceRetention === void 0 ? {} : { ownerWorkspaceRetention },
24880
25332
  ...interactiveBindingDir === void 0 ? {} : { interactiveBindingDir }
24881
25333
  }
24882
25334
  }, "supervisor.run");
25335
+ if (teardownConfirmMs !== void 0 && (typeof teardownConfirmMs !== "number" || !Number.isFinite(teardownConfirmMs) || teardownConfirmMs < 0)) throw new ValidationError$1(`supervisor: teardownConfirmMs must be a nonnegative finite number of milliseconds, got ${JSON.stringify(teardownConfirmMs)}`);
24883
25336
  if (requestedRetainedAtSettlement !== void 0 && requestedRetainedAtSettlement !== "release" && requestedRetainedAtSettlement !== "keep") throw new ValidationError$1(`supervisor: retainedAtSettlement must be 'release' or 'keep', got ${JSON.stringify(requestedRetainedAtSettlement)}`);
24884
25337
  opts = Object.freeze({
24885
25338
  ...input.options,
@@ -25051,12 +25504,31 @@ function createSupervisor() {
25051
25504
  try {
25052
25505
  teardownUnconfirmed = await drainLiveChildren(openScope, controller, settleGraceMs);
25053
25506
  if (retainedAtSettlement === "release") teardownUnconfirmed = await releaseRetainedEnvironments(openScope);
25507
+ const confirmWindowMs = opts.teardownConfirmMs ?? DEFAULT_TEARDOWN_CONFIRM_MS;
25508
+ const releasing = retainedAtSettlement === "release";
25509
+ if (teardownUnconfirmed.length > 0 && confirmWindowMs > 0 && hasRetriableTeardowns(openScope, releasing)) {
25510
+ const pending = teardownUnconfirmed;
25511
+ for (const node of pending) await opts.journal.appendEvent(opts.runId, {
25512
+ kind: "teardown-pending",
25513
+ ...unconfirmedRecord(node),
25514
+ seq: teardownSeq++,
25515
+ at: new Date(now()).toISOString()
25516
+ });
25517
+ teardownUnconfirmed = await confirmSettledTeardowns(openScope, confirmWindowMs, releasing);
25518
+ const still = new Set(teardownUnconfirmed.map((node) => node.id));
25519
+ for (const node of pending) {
25520
+ if (still.has(node.id)) continue;
25521
+ await opts.journal.appendEvent(opts.runId, {
25522
+ kind: "teardown-confirmed",
25523
+ id: node.id,
25524
+ seq: teardownSeq++,
25525
+ at: new Date(now()).toISOString()
25526
+ });
25527
+ }
25528
+ }
25054
25529
  for (const node of teardownUnconfirmed) await opts.journal.appendEvent(opts.runId, {
25055
25530
  kind: "teardown-unconfirmed",
25056
- id: node.id,
25057
- label: node.label,
25058
- runtime: node.runtime,
25059
- status: node.status,
25531
+ ...unconfirmedRecord(node),
25060
25532
  seq: teardownSeq++,
25061
25533
  at: new Date(now()).toISOString()
25062
25534
  });
@@ -25301,22 +25773,89 @@ async function drainLiveChildren(scope, controller, settleGraceMs = 0) {
25301
25773
  if (after.inFlight > 0 || after.waiting > 0) throw new RuntimeRunStateError(`supervisor: cleanup ended with ${after.inFlight} running, ${after.waiting} waiting, and ` + describeUnconfirmed(scope));
25302
25774
  return unconfirmedTeardowns(scope);
25303
25775
  }
25304
- /**
25305
- * The settled children whose executor teardown was never acknowledged.
25306
- *
25307
- * They still hold their capacity slot — the ledger stays poisoned, so replacement work can never
25308
- * exceed the physical live count — but every one of them has already reached a terminal state and
25309
- * journaled its work. That is evidence about an EXECUTOR, not a cause of run failure, so the
25310
- * barrier NAMES them and lets the run reach its real terminal state. Live work after the drain is
25311
- * a different fault and still fails loud.
25312
- */
25313
- function unconfirmedTeardowns(scope) {
25314
- return scope.workerCapacity.unconfirmed;
25776
+ /** Five minutes: long enough to outlast a provider's transient delete failures and a slow
25777
+ * acknowledgement, short enough that a cancelled run still settles promptly. */
25778
+ const DEFAULT_TEARDOWN_CONFIRM_MS = 3e5;
25779
+ /** The fields a `teardown-pending` or `teardown-unconfirmed` record carries for one node. */
25780
+ function unconfirmedRecord(node) {
25781
+ return {
25782
+ id: node.id,
25783
+ label: node.label,
25784
+ runtime: node.runtime,
25785
+ status: node.status,
25786
+ ...node.environments === void 0 ? {} : { environments: node.environments },
25787
+ ...node.kept === void 0 ? {} : { kept: node.kept },
25788
+ ...node.attempts === void 0 ? {} : { attempts: node.attempts },
25789
+ ...node.detail === void 0 ? {} : { detail: node.detail }
25790
+ };
25791
+ }
25792
+ /**
25793
+ * Retry every unconfirmed teardown in the settled tree until each executor confirms destruction
25794
+ * or `windowMs` passes, and return what is still unconfirmed.
25795
+ *
25796
+ * Settled children are evidence about an EXECUTOR, not a cause of run failure, so the barrier
25797
+ * never fails the run over them; it asks again and then NAMES what it could not confirm. Backoff
25798
+ * starts at 1/300 of the window and doubles up to 1/10 of it, so the default window gives about
25799
+ * fourteen attempts. A request still running is awaited by later passes and never sent twice,
25800
+ * including a settlement request that missed its acknowledgement window, and it never holds up
25801
+ * another child's retry. Under `release`, a retained environment whose release
25802
+ * failed is released again; otherwise it is kept for a resume and not retried. The window is wall
25803
+ * clock, like the timers that pace it, so an injected `now` cannot stall it.
25804
+ */
25805
+ async function confirmSettledTeardowns(scope, windowMs, release) {
25806
+ const closesAt = Date.now() + windowMs;
25807
+ const maxDelayMs = windowMs / 10;
25808
+ let delayMs = windowMs / 300;
25809
+ let releasing;
25810
+ let failure;
25811
+ while (failure === void 0 && hasRetriableTeardowns(scope, release)) {
25812
+ if (closesAt - Date.now() <= 0) break;
25813
+ await pause(Math.min(delayMs, closesAt - Date.now()));
25814
+ delayMs = Math.min(delayMs * 2, maxDelayMs);
25815
+ if (release && releasing === void 0) releasing = releaseRetainedEnvironments(scope).finally(() => {
25816
+ releasing = void 0;
25817
+ });
25818
+ const pass = Promise.all([releasing, retryUnconfirmedTeardowns(scope)]).catch((error) => {
25819
+ failure ??= { error };
25820
+ });
25821
+ const answerWindow = pausable(Math.min(delayMs, Math.max(0, closesAt - Date.now())));
25822
+ await Promise.race([pass, answerWindow.elapsed]);
25823
+ answerWindow.cancel();
25824
+ }
25825
+ const inFlight = releasing;
25826
+ if (inFlight !== void 0) await inFlight.catch((error) => {
25827
+ failure ??= { error };
25828
+ });
25829
+ if (failure !== void 0) throw failure.error;
25830
+ return unconfirmedTeardowns(scope);
25831
+ }
25832
+ /** A wall-clock wait that keeps the process alive until it ends. */
25833
+ function pause(ms) {
25834
+ return pausable(ms).elapsed;
25835
+ }
25836
+ /** A wall-clock wait that can be cancelled, so a wait that lost a race holds no timer open. */
25837
+ function pausable(ms) {
25838
+ if (ms <= 0) return {
25839
+ elapsed: Promise.resolve(),
25840
+ cancel: () => {}
25841
+ };
25842
+ let cancel = () => {};
25843
+ return {
25844
+ elapsed: new Promise((resolve) => {
25845
+ cancel = armDeadlineTimer(ms, resolve, true);
25846
+ }),
25847
+ cancel
25848
+ };
25315
25849
  }
25316
25850
  /** The unconfirmed set as one error clause: the count plus the node ids behind it. One integer is
25317
25851
  * not actionable after a six-hour run. */
25318
25852
  function describeUnconfirmed(scope) {
25319
- const named = scope.workerCapacity.unconfirmed.map((node) => `${node.id} (${node.label}, ${node.runtime}, ${node.status})`).join(", ");
25853
+ const named = scope.workerCapacity.unconfirmed.map((node) => `${node.id} (${[
25854
+ node.label,
25855
+ node.runtime,
25856
+ node.status,
25857
+ ...(node.environments ?? []).map((environment) => `${environment.provider}:${environment.environmentId}`)
25858
+ ].join(", ")})`).join(", ");
25320
25859
  return `${scope.workerCapacity.live} executor resource(s) not confirmed destroyed${named.length > 0 ? `: ${named}` : ""}`;
25321
25860
  }
25322
25861
  /** The settle window a driver's children actually get: the caller's grace, never past an explicit
@@ -25491,6 +26030,6 @@ function isNonEmptySpend(s) {
25491
26030
  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);
25492
26031
  }
25493
26032
  //#endregion
25494
- export { startRetainedInteractiveRun as $, withBudgetResources as $i, contentAddress as $n, writeAllBytes as $r, isPeerMailEnvelope as $t, validateWaitSpec as A, mapSandboxEvent as Ai, providerAsSandboxClient as An, localHarnessExecutable as Ar, workerTraceAnalysisStore as At, SPAWN_RESOURCE_PATH_MAX_BYTES as B, hasCompleteCacheBreakdown as Bi, startRetainedRun as Bn, promptControlProfileMaterialization as Br, workerTraceEnv as Bt, restoreScopeOwnerAcceptedExecution as C, readSandboxOutcome as Ci, routerBrain as Cn, runWorktreeHarness as Cr, materializeTreeView as Ct, isWaitOutcome as D, createSandboxUsageLedger as Di, DEFAULT_SANDBOX_IDLE_TIMEOUT_SECONDS as Dn, DEFAULT_LOCAL_HARNESS as Dr, captureWorkerTraceEvidence as Dt, createWaitProbes as E, createSandboxToolPartState as Ei, observedModelMatchesDeclared as En, removeWorktree as Er, WORKER_TOOL_TRACE_SCHEMA_VERSION as Et, prepareScopeRetainedOwnerTask as F, sumSandboxUsage as Fi, sandboxSessionTraceSource as Fn, assertProfileMaterialization as Fr, newUsageTotals as Ft, readWorkerInteractiveAdmissions as G, stringifySafe as Gi, linkAbort as Gn, renderUnsupported as Gr, createActivityLog as Gt, hostDirectoryReader as H, promptCacheTokenClasses as Hi, retainedCreateMaterial as Hn, promptOnlyProfileMaterialization as Hr, workerTraceSeamKey as Ht, scopeRetainedOwnerContext as I, addSpend as Ii, registerRetainedExecutorPreparation as In, controlProfileMaterialization as Ir, spendFromUsageEvents as It, readWorkerInteractiveBinding as J, unmeteredSpend as Ji, defaultRedactorIdentityMaterial as Jn, validateProfileMaterialization as Jr, AUTHORITY_MARKERS as Jt, workerInteractiveAdmissionFile as K, throwAbort as Ki, runAbortable as Kn, sandboxActProfileMaterialization as Kr, readWorkerProgress as Kt, scopeRetainedOwnerPriorSpend as L, chargedTokens as Li, retainedExecutorSeamKey as Ln, defineProfileMaterializationContract as Lr, spendFromUsageTotals as Lt, bindScopeRetainedOwnerEnvironmentId as M, notifySandboxEventObserver as Mi, sandboxClientAsProvider as Mn, CodexExecutionDiagnosticError as Mr, assertValidBudget as Mt, bindScopeRetainedOwnerProvider as N, sandboxEventServedBackend as Ni, createPushTraceSource as Nn, terminateProcessTreeAndConfirm as Nr, createBudgetPool as Nt, pollFor as O, extractLlmCallEvent as Oi, createAgentEnvironmentProviderRegistry as On, LOCAL_HARNESSES as Or, isTraceAnalysisStore as Ot, consumeScopeRetainedOwnerResult as P, sandboxProgressEvents as Pi, decodeToolPart as Pn, AGENT_PROFILE_MATERIALIZATION_AXES as Pr, meterUsageEvent as Pt, recoverRetainedInteractiveRun as Q, resourceTelemetry as Qi, persistHarnessTranscript as Qn, readCommittedJsonLines as Qr, createPeerMailbox as Qt, scopeRetainedOwnerResourceReader as R, cloneSpend as Ri, reconnectRetainedRun as Rn, fullProfileMaterialization as Rr, WORKER_TRACE_PROPAGATION as Rt, recordScopeOwnerMaterialization as S, projectSandboxOutcome as Si, readPromptOptions as Sn, runSettledCommand as Sr, loadSpawnForest as St, settledToIteration as T, canonicalStreamEventFromSandboxEvent as Ti, canonicalObservedModelParts as Tn, createWorktree as Tr, replaySpawnTree as Tt, resolveSpawnResourcePaths as U, randomSuffix as Ui, RunCancellationReason as Un, promptResourceProfileMaterialization as Ur, taskToPrompt as Ut, environmentReader as V, isAbortError$2 as Vi, startRetainedRunInEnvironment as Vn, promptModelProfileMaterialization as Vr, workerTraceHeaders as Vt, interactiveAdmissionSeamKey as W, sleep as Wi, abortError as Wn, renderProfileMaterializationIssues as Wr, DEFAULT_STALL_AFTER_MS as Wt, workerInteractiveBindingsDir as X, zeroSpend as Xi, captureHarnessTranscript as Xn, isNoEntError as Xr, PEER_MAIL_WIRE_KEY as Xt, workerInteractiveBindingFile as Y, withTimeout as Yi, resolveRedactor as Yn, worktreeCliProfileMaterialization as Yr, DEFAULT_PEER_MAIL_LIMITS as Yt, reconnectRetainedInteractiveRun as Z, addResourceSpend as Zi, harnessTranscriptArtifact as Zn, prepareJsonlAppend as Zr, claimsAuthority as Zt, beginScopeOwnerAttempt as _, unknownMaterializationReceipt as _i, runAgentRounds as _n, createRuntimeEventCollector as _r, FileResultBlobStore as _t, pickBestDelivered as a, teardownExecutor as aa, knownExecutionBindingReceipt as ai, bridgeAdmissionRefusal as an, buildLoopOtelSpans as ar, rollingDispatch as at, meterRuntimeOwnedAccounting as b, detachedFrozen as bi, acquireSandbox as bn, sanitizeKnowledgeReadinessReport as br, InMemorySpawnJournal as bt, DriverAttemptsExhaustedError as c, providerMessageText as ca, providerAttemptEvidence as ci, createCodexRolloutStoreReader as cn, createOpenInferenceFileExporter as cr, cliInPlaceExecutor as ct, defaultUnmetContractSteer as d, runtimeOwnedExecutorExecutionBinding as di, bridgeRuntimeAttachmentsKey as dn, flatOtelSpan as dr, createExecutorRegistry as dt, decodeHarnessUsage as ea, attestRuntimeOwnedPendingExecutor as ei, peerMailTools as en, createPropagatingTraceEmitter as er, destroyInteractiveEnvironment as et, runDriverWithRetry as f, runtimeOwnedExecutorMaterialization as fi, bridgeStopSignalKey as fn, generateSpanId as fr, snapshotExecutorConfig as ft, withDriverExecutor as g, unknownExecutionBindingReceipt as gi, isTerminalDecision as gn, toOtelAttributes as gr, createInPlaceCliExecutor as gt, isDriverSpec as h, runtimeOwnedScopeOwnerRuntime as hi, defaultSelectWinner as hn, padTraceId as hr, createSteerableSandboxSession as ht, collectDelivered as i, armDeadlineTimer as ia, inheritRuntimeOwnedExecutorAttestation as ii, executorFailure as in, INTELLIGENCE_WIRE_VERSION as ir, queueOf as it, waitUntil as j, mapSandboxToolEvent as ji, resolveAgentEnvironmentProvider as jn, parseCodexTokenUsage as jr, BudgetReconcileFault as jt, timerAt as k, isSandboxTerminalEvent as ki, providerAsExecutor as kn, harnessSupportsReasoningEffort as kr, parseWorkerToolTraceArtifact as kt, HarnessTurnFailedError as l, recordRuntimeOwnedDriveHarnessProviderEvidence as li, harnessUsageIsEmpty as ln, createOtelExporter as lr, cliWorktreeExecutor as lt, driverExecutorFactory as m, runtimeOwnedPendingExecutorMaterialization as mi, createSandboxForSpec as mn, padSpanId as mr, DEFAULT_SANDBOX_STEERING_MAX_TURNS as mt, createSupervisor as n, awaitAbortable$1 as na, authoredProfileDigest as ni, isLiveNodeStatus as nn, readTraceContextFromEnv as nr, effectiveConcurrency as nt, runFinalizer as o, promptFromAgentTurnInput as oa, knownMaterializationReceipt as oi, bridgeModelRouteRefusal as on, buildLoopSpanNodes as or, bindReusableExecutorExecutionId as ot, driverChild as p, runtimeOwnedExecutorProviderEvidence as pi, TERMINAL_DECISIONS as pn, loopEventToOtelSpan as pr, createWorktreeCliExecutor as pt, attachWorker as q, throwIfAborted as qi, defaultRedactor as qn, unsupportedProfileDimensions as qr, createInbox as qt, bestDelivered as r, DEFAULT_SUCCESSFUL_SHUTDOWN_MS as ra, finalizeRuntimeOwnedPendingExecutor as ri, isTerminalNodeStatus as rn, traceContextToEnv as rr, freeSlots as rt, runTree as s, promptOptionsFromAgentTurnInput as sa, newExecutionAttemptId as si, addHarnessUsage as sn, buildRuntimeEventOtelSpans as sr, captureReusableExecutorConfig as st, createRootHandle as t, abortError$2 as ta, attestRuntimeOwnedScopeOwner as ti, peerMailVerbNames as tn, mergeTraceEnv as tr, errMessage as tt, classifyDriverFailure as u, runtimeOwnedDriveHarnessProviderEvidence as ui, readCodexRolloutSession as un, exportEvalRuns as ur, createExecutor as ut, createScope as v, executableAgentProfileSnapshot as vi, createSandboxLineage as vn, createRuntimeStreamEventCollector as vr, FileSpawnJournal as vt, scopeOwnerExecutorNodeContext as w, assertSandboxServedModel as wi, runBrainLoop as wn, captureWorktreeDiff as wr, pendingWaits as wt, meterRuntimeOwnedProviderAttempt as x, detachedSnapshot as xi, assertBoxlessPromptOptions as xn, sanitizeRuntimeStreamEvent as xr, insideCursorNamespace as xt, deriveNodeExecutionIdentity as y, executableAgentSpecSnapshot as yi, probeSandboxCapabilities as yn, sanitizeAgentRuntimeEvent as yr, InMemoryResultBlobStore as yt, scopeRetainedOwnerResult as z, deleteBoxSafe as zi, recoverRetainedRun as zn, profileMaterializationAxes$1 as zr, readWorkerTraceContext as zt };
26033
+ export { startRetainedInteractiveRun as $, resourceTelemetry as $i, persistHarnessTranscript as $n, readCommittedJsonLines as $r, peerMailTools as $t, validateWaitSpec as A, isSandboxTerminalEvent as Ai, resolveAgentEnvironmentProvider as An, harnessSupportsReasoningEffort as Ar, BudgetReconcileFault as At, SPAWN_RESOURCE_PATH_MAX_BYTES as B, deleteBoxSafe as Bi, startRetainedRunInEnvironment as Bn, profileMaterializationAxes$1 as Br, workerTraceHeaders as Bt, restoreScopeOwnerAcceptedExecution as C, projectSandboxOutcome as Ci, runBrainLoop as Cn, runSettledCommand as Cr, pendingWaits as Ct, isWaitOutcome as D, createSandboxToolPartState as Di, createAgentEnvironmentProviderRegistry as Dn, removeWorktree as Dr, isTraceAnalysisStore as Dt, createWaitProbes as E, canonicalStreamEventFromSandboxEvent as Ei, DEFAULT_SANDBOX_IDLE_TIMEOUT_SECONDS as En, createWorktree as Er, captureWorkerTraceEvidence as Et, prepareScopeRetainedOwnerTask as F, sandboxProgressEvents as Fi, registerRetainedExecutorPreparation as Fn, AGENT_PROFILE_MATERIALIZATION_AXES as Fr, spendFromUsageEvents as Ft, readWorkerInteractiveAdmissions as G, sleep as Gi, abortError as Gn, renderProfileMaterializationIssues as Gr, readWorkerProgress as Gt, hostDirectoryReader as H, isAbortError$2 as Hi, destroyInteractiveEnvironment as Hn, promptModelProfileMaterialization as Hr, taskToPrompt as Ht, scopeRetainedOwnerContext as I, sumSandboxUsage as Ii, retainedExecutorSeamKey as In, assertProfileMaterialization as Ir, spendFromUsageTotals as It, readWorkerInteractiveBinding as J, throwIfAborted as Ji, defaultRedactor as Jn, unsupportedProfileDimensions as Jr, DEFAULT_PEER_MAIL_LIMITS as Jt, workerInteractiveAdmissionFile as K, stringifySafe as Ki, linkAbort as Kn, renderUnsupported as Kr, createInbox as Kt, scopeRetainedOwnerPriorSpend as L, addSpend as Li, reconnectRetainedRun as Ln, controlProfileMaterialization as Lr, WORKER_TRACE_PROPAGATION as Lt, bindScopeRetainedOwnerEnvironmentId as M, mapSandboxToolEvent as Mi, createPushTraceSource as Mn, parseCodexTokenUsage as Mr, createBudgetPool as Mt, bindScopeRetainedOwnerProvider as N, notifySandboxEventObserver as Ni, decodeToolPart as Nn, CodexExecutionDiagnosticError as Nr, meterUsageEvent as Nt, pollFor as O, createSandboxUsageLedger as Oi, providerAsExecutor as On, DEFAULT_LOCAL_HARNESS as Or, parseWorkerToolTraceArtifact as Ot, consumeScopeRetainedOwnerResult as P, sandboxEventServedBackend as Pi, sandboxSessionTraceSource as Pn, terminateProcessTreeAndConfirm as Pr, newUsageTotals as Pt, recoverRetainedInteractiveRun as Q, addResourceSpend as Qi, harnessTranscriptArtifact as Qn, prepareJsonlAppend as Qr, isPeerMailEnvelope as Qt, scopeRetainedOwnerResourceReader as R, chargedTokens as Ri, recoverRetainedRun as Rn, defineProfileMaterializationContract as Rr, readWorkerTraceContext as Rt, recordScopeOwnerMaterialization as S, detachedSnapshot as Si, routerBrain as Sn, sanitizeRuntimeStreamEvent as Sr, materializeTreeView as St, settledToIteration as T, assertSandboxServedModel as Ti, observedModelMatchesDeclared as Tn, captureWorktreeDiff as Tr, WORKER_TOOL_TRACE_SCHEMA_VERSION as Tt, resolveSpawnResourcePaths as U, promptCacheTokenClasses as Ui, environmentGone as Un, promptOnlyProfileMaterialization as Ur, DEFAULT_STALL_AFTER_MS as Ut, environmentReader as V, hasCompleteCacheBreakdown as Vi, retainedCreateMaterial as Vn, promptControlProfileMaterialization as Vr, workerTraceSeamKey as Vt, interactiveAdmissionSeamKey as W, randomSuffix as Wi, RunCancellationReason as Wn, promptResourceProfileMaterialization as Wr, createActivityLog as Wt, workerInteractiveBindingsDir as X, withTimeout as Xi, resolveRedactor as Xn, worktreeCliProfileMaterialization as Xr, claimsAuthority as Xt, workerInteractiveBindingFile as Y, unmeteredSpend as Yi, defaultRedactorIdentityMaterial as Yn, validateProfileMaterialization as Yr, PEER_MAIL_WIRE_KEY as Yt, reconnectRetainedInteractiveRun as Z, zeroSpend as Zi, captureHarnessTranscript as Zn, isNoEntError as Zr, createPeerMailbox as Zt, beginScopeOwnerAttempt as _, unknownExecutionBindingReceipt as _i, createSandboxLineage as _n, toOtelAttributes as _r, FileSpawnJournal as _t, pickBestDelivered as a, armDeadlineTimer as aa, inheritRuntimeOwnedExecutorAttestation as ai, bridgeModelRouteRefusal as an, INTELLIGENCE_WIRE_VERSION as ar, bindReusableExecutorExecutionId as at, meterRuntimeOwnedAccounting as b, executableAgentSpecSnapshot as bi, assertBoxlessPromptOptions as bn, sanitizeAgentRuntimeEvent as br, insideCursorNamespace as bt, DriverAttemptsExhaustedError as c, promptFromAgentTurnInput as ca, newExecutionAttemptId as ci, harnessUsageIsEmpty as cn, buildRuntimeEventOtelSpans as cr, cliWorktreeExecutor as ct, defaultUnmetContractSteer as d, runtimeOwnedDriveHarnessProviderEvidence as di, bridgeStopSignalKey as dn, exportEvalRuns as dr, snapshotExecutorConfig as dt, withBudgetResources as ea, writeAllBytes as ei, peerMailVerbNames as en, contentAddress as er, errMessage as et, runDriverWithRetry as f, runtimeOwnedExecutorExecutionBinding as fi, TERMINAL_DECISIONS as fn, flatOtelSpan as fr, createWorktreeCliExecutor as ft, withDriverExecutor as g, runtimeOwnedScopeOwnerRuntime as gi, runAgentRounds as gn, padTraceId as gr, FileResultBlobStore as gt, isDriverSpec as h, runtimeOwnedPendingExecutorMaterialization as hi, isTerminalDecision as hn, padSpanId as hr, createInPlaceCliExecutor as ht, collectDelivered as i, DEFAULT_SUCCESSFUL_SHUTDOWN_MS as ia, finalizeRuntimeOwnedPendingExecutor as ii, bridgeAdmissionRefusal as in, traceContextToEnv as ir, rollingDispatch as it, waitUntil as j, mapSandboxEvent as ji, sandboxClientAsProvider as jn, localHarnessExecutable as jr, assertValidBudget as jt, timerAt as k, extractLlmCallEvent as ki, providerAsSandboxClient as kn, LOCAL_HARNESSES as kr, workerTraceAnalysisStore as kt, HarnessTurnFailedError as l, promptOptionsFromAgentTurnInput as la, providerAttemptEvidence as li, readCodexRolloutSession as ln, createOpenInferenceFileExporter as lr, createExecutor as lt, driverExecutorFactory as m, runtimeOwnedExecutorProviderEvidence as mi, defaultSelectWinner as mn, loopEventToOtelSpan as mr, createSteerableSandboxSession as mt, createSupervisor as n, abortError$2 as na, attestRuntimeOwnedScopeOwner as ni, isTerminalNodeStatus as nn, mergeTraceEnv as nr, freeSlots as nt, runFinalizer as o, teardownExecutor as oa, knownExecutionBindingReceipt as oi, addHarnessUsage as on, buildLoopOtelSpans as or, captureReusableExecutorConfig as ot, driverChild as p, runtimeOwnedExecutorMaterialization as pi, createSandboxForSpec as pn, generateSpanId as pr, DEFAULT_SANDBOX_STEERING_MAX_TURNS as pt, attachWorker as q, throwAbort as qi, runAbortable as qn, sandboxActProfileMaterialization as qr, AUTHORITY_MARKERS as qt, bestDelivered as r, awaitAbortable$1 as ra, authoredProfileDigest as ri, executorFailure as rn, readTraceContextFromEnv as rr, queueOf as rt, runTree as s, teardownSurfaces as sa, knownMaterializationReceipt as si, createCodexRolloutStoreReader as sn, buildLoopSpanNodes as sr, cliInPlaceExecutor as st, createRootHandle as t, decodeHarnessUsage as ta, attestRuntimeOwnedPendingExecutor as ti, isLiveNodeStatus as tn, createPropagatingTraceEmitter as tr, effectiveConcurrency as tt, classifyDriverFailure as u, providerMessageText as ua, recordRuntimeOwnedDriveHarnessProviderEvidence as ui, bridgeRuntimeAttachmentsKey as un, createOtelExporter as ur, createExecutorRegistry as ut, createScope as v, unknownMaterializationReceipt as vi, probeSandboxCapabilities as vn, createRuntimeEventCollector as vr, InMemoryResultBlobStore as vt, scopeOwnerExecutorNodeContext as w, readSandboxOutcome as wi, canonicalObservedModelParts as wn, runWorktreeHarness as wr, replaySpawnTree as wt, meterRuntimeOwnedProviderAttempt as x, detachedFrozen as xi, readPromptOptions as xn, sanitizeKnowledgeReadinessReport as xr, loadSpawnForest as xt, deriveNodeExecutionIdentity as y, executableAgentProfileSnapshot as yi, acquireSandbox as yn, createRuntimeStreamEventCollector as yr, InMemorySpawnJournal as yt, scopeRetainedOwnerResult as z, cloneSpend as zi, startRetainedRun as zn, fullProfileMaterialization as zr, workerTraceEnv as zt };
25495
26034
 
25496
- //# sourceMappingURL=supervisor-BlDW3u0y.js.map
26035
+ //# sourceMappingURL=supervisor-CJyzUjc7.js.map