@gajae-code/coding-agent 0.18.11 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (462) hide show
  1. package/CHANGELOG.md +760 -0
  2. package/dist/types/async/job-manager.d.ts +7 -3
  3. package/dist/types/async/result-formatting.d.ts +2 -0
  4. package/dist/types/autoresearch/git.d.ts +1 -1
  5. package/dist/types/capability/fs.d.ts +2 -2
  6. package/dist/types/capability/rule.d.ts +7 -2
  7. package/dist/types/cli/accounts-cli.d.ts +2 -2
  8. package/dist/types/cli/append-system-prompt.d.ts +6 -0
  9. package/dist/types/cli/args.d.ts +7 -2
  10. package/dist/types/cli/customize-doctor-precedence.d.ts +16 -0
  11. package/dist/types/cli/customize-doctor.d.ts +4 -3
  12. package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
  13. package/dist/types/cli/install-activation.d.ts +10 -4
  14. package/dist/types/cli/public-command-errors.d.ts +2 -0
  15. package/dist/types/cli/root-flags.d.ts +0 -12
  16. package/dist/types/cli/update-cli.d.ts +21 -3
  17. package/dist/types/cli-main.d.ts +0 -6
  18. package/dist/types/cli-ordinary.d.ts +2 -2
  19. package/dist/types/commands/accounts.d.ts +2 -1
  20. package/dist/types/commands/launch.d.ts +0 -6
  21. package/dist/types/commands/migrate.d.ts +1 -1
  22. package/dist/types/commands/sdk.d.ts +13 -0
  23. package/dist/types/commit/changelog/index.d.ts +1 -0
  24. package/dist/types/commit/map-reduce/index.d.ts +4 -4
  25. package/dist/types/config/autorouting-tier-map.d.ts +53 -1
  26. package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
  27. package/dist/types/config/config-hot-reload.d.ts +44 -0
  28. package/dist/types/config/file-lock.d.ts +52 -3
  29. package/dist/types/config/model-discovery-manager.d.ts +2 -0
  30. package/dist/types/config/model-profile-activation.d.ts +79 -9
  31. package/dist/types/config/model-registry.d.ts +72 -8
  32. package/dist/types/config/model-resolver.d.ts +7 -4
  33. package/dist/types/config/models-config-schema.d.ts +10 -0
  34. package/dist/types/config/settings-schema.d.ts +57 -4
  35. package/dist/types/config/settings.d.ts +33 -1
  36. package/dist/types/coordinator-mcp/server.d.ts +4 -0
  37. package/dist/types/customization/import.d.ts +2 -0
  38. package/dist/types/customization/types.d.ts +1 -1
  39. package/dist/types/dap/config.d.ts +8 -4
  40. package/dist/types/dap/session.d.ts +11 -2
  41. package/dist/types/debug/system-info.d.ts +6 -1
  42. package/dist/types/discovery/helpers.d.ts +7 -2
  43. package/dist/types/discovery/mcp-compat.d.ts +3 -1
  44. package/dist/types/edit/index.d.ts +5 -0
  45. package/dist/types/edit/modes/patch.d.ts +14 -0
  46. package/dist/types/edit/modes/replace.d.ts +3 -0
  47. package/dist/types/eval/py/runtime.d.ts +9 -0
  48. package/dist/types/exec/bash-executor.d.ts +12 -0
  49. package/dist/types/export/ttsr.d.ts +19 -0
  50. package/dist/types/extensibility/extensions/types.d.ts +5 -1
  51. package/dist/types/extensibility/slash-commands.d.ts +1 -0
  52. package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
  53. package/dist/types/gjc-runtime/ralplan-current-final.d.ts +54 -0
  54. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +5 -0
  55. package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
  56. package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
  57. package/dist/types/gjc-runtime/tmux-sessions.d.ts +24 -0
  58. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +6 -0
  59. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
  60. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  61. package/dist/types/hindsight/content.d.ts +5 -6
  62. package/dist/types/internal-urls/types.d.ts +2 -0
  63. package/dist/types/lsp/clients/swiftlint-client.d.ts +0 -4
  64. package/dist/types/main.d.ts +23 -18
  65. package/dist/types/migrate/action-planner.d.ts +10 -1
  66. package/dist/types/migrate/adapters/codex.d.ts +2 -1
  67. package/dist/types/migrate/adapters/index.d.ts +42 -1
  68. package/dist/types/migrate/executor.d.ts +3 -1
  69. package/dist/types/migrate/hook-module.d.ts +23 -0
  70. package/dist/types/migrate/report.d.ts +2 -1
  71. package/dist/types/migrate/types.d.ts +82 -3
  72. package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
  73. package/dist/types/modes/components/model-selector.d.ts +43 -0
  74. package/dist/types/modes/components/settings-selector.d.ts +6 -0
  75. package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
  76. package/dist/types/modes/prompt-suggestion-controller.d.ts +1 -1
  77. package/dist/types/modes/theme/theme.d.ts +1 -0
  78. package/dist/types/modes/utils/host-status.d.ts +15 -11
  79. package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
  80. package/dist/types/runtime-mcp/manager.d.ts +7 -0
  81. package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
  82. package/dist/types/runtime-mcp/project-host-values.d.ts +11 -5
  83. package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
  84. package/dist/types/sdk/broker/broker-exit.d.ts +3 -3
  85. package/dist/types/sdk/broker/broker.d.ts +29 -2
  86. package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
  87. package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
  88. package/dist/types/sdk/broker/ensure.d.ts +141 -9
  89. package/dist/types/sdk/broker/hop.d.ts +45 -0
  90. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
  91. package/dist/types/sdk/broker/lifecycle.d.ts +22 -0
  92. package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
  93. package/dist/types/sdk/broker/session-index.d.ts +6 -1
  94. package/dist/types/sdk/broker/transport.d.ts +2 -0
  95. package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
  96. package/dist/types/sdk/bus/index.d.ts +44 -0
  97. package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
  98. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -1
  99. package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
  100. package/dist/types/sdk/bus/threaded-render.d.ts +2 -1
  101. package/dist/types/sdk/cli/session-cli.d.ts +0 -1
  102. package/dist/types/sdk/host/control/operations.d.ts +5 -1
  103. package/dist/types/sdk/host/events.d.ts +4 -0
  104. package/dist/types/sdk/host/host.d.ts +2 -1
  105. package/dist/types/sdk/host/prompt-image-upload.d.ts +43 -0
  106. package/dist/types/sdk/host/session-runtime.d.ts +40 -8
  107. package/dist/types/sdk/host/surface-policy.d.ts +2 -1
  108. package/dist/types/sdk/lifecycle/service.d.ts +12 -0
  109. package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
  110. package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
  111. package/dist/types/sdk/prompt-status.d.ts +11 -4
  112. package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
  113. package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
  114. package/dist/types/sdk/session-list.d.ts +1 -1
  115. package/dist/types/session/agent-session.d.ts +107 -9
  116. package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
  117. package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
  118. package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
  119. package/dist/types/session/messages.d.ts +5 -1
  120. package/dist/types/session/session-manager.d.ts +29 -3
  121. package/dist/types/session/startup-auth-config.d.ts +24 -2
  122. package/dist/types/session/streaming-output.d.ts +11 -0
  123. package/dist/types/session/terminal-abort.d.ts +3 -1
  124. package/dist/types/session-import/service.d.ts +1 -1
  125. package/dist/types/skill-state/workflow-mutation-guard.d.ts +20 -4
  126. package/dist/types/slash-commands/helpers/mcp.d.ts +5 -0
  127. package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
  128. package/dist/types/ssh/ssh-executor.d.ts +8 -1
  129. package/dist/types/system-prompt.d.ts +3 -2
  130. package/dist/types/task/executor.d.ts +19 -2
  131. package/dist/types/task/role-body.d.ts +11 -0
  132. package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
  133. package/dist/types/tools/atomic-file-write.d.ts +9 -7
  134. package/dist/types/tools/awaiting-input.d.ts +28 -0
  135. package/dist/types/tools/bash-allowed-prefixes.d.ts +17 -0
  136. package/dist/types/tools/bash-skill-urls.d.ts +4 -0
  137. package/dist/types/tools/bash.d.ts +7 -0
  138. package/dist/types/tools/descriptors.d.ts +15 -2
  139. package/dist/types/tools/fetch.d.ts +7 -1
  140. package/dist/types/tools/index.d.ts +2 -0
  141. package/dist/types/tools/irc.d.ts +5 -3
  142. package/dist/types/tools/python.d.ts +1 -1
  143. package/dist/types/tools/report-issue.d.ts +41 -0
  144. package/dist/types/tools/subagent.d.ts +23 -0
  145. package/dist/types/tools/tmux-self-injection-guard.d.ts +2 -0
  146. package/dist/types/tools/ultragoal-ask-guard.d.ts +1 -1
  147. package/dist/types/tools/write.d.ts +2 -0
  148. package/dist/types/utils/file-mentions.d.ts +5 -0
  149. package/dist/types/utils/image-limits.d.ts +7 -0
  150. package/dist/types/utils/image-loading.d.ts +0 -1
  151. package/dist/types/utils/open.d.ts +0 -1
  152. package/dist/types/utils/pasted-image-loading.d.ts +1 -5
  153. package/dist/types/utils/prompt-suggestion.d.ts +2 -2
  154. package/dist/types/utils/shell-snapshot.d.ts +2 -0
  155. package/dist/types/utils/title-generator.d.ts +13 -3
  156. package/dist/types/web/scrapers/types.d.ts +8 -1
  157. package/dist/types/web/search/providers/codex.d.ts +6 -7
  158. package/dist/types/web/search/providers/insane.d.ts +7 -1
  159. package/dist/types/web/search/providers/searxng.d.ts +5 -0
  160. package/package.json +10 -9
  161. package/scripts/acp-conformance-agent.ts +12 -2
  162. package/scripts/build-binary.ts +2 -1
  163. package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
  164. package/scripts/generate-docs-index.ts +8 -1
  165. package/scripts/generate-sdk-operation-inventory.ts +38 -4
  166. package/src/async/job-manager.ts +356 -56
  167. package/src/async/result-formatting.ts +40 -0
  168. package/src/autoresearch/git.ts +9 -2
  169. package/src/autoresearch/prompts/prompt-setup.md +1 -1
  170. package/src/capability/fs.ts +58 -22
  171. package/src/capability/index.ts +2 -2
  172. package/src/capability/rule.ts +11 -2
  173. package/src/cli/accounts-cli.ts +176 -8
  174. package/src/cli/append-system-prompt.ts +12 -0
  175. package/src/cli/args.ts +11 -7
  176. package/src/cli/auth-broker-cli.ts +21 -11
  177. package/src/cli/customize-doctor-precedence.ts +31 -0
  178. package/src/cli/customize-doctor.ts +49 -39
  179. package/src/cli/doctor/install-repairs.ts +35 -5
  180. package/src/cli/fast-help.ts +1 -3
  181. package/src/cli/install-activation.ts +47 -4
  182. package/src/cli/migrate-cli.ts +19 -6
  183. package/src/cli/public-command-errors.ts +6 -0
  184. package/src/cli/root-flags.ts +2 -4
  185. package/src/cli/stats-cli.ts +9 -5
  186. package/src/cli/update-cli.ts +471 -13
  187. package/src/cli-ordinary.ts +7 -2
  188. package/src/commands/accounts.ts +10 -5
  189. package/src/commands/harness.ts +25 -15
  190. package/src/commands/migrate.ts +3 -3
  191. package/src/commands/sdk.ts +277 -50
  192. package/src/commands/ultragoal.ts +16 -8
  193. package/src/commit/agentic/agent.ts +6 -6
  194. package/src/commit/analysis/conventional.ts +14 -5
  195. package/src/commit/changelog/index.ts +39 -1
  196. package/src/commit/map-reduce/index.ts +7 -7
  197. package/src/commit/message.ts +10 -3
  198. package/src/commit/pipeline.ts +12 -12
  199. package/src/config/autorouting-tier-map.ts +50 -1
  200. package/src/config/config-file.ts +106 -3
  201. package/src/config/config-hot-reload-trust.ts +148 -0
  202. package/src/config/config-hot-reload.ts +742 -0
  203. package/src/config/file-lock.ts +1615 -328
  204. package/src/config/keybindings.ts +154 -7
  205. package/src/config/model-bindings-applier.ts +85 -47
  206. package/src/config/model-discovery-manager.ts +10 -0
  207. package/src/config/model-profile-activation.ts +889 -148
  208. package/src/config/model-registry.ts +1706 -205
  209. package/src/config/model-resolver.ts +52 -22
  210. package/src/config/models-config-schema.ts +6 -0
  211. package/src/config/settings-schema.ts +73 -4
  212. package/src/config/settings.ts +460 -24
  213. package/src/coordinator-mcp/policy.ts +26 -1
  214. package/src/coordinator-mcp/server.ts +37 -2
  215. package/src/crash/sanitize.ts +7 -1
  216. package/src/customization/import.ts +279 -8
  217. package/src/customization/inventory.ts +24 -8
  218. package/src/customization/types.ts +1 -0
  219. package/src/dap/client.ts +3 -2
  220. package/src/dap/config.ts +31 -11
  221. package/src/dap/defaults.json +1 -1
  222. package/src/dap/session.ts +161 -36
  223. package/src/debug/crash-diagnostics.ts +89 -6
  224. package/src/debug/report-bundle.ts +90 -2
  225. package/src/debug/system-info.ts +8 -3
  226. package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
  227. package/src/discovery/agents-md.ts +1 -1
  228. package/src/discovery/builtin.ts +4 -3
  229. package/src/discovery/helpers.ts +25 -16
  230. package/src/discovery/mcp-compat.ts +120 -17
  231. package/src/edit/apply-patch/index.ts +12 -1
  232. package/src/edit/index.ts +204 -22
  233. package/src/edit/modes/patch.ts +214 -8
  234. package/src/edit/modes/replace.ts +136 -0
  235. package/src/eval/js/context-manager.ts +29 -3
  236. package/src/eval/js/worker-entry.ts +51 -18
  237. package/src/eval/py/executor.ts +14 -4
  238. package/src/eval/py/runner.py +144 -5
  239. package/src/eval/py/runtime.ts +44 -4
  240. package/src/exec/bash-executor.ts +81 -4
  241. package/src/exec/bash-shell-guardian.ts +4 -1
  242. package/src/exec/bash-shell-supervisor.ts +8 -4
  243. package/src/exec/isolated-shell.ts +5 -1
  244. package/src/exec/non-interactive-env.ts +0 -1
  245. package/src/export/html/index.ts +86 -6
  246. package/src/export/ttsr.ts +176 -1
  247. package/src/extensibility/custom-tools/wrapper.ts +3 -1
  248. package/src/extensibility/extensions/loader.ts +10 -1
  249. package/src/extensibility/extensions/ouroboros-ooo-bridge.ts +63 -1
  250. package/src/extensibility/extensions/types.ts +5 -1
  251. package/src/extensibility/hooks/loader.ts +10 -2
  252. package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
  253. package/src/extensibility/plugins/marketplace/manager.ts +36 -10
  254. package/src/extensibility/slash-commands.ts +5 -0
  255. package/src/gjc-runtime/gc-runtime.ts +37 -7
  256. package/src/gjc-runtime/launch-tmux.ts +30 -15
  257. package/src/gjc-runtime/launch-worktree.test.ts +148 -0
  258. package/src/gjc-runtime/launch-worktree.ts +101 -14
  259. package/src/gjc-runtime/managed-owner-admission.ts +46 -2
  260. package/src/gjc-runtime/ralplan-current-final.ts +294 -0
  261. package/src/gjc-runtime/ralplan-runtime.ts +95 -1
  262. package/src/gjc-runtime/session-resolution.ts +38 -6
  263. package/src/gjc-runtime/session-state-lock.ts +59 -14
  264. package/src/gjc-runtime/state-runtime.ts +23 -19
  265. package/src/gjc-runtime/state-writer.ts +109 -5
  266. package/src/gjc-runtime/tmux-sessions.ts +93 -13
  267. package/src/gjc-runtime/ultragoal-change-set.ts +90 -11
  268. package/src/gjc-runtime/ultragoal-guard.ts +9 -1
  269. package/src/gjc-runtime/ultragoal-runtime.ts +15 -5
  270. package/src/harness-control-plane/finalize.ts +11 -0
  271. package/src/harness-control-plane/receipt-spool.ts +105 -28
  272. package/src/harness-control-plane/storage.ts +124 -6
  273. package/src/hindsight/content.ts +116 -16
  274. package/src/hindsight/mental-models.ts +22 -10
  275. package/src/hindsight/state.ts +7 -4
  276. package/src/hooks/native-skill-hook.ts +17 -12
  277. package/src/internal-urls/artifact-protocol.ts +3 -1
  278. package/src/internal-urls/docs-index.generated.ts +23 -22
  279. package/src/internal-urls/local-protocol.ts +167 -8
  280. package/src/internal-urls/types.ts +2 -0
  281. package/src/lsp/client.ts +2 -1
  282. package/src/lsp/clients/biome-client.ts +2 -0
  283. package/src/lsp/clients/swiftlint-client.ts +2 -0
  284. package/src/lsp/index.ts +29 -0
  285. package/src/lsp/workspace-path.ts +23 -0
  286. package/src/main.ts +330 -92
  287. package/src/memories/index.ts +25 -2
  288. package/src/migrate/action-planner.ts +574 -2
  289. package/src/migrate/adapters/claude-code.ts +162 -5
  290. package/src/migrate/adapters/codex.ts +77 -7
  291. package/src/migrate/adapters/index.ts +258 -5
  292. package/src/migrate/adapters/opencode.ts +10 -1
  293. package/src/migrate/executor.ts +222 -7
  294. package/src/migrate/hook-module.ts +193 -0
  295. package/src/migrate/report.ts +63 -2
  296. package/src/migrate/types.ts +84 -4
  297. package/src/modes/DESIGN.md +51 -0
  298. package/src/modes/acp/acp-agent.ts +10 -1
  299. package/src/modes/acp/permission-mode.ts +18 -1
  300. package/src/modes/components/agent-dashboard.ts +20 -4
  301. package/src/modes/components/assistant-message.ts +55 -1
  302. package/src/modes/components/customization/customization-dashboard.ts +7 -0
  303. package/src/modes/components/customization/import-wizard.ts +29 -3
  304. package/src/modes/components/model-selector.ts +157 -103
  305. package/src/modes/components/settings-selector.ts +103 -37
  306. package/src/modes/components/welcome.ts +3 -1
  307. package/src/modes/controllers/command-controller.ts +300 -9
  308. package/src/modes/controllers/event-controller.ts +1 -1
  309. package/src/modes/controllers/extension-ui-controller.ts +31 -1
  310. package/src/modes/controllers/goal-mode-controller.ts +79 -10
  311. package/src/modes/controllers/input-controller.ts +2 -0
  312. package/src/modes/controllers/plan-mode-controller.ts +66 -11
  313. package/src/modes/controllers/runtime-mcp-command-controller.ts +7 -6
  314. package/src/modes/controllers/selector-controller.ts +76 -7
  315. package/src/modes/interactive-mode.ts +123 -4
  316. package/src/modes/prompt-suggestion-controller.ts +1 -1
  317. package/src/modes/runtime-init.ts +5 -1
  318. package/src/modes/theme/theme.ts +15 -0
  319. package/src/modes/utils/host-status.ts +21 -10
  320. package/src/prompts/agent-fragments/browser-aside.md +2 -2
  321. package/src/prompts/system/irc-incoming.md +3 -1
  322. package/src/prompts/tools/debug.md +1 -1
  323. package/src/prompts/tools/irc.md +1 -1
  324. package/src/prompts/tools/read.md +1 -1
  325. package/src/prompts/tools/report-issue.md +13 -0
  326. package/src/prompts/tools/task.md +1 -1
  327. package/src/runtime-credential-selector.ts +2 -2
  328. package/src/runtime-mcp/content-limits.ts +7 -0
  329. package/src/runtime-mcp/manager-pool.test.ts +5 -4
  330. package/src/runtime-mcp/manager.ts +40 -3
  331. package/src/runtime-mcp/oauth-flow.ts +32 -6
  332. package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
  333. package/src/runtime-mcp/project-host-values.ts +12 -8
  334. package/src/runtime-mcp/render.ts +16 -1
  335. package/src/runtime-mcp/tool-bridge.ts +194 -21
  336. package/src/runtime-mcp/transports/stdio.ts +2 -1
  337. package/src/sdk/broker/broker-exit.ts +10 -5
  338. package/src/sdk/broker/broker.ts +484 -85
  339. package/src/sdk/broker/daemon-entry.ts +338 -116
  340. package/src/sdk/broker/doctor-restart.ts +2 -1
  341. package/src/sdk/broker/ensure.ts +1214 -268
  342. package/src/sdk/broker/hop.ts +286 -0
  343. package/src/sdk/broker/lifecycle-ledger.ts +38 -11
  344. package/src/sdk/broker/lifecycle.ts +102 -6
  345. package/src/sdk/broker/lock-host-identity.ts +29 -0
  346. package/src/sdk/broker/session-index.ts +91 -16
  347. package/src/sdk/broker/transport.ts +17 -1
  348. package/src/sdk/bus/chat-command-policy.ts +16 -3
  349. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  350. package/src/sdk/bus/index.ts +460 -35
  351. package/src/sdk/bus/reconciliation-store.ts +201 -8
  352. package/src/sdk/bus/session-control.ts +2 -0
  353. package/src/sdk/bus/slack-daemon.ts +105 -9
  354. package/src/sdk/bus/telegram-daemon-contract.ts +9 -1
  355. package/src/sdk/bus/telegram-daemon.ts +10 -2
  356. package/src/sdk/bus/threaded-render.ts +20 -1
  357. package/src/sdk/cli/session-cli.ts +23 -6
  358. package/src/sdk/host/control/dispatch.ts +13 -1
  359. package/src/sdk/host/control/operations.ts +10 -1
  360. package/src/sdk/host/events.ts +67 -4
  361. package/src/sdk/host/host.ts +8 -2
  362. package/src/sdk/host/prompt-image-upload.ts +438 -0
  363. package/src/sdk/host/sdk-surface-parity.test.ts +15 -0
  364. package/src/sdk/host/session-runtime.test.ts +1737 -129
  365. package/src/sdk/host/session-runtime.ts +684 -83
  366. package/src/sdk/host/surface-policy.ts +4 -0
  367. package/src/sdk/host/websocket-transport.lifecycle.test.ts +90 -2
  368. package/src/sdk/host/websocket-transport.ts +19 -7
  369. package/src/sdk/lifecycle/service.ts +15 -1
  370. package/src/sdk/prompt-deadline-flush.ts +78 -5
  371. package/src/sdk/prompt-deadline-manager.ts +68 -14
  372. package/src/sdk/prompt-status.ts +6 -4
  373. package/src/sdk/protocol/adapter-validation.ts +81 -12
  374. package/src/sdk/protocol/operation-inventory.generated.json +261 -2
  375. package/src/sdk/protocol/operation-registry.ts +33 -3
  376. package/src/sdk/reconciliation-extensions.ts +1 -0
  377. package/src/sdk/session-list.ts +1 -0
  378. package/src/sdk/session.ts +237 -97
  379. package/src/session/agent-session.ts +2726 -479
  380. package/src/session/history-storage.ts +182 -12
  381. package/src/session/internal/managed-session-scope.ts +173 -57
  382. package/src/session/internal/managed-session-storage.ts +85 -12
  383. package/src/session/internal/native-publish-outcome.ts +5 -1
  384. package/src/session/messages.ts +47 -6
  385. package/src/session/session-manager.ts +326 -19
  386. package/src/session/startup-auth-config.ts +116 -8
  387. package/src/session/streaming-output.ts +262 -4
  388. package/src/session/terminal-abort.ts +14 -2
  389. package/src/session-import/redact.ts +53 -2
  390. package/src/session-import/service.ts +1 -0
  391. package/src/skill-state/workflow-mutation-guard.ts +2145 -206
  392. package/src/slash-commands/builtin-registry.ts +21 -6
  393. package/src/slash-commands/helpers/credential-switch.ts +10 -5
  394. package/src/slash-commands/helpers/mcp.ts +11 -3
  395. package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
  396. package/src/ssh/ssh-executor.ts +9 -2
  397. package/src/stt/recorder.ts +26 -9
  398. package/src/system-prompt.ts +61 -16
  399. package/src/task/executor.ts +115 -20
  400. package/src/task/index.ts +389 -175
  401. package/src/task/role-body.ts +84 -0
  402. package/src/task/token-log-mode.test.ts +162 -0
  403. package/src/task/token-log.ts +91 -2
  404. package/src/tools/archive-reader.ts +650 -37
  405. package/src/tools/ask.ts +1 -0
  406. package/src/tools/ast-edit-write-path.ts +64 -0
  407. package/src/tools/ast-edit.ts +18 -1
  408. package/src/tools/ast-grep.ts +7 -2
  409. package/src/tools/atomic-file-write.ts +46 -15
  410. package/src/tools/auto-generated-guard.ts +15 -3
  411. package/src/tools/awaiting-input.ts +114 -0
  412. package/src/tools/bash-allowed-prefixes.ts +214 -6
  413. package/src/tools/bash-interactive.ts +14 -2
  414. package/src/tools/bash-skill-urls.ts +58 -5
  415. package/src/tools/bash.ts +113 -26
  416. package/src/tools/browser/tab-worker.ts +39 -13
  417. package/src/tools/browser.ts +17 -7
  418. package/src/tools/cron.ts +10 -1
  419. package/src/tools/debug.ts +16 -8
  420. package/src/tools/descriptors.test.ts +44 -0
  421. package/src/tools/descriptors.ts +50 -6
  422. package/src/tools/eval.ts +15 -0
  423. package/src/tools/fetch.ts +93 -4
  424. package/src/tools/gh.ts +27 -12
  425. package/src/tools/image-gen.ts +20 -6
  426. package/src/tools/index.ts +2 -0
  427. package/src/tools/irc.ts +5 -3
  428. package/src/tools/monitor.ts +9 -1
  429. package/src/tools/output-meta.ts +74 -5
  430. package/src/tools/python.ts +1 -1
  431. package/src/tools/read.ts +26 -37
  432. package/src/tools/recipe/runner.ts +23 -12
  433. package/src/tools/render-utils.ts +2 -2
  434. package/src/tools/report-issue.ts +184 -0
  435. package/src/tools/search.ts +3 -2
  436. package/src/tools/ssh.ts +274 -8
  437. package/src/tools/subagent-render.ts +114 -12
  438. package/src/tools/subagent.ts +118 -5
  439. package/src/tools/tmux-self-injection-guard.ts +3301 -122
  440. package/src/tools/todo-write.ts +41 -3
  441. package/src/tools/tool-catalog.generated.ts +32 -4
  442. package/src/tools/ultragoal-ask-guard.ts +13 -1
  443. package/src/tools/write.ts +42 -3
  444. package/src/tui/tree-list.ts +15 -1
  445. package/src/utils/commit-message-generator.ts +12 -4
  446. package/src/utils/external-editor.ts +21 -7
  447. package/src/utils/file-mentions.ts +75 -7
  448. package/src/utils/git.ts +38 -7
  449. package/src/utils/image-limits.ts +8 -0
  450. package/src/utils/image-loading.ts +1 -1
  451. package/src/utils/open.ts +73 -4
  452. package/src/utils/pasted-image-loading.ts +9 -8
  453. package/src/utils/prompt-suggestion.ts +5 -4
  454. package/src/utils/shell-snapshot.ts +9 -1
  455. package/src/utils/title-generator.ts +72 -22
  456. package/src/web/scrapers/index.ts +3 -1
  457. package/src/web/scrapers/types.ts +8 -0
  458. package/src/web/scrapers/youtube.ts +3 -2
  459. package/src/web/search/index.ts +2 -1
  460. package/src/web/search/providers/codex.ts +29 -32
  461. package/src/web/search/providers/insane.ts +91 -28
  462. package/src/web/search/providers/searxng.ts +62 -10
