@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.75048e7

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 (452) hide show
  1. package/dist/cli.js +3 -2
  2. package/dist/help-text.js +10 -6
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
  5. package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
  6. package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
  7. package/dist/resources/extensions/browser-tools/index.js +57 -9
  8. package/dist/resources/extensions/browser-tools/package.json +5 -1
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +167 -16
  10. package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
  11. package/dist/resources/extensions/gsd/auto/phases.js +4 -3
  12. package/dist/resources/extensions/gsd/auto-dashboard.js +92 -17
  13. package/dist/resources/extensions/gsd/auto-dispatch.js +55 -0
  14. package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
  15. package/dist/resources/extensions/gsd/auto-prompts.js +72 -22
  16. package/dist/resources/extensions/gsd/auto-recovery.js +7 -8
  17. package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
  18. package/dist/resources/extensions/gsd/auto-start.js +94 -15
  19. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  20. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +18 -65
  21. package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
  22. package/dist/resources/extensions/gsd/auto.js +31 -6
  23. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -4
  24. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +56 -20
  26. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +33 -38
  27. package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
  28. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
  29. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  30. package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
  31. package/dist/resources/extensions/gsd/commands/handlers/ops.js +9 -5
  32. package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
  33. package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
  34. package/dist/resources/extensions/gsd/commands-mcp-status.js +109 -60
  35. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
  36. package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
  37. package/dist/resources/extensions/gsd/config-overlay.js +2 -1
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
  41. package/dist/resources/extensions/gsd/error-classifier.js +2 -1
  42. package/dist/resources/extensions/gsd/escalation.js +4 -4
  43. package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
  44. package/dist/resources/extensions/gsd/forensics.js +74 -2
  45. package/dist/resources/extensions/gsd/gsd-db.js +42 -6
  46. package/dist/resources/extensions/gsd/guided-flow.js +119 -176
  47. package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
  48. package/dist/resources/extensions/gsd/mcp-project-config.js +76 -84
  49. package/dist/resources/extensions/gsd/memory-store.js +4 -1
  50. package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
  51. package/dist/resources/extensions/gsd/milestone-closeout.js +3 -1
  52. package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
  53. package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
  54. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  55. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  56. package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
  57. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  58. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  59. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  60. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  61. package/dist/resources/extensions/gsd/prompts/run-uat.md +33 -23
  62. package/dist/resources/extensions/gsd/prompts/system.md +3 -1
  63. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  64. package/dist/resources/extensions/gsd/recovery-classification.js +20 -0
  65. package/dist/resources/extensions/gsd/rule-registry.js +428 -52
  66. package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
  67. package/dist/resources/extensions/gsd/skill-activation.js +20 -3
  68. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +4 -2
  69. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
  70. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
  71. package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
  72. package/dist/resources/extensions/gsd/state.js +17 -14
  73. package/dist/resources/extensions/gsd/templates/plan.md +3 -1
  74. package/dist/resources/extensions/gsd/tool-contract.js +5 -0
  75. package/dist/resources/extensions/gsd/tool-presentation-plan.js +143 -0
  76. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
  77. package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
  78. package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
  79. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
  80. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  81. package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
  82. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +483 -6
  83. package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
  84. package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
  85. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  86. package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
  87. package/dist/resources/extensions/gsd/verification-gate.js +72 -1
  88. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -1
  89. package/dist/resources/extensions/gsd/workflow-mcp.js +5 -73
  90. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
  91. package/dist/resources/extensions/mcp-client/manager.js +31 -1
  92. package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
  93. package/dist/rtk.d.ts +7 -1
  94. package/dist/rtk.js +27 -11
  95. package/dist/update-check.d.ts +15 -1
  96. package/dist/update-check.js +87 -12
  97. package/dist/update-cmd.d.ts +1 -0
  98. package/dist/update-cmd.js +53 -2
  99. package/dist/web/standalone/.next/BUILD_ID +1 -1
  100. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  101. package/dist/web/standalone/.next/build-manifest.json +2 -2
  102. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  103. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  112. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/index.html +1 -1
  121. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  128. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  129. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  131. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  132. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  133. package/package.json +5 -3
  134. package/packages/cloud-mcp-gateway/package.json +2 -2
  135. package/packages/contracts/dist/workflow.d.ts +14 -0
  136. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  137. package/packages/contracts/dist/workflow.js +16 -0
  138. package/packages/contracts/dist/workflow.js.map +1 -1
  139. package/packages/contracts/package.json +1 -1
  140. package/packages/daemon/package.json +4 -4
  141. package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
  142. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  143. package/packages/gsd-agent-core/dist/agent-session.js +32 -0
  144. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  145. package/packages/gsd-agent-core/dist/index.d.ts +1 -0
  146. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  147. package/packages/gsd-agent-core/dist/index.js +1 -0
  148. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  149. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
  150. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
  151. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
  152. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
  153. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
  154. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  155. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  156. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  157. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
  158. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  159. package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
  160. package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
  161. package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
  162. package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
  163. package/packages/gsd-agent-core/package.json +6 -6
  164. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
  165. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
  167. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
  168. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  169. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  171. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  172. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  173. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
  176. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  177. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +92 -31
  178. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  179. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
  181. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  188. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  190. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
  194. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  196. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
  197. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  198. package/packages/gsd-agent-modes/package.json +7 -7
  199. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  200. package/packages/mcp-server/dist/remote-questions.js +23 -9
  201. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  203. package/packages/mcp-server/dist/workflow-tools.js +84 -2
  204. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  205. package/packages/mcp-server/package.json +3 -3
  206. package/packages/native/package.json +1 -1
  207. package/packages/pi-agent-core/dist/agent-loop.js +42 -3
  208. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  209. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  210. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  211. package/packages/pi-agent-core/dist/agent.js +2 -0
  212. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  213. package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  214. package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
  215. package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  216. package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
  217. package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  218. package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
  219. package/packages/pi-agent-core/dist/types.d.ts +6 -1
  220. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  221. package/packages/pi-agent-core/dist/types.js.map +1 -1
  222. package/packages/pi-agent-core/package.json +1 -1
  223. package/packages/pi-ai/dist/api-registry.d.ts +2 -0
  224. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  225. package/packages/pi-ai/dist/api-registry.js +23 -0
  226. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  227. package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
  228. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  229. package/packages/pi-ai/dist/image-models.generated.js +15 -0
  230. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  231. package/packages/pi-ai/dist/models.generated.d.ts +411 -39
  232. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  233. package/packages/pi-ai/dist/models.generated.js +504 -153
  234. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  235. package/packages/pi-ai/dist/stream.js +6 -6
  236. package/packages/pi-ai/dist/stream.js.map +1 -1
  237. package/packages/pi-ai/package.json +1 -1
  238. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
  239. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  240. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  243. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  245. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  246. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  247. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
  249. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  251. package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
  252. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  253. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
  254. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
  256. package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
  257. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
  259. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  260. package/packages/pi-coding-agent/package.json +7 -7
  261. package/packages/pi-tui/dist/terminal.d.ts +1 -0
  262. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  263. package/packages/pi-tui/dist/terminal.js +8 -4
  264. package/packages/pi-tui/dist/terminal.js.map +1 -1
  265. package/packages/pi-tui/package.json +1 -1
  266. package/packages/rpc-client/package.json +2 -2
  267. package/pkg/package.json +1 -1
  268. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
  269. package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
  270. package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
  271. package/src/resources/extensions/browser-tools/index.ts +60 -9
  272. package/src/resources/extensions/browser-tools/package.json +5 -1
  273. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
  274. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
  275. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
  276. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
  277. package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
  278. package/src/resources/extensions/gsd/auto/phases.ts +5 -3
  279. package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
  280. package/src/resources/extensions/gsd/auto-dispatch.ts +67 -0
  281. package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
  282. package/src/resources/extensions/gsd/auto-prompts.ts +106 -15
  283. package/src/resources/extensions/gsd/auto-recovery.ts +7 -7
  284. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
  285. package/src/resources/extensions/gsd/auto-start.ts +112 -17
  286. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  287. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -73
  288. package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
  289. package/src/resources/extensions/gsd/auto.ts +47 -5
  290. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +96 -4
  291. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
  292. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +81 -25
  293. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +70 -63
  294. package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
  295. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
  296. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  297. package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
  298. package/src/resources/extensions/gsd/commands/handlers/ops.ts +9 -5
  299. package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
  300. package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
  301. package/src/resources/extensions/gsd/commands-mcp-status.ts +136 -58
  302. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
  303. package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
  304. package/src/resources/extensions/gsd/config-overlay.ts +3 -1
  305. package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
  306. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  307. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
  308. package/src/resources/extensions/gsd/error-classifier.ts +2 -1
  309. package/src/resources/extensions/gsd/escalation.ts +4 -4
  310. package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
  311. package/src/resources/extensions/gsd/forensics.ts +99 -5
  312. package/src/resources/extensions/gsd/gsd-db.ts +46 -8
  313. package/src/resources/extensions/gsd/guided-flow.ts +215 -217
  314. package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
  315. package/src/resources/extensions/gsd/mcp-project-config.ts +105 -88
  316. package/src/resources/extensions/gsd/memory-store.ts +4 -1
  317. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  318. package/src/resources/extensions/gsd/milestone-closeout.ts +3 -1
  319. package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
  320. package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
  321. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  322. package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
  323. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  324. package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
  325. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  326. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  327. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  328. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  329. package/src/resources/extensions/gsd/prompts/run-uat.md +33 -23
  330. package/src/resources/extensions/gsd/prompts/system.md +3 -1
  331. package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  332. package/src/resources/extensions/gsd/recovery-classification.ts +20 -0
  333. package/src/resources/extensions/gsd/rule-registry.ts +558 -58
  334. package/src/resources/extensions/gsd/rule-types.ts +2 -0
  335. package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
  336. package/src/resources/extensions/gsd/skill-activation.ts +20 -2
  337. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +4 -2
  338. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
  339. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
  340. package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
  341. package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
  342. package/src/resources/extensions/gsd/state.ts +18 -14
  343. package/src/resources/extensions/gsd/templates/plan.md +3 -1
  344. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
  345. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +123 -0
  346. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +10 -2
  347. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
  348. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
  349. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
  350. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +12 -2
  351. package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
  352. package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
  353. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
  354. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
  355. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
  356. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
  357. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
  358. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  359. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
  360. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
  361. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
  362. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
  363. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
  364. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +40 -1
  365. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -0
  366. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
  367. package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
  368. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
  369. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
  370. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
  371. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
  372. package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
  373. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +31 -79
  374. package/src/resources/extensions/gsd/tests/gsd-rebuild.test.ts +199 -0
  375. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -0
  376. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
  377. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
  378. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +5 -3
  379. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
  380. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
  381. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
  382. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
  383. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
  384. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +72 -10
  385. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +13 -6
  386. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
  387. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +100 -0
  388. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +179 -0
  389. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
  390. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +63 -0
  391. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
  392. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
  394. package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
  395. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
  396. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
  397. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +39 -1
  398. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
  399. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
  400. package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
  401. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +83 -1
  402. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
  403. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
  404. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
  405. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
  406. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +79 -0
  407. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
  408. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
  409. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +4 -0
  410. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
  411. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
  412. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
  413. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
  414. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  415. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
  416. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  417. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
  418. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
  419. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
  420. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
  421. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
  422. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
  423. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
  424. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
  425. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +17 -2
  426. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +493 -0
  427. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +40 -0
  428. package/src/resources/extensions/gsd/tool-contract.ts +6 -0
  429. package/src/resources/extensions/gsd/tool-presentation-plan.ts +223 -0
  430. package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
  431. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
  432. package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
  433. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
  434. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  435. package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
  436. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +589 -8
  437. package/src/resources/extensions/gsd/types.ts +69 -5
  438. package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
  439. package/src/resources/extensions/gsd/unit-tool-contracts.ts +186 -0
  440. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  441. package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
  442. package/src/resources/extensions/gsd/verification-gate.ts +87 -1
  443. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -1
  444. package/src/resources/extensions/gsd/workflow-mcp.ts +5 -73
  445. package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
  446. package/src/resources/extensions/mcp-client/manager.ts +33 -1
  447. package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
  448. package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
  449. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
  450. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
  451. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_buildManifest.js +0 -0
  452. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_ssgManifest.js +0 -0
