gsd-pi 2.82.0 → 3.0.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 (555) hide show
  1. package/README.md +51 -32
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +10 -1
  4. package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
  5. package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
  6. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  7. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +1 -1
  8. package/dist/resources/extensions/cmux/index.js +5 -0
  9. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  10. package/dist/resources/extensions/gsd/auto/loop.js +19 -6
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
  12. package/dist/resources/extensions/gsd/auto/phases.js +90 -31
  13. package/dist/resources/extensions/gsd/auto/session.js +4 -0
  14. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
  15. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  16. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  17. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
  18. package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
  19. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  20. package/dist/resources/extensions/gsd/auto-post-unit.js +246 -133
  21. package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
  22. package/dist/resources/extensions/gsd/auto-recovery.js +71 -14
  23. package/dist/resources/extensions/gsd/auto-start.js +87 -14
  24. package/dist/resources/extensions/gsd/auto-verification.js +45 -26
  25. package/dist/resources/extensions/gsd/auto-worktree.js +176 -10
  26. package/dist/resources/extensions/gsd/auto.js +178 -63
  27. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
  28. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -9
  29. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
  30. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  31. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +17 -3
  33. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  34. package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
  35. package/dist/resources/extensions/gsd/commands/handlers/core.js +39 -1
  36. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  37. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  38. package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
  39. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +7 -2
  40. package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
  41. package/dist/resources/extensions/gsd/context-store.js +112 -0
  42. package/dist/resources/extensions/gsd/crash-recovery.js +43 -5
  43. package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
  44. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  45. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  46. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  47. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  48. package/dist/resources/extensions/gsd/doctor-git-checks.js +87 -7
  49. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  50. package/dist/resources/extensions/gsd/doctor.js +2 -28
  51. package/dist/resources/extensions/gsd/export-html.js +27 -425
  52. package/dist/resources/extensions/gsd/forensics.js +3 -3
  53. package/dist/resources/extensions/gsd/git-service.js +45 -3
  54. package/dist/resources/extensions/gsd/gsd-db.js +21 -6
  55. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
  56. package/dist/resources/extensions/gsd/guided-flow.js +101 -116
  57. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  58. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  59. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  60. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  61. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  62. package/dist/resources/extensions/gsd/markdown-renderer.js +16 -9
  63. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  64. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  65. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  66. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  67. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  68. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  69. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  70. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  71. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  72. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  73. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  74. package/dist/resources/extensions/gsd/paths.js +4 -0
  75. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  76. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  77. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  78. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  79. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  80. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  81. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  82. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  83. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  84. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  85. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  86. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  87. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  88. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  89. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  90. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  91. package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
  92. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  93. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  94. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  95. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  96. package/dist/resources/extensions/gsd/state.js +3 -3
  97. package/dist/resources/extensions/gsd/status-guards.js +11 -0
  98. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  99. package/dist/resources/extensions/gsd/templates/plan.md +9 -5
  100. package/dist/resources/extensions/gsd/templates/task-plan.md +10 -2
  101. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  102. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  103. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  104. package/dist/resources/extensions/gsd/tools/plan-slice.js +87 -14
  105. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  106. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  107. package/dist/resources/extensions/gsd/validation.js +23 -1
  108. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  109. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  110. package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
  111. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  112. package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
  113. package/dist/resources/extensions/gsd/worktree-manager.js +1 -1
  114. package/dist/resources/extensions/shared/html-shell.js +388 -0
  115. package/dist/resources/extensions/subagent/index.js +448 -78
  116. package/dist/resources/extensions/subagent/launch.js +77 -0
  117. package/dist/resources/extensions/subagent/run-store.js +148 -0
  118. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  119. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  120. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  121. package/dist/resources/extensions/visual-brief/index.js +5 -0
  122. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  123. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  124. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  125. package/dist/web/standalone/.next/BUILD_ID +1 -1
  126. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  127. package/dist/web/standalone/.next/build-manifest.json +3 -3
  128. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  129. package/dist/web/standalone/.next/react-loadable-manifest.json +5 -5
  130. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  140. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  145. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  147. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  150. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/index.html +1 -1
  153. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  154. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  155. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  156. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  158. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  159. package/dist/web/standalone/.next/server/app/page.js +2 -2
  160. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  163. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  164. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  168. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  169. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  170. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  171. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  172. package/dist/web/standalone/.next/static/chunks/8359.65b24fac92188a6b.js +10 -0
  173. package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
  174. package/dist/web/standalone/.next/static/chunks/app/layout-b23b3f6858dc6dc8.js +1 -0
  175. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
  176. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  177. package/package.json +6 -5
  178. package/packages/contracts/dist/rpc.test.js +7 -0
  179. package/packages/contracts/dist/rpc.test.js.map +1 -1
  180. package/packages/contracts/dist/workflow.d.ts +21 -0
  181. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  182. package/packages/contracts/dist/workflow.js +24 -0
  183. package/packages/contracts/dist/workflow.js.map +1 -1
  184. package/packages/contracts/src/rpc.test.ts +8 -0
  185. package/packages/contracts/src/workflow.ts +24 -0
  186. package/packages/daemon/package.json +2 -2
  187. package/packages/mcp-server/README.md +14 -3
  188. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  189. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  190. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  191. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  192. package/packages/mcp-server/package.json +2 -2
  193. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  194. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  195. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  196. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  197. package/packages/native/package.json +1 -1
  198. package/packages/native/tsconfig.json +2 -1
  199. package/packages/native/tsconfig.tsbuildinfo +1 -1
  200. package/packages/pi-agent-core/package.json +1 -1
  201. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  202. package/packages/pi-ai/dist/index.d.ts +2 -2
  203. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  204. package/packages/pi-ai/dist/index.js +1 -1
  205. package/packages/pi-ai/dist/index.js.map +1 -1
  206. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  207. package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
  208. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  209. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
  210. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
  211. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
  212. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
  213. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  214. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  215. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  216. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  217. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  218. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  219. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  220. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  221. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  222. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  223. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  224. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  225. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  226. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  227. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  228. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  229. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  230. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  231. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  232. package/packages/pi-ai/package.json +1 -1
  233. package/packages/pi-ai/src/index.ts +7 -2
  234. package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +49 -0
  235. package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
  236. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  237. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  238. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  239. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  240. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  241. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  242. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  243. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  244. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  245. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  246. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  247. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
  249. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
  251. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  253. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  257. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +71 -97
  259. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
  261. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  263. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  264. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
  265. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  267. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  268. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  269. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  270. package/packages/pi-coding-agent/package.json +1 -1
  271. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  272. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  273. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
  274. package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
  275. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  276. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  277. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -102
  278. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
  279. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
  280. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  281. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  282. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
  283. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
  284. package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
  285. package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
  286. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  287. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  288. package/packages/pi-tui/dist/terminal.js +12 -0
  289. package/packages/pi-tui/dist/terminal.js.map +1 -1
  290. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  291. package/packages/pi-tui/dist/tui.js +5 -0
  292. package/packages/pi-tui/dist/tui.js.map +1 -1
  293. package/packages/pi-tui/package.json +1 -1
  294. package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
  295. package/packages/pi-tui/src/terminal.ts +11 -0
  296. package/packages/pi-tui/src/tui.ts +6 -0
  297. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  298. package/packages/rpc-client/package.json +1 -1
  299. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  300. package/pkg/package.json +1 -1
  301. package/src/resources/GSD-WORKFLOW.md +10 -1
  302. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  303. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  304. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  305. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +1 -1
  306. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  307. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +9 -0
  308. package/src/resources/extensions/cmux/index.ts +6 -0
  309. package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
  310. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  311. package/src/resources/extensions/gsd/auto/loop.ts +22 -6
  312. package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
  313. package/src/resources/extensions/gsd/auto/phases.ts +104 -38
  314. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  315. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
  316. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  317. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  318. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
  319. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -19
  320. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  321. package/src/resources/extensions/gsd/auto-post-unit.ts +279 -144
  322. package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
  323. package/src/resources/extensions/gsd/auto-recovery.ts +74 -11
  324. package/src/resources/extensions/gsd/auto-start.ts +94 -12
  325. package/src/resources/extensions/gsd/auto-verification.ts +58 -36
  326. package/src/resources/extensions/gsd/auto-worktree.ts +193 -10
  327. package/src/resources/extensions/gsd/auto.ts +187 -61
  328. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
  329. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -9
  330. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
  331. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  332. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  333. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +20 -4
  334. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  335. package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
  336. package/src/resources/extensions/gsd/commands/handlers/core.ts +42 -1
  337. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  338. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  339. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  340. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +8 -3
  341. package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
  342. package/src/resources/extensions/gsd/context-store.ts +120 -1
  343. package/src/resources/extensions/gsd/crash-recovery.ts +44 -4
  344. package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
  345. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  346. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  347. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  348. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  349. package/src/resources/extensions/gsd/doctor-git-checks.ts +89 -7
  350. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  351. package/src/resources/extensions/gsd/doctor-types.ts +3 -0
  352. package/src/resources/extensions/gsd/doctor.ts +2 -27
  353. package/src/resources/extensions/gsd/export-html.ts +27 -427
  354. package/src/resources/extensions/gsd/forensics.ts +3 -3
  355. package/src/resources/extensions/gsd/git-service.ts +51 -4
  356. package/src/resources/extensions/gsd/gsd-db.ts +21 -6
  357. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
  358. package/src/resources/extensions/gsd/guided-flow.ts +134 -133
  359. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  360. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  361. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  362. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  363. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  364. package/src/resources/extensions/gsd/markdown-renderer.ts +16 -9
  365. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  366. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  367. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  368. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  369. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  370. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  371. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  372. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  373. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  374. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  375. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  376. package/src/resources/extensions/gsd/paths.ts +5 -0
  377. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  378. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  379. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  380. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  381. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  382. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  383. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  384. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  385. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  386. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  387. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  388. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  389. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  390. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  391. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  392. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  393. package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
  394. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  395. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  396. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  397. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  398. package/src/resources/extensions/gsd/state.ts +3 -3
  399. package/src/resources/extensions/gsd/status-guards.ts +13 -0
  400. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  401. package/src/resources/extensions/gsd/templates/plan.md +9 -5
  402. package/src/resources/extensions/gsd/templates/task-plan.md +10 -2
  403. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  404. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  405. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +131 -0
  406. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
  407. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
  408. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  409. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +18 -6
  410. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +91 -6
  411. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
  412. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  413. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  414. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  415. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  416. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  417. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
  418. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  419. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
  420. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  421. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +378 -0
  422. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  423. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  424. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  425. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  426. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +86 -2
  427. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  428. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  429. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  430. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  431. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  432. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  433. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +66 -0
  434. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  435. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  436. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  437. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  438. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  439. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +11 -0
  440. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  441. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
  442. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  443. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  444. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  445. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  446. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  447. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  448. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  449. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  450. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  451. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  452. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  453. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +112 -1
  454. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  455. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  456. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  457. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +46 -0
  458. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  459. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  460. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  461. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  462. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  463. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
  464. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  465. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  466. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  467. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  468. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  469. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  470. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  471. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  472. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
  473. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  474. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  475. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  476. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +251 -2
  477. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  478. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  479. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  480. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  481. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +84 -0
  482. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  483. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +59 -0
  484. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
  485. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  486. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
  487. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  488. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
  489. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
  490. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
  491. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
  492. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  493. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  494. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  495. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
  496. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  497. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  498. package/src/resources/extensions/gsd/tests/status-guards.test.ts +13 -1
  499. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  500. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  501. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +103 -7
  502. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
  503. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  504. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  505. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
  506. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
  507. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  508. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  509. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  510. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  511. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
  512. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  513. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  514. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  515. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  516. package/src/resources/extensions/gsd/tools/plan-slice.ts +97 -12
  517. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  518. package/src/resources/extensions/gsd/types.ts +1 -1
  519. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  520. package/src/resources/extensions/gsd/validation.ts +23 -1
  521. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  522. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  523. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  524. package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
  525. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  526. package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
  527. package/src/resources/extensions/gsd/worktree-manager.ts +1 -1
  528. package/src/resources/extensions/shared/html-shell.ts +412 -0
  529. package/src/resources/extensions/subagent/index.ts +567 -103
  530. package/src/resources/extensions/subagent/launch.ts +131 -0
  531. package/src/resources/extensions/subagent/run-store.ts +218 -0
  532. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  533. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  534. package/src/resources/extensions/ttsr/ttsr-manager.ts +5 -1
  535. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  536. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  537. package/src/resources/extensions/visual-brief/index.ts +8 -0
  538. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  539. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  540. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  541. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  542. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  543. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +0 -10
  544. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  545. package/dist/web/standalone/.next/static/chunks/app/layout-9ecfd95f343793f0.js +0 -1
  546. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  547. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  548. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  549. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  550. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  551. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  552. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  553. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  554. /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → qoMxZh-xuwuvpFW0x0k01}/_buildManifest.js +0 -0
  555. /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → qoMxZh-xuwuvpFW0x0k01}/_ssgManifest.js +0 -0