package/src/task/index.ts CHANGED
@@ -31,6 +31,7 @@ import { AUTOROUTING_SELECTOR_MAX_LENGTH, type AutoroutingReasonCode } from "../
31
31
  import { resolveProfileBindings } from "../config/model-profiles";
32
32
  import { resolveAgentModelPatterns } from "../config/model-resolver";
33
33
  import type { Theme } from "../modes/theme/theme";
34
+ import type { PlanModeState } from "../plan-mode/state";
34
35
  import planModeSubagentPrompt from "../prompts/system/plan-mode-subagent.md" with { type: "text" };
35
36
  import taskSummaryTemplate from "../prompts/tools/task-summary.md" with { type: "text" };
36
37
  import type { ForkContextSeed } from "../session/agent-session";
@@ -118,11 +119,17 @@ interface DuplicateDisposition {
118
119
  predecessorIds: string[];
119
120
  }
120
121
 
122
+ interface TaskArtifactPersistence {
123
+ effectiveArtifactsDir: string | undefined;
124
+ parentArtifactManager: ArtifactManager | undefined;
125
+ }
126
+
121
127
  interface TaskResumeDescriptor {
122
128
  toolCallId: string;
123
129
  params: TaskParams;
124
130
  task: TaskItem & { id: string };
125
131
  sessionFile: string | null;
132
+ artifactPersistence: TaskArtifactPersistence;
126
133
  durableOutputAllowed?: boolean;
127
134
  forkContextSeed?: ForkContextSeed;
128
135
  agentSource: AgentDefinition["source"];
@@ -136,6 +143,96 @@ interface TaskResumeDescriptor {
136
143
  function isTaskResumeDescriptor(value: unknown): value is TaskResumeDescriptor {
137
144
  return typeof value === "object" && value !== null && "task" in value && "params" in value;
138
145
  }
146
+
147
+ /** Retain the caller-visible execution inputs for detached and resumed runs. */
148
+ function captureTaskExecutionScope(session: ToolSession): ToolSession {
149
+ const snapshot = new Map<PropertyKey, unknown>([
150
+ ["cwd", session.cwd],
151
+ ["hasUI", session.hasUI],
152
+ ["contextFiles", session.contextFiles ? [...session.contextFiles] : undefined],
153
+ ["workspaceTree", session.workspaceTree],
154
+ ["home", session.home],
155
+ ["profileAuthority", session.profileAuthority],
156
+ ["skills", session.skills ? [...session.skills] : undefined],
157
+ ["promptTemplates", session.promptTemplates ? [...session.promptTemplates] : undefined],
158
+ ["enableLsp", session.enableLsp],
159
+ ["hasEditTool", session.hasEditTool],
160
+ ["eventBus", session.eventBus],
161
+ ["outputSchema", session.outputSchema],
162
+ ["requireYieldTool", session.requireYieldTool],
163
+ ["taskDepth", session.taskDepth],
164
+ ["currentAgentType", session.currentAgentType],
165
+ ["model", session.model],
166
+ ["settings", session.settings.snapshot()],
167
+ ["serviceTier", session.serviceTier],
168
+ ["authStorage", session.authStorage],
169
+ ["modelRegistry", session.modelRegistry],
170
+ ["agentRegistry", session.agentRegistry],
171
+ ]);
172
+ for (const key of [
173
+ "getSessionFile",
174
+ "getSessionSpawns",
175
+ "getSessionId",
176
+ "getAsyncEndpointId",
177
+ "getAsyncJobManager",
178
+ "getCredentialSessionId",
179
+ "getAgentId",
180
+ "getSessionAgentDir",
181
+ "getActiveModelString",
182
+ "getModelString",
183
+ "getActiveModelProfile",
184
+ "getCompactContext",
185
+ "getMcpManager",
186
+ "getHindsightSessionState",
187
+ "isManagedSessionDestination",
188
+ ] as const) {
189
+ const accessor: unknown = Reflect.get(session, key, session);
190
+ if (typeof accessor === "function") {
191
+ const value: unknown = Reflect.apply(accessor, session, []);
192
+ snapshot.set(key, () => value);
193
+ } else {
194
+ snapshot.set(key, accessor);
195
+ }
196
+ }
197
+
198
+ const boundMethods = new Map<PropertyKey, { source: unknown; bound: unknown }>();
199
+ return new Proxy(session, {
200
+ get(target, property) {
201
+ if (snapshot.has(property)) return snapshot.get(property);
202
+ const value: unknown = Reflect.get(target, property, target);
203
+ if (typeof value !== "function") return value;
204
+ const cached = boundMethods.get(property);
205
+ if (cached?.source === value) return cached.bound;
206
+ const bound = value.bind(target);
207
+ boundMethods.set(property, { source: value, bound });
208
+ return bound;
209
+ },
210
+ }) as ToolSession;
211
+ }
212
+
213
+ /** Approval policy copied into a task child. A missing mode stays `allow`, the child default. */
214
+ function inheritedSubagentApproval(session: ToolSession) {
215
+ const mode = session.getSdkPermissionMode?.();
216
+ return {
217
+ sdkPermissionMode: mode === "deny" || mode === "prompt" ? mode : ("allow" as const),
218
+ clientBridge: session.getClientBridge?.(),
219
+ };
220
+ }
221
+
222
+ /** Enabled plan mode only. A missing or disabled state leaves the child writable. */
223
+ function inheritedPlanMode(session: ToolSession): { planModeState?: PlanModeState } {
224
+ const state = session.getPlanModeState?.();
225
+ if (!state?.enabled || !state.planFilePath) return {};
226
+ return {
227
+ planModeState: {
228
+ enabled: true,
229
+ planFilePath: state.planFilePath,
230
+ ...(state.workflow ? { workflow: state.workflow } : {}),
231
+ ...(state.reentry !== undefined ? { reentry: state.reentry } : {}),
232
+ },
233
+ };
234
+ }
235
+
139
236
  function renderTaskAssignment(assignment: string, simpleMode: TaskSimpleMode): string {
140
237
  return renderSubagentUserPrompt(assignment, simpleMode === "independent");
141
238
  }
@@ -587,22 +684,43 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
587
684
  return renderTaskDescription(this.session);
588
685
  }
589
686
  readonly #sessionRepositoryBinding: RepositoryBinding;
687
+ readonly #ownerSession: ToolSession;
688
+ readonly #parentModelProfileOwnershipMarker: unknown;
590
689
  #testRunSubprocess: typeof runSubprocess | undefined;
591
690
 
592
691
  private constructor(
593
692
  private readonly session: ToolSession,
594
693
  discoveredAgents: AgentDefinition[],
595
694
  sessionRepositoryBinding: RepositoryBinding,
695
+ ownerSession?: ToolSession,
696
+ parentModelProfileOwnershipMarker?: unknown,
596
697
  ) {
597
698
  this.#blockedAgent = $pickenv("GJC_BLOCKED_AGENT", "PI_BLOCKED_AGENT");
598
699
  this.#discoveredAgents = discoveredAgents;
599
700
  this.#sessionRepositoryBinding = sessionRepositoryBinding;
701
+ this.#ownerSession = ownerSession ?? session;
702
+ this.#parentModelProfileOwnershipMarker = parentModelProfileOwnershipMarker;
600
703
  }
601
704
 
602
705
  #runSubprocess(options: Parameters<typeof runSubprocess>[0]): Promise<SingleResult> {
603
706
  return (this.#testRunSubprocess ?? runSubprocess)(options);
604
707
  }
605
708
 
709
+ #createExecutionFacade(): TaskTool {
710
+ const parentModelProfileOwnershipMarker = (
711
+ this.#ownerSession as { sessionManager?: { getModelProfileOwnershipMarker?: () => unknown } }
712
+ ).sessionManager?.getModelProfileOwnershipMarker?.();
713
+ const invocation = new TaskTool(
714
+ captureTaskExecutionScope(this.#ownerSession),
715
+ this.#discoveredAgents,
716
+ this.#sessionRepositoryBinding,
717
+ this.#ownerSession,
718
+ parentModelProfileOwnershipMarker,
719
+ );
720
+ invocation.#testRunSubprocess = this.#testRunSubprocess;
721
+ return invocation;
722
+ }
723
+
606
724
  #getTaskSimpleMode(): TaskSimpleMode {
607
725
  return this.session.settings.get("task.simple");
608
726
  }