@@ -1,7 +1,7 @@
1
1
  // gsd-pi - Claude Code stream adapter regression tests
2
2
  import { describe, test } from "node:test";
3
3
  import assert from "node:assert/strict";
4
- import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
4
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
5
5
  import { join, resolve } from "node:path";
6
6
  import { tmpdir } from "node:os";
7
7
  import {
@@ -33,6 +33,8 @@ import {
33
33
  resolveBundledClaudeCliPath,
34
34
  normalizeClaudePathForSdk,
35
35
  roundResultToElicitationContent,
36
+ autoInitClaudeCodeWorkflowMcp,
37
+ inferGsdPhaseFromContext,
36
38
  } from "../stream-adapter.ts";
37
39
  import type { AssistantMessage, Context, Message } from "@gsd/pi-ai";
38
40
  import type { SDKUserMessage } from "../sdk-types.ts";
@@ -794,6 +796,11 @@ describe("stream-adapter — session persistence (#2859)", () => {
794
796
  assert.equal(options.persistSession, true, "persistSession must default to true");
795
797
  });
796
798
 
799
+ test("buildSdkOptions loads project and local settings so approved .mcp.json servers are active", () => {
800
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test prompt");
801
+ assert.deepEqual(options.settingSources, ["project", "local"]);
802
+ });
803
+
797
804
  test("buildSdkOptions sets model and prompt correctly", () => {
798
805
  const options = buildSdkOptions("claude-sonnet-4-20250514", "hello world");
799
806
  assert.equal(options.model, "claude-sonnet-4-20250514");
@@ -829,6 +836,29 @@ describe("stream-adapter — session persistence (#2859)", () => {
829
836
  }
830
837
  });
831
838
 
839
+ test("autoInitClaudeCodeWorkflowMcp writes and approves project GSD MCP config", () => {
840
+ const projectRoot = realpathSync(mkdtempSync(join(tmpdir(), "claude-sdk-auto-init-")));
841
+ const restore = setWorkflowMcpEnv({
842
+ GSD_WORKFLOW_MCP_COMMAND: "node",
843
+ GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
844
+ GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["server.js"]),
845
+ GSD_WORKFLOW_MCP_CWD: projectRoot,
846
+ });
847
+
848
+ try {
849
+ autoInitClaudeCodeWorkflowMcp(projectRoot);
850
+ assert.equal(existsSync(join(projectRoot, ".mcp.json")), true);
851
+
852
+ const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
853
+ enabledMcpjsonServers?: string[];
854
+ };
855
+ assert.deepEqual(settings.enabledMcpjsonServers, ["gsd-workflow", "gsd-browser"]);
856
+ } finally {
857
+ restore();
858
+ rmSync(projectRoot, { recursive: true, force: true });
859
+ }
860
+ });
861
+
832
862
  test("resolveClaudeCodeCwd falls back to process cwd when no stream cwd is provided", () => {
833
863
  assert.equal(resolveClaudeCodeCwd(), process.cwd());
834
864
  assert.equal(resolveClaudeCodeCwd({ cwd: " " }), process.cwd());
@@ -1013,21 +1043,118 @@ describe("stream-adapter — session persistence (#2859)", () => {
1013
1043
  }
1014
1044
  });
1015
1045
 
1016
- test("buildSdkOptions prefers custom workflow MCP question tools over native AskUserQuestion", () => {
1017
- const restore = setWorkflowMcpEnv({
1018
- GSD_WORKFLOW_MCP_COMMAND: "node",
1046
+ test("buildSdkOptions scopes run-uat to exact workflow MCP tools", () => {
1047
+ const restore = setWorkflowMcpEnv({
1048
+ GSD_WORKFLOW_MCP_COMMAND: "node",
1049
+ GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
1050
+ GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["packages/mcp-server/dist/cli.js"]),
1051
+ GSD_WORKFLOW_MCP_ENV: JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" }),
1052
+ GSD_WORKFLOW_MCP_CWD: "/tmp/project",
1053
+ });
1054
+ const originalCwd = process.cwd();
1055
+ const emptyDir = mkdtempSync(join(tmpdir(), "claude-mcp-uat-"));
1056
+ try {
1057
+ process.chdir(emptyDir);
1058
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test", undefined, { gsdPhase: "run-uat" });
1059
+ const allowedTools = options.allowedTools as string[];
1060
+ const disallowedTools = options.disallowedTools as string[];
1061
+
1062
+ assert.deepEqual(allowedTools, [
1063
+ "Read",
1064
+ "Glob",
1065
+ "Grep",
1066
+ "mcp__gsd-workflow__gsd_uat_exec",
1067
+ "mcp__gsd-workflow__gsd_uat_result_save",
1068
+ "mcp__gsd-workflow__gsd_resume",
1069
+ "mcp__gsd-workflow__gsd_milestone_status",
1070
+ "mcp__gsd-workflow__gsd_journal_query",
1071
+ "mcp__gsd-browser__*",
1072
+ ]);
1073
+ assert.ok(!allowedTools.includes("Bash"));
1074
+ assert.ok(!allowedTools.includes("Write"));
1075
+ assert.ok(!allowedTools.includes("Edit"));
1076
+ assert.ok(!allowedTools.includes("WebSearch"));
1077
+ assert.ok(!allowedTools.includes("mcp__gsd-workflow__*"));
1078
+ assert.ok(disallowedTools.includes("Bash"));
1079
+ assert.ok(disallowedTools.includes("Write"));
1080
+ assert.ok(disallowedTools.includes("Edit"));
1081
+ assert.ok(disallowedTools.includes("WebSearch"));
1082
+ assert.ok(disallowedTools.includes("mcp__gsd-workflow__gsd_exec"));
1083
+ assert.ok(disallowedTools.includes("mcp__gsd-workflow__gsd_summary_save"));
1084
+ assert.ok(disallowedTools.includes("mcp__gsd-workflow__gsd_save_gate_result"));
1085
+ assert.equal(options.strictMcpConfig, true);
1086
+ assert.deepEqual(options.settingSources, []);
1087
+ assert.ok((options.mcpServers as Record<string, unknown>)?.["gsd-workflow"]);
1088
+ assert.ok((options.mcpServers as Record<string, unknown>)?.["gsd-browser"]);
1089
+ } finally {
1090
+ process.chdir(originalCwd);
1091
+ rmSync(emptyDir, { recursive: true, force: true });
1092
+ restore();
1093
+ }
1094
+ });
1095
+
1096
+ test("buildSdkOptions presents exact required workflow MCP tools for non-UAT GSD phases", () => {
1097
+ const restore = setWorkflowMcpEnv({
1098
+ GSD_WORKFLOW_MCP_COMMAND: "node",
1099
+ GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
1100
+ GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["packages/mcp-server/dist/cli.js"]),
1101
+ GSD_WORKFLOW_MCP_ENV: JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" }),
1102
+ GSD_WORKFLOW_MCP_CWD: "/tmp/project",
1103
+ });
1104
+ const originalCwd = process.cwd();
1105
+ const emptyDir = mkdtempSync(join(tmpdir(), "claude-mcp-plan-"));
1106
+ try {
1107
+ process.chdir(emptyDir);
1108
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test", undefined, { gsdPhase: "plan-milestone" });
1109
+ const allowedTools = options.allowedTools as string[];
1110
+
1111
+ assert.ok(
1112
+ allowedTools.includes("mcp__gsd-workflow__gsd_plan_milestone"),
1113
+ "plan-milestone must expose exact planning tool",
1114
+ );
1115
+ assert.ok(
1116
+ allowedTools.includes("mcp__gsd-workflow__gsd_milestone_status"),
1117
+ "plan-milestone must expose exact milestone status helper before ToolSearch is needed",
1118
+ );
1119
+ assert.ok(
1120
+ allowedTools.includes("mcp__gsd-workflow__*"),
1121
+ "non-UAT workflow phases keep the wildcard for existing broad workflow behavior",
1122
+ );
1123
+ assert.ok((options.disallowedTools as string[]).includes("AskUserQuestion"));
1124
+ assert.equal(options.strictMcpConfig, true);
1125
+ assert.ok((options.mcpServers as Record<string, unknown>)?.["gsd-workflow"]);
1126
+ } finally {
1127
+ process.chdir(originalCwd);
1128
+ rmSync(emptyDir, { recursive: true, force: true });
1129
+ restore();
1130
+ }
1131
+ });
1132
+
1133
+ test("inferGsdPhaseFromContext recognizes non-UAT unit prompts", () => {
1134
+ const context = {
1135
+ messages: [
1136
+ { role: "user", content: "## UNIT: Plan Milestone M002 (\"Plan by Priority\")" },
1137
+ ],
1138
+ } as Context;
1139
+
1140
+ assert.equal(inferGsdPhaseFromContext(context), "plan-milestone");
1141
+ });
1142
+
1143
+ test("buildSdkOptions prefers custom workflow MCP question tools over native AskUserQuestion", () => {
1144
+ const restore = setWorkflowMcpEnv({
1145
+ GSD_WORKFLOW_MCP_COMMAND: "node",
1019
1146
  GSD_WORKFLOW_MCP_NAME: "custom-workflow",
1020
1147
  GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["packages/mcp-server/dist/cli.js"]),
1021
- GSD_WORKFLOW_MCP_ENV: JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" }),
1022
- GSD_WORKFLOW_MCP_CWD: "/tmp/project",
1023
- });
1024
- const originalCwd = process.cwd();
1025
- const emptyDir = mkdtempSync(join(tmpdir(), "claude-mcp-custom-inject-"));
1026
- try {
1027
- process.chdir(emptyDir);
1148
+ GSD_WORKFLOW_MCP_ENV: JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" }),
1149
+ GSD_WORKFLOW_MCP_CWD: "/tmp/project",
1150
+ });
1151
+ const originalCwd = process.cwd();
1152
+ const emptyDir = mkdtempSync(join(tmpdir(), "claude-mcp-custom-inject-"));
1153
+ try {
1154
+ process.chdir(emptyDir);
1028
1155
 
1029
- const options = buildSdkOptions("claude-sonnet-4-20250514", "test");
1030
- const mcpServers = options.mcpServers as Record<string, any>;
1156
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test");
1157
+ const mcpServers = options.mcpServers as Record<string, any>;
1031
1158
  assert.ok(mcpServers?.["custom-workflow"], "expected custom workflow server config");
1032
1159
  assert.ok(mcpServers?.["gsd-browser"], "expected gsd-browser server config");
1033
1160
  assert.deepEqual(options.disallowedTools, ["ToolSearch", "AskUserQuestion"]);
@@ -1041,15 +1168,15 @@ describe("stream-adapter — session persistence (#2859)", () => {
1041
1168
  "Agent",
1042
1169
  "WebFetch",
1043
1170
  "WebSearch",
1044
- "mcp__custom-workflow__*",
1045
- "mcp__gsd-browser__*",
1046
- ]);
1047
- } finally {
1048
- process.chdir(originalCwd);
1049
- rmSync(emptyDir, { recursive: true, force: true });
1050
- restore();
1051
- }
1052
- });
1171
+ "mcp__custom-workflow__*",
1172
+ "mcp__gsd-browser__*",
1173
+ ]);
1174
+ } finally {
1175
+ process.chdir(originalCwd);
1176
+ rmSync(emptyDir, { recursive: true, force: true });
1177
+ restore();
1178
+ }
1179
+ });
1053
1180
 
