@caupulican/pi-adaptative 0.85.8 → 0.86.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/core/agent-paths.d.ts +6 -3
  3. package/dist/core/agent-paths.d.ts.map +1 -1
  4. package/dist/core/agent-paths.js +10 -3
  5. package/dist/core/agent-paths.js.map +1 -1
  6. package/dist/core/agent-session.d.ts +5 -2
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +7 -1
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
  11. package/dist/core/autonomy/bounded-completion.js +19 -8
  12. package/dist/core/autonomy/bounded-completion.js.map +1 -1
  13. package/dist/core/autonomy/lane-tool-surface.d.ts +11 -5
  14. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  15. package/dist/core/autonomy/lane-tool-surface.js +34 -8
  16. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  17. package/dist/core/autonomy/subagent-prompt.d.ts +3 -3
  18. package/dist/core/autonomy/subagent-prompt.js +9 -9
  19. package/dist/core/autonomy/subagent-prompt.js.map +1 -1
  20. package/dist/core/background-lane-controller.d.ts +10 -8
  21. package/dist/core/background-lane-controller.d.ts.map +1 -1
  22. package/dist/core/background-lane-controller.js +23 -13
  23. package/dist/core/background-lane-controller.js.map +1 -1
  24. package/dist/core/bash-execution-controller.d.ts +4 -0
  25. package/dist/core/bash-execution-controller.d.ts.map +1 -1
  26. package/dist/core/bash-execution-controller.js +11 -4
  27. package/dist/core/bash-execution-controller.js.map +1 -1
  28. package/dist/core/bash-executor.d.ts +2 -0
  29. package/dist/core/bash-executor.d.ts.map +1 -1
  30. package/dist/core/bash-executor.js +2 -1
  31. package/dist/core/bash-executor.js.map +1 -1
  32. package/dist/core/capability-contract.d.ts +1 -1
  33. package/dist/core/capability-contract.d.ts.map +1 -1
  34. package/dist/core/capability-contract.js +0 -1
  35. package/dist/core/capability-contract.js.map +1 -1
  36. package/dist/core/default-tool-surface.d.ts +1 -0
  37. package/dist/core/default-tool-surface.d.ts.map +1 -1
  38. package/dist/core/default-tool-surface.js +3 -2
  39. package/dist/core/default-tool-surface.js.map +1 -1
  40. package/dist/core/delegation/worker-agent-control-coordinator.d.ts +27 -8
  41. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
  42. package/dist/core/delegation/worker-agent-control-coordinator.js +191 -33
  43. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
  44. package/dist/core/delegation/worker-agent-control.d.ts +45 -6
  45. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
  46. package/dist/core/delegation/worker-agent-control.js +110 -13
  47. package/dist/core/delegation/worker-agent-control.js.map +1 -1
  48. package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
  49. package/dist/core/delegation/worker-attempt-executor.js +177 -158
  50. package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
  51. package/dist/core/delegation/worker-authority-resolver.d.ts +23 -0
  52. package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -0
  53. package/dist/core/delegation/worker-authority-resolver.js +128 -0
  54. package/dist/core/delegation/worker-authority-resolver.js.map +1 -0
  55. package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -1
  56. package/dist/core/delegation/worker-conversation-store.js +1 -1
  57. package/dist/core/delegation/worker-conversation-store.js.map +1 -1
  58. package/dist/core/delegation/worker-delegation-controller.d.ts +7 -1
  59. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  60. package/dist/core/delegation/worker-delegation-controller.js +260 -87
  61. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  62. package/dist/core/delegation/worker-delegation-request.d.ts +25 -4
  63. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
  64. package/dist/core/delegation/worker-delegation-request.js +90 -1
  65. package/dist/core/delegation/worker-delegation-request.js.map +1 -1
  66. package/dist/core/delegation/worker-execution-policy.d.ts +2 -0
  67. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
  68. package/dist/core/delegation/worker-execution-policy.js +22 -12
  69. package/dist/core/delegation/worker-execution-policy.js.map +1 -1
  70. package/dist/core/delegation/worker-lifecycle.d.ts +1 -0
  71. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
  72. package/dist/core/delegation/worker-lifecycle.js +4 -2
  73. package/dist/core/delegation/worker-lifecycle.js.map +1 -1
  74. package/dist/core/delegation/worker-profile-resolver.d.ts +0 -2
  75. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
  76. package/dist/core/delegation/worker-profile-resolver.js +8 -35
  77. package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
  78. package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
  79. package/dist/core/delegation/worker-recovery-coordinator.js +1 -0
  80. package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
  81. package/dist/core/delegation/worker-runner.d.ts +6 -1
  82. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  83. package/dist/core/delegation/worker-runner.js +20 -6
  84. package/dist/core/delegation/worker-runner.js.map +1 -1
  85. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts +47 -0
  86. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -0
  87. package/dist/core/delegation/worker-tree-budget-coordinator.js +210 -0
  88. package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -0
  89. package/dist/core/memory/providers/file-store.d.ts +2 -0
  90. package/dist/core/memory/providers/file-store.d.ts.map +1 -1
  91. package/dist/core/memory/providers/file-store.js +22 -20
  92. package/dist/core/memory/providers/file-store.js.map +1 -1
  93. package/dist/core/models/runtime-process.d.ts.map +1 -1
  94. package/dist/core/models/runtime-process.js +5 -18
  95. package/dist/core/models/runtime-process.js.map +1 -1
  96. package/dist/core/orchestration/bounded-string-array.d.ts +11 -0
  97. package/dist/core/orchestration/bounded-string-array.d.ts.map +1 -0
  98. package/dist/core/orchestration/bounded-string-array.js +17 -0
  99. package/dist/core/orchestration/bounded-string-array.js.map +1 -0
  100. package/dist/core/orchestration/capability-gateway.d.ts +16 -0
  101. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  102. package/dist/core/orchestration/capability-gateway.js +38 -0
  103. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  104. package/dist/core/orchestration/contracts.d.ts +11 -3
  105. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  106. package/dist/core/orchestration/contracts.js +0 -1
  107. package/dist/core/orchestration/contracts.js.map +1 -1
  108. package/dist/core/orchestration/delegation-ledger.d.ts +1 -0
  109. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
  110. package/dist/core/orchestration/delegation-ledger.js +3 -0
  111. package/dist/core/orchestration/delegation-ledger.js.map +1 -1
  112. package/dist/core/orchestration/event-store.d.ts +12 -10
  113. package/dist/core/orchestration/event-store.d.ts.map +1 -1
  114. package/dist/core/orchestration/event-store.js +94 -104
  115. package/dist/core/orchestration/event-store.js.map +1 -1
  116. package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
  117. package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
  118. package/dist/core/orchestration/lane-tool-manifests.js +4 -1
  119. package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
  120. package/dist/core/orchestration/policy-compiler.d.ts.map +1 -1
  121. package/dist/core/orchestration/policy-compiler.js +8 -9
  122. package/dist/core/orchestration/policy-compiler.js.map +1 -1
  123. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  124. package/dist/core/orchestration/profile-registry.js +4 -10
  125. package/dist/core/orchestration/profile-registry.js.map +1 -1
  126. package/dist/core/orchestration/task-runtime.d.ts +1 -0
  127. package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
  128. package/dist/core/orchestration/task-runtime.js +58 -3
  129. package/dist/core/orchestration/task-runtime.js.map +1 -1
  130. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
  131. package/dist/core/orchestration/worker-execution-contract.js +10 -17
  132. package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
  133. package/dist/core/risk-classifier.js +3 -3
  134. package/dist/core/risk-classifier.js.map +1 -1
  135. package/dist/core/runtime-builder.d.ts +4 -1
  136. package/dist/core/runtime-builder.d.ts.map +1 -1
  137. package/dist/core/runtime-builder.js +34 -15
  138. package/dist/core/runtime-builder.js.map +1 -1
  139. package/dist/core/secrets/bitwarden-credential-storage.d.ts +51 -0
  140. package/dist/core/secrets/bitwarden-credential-storage.d.ts.map +1 -0
  141. package/dist/core/secrets/bitwarden-credential-storage.js +345 -0
  142. package/dist/core/secrets/bitwarden-credential-storage.js.map +1 -0
  143. package/dist/core/secrets/credential-exposure-guard.d.ts +8 -4
  144. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
  145. package/dist/core/secrets/credential-exposure-guard.js +30 -31
  146. package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
  147. package/dist/core/secrets/credential-manager.d.ts +109 -0
  148. package/dist/core/secrets/credential-manager.d.ts.map +1 -0
  149. package/dist/core/secrets/credential-manager.js +384 -0
  150. package/dist/core/secrets/credential-manager.js.map +1 -0
  151. package/dist/core/secrets/credential-project.d.ts +4 -0
  152. package/dist/core/secrets/credential-project.d.ts.map +1 -0
  153. package/dist/core/secrets/credential-project.js +145 -0
  154. package/dist/core/secrets/credential-project.js.map +1 -0
  155. package/dist/core/secrets/secret-dotenv.d.ts +1 -1
  156. package/dist/core/secrets/secret-dotenv.js +1 -1
  157. package/dist/core/secrets/secret-dotenv.js.map +1 -1
  158. package/dist/core/settings-manager.d.ts +4 -2
  159. package/dist/core/settings-manager.d.ts.map +1 -1
  160. package/dist/core/settings-manager.js +9 -5
  161. package/dist/core/settings-manager.js.map +1 -1
  162. package/dist/core/slash-commands.d.ts.map +1 -1
  163. package/dist/core/slash-commands.js +1 -0
  164. package/dist/core/slash-commands.js.map +1 -1
  165. package/dist/core/system-prompt.js +1 -1
  166. package/dist/core/system-prompt.js.map +1 -1
  167. package/dist/core/tool-capability-policy.js +2 -2
  168. package/dist/core/tool-capability-policy.js.map +1 -1
  169. package/dist/core/tools/delegate.d.ts +29 -1
  170. package/dist/core/tools/delegate.d.ts.map +1 -1
  171. package/dist/core/tools/delegate.js +179 -28
  172. package/dist/core/tools/delegate.js.map +1 -1
  173. package/dist/core/tools/git-filter.d.ts +1 -0
  174. package/dist/core/tools/git-filter.d.ts.map +1 -1
  175. package/dist/core/tools/git-filter.js +1 -1
  176. package/dist/core/tools/git-filter.js.map +1 -1
  177. package/dist/core/tools/profile-writer.js +3 -3
  178. package/dist/core/tools/profile-writer.js.map +1 -1
  179. package/dist/core/tools/python.d.ts +2 -0
  180. package/dist/core/tools/python.d.ts.map +1 -1
  181. package/dist/core/tools/python.js +17 -12
  182. package/dist/core/tools/python.js.map +1 -1
  183. package/dist/core/tools/run-process.d.ts +2 -0
  184. package/dist/core/tools/run-process.d.ts.map +1 -1
  185. package/dist/core/tools/run-process.js +7 -3
  186. package/dist/core/tools/run-process.js.map +1 -1
  187. package/dist/core/tools/secret-store.d.ts +8 -18
  188. package/dist/core/tools/secret-store.d.ts.map +1 -1
  189. package/dist/core/tools/secret-store.js +83 -348
  190. package/dist/core/tools/secret-store.js.map +1 -1
  191. package/dist/index.d.ts +3 -1
  192. package/dist/index.d.ts.map +1 -1
  193. package/dist/index.js +3 -1
  194. package/dist/index.js.map +1 -1
  195. package/dist/migrations.d.ts.map +1 -1
  196. package/dist/migrations.js +38 -1
  197. package/dist/migrations.js.map +1 -1
  198. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  199. package/dist/modes/interactive/components/settings-selector.js +35 -14
  200. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  201. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  202. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  203. package/dist/modes/interactive/interactive-mode.js +26 -3
  204. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  205. package/dist/modes/interactive/secret-menu-controller.d.ts +21 -0
  206. package/dist/modes/interactive/secret-menu-controller.d.ts.map +1 -0
  207. package/dist/modes/interactive/secret-menu-controller.js +276 -0
  208. package/dist/modes/interactive/secret-menu-controller.js.map +1 -0
  209. package/dist/utils/tools-manager.d.ts +2 -1
  210. package/dist/utils/tools-manager.d.ts.map +1 -1
  211. package/dist/utils/tools-manager.js +43 -48
  212. package/dist/utils/tools-manager.js.map +1 -1
  213. package/dist/utils/zip-extractor.d.ts +8 -0
  214. package/dist/utils/zip-extractor.d.ts.map +1 -0
  215. package/dist/utils/zip-extractor.js +275 -0
  216. package/dist/utils/zip-extractor.js.map +1 -0
  217. package/docs/harness-architecture.md +34 -22
  218. package/docs/index.md +1 -1
  219. package/docs/resources.md +1 -1
  220. package/docs/settings.md +39 -103
  221. package/docs/usage.md +7 -5
  222. package/docs/worker-profiles.md +9 -7
  223. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  224. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  225. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  226. package/examples/extensions/sandbox/package-lock.json +2 -2
  227. package/examples/extensions/sandbox/package.json +1 -1
  228. package/examples/extensions/with-deps/package-lock.json +2 -2
  229. package/examples/extensions/with-deps/package.json +1 -1
  230. package/npm-shrinkwrap.json +12 -12
  231. package/package.json +4 -4
  232. package/dist/core/secrets/secret-vault-format.d.ts +0 -112
  233. package/dist/core/secrets/secret-vault-format.d.ts.map +0 -1
  234. package/dist/core/secrets/secret-vault-format.js +0 -396
  235. package/dist/core/secrets/secret-vault-format.js.map +0 -1
  236. package/dist/core/secrets/secret-vault.d.ts +0 -72
  237. package/dist/core/secrets/secret-vault.d.ts.map +0 -1
  238. package/dist/core/secrets/secret-vault.js +0 -663
  239. package/dist/core/secrets/secret-vault.js.map +0 -1