@@ -624,7 +742,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
624
742
  * advertise agent:// URIs without a successful allocation.
625
743
  */
626
744
  async #ensureSessionLifetimeArtifacts(): Promise<{ dir: string; manager: ArtifactManager } | null> {
627
- const state = sessionLifetimeArtifactsState(this.session);
745
+ const state = sessionLifetimeArtifactsState(this.#ownerSession);
628
746
  if (state.authorized && state.dir && state.manager) return { dir: state.dir, manager: state.manager };
629
747
  if (this.session.ensureArtifactManager) {
630
748
  const manager = await this.session.ensureArtifactManager();
@@ -685,13 +803,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
685
803
  adoptIntoSessionOwner: boolean,
686
804
  ): Promise<boolean> {
687
805
  if (state.authorized) return true;
688
- state.originalGetArtifactsDir = this.session.getArtifactsDir;
689
- state.originalGetAuthorizedArtifactsDirs = this.session.getAuthorizedArtifactsDirs;
690
- state.originalGetArtifactManager = this.session.getArtifactManager;
691
- state.originalIsArtifactManagerAuthorized = this.session.isArtifactManagerAuthorized;
692
- state.originalAgentOutputManager = this.session.agentOutputManager;
806
+ state.originalGetArtifactsDir = this.#ownerSession.getArtifactsDir;
807
+ state.originalGetAuthorizedArtifactsDirs = this.#ownerSession.getAuthorizedArtifactsDirs;
808
+ state.originalGetArtifactManager = this.#ownerSession.getArtifactManager;
809
+ state.originalIsArtifactManagerAuthorized = this.#ownerSession.isArtifactManagerAuthorized;
810
+ state.originalAgentOutputManager = this.#ownerSession.agentOutputManager;
693
811
 
694
- state.installedGetArtifactsDir = () => state.originalGetArtifactsDir?.() ?? dir;
812
+ state.installedGetArtifactsDir = () => state.originalGetArtifactsDir?.call(this.#ownerSession) ?? dir;
695
813
  state.installedGetAuthorizedArtifactsDirs = () => {
696
814
  const dirs: string[] = [];
697
815
  const add = (candidate: string | null | undefined) => {
@@ -699,68 +817,73 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
699
817
  const normalized = path.resolve(candidate);
700
818
  if (!dirs.includes(normalized)) dirs.push(normalized);
701
819
  };
702
- for (const authorized of state.originalGetAuthorizedArtifactsDirs?.() ?? []) add(authorized);
820
+ for (const authorized of state.originalGetAuthorizedArtifactsDirs?.call(this.#ownerSession) ?? [])
821
+ add(authorized);
703
822
  add(dir);
704
823
  return dirs;
705
824
  };
706
825
  state.installedGetArtifactManager = () => manager;
707
826
  state.installedIsArtifactManagerAuthorized = candidate =>
708
- candidate === manager || state.originalIsArtifactManagerAuthorized?.(candidate) === true;
709
- if (owned || !this.session.agentOutputManager) {
710
- state.installedAgentOutputManager = new AgentOutputManager(() => this.session.getArtifactsDir?.() ?? null, {
711
- parentPrefix: owned ? state.outputPrefix : undefined,
712
- getAuthorizedArtifactsDirs: () => this.session.getAuthorizedArtifactsDirs?.() ?? [],
713
- });
827
+ candidate === manager ||
828
+ state.originalIsArtifactManagerAuthorized?.call(this.#ownerSession, candidate) === true;
829
+ if (owned || !this.#ownerSession.agentOutputManager) {
830
+ state.installedAgentOutputManager = new AgentOutputManager(
831
+ () => this.#ownerSession.getArtifactsDir?.() ?? null,
832
+ {
833
+ parentPrefix: owned ? state.outputPrefix : undefined,
834
+ getAuthorizedArtifactsDirs: () => this.#ownerSession.getAuthorizedArtifactsDirs?.() ?? [],
835
+ },
836
+ );
714
837
  }
715
838
 
716
839
  let cleanupRan = false;
717
840
  const cleanup = async () => {
718
841
  cleanupRan = true;
719
- this.session.releaseArtifactManager?.(manager);
720
- if (this.session.getArtifactsDir === state.installedGetArtifactsDir)
721
- this.session.getArtifactsDir = state.originalGetArtifactsDir;
722
- if (this.session.getAuthorizedArtifactsDirs === state.installedGetAuthorizedArtifactsDirs)
723
- this.session.getAuthorizedArtifactsDirs = state.originalGetAuthorizedArtifactsDirs;
724
- if (this.session.getArtifactManager === state.installedGetArtifactManager)
725
- this.session.getArtifactManager = state.originalGetArtifactManager;
726
- if (this.session.isArtifactManagerAuthorized === state.installedIsArtifactManagerAuthorized)
727
- this.session.isArtifactManagerAuthorized = state.originalIsArtifactManagerAuthorized;
728
- if (this.session.agentOutputManager === state.installedAgentOutputManager)
729
- this.session.agentOutputManager = state.originalAgentOutputManager;
730
- sessionLifetimeArtifacts.delete(this.session);
842
+ this.#ownerSession.releaseArtifactManager?.(manager);
843
+ if (this.#ownerSession.getArtifactsDir === state.installedGetArtifactsDir)
844
+ this.#ownerSession.getArtifactsDir = state.originalGetArtifactsDir;
845
+ if (this.#ownerSession.getAuthorizedArtifactsDirs === state.installedGetAuthorizedArtifactsDirs)
846
+ this.#ownerSession.getAuthorizedArtifactsDirs = state.originalGetAuthorizedArtifactsDirs;
847
+ if (this.#ownerSession.getArtifactManager === state.installedGetArtifactManager)
848
+ this.#ownerSession.getArtifactManager = state.originalGetArtifactManager;
849
+ if (this.#ownerSession.isArtifactManagerAuthorized === state.installedIsArtifactManagerAuthorized)
850
+ this.#ownerSession.isArtifactManagerAuthorized = state.originalIsArtifactManagerAuthorized;
851
+ if (this.#ownerSession.agentOutputManager === state.installedAgentOutputManager)
852
+ this.#ownerSession.agentOutputManager = state.originalAgentOutputManager;
853
+ sessionLifetimeArtifacts.delete(this.#ownerSession);
731
854
  if (owned) await fs.rm(dir, { recursive: true, force: true });
732
855
  };
733
- const registerCleanup = this.session.registerSessionCleanup;
856
+ const registerCleanup = this.#ownerSession.registerSessionCleanup;
734
857
  if (!registerCleanup) {
735
858
  state.dir = undefined;
736
859
  state.manager = undefined;
737
860
  state.ensurePromise = undefined;
738
- sessionLifetimeArtifacts.delete(this.session);
861
+ sessionLifetimeArtifacts.delete(this.#ownerSession);
739
862
  if (owned) await fs.rm(dir, { recursive: true, force: true }).catch(() => {});
740
863
  return false;
741
864
  }
742
865
  try {
743
- registerCleanup(cleanup);
866
+ registerCleanup.call(this.#ownerSession, cleanup);
744
867
  } catch {
745
868
  state.dir = undefined;
746
869
  state.manager = undefined;
747
870
  state.ensurePromise = undefined;
748
- sessionLifetimeArtifacts.delete(this.session);
871
+ sessionLifetimeArtifacts.delete(this.#ownerSession);
749
872
  if (owned) await fs.rm(dir, { recursive: true, force: true }).catch(() => {});
750
873
  return false;
751
874
  }
752
875
  if (cleanupRan) return false;
753
876
  state.cleanupRegistered = true;
754
- if (adoptIntoSessionOwner && this.session.adoptArtifactManager) {
877
+ if (adoptIntoSessionOwner && this.#ownerSession.adoptArtifactManager) {
755
878
  try {
756
- this.session.adoptArtifactManager(manager);
879
+ this.#ownerSession.adoptArtifactManager(manager);
757
880
  } catch {
758
881
  await cleanup();
759
882
  return false;
760
883
  }
761
884
  if (
762
- this.session.getArtifactManager?.() !== manager ||
763
- this.session.isArtifactManagerAuthorized?.(manager) !== true
885
+ this.#ownerSession.getArtifactManager?.() !== manager ||
886
+ this.#ownerSession.isArtifactManagerAuthorized?.(manager) !== true
764
887
  ) {
765
888
  await cleanup();
766
889
  return false;
@@ -768,11 +891,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
768
891
  }
769
892
 
770
893
  state.authorized = true;
771
- this.session.getArtifactsDir = state.installedGetArtifactsDir;
772
- this.session.getAuthorizedArtifactsDirs = state.installedGetAuthorizedArtifactsDirs;
773
- this.session.getArtifactManager = state.installedGetArtifactManager;
774
- this.session.isArtifactManagerAuthorized = state.installedIsArtifactManagerAuthorized;
775
- if (state.installedAgentOutputManager) this.session.agentOutputManager = state.installedAgentOutputManager;
894
+ this.#ownerSession.getArtifactsDir = state.installedGetArtifactsDir;
895
+ this.#ownerSession.getAuthorizedArtifactsDirs = state.installedGetAuthorizedArtifactsDirs;
896
+ this.#ownerSession.getArtifactManager = state.installedGetArtifactManager;
897
+ this.#ownerSession.isArtifactManagerAuthorized = state.installedIsArtifactManagerAuthorized;
898
+ if (state.installedAgentOutputManager) this.#ownerSession.agentOutputManager = state.installedAgentOutputManager;
776
899
  return true;
777
900
  }
778
901
 
@@ -819,6 +942,26 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
819
942
  };
820
943
  }
821
944
 
945
+ #resolveAdmittedArtifactPersistence(admitted: TaskArtifactPersistence): TaskArtifactPersistence {
946
+ if (!admitted.parentArtifactManager?.getManagedStore()) return admitted;
947
+ const admittedOwnerId = this.session.getSessionId?.();
948
+ const currentOwnerId = this.#ownerSession.getSessionId?.();
949
+ const admittedFile = this.session.getSessionFile();
950
+ const currentFile = this.#ownerSession.getSessionFile();
951
+ if (
952
+ !admittedOwnerId ||
953
+ admittedOwnerId !== currentOwnerId ||
954
+ !admittedFile ||
955
+ !currentFile ||
956
+ path.basename(admittedFile) !== path.basename(currentFile)
957
+ )
958
+ return admitted;
959
+ const current = this.#sharedArtifactStore();
960
+ if (!current?.manager.getManagedStore()) return admitted;
961
+ current.manager.assertManagedBinding();
962
+ return { effectiveArtifactsDir: current.dir, parentArtifactManager: current.manager };
963
+ }
964
+
822
965
  /**
823
966
  * Create a TaskTool instance.
824
967
  * Repository authority is captured from session cwd *before* agent discovery so
@@ -863,8 +1006,18 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
863
1006
  signal?: AbortSignal,
864
1007
  onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
865
1008
  ): Promise<AgentToolResult<TaskToolDetails>> {
1009
+ return this.#createExecutionFacade().#executeCaptured(_toolCallId, rawParams, signal, onUpdate);
1010
+ }
1011
+
1012
+ async #executeCaptured(
1013
+ _toolCallId: string,
1014
+ rawParams: unknown,
1015
+ signal?: AbortSignal,
1016
+ onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
1017
+ ): Promise<AgentToolResult<TaskToolDetails>> {
1018
+ const session = this.session;
866
1019
  const params = normalizeTaskAdmissionParams(rawParams as TaskParams);
867
- const simpleMode = this.#getTaskSimpleMode();
1020
+ const simpleMode = session.settings.get("task.simple");
868
1021
  const validationError = validateTaskModeParams(simpleMode, params);
869
1022
  if (validationError) {
870
1023
  return createTaskModeError(validationError);
@@ -872,7 +1025,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
872
1025
 
873
1026
  // Re-verify session authority before using any discovered agents or scheduling work.
874
1027
  try {
875
- await assertExecutionRootMatchesRepositoryBinding(this.session.cwd, this.#sessionRepositoryBinding);
1028
+ await assertExecutionRootMatchesRepositoryBinding(session.cwd, this.#sessionRepositoryBinding);
876
1029
  } catch (error) {
877
1030
  const message =
878
1031
  error instanceof RepositoryBindingError
@@ -888,7 +1041,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
888
1041
  if (taskIdValidationError) {
889
1042
  return createTaskModeError(taskIdValidationError);
890
1043
  }
891
- const bindingResolution = await resolveTaskItemsWithRepositoryBindings(this.session.cwd, rawTaskItems);
1044
+ const bindingResolution = await resolveTaskItemsWithRepositoryBindings(session.cwd, rawTaskItems);
892
1045
  if (bindingResolution.error) {
893
1046
  return createTaskModeError(bindingResolution.error);
894
1047
  }
@@ -900,7 +1053,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
900
1053
  const agent = getAgent(this.#discoveredAgents, params.agent);
901
1054
  if (!agent) {
902
1055
  const available =
903
- callableAgents(this.#discoveredAgents, this.session)
1056
+ callableAgents(this.#discoveredAgents, session)
904
1057
  .map(agent => agent.name)
905
1058
  .join(", ") || "none";
906
1059
  return {
@@ -909,7 +1062,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
909
1062
  };
910
1063
  }
911
1064
 
912
- const disabledAgents = this.session.settings.get("task.disabledAgents") as string[];
1065
+ const disabledAgents = session.settings.get("task.disabledAgents") as string[];
913
1066
  if (disabledAgents.length > 0 && disabledAgents.includes(params.agent)) {
914
1067
  const enabled = filterVisibleAgents(this.#discoveredAgents)
915
1068
  .filter(a => !disabledAgents.includes(a.name))
@@ -928,7 +1081,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
928
1081
  const forkContextValidationError = validateForkContextRequests(
929
1082
  taskItems,
930
1083
  agent,
931
- this.session.settings.get("task.forkContext.enabled"),
1084
+ session.settings.get("task.forkContext.enabled"),
932
1085
  );
933
1086
  if (forkContextValidationError) {
934
1087
  return createTaskModeError(forkContextValidationError);
@@ -972,9 +1125,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
972
1125
  // Durable allocation failed: keep child session jsonl under local:// only.
973
1126
  // Do not advertise agent:// URIs without durable output backing.
974
1127
  const asyncLocalOptions: LocalProtocolOptions = {
975
- getArtifactsDir: this.session.getArtifactsDir ?? (() => null),
976
- isManagedDestination: this.session.isManagedSessionDestination,
977
- getSessionId: this.session.getSessionId ?? (() => null),
1128
+ getArtifactsDir: () => this.session.getArtifactsDir?.() ?? null,
1129
+ isManagedDestination: session.isManagedSessionDestination,
1130
+ getSessionId: session.getSessionId ?? (() => null),
978
1131
  };
979
1132
  await initializeLocalRoot(asyncLocalOptions);
980
1133
  externalTaskSessionsDir = resolveLocalUrlToPath("local://subagents/sessions", asyncLocalOptions);
@@ -982,7 +1135,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
982
1135
  }
983
1136
 
984
1137
  const outputManager =
985
- this.session.agentOutputManager ?? new AgentOutputManager(this.session.getArtifactsDir ?? (() => null));
1138
+ this.session.agentOutputManager ?? new AgentOutputManager(() => this.session.getArtifactsDir?.() ?? null);
986
1139
  const uniqueIds = await outputManager.allocateBatch(taskItems.map(t => t.id));
987
1140
  const fallbackAgentSource =
988
1141
  this.#discoveredAgents.find(agent => agent.name === params.agent)?.source ?? "bundled";
@@ -1041,9 +1194,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1041
1194
  });
1042
1195
  };
1043
1196
 
1044
- const maxConcurrency = this.session.settings.get("task.maxConcurrency");
1045
- const ownerId = this.session.getAgentId?.() ?? undefined;
1046
- const parentSession = this.session.getSessionFile();
1197
+ const maxConcurrency = session.settings.get("task.maxConcurrency");
1198
+ const ownerId = session.getAgentId?.() ?? undefined;
1199
+ const parentSession = session.getSessionFile();
1047
1200
  const admitDuplicateLaunch = (
1048
1201
  subagentId: string,
1049
1202
  task: TaskItem,
@@ -1083,7 +1236,14 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1083
1236
  };
1084
1237
  let resumeRunner: ResumeRunner | undefined;
1085
1238
  if (typeof manager.setResumeRunner === "function") {
1086
- resumeRunner = (_subagentId, message, resumeDescriptor, resumeToolCallId) => {
1239
+ resumeRunner = (
1240
+ _subagentId,
1241
+ message,
1242
+ resumeDescriptor,
1243
+ resumeToolCallId,
1244
+ admissionEndpointId,
1245
+ ownedRegistrationEndpointId,
1246
+ ) => {
1087
1247
  const descriptor = isTaskResumeDescriptor(resumeDescriptor?.data) ? resumeDescriptor.data : undefined;
1088
1248
  if (!descriptor) return undefined;
1089
1249
  const admission = (() => {
@@ -1148,10 +1308,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1148
1308
  {
1149
1309
  runMode: message ? "message" : "resume",
1150
1310
  resumeMessage: message,
1311
+ asyncJobManager: manager,
1151
1312
  sessionFiles: new Map([[descriptor.task.id, descriptor.sessionFile]]),
1152
1313
  suppressRoiReconciliation: true,
1153
1314
  ...(descriptor.durableOutputAllowed === true
1154
- ? {}
1315
+ ? { persistence: descriptor.artifactPersistence }
1155
1316
  : {
1156
1317
  persistence: {
1157
1318
  effectiveArtifactsDir: undefined,
@@ -1181,7 +1342,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1181
1342
  },
1182
1343
  {
1183
1344
  id: `${descriptor.task.id}-resume-${Snowflake.next()}`,
1184
- ownerId: this.session.getAgentId?.() ?? undefined,
1345
+ ownerId: session.getAgentId?.() ?? undefined,
1185
1346
  metadata: {
1186
1347
  subagent: {
1187
1348
  id: descriptor.task.id,
@@ -1208,7 +1369,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1208
1369
  manager,
1209
1370
  resumeToolCallId ?? descriptor.toolCallId,
1210
1371
  resumeJobId,
1211
- this.session.getAsyncEndpointId?.() ?? this.session.getSessionId?.() ?? undefined,
1372
+ admissionEndpointId ?? session.getAsyncEndpointId?.() ?? session.getSessionId?.() ?? undefined,
1373
+ ownedRegistrationEndpointId ?? AsyncJobManager.endpointIdOf(manager),
1212
1374
  );
1213
1375
  return resumeJobId;
1214
1376
  };
@@ -1217,21 +1379,21 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1217
1379
  const semaphore = new Semaphore(maxConcurrency);
1218
1380
  const buildForkContextSeedForTask = async (task: TaskItem): Promise<ForkContextSeed | undefined> => {
1219
1381
  if (!requestsForkContext(task)) return undefined;
1220
- if (!this.session.buildForkContextSeed) {
1382
+ if (!session.buildForkContextSeed) {
1221
1383
  throw new Error("Current session cannot build fork-context seeds.");
1222
1384
  }
1223
- const configuredMaxMessages = this.session.settings.has("task.forkContext.maxMessages")
1224
- ? this.session.settings.get("task.forkContext.maxMessages")
1385
+ const configuredMaxMessages = session.settings.has("task.forkContext.maxMessages")
1386
+ ? session.settings.get("task.forkContext.maxMessages")
1225
1387
  : undefined;
1226
- const configuredMaxTokens = this.session.settings.get("task.forkContext.maxTokens");
1388
+ const configuredMaxTokens = session.settings.get("task.forkContext.maxTokens");
1227
1389
  const params = resolveForkSeedParamsForMode(
1228
1390
  task.inheritContext,
1229
1391
  configuredMaxMessages,
1230
1392
  configuredMaxTokens,
1231
- this.session.model,
1393
+ session.model,
1232
1394
  );
1233
1395
  if (!params) return undefined;
1234
- return await this.session.buildForkContextSeed({
1396
+ return await session.buildForkContextSeed({
1235
1397
  ...params,
1236
1398
  signal,
1237
1399
  });
@@ -1328,6 +1490,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1328
1490
  [uniqueId],
1329
1491
  frozenForkSeeds,
1330
1492
  {
1493
+ asyncJobManager: manager,
1331
1494
  sessionFiles: new Map([[uniqueId, subtaskSessionFile]]),
1332
1495
  suppressRoiReconciliation: true,
1333
1496
  persistence: {
@@ -1420,7 +1583,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1420
1583
  },
1421
1584
  {
1422
1585
  id: label,
1423
- ownerId: this.session.getAgentId?.() ?? undefined,
1586
+ ownerId: session.getAgentId?.() ?? undefined,
1424
1587
  metadata: {
1425
1588
  subagent: {
1426
1589
  id: uniqueId,
@@ -1444,19 +1607,23 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1444
1607
  manager,
1445
1608
  _toolCallId,
1446
1609
  jobId,
1447
- this.session.getAsyncEndpointId?.() ?? this.session.getSessionId?.() ?? undefined,
1610
+ session.getAsyncEndpointId?.() ?? session.getSessionId?.() ?? undefined,
1448
1611
  );
1449
1612
  startedJobs.push({ jobId, taskId: taskItem.id });
1450
1613
  if (typeof manager.registerResumeDescriptor === "function") {
1451
1614
  manager.registerResumeDescriptor(
1452
1615
  {
1453
1616
  subagentId: uniqueId,
1454
- ownerId: this.session.getAgentId?.() ?? undefined,
1617
+ ownerId: session.getAgentId?.() ?? undefined,
1455
1618
  data: {
1456
1619
  toolCallId: _toolCallId,
1457
1620
  params,
1458
1621
  task: { ...taskItem, id: uniqueId },
1459
1622
  sessionFile: subtaskSessionFile,
1623
+ artifactPersistence: {
1624
+ effectiveArtifactsDir: batchArtifactsDir,
1625
+ parentArtifactManager: asyncParentArtifactManager,
1626
+ },
1460
1627
  durableOutputAllowed: Boolean(batchArtifactsDir),
1461
1628
  forkContextSeed: frozenForkSeed,
1462
1629
  agentSource: fallbackAgentSource,
@@ -1472,7 +1639,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1472
1639
  if (typeof manager.registerSubagentRecord === "function") {
1473
1640
  manager.registerSubagentRecord({
1474
1641
  subagentId: uniqueId,
1475
- ownerId: this.session.getAgentId?.() ?? undefined,
1642
+ ownerId: session.getAgentId?.() ?? undefined,
1476
1643
  currentJobId: jobId,
1477
1644
  currentJobGeneration: manager.getJob(jobId)?.generation,
1478
1645
  historicalJobIds: [],
@@ -1556,7 +1723,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1556
1723
  ? ` Failed to schedule ${failedSchedules.length} task${failedSchedules.length === 1 ? "" : "s"}.`
1557
1724
  : "";
1558
1725
 
1559
- const ircEnabled = hasAvailableIrcTool(this.session);
1726
+ const ircEnabled = hasAvailableIrcTool(session);
1560
1727
  const taskIdByItemId = new Map<string, string>();
1561
1728
  for (let i = 0; i < taskItems.length; i++) {
1562
1729
  taskIdByItemId.set(taskItems[i].id, uniqueIds[i]);
@@ -1603,11 +1770,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1603
1770
  executionOverrides?: {
1604
1771
  runMode?: "initial" | "resume" | "message";
1605
1772
  resumeMessage?: string;
1773
+ asyncJobManager?: AsyncJobManager;
1606
1774
  sessionFiles?: ReadonlyMap<string, string | null>;
1607
- persistence?: {
1608
- effectiveArtifactsDir: string | undefined;
1609
- parentArtifactManager: ArtifactManager | undefined;
1610
- };
1775
+ persistence?: TaskArtifactPersistence;
1611
1776
  /**
1612
1777
  * Set for per-child async runs: the spawnPlan is carried for gate
1613
1778
  * consistency, but batch-level ROI reconciliation must not be computed
@@ -1616,10 +1781,12 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1616
1781
  suppressRoiReconciliation?: boolean;
1617
1782
  },
1618
1783
  ): Promise<AgentToolResult<TaskToolDetails>> {
1784
+ const session = this.session;
1785
+ const ownedJobManager = executionOverrides?.asyncJobManager ?? this.#resolveOwnedJobManager();
1619
1786
  const startTime = Date.now();
1620
1787
  // Pre-discovery authority: session cwd must still match the capture from create().
1621
1788
  try {
1622
- await assertExecutionRootMatchesRepositoryBinding(this.session.cwd, this.#sessionRepositoryBinding);
1789
+ await assertExecutionRootMatchesRepositoryBinding(session.cwd, this.#sessionRepositoryBinding);
1623
1790
  } catch (error) {
1624
1791
  const message =
1625
1792
  error instanceof RepositoryBindingError
@@ -1629,25 +1796,25 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1629
1796
  : String(error);
1630
1797
  return createTaskModeError(`Session repository binding rejected before task discovery: ${message}`);
1631
1798
  }
1632
- const bindingResolution = await resolveTaskItemsWithRepositoryBindings(this.session.cwd, params.tasks ?? []);
1799
+ const bindingResolution = await resolveTaskItemsWithRepositoryBindings(session.cwd, params.tasks ?? []);
1633
1800
  if (bindingResolution.error) {
1634
1801
  return createTaskModeError(bindingResolution.error);
1635
1802
  }
1636
1803
  const boundParams: TaskParams = { ...params, tasks: bindingResolution.tasks };
1637
1804
 
1638
- const { agents, projectAgentsDir } = await discoverAgents(this.session.cwd);
1805
+ const { agents, projectAgentsDir } = await discoverAgents(session.cwd);
1639
1806
  const { agent: agentName, context, schema: outputSchema } = boundParams;
1640
- const simpleMode = this.#getTaskSimpleMode();
1807
+ const simpleMode = session.settings.get("task.simple");
1641
1808
  const { contextEnabled, customSchemaEnabled } = getTaskSimpleModeCapabilities(simpleMode);
1642
1809
  const sharedContext = contextEnabled ? context?.trim() : undefined;
1643
- const isolationMode = this.session.settings.get("task.isolation.mode");
1810
+ const isolationMode = session.settings.get("task.isolation.mode");
1644
1811
  const isolationRequested = "isolated" in boundParams ? boundParams.isolated === true : false;
1645
1812
  const isIsolated = isolationMode !== "none" && isolationRequested;
1646
- const mergeMode = this.session.settings.get("task.isolation.merge");
1647
- const commitStyle = this.session.settings.get("task.isolation.commits");
1648
- const maxConcurrency = this.session.settings.get("task.maxConcurrency");
1649
- const taskDepth = this.session.taskDepth ?? 0;
1650
- const subagentLspEnabled = (this.session.enableLsp ?? true) && this.session.settings.get("task.enableLsp");
1813
+ const mergeMode = session.settings.get("task.isolation.merge");
1814
+ const commitStyle = session.settings.get("task.isolation.commits");
1815
+ const maxConcurrency = session.settings.get("task.maxConcurrency");
1816
+ const taskDepth = session.taskDepth ?? 0;
1817
+ const subagentLspEnabled = (session.enableLsp ?? true) && session.settings.get("task.enableLsp");
1651
1818
 
1652
1819
  if (isolationMode === "none" && "isolated" in boundParams) {
1653
1820
  return {
@@ -1669,7 +1836,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1669
1836
  const agent = getAgent(agents, agentName);
1670
1837
  if (!agent) {
1671
1838
  const available =
1672
- callableAgents(agents, this.session)
1839
+ callableAgents(agents, session)
1673
1840
  .map(agent => agent.name)
1674
1841
  .join(", ") || "none";
1675
1842
  return {
@@ -1688,7 +1855,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1688
1855
  }
1689
1856
 
1690
1857
  // Check if agent is disabled in settings
1691
- const disabledAgents = this.session.settings.get("task.disabledAgents") as string[];
1858
+ const disabledAgents = session.settings.get("task.disabledAgents") as string[];
1692
1859
  if (disabledAgents.length > 0 && disabledAgents.includes(agentName)) {
1693
1860
  const enabled = filterVisibleAgents(agents)
1694
1861
  .filter(a => !disabledAgents.includes(a.name))
@@ -1711,13 +1878,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1711
1878
  const forkContextValidationError = validateForkContextRequests(
1712
1879
  boundParams.tasks ?? [],
1713
1880
  agent,
1714
- this.session.settings.get("task.forkContext.enabled"),
1881
+ session.settings.get("task.forkContext.enabled"),
1715
1882
  );
1716
1883
  if (forkContextValidationError) {
1717
1884
  return createTaskModeError(forkContextValidationError);
1718
1885
  }
1719
1886
 
1720
- const planModeState = this.session.getPlanModeState?.();
1887
+ const planModeState = session.getPlanModeState?.();
1721
1888
  const planModeTools = ["read", "search", "find", "lsp", "web_search"];
1722
1889
  const effectiveAgent: typeof agent = planModeState?.enabled
1723
1890
  ? {
@@ -1729,21 +1896,19 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1729
1896
  : agent;
1730
1897
 
1731
1898
  // Apply per-agent model override from settings (highest priority)
1732
- const agentModelOverrides = this.session.settings.get("task.agentModelOverrides");
1899
+ const agentModelOverrides = session.settings.get("task.agentModelOverrides");
1733
1900
  const settingsModelOverride = agentModelOverrides[agentName];
1734
- const parentActiveModelPattern = this.session.getActiveModelString?.();
1901
+ const parentActiveModelPattern = session.getActiveModelString?.();
1735
1902
  // A live active model profile claims persisted agent overrides: bare
1736
1903
  // profile aliases may re-resolve to an equivalent provider variant at
1737
1904
  // dispatch. Manual/direct sessions (no active profile) stay exact.
1738
1905
  const parentActiveModelProfile = (
1739
- this.session as { getActiveModelProfile?: () => string | undefined }
1906
+ session as { getActiveModelProfile?: () => string | undefined }
1740
1907
  ).getActiveModelProfile?.();
1741
1908
  // Propagate the parent session's ownership marker when a session-local profile is active.
1742
- const parentModelProfileOwnershipMarker = (
1743
- this.session as { sessionManager?: { getModelProfileOwnershipMarker?: () => unknown } }
1744
- ).sessionManager?.getModelProfileOwnershipMarker?.();
1909
+ const parentModelProfileOwnershipMarker = this.#parentModelProfileOwnershipMarker;
1745
1910
  const parentProfileDefinition = parentActiveModelProfile
1746
- ? this.session.modelRegistry?.getModelProfile?.(parentActiveModelProfile)
1911
+ ? session.modelRegistry?.getModelProfile?.(parentActiveModelProfile)
1747
1912
  : undefined;
1748
1913
  const parentProfileBindings = parentProfileDefinition
1749
1914
  ? resolveProfileBindings(parentProfileDefinition)
@@ -1765,17 +1930,17 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1765
1930
  // profile's role binding before falling back to the parent model.
1766
1931
  settingsOverride: settingsModelOverride ?? parentProfileBinding,
1767
1932
  agentModel: effectiveAgent.model,
1768
- settings: this.session.settings,
1933
+ settings: session.settings,
1769
1934
  activeModelPattern: parentActiveModelPattern,
1770
- fallbackModelPattern: this.session.getModelString?.(),
1935
+ fallbackModelPattern: session.getModelString?.(),
1771
1936
  });
1772
1937
  const thinkingLevelOverride = effectiveAgent.thinkingLevel;
1773
1938
 
1774
1939
  // Output schema priority: task call > agent frontmatter > inherited parent session.
1775
1940
  // task.simple can disable the task-call override while leaving agent/session schemas intact.
1776
1941
  const effectiveOutputSchema = customSchemaEnabled
1777
- ? (outputSchema ?? effectiveAgent.output ?? this.session.outputSchema)
1778
- : (effectiveAgent.output ?? this.session.outputSchema);
1942
+ ? (outputSchema ?? effectiveAgent.output ?? session.outputSchema)
1943
+ : (effectiveAgent.output ?? session.outputSchema);
1779
1944
 
1780
1945
  // Handle empty or missing tasks
1781
1946
  if (!boundParams.tasks || boundParams.tasks.length === 0) {
@@ -1865,7 +2030,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1865
2030
  let baseline: WorktreeBaseline | null = null;
1866
2031
  if (isIsolated) {
1867
2032
  try {
1868
- repoRoot = await getRepoRoot(this.session.cwd);
2033
+ repoRoot = await getRepoRoot(session.cwd);
1869
2034
  baseline = await captureBaseline(repoRoot);
1870
2035
  } catch (err) {
1871
2036
  const message = err instanceof Error ? err.message : String(err);
@@ -1890,15 +2055,16 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1890
2055
  // File-backed session artifacts, or a session-lifetime durable temp root for
1891
2056
  // in-memory parents. Never use a per-task temp dir that is deleted on return —
1892
2057
  // advertised agent:// URIs must remain readable for the parent session lifetime.
1893
- const { effectiveArtifactsDir, parentArtifactManager } =
1894
- executionOverrides?.persistence ?? (await this.#resolveEffectiveArtifactsDir());
2058
+ const { effectiveArtifactsDir, parentArtifactManager } = executionOverrides?.persistence
2059
+ ? this.#resolveAdmittedArtifactPersistence(executionOverrides.persistence)
2060
+ : await this.#resolveEffectiveArtifactsDir();
1895
2061
  const hasDurableOutputBacking = Boolean(effectiveArtifactsDir);
1896
2062
 
1897
2063
  // Share the parent session's local:// root with subagents so they read/write the same scratch space
1898
2064
  const localProtocolOptions: LocalProtocolOptions = {
1899
- getArtifactsDir: this.session.getArtifactsDir ?? (() => null),
1900
- isManagedDestination: this.session.isManagedSessionDestination,
1901
- getSessionId: this.session.getSessionId ?? (() => null),
2065
+ getArtifactsDir: () => this.session.getArtifactsDir?.() ?? null,
2066
+ isManagedDestination: session.isManagedSessionDestination,
2067
+ getSessionId: session.getSessionId ?? (() => null),
1902
2068
  };
1903
2069
 
1904
2070
  // Subagents adopt the parent's ArtifactManager (including session-lifetime
@@ -1942,7 +2108,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1942
2108
  }
1943
2109
 
1944
2110
  // Check spawn restrictions from parent
1945
- const parentSpawns = this.session.getSessionSpawns() ?? "*";
2111
+ const parentSpawns = session.getSessionSpawns() ?? "*";
1946
2112
  const allowedSpawns = parentSpawns.split(",").map(s => s.trim());
1947
2113
  const isSpawnAllowed = (): boolean => {
1948
2114
  if (parentSpawns === "") return false; // Empty = deny all
@@ -1971,8 +2137,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1971
2137
  // Place fork-context handoff material in the session-scoped external local
1972
2138
  // root. Subagent prompts may expose this path to subprocesses, so it must
1973
2139
  // never carry managed transcript/artifact authority.
1974
- const shouldWriteConversationContext = !hasAvailableIrcTool(this.session);
1975
- const compactContext = shouldWriteConversationContext ? this.session.getCompactContext?.() : undefined;
2140
+ const shouldWriteConversationContext = !hasAvailableIrcTool(session);
2141
+ const compactContext = shouldWriteConversationContext ? session.getCompactContext?.() : undefined;
1976
2142
  let contextFilePath: string | undefined;
1977
2143
  if (compactContext) {
1978
2144
  await initializeLocalRoot(localProtocolOptions);
@@ -1988,13 +2154,19 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1988
2154
  uniqueIds = preAllocatedIds;
1989
2155
  } else {
1990
2156
  const outputManager =
1991
- this.session.agentOutputManager ?? new AgentOutputManager(this.session.getArtifactsDir ?? (() => null));
2157
+ this.session.agentOutputManager ??
2158
+ new AgentOutputManager(() => this.session.getArtifactsDir?.() ?? null);
1992
2159
  uniqueIds = await outputManager.allocateBatch(tasks.map(t => t.id));
1993
2160
  }
1994
2161
  const tasksWithUniqueIds = tasks.map((t, i) => ({ ...t, id: validateAllocatedTaskId(uniqueIds[i] ?? "") }));
1995
2162
 
1996
- const effectiveAutorouting = this.session.settings.getEffectiveAutorouting();
1997
- const registry = this.session.modelRegistry as
2163
+ const isResumedRun = executionOverrides?.runMode === "resume" || executionOverrides?.runMode === "message";
2164
+ const routingSettings = isResumedRun ? this.#ownerSession.settings : session.settings;
2165
+ const effectiveAutorouting = routingSettings.getEffectiveAutorouting();
2166
+ const disabledProviders = new Set(
2167
+ routingSettings.get("disabledProviders").map(provider => provider.toLowerCase()),
2168
+ );
2169
+ const registry = session.modelRegistry as
1998
2170
  | {
1999
2171
  getAvailable?: () => Model[];
2000
2172
  getAll?: () => Model[];
@@ -2002,16 +2174,20 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2002
2174
  }
2003
2175
  | undefined;
2004
2176
  const routingSnapshot = registry?.getAll?.() ?? registry?.getAvailable?.();
2177
+ const availableRoutingSnapshot = routingSnapshot?.filter(
2178
+ model => !disabledProviders.has(model.provider.toLowerCase()),
2179
+ );
2005
2180
  const routingByIndex = new Map<number, RoutingOutcome>();
2006
2181
  const routingCandidatesByIndex = new Map<number, string[]>();
2007
2182
  const routingSkipsByIndex = new Map<number, Array<{ selector: string; code: AutoroutingReasonCode }>>();
2183
+ const routingPreflightErrorsByIndex = new Map<number, Map<string, unknown>>();
2008
2184
  for (let i = 0; i < tasksWithUniqueIds.length; i++) {
2009
2185
  const task = tasksWithUniqueIds[i];
2010
2186
  const outcome = routingSnapshot
2011
2187
  ? resolveTaskRouting({
2012
2188
  effectiveAutorouting,
2013
2189
  requestedTier: task.tier,
2014
- availableModels: routingSnapshot,
2190
+ availableModels: availableRoutingSnapshot,
2015
2191
  })
2016
2192
  : effectiveAutorouting.active
2017
2193
  ? {
@@ -2033,9 +2209,6 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2033
2209
  const configured = effectiveAutorouting.map[outcome.tier] ?? [];
2034
2210
  const candidates: string[] = [];
2035
2211
  const skips: Array<{ selector: string; code: AutoroutingReasonCode }> = [];
2036
- const disabledProviders = new Set(
2037
- this.session.settings.get("disabledProviders").map(provider => provider.toLowerCase()),
2038
- );
2039
2212
  for (const selector of configured) {
2040
2213
  const slash = selector.indexOf("/");
2041
2214
  const provider = slash > 0 ? selector.slice(0, slash).toLowerCase() : "";
@@ -2060,6 +2233,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2060
2233
  }
2061
2234
  const resolveAutoroutingCandidates = async (
2062
2235
  index: number,
2236
+ stopAfterFirstAuthenticatedCandidate = false,
2063
2237
  ): Promise<{
2064
2238
  candidates: string[];
2065
2239
  skips: Array<{ selector: string; code: AutoroutingReasonCode }>;
@@ -2079,19 +2253,38 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2079
2253
  try {
2080
2254
  const key = await registry.getApiKey(
2081
2255
  model,
2082
- this.session.getCredentialSessionId?.() ?? this.session.getSessionId?.() ?? undefined,
2256
+ session.getCredentialSessionId?.() ?? session.getSessionId?.() ?? undefined,
2083
2257
  );
2084
- if (key) authenticated.push(selector);
2085
- else skips.push({ selector, code: "credential_unavailable" });
2258
+ if (key) {
2259
+ authenticated.push(selector);
2260
+ if (stopAfterFirstAuthenticatedCandidate) break;
2261
+ } else skips.push({ selector, code: "credential_unavailable" });
2086
2262
  } catch (error) {
2087
- // Preserve the candidate for executor preflight, which records the
2088
- // terminal lookup failure in the routing ledger.
2263
+ // Preserve lookup errors for executor terminalization; only a returned
2264
+ // undefined value means this candidate may be skipped.
2089
2265
  preflightErrors.set(selector, error);
2090
2266
  authenticated.push(selector);
2267
+ if (stopAfterFirstAuthenticatedCandidate) break;
2091
2268
  }
2092
2269
  }
2093
2270
  return { candidates: authenticated, skips, preflightErrors };
2094
2271
  };
2272
+ if (isResumedRun) {
2273
+ for (const [index, outcome] of routingByIndex) {
2274
+ if (outcome.kind !== "routed") continue;
2275
+ const { candidates, skips, preflightErrors } = await resolveAutoroutingCandidates(index, true);
2276
+ routingSkipsByIndex.set(index, skips);
2277
+ const pinnedSelector = candidates[0];
2278
+ if (pinnedSelector) {
2279
+ routingCandidatesByIndex.set(index, [pinnedSelector]);
2280
+ if (preflightErrors.size > 0) routingPreflightErrorsByIndex.set(index, preflightErrors);
2281
+ routingByIndex.set(index, { ...outcome, pinnedSelector });
2282
+ continue;
2283
+ }
2284
+ routingPreflightErrorsByIndex.delete(index);
2285
+ routingCandidatesByIndex.set(index, []);
2286
+ }
2287
+ }
2095
2288
  const effectivePatterns = (index: number): string | string[] => {
2096
2289
  const outcome = routingByIndex.get(index);
2097
2290
  return outcome?.kind === "routed" ? [outcome.pinnedSelector] : modelOverride;
@@ -2110,7 +2303,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2110
2303
  };
2111
2304
  };
2112
2305
 
2113
- const availableSkills = [...(this.session.skills ?? [])];
2306
+ const availableSkills = [...(session.skills ?? [])];
2114
2307
  // Resolve autoload skills from agent definition against available skills
2115
2308
  const resolvedAutoloadSkills =
2116
2309
  agent.autoloadSkills?.length && availableSkills.length > 0
@@ -2118,11 +2311,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2118
2311
  .map(name => availableSkills.find(s => s.name === name))
2119
2312
  .filter((s): s is NonNullable<typeof s> => s !== undefined)
2120
2313
  : [];
2121
- const contextFiles = this.session.contextFiles?.filter(
2314
+ const contextFiles = session.contextFiles?.filter(
2122
2315
  file => path.basename(file.path).toLowerCase() !== "agents.md",
2123
2316
  );
2124
- const promptTemplates = this.session.promptTemplates;
2125
- const parentMcpManager = this.session.getMcpManager?.();
2317
+ const promptTemplates = session.promptTemplates;
2318
+ const parentMcpManager = session.getMcpManager?.();
2126
2319
  // Exact-config tools-only managers belong to the top-level ACP session and cannot be reused by sub-sessions.
2127
2320
  const reusableParentMcpManager = parentMcpManager?.isToolsOnly() ? undefined : parentMcpManager;
2128
2321
 
@@ -2152,21 +2345,21 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2152
2345
 
2153
2346
  const buildForkContextSeed = async (task: (typeof tasksWithUniqueIds)[number]) => {
2154
2347
  if (!requestsForkContext(task)) return undefined;
2155
- if (!this.session.buildForkContextSeed) {
2348
+ if (!session.buildForkContextSeed) {
2156
2349
  throw new Error("Current session cannot build fork-context seeds.");
2157
2350
  }
2158
- const configuredMaxMessages = this.session.settings.has("task.forkContext.maxMessages")
2159
- ? this.session.settings.get("task.forkContext.maxMessages")
2351
+ const configuredMaxMessages = session.settings.has("task.forkContext.maxMessages")
2352
+ ? session.settings.get("task.forkContext.maxMessages")
2160
2353
  : undefined;
2161
- const configuredMaxTokens = this.session.settings.get("task.forkContext.maxTokens");
2354
+ const configuredMaxTokens = session.settings.get("task.forkContext.maxTokens");
2162
2355
  const params = resolveForkSeedParamsForMode(
2163
2356
  task.inheritContext,
2164
2357
  configuredMaxMessages,
2165
2358
  configuredMaxTokens,
2166
- this.session.model,
2359
+ session.model,
2167
2360
  );
2168
2361
  if (!params) return undefined;
2169
- return await this.session.buildForkContextSeed({
2362
+ return await session.buildForkContextSeed({
2170
2363
  ...params,
2171
2364
  signal,
2172
2365
  });
@@ -2185,7 +2378,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2185
2378
  // The session's ENDPOINT-owned manager (resolved once per task so
2186
2379
  // model metadata and live handles land in the SAME manager the
2187
2380
  // job runs in — review thread P1).
2188
- const manager = this.#resolveOwnedJobManager();
2381
+ const manager = ownedJobManager;
2189
2382
  const forkContext = requestsForkContext(task)
2190
2383
  ? { mode: task.inheritContext, clonedTokens: forkContextSeed?.metadata.approximateTokens ?? 0 }
2191
2384
  : undefined;
@@ -2200,8 +2393,14 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2200
2393
  recommendedMode: advisory.recommendedMode,
2201
2394
  reasons: advisory.reasons,
2202
2395
  };
2396
+ let retainedPersistence: TaskArtifactPersistence = { effectiveArtifactsDir, parentArtifactManager };
2203
2397
  const managedPersistence = parentArtifactManager?.getManagedStore()
2204
- ? createManagedTaskPersistence(parentArtifactManager, task.id)
2398
+ ? createManagedTaskPersistence(parentArtifactManager, task.id, () => {
2399
+ retainedPersistence = this.#resolveAdmittedArtifactPersistence(retainedPersistence);
2400
+ if (!retainedPersistence.parentArtifactManager)
2401
+ throw new Error("Managed Task storage authority is unavailable");
2402
+ return retainedPersistence.parentArtifactManager;
2403
+ })
2205
2404
  : undefined;
2206
2405
 
2207
2406
  const routingOutcome = routingByIndex.get(index);
@@ -2232,6 +2431,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2232
2431
  const effectiveRunMode = overrides?.runMode ?? executionOverrides?.runMode;
2233
2432
  const autoroutingInitial =
2234
2433
  routingOutcome?.kind === "routed" && (effectiveRunMode ?? "initial") === "initial";
2434
+ const includeAutoroutingResolution =
2435
+ autoroutingInitial || effectiveRunMode === "resume" || effectiveRunMode === "message";
2235
2436
  const autoroutingData =
2236
2437
  (effectiveRunMode ?? "initial") === "initial" && routingOutcome && routingOutcome.kind !== "disabled"
2237
2438
  ? routingOutcome.kind === "routed"
@@ -2241,7 +2442,14 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2241
2442
  skips: [...(routingSkipsByIndex.get(index) ?? [])],
2242
2443
  preflightErrors: new Map(),
2243
2444
  }
2244
- : { candidates: undefined, skips: undefined, preflightErrors: new Map() };
2445
+ : {
2446
+ candidates:
2447
+ includeAutoroutingResolution && routingOutcome?.kind === "routed"
2448
+ ? [...(routingCandidatesByIndex.get(index) ?? [])]
2449
+ : undefined,
2450
+ skips: [...(routingSkipsByIndex.get(index) ?? [])],
2451
+ preflightErrors: routingPreflightErrorsByIndex.get(index) ?? new Map(),
2452
+ };
2245
2453
  const routingForRun = routeEvidence(
2246
2454
  routingOutcome,
2247
2455
  effectiveRunMode === "resume" || effectiveRunMode === "message",
@@ -2257,9 +2465,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2257
2465
  assertPathUnderRepositoryBinding(taskRepositoryBinding, ".");
2258
2466
  }
2259
2467
  if (!isIsolated) {
2260
- await assertExecutionRootMatchesRepositoryBinding(this.session.cwd, taskRepositoryBinding);
2468
+ await assertExecutionRootMatchesRepositoryBinding(session.cwd, taskRepositoryBinding);
2261
2469
  const result = await this.#runSubprocess({
2262
- cwd: this.session.cwd,
2470
+ cwd: session.cwd,
2263
2471
  agent: effectiveAgent,
2264
2472
  task: renderTaskAssignment(task.assignment, simpleMode),
2265
2473
  assignment: task.assignment.trim(),
@@ -2278,9 +2486,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2278
2486
  parentActiveModelPattern,
2279
2487
  parentActiveModelProfile: parentOwnedModelProfile,
2280
2488
  parentModelProfileOwnershipMarker: parentModelProfileOwnershipMarker as any,
2281
- parentSessionId: this.session.getSessionId?.() ?? undefined,
2489
+ parentSessionId: session.getSessionId?.() ?? undefined,
2282
2490
  parentCredentialSessionId:
2283
- this.session.getCredentialSessionId?.() ?? this.session.getSessionId?.() ?? undefined,
2491
+ session.getCredentialSessionId?.() ?? session.getSessionId?.() ?? undefined,
2284
2492
  thinkingLevel: thinkingLevelOverride,
2285
2493
  outputSchema: effectiveOutputSchema,
2286
2494
  sessionFile: taskSessionFile,
@@ -2288,39 +2496,43 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2288
2496
  artifactsDir: effectiveArtifactsDir,
2289
2497
  managedPersistence,
2290
2498
  contextFile: contextFilePath,
2291
- ircAvailable: hasAvailableIrcTool(this.session),
2499
+ ircAvailable: hasAvailableIrcTool(session),
2292
2500
  enableLsp: subagentLspEnabled,
2293
2501
  signal,
2294
- eventBus: this.session.eventBus,
2502
+ eventBus: session.eventBus,
2295
2503
  routing: routingForRun,
2296
- autoroutingCandidates: autoroutingInitial ? autoroutingData.candidates : undefined,
2297
- autoroutingSkips: autoroutingInitial ? autoroutingData.skips : undefined,
2298
- autoroutingPreflightErrors: autoroutingInitial ? autoroutingData.preflightErrors : undefined,
2504
+ autoroutingCandidates: includeAutoroutingResolution ? autoroutingData.candidates : undefined,
2505
+ autoroutingSkips: includeAutoroutingResolution ? autoroutingData.skips : undefined,
2506
+ autoroutingPreflightErrors: includeAutoroutingResolution
2507
+ ? autoroutingData.preflightErrors
2508
+ : undefined,
2299
2509
  autoroutingPreflight: autoroutingInitial,
2300
2510
 
2301
2511
  onProgress: progress => {
2302
2512
  progressMap.set(index, {
2303
2513
  ...structuredClone(progress),
2304
2514
  });
2305
- this.#resolveOwnedJobManager()?.recordSubagentProgress(task.id, progress);
2515
+ ownedJobManager?.recordSubagentProgress(task.id, progress);
2306
2516
  emitProgress();
2307
2517
  },
2308
- authStorage: this.session.authStorage,
2309
- modelRegistry: this.session.modelRegistry,
2310
- agentRegistry: this.session.agentRegistry,
2311
- settings: this.session.settings,
2312
- agentDir: this.session.getSessionAgentDir?.() ?? this.session.settings.getAgentDir(),
2313
- profileAuthority: this.session.profileAuthority,
2314
- inheritedServiceTier: this.session.serviceTier,
2518
+ authStorage: session.authStorage,
2519
+ modelRegistry: session.modelRegistry,
2520
+ agentRegistry: session.agentRegistry,
2521
+ settings: session.settings,
2522
+ agentDir: session.getSessionAgentDir?.() ?? session.settings.getAgentDir(),
2523
+ profileAuthority: session.profileAuthority,
2524
+ inheritedServiceTier: session.serviceTier,
2525
+ ...inheritedSubagentApproval(session),
2526
+ ...inheritedPlanMode(session),
2315
2527
  contextFiles,
2316
2528
  skills: availableSkills,
2317
2529
  autoloadSkills: resolvedAutoloadSkills,
2318
- workspaceTree: this.session.workspaceTree,
2530
+ workspaceTree: session.workspaceTree,
2319
2531
  promptTemplates,
2320
2532
  localProtocolOptions,
2321
2533
  parentArtifactManager,
2322
- parentHindsightSessionState: this.session.getHindsightSessionState?.(),
2323
- parentTelemetry: this.session.getTelemetry?.(),
2534
+ parentHindsightSessionState: session.getHindsightSessionState?.(),
2535
+ parentTelemetry: session.getTelemetry?.(),
2324
2536
  parentMcpManager: reusableParentMcpManager,
2325
2537
  forkContextSeed,
2326
2538
  });
@@ -2346,7 +2558,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2346
2558
  await assertExecutionRootMatchesRepositoryBinding(isolationDir, taskRepositoryBinding);
2347
2559
 
2348
2560
  const result = await this.#runSubprocess({
2349
- cwd: this.session.cwd,
2561
+ cwd: session.cwd,
2350
2562
  worktree: isolationDir,
2351
2563
  agent: effectiveAgent,
2352
2564
  task: renderTaskAssignment(task.assignment, simpleMode),
@@ -2366,9 +2578,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2366
2578
  parentActiveModelPattern,
2367
2579
  parentActiveModelProfile: parentOwnedModelProfile,
2368
2580
  parentModelProfileOwnershipMarker: parentModelProfileOwnershipMarker as any,
2369
- parentSessionId: this.session.getSessionId?.() ?? undefined,
2581
+ parentSessionId: session.getSessionId?.() ?? undefined,
2370
2582
  parentCredentialSessionId:
2371
- this.session.getCredentialSessionId?.() ?? this.session.getSessionId?.() ?? undefined,
2583
+ session.getCredentialSessionId?.() ?? session.getSessionId?.() ?? undefined,
2372
2584
  thinkingLevel: thinkingLevelOverride,
2373
2585
  outputSchema: effectiveOutputSchema,
2374
2586
  sessionFile: taskSessionFile,
@@ -2376,38 +2588,42 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2376
2588
  artifactsDir: effectiveArtifactsDir,
2377
2589
  managedPersistence,
2378
2590
  contextFile: contextFilePath,
2379
- ircAvailable: hasAvailableIrcTool(this.session),
2591
+ ircAvailable: hasAvailableIrcTool(session),
2380
2592
  enableLsp: subagentLspEnabled,
2381
2593
  signal,
2382
- eventBus: this.session.eventBus,
2594
+ eventBus: session.eventBus,
2383
2595
  routing: routingForRun,
2384
- autoroutingCandidates: autoroutingInitial ? autoroutingData.candidates : undefined,
2385
- autoroutingSkips: autoroutingInitial ? autoroutingData.skips : undefined,
2386
- autoroutingPreflightErrors: autoroutingInitial ? autoroutingData.preflightErrors : undefined,
2596
+ autoroutingCandidates: includeAutoroutingResolution ? autoroutingData.candidates : undefined,
2597
+ autoroutingSkips: includeAutoroutingResolution ? autoroutingData.skips : undefined,
2598
+ autoroutingPreflightErrors: includeAutoroutingResolution
2599
+ ? autoroutingData.preflightErrors
2600
+ : undefined,
2387
2601
  autoroutingPreflight: autoroutingInitial,
2388
2602
  onProgress: progress => {
2389
2603
  progressMap.set(index, {
2390
2604
  ...structuredClone(progress),
2391
2605
  });
2392
- this.#resolveOwnedJobManager()?.recordSubagentProgress(task.id, progress);
2606
+ ownedJobManager?.recordSubagentProgress(task.id, progress);
2393
2607
  emitProgress();
2394
2608
  },
2395
- authStorage: this.session.authStorage,
2396
- modelRegistry: this.session.modelRegistry,
2397
- agentRegistry: this.session.agentRegistry,
2398
- settings: this.session.settings,
2399
- agentDir: this.session.getSessionAgentDir?.() ?? this.session.settings.getAgentDir(),
2400
- profileAuthority: this.session.profileAuthority,
2401
- inheritedServiceTier: this.session.serviceTier,
2609
+ authStorage: session.authStorage,
2610
+ modelRegistry: session.modelRegistry,
2611
+ agentRegistry: session.agentRegistry,
2612
+ settings: session.settings,
2613
+ agentDir: session.getSessionAgentDir?.() ?? session.settings.getAgentDir(),
2614
+ profileAuthority: session.profileAuthority,
2615
+ inheritedServiceTier: session.serviceTier,
2616
+ ...inheritedSubagentApproval(session),
2617
+ ...inheritedPlanMode(session),
2402
2618
  contextFiles,
2403
2619
  skills: availableSkills,
2404
2620
  autoloadSkills: resolvedAutoloadSkills,
2405
- workspaceTree: this.session.workspaceTree,
2621
+ workspaceTree: session.workspaceTree,
2406
2622
  promptTemplates,
2407
2623
  localProtocolOptions,
2408
2624
  parentArtifactManager,
2409
- parentHindsightSessionState: this.session.getHindsightSessionState?.(),
2410
- parentTelemetry: this.session.getTelemetry?.(),
2625
+ parentHindsightSessionState: session.getHindsightSessionState?.(),
2626
+ parentTelemetry: session.getTelemetry?.(),
2411
2627
  parentMcpManager: reusableParentMcpManager,
2412
2628
  forkContextSeed,
2413
2629
  });
@@ -2425,15 +2641,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
2425
2641
  if (mergeMode === "branch" && taskSucceeded) {
2426
2642
  try {
2427
2643
  const commitMsg =
2428
- commitStyle === "ai" && this.session.modelRegistry
2644
+ commitStyle === "ai" && session.modelRegistry
2429
2645
  ? async (diff: string) => {
2430
2646
  return generateCommitMessage(
2431
2647
  diff,
2432
- this.session.modelRegistry!,
2433
- this.session.settings,
2434
- this.session.getCredentialSessionId?.() ??
2435
- this.session.getSessionId?.() ??
2436
- undefined,
2648
+ session.modelRegistry!,
2649
+ session.settings,
2650
+ session.getCredentialSessionId?.() ?? session.getSessionId?.() ?? undefined,
2437
2651
  );
2438
2652
  }
2439
2653
  : undefined;