@@ -28,6 +28,9 @@ import { registerWorker, updateWorker } from "./worker-registry.js";
28
28
  import { loadEffectiveGSDPreferences } from "../gsd/preferences.js";
29
29
  import { emitJournalEvent } from "../gsd/journal.js";
30
30
  import { CmuxClient, shellEscape } from "../cmux/index.js";
31
+ import { buildShellEnvAssignments, createSubagentLaunchPlan, isSubagentChildProcess, } from "./launch.js";
32
+ import { SubagentRunStore, createInitialRunRecord, createSubagentTrackingName, deriveRunStatus, } from "./run-store.js";
33
+ export { buildSubagentProcessArgs } from "./launch.js";
31
34
  const MAX_PARALLEL_TASKS = 8;
32
35
  const MAX_CONCURRENCY = 4;
33
36
  const COLLAPSED_ITEM_COUNT = 10;
@@ -195,18 +198,6 @@ function writePromptToTempFile(agentName, prompt) {
195
198
  fs.writeFileSync(filePath, prompt, { encoding: "utf-8", mode: 0o600 });
196
199
  return { dir: tmpDir, filePath };
197
200
  }
198
- export function buildSubagentProcessArgs(agent, task, tmpPromptPath, modelOverride) {
199
- const args = ["--mode", "json", "-p", "--no-session"];
200
- const effectiveModel = modelOverride ?? agent.model;
201
- if (effectiveModel)
202
- args.push("--model", effectiveModel);
203
- if (agent.tools && agent.tools.length > 0)
204
- args.push("--tools", agent.tools.join(","));
205
- if (tmpPromptPath)
206
- args.push("--append-system-prompt", tmpPromptPath);
207
- args.push(`Task: ${task}`);
208
- return args;
209
- }
210
201
  function processSubagentEventLine(line, currentResult, emitUpdate) {
211
202
  if (!line.trim())
212
203
  return;
@@ -256,12 +247,68 @@ async function waitForFile(filePath, signal, timeoutMs = 30 * 60 * 1000) {
256
247
  }
257
248
  return false;
258
249
  }