@@ -3,6 +3,7 @@ import { getPrivateLaneDeniedPaths } from "../autonomy/lane-private-paths.js";
3
3
  import { createLaneToolSurface } from "../autonomy/lane-tool-surface.js";
4
4
  import { appendLaneRecordSnapshot } from "../autonomy/session-lane-record.js";
5
5
  import { AUTONOMY_TELEMETRY_EVENT_TYPES } from "../autonomy/telemetry-events.js";
6
+ import { STABLE_SHELL_TOOL_NAME } from "../default-tool-surface.js";
6
7
  import { deriveModelCapabilityProfile } from "../model-capability.js";
7
8
  import { isLoopbackModelEndpoint } from "../models/model-endpoint.js";
8
9
  import { providerUsageFromAttemptUsage } from "../orchestration/attempt-usage.js";
@@ -10,10 +11,15 @@ import { SessionTaskProfileStore } from "../orchestration/session-task-profile-s
10
11
  import { TaskProfileWriter, } from "../orchestration/task-profile-writer.js";
11
12
  import { createWorkerExecutionContract, verifierWorkerExecutionContract, } from "../orchestration/worker-execution-contract.js";
12
13
  import { registerInFlightWork } from "../reload-blockers.js";
14
+ import { createDelegateToolDefinition } from "../tools/delegate.js";
15
+ import { disposePersistentShellSession } from "../tools/shell-session.js";
16
+ import { wrapToolDefinition } from "../tools/tool-definition-wrapper.js";
13
17
  import { applyWorkerActions } from "./worker-actions.js";
