@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
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs/promises";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
- import { $which, logger, Snowflake } from "@gajae-code/utils";
4
+ import { $which, logger } from "@gajae-code/utils";
5
5
  import { $ } from "bun";
6
6
 
7
7
  export interface RecordingHandle {
@@ -212,10 +212,29 @@ if (Test-Path $outPath) {
212
212
  }
213
213
  `;
214
214
 
215
+ async function writePowerShellRecordingScript(): Promise<{ tempDir: string; scriptPath: string }> {
216
+ // Random directory plus an exclusive create: a preexisting symlink under the
217
+ // shared temp directory is not opened, and the script is not left world-readable.
218
+ const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "gjc-stt-record-"));
219
+ try {
220
+ if (process.platform !== "win32") await fs.chmod(tempDir, 0o700);
221
+ const scriptPath = path.join(tempDir, "record.ps1");
222
+ const handle = await fs.open(scriptPath, "wx", 0o600);
223
+ try {
224
+ await handle.writeFile(PS_RECORD_SCRIPT);
225
+ } finally {
226
+ await handle.close();
227
+ }
228
+ if (process.platform !== "win32") await fs.chmod(scriptPath, 0o600);
229
+ return { tempDir, scriptPath };
230
+ } catch (error) {
231
+ await fs.rm(tempDir, { recursive: true, force: true });
232
+ throw error;
233
+ }
234
+ }
235
+
215
236
  async function startPowerShellRecording(outputPath: string): Promise<RecordingHandle> {
216
- // Write script to temp file — avoids quoting/escaping issues with -Command
217
- const scriptPath = path.join(os.tmpdir(), `gjc-stt-record-${Snowflake.next()}.ps1`);
218
- await Bun.write(scriptPath, PS_RECORD_SCRIPT);
237
+ const { tempDir, scriptPath } = await writePowerShellRecordingScript();
219
238
 
220
239
  const proc = Bun.spawn(["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", scriptPath, outputPath], {
221
240
  stdin: "pipe",
@@ -224,7 +243,7 @@ async function startPowerShellRecording(outputPath: string): Promise<RecordingHa
224
243
  });
225
244
 
226
245
  proc.exited.then(() => {
227
- fs.unlink(scriptPath).catch(() => {});
246
+ fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
228
247
  });
229
248
 
230
249
  // Wait for "RECORDING" on stdout to confirm it started
@@ -250,8 +269,7 @@ async function startPowerShellRecording(outputPath: string): Promise<RecordingHa
250
269
  if (proc.stderr && typeof proc.stderr !== "number") {
251
270
  stderrText = await new Response(proc.stderr as ReadableStream).text();
252
271
  }
253
- // Clean up temp script
254
- fs.unlink(scriptPath).catch(() => {});
272
+ fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
255
273
  throw new Error(
256
274
  `PowerShell audio recording failed to start: ${stderrText.trim() || output.trim() || "(no output)"}`,
257
275
  );
@@ -269,8 +287,7 @@ async function startPowerShellRecording(outputPath: string): Promise<RecordingHa
269
287
  const killTimer = setTimeout(() => proc.kill(), 8000);
270
288
  await proc.exited;
271
289
  clearTimeout(killTimer);
272
- // Clean up temp script
273
- fs.unlink(scriptPath).catch(() => {});
290
+ fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
274
291
  },
275
292
  };
276
293
  }
@@ -75,6 +75,31 @@ function sanitizeEmbeddedPromptContent(content: string): string {
75
75
  return escapePromptMetadata(content, { preserveNewlines: true });
76
76
  }
77
77
 
78
+ const UNTRUSTED_CONTENT_OPEN_LINE = "<untrusted-content>\n";
79
+ const UNTRUSTED_CONTENT_CLOSE_LINE = "\n</untrusted-content>";
80
+
81
+ /**
82
+ * Encode an inventory description. MCP descriptions already include a host-owned
83
+ * untrusted-content fence; keep those delimiters and encode only the body.
84
+ * A body that still contains a closing fence is not that wrapper, so encode the whole value.
85
+ */
86
+ function escapeInventoryDescription(description: string): string {
87
+ const openLength = UNTRUSTED_CONTENT_OPEN_LINE.length;
88
+ const closeLength = UNTRUSTED_CONTENT_CLOSE_LINE.length;
89
+ if (
90
+ description.startsWith(UNTRUSTED_CONTENT_OPEN_LINE) &&
91
+ description.endsWith(UNTRUSTED_CONTENT_CLOSE_LINE) &&
92
+ description.length >= openLength + closeLength
93
+ ) {
94
+ const body = description.slice(openLength, -closeLength);
95
+ if (!/<\/untrusted-content>/i.test(body)) {
96
+ const encodedBody = escapePromptMetadata(body, { preserveNewlines: true });
97
+ return `${UNTRUSTED_CONTENT_OPEN_LINE}${encodedBody}${UNTRUSTED_CONTENT_CLOSE_LINE}`;
98
+ }
99
+ }
100
+ return escapePromptMetadata(description, { preserveNewlines: true });
101
+ }
102
+
78
103
  function firstNonEmpty(...values: (string | undefined | null)[]): string | null {
79
104
  for (const value of values) {
80
105
  const trimmed = value?.trim();
@@ -345,8 +370,9 @@ export async function loadProjectContextFiles(
345
370
  }
346
371
 
347
372
  /**
348
- * Load the effective system prompt customization from SYSTEM.md.
349
- * Project-level SYSTEM.md overrides user-level SYSTEM.md.
373
+ * Load the user system prompt customization from SYSTEM.md.
374
+ * A repository SYSTEM.md is untrusted project text. It must not replace the
375
+ * user file or become the customization block.
350
376
  */
351
377
  export async function loadSystemPromptFiles(options: LoadContextFilesOptions = {}): Promise<string | null> {
352
378
  const resolvedCwd = options.cwd ?? getProjectDir();
@@ -359,11 +385,6 @@ export async function loadSystemPromptFiles(options: LoadContextFilesOptions = {
359
385
 
360
386
  if (result.items.length === 0) return null;
361
387
 
362
- const projectLevel = result.items.find(item => item.level === "project");
363
- if (projectLevel) {
364
- return projectLevel.content;
365
- }
366
-
367
388
  const userLevel = result.items.find(item => item.level === "user");
368
389
  return userLevel?.content ?? null;
369
390
  }
@@ -745,18 +766,31 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
745
766
  const toolPromptNames = new Map<string, string>(toolNames.map(name => [name, tools?.get(name)?.wireName ?? name]));
746
767
  const toolRefs = Object.fromEntries(toolPromptNames.entries());
747
768
  const hasHiddenToolDiscoveryTool = Object.hasOwn(toolRefs, "search_tool_bm25");
748
- const toolInfo = toolNames.map(name => ({
749
- name: toolPromptNames.get(name) ?? name,
750
- internalName: name,
751
- label: tools?.get(name)?.label ?? "",
752
- description: tools?.get(name)?.description ?? "",
753
- }));
769
+ // The inventory template is compiled with noEscape. Encode tool metadata here so a
770
+ // tools/list label or description cannot close <inventory> or insert a system block.
771
+ // Repeated MCP descriptions keep the host <untrusted-content> fence; only the body is encoded.
772
+ // The `tools` list stays raw so {{#has}} still matches the call name.
773
+ const toolInfo = toolNames.map(name => {
774
+ const meta = tools?.get(name);
775
+ return {
776
+ name: escapePromptMetadata(toolPromptNames.get(name) ?? name),
777
+ internalName: escapePromptMetadata(name),
778
+ label: escapePromptMetadata(meta?.label ?? ""),
779
+ description: escapeInventoryDescription(meta?.description ?? ""),
780
+ };
781
+ });
754
782
 
755
- const effectiveSystemPromptCustomization = dedupePromptSource(systemPromptCustomization, [
783
+ const rawSystemPromptCustomization = dedupePromptSource(systemPromptCustomization, [
756
784
  resolvedCustomPrompt,
757
785
  resolvedAppendPrompt,
758
786
  ]);
759
- const promptSources = [effectiveSystemPromptCustomization, resolvedCustomPrompt, resolvedAppendPrompt];
787
+ // Encode after dedupe so rule matching still sees the file text. The customization
788
+ // template is noEscape; the same encoder used for context files keeps a file from
789
+ // closing <system-prompt-customization> or forging a sibling marker.
790
+ const effectiveSystemPromptCustomization = rawSystemPromptCustomization
791
+ ? sanitizeEmbeddedPromptContent(rawSystemPromptCustomization)
792
+ : "";
793
+ const promptSources = [rawSystemPromptCustomization, resolvedCustomPrompt, resolvedAppendPrompt];
760
794
  const injectedAlwaysApplyRules = dedupeAlwaysApplyRules(alwaysApplyRules, promptSources);
761
795
 
762
796
  const environment = await logger.time("getEnvironmentInfo", getEnvironmentInfo);
@@ -771,6 +805,17 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
771
805
  path: escapePromptMetadata(rule.path),
772
806
  content: sanitizeEmbeddedPromptContent(rule.content),
773
807
  }));
808
+ // Both rulebook templates compile with noEscape. Encode the fields they interpolate
809
+ // so repository frontmatter cannot close <rules> or the name attribute.
810
+ const sanitizedRulebookRules = (rules ?? []).map(rule => ({
811
+ ...rule,
812
+ name: escapePromptMetadata(rule.name),
813
+ description:
814
+ rule.description === undefined
815
+ ? undefined
816
+ : escapePromptMetadata(rule.description, { preserveNewlines: true }),
817
+ globs: rule.globs?.map(glob => escapePromptMetadata(glob)),
818
+ }));
774
819
  const data = {
775
820
  systemPromptCustomization: effectiveSystemPromptCustomization,
776
821
  customPrompt: resolvedCustomPrompt,
@@ -784,7 +829,7 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
784
829
  contextFiles: sanitizedContextFiles,
785
830
  agentsMdSearch: { files: agentsMdFiles.map(file => escapePromptMetadata(file)) },
786
831
  workspaceTree,
787
- rules: rules ?? [],
832
+ rules: sanitizedRulebookRules,
788
833
  alwaysApplyRules: sanitizedAlwaysApplyRules,
789
834
  cwd: promptCwd,
790
835
  intentTracing: !!intentField,
@@ -51,6 +51,7 @@ import { buildSkillPromptMessage, type Skill } from "../extensibility/skills";
51
51
  import { sessionRoot } from "../gjc-runtime/session-layout";
52
52
  import type { HindsightSessionState } from "../hindsight/state";
53
53
  import type { LocalProtocolOptions } from "../internal-urls";
54
+ import type { PlanModeState } from "../plan-mode/state";
54
55
  import subagentSystemPromptTemplate from "../prompts/system/subagent-system-prompt.md" with { type: "text" };
55
56
  import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.md" with { type: "text" };
56
57
  import submitReminderTemplate from "../prompts/system/subagent-yield-reminder.md" with { type: "text" };
@@ -59,6 +60,7 @@ import { discoverAuthStorage } from "../sdk";
59
60
  import type { AgentSession, AgentSessionEvent, ForkContextSeed } from "../session/agent-session";
60
61
  import { ArtifactManager } from "../session/artifacts";
61
62
  import type { AuthStorage } from "../session/auth-storage";
63
+ import type { ClientBridge } from "../session/client-bridge";
62
64
  import { SKILL_PROMPT_MESSAGE_TYPE } from "../session/messages";
63
65
  import { SessionManager, type SessionMemoryMode } from "../session/session-manager";
64
66
  import { FileSessionStorage } from "../session/session-storage";
@@ -74,6 +76,7 @@ import { buildNamedToolChoiceResult } from "../utils/tool-choice";
74
76
  import type { WorkspaceTree } from "../workspace-tree";
75
77
  import { validateAllocatedTaskId } from "./id";
76
78
  import { classifyProviderRetryFromTransport, providerNameFromModel } from "./provider-retry-status";
79
+ import { containSubagentRoleBody } from "./role-body";
77
80
  import { subprocessToolRegistry } from "./subprocess-tool-registry";
78
81
  import { persistTaskTokenLog, taskTokenLogFromUsage } from "./token-log";
79
82
  import {
@@ -300,6 +303,21 @@ export interface ExecutorOptions {
300
303
  * the same immutable child settings snapshot.
301
304
  */
302
305
  inheritedServiceTier?: ServiceTier;
306
+ /**
307
+ * Parent ACP/SDK approval mode. `deny` and `prompt` replace the child
308
+ * default (`allow`) before the first prompt. `allow` is that default.
309
+ */
310
+ sdkPermissionMode?: "prompt" | "allow" | "deny";
311
+ /**
312
+ * Parent plan-mode state. Copied onto the child before the first prompt so
313
+ * `enforcePlanModeWrite` still refuses product-file writes.
314
+ */
315
+ planModeState?: PlanModeState;
316
+ /**
317
+ * Parent client bridge. Only `requestPermission` is copied onto the child.
318
+ * Terminal, filesystem, and deferAgentInitiatedTurns stay on the parent.
319
+ */
320
+ clientBridge?: ClientBridge;
303
321
  /** Override local:// protocol options so subagent shares parent's local:// root */
304
322
  localProtocolOptions?: LocalProtocolOptions;
305
323
  /**
@@ -342,28 +360,32 @@ export interface ExecutorOptions {
342
360
  export class ManagedTaskPersistence {
343
361
  readonly #artifacts: ArtifactManager;
344
362
  readonly #taskId: string;
363
+ readonly #getArtifacts: () => ArtifactManager;
345
364
 
346
- constructor(artifacts: ArtifactManager, taskId: string) {
365
+ constructor(artifacts: ArtifactManager, taskId: string, getArtifacts: () => ArtifactManager = () => artifacts) {
347
366
  this.#artifacts = artifacts;
348
367
  this.#taskId = validateAllocatedTaskId(taskId);
368
+ this.#getArtifacts = getArtifacts;
349
369
  if (!artifacts.getManagedSubtreeRootAuthority())
350
370
  throw new Error("Managed task persistence authority is unavailable");
351
371
  }
352
372
 
353
373
  async openSession(cwd: string, sessionMemoryMode: SessionMemoryMode = "shadow"): Promise<SessionManager> {
354
- const store = this.#artifacts.getManagedStore();
374
+ const artifacts = this.#getArtifacts();
375
+ const store = artifacts.getManagedStore();
355
376
  if (!store) throw new Error("Managed task persistence authority is unavailable");
356
- this.#artifacts.assertManagedBinding();
357
- const sessionFile = path.join(this.#artifacts.dir, `${this.#taskId}.jsonl`);
377
+ artifacts.assertManagedBinding();
378
+ const sessionFile = path.join(artifacts.dir, `${this.#taskId}.jsonl`);
358
379
  const session = await SessionManager.openNestedManaged(
359
380
  sessionFile,
360
- SessionManager.nestedManagedDestination(store, this.#artifacts.dir),
381
+ SessionManager.nestedManagedDestination(store, artifacts.dir),
361
382
  store,
362
383
  undefined,
363
384
  cwd,
364
385
  sessionMemoryMode,
365
386
  );
366
- this.#artifacts.assertManagedBinding();
387
+ artifacts.assertManagedBinding();
388
+ session.registerManagedTranscriptRelocationResolver(this.#getArtifacts);
367
389
  return session;
368
390
  }
369
391
  async openStagedSession(attemptId = this.#taskId): Promise<SessionManager> {
@@ -385,8 +407,10 @@ export class ManagedTaskPersistence {
385
407
  }
386
408
 
387
409
  async publishOutput(rawOutput: string, metadata: Uint8Array): Promise<void> {
388
- await withArtifactManagerFinalizationTurn(this.#artifacts, () =>
389
- this.#artifacts.publishManagedOutputGeneration(
410
+ const artifacts = this.#getArtifacts();
411
+ artifacts.assertManagedBinding();
412
+ await withArtifactManagerFinalizationTurn(artifacts, () =>
413
+ artifacts.publishManagedOutputGeneration(
390
414
  `${this.#taskId}.md.selector.json`,
391
415
  `${this.#taskId}.md`,
392
416
  Buffer.from(rawOutput, "utf8"),
@@ -396,8 +420,12 @@ export class ManagedTaskPersistence {
396
420
  }
397
421
  }
398
422
 
399
- export function createManagedTaskPersistence(artifacts: ArtifactManager, taskId: string): ManagedTaskPersistence {
400
- return new ManagedTaskPersistence(artifacts, taskId);
423
+ export function createManagedTaskPersistence(
424
+ artifacts: ArtifactManager,
425
+ taskId: string,
426
+ getArtifacts?: () => ArtifactManager,
427
+ ): ManagedTaskPersistence {
428
+ return new ManagedTaskPersistence(artifacts, taskId, getArtifacts);
401
429
  }
402
430
 
403
431
  const MAX_REVIEW_FINDINGS_ARTIFACT_BYTES = 16 * 1024 * 1024;
@@ -1006,6 +1034,16 @@ function autoroutingAttemptDisposition(failure: AutoroutingPreflightFailure): {
1006
1034
  return { code: "unclassified_terminal", advance: false };
1007
1035
  }
1008
1036
 
1037
+ /** Permission callback only. Terminal, filesystem, and defer flags stay on the parent. */
1038
+ function permissionOnlyBridge(bridge: ClientBridge | undefined): ClientBridge | undefined {
1039
+ if (!bridge?.requestPermission || bridge.capabilities.requestPermission !== true) return undefined;
1040
+ const requestPermission = bridge.requestPermission.bind(bridge);
1041
+ return {
1042
+ capabilities: { requestPermission: true },
1043
+ requestPermission: (toolCall, options, signal) => requestPermission(toolCall, options, signal),
1044
+ };
1045
+ }
1046
+
1009
1047
  export async function runSubprocessOnce(options: ExecutorOptions): Promise<SingleResult> {
1010
1048
  const {
1011
1049
  cwd,
@@ -1739,9 +1777,14 @@ export async function runSubprocessOnce(options: ExecutorOptions): Promise<Singl
1739
1777
  });
1740
1778
  let modelRegistry = options.modelRegistry ?? ownedModelRegistry!;
1741
1779
  const authStorage = modelRegistry.authStorage;
1742
- if (options.authStorage && options.authStorage !== authStorage) {
1780
+ // Reject if both authStorage and modelRegistry are provided with different instances.
1781
+ if (
1782
+ options.authStorage !== undefined &&
1783
+ options.modelRegistry !== undefined &&
1784
+ options.authStorage !== authStorage
1785
+ ) {
1743
1786
  throw new Error(
1744
- "options.authStorage and options.modelRegistry.authStorage must be the same instance when both are provided",
1787
+ "options.authStorage and options.modelRegistry.authStorage must be the same instance or one must be omitted",
1745
1788
  );
1746
1789
  }
1747
1790
  checkAbort();
@@ -2044,14 +2087,15 @@ export async function runSubprocessOnce(options: ExecutorOptions): Promise<Singl
2044
2087
  promptTemplates: options.promptTemplates,
2045
2088
  workspaceTree: options.workspaceTree,
2046
2089
  systemPrompt: defaultPrompt => {
2047
- const subagentPrompt = prompt.render(subagentSystemPromptTemplate, {
2048
- agent: prompt.render(agent.systemPrompt, {
2049
- // Typed executionMode wins; assignment text is compatibility-only (#2698 / #2456).
2050
- ultragoalRedTeam: resolveUltragoalRedTeamActivation({
2051
- executionMode: options.executionMode,
2052
- assignment: options.assignment ?? task,
2053
- }),
2090
+ const renderedRole = prompt.render(agent.systemPrompt, {
2091
+ // Typed executionMode wins; assignment text is compatibility-only (#2698 / #2456).
2092
+ ultragoalRedTeam: resolveUltragoalRedTeamActivation({
2093
+ executionMode: options.executionMode,
2094
+ assignment: options.assignment ?? task,
2054
2095
  }),
2096
+ });
2097
+ const subagentPrompt = prompt.render(subagentSystemPromptTemplate, {
2098
+ agent: containSubagentRoleBody(renderedRole),
2055
2099
  context: options.context?.trim() ?? "",
2056
2100
  worktree: worktree ?? "",
2057
2101
  outputSchema: normalizedOutputSchema,
@@ -2101,6 +2145,22 @@ export async function runSubprocessOnce(options: ExecutorOptions): Promise<Singl
2101
2145
  );
2102
2146
 
2103
2147
  activeSession = session;
2148
+ // Plan mode is session state, not a tool-list filter. Copy it before the
2149
+ // first prompt so product writes hit the same read-only guard as the parent.
2150
+ if (options.planModeState?.enabled) {
2151
+ session.setPlanModeState({
2152
+ enabled: true,
2153
+ planFilePath: options.planModeState.planFilePath,
2154
+ ...(options.planModeState.workflow ? { workflow: options.planModeState.workflow } : {}),
2155
+ ...(options.planModeState.reentry !== undefined ? { reentry: options.planModeState.reentry } : {}),
2156
+ });
2157
+ }
2158
+ // `allow` is the child default. deny/prompt must be copied before the first prompt.
2159
+ if (options.sdkPermissionMode === "deny" || options.sdkPermissionMode === "prompt") {
2160
+ session.setSdkPermissionMode(options.sdkPermissionMode);
2161
+ }
2162
+ const approvalBridge = permissionOnlyBridge(options.clientBridge);
2163
+ if (approvalBridge) session.setClientBridge(approvalBridge);
2104
2164
  const configuredChildChain = parentFallbackSelector ? [parentFallbackSelector] : modelPatterns;
2105
2165
  session.setConfiguredModelChain("default", configuredChildChain, "subagent", agent.name, true);
2106
2166
  if (!parentFallbackSelector) {
@@ -2151,7 +2211,9 @@ export async function runSubprocessOnce(options: ExecutorOptions): Promise<Singl
2151
2211
  const parentOwnedToolNames = new Set(["todo_write"]);
2152
2212
  const filteredSubagentTools = subagentToolNames.filter(name => !parentOwnedToolNames.has(name));
2153
2213
  if (filteredSubagentTools.length !== subagentToolNames.length) {
2154
- await awaitAbortable(session.setActiveToolsByName(filteredSubagentTools));
2214
+ await awaitAbortable(
2215
+ session.setActiveToolsByName(filteredSubagentTools, { explicit: false, persistMCPSelection: false }),
2216
+ );
2155
2217
  }
2156
2218
 
2157
2219
  if (!options.preflightProbe && !options.preflightDurable) {
@@ -2881,6 +2943,39 @@ function preflightTerminalResult(
2881
2943
 
2882
2944
  /** Run routed initial tasks through the bounded probe/durable candidate ledger. */
2883
2945
  export async function runSubprocess(options: ExecutorOptions): Promise<SingleResult> {
2946
+ // Resume routing resolves credentials before dispatch; do not let an unexpected
2947
+ // lookup exception bypass terminalization just because the initial probe ledger is off.
2948
+ if (
2949
+ (options.runMode ?? "initial") !== "initial" &&
2950
+ options.autoroutingCandidates &&
2951
+ options.autoroutingPreflightErrors
2952
+ ) {
2953
+ const failedSelector = options.autoroutingCandidates.find(selector =>
2954
+ options.autoroutingPreflightErrors?.has(selector),
2955
+ );
2956
+ if (failedSelector) {
2957
+ const preflightError = options.autoroutingPreflightErrors.get(failedSelector);
2958
+ const failure = classifyAutoroutingPreflightFailure(preflightError, "auth_resolve");
2959
+ const { code } = autoroutingAttemptDisposition(failure);
2960
+ const skips = buildBoundedRoutingSkips(options.autoroutingSkips);
2961
+ const routedOptions = options.routing ? { ...options.routing, ...skips } : options.routing;
2962
+ return preflightTerminalResult(
2963
+ { ...options, routing: routedOptions },
2964
+ [{ selector: failedSelector, phase: "probe", code }],
2965
+ "preflight_exhausted",
2966
+ );
2967
+ }
2968
+ }
2969
+ if ((options.runMode ?? "initial") !== "initial" && options.autoroutingCandidates?.length === 0 && options.routing) {
2970
+ const skippedCandidates = options.autoroutingSkips?.filter(skip => skip.code === "credential_unavailable") ?? [];
2971
+ return preflightTerminalResult(
2972
+ { ...options, routing: { ...options.routing, ...buildBoundedRoutingSkips(options.autoroutingSkips) } },
2973
+ skippedCandidates
2974
+ .slice(0, 6)
2975
+ .map(skip => ({ selector: skip.selector, phase: "probe", code: "credential_unavailable" })),
2976
+ "all_candidates_skipped",
2977
+ );
2978
+ }
2884
2979
  if (
2885
2980
  !options.autoroutingPreflight ||
2886
2981
  (options.runMode ?? "initial") !== "initial" ||