259
- async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride) {
250
+ function resultStatus(result) {
251
+ if (result.stopReason === "aborted")
252
+ return "interrupted";
253
+ return result.exitCode === 0 ? "succeeded" : "failed";
254
+ }
255
+ function resultToChildArtifact(result, index, cwd) {
256
+ const running = result.running === true || result.exitCode === -1;
257
+ return {
258
+ index,
259
+ agent: result.agent,
260
+ trackingName: result.trackingName,
261
+ task: result.task,
262
+ status: running ? "running" : resultStatus(result),
263
+ exitCode: result.exitCode,
264
+ cwd,
265
+ sessionFile: result.sessionFile,
266
+ completedAt: running ? undefined : new Date().toISOString(),
267
+ output: getFinalOutput(result.messages),
268
+ stderr: result.stderr || undefined,
269
+ errorMessage: result.errorMessage,
270
+ stopReason: result.stopReason,
271
+ model: result.model,
272
+ usage: result.usage,
273
+ merge: result.mergeResult
274
+ ? {
275
+ success: result.mergeResult.success,
276
+ appliedPatches: result.mergeResult.appliedPatches,
277
+ failedPatches: result.mergeResult.failedPatches,
278
+ error: result.mergeResult.error,
279
+ }
280
+ : undefined,
281
+ };
282
+ }
283
+ function formatAgentLabel(agent, trackingName) {
284
+ return trackingName ? `${trackingName} / ${agent}` : agent;
285
+ }
286
+ function formatRunRecord(record) {
287
+ if (!record)
288
+ return "Subagent run not found.";
289
+ const lines = [
290
+ `Run ${record.runId}: ${record.status}`,
291
+ `Mode: ${record.mode}`,
292
+ `Context: ${record.contextMode}`,
293
+ `Updated: ${record.updatedAt}`,
294
+ ];
295
+ for (const child of record.children) {
296
+ const exit = child.exitCode === undefined ? "" : ` (exit ${child.exitCode})`;
297
+ lines.push(`- [${child.status}] ${formatAgentLabel(child.agent, child.trackingName)}${exit}: ${child.output || child.errorMessage || child.stderr || child.task}`);
298
+ if (child.sessionFile)
299
+ lines.push(` session: ${child.sessionFile}`);
300
+ }
301
+ if (record.failure)
302
+ lines.push(`Failure: ${record.failure.message}`);
303
+ return lines.join("\n");
304
+ }
305
+ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride, contextMode = "fresh", parentSessionManager, sessionOverride, trackingName) {
260
306
  const agent = agents.find((a) => a.name === agentName);
261
307
  if (!agent) {
262
308
  const available = agents.map((a) => `"${a.name}"`).join(", ") || "none";
263
309
  return {
264
310
  agent: agentName,
311
+ trackingName,
265
312
  agentSource: "unknown",
266
313
  task,
267
314
  exitCode: 1,
@@ -277,6 +324,7 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
277
324
  if (activePhase && agent.conflictsWith.includes(activePhase)) {
278
325
  return {
279
326
  agent: agentName,
327
+ trackingName,
280
328
  agentSource: agent.source,
281
329
  task,
282
330
  exitCode: 1,
@@ -291,9 +339,11 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
291
339
  let tmpPromptPath = null;
292
340
  const currentResult = {
293
341
  agent: agentName,
342
+ trackingName,
294
343
  agentSource: agent.source,
295
344
  task,
296
- exitCode: 0,
345
+ exitCode: -1,
346
+ running: true,
297
347
  messages: [],
298
348
  stderr: "",
299
349
  usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 },
@@ -314,12 +364,24 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
314
364
  tmpPromptDir = tmp.dir;
315
365
  tmpPromptPath = tmp.filePath;
316
366
  }
317
- const args = buildSubagentProcessArgs(agent, task, tmpPromptPath, modelOverride);
367
+ const launch = createSubagentLaunchPlan({
368
+ agent,
369
+ task,
370
+ tmpPromptPath,
371
+ modelOverride,
372
+ contextMode,
373
+ parentSessionManager,
374
+ session: sessionOverride,
375
+ cwd,
376
+ defaultCwd,
377
+ });
378
+ if (launch.session.mode === "fork")
379
+ currentResult.sessionFile = launch.session.sessionFile;
318
380
  let wasAborted = false;
319
381
  const exitCode = await new Promise((resolve) => {
320
382
  const bundledPaths = (process.env.GSD_BUNDLED_EXTENSION_PATHS ?? "").split(path.delimiter).map(s => s.trim()).filter(Boolean);
321
383
  const extensionArgs = bundledPaths.flatMap(p => ["--extension", p]);
322
- const proc = spawn(process.execPath, [process.env.GSD_BIN_PATH, ...extensionArgs, ...args], { cwd: cwd ?? defaultCwd, shell: false, stdio: ["ignore", "pipe", "pipe"] });
384
+ const proc = spawn(process.execPath, [process.env.GSD_BIN_PATH, ...extensionArgs, ...launch.args], { cwd: launch.cwd, env: launch.env, shell: false, stdio: ["ignore", "pipe", "pipe"] });
323
385
  liveSubagentProcesses.add(proc);
324
386
  let buffer = "";
325
387
  proc.stdout.on("data", (data) => {
@@ -358,6 +420,7 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
358
420
  }
359
421
  });
360
422
  currentResult.exitCode = exitCode;
423
+ currentResult.running = false;
361
424
  if (wasAborted)
362
425
  throw new Error("Subagent was aborted");
363
426
  return currentResult;
@@ -379,19 +442,21 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
379
442
  }
380
443
  }
381
444
  }
382
- async function runSingleAgentInCmuxSplit(cmuxClient, directionOrSurfaceId, defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride) {
445
+ async function runSingleAgentInCmuxSplit(cmuxClient, directionOrSurfaceId, defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride, contextMode = "fresh", parentSessionManager, sessionOverride, trackingName) {
383
446
  const agent = agents.find((a) => a.name === agentName);
384
447
  if (!agent) {
385
- return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride);
448
+ return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride, contextMode, parentSessionManager, sessionOverride, trackingName);
386
449
  }
387
450
  let tmpPromptDir = null;
388
451
  let tmpPromptPath = null;
389
452
  let tmpOutputDir = null;
390
453
  const currentResult = {
391
454
  agent: agentName,
455
+ trackingName,
392
456
  agentSource: agent.source,
393
457
  task,
394
- exitCode: 0,
458
+ exitCode: -1,
459
+ running: true,
395
460
  messages: [],
396
461
  stderr: "",
397
462
  usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 },
@@ -423,30 +488,63 @@ async function runSingleAgentInCmuxSplit(cmuxClient, directionOrSurfaceId, defau
423
488
  ? await cmuxClient.createSplit(directionOrSurfaceId)
424
489
  : directionOrSurfaceId;
425
490
  if (!cmuxSurfaceId) {
426
- return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride);
491
+ return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride, contextMode, parentSessionManager, sessionOverride, trackingName);
427
492
  }
428
493
  const bundledPaths = (process.env.GSD_BUNDLED_EXTENSION_PATHS ?? "").split(path.delimiter).map((s) => s.trim()).filter(Boolean);
429
494
  const extensionArgs = bundledPaths.flatMap((p) => ["--extension", p]);
430
- const processArgs = [process.env.GSD_BIN_PATH, ...extensionArgs, ...buildSubagentProcessArgs(agent, task, tmpPromptPath, modelOverride)];
495
+ const launch = createSubagentLaunchPlan({
496
+ agent,
497
+ task,
498
+ tmpPromptPath,
499
+ modelOverride,
500
+ contextMode,
501
+ parentSessionManager,
502
+ session: sessionOverride,
503
+ cwd,
504
+ defaultCwd,
505
+ });
506
+ if (launch.session.mode === "fork")
507
+ currentResult.sessionFile = launch.session.sessionFile;
508
+ const processArgs = [process.env.GSD_BIN_PATH, ...extensionArgs, ...launch.args];
431
509
  // Normalize all paths to forward slashes before embedding in bash strings.
432
510
  // On Windows, backslashes are interpreted as escape characters by bash,
433
511
  // mangling paths like C:\Users\user into C:Useruser (#1436).
434
512
  const bashPath = (p) => shellEscape(p.replaceAll("\\", "/"));
513
+ const envPrefix = buildShellEnvAssignments(launch.env).join(" ");
514
+ const commandPrefix = envPrefix ? `${envPrefix} ` : "";
435
515
  const innerScript = [
436
- `cd ${bashPath(cwd ?? defaultCwd)}`,
516
+ `cd ${bashPath(launch.cwd)}`,
437
517
  "set -o pipefail",
438
- `${bashPath(process.execPath)} ${processArgs.map(a => bashPath(a)).join(" ")} 2> >(tee ${bashPath(stderrPath)} >&2) | tee ${bashPath(stdoutPath)}`,
518
+ `${commandPrefix}${bashPath(process.execPath)} ${processArgs.map(a => bashPath(a)).join(" ")} 2> >(tee ${bashPath(stderrPath)} >&2) | tee ${bashPath(stdoutPath)}`,
439
519
  "status=${PIPESTATUS[0]}",
440
520
  `printf '%s' "$status" > ${bashPath(exitPath)}`,
441
521
  ].join("; ");
442
522
  const sent = await cmuxClient.sendSurface(cmuxSurfaceId, `bash -lc ${shellEscape(innerScript)}`);
443
523
  if (!sent) {
444
- return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride);
524
+ return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride, contextMode, parentSessionManager, sessionOverride, trackingName);
445
525
  }