14
18
  import { WorkerAgentControlCoordinator } from "./worker-agent-control-coordinator.js";
15
19
  import { createWorkerAttemptExecutor } from "./worker-attempt-executor.js";
20
+ import { resolveWorkerAuthority } from "./worker-authority-resolver.js";
16
21
  import { WorkerConversationStore, } from "./worker-conversation-store.js";
22
+ import { parseWorkerDelegationAuthorityRequest } from "./worker-delegation-request.js";
17
23
  import { WorkerDispatchScheduler } from "./worker-dispatch-scheduler.js";
18
24
  import { buildWorkerExecutionPlan, compileWorkerExecutionGrant, narrowWorkerExecutionPlan, workerExecutionAuthorityFromPlan, } from "./worker-execution-policy.js";
19
25
  import { createLocalWorkerProcessOwnerId } from "./worker-process-owner.js";
@@ -22,6 +28,7 @@ import { WorkerRecoveryCoordinator } from "./worker-recovery-coordinator.js";
22
28
  import { selectWorkerResourcePointers } from "./worker-resource-catalog.js";
23
29
  import { materializeWorkerResourceBundle } from "./worker-resource-materializer.js";
24
30
  import { finalizeWorkerClaim } from "./worker-terminal-finalizer.js";
31
+ import { collectWorkerTreeBudgetSeeds, WorkerTreeBudgetCoordinator } from "./worker-tree-budget-coordinator.js";
25
32
  import { WorkerWriteReservationCoordinator } from "./worker-write-reservation-coordinator.js";