1054
1181
  test("buildSdkOptions auto-discovers bundled MCP server even without env hints", () => {
1055
1182
  // Use setWorkflowMcpEnv with no values to save current state;
@@ -1162,7 +1289,41 @@ describe("stream-adapter — session persistence (#2859)", () => {
1162
1289
  }
1163
1290
  });
1164
1291
 
1165
- test("buildSdkOptions does not inject workflow MCP when already declared in project .mcp.json (avoids duplicate registration)", () => {
1292
+ test("buildSdkOptions force-inlines workflow MCP for GSD phases when project .mcp.json already declares it", () => {
1293
+ const restore = setWorkflowMcpEnv({
1294
+ GSD_WORKFLOW_MCP_COMMAND: "node",
1295
+ GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
1296
+ GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["packages/mcp-server/dist/cli.js"]),
1297
+ GSD_WORKFLOW_MCP_ENV: JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" }),
1298
+ GSD_WORKFLOW_MCP_CWD: "/tmp/project",
1299
+ });
1300
+ const originalCwd = process.cwd();
1301
+ const projectDir = mkdtempSync(join(tmpdir(), "claude-mcp-inline-project-"));
1302
+ try {
1303
+ writeFileSync(
1304
+ join(projectDir, ".mcp.json"),
1305
+ JSON.stringify({ mcpServers: { "gsd-workflow": { command: "node", args: ["old-cli.js"] }, "other-mcp": { command: "npx", args: ["other"] } } }),
1306
+ );
1307
+ process.chdir(projectDir);
1308
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test", undefined, { gsdPhase: "plan-milestone" });
1309
+
1310
+ assert.equal(options.strictMcpConfig, true);
1311
+ assert.deepEqual(options.settingSources, []);
1312
+ assert.deepEqual(options.mcpServers, {
1313
+ "gsd-workflow": { command: "node", args: ["old-cli.js"] },
1314
+ });
1315
+ const allowedTools = options.allowedTools as string[];
1316
+ assert.ok(allowedTools.includes("mcp__gsd-workflow__gsd_plan_milestone"));
1317
+ assert.ok(allowedTools.includes("mcp__gsd-workflow__gsd_milestone_status"));
1318
+ assert.ok(allowedTools.includes("mcp__gsd-workflow__*"));
1319
+ } finally {
1320
+ process.chdir(originalCwd);
1321
+ rmSync(projectDir, { recursive: true, force: true });
1322
+ restore();
1323
+ }
1324
+ });
1325
+
1326
+ test("buildSdkOptions does not inject workflow MCP when already declared in project .mcp.json outside GSD phases", () => {
1166
1327
  const restore = setWorkflowMcpEnv({
1167
1328
  GSD_WORKFLOW_MCP_COMMAND: "node",
1168
1329
  GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
@@ -1194,50 +1355,65 @@ describe("stream-adapter — session persistence (#2859)", () => {
1194
1355
  process.chdir(originalCwd);
1195
1356
  rmSync(projectDir, { recursive: true, force: true });
1196
1357
  restore();
1197
- }
1358
+ }
1359
+ });
1360
+
1361
+ test("buildSdkOptions uses project-declared custom workflow MCP namespace", () => {
1362
+ const restore = setWorkflowMcpEnv({
1363
+ GSD_WORKFLOW_MCP_COMMAND: "node",
1364
+ GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
1365
+ GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["packages/mcp-server/dist/cli.js"]),
1366
+ GSD_WORKFLOW_MCP_ENV: JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" }),
1367
+ GSD_WORKFLOW_MCP_CWD: "/tmp/project",
1198
1368
  });
1369
+ const originalCwd = process.cwd();
1370
+ const projectDir = mkdtempSync(join(tmpdir(), "claude-mcp-custom-project-"));
1371
+ try {
1372
+ writeFileSync(
1373
+ join(projectDir, ".mcp.json"),
1374
+ JSON.stringify({
1375
+ mcpServers: {
1376
+ "custom-workflow": {
1377
+ command: "node",
1378
+ args: ["custom-cli.js"],
1379
+ env: { GSD_WORKFLOW_PROJECT_ROOT: projectDir },
1380
+ },
1381
+ },
1382
+ }),
1383
+ );
1384
+ process.chdir(projectDir);
1385
+ const options = buildSdkOptions("claude-sonnet-4-20250514", "test");
1386
+ const mcpServers = options.mcpServers as Record<string, any>;
1387
+ assert.deepEqual(Object.keys(mcpServers), ["gsd-browser"], "should inject only browser when project declares a workflow server");
1388
+ const allowedTools = options.allowedTools as string[];
1389
+ assert.ok(allowedTools.includes("mcp__custom-workflow__*"), "allowedTools must use the project workflow namespace");
1390
+ assert.ok(allowedTools.includes("mcp__gsd-browser__*"), "allowedTools must include default browser namespace");
1391
+ assert.ok(!allowedTools.includes("mcp__gsd-workflow__*"), "allowedTools must not advertise the absent default namespace");
1392
+ const disallowedTools = options.disallowedTools as string[];
1393
+ assert.ok(disallowedTools.includes("AskUserQuestion"), "AskUserQuestion should be suppressed when workflow is available");
1199
1394
 
1200
- test("buildSdkOptions uses project-declared custom workflow MCP namespace", () => {
1201
- const restore = setWorkflowMcpEnv({
1202
- GSD_WORKFLOW_MCP_COMMAND: "node",
1203
- GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
1204
- GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["packages/mcp-server/dist/cli.js"]),
1205
- GSD_WORKFLOW_MCP_ENV: JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" }),
1206
- GSD_WORKFLOW_MCP_CWD: "/tmp/project",
1395
+ const phaseOptions = buildSdkOptions("claude-sonnet-4-20250514", "test", undefined, { gsdPhase: "plan-milestone" });
1396
+ assert.equal(phaseOptions.strictMcpConfig, true);
1397
+ assert.deepEqual(phaseOptions.settingSources, []);
1398
+ assert.deepEqual(phaseOptions.mcpServers, {
1399
+ "custom-workflow": {
1400
+ command: "node",
1401
+ args: ["custom-cli.js"],
1402
+ env: { GSD_WORKFLOW_PROJECT_ROOT: projectDir },
1403
+ },
1207
1404
  });
1208
- const originalCwd = process.cwd();
1209
- const projectDir = mkdtempSync(join(tmpdir(), "claude-mcp-custom-project-"));
1210
- try {
1211
- writeFileSync(
1212
- join(projectDir, ".mcp.json"),
1213
- JSON.stringify({
1214
- mcpServers: {
1215
- "custom-workflow": {
1216
- command: "node",
1217
- args: ["custom-cli.js"],
1218
- env: { GSD_WORKFLOW_PROJECT_ROOT: projectDir },
1219
- },
1220
- },
1221
- }),
1222
- );
1223
- process.chdir(projectDir);
1224
- const options = buildSdkOptions("claude-sonnet-4-20250514", "test");
1225
- const mcpServers = options.mcpServers as Record<string, any>;
1226
- assert.deepEqual(Object.keys(mcpServers), ["gsd-browser"], "should inject only browser when project declares a workflow server");
1227
- const allowedTools = options.allowedTools as string[];
1228
- assert.ok(allowedTools.includes("mcp__custom-workflow__*"), "allowedTools must use the project workflow namespace");
1229
- assert.ok(allowedTools.includes("mcp__gsd-browser__*"), "allowedTools must include default browser namespace");
1230
- assert.ok(!allowedTools.includes("mcp__gsd-workflow__*"), "allowedTools must not advertise the absent default namespace");
1231
- const disallowedTools = options.disallowedTools as string[];
1232
- assert.ok(disallowedTools.includes("AskUserQuestion"), "AskUserQuestion should be suppressed when workflow is available");
1233
- } finally {
1234
- process.chdir(originalCwd);
1235
- rmSync(projectDir, { recursive: true, force: true });
1236
- restore();
1237
- }
1238
- });
1405
+ const phaseAllowedTools = phaseOptions.allowedTools as string[];
1406
+ assert.ok(phaseAllowedTools.includes("mcp__custom-workflow__gsd_plan_milestone"));
1407
+ assert.ok(phaseAllowedTools.includes("mcp__custom-workflow__gsd_milestone_status"));
1408
+ assert.ok(!phaseAllowedTools.includes("mcp__gsd-workflow__*"));
1409
+ } finally {
1410
+ process.chdir(originalCwd);
1411
+ rmSync(projectDir, { recursive: true, force: true });
1412
+ restore();
1413
+ }
1414
+ });
1239
1415
 
1240
- test("buildSdkOptions preserves runtime callbacks such as onElicitation", () => {
1416
+ test("buildSdkOptions preserves runtime callbacks such as onElicitation", () => {
1241
1417
  const restore = setWorkflowMcpEnv({});
1242
1418
  const onElicitation = async () => ({ action: "decline" as const });
1243
1419
  try {
@@ -277,7 +277,6 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
277
277
  this.status.activeUnit = { unitType: decision.unitType, unitId: decision.unitId };
278
278
  this.status.phase = "running";
279
279
  this.lastAdvanceKey = nextKey;
280
- this.lastFinalizedUnitKey = null;
281
280
  this.bumpTransition();
282
281
 
283
282
  await this.deps.runtime.journalTransition({
@@ -88,7 +88,7 @@ import { resolveManifest } from "../unit-context-manifest.js";
88
88
  import { createWorktreeSafetyModule, type WorktreeSafetyResult } from "../worktree-safety.js";
89
89
  import { isSuspiciousGhostCompletion } from "../auto-unit-closeout.js";
90
90
  import { decideVerificationRetry, verificationRetryKey } from "./verification-retry-policy.js";
91
- import { buildPhaseHandoffOutcome, setAutoOutcomeWidget } from "../auto-dashboard.js";
91
+ import { buildPhaseHandoffOutcome, setAutoActiveStatus, setAutoOutcomeWidget } from "../auto-dashboard.js";
92
92
  import { getConsecutiveDispatchBlocker } from "../dispatch-guard.js";
93
93
  import {
94
94
  captureRootDirtySnapshot,
@@ -100,7 +100,7 @@ import { classifyError, isTransient } from "../error-classifier.js";
100
100
  export const STUCK_WINDOW_SIZE = 6;
101
101
  const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
102
102
  const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE =
103
- /^(?:api error(?::|$|\s*\()|provider error(?::|$|\s*\()|request failed\b|(?:http\s*)?(?:429|500|502|503)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|socket hang up\b|fetch failed\b|(?:network|connection|server) error(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|dns\b.*(?:fail|error|timeout)|unexpected eof\b|stream idle timeout\b|partial response received\b|stream_exhausted\b|terminated(?::|$)|(?:connection|stream|request)\b.{0,40}\bterminated\b|other side closed\b|rate.?limit(?:ed| exceeded| reached| error)|too many requests\b|you(?:'ve| have) hit your limit\b|usage limit\b|out of extra usage\b|service.?unavailable\b|internal(?: server)? error(?::|$)|internal(?:[_-]server)?[_-]error\b|server[_-]error\b|(?:provider|server|api|model|codex|claude|openai|anthropic|gemini)\b.{0,80}\boverloaded\b|overloaded\b.{0,80}\b(?:provider|server|api|model)\b|context (?:window|length) exceed|context window exceed)/i;
103
+ /^(?:api error(?::|$|\s*\()|provider error(?::|$|\s*\()|request failed\b|(?:http\s*)?(?:429|500|502|503)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|socket hang up\b|fetch failed\b|(?:network|connection|server) error(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|dns\b.*(?:fail|error|timeout)|unexpected eof\b|stream idle timeout\b|partial response received\b|stream_exhausted\b|terminated(?::|$)|(?:connection|stream|request)\b.{0,40}\bterminated\b|other side closed\b|rate.?limit(?:ed| exceeded| reached| error)|too many requests\b|you(?:'ve| have) (?:hit|reached) your (?:\w+ )?limit\b|.*\b(?:usage|session|weekly|daily|monthly|quota) limit\b|limit\b.{0,40}\bresets?\b|out of extra usage\b|service.?unavailable\b|internal(?: server)? error(?::|$)|internal(?:[_-]server)?[_-]error\b|server[_-]error\b|(?:provider|server|api|model|codex|claude|openai|anthropic|gemini)\b.{0,80}\boverloaded\b|overloaded\b.{0,80}\b(?:provider|server|api|model)\b|context (?:window|length) exceed|context window exceed)/i;
104
104
  const ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE =
105
105
  /(?:\b(?:http|status(?: code)?|code|error:)\s*(?:429|500|502|503)\b|\b(?:api|provider) error\s*[:(]?\s*(?:429|500|502|503)\b|\b(?:typeerror|error):\s*(?:fetch failed\b|socket hang up\b|terminated(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|(?:network|connection|server) error(?::|$)|stream idle timeout\b|partial response received\b|unexpected eof\b)|\b(?:server_error|api_error|stream_exhausted(?:_without_result)?)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|context (?:window|length) exceed|context window exceed)/i;
106
106
 
@@ -114,6 +114,8 @@ function classifyZeroToolProviderMessage(message: string): ReturnType<typeof cla
114
114
  return classifyError(firstLine);
115
115
  }
116
116
 
117
+ export const _classifyZeroToolProviderMessageForTest = classifyZeroToolProviderMessage;
118
+
117
119
  export function resolveDispatchRecoveryAttempts(
118
120
  unitRecoveryCount: Map<string, number>,
119
121
  unitType: string,
@@ -2092,7 +2094,7 @@ export async function runUnitPhase(
2092
2094
  const nextDispatchCount = (s.unitDispatchCount.get(dispatchKey) ?? 0) + 1;
2093
2095
 
2094
2096
  // Status bar (widget + preconditions deferred until after model selection — see #2899)
2095
- ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
2097
+ setAutoActiveStatus(ctx, s.stepMode ? "next" : "auto");
2096
2098
  if (mid)
2097
2099
  deps.updateSliceProgressCache(s.basePath, mid, state.activeSlice?.id);
2098
2100
 
@@ -13,10 +13,11 @@ import type {
13
13
  ExtensionCommandContext,
14
14
  ReadonlyFooterDataProvider,
15
15
  Theme,
16
+ ThemeColor,
16
17
  } from "@gsd/pi-coding-agent";
17
18
  import type { GSDState } from "./types.js";
18
19
  import { getActiveHook } from "./post-unit-hooks.js";
19
- import { getLedger } from "./metrics.js";
20
+ import { getLedger, getProjectTotals } from "./metrics.js";
20
21
  import { getErrorMessage } from "./error-utils.js";
21
22
  import { nativeIsRepo } from "./native-git-bridge.js";
22
23
  import {
@@ -304,6 +305,40 @@ export function shouldRenderRoadmapProgress(
304
305
  return !!progress && progress.total > 0;
305
306
  }
306
307
 
308
+ function widgetGridLabel(theme: Theme, text: string, color: ThemeColor = "borderAccent"): string {
309
+ return theme.fg(color, theme.bold(text.toUpperCase()));
310
+ }
311
+
312
+ function widgetGridColumn(content: string, width: number): string {
313
+ return padRightVisible(truncateToWidth(content, width, "…"), width);
314
+ }
315
+
316
+ function widgetGridColumns(theme: Theme, width: number, parts: string[]): string {
317
+ if (parts.length === 0) return "";
318
+ const gap = theme.fg("dim", " │ ");
319
+ const gapWidth = visibleWidth(gap) * (parts.length - 1);
320
+ const available = Math.max(parts.length * 8, width - gapWidth);
321
+ const base = Math.floor(available / parts.length);
322
+ let remaining = available - base * parts.length;
323
+ const columns = parts.map((part) => {
324
+ const columnWidth = base + (remaining > 0 ? 1 : 0);
325
+ remaining--;
326
+ return widgetGridColumn(part, columnWidth);
327
+ });
328
+ return truncateToWidth(columns.join(gap), width, "…");
329
+ }
330
+
331
+ function formatSmallWidgetSpend(): string {
332
+ const ledger = getLedger();
333
+ if (!ledger || ledger.units.length === 0) return "--";
334
+
335
+ const totals = getProjectTotals(ledger.units);
336
+ const parts: string[] = [];
337
+ if (totals.tokens.total > 0) parts.push(formatWidgetTokens(totals.tokens.total));
338
+ if (totals.cost > 0) parts.push(`$${totals.cost.toFixed(2)}`);
339
+ return parts.length > 0 ? parts.join(" · ") : "--";
340
+ }
341
+
307
342
  // ─── ETA Estimation ──────────────────────────────────────────────────────────
308
343
 
309
344
  /**
@@ -516,8 +551,9 @@ export const hideFooter = (_tui: unknown, theme: Theme, footerData: ReadonlyFoot
516
551
 
517
552
  /** Widget display modes: full → small → min → off → full */
518
553
  export type WidgetMode = "full" | "small" | "min" | "off";
554
+ export const DEFAULT_WIDGET_MODE: WidgetMode = "small";
519
555
  const WIDGET_MODES: WidgetMode[] = ["full", "small", "min", "off"];
520
- let widgetMode: WidgetMode = "full";
556
+ let widgetMode: WidgetMode = DEFAULT_WIDGET_MODE;
521
557
  let widgetModeInitialized = false;
522
558
  let widgetModePreferencePath: string | null = null;
523
559
 
@@ -628,7 +664,7 @@ export function getWidgetMode(projectPath?: string, globalPath?: string): Widget
628
664
 
629
665
  /** Test-only reset for widget mode caching. */
630
666
  export function _resetWidgetModeForTests(): void {
631
- widgetMode = "full";
667
+ widgetMode = DEFAULT_WIDGET_MODE;
632
668
  widgetModeInitialized = false;
633
669
  widgetModePreferencePath = null;
634
670
  }
@@ -648,6 +684,16 @@ export interface WidgetStateAccessors {
648
684
  getCurrentDispatchedModelId(): string | null;
649
685
  }
650
686
 
687
+ function clearAutoOutcomeWidget(ctx: ExtensionContext): void {
688
+ if (!ctx.hasUI) return;
689
+ ctx.ui.setWidget("gsd-outcome", undefined);
690
+ }
691
+
692
+ export function setAutoActiveStatus(ctx: ExtensionContext, status: "auto" | "next"): void {
693
+ ctx.ui.setStatus("gsd-auto", status);
694
+ clearAutoOutcomeWidget(ctx);
695
+ }
696
+
651
697
  export function updateProgressWidget(
652
698
  ctx: ExtensionContext,
653
699
  unitType: string,
@@ -673,7 +719,7 @@ export function updateProgressWidget(
673
719
  ctx.ui.setStatus("gsd-step", undefined);
674
720
  }
675
721
  if (!accessors.isSessionSwitching()) {
676
- ctx.ui.setWidget("gsd-outcome", undefined);
722
+ clearAutoOutcomeWidget(ctx);
677
723
  }
678
724
 
679
725
  const verb = unitVerb(unitType);
@@ -732,6 +778,7 @@ export function updateProgressWidget(
732
778
  logWarning("dashboard", `DB status update failed: ${err instanceof Error ? err.message : String(err)}`);
733
779
  }
734
780
  }, 15_000);
781
+ progressRefreshTimer.unref?.();
735
782
 
736
783
  return {
737
784
  render(width: number): string[] {
@@ -824,29 +871,62 @@ export function updateProgressWidget(
824
871
  return lines;
825
872
  }
826
873
 
827
- // ── Mode: small — header + active work progress ───────────────
874
+ // ── Mode: small — dense horizontal grid ───────────────────────
828
875
  if (widgetMode === "small") {
829
- lines.push("");
830
-
831
- // Action line
832
- const target = task ? `${task.id}: ${task.title}` : unitId;
833
- const actionLeft = `${pad}${theme.fg("accent", "▸")} ${theme.fg("accent", verb)} ${theme.fg("text", target)}`;
834
- lines.push(rightAlign(actionLeft, theme.fg("dim", phaseLabel), width));
876
+ lines.length = 0;
877
+ lines.push(...ui.bar());
835
878
 
836
- // Progress bar
837
879
  const roadmapSlices = mid ? getRoadmapSlicesSync() : null;
880
+ const unitLabel = unitId || [mid?.id, slice?.id, task?.id].filter(Boolean).join("/");
881
+ const statusParts = [
882
+ spinner,
883
+ theme.fg("success", modeTag),
884
+ theme.fg(stateColor, activeState),
885
+ ];
886
+ if (runtimeSignal?.summary) {
887
+ statusParts.push(theme.fg(healthColor, healthSummary));
888
+ } else if (healthLevel !== "green") {
889
+ statusParts.push(`${theme.fg(healthColor, healthIcon)} ${theme.fg(healthColor, healthSummary)}`);
890
+ }
891
+
892
+ const timeValue = [elapsed, etaShort].filter(Boolean).join(" · ") || "--";
893
+ const rowOne = widgetGridColumns(theme, width, [
894
+ `${widgetGridLabel(theme, "status", "border")} ${statusParts.join(" ")}`,
895
+ `${widgetGridLabel(theme, "unit")} ${theme.fg("text", unitLabel || "--")}`,
896
+ `${widgetGridLabel(theme, "spend", "border")} ${theme.fg("dim", formatSmallWidgetSpend())}`,
897
+ `${widgetGridLabel(theme, "time")} ${theme.fg("dim", timeValue)}`,
898
+ ]);
899
+
900
+ const target = task
901
+ ? `${task.id}: ${task.title}`
902
+ : slice
903
+ ? `${slice.id}: ${slice.title}`
904
+ : unitId;
905
+
906
+ let taskValue = task?.id ?? "--";
907
+ let sliceValue = slice?.id ?? "--";
838
908
  if (shouldRenderRoadmapProgress(roadmapSlices)) {
839
909
  const { done, total, activeSliceTasks } = roadmapSlices;
840
- const barWidth = Math.max(6, Math.min(18, Math.floor(width * 0.25)));
910
+ const barWidth = Math.max(4, Math.min(14, Math.floor(width * 0.12)));
841
911
  const bar = renderProgressBar(theme, done, total, barWidth);
842
- let meta = `${theme.fg("text", `${done}`)}${theme.fg("dim", `/${total} slices`)}`;
912
+ sliceValue = `${bar} ${theme.fg("text", `${done}/${total}`)}`;
843
913
  if (activeSliceTasks && activeSliceTasks.total > 0) {
844
- const tn = Math.min(activeSliceTasks.done + 1, activeSliceTasks.total);
845
- meta += `${theme.fg("dim", " · task ")}${theme.fg("accent", `${tn}`)}${theme.fg("dim", `/${activeSliceTasks.total}`)}`;
914
+ const taskNum = isHook
915
+ ? Math.max(activeSliceTasks.done, 1)
916
+ : Math.min(activeSliceTasks.done + 1, activeSliceTasks.total);
917
+ taskValue = `${theme.fg("accent", `${taskNum}`)}${theme.fg("dim", `/${activeSliceTasks.total}`)}`;
846
918
  }
847
- lines.push(`${pad}${bar} ${meta}`);
848
919
  }
849
920
 
921
+ const rowTwo = widgetGridColumns(theme, width, [
922
+ `${widgetGridLabel(theme, "phase", "border")} ${theme.fg("dim", unitType)}`,
923
+ `${widgetGridLabel(theme, "work")} ${theme.fg("text", target || "--")}`,
924
+ `${widgetGridLabel(theme, "task", "border")} ${taskValue}`,
925
+ `${widgetGridLabel(theme, "slice")} ${sliceValue}`,
926
+ ]);
927
+
928
+ lines.push(rowOne);
929
+ lines.push(rowTwo);
850
930
  lines.push(...ui.bar());
851
931
  cachedLines = lines;
852
932
  cachedWidth = width;
@@ -1003,7 +1083,7 @@ export function setCompletionProgressWidget(
1003
1083
  ): void {
1004
1084
  if (!ctx.hasUI) return;
1005
1085
  const widgetKey = "gsd-progress";
1006
- ctx.ui.setWidget("gsd-outcome", undefined);
1086
+ clearAutoOutcomeWidget(ctx);
1007
1087
 
1008
1088
  if (typeof ctx.ui?.setHeader === "function") {
1009
1089
  ctx.ui.setHeader(() => ({