446
526
  const finished = await waitForFile(exitPath, signal);
447
527
  if (!finished) {
528
+ // Terminate the child running inside the cmux split: send Ctrl-C
529
+ // so bash interrupts the pipeline and writes the exit code, instead
530
+ // of leaving an orphaned subagent that can keep editing after cancel.
531
+ try {
532
+ await cmuxClient.sendInterrupt(cmuxSurfaceId);
533
+ }
534
+ catch {
535
+ /* ignore — best-effort */
536
+ }
537
+ // Give the shell a brief window to reap the killed child and write exit.code.
538
+ await waitForFile(exitPath, undefined, 5000);
448
539
  currentResult.exitCode = 1;
540
+ currentResult.running = false;
449
541
  currentResult.stderr = "cmux split execution timed out or was aborted";
542
+ if (fs.existsSync(stdoutPath)) {
543
+ const stdout = fs.readFileSync(stdoutPath, "utf-8");
544
+ for (const line of stdout.split("\n")) {
545
+ processSubagentEventLine(line, currentResult, emitUpdate);
546
+ }
547
+ }
450
548
  return currentResult;
451
549
  }
452
550
  if (fs.existsSync(stdoutPath)) {
@@ -459,6 +557,7 @@ async function runSingleAgentInCmuxSplit(cmuxClient, directionOrSurfaceId, defau
459
557
  currentResult.stderr = fs.readFileSync(stderrPath, "utf-8");
460
558
  }
461
559
  currentResult.exitCode = Number.parseInt(fs.readFileSync(exitPath, "utf-8").trim() || "1", 10) || 0;
560
+ currentResult.running = false;
462
561
  return currentResult;
463
562
  }
464
563
  finally {
@@ -490,23 +589,44 @@ const TaskItem = Type.Object({
490
589
  task: Type.String({ description: "Task to delegate to the agent" }),
491
590
  cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })),
492
591
  model: Type.Optional(Type.String({ description: "Model override for this task (e.g. 'claude-sonnet-4-6')" })),
592
+ context: Type.Optional(StringEnum(["fresh", "fork"], {
593
+ description: 'Context mode for this task. "fresh" keeps the existing isolated context behavior; "fork" branches the parent session.',
594
+ default: "fresh",
595
+ })),
493
596
  });
494
597
  const ChainItem = Type.Object({
495
598
  agent: Type.String({ description: "Name of the agent to invoke" }),
496
599
  task: Type.String({ description: "Task with optional {previous} placeholder for prior output" }),
497
600
  cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })),
498
601
  model: Type.Optional(Type.String({ description: "Model override for this step (e.g. 'claude-sonnet-4-6')" })),
602
+ context: Type.Optional(StringEnum(["fresh", "fork"], {
603
+ description: 'Context mode for this step. "fresh" keeps the existing isolated context behavior; "fork" branches the parent session.',
604
+ default: "fresh",
605
+ })),
499
606
  });
500
607
  const AgentScopeSchema = StringEnum(["user", "project", "both"], {
501
608
  description: 'Which agent directories to use. Default: "both" (user + project-local).',
502
609
  default: "both",
503
610
  });
611
+ const ContextModeSchema = StringEnum(["fresh", "fork"], {
612
+ description: 'Context mode for delegated work. "fresh" is the default existing behavior; "fork" branches the parent session.',
613
+ default: "fresh",
614
+ });
615
+ const SubagentActionSchema = StringEnum(["launch", "status", "resume"], {
616
+ description: 'Run action. "launch" starts delegated work, "status" inspects a persisted run, and "resume" follows up a child session from a run.',
617
+ default: "launch",
618
+ });
504
619
  const SubagentParams = Type.Object({
620
+ action: Type.Optional(SubagentActionSchema),
621
+ runId: Type.Optional(Type.String({ description: "Persisted subagent run id for status or resume actions" })),
505
622
  agent: Type.Optional(Type.String({ description: "Name of the agent to invoke (for single mode)" })),
506
623
  task: Type.Optional(Type.String({ description: "Task to delegate (for single mode)" })),
507
624
  tasks: Type.Optional(Type.Array(TaskItem, { description: "Array of {agent, task} for parallel execution" })),
508
625
  chain: Type.Optional(Type.Array(ChainItem, { description: "Array of {agent, task} for sequential execution" })),
509
626
  agentScope: Type.Optional(AgentScopeSchema),
627
+ context: Type.Optional(ContextModeSchema),
628
+ background: Type.Optional(Type.Boolean({ description: "Return after starting the run and keep status in the persisted run record. Default: false.", default: false })),
629
+ followUp: Type.Optional(Type.String({ description: "Follow-up instruction for resume action. Falls back to task when omitted." })),
510
630
  confirmProjectAgents: Type.Optional(Type.Boolean({ description: "Prompt before running project-local agents. Default: false.", default: false })),
511
631
  cwd: Type.Optional(Type.String({ description: "Working directory for the agent process (single mode)" })),
512
632
  model: Type.Optional(Type.String({ description: "Model override for the subagent (e.g. 'claude-sonnet-4-6'). Takes precedence over the agent's frontmatter model." })),
@@ -518,6 +638,8 @@ const SubagentParams = Type.Object({
518
638
  })),
519
639
  });