26
33
  export function isLocalExecutionModel(model) {
27
34
  if (model.provider === "ollama" || model.provider === "transformers" || model.provider === "llama-cpp") {
@@ -54,8 +61,11 @@ export class WorkerDelegationController {
54
61
  constructor(deps, notifications, lifecycle) {
55
62
  this.workerAbort = new AbortController();
56
63
  this.laneAbortControllers = new Map();
64
+ this.shellSessionKeys = new Set();
57
65
  this.publishedTerminalAttemptIds = new Set();
66
+ this.yieldedCapacityAttemptIds = new Set();
58
67
  this.conversations = new WorkerConversationStore();
68
+ this.treeBudgets = new WorkerTreeBudgetCoordinator();
59
69
  this.inFlightLedgers = new Map();
60
70
  this.deps = deps;
61
71
  this.notifications = notifications;
@@ -106,6 +116,7 @@ export class WorkerDelegationController {
106
116
  this.publishTerminalRecord(terminal);
107
117
  return terminal;
108
118
  },
119
+ yieldCapacity: (callerAgentId, targetAgentId) => this.yieldWorkerCapacity(callerAgentId, targetAgentId),
109
120
  });
110
121
  this.writeReservations = new WorkerWriteReservationCoordinator({
111
122
  agentDir: this.deps.getAgentDir(),
@@ -226,6 +237,9 @@ export class WorkerDelegationController {
226
237
  }
227
238
  this.scheduler.cancelQueued();
228
239
  this.writeReservations.dispose();
240
+ for (const shellSessionKey of this.shellSessionKeys)
241
+ disposePersistentShellSession(shellSessionKey);
242
+ this.shellSessionKeys.clear();
229
243
  }
230
244
  getWorkerLifecycle() {
231
245
  return this.lifecycle;
@@ -240,7 +254,6 @@ export class WorkerDelegationController {
240
254
  getResourceLoader: () => this.deps.getResourceLoader(),
241
255
  getModelRegistry: () => this.deps.getModelRegistry(),
242
256
  isModelExhausted: (model) => this.deps.isModelExhausted(model),
243
- getActiveOrchestrationProfile: () => this.deps.getActiveOrchestrationProfile?.(),
244
257
  getTaskProfileStore: () => this.getTaskProfileStore(),
245
258
  onDiagnostic: (message) => this.safeWarn(message),
246
259
  });
@@ -325,6 +338,23 @@ export class WorkerDelegationController {
325
338
  ? { ok: true, shipment: resolved.resolved }
326
339
  : { ok: false, skipReason: `independent_verifier_unavailable:${resolved.reason}` };
327
340
  }
341
+ hasExactRecursiveCycle(parentAgentId, instructions, profileId) {
342
+ const normalizedInstructions = instructions.trim();
343
+ const visited = new Set();
344
+ let current = this.lifecycle.getAgent(parentAgentId);
345
+ while (current) {
346
+ if (visited.has(current.agentId))
347
+ return true;
348
+ visited.add(current.agentId);
349
+ const attempt = this.lifecycle.getLatestAgentAttempt(current.agentId);
350
+ if (attempt?.dispatch.instructions.trim() === normalizedInstructions &&
351
+ attempt.dispatch.profileId === profileId) {
352
+ return true;
353
+ }
354
+ current = current.parentAgentId ? this.lifecycle.getAgent(current.parentAgentId) : undefined;
355
+ }
356
+ return false;
357
+ }
328
358
  /** Single admission contract shared by enqueue, scheduler revalidation, and execution. */
329
359
  resolveWorkerAdmission(request, pinnedContract) {
330
360
  if (this.deps.isDisposed())
@@ -337,16 +367,64 @@ export class WorkerDelegationController {
337
367
  const settings = this.deps.getSettingsManager().getWorkerDelegationSettings();
338
368
  if (!settings.enabled)
339
369
  return { ok: false, skipReason: "worker_delegation_disabled" };
370
+ const parentAgent = request.parentAgentId ? this.lifecycle.getAgent(request.parentAgentId) : undefined;
371
+ if (request.parentAgentId && !parentAgent) {
372
+ return { ok: false, skipReason: "orchestration_parent_agent_unknown" };
373
+ }
374
+ const parentAttempt = parentAgent ? this.lifecycle.getLatestAgentAttempt(parentAgent.agentId) : undefined;
375
+ const parentContract = parentAttempt?.dispatch.executionContract;
376
+ if (parentAgent && !parentContract) {
377
+ return { ok: false, skipReason: "orchestration_parent_authority_missing" };
378
+ }
340
379
  if (pinnedContract && request.profileId && request.profileId !== pinnedContract.worker.profile.profileId) {
341
380
  return { ok: false, skipReason: "orchestration_execution_contract_mismatch" };
342
381
  }
343
- const resolved = pinnedContract
344
- ? this.getWorkerProfileResolver().resolveContract(pinnedContract.worker)
345
- : this.resolveWorkerShipment(request, settings);
346
- if (!resolved.ok) {
347
- return { ok: false, skipReason: "skipReason" in resolved ? resolved.skipReason : resolved.reason };
382
+ let authority = request.authority;
383
+ if (!pinnedContract && authority) {
384
+ try {
385
+ authority = parseWorkerDelegationAuthorityRequest(authority);
386
+ }
387
+ catch (error) {
388
+ return {
389
+ ok: false,
390
+ skipReason: `orchestration_authority_invalid:${error instanceof Error ? error.message : String(error)}`,
391
+ };
392
+ }
393
+ }
394
+ let baseShipment;
395
+ if (pinnedContract) {
396
+ const pinned = this.getWorkerProfileResolver().resolveContract(pinnedContract.worker);
397
+ if (!pinned.ok)
398
+ return { ok: false, skipReason: pinned.reason };
399
+ baseShipment = pinned.resolved;
400
+ }
401
+ else if (!request.profileId && parentContract) {
402
+ const inherited = this.getWorkerProfileResolver().resolveContract(parentContract.worker);
403
+ if (!inherited.ok)
404
+ return { ok: false, skipReason: inherited.reason };
405
+ baseShipment = inherited.resolved;
406
+ }
407
+ else if (request.profileId || settings.orchestrationProfile) {
408
+ const configured = this.resolveWorkerShipment(request, settings);
409
+ if (!configured.ok)
410
+ return configured;
411
+ baseShipment = configured.shipment;
412
+ }
413
+ const adaptive = pinnedContract
414
+ ? { ok: true, shipment: baseShipment }
415
+ : resolveWorkerAuthority({
416
+ authority,
417
+ ...(baseShipment ? { base: baseShipment } : {}),
418
+ ...(this.deps.getModel() ? { foregroundModel: this.deps.getModel() } : {}),
419
+ modelRegistry: this.deps.getModelRegistry(),
420
+ isModelExhausted: (model) => this.deps.isModelExhausted(model),
421
+ });
422
+ if (!adaptive.ok)
423
+ return { ok: false, skipReason: adaptive.reason };
424
+ const shipment = adaptive.shipment;
425
+ if (parentAgent && this.hasExactRecursiveCycle(parentAgent.agentId, instructions, shipment.profile.profileId)) {
426
+ return { ok: false, skipReason: "recursive_delegation_cycle" };
348
427
  }
349
- const shipment = "shipment" in resolved ? resolved.shipment : resolved.resolved;
350
428
  if (request.verificationOfTaskId && shipment.profile.role !== "verifier") {
351
429
  return { ok: false, skipReason: "verification_profile_role_mismatch" };
352
430
  }
@@ -380,9 +458,10 @@ export class WorkerDelegationController {
380
458
  : shipment.resourcePointers.map((pointer) => pointer.id));
381
459
  if (!selectedResources.ok)
382
460
  return { ok: false, skipReason: selectedResources.reason };
383
- const currentExecutionPlan = this.buildWorkerExecutionPlan(shipment.profile, settings);
384
- const executionPlan = pinnedContract
385
- ? narrowWorkerExecutionPlan(pinnedContract.worker.authority, currentExecutionPlan)
461
+ const currentExecutionPlan = this.buildWorkerExecutionPlan(shipment.profile, settings, adaptive.requestedReadPaths, adaptive.requestedWritePaths);
462
+ const inheritedAuthority = pinnedContract?.worker.authority ?? parentContract?.worker.authority;
463
+ const executionPlan = inheritedAuthority
464
+ ? narrowWorkerExecutionPlan(inheritedAuthority, currentExecutionPlan)
386
465
  : currentExecutionPlan;
387
466
  const executionContract = pinnedContract ??
388
467
  createWorkerExecutionContract({
@@ -428,10 +507,37 @@ export class WorkerDelegationController {
428
507
  };
429
508
  }
430
509
  publishTerminalRecord(record) {
431
- const attemptId = this.lifecycle?.getActiveAttempt(record.laneId)?.attemptId;
510
+ const attempt = this.lifecycle?.getActiveAttempt(record.laneId);
511
+ const attemptId = attempt?.attemptId;
432
512
  if (attemptId && this.publishedTerminalAttemptIds.has(attemptId))
433
513
  return;
434
- this.recordTerminal(record);
514
+ const childAgentId = attempt?.agentId ?? attempt?.dispatch.logicalLaneId ?? record.laneId;
515
+ const parentAgentId = this.lifecycle.getAgent(childAgentId)?.parentAgentId ?? attempt?.dispatch.parentAgentId;
516
+ let handedOffToParent = false;
517
+ if (attemptId && parentAgentId) {
518
+ try {
519
+ this.agentControl.deliverWorkerTerminalHandoff({
520
+ parentAgentId,
521
+ childAgentId,
522
+ terminalAttemptId: attemptId,
523
+ record,
524
+ });
525
+ handedOffToParent = true;
526
+ }
527
+ catch (error) {
528
+ this.safeWarn(`Worker terminal handoff for ${record.laneId} failed: ${error instanceof Error ? error.message : String(error)}`);
529
+ }
530
+ }
531
+ if (handedOffToParent) {
532
+ const notification = this.lifecycle.getTerminalNotification(record.laneId);
533
+ if (notification?.status === "pending") {
534
+ this.lifecycle.markNotificationsDelivered([notification.notificationId]);
535
+ }
536
+ this.notifications.statusChanged();
537
+ }
538
+ else {
539
+ this.recordTerminal(record);
540
+ }
435
541
  appendLaneRecordSnapshot(this.deps.getSessionManager(), record);
436
542
  this.deps.emitAutonomyTelemetry({
437
543
  type: AUTONOMY_TELEMETRY_EVENT_TYPES.workerTerminal,
@@ -444,6 +550,7 @@ export class WorkerDelegationController {
444
550
  costUsd: record.costUsd ?? null,
445
551
  },
446
552
  });
553
+ this.agentControl.signalStateChanged();
447
554
  if (attemptId)
448
555
  this.publishedTerminalAttemptIds.add(attemptId);
449
556
  }
@@ -459,18 +566,44 @@ export class WorkerDelegationController {
459
566
  this.publishTerminalRecord(record);
460
567
  return record;
461
568
  }
462
- hasWorkerCapacity(settings, profile) {
463
- const lifecycle = this.getWorkerLifecycle();
464
- if (lifecycle.getRunningCount() >= settings.maxConcurrent)
465
- return false;
466
- return lifecycle.getRunningCount(profile.profileId) < profile.maxConcurrent;
569
+ hasWorkerCapacity(settings) {
570
+ const snapshot = this.getWorkerLifecycle().getTaskRuntimeSnapshot();
571
+ let yielded = 0;
572
+ for (const attemptId of [...this.yieldedCapacityAttemptIds]) {
573
+ const status = snapshot.attempts[attemptId]?.status;
574
+ if (status === "leased" || status === "running")
575
+ yielded += 1;
576
+ else
577
+ this.yieldedCapacityAttemptIds.delete(attemptId);
578
+ }
579
+ return Math.max(0, this.getWorkerLifecycle().getRunningCount() - yielded) < settings.maxConcurrent;
580
+ }
581
+ yieldWorkerCapacity(callerAgentId, targetAgentId) {
582
+ const caller = this.lifecycle.getAgent(callerAgentId);
583
+ const target = this.lifecycle.getAgent(targetAgentId);
584
+ if (!caller || !target || caller.rootAgentId !== target.rootAgentId)
585
+ return () => undefined;
586
+ const attempt = this.lifecycle.getLatestAgentAttempt(caller.agentId);
587
+ if (!attempt || (attempt.status !== "leased" && attempt.status !== "running"))
588
+ return () => undefined;
589
+ this.yieldedCapacityAttemptIds.add(attempt.attemptId);
590
+ this.scheduler.drain();
591
+ let released = false;
592
+ return () => {
593
+ if (released)
594
+ return;
595
+ released = true;
596
+ this.yieldedCapacityAttemptIds.delete(attempt.attemptId);
597
+ if (!this.deps.isDisposed())
598
+ this.scheduler.drain();
599
+ };
467
600
  }
468
601
  workerDispatchAdmission(request, record) {
469
602
  const contract = this.getWorkerLifecycle().getActiveAttempt(record.laneId)?.dispatch.executionContract;
470
603
  const admission = this.resolveWorkerAdmission(request, contract);
471
604
  if (!admission.ok)
472
605
  return { action: "cancel", reasonCode: admission.skipReason };
473
- if (!this.hasWorkerCapacity(admission.settings, admission.shipment.profile))
606
+ if (!this.hasWorkerCapacity(admission.settings))
474
607
  return { action: "wait", reason: "capacity" };
475
608
  const attempt = this.getWorkerLifecycle().getActiveAttempt(record.laneId);
476
609
  if (!attempt)
@@ -480,7 +613,7 @@ export class WorkerDelegationController {
480
613
  return { action: "cancel", reasonCode: reservation.reasonCode };
481
614
  return reservation.kind === "granted" ? { action: "start" } : { action: "wait", reason: "write_reservation" };
482
615
  }
483
- buildWorkerExecutionPlan(profile, settings) {
616
+ buildWorkerExecutionPlan(profile, settings, requestedReadPaths, requestedWritePaths) {
484
617
  return buildWorkerExecutionPlan({
485
618
  profile,
486
619
  settings,
@@ -488,6 +621,8 @@ export class WorkerDelegationController {
488
621
  deniedPaths: getPrivateLaneDeniedPaths(this.deps.getCwd(), this.deps.getAgentDir()),
489
622
  foregroundMaxCostUsd: this.deps.getCapabilityEnvelope()?.maxEstimatedUsd,
490
623
  memoryEnabled: this.deps.getSettingsManager().getMemoryRetrievalSettings().enabled,
624
+ ...(requestedReadPaths ? { requestedReadPaths } : {}),
625
+ ...(requestedWritePaths ? { requestedWritePaths } : {}),
491
626
  });
492
627
  }
493
628
  /** One durable preparation path for queued, immediate, and recovered execution. */
@@ -504,6 +639,7 @@ export class WorkerDelegationController {
504
639
  const goal = this.deps.getGoalStateSnapshot();
505
640
  const prepared = lifecycle.prepare({
506
641
  instructions: admission.instructions,
642
+ ...(request.parentAgentId ? { parentAgentId: request.parentAgentId } : {}),
507
643
  executionContract: admission.executionContract,
508
644
  requiredCapabilities: admission.executionPlan.requiredCapabilities,
509
645
  ...(request.verificationOfTaskId ? { verificationOfTaskId: request.verificationOfTaskId } : {}),
@@ -517,6 +653,57 @@ export class WorkerDelegationController {
517
653
  });
518
654
  return { executionPlan: admission.executionPlan, lifecycle, ...prepared };
519
655
  }
656
+ ensurePreparedAgent(prepared, admission) {
657
+ if (!prepared.attempt)
658
+ throw new Error("Prepared worker attempt is missing.");
659
+ const immutableWorker = prepared.attempt.dispatch.executionContract?.worker;
660
+ if (!immutableWorker)
661
+ throw new Error("Prepared worker execution contract is missing.");
662
+ const agentId = prepared.attempt.agentId ?? prepared.attempt.dispatch.logicalLaneId ?? prepared.record.laneId;
663
+ const existing = prepared.lifecycle.getAgent(agentId);
664
+ if (existing) {
665
+ const conversation = this.conversations.open({
666
+ agentDir: this.deps.getAgentDir(),
667
+ resumeContext: existing.resumeContext,
668
+ expectedLogicalAgentId: existing.agentId,
669
+ });
670
+ const materialized = materializeWorkerResourceBundle(existing.resumeContext.contextPointers);
671
+ if (!materialized.ok)
672
+ throw new Error(`worker_resource_materialization_${materialized.code}`);
673
+ return {
674
+ conversation,
675
+ resources: materialized.pointers,
676
+ resourceSystemPrompt: materialized.systemPrompt,
677
+ };
678
+ }
679
+ const selected = selectWorkerResourcePointers(immutableWorker.resourcePointers, admission.resourcePointerIds);
680
+ if (!selected.ok)
681
+ throw new Error(selected.reason);
682
+ const materialized = materializeWorkerResourceBundle(selected.pointers);
683
+ if (!materialized.ok)
684
+ throw new Error(`worker_resource_materialization_${materialized.code}`);
685
+ const conversation = this.conversations.ensure({
686
+ agentDir: this.deps.getAgentDir(),
687
+ parentSessionId: this.deps.getSessionId(),
688
+ logicalAgentId: agentId,
689
+ cwd: this.deps.getCwd(),
690
+ orchestrationProfileId: immutableWorker.profile.profileId,
691
+ modelRef: `${immutableWorker.modelBinding.provider}/${immutableWorker.modelBinding.modelId}`,
692
+ resourceProfileNames: immutableWorker.profile.resourceProfileNames,
693
+ contextPointers: materialized.pointers,
694
+ });
695
+ prepared.lifecycle.ensureAgent({
696
+ agentId,
697
+ ...(prepared.attempt.dispatch.parentAgentId ? { parentAgentId: prepared.attempt.dispatch.parentAgentId } : {}),
698
+ role: immutableWorker.profile.role,
699
+ resumeContext: conversation.getResumeContext(),
700
+ });
701
+ return {
702
+ conversation,
703
+ resources: materialized.pointers,
704
+ resourceSystemPrompt: materialized.systemPrompt,
705
+ };
706
+ }
520
707
  start(request) {
521
708
  return this.startInternal(request);
522
709
  }
@@ -529,21 +716,24 @@ export class WorkerDelegationController {
529
716
  const { settings, shipment } = admission;
530
717
  const foreground = this.deps.getModel();
531
718
  const contendsWithLocalForeground = foreground !== undefined && isLocalExecutionModel(foreground) && isLocalExecutionModel(shipment.model);
532
- if (contendsWithLocalForeground || !this.hasWorkerCapacity(settings, shipment.profile)) {
719
+ if (contendsWithLocalForeground || !this.hasWorkerCapacity(settings)) {
533
720
  // A mandatory verifier is the continuation of an already admitted implementation, not a
534
721
  // new owner request. Reserve its queue admission so a burst of ordinary work cannot strand
535
722
  // the subject behind `independent_verification_required` with no terminal handoff.
536
- if (this.scheduler.queuedCount >= 8 && !request.verificationOfTaskId) {
537
- return { started: false, skipReason: "worker_delegation_queue_full" };
538
- }
539
723
  let record;
540
724
  try {
541
- record = this.prepareWorkerAttempt(request, admission).record;
725
+ const prepared = this.prepareWorkerAttempt(request, admission);
726
+ record = prepared.record;
727
+ this.ensurePreparedAgent(prepared, admission);
542
728
  }
543
729
  catch (error) {
730
+ if (record)
731
+ this.cancelAndPublish(this.lifecycle, record.laneId, "worker_conversation_unavailable");
544
732
  this.safeWarn(`Worker dispatch was not persisted: ${error instanceof Error ? error.message : String(error)}`);
545
733
  return { started: false, skipReason: "orchestration_ledger_error" };
546
734
  }
735
+ if (!record)
736
+ return { started: false, skipReason: "orchestration_attempt_missing" };
547
737
  this.scheduler.enqueue(record, { ...request, profileId: shipment.profile.profileId }, false, request.verificationOfTaskId !== undefined);
548
738
  this.notifications.statusChanged();
549
739
  return { started: true, record };
@@ -575,7 +765,7 @@ export class WorkerDelegationController {
575
765
  this.recovery.recover();
576
766
  const { instructions, settings, verifierShipment } = admission;
577
767
  const { model, modelBinding, profile: orchestrationProfile, soul } = admission.shipment;
578
- if (!this.hasWorkerCapacity(settings, orchestrationProfile)) {
768
+ if (!this.hasWorkerCapacity(settings)) {
579
769
  return { started: false, skipReason: "worker_delegation_already_running" };
580
770
  }
581
771
  const laneCapability = this.laneCapabilityProfile(model);
@@ -584,42 +774,31 @@ export class WorkerDelegationController {
584
774
  const { executionPlan, lifecycle } = prepared;
585
775
  if (!prepared.attempt)
586
776
  return { started: false, skipReason: "orchestration_attempt_missing" };
777
+ let preparedAgent;
778
+ try {
779
+ preparedAgent = this.ensurePreparedAgent(prepared, admission);
780
+ }
781
+ catch (error) {
782
+ this.cancelAndPublish(lifecycle, prepared.record.laneId, "worker_conversation_unavailable");
783
+ this.safeWarn(`Worker conversation setup failed: ${error instanceof Error ? error.message : String(error)}`);
784
+ return { started: false, skipReason: "worker_conversation_unavailable" };
785
+ }
587
786
  const durableTask = lifecycle.getTask(prepared.record.laneId);
588
787
  if (!durableTask)
589
788
  return { started: false, skipReason: "orchestration_task_missing" };
590
789
  const immutableWorker = prepared.attempt.dispatch.executionContract?.worker;
591
790
  if (!immutableWorker)
592
791
  return { started: false, skipReason: "orchestration_execution_contract_missing" };
593
- const selectedResources = selectWorkerResourcePointers(immutableWorker.resourcePointers, prepared.attempt.dispatch.resourcePointerIds.length > 0
594
- ? prepared.attempt.dispatch.resourcePointerIds
595
- : admission.resourcePointerIds);
596
- if (!selectedResources.ok) {
597
- this.cancelAndPublish(lifecycle, prepared.record.laneId, selectedResources.reason);
598
- return { started: false, skipReason: selectedResources.reason };
599
- }
600
792
  let grant;
601
- let workerResourceSystemPrompt;
793
+ const workerResourceSystemPrompt = preparedAgent.resourceSystemPrompt;
602
794
  if (prepared.attempt.grant) {
603
- if (!this.recovery.durableGrantIsStillPermitted(prepared.attempt.grant, executionPlan, selectedResources.pointers)) {
795
+ if (!this.recovery.durableGrantIsStillPermitted(prepared.attempt.grant, executionPlan, preparedAgent.resources)) {
604
796
  this.cancelAndPublish(lifecycle, prepared.record.laneId, "recovered_grant_revoked");
605
797
  return { started: false, skipReason: "recovered_grant_revoked" };
606
798
  }
607
799
  grant = prepared.attempt.grant;
608
- const materialized = materializeWorkerResourceBundle(grant.resources);
609
- if (!materialized.ok) {
610
- const reason = `worker_resource_materialization_${materialized.code}`;
611
- this.cancelAndPublish(lifecycle, prepared.record.laneId, reason);
612
- return { started: false, skipReason: reason };
613
- }
614
- workerResourceSystemPrompt = materialized.systemPrompt;
615
800
  }
616
801
  else {
617
- const materialized = materializeWorkerResourceBundle(selectedResources.pointers);
618
- if (!materialized.ok) {
619
- const reason = `worker_resource_materialization_${materialized.code}`;
620
- this.cancelAndPublish(lifecycle, prepared.record.laneId, reason);
621
- return { started: false, skipReason: reason };
622
- }
623
802
  const compiled = compileWorkerExecutionGrant({
624
803
  target: {
625
804
  objectiveId: durableTask.task.objectiveId,
@@ -628,7 +807,7 @@ export class WorkerDelegationController {
628
807
  },
629
808
  profile: orchestrationProfile,
630
809
  plan: executionPlan,
631
- resources: materialized.pointers,
810
+ resources: preparedAgent.resources,
632
811
  });
633
812
  if (!compiled.ok) {
634
813
  this.cancelAndPublish(lifecycle, prepared.record.laneId, compiled.reasonCodes.join(","));
@@ -636,7 +815,6 @@ export class WorkerDelegationController {
636
815
  }
637
816
  lifecycle.bindGrant(prepared.attempt.attemptId, compiled.grant);
638
817
  grant = compiled.grant;
639
- workerResourceSystemPrompt = materialized.systemPrompt;
640
818
  }
641
819
  const immutableProfile = immutableWorker.profile;
642
820
  // Follow-up tasks deliberately receive unique task ids while retaining the original logical
@@ -647,44 +825,9 @@ export class WorkerDelegationController {
647
825
  this.cancelAndPublish(lifecycle, prepared.record.laneId, "orchestration_agent_missing");
648
826
  return { started: false, skipReason: "orchestration_agent_missing" };
649
827
  }
650
- let conversation;
651
- try {
652
- if (registeredAgent) {
653
- // Recovery must trust only the registered resume context; reconstructing one here could
654
- // silently redirect a logical worker to a different transcript or resource scope.
655
- conversation = this.conversations.open({
656
- agentDir: this.deps.getAgentDir(),
657
- resumeContext: registeredAgent.resumeContext,
658
- expectedLogicalAgentId: registeredAgent.agentId,
659
- });
660
- if (prepared.attempt.status === "suspended")
661
- this.recovery.repairInterruptedToolResults(conversation);
662
- }
663
- else {
664
- conversation = this.conversations.ensure({
665
- agentDir: this.deps.getAgentDir(),
666
- parentSessionId: this.deps.getSessionId(),
667
- logicalAgentId: agentId,
668
- cwd: this.deps.getCwd(),
669
- orchestrationProfileId: immutableProfile.profileId,
670
- modelRef: `${prepared.attempt.dispatch.executionContract.worker.modelBinding.provider}/${prepared.attempt.dispatch.executionContract.worker.modelBinding.modelId}`,
671
- resourceProfileNames: immutableProfile.resourceProfileNames,
672
- contextPointers: grant.resources,
673
- });
674
- lifecycle.ensureAgent({
675
- agentId,
676
- role: immutableProfile.role,
677
- resumeContext: conversation.getResumeContext(),
678
- });
679
- }
680
- }
681
- catch (error) {
682
- if (prepared.attempt.status !== "suspended") {
683
- this.cancelAndPublish(lifecycle, prepared.record.laneId, "worker_conversation_unavailable");
684
- }
685
- this.safeWarn(`Worker conversation setup failed: ${error instanceof Error ? error.message : String(error)}`);
686
- return { started: false, skipReason: "worker_conversation_unavailable" };
687
- }
828
+ const conversation = preparedAgent.conversation;
829
+ if (prepared.attempt.status === "suspended")
830
+ this.recovery.repairInterruptedToolResults(conversation);
688
831
  const reservation = this.writeReservations.acquire(prepared.record.laneId, prepared.attempt, executionPlan);
689
832
  if (reservation.kind === "denied") {
690
833
  this.cancelAndPublish(lifecycle, prepared.record.laneId, reservation.reasonCode);
@@ -727,6 +870,31 @@ export class WorkerDelegationController {
727
870
  onStarted?.(startedRecord);
728
871
  const maxUsd = grant.budget.maxCostUsd;
729
872
  const executionPolicy = orchestrationProfile.executionPolicy;
873
+ const recursiveDelegateTool = wrapToolDefinition(createDelegateToolDefinition({
874
+ startWorkerDelegation: (childRequest) => this.start({ ...childRequest, parentAgentId: agentId }),
875
+ runWorkerDelegation: (childRequest) => this.runOnce({ ...childRequest, parentAgentId: agentId }),
876
+ orchestrationProfiles: this.getProfileCatalog(),
877
+ workerAgentControl: this.agentControl,
878
+ callerAgentId: agentId,
879
+ }));
880
+ const agentBinding = lifecycle.getAgent(agentId);
881
+ if (!agentBinding) {
882
+ this.cancelAndPublish(lifecycle, prepared.record.laneId, "orchestration_agent_missing");
883
+ return { started: false, skipReason: "orchestration_agent_missing" };
884
+ }
885
+ const rootAttempt = lifecycle.getLatestAgentAttempt(agentBinding.rootAgentId);
886
+ const rootBudget = rootAttempt?.dispatch.executionContract?.worker.authority.budget ?? grant.budget;
887
+ const sharedBudget = this.treeBudgets.createPort({
888
+ rootAgentId: agentBinding.rootAgentId,
889
+ attemptId: durableHandle.attemptId,
890
+ budget: rootBudget,
891
+ seeds: collectWorkerTreeBudgetSeeds(lifecycle.getTaskRuntimeSnapshot(), agentBinding.rootAgentId),
892
+ initialUsage,
893
+ });
894
+ const shellGranted = executionPlan.toolManifests.some((manifest) => manifest.toolName === STABLE_SHELL_TOOL_NAME);
895
+ const shellSessionKey = shellGranted ? `worker:${this.deps.getSessionId()}:${agentId}` : undefined;
896
+ if (shellSessionKey)
897
+ this.shellSessionKeys.add(shellSessionKey);
730
898
  const toolSurface = createLaneToolSurface({
731
899
  cwd: this.deps.getCwd(),
732
900
  readMemory: executionPlan.readMemory ? (query) => this.deps.readMemoryForLane(query) : undefined,
@@ -734,9 +902,12 @@ export class WorkerDelegationController {
734
902
  writePaths: executionPlan.writePaths,
735
903
  ...(executionPlan.processEnabled && executionPolicy ? { executionPolicy } : {}),
736
904
  processMaxWallClockMs: grant.budget.maxWallClockMs ?? 0,
905
+ ...(shellSessionKey ? { shellSessionKey } : {}),
737
906
  grant,
738
907
  toolManifests: executionPlan.toolManifests,
908
+ additionalTools: [recursiveDelegateTool],
739
909
  initialUsage,
910
+ sharedBudget,
740
911
  });
741
912
  const writeGranted = executionPlan.writeEnabled &&
742
913
  toolSurface.gateway !== undefined &&
@@ -1010,6 +1181,8 @@ export class WorkerDelegationController {
1010
1181
  }
1011
1182
  this.agentControl.signalStateChanged();
1012
1183
  deregisterInFlight();
1184
+ if (!this.deps.isDisposed())
1185
+ this.scheduler.drain(true);
1013
1186
  }
1014
1187
  }
1015
1188
  /** Start every capacity-eligible queued worker at the owner session's foreground-idle boundary. */