520
640
  export default function (pi) {
641
+ if (isSubagentChildProcess())
642
+ return;
521
643
  pi.on("session_shutdown", async () => {
522
644
  await stopLiveSubagents();
523
645
  });
@@ -562,11 +684,16 @@ export default function (pi) {
562
684
  const confirmProjectAgents = params.confirmProjectAgents ?? false;
563
685
  const cmuxClient = CmuxClient.fromPreferences(loadEffectiveGSDPreferences()?.preferences);
564
686
  const cmuxSplitsEnabled = cmuxClient.getConfig().splits;
687
+ const runStore = new SubagentRunStore();
688
+ const action = params.action ?? "launch";
689
+ const contextMode = params.context ?? "fresh";
690
+ const taskParams = Array.isArray(params.tasks) ? params.tasks : [];
691
+ const chainParams = Array.isArray(params.chain) ? params.chain : [];
565
692
  // Resolve isolation mode
566
693
  const isolationMode = readIsolationMode();
567
694
  const useIsolation = Boolean(params.isolated) && isolationMode !== "none";
568
- const hasChain = (params.chain?.length ?? 0) > 0;
569
- const hasTasks = (params.tasks?.length ?? 0) > 0;
695
+ const hasChain = chainParams.length > 0;
696
+ const hasTasks = taskParams.length > 0;
570
697
  const hasSingle = Boolean(params.agent && params.task);
571
698
  const modeCount = Number(hasChain) + Number(hasTasks) + Number(hasSingle);
572
699
  const makeDetails = (mode) => (results) => ({
@@ -575,6 +702,68 @@ export default function (pi) {
575
702
  projectAgentsDir: discovery.projectAgentsDir,
576
703
  results,
577
704
  });
705
+ if (action === "status") {
706
+ if (!params.runId) {
707
+ return {
708
+ content: [{ type: "text", text: "Status requires runId." }],
709
+ details: makeDetails("single")([]),
710
+ isError: true,
711
+ };
712
+ }
713
+ const record = runStore.get(params.runId);
714
+ return {
715
+ content: [{ type: "text", text: formatRunRecord(record) }],
716
+ details: makeDetails("single")([]),
717
+ ...(record ? {} : { isError: true }),
718
+ };
719
+ }
720
+ if (action === "resume") {
721
+ if (!params.runId) {
722
+ return {
723
+ content: [{ type: "text", text: "Resume requires runId." }],
724
+ details: makeDetails("single")([]),
725
+ isError: true,
726
+ };
727
+ }
728
+ const record = runStore.get(params.runId);
729
+ if (!record) {
730
+ return {
731
+ content: [{ type: "text", text: `Subagent run not found: ${params.runId}` }],
732
+ details: makeDetails("single")([]),
733
+ isError: true,
734
+ };
735
+ }
736
+ const followUp = params.followUp ?? params.task;
737
+ if (!followUp) {
738
+ return {
739
+ content: [{ type: "text", text: "Resume requires followUp or task." }],
740
+ details: makeDetails("single")([]),
741
+ isError: true,
742
+ };
743
+ }
744
+ const sessionChildren = record.children.filter((child) => child.sessionFile);
745
+ const matches = params.agent
746
+ ? sessionChildren.filter((child) => child.agent === params.agent)
747
+ : sessionChildren;
748
+ const selected = matches.length === 1 ? matches[0] : undefined;
749
+ if (!selected?.sessionFile) {
750
+ const available = sessionChildren.map((child) => formatAgentLabel(child.agent, child.trackingName)).join(", ") || "none";
751
+ return {
752
+ content: [{
753
+ type: "text",
754
+ text: `Resume requires exactly one child session or an agent selector. Available resumable agents: ${available}`,
755
+ }],
756
+ details: makeDetails("single")([]),
757
+ isError: true,
758
+ };
759
+ }
760
+ const result = await runSingleAgent(ctx.cwd, agents, selected.agent, followUp, selected.cwd, undefined, signal, onUpdate, makeDetails("single"), params.model, "fresh", ctx.sessionManager, { mode: "fork", sessionFile: selected.sessionFile, sessionDir: path.dirname(selected.sessionFile) }, selected.trackingName);
761
+ return {
762
+ content: [{ type: "text", text: getFinalOutput(result.messages) || result.errorMessage || result.stderr || "(no output)" }],
763
+ details: makeDetails("single")([result]),
764
+ ...(result.exitCode === 0 ? {} : { isError: true }),
765
+ };
766
+ }
578
767
  if (modeCount !== 1) {
579
768
  const available = agents.map((a) => `${a.name} (${a.source})`).join(", ") || "none";
580
769
  return {
@@ -592,16 +781,16 @@ export default function (pi) {
592
781
  // auto-mode flowId; per-dispatch ids still let us measure frequency, batch size, mode).
593
782
  const dispatchMode = hasChain ? "chain" : hasTasks ? "parallel" : "single";
594
783
  const dispatchAgents = hasChain
595
- ? params.chain.map((s) => s.agent)
784
+ ? chainParams.map((s) => s.agent)
596
785
  : hasTasks
597
- ? params.tasks.map((t) => t.agent)
786
+ ? taskParams.map((t) => t.agent)
598
787
  : params.agent
599
788
  ? [params.agent]
600
789
  : [];
601
790
  const dispatchTasks = hasChain
602
- ? params.chain.map((s) => s.task)
791
+ ? chainParams.map((s) => s.task)
603
792
  : hasTasks
604
- ? params.tasks.map((t) => t.task)
793
+ ? taskParams.map((t) => t.task)
605
794
  : params.task
606
795
  ? [params.task]
607
796
  : [];
@@ -609,6 +798,85 @@ export default function (pi) {
609
798
  const dispatchStartMs = Date.now();
610
799
  let finalResults = [];
611
800
  let dispatchCompletedEmitted = false;
801
+ const usedTrackingNames = new Set();
802
+ const dispatchTrackingNames = dispatchAgents.map(() => {
803
+ const trackingName = createSubagentTrackingName(usedTrackingNames);
804
+ usedTrackingNames.add(trackingName);
805
+ return trackingName;
806
+ });
807
+ const dispatchContextMode = hasChain && chainParams.some((step) => (step.context ?? contextMode) === "fork")
808
+ ? "fork"
809
+ : hasTasks && taskParams.some((task) => (task.context ?? contextMode) === "fork")
810
+ ? "fork"
811
+ : contextMode;
812
+ const dispatchChildren = dispatchAgents.map((agent, index) => ({
813
+ agent,
814
+ trackingName: dispatchTrackingNames[index],
815
+ task: dispatchTasks[index] ?? "",
816
+ cwd: hasChain
817
+ ? chainParams[index]?.cwd
818
+ : hasTasks
819
+ ? taskParams[index]?.cwd
820
+ : params.cwd,
821
+ }));
822
+ try {
823
+ runStore.create(createInitialRunRecord({
824
+ runId: dispatchId,
825
+ mode: dispatchMode,
826
+ contextMode: dispatchContextMode,
827
+ cwd: ctx.cwd,
828
+ children: dispatchChildren,
829
+ }));
830
+ }
831
+ catch {
832
+ // Persistence is observability; execution remains authoritative.
833
+ }
834
+ const persistRunResults = (results, completed = false) => {
835
+ try {
836
+ runStore.update(dispatchId, (record) => {
837
+ const children = [...record.children];
838
+ for (let index = 0; index < results.length; index++) {
839
+ const result = results[index];
840
+ if (!result)
841
+ continue;
842
+ children[index] = {
843
+ ...children[index],
844
+ ...resultToChildArtifact(result, index, children[index]?.cwd),
845
+ };
846
+ }
847
+ if (completed) {
848
+ for (let index = 0; index < children.length; index++) {
849
+ const child = children[index];
850
+ if (child.status === "queued" || child.status === "running") {
851
+ children[index] = {
852
+ ...child,
853
+ status: "failed",
854
+ completedAt: new Date().toISOString(),
855
+ errorMessage: "Subagent run ended before this child completed.",
856
+ };
857
+ }
858
+ }
859
+ }
860
+ const status = completed ? deriveRunStatus(children) : "running";
861
+ const failed = children.find((child) => child.status === "failed");
862
+ const interrupted = children.find((child) => child.status === "interrupted");
863
+ return {
864
+ ...record,
865
+ children,
866
+ status,
867
+ ...(completed && status !== "running" ? { completedAt: new Date().toISOString() } : {}),
868
+ ...(interrupted
869
+ ? { failure: { type: "interrupted", message: interrupted.errorMessage || interrupted.stderr || "Subagent run was interrupted" } }
870
+ : failed
871
+ ? { failure: { type: failed.merge?.success === false ? "merge-failed" : "child-failed", message: failed.errorMessage || failed.stderr || `Subagent ${failed.agent} failed` } }
872
+ : {}),
873
+ };
874
+ });
875
+ }
876
+ catch {
877
+ // Persistence is observability; execution remains authoritative.
878
+ }
879
+ };
612
880
  emitJournalEvent(ctx.cwd, {
613
881
  ts: new Date().toISOString(),
614
882
  flowId: dispatchId,
@@ -633,10 +901,12 @@ export default function (pi) {
633
901
  turns: 0,
634
902
  });
635
903
  const errorMessageFor = (err) => err instanceof Error ? err.message : String(err || "subagent dispatch failed");
636
- const makeFailureResult = (err, agent, task, step) => {
904
+ const makeFailureResult = (err, agent, task, step, trackingName) => {
637
905
  const message = errorMessageFor(err);
906
+ const dispatchIndex = dispatchAgents.findIndex((dispatchAgent, index) => dispatchAgent === agent && dispatchTasks[index] === task);
638
907
  return {
639
908
  agent,
909
+ trackingName: trackingName ?? (dispatchIndex >= 0 ? dispatchTrackingNames[dispatchIndex] : undefined),
640
910
  agentSource: "unknown",
641
911
  task,
642
912
  exitCode: 1,
@@ -671,18 +941,19 @@ export default function (pi) {
671
941
  if (nextIndex > 0) {
672
942
  return [
673
943
  ...finalResults,
674
- makeFailureResult(err, dispatchAgents[nextIndex] ?? "unknown", dispatchTasks[nextIndex] ?? "", dispatchMode === "chain" ? nextIndex + 1 : undefined),
944
+ makeFailureResult(err, dispatchAgents[nextIndex] ?? "unknown", dispatchTasks[nextIndex] ?? "", dispatchMode === "chain" ? nextIndex + 1 : undefined, dispatchTrackingNames[nextIndex]),
675
945
  ];
676
946
  }
677
947
  }
678
948
  const agentsForFailure = dispatchAgents.length > 0 ? dispatchAgents : ["unknown"];
679
- return agentsForFailure.map((agent, index) => makeFailureResult(err, agent, dispatchTasks[index] ?? "", dispatchMode === "chain" ? index + 1 : undefined));
949
+ return agentsForFailure.map((agent, index) => makeFailureResult(err, agent, dispatchTasks[index] ?? "", dispatchMode === "chain" ? index + 1 : undefined, dispatchTrackingNames[index]));
680
950
  };
681
951
  const finishDispatch = (results) => {
682
952
  if (dispatchCompletedEmitted)
683
953
  return;
684
954
  finalResults = results;
685
955
  dispatchCompletedEmitted = true;
956
+ persistRunResults(results, true);
686
957
  const successCount = results.filter((r) => r.exitCode === 0).length;
687
958
  const failureCount = results.filter((r) => r.exitCode !== 0).length;
688
959
  const totalCost = results.reduce((s, r) => s + (r.usage?.cost ?? 0), 0);
@@ -709,11 +980,11 @@ export default function (pi) {
709
980
  try {
710
981
  if ((agentScope === "project" || agentScope === "both") && confirmProjectAgents && ctx.hasUI) {
711
982
  const requestedAgentNames = new Set();
712
- if (params.chain)
713
- for (const step of params.chain)
983
+ if (hasChain)
984
+ for (const step of chainParams)
714
985
  requestedAgentNames.add(step.agent);
715
- if (params.tasks)
716
- for (const t of params.tasks)
986
+ if (hasTasks)
987
+ for (const t of taskParams)
717
988
  requestedAgentNames.add(t.agent);
718
989
  if (params.agent)
719
990
  requestedAgentNames.add(params.agent);
@@ -733,29 +1004,86 @@ export default function (pi) {
733
1004
  }
734
1005
  }
735
1006
  }
736
- if (params.chain && params.chain.length > 0) {
1007
+ if (params.background) {
1008
+ if (!params.agent || !params.task || hasTasks || hasChain) {
1009
+ const failure = makeFailureResult(new Error("Background launch currently requires single mode with agent and task."), params.agent ?? "unknown", params.task ?? "");
1010
+ finishDispatch([failure]);
1011
+ return {
1012
+ content: [{ type: "text", text: failure.errorMessage ?? failure.stderr }],
1013
+ details: makeDetails("single")([failure]),
1014
+ isError: true,
1015
+ };
1016
+ }
1017
+ void (async () => {
1018
+ let isolation = null;
1019
+ try {
1020
+ const effectiveCwd = params.cwd ?? ctx.cwd;
1021
+ if (useIsolation) {
1022
+ const taskId = crypto.randomUUID();
1023
+ isolation = await createIsolation(effectiveCwd, taskId, isolationMode);
1024
+ }
1025
+ const result = await runSingleAgent(ctx.cwd, agents, params.agent, params.task, isolation ? isolation.workDir : params.cwd, undefined, undefined, (partial) => {
1026
+ if (partial.details?.results[0])
1027
+ persistRunResults([partial.details.results[0]]);
1028
+ }, makeDetails("single"), params.model, contextMode, ctx.sessionManager, undefined, dispatchTrackingNames[0]);
1029
+ if (isolation && result.exitCode === 0) {
1030
+ const patches = await isolation.captureDelta();
1031
+ if (patches.length > 0) {
1032
+ const mergeResult = await mergeDeltaPatches(effectiveCwd, patches);
1033
+ result.mergeResult = mergeResult;
1034
+ if (!mergeResult.success) {
1035
+ result.exitCode = 1;
1036
+ result.stopReason = "error";
1037
+ result.errorMessage = `Patch merge failed: ${mergeResult.error || "unknown error"}`;
1038
+ result.stderr = result.stderr || result.errorMessage;
1039
+ }
1040
+ }
1041
+ }
1042
+ finalResults = [result];
1043
+ finishDispatch([result]);
1044
+ }
1045
+ catch (err) {
1046
+ finalResults = synthesizeFailureResults(err);
1047
+ finishDispatch(finalResults);
1048
+ }
1049
+ finally {
1050
+ if (isolation)
1051
+ await isolation.cleanup();
1052
+ }
1053
+ })();
1054
+ return {
1055
+ content: [{
1056
+ type: "text",
1057
+ text: `Started background subagent run ${dispatchId}. Use action: "status" with runId: "${dispatchId}" to inspect it.`,
1058
+ }],
1059
+ details: makeDetails("single")([]),
1060
+ };
1061
+ }
1062
+ if (chainParams.length > 0) {
737
1063
  const results = [];
738
1064
  finalResults = results;
739
1065
  let previousOutput = "";
740
- for (let i = 0; i < params.chain.length; i++) {
741
- const step = params.chain[i];
1066
+ for (let i = 0; i < chainParams.length; i++) {
1067
+ const step = chainParams[i];
742
1068
  const taskWithContext = step.task.replace(/\{previous\}/g, previousOutput);
743
1069
  // Create update callback that includes all previous results
744
- const chainUpdate = onUpdate
745
- ? (partial) => {
746
- // Combine completed results with current streaming result
747
- const currentResult = partial.details?.results[0];
748
- if (currentResult) {
749
- const allResults = [...results, currentResult];
1070
+ const chainUpdate = (partial) => {
1071
+ // Combine completed results with current streaming result
1072
+ const currentResult = partial.details?.results[0];
1073
+ if (currentResult) {
1074
+ const allResults = [...results, currentResult];
1075
+ persistRunResults(allResults);
1076
+ if (onUpdate) {
750
1077
  onUpdate({
751
1078
  content: partial.content,
752
1079
  details: makeDetails("chain")(allResults),
753
1080
  });
754
1081
  }
755
1082
  }
756
- : undefined;
757
- const result = await runSingleAgent(ctx.cwd, agents, step.agent, taskWithContext, step.cwd, i + 1, signal, chainUpdate, makeDetails("chain"), step.model || params.model);
1083
+ };
1084
+ const result = await runSingleAgent(ctx.cwd, agents, step.agent, taskWithContext, step.cwd, i + 1, signal, chainUpdate, makeDetails("chain"), step.model || params.model, step.context ?? contextMode, ctx.sessionManager, undefined, dispatchTrackingNames[i]);
758
1085
  results.push(result);
1086
+ persistRunResults(results);
759
1087
  const isError = result.exitCode !== 0 || result.stopReason === "error" || result.stopReason === "aborted";
760
1088
  if (isError) {
761
1089
  const errorMsg = result.errorMessage || result.stderr || getFinalOutput(result.messages) || "(no output)";
@@ -774,27 +1102,28 @@ export default function (pi) {
774
1102
  details: makeDetails("chain")(results),
775
1103
  };
776
1104
  }
777
- if (params.tasks && params.tasks.length > 0) {
778
- if (params.tasks.length > MAX_PARALLEL_TASKS) {
1105
+ if (taskParams.length > 0) {
1106
+ if (taskParams.length > MAX_PARALLEL_TASKS) {
779
1107
  finishDispatch([]);
780
1108
  return {
781
1109
  content: [
782
1110
  {
783
1111
  type: "text",
784
- text: `Too many parallel tasks (${params.tasks.length}). Max is ${MAX_PARALLEL_TASKS}.`,
1112
+ text: `Too many parallel tasks (${taskParams.length}). Max is ${MAX_PARALLEL_TASKS}.`,
785
1113
  },
786
1114
  ],
787
1115
  details: makeDetails("parallel")([]),
788
1116
  };
789
1117
  }
790
1118
  // Track all results for streaming updates
791
- const allResults = new Array(params.tasks.length);
1119
+ const allResults = new Array(taskParams.length);
792
1120
  // Initialize placeholder results
793
- for (let i = 0; i < params.tasks.length; i++) {
1121
+ for (let i = 0; i < taskParams.length; i++) {
794
1122
  allResults[i] = {
795
- agent: params.tasks[i].agent,
1123
+ agent: taskParams[i].agent,
1124
+ trackingName: dispatchTrackingNames[i],
796
1125
  agentSource: "unknown",
797
- task: params.tasks[i].task,
1126
+ task: taskParams[i].task,
798
1127
  exitCode: -1, // -1 = still running
799
1128
  messages: [],
800
1129
  stderr: "",
@@ -816,27 +1145,53 @@ export default function (pi) {
816
1145
  };
817
1146
  const MAX_RETRIES = 1; // Retry failed tasks once
818
1147
  const batchId = crypto.randomUUID();
819
- const batchSize = params.tasks.length;
1148
+ const batchSize = taskParams.length;
820
1149
  // Pre-create a grid layout for cmux splits so agents get a clean tiled arrangement
821
1150
  const gridSurfaces = cmuxSplitsEnabled
822
1151
  ? await cmuxClient.createGridLayout(Math.min(batchSize, MAX_CONCURRENCY))
823
1152
  : [];
824
- const results = await mapWithConcurrencyLimit(params.tasks, MAX_CONCURRENCY, async (t, index) => {
1153
+ const results = await mapWithConcurrencyLimit(taskParams, MAX_CONCURRENCY, async (t, index) => {
825
1154
  const workerId = registerWorker(t.agent, t.task, index, batchSize, batchId);
826
1155
  const taskModel = t.model || params.model;
827
- const runTask = () => cmuxSplitsEnabled
828
- ? runSingleAgentInCmuxSplit(cmuxClient, gridSurfaces[index] ?? (index % 2 === 0 ? "right" : "down"), ctx.cwd, agents, t.agent, t.task, t.cwd, undefined, signal, (partial) => {
829
- if (partial.details?.results[0]) {
830
- allResults[index] = partial.details.results[0];
831
- emitParallelUpdate();
1156
+ const updateParallelResult = (partial) => {
1157
+ if (partial.details?.results[0]) {
1158
+ allResults[index] = partial.details.results[0];
1159
+ persistRunResults([...allResults]);
1160
+ emitParallelUpdate();
1161
+ }
1162
+ };
1163
+ const executeOnce = (runCwd) => cmuxSplitsEnabled
1164
+ ? runSingleAgentInCmuxSplit(cmuxClient, gridSurfaces[index] ?? (index % 2 === 0 ? "right" : "down"), ctx.cwd, agents, t.agent, t.task, runCwd, undefined, signal, updateParallelResult, makeDetails("parallel"), taskModel, t.context ?? contextMode, ctx.sessionManager, undefined, dispatchTrackingNames[index])
1165
+ : runSingleAgent(ctx.cwd, agents, t.agent, t.task, runCwd, undefined, signal, updateParallelResult, makeDetails("parallel"), taskModel, t.context ?? contextMode, ctx.sessionManager, undefined, dispatchTrackingNames[index]);
1166
+ const runTask = async () => {
1167
+ let isolation = null;
1168
+ const effectiveCwd = t.cwd ?? ctx.cwd;
1169
+ try {
1170
+ if (useIsolation) {
1171
+ const taskId = crypto.randomUUID();
1172
+ isolation = await createIsolation(effectiveCwd, taskId, isolationMode);
832
1173
  }
833
- }, makeDetails("parallel"), taskModel)
834
- : runSingleAgent(ctx.cwd, agents, t.agent, t.task, t.cwd, undefined, signal, (partial) => {
835
- if (partial.details?.results[0]) {
836
- allResults[index] = partial.details.results[0];
837
- emitParallelUpdate();
1174
+ const result = await executeOnce(isolation ? isolation.workDir : t.cwd);
1175
+ if (isolation && result.exitCode === 0) {
1176
+ const patches = await isolation.captureDelta();
1177
+ const mergeResult = patches.length > 0
1178
+ ? await mergeDeltaPatches(effectiveCwd, patches)
1179
+ : { success: true, appliedPatches: [], failedPatches: [] };
1180
+ result.mergeResult = mergeResult;
1181
+ if (!mergeResult.success) {
1182
+ result.exitCode = 1;
1183
+ result.stopReason = "error";
1184
+ result.errorMessage = `Patch merge failed: ${mergeResult.error || "unknown error"}`;
1185
+ result.stderr = result.stderr || result.errorMessage;
1186
+ }
838
1187
  }
839
- }, makeDetails("parallel"), taskModel);
1188
+ return result;
1189
+ }
1190
+ finally {
1191
+ if (isolation)
1192
+ await isolation.cleanup();
1193
+ }
1194
+ };
840
1195
  let result = await runTask();
841
1196
  // Auto-retry failed tasks (likely API rate limit or transient error)
842
1197
  const isFailed = result.exitCode !== 0 || (result.messages.length === 0 && !signal?.aborted);
@@ -845,6 +1200,7 @@ export default function (pi) {
845
1200
  }
846
1201
  updateWorker(workerId, result.exitCode === 0 ? "completed" : "failed");
847
1202
  allResults[index] = result;
1203
+ persistRunResults([...allResults]);
848
1204
  emitParallelUpdate();
849
1205
  return result;
850
1206
  });
@@ -855,7 +1211,7 @@ export default function (pi) {
855
1211
  const output = isError
856
1212
  ? (r.errorMessage || r.stderr || getFinalOutput(r.messages) || "(no output)")
857
1213
  : getFinalOutput(r.messages);
858
- return `[${r.agent}] ${r.exitCode === 0 ? "completed" : `failed (exit ${r.exitCode})`}: ${output || "(no output)"}`;
1214
+ return `[${formatAgentLabel(r.agent, r.trackingName)}] ${r.exitCode === 0 ? "completed" : `failed (exit ${r.exitCode})`}: ${output || "(no output)"}`;
859
1215
  });
860
1216
  finishDispatch(results);
861
1217
  return {
@@ -877,15 +1233,28 @@ export default function (pi) {
877
1233
  const taskId = crypto.randomUUID();
878
1234
  isolation = await createIsolation(effectiveCwd, taskId, isolationMode);
879
1235
  }
1236
+ const singleUpdate = (partial) => {
1237
+ if (partial.details?.results[0])
1238
+ persistRunResults([partial.details.results[0]]);
1239
+ if (onUpdate)
1240
+ onUpdate(partial);
1241
+ };
880
1242
  const result = cmuxSplitsEnabled
881
- ? await runSingleAgentInCmuxSplit(cmuxClient, "right", ctx.cwd, agents, params.agent, params.task, isolation ? isolation.workDir : params.cwd, undefined, signal, onUpdate, makeDetails("single"), params.model)
882
- : await runSingleAgent(ctx.cwd, agents, params.agent, params.task, isolation ? isolation.workDir : params.cwd, undefined, signal, onUpdate, makeDetails("single"), params.model);
1243
+ ? await runSingleAgentInCmuxSplit(cmuxClient, "right", ctx.cwd, agents, params.agent, params.task, isolation ? isolation.workDir : params.cwd, undefined, signal, singleUpdate, makeDetails("single"), params.model, contextMode, ctx.sessionManager, undefined, dispatchTrackingNames[0])
1244
+ : await runSingleAgent(ctx.cwd, agents, params.agent, params.task, isolation ? isolation.workDir : params.cwd, undefined, signal, singleUpdate, makeDetails("single"), params.model, contextMode, ctx.sessionManager, undefined, dispatchTrackingNames[0]);
883
1245
  finalResults = [result];
884
1246
  // Capture and merge delta if isolated
885
1247
  if (isolation) {
886
1248
  const patches = await isolation.captureDelta();
887
1249
  if (patches.length > 0) {
888
1250
  mergeResult = await mergeDeltaPatches(effectiveCwd, patches);
1251
+ result.mergeResult = mergeResult;
1252
+ if (!mergeResult.success) {
1253
+ result.exitCode = 1;
1254
+ result.stopReason = "error";
1255
+ result.errorMessage = `Patch merge failed: ${mergeResult.error || "unknown error"}`;
1256
+ result.stderr = result.stderr || result.errorMessage;
1257
+ }
889
1258
  }
890
1259
  }
891
1260
  const isError = result.exitCode !== 0 || result.stopReason === "error" || result.stopReason === "aborted";
@@ -927,7 +1296,8 @@ export default function (pi) {
927
1296
  throw err;
928
1297
  }
929
1298
  finally {
930
- finishDispatch(finalResults);
1299
+ if (!params.background)
1300
+ finishDispatch(finalResults);
931
1301
  }
932
1302
  },
933
1303
  renderCall(args, theme) {
@@ -1004,7 +1374,7 @@ export default function (pi) {
1004
1374
  const finalOutput = getFinalOutput(r.messages);
1005
1375
  if (expanded) {
1006
1376
  const container = new Container();
1007
- let header = `${icon} ${theme.fg("toolTitle", theme.bold(r.agent))}${theme.fg("muted", ` (${r.agentSource})`)}`;
1377
+ let header = `${icon} ${theme.fg("toolTitle", theme.bold(formatAgentLabel(r.agent, r.trackingName)))}${theme.fg("muted", ` (${r.agentSource})`)}`;
1008
1378
  if (isError && r.stopReason)
1009
1379
  header += ` ${theme.fg("error", `[${r.stopReason}]`)}`;
1010
1380
  container.addChild(new Text(header, 0, 0));
@@ -1035,7 +1405,7 @@ export default function (pi) {
1035
1405
  }
1036
1406
  return container;
1037
1407
  }
1038
- let text = `${icon} ${theme.fg("toolTitle", theme.bold(r.agent))}${theme.fg("muted", ` (${r.agentSource})`)}`;
1408
+ let text = `${icon} ${theme.fg("toolTitle", theme.bold(formatAgentLabel(r.agent, r.trackingName)))}${theme.fg("muted", ` (${r.agentSource})`)}`;
1039
1409
  if (isError && r.stopReason)
1040
1410
  text += ` ${theme.fg("error", `[${r.stopReason}]`)}`;
1041
1411
  if (isError && r.errorMessage)
@@ -1078,7 +1448,7 @@ export default function (pi) {
1078
1448
  const displayItems = getDisplayItems(r.messages);
1079
1449
  const finalOutput = getFinalOutput(r.messages);
1080
1450
  container.addChild(new Spacer(1));
1081
- container.addChild(new Text(`${theme.fg("muted", `─── Step ${r.step}: `) + theme.fg("accent", r.agent)} ${rIcon}`, 0, 0));
1451
+ container.addChild(new Text(`${theme.fg("muted", `─── Step ${r.step}: `) + theme.fg("accent", formatAgentLabel(r.agent, r.trackingName))} ${rIcon}`, 0, 0));
1082
1452
  container.addChild(new Text(theme.fg("muted", "Task: ") + theme.fg("dim", r.task), 0, 0));
1083
1453
  // Show tool calls
1084
1454
  for (const item of displayItems) {
@@ -1110,7 +1480,7 @@ export default function (pi) {
1110
1480
  for (const r of details.results) {
1111
1481
  const rIcon = r.exitCode === 0 ? theme.fg("success", "✓") : theme.fg("error", "✗");
1112
1482
  const displayItems = getDisplayItems(r.messages);
1113
- text += `\n\n${theme.fg("muted", `─── Step ${r.step}: `)}${theme.fg("accent", r.agent)} ${rIcon}`;
1483
+ text += `\n\n${theme.fg("muted", `─── Step ${r.step}: `)}${theme.fg("accent", formatAgentLabel(r.agent, r.trackingName))} ${rIcon}`;
1114
1484
  if (displayItems.length === 0)
1115
1485
  text += `\n${theme.fg("muted", "(no output)")}`;
1116
1486
  else
@@ -1143,7 +1513,7 @@ export default function (pi) {
1143
1513
  const displayItems = getDisplayItems(r.messages);
1144
1514
  const finalOutput = getFinalOutput(r.messages);
1145
1515
  container.addChild(new Spacer(1));
1146
- container.addChild(new Text(`${theme.fg("muted", "─── ") + theme.fg("accent", r.agent)} ${rIcon}`, 0, 0));
1516
+ container.addChild(new Text(`${theme.fg("muted", "─── ") + theme.fg("accent", formatAgentLabel(r.agent, r.trackingName))} ${rIcon}`, 0, 0));
1147
1517
  container.addChild(new Text(theme.fg("muted", "Task: ") + theme.fg("dim", r.task), 0, 0));
1148
1518
  // Show tool calls
1149
1519
  for (const item of displayItems) {
@@ -1176,7 +1546,7 @@ export default function (pi) {
1176
1546
  ? theme.fg("success", "✓")
1177
1547
  : theme.fg("error", "✗");
1178
1548
  const displayItems = getDisplayItems(r.messages);
1179
- text += `\n\n${theme.fg("muted", "─── ")}${theme.fg("accent", r.agent)} ${rIcon}`;
1549
+ text += `\n\n${theme.fg("muted", "─── ")}${theme.fg("accent", formatAgentLabel(r.agent, r.trackingName))} ${rIcon}`;
1180
1550
  if (displayItems.length === 0)
1181
1551
  text += `\n${theme.fg("muted", r.exitCode === -1 ? "(running...)" : "(no output)")}`;
1182
1552
  else