@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.9bb7453

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 (395) 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 +44 -0
  14. package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
  15. package/dist/resources/extensions/gsd/auto-prompts.js +68 -22
  16. package/dist/resources/extensions/gsd/auto-recovery.js +4 -4
  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 +2 -1
  21. package/dist/resources/extensions/gsd/auto.js +31 -6
  22. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +83 -4
  23. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
  24. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +39 -14
  25. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -10
  26. package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
  27. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
  29. package/dist/resources/extensions/gsd/commands/handlers/ops.js +9 -5
  30. package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
  31. package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
  32. package/dist/resources/extensions/gsd/commands-mcp-status.js +109 -60
  33. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
  34. package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
  35. package/dist/resources/extensions/gsd/config-overlay.js +2 -1
  36. package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
  37. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  38. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
  39. package/dist/resources/extensions/gsd/error-classifier.js +2 -1
  40. package/dist/resources/extensions/gsd/escalation.js +4 -4
  41. package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
  42. package/dist/resources/extensions/gsd/forensics.js +74 -2
  43. package/dist/resources/extensions/gsd/gsd-db.js +42 -6
  44. package/dist/resources/extensions/gsd/guided-flow.js +30 -69
  45. package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
  46. package/dist/resources/extensions/gsd/mcp-project-config.js +76 -84
  47. package/dist/resources/extensions/gsd/memory-store.js +4 -1
  48. package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
  49. package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
  50. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  51. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  52. package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
  53. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  54. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  55. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  56. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  57. package/dist/resources/extensions/gsd/prompts/run-uat.md +48 -24
  58. package/dist/resources/extensions/gsd/prompts/system.md +3 -1
  59. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  60. package/dist/resources/extensions/gsd/rule-registry.js +428 -52
  61. package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
  62. package/dist/resources/extensions/gsd/skill-activation.js +20 -3
  63. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +4 -2
  64. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
  65. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
  66. package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
  67. package/dist/resources/extensions/gsd/state.js +17 -14
  68. package/dist/resources/extensions/gsd/templates/plan.md +3 -1
  69. package/dist/resources/extensions/gsd/tool-presentation-plan.js +120 -0
  70. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
  71. package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
  72. package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
  73. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
  74. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  75. package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
  76. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +403 -3
  77. package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
  78. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  79. package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
  80. package/dist/resources/extensions/gsd/verification-gate.js +72 -1
  81. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -1
  82. package/dist/resources/extensions/gsd/workflow-mcp.js +5 -1
  83. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
  84. package/dist/resources/extensions/mcp-client/manager.js +31 -1
  85. package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
  86. package/dist/rtk.d.ts +7 -1
  87. package/dist/rtk.js +27 -11
  88. package/dist/update-check.d.ts +15 -1
  89. package/dist/update-check.js +87 -12
  90. package/dist/update-cmd.d.ts +1 -0
  91. package/dist/update-cmd.js +53 -2
  92. package/dist/web/standalone/.next/BUILD_ID +1 -1
  93. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  94. package/dist/web/standalone/.next/build-manifest.json +2 -2
  95. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  96. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/index.html +1 -1
  114. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  121. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  122. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  124. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  125. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  126. package/package.json +5 -3
  127. package/packages/cloud-mcp-gateway/package.json +2 -2
  128. package/packages/contracts/dist/workflow.d.ts +14 -0
  129. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  130. package/packages/contracts/dist/workflow.js +16 -0
  131. package/packages/contracts/dist/workflow.js.map +1 -1
  132. package/packages/contracts/package.json +1 -1
  133. package/packages/daemon/package.json +4 -4
  134. package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
  135. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  136. package/packages/gsd-agent-core/dist/agent-session.js +32 -0
  137. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  138. package/packages/gsd-agent-core/dist/index.d.ts +1 -0
  139. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  140. package/packages/gsd-agent-core/dist/index.js +1 -0
  141. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  142. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
  143. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
  144. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
  145. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
  146. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
  147. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  148. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  149. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  150. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
  151. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  152. package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
  153. package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
  154. package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
  155. package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
  156. package/packages/gsd-agent-core/package.json +6 -6
  157. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
  158. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
  159. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
  160. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
  161. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  162. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  163. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  164. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  165. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +92 -31
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
  171. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  172. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
  173. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
  176. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
  177. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  178. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
  179. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
  181. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  188. package/packages/gsd-agent-modes/package.json +7 -7
  189. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  190. package/packages/mcp-server/dist/remote-questions.js +23 -9
  191. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  192. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  193. package/packages/mcp-server/dist/workflow-tools.js +84 -2
  194. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  195. package/packages/mcp-server/package.json +3 -3
  196. package/packages/native/package.json +1 -1
  197. package/packages/pi-agent-core/dist/agent-loop.js +38 -0
  198. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  199. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  200. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  201. package/packages/pi-agent-core/dist/agent.js +2 -0
  202. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  203. package/packages/pi-agent-core/dist/types.d.ts +3 -0
  204. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  205. package/packages/pi-agent-core/dist/types.js.map +1 -1
  206. package/packages/pi-agent-core/package.json +1 -1
  207. package/packages/pi-ai/dist/api-registry.d.ts +2 -0
  208. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  209. package/packages/pi-ai/dist/api-registry.js +23 -0
  210. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  211. package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
  212. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  213. package/packages/pi-ai/dist/image-models.generated.js +15 -0
  214. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  215. package/packages/pi-ai/dist/models.generated.d.ts +406 -17
  216. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  217. package/packages/pi-ai/dist/models.generated.js +484 -116
  218. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  219. package/packages/pi-ai/dist/stream.js +6 -6
  220. package/packages/pi-ai/dist/stream.js.map +1 -1
  221. package/packages/pi-ai/package.json +1 -1
  222. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  223. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  224. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  225. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  226. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  227. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  228. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  229. package/packages/pi-coding-agent/package.json +7 -7
  230. package/packages/pi-tui/dist/terminal.d.ts +1 -0
  231. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  232. package/packages/pi-tui/dist/terminal.js +8 -4
  233. package/packages/pi-tui/dist/terminal.js.map +1 -1
  234. package/packages/pi-tui/package.json +1 -1
  235. package/packages/rpc-client/package.json +2 -2
  236. package/pkg/package.json +1 -1
  237. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
  238. package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
  239. package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
  240. package/src/resources/extensions/browser-tools/index.ts +60 -9
  241. package/src/resources/extensions/browser-tools/package.json +5 -1
  242. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
  243. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
  244. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
  245. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
  246. package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
  247. package/src/resources/extensions/gsd/auto/phases.ts +5 -3
  248. package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
  249. package/src/resources/extensions/gsd/auto-dispatch.ts +53 -0
  250. package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
  251. package/src/resources/extensions/gsd/auto-prompts.ts +102 -15
  252. package/src/resources/extensions/gsd/auto-recovery.ts +4 -4
  253. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
  254. package/src/resources/extensions/gsd/auto-start.ts +112 -17
  255. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  256. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +2 -1
  257. package/src/resources/extensions/gsd/auto.ts +47 -5
  258. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +90 -4
  259. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
  260. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +60 -19
  261. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +21 -10
  262. package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
  263. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  264. package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
  265. package/src/resources/extensions/gsd/commands/handlers/ops.ts +9 -5
  266. package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
  267. package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
  268. package/src/resources/extensions/gsd/commands-mcp-status.ts +136 -58
  269. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
  270. package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
  271. package/src/resources/extensions/gsd/config-overlay.ts +3 -1
  272. package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
  273. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  274. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
  275. package/src/resources/extensions/gsd/error-classifier.ts +2 -1
  276. package/src/resources/extensions/gsd/escalation.ts +4 -4
  277. package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
  278. package/src/resources/extensions/gsd/forensics.ts +99 -5
  279. package/src/resources/extensions/gsd/gsd-db.ts +46 -8
  280. package/src/resources/extensions/gsd/guided-flow.ts +91 -83
  281. package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
  282. package/src/resources/extensions/gsd/mcp-project-config.ts +105 -88
  283. package/src/resources/extensions/gsd/memory-store.ts +4 -1
  284. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  285. package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
  286. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  287. package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
  288. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  289. package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
  290. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  291. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  292. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  293. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  294. package/src/resources/extensions/gsd/prompts/run-uat.md +48 -24
  295. package/src/resources/extensions/gsd/prompts/system.md +3 -1
  296. package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  297. package/src/resources/extensions/gsd/rule-registry.ts +558 -58
  298. package/src/resources/extensions/gsd/rule-types.ts +2 -0
  299. package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
  300. package/src/resources/extensions/gsd/skill-activation.ts +20 -2
  301. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +4 -2
  302. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
  303. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
  304. package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
  305. package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
  306. package/src/resources/extensions/gsd/state.ts +18 -14
  307. package/src/resources/extensions/gsd/templates/plan.md +3 -1
  308. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
  309. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +123 -0
  310. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
  311. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
  312. package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
  313. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
  314. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
  315. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
  316. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  317. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
  318. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
  319. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
  320. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
  321. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
  322. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -0
  323. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
  324. package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
  325. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
  326. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
  327. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
  328. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
  329. package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
  330. package/src/resources/extensions/gsd/tests/gsd-rebuild.test.ts +199 -0
  331. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -0
  332. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
  333. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
  334. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
  335. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
  336. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +66 -10
  337. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +13 -6
  338. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
  339. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +100 -0
  340. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +179 -0
  341. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
  342. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
  343. package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
  344. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
  345. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
  346. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +39 -1
  347. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
  348. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
  349. package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
  350. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +53 -1
  351. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
  352. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
  353. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
  354. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
  355. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +35 -0
  356. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
  357. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
  358. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
  359. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
  360. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
  361. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  362. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
  363. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  364. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
  365. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
  366. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
  367. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
  368. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
  369. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
  370. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
  371. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
  372. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +17 -2
  373. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +213 -0
  374. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +25 -0
  375. package/src/resources/extensions/gsd/tool-presentation-plan.ts +167 -0
  376. package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
  377. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
  378. package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
  379. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
  380. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  381. package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
  382. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +489 -3
  383. package/src/resources/extensions/gsd/types.ts +69 -5
  384. package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
  385. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  386. package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
  387. package/src/resources/extensions/gsd/verification-gate.ts +87 -1
  388. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -1
  389. package/src/resources/extensions/gsd/workflow-mcp.ts +5 -1
  390. package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
  391. package/src/resources/extensions/mcp-client/manager.ts +33 -1
  392. package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
  393. package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
  394. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → jBtwT9v1u2lUA3UEOy_ZH}/_buildManifest.js +0 -0
  395. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → jBtwT9v1u2lUA3UEOy_ZH}/_ssgManifest.js +0 -0
@@ -4,7 +4,7 @@
4
4
  "version": "1.0.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
- "test": "node --test tests/*.test.mjs"
7
+ "test": "node --import ../gsd/tests/resolve-ts.mjs --experimental-strip-types --test tests/*.test.mjs"
8
8
  },
9
9
  "pi": {
10
10
  "extensions": [
@@ -12,10 +12,14 @@
12
12
  ]
13
13
  },
14
14
  "peerDependencies": {
15
+ "@opengsd/gsd-browser": ">=0.1.27",
15
16
  "playwright": ">=1.40.0",
16
17
  "sharp": ">=0.33.0"
17
18
  },
18
19
  "peerDependenciesMeta": {
20
+ "@opengsd/gsd-browser": {
21
+ "optional": true
22
+ },
19
23
  "playwright": {
20
24
  "optional": true
21
25
  },
@@ -15,10 +15,11 @@ import { homedir } from "node:os";
15
15
  import { createRequire } from "node:module";
16
16
  import { dirname, join } from "node:path";
17
17
  import { PartialMessageBuilder, ZERO_USAGE, mapUsage } from "./partial-builder.js";
18
- import { buildWorkflowMcpServers, resolveWorkflowMcpProjectRoot } from "../gsd/workflow-mcp.js";
19
- import { buildProjectGsdMcpServers } from "../gsd/mcp-project-config.js";
18
+ import { buildWorkflowMcpServers, getRequiredWorkflowToolsForAutoUnit, resolveWorkflowMcpProjectRoot, } from "../gsd/workflow-mcp.js";
19
+ import { buildProjectGsdMcpServers, ensureProjectWorkflowMcpConfig } from "../gsd/mcp-project-config.js";
20
20
  import { loadProjectGSDPreferences } from "../gsd/preferences.js";
21
- import { discoverBrowserMcpServerName, discoverMcpServerNames, discoverWorkflowMcpServerName, computeMcpDisallowedTools } from "../gsd/mcp-filter.js";
21
+ import { discoverBrowserMcpServerName, discoverMcpServers, discoverMcpServerNames, discoverWorkflowMcpServerName, computeMcpDisallowedTools, } from "../gsd/mcp-filter.js";
22
+ import { RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES, RUN_UAT_FORBIDDEN_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES, resolveToolPresentationPlan } from "../gsd/tool-presentation-plan.js";
22
23
  import { showInterviewRound } from "../shared/tui.js";
23
24
  export function serverToolUseToToolCallLike(block) {
24
25
  const argumentsValue = block.input && typeof block.input === "object" && !Array.isArray(block.input)
@@ -164,6 +165,32 @@ function extractMessageText(msg) {
164
165
  }
165
166
  return "";
166
167
  }
168
+ const GSD_PHASE_PATTERNS = [
169
+ ["run-uat", /\b(?:UNIT:\s*Run UAT|run-uat)\b/i],
170
+ ["complete-milestone", /\b(?:UNIT:\s*Complete Milestone|complete-milestone)\b/i],
171
+ ["validate-milestone", /\b(?:UNIT:\s*Validate Milestone|validate-milestone)\b/i],
172
+ ["reassess-roadmap", /\b(?:UNIT:\s*Reassess Roadmap|reassess-roadmap)\b/i],
173
+ ["complete-slice", /\b(?:UNIT:\s*Complete Slice|complete-slice)\b/i],
174
+ ["replan-slice", /\b(?:UNIT:\s*Replan Slice|replan-slice)\b/i],
175
+ ["plan-slice", /\b(?:UNIT:\s*Plan Slice|plan-slice|gsd_plan_slice)\b/i],
176
+ ["plan-milestone", /\b(?:UNIT:\s*Plan Milestone|plan-milestone|gsd_plan_milestone)\b/i],
177
+ ["execute-task", /\b(?:UNIT:\s*Execute Task|execute-task|execute-task-simple|reactive-execute)\b/i],
178
+ ["gate-evaluate", /\b(?:UNIT:\s*Gate Evaluate|gate-evaluate|gsd_save_gate_result)\b/i],
179
+ ["research-milestone", /\b(?:UNIT:\s*Research Milestone|research-milestone)\b/i],
180
+ ["research-slice", /\b(?:UNIT:\s*Research Slice|research-slice)\b/i],
181
+ ["discuss-milestone", /\b(?:Discuss milestone|discuss-milestone)\b/i],
182
+ ];
183
+ export function inferGsdPhaseFromContext(context) {
184
+ const text = [
185
+ context.systemPrompt ?? "",
186
+ ...context.messages.map((message) => extractMessageText(message)),
187
+ ].join("\n");
188
+ for (const [phase, pattern] of GSD_PHASE_PATTERNS) {
189
+ if (pattern.test(text))
190
+ return phase;
191
+ }
192
+ return undefined;
193
+ }
167
194
  /**
168
195
  * Build a full conversational prompt from GSD's context messages.
169
196
  *
@@ -1175,22 +1202,106 @@ function mapThinkingLevelToAnthropicEffort(level, modelId) {
1175
1202
  return "high";
1176
1203
  }
1177
1204
  }
1178
- function workflowMcpServerNameFromAllowedTools(allowedTools) {
1205
+ function parseAllowedMcpToolName(toolName) {
1206
+ const match = /^mcp__(.+)__(\*|[^*]+)$/.exec(toolName);
1207
+ return match?.[1] && match[2] ? { server: match[1], tool: match[2] } : undefined;
1208
+ }
1209
+ function browserMcpServerNameFromAllowedTools(allowedTools) {
1179
1210
  if (!Array.isArray(allowedTools))
1180
1211
  return undefined;
1181
1212
  for (const toolName of allowedTools) {
1182
1213
  if (typeof toolName !== "string")
1183
1214
  continue;
1184
- const match = /^mcp__(.+)__\*$/.exec(toolName);
1185
- if (match?.[1] && match[1] !== "gsd-browser")
1186
- return match[1];
1215
+ const parsed = parseAllowedMcpToolName(toolName);
1216
+ if (!parsed)
1217
+ continue;
1218
+ if (parsed.server === "gsd-browser" || parsed.tool.startsWith("browser_")) {
1219
+ return parsed.server;
1220
+ }
1187
1221
  }
1188
1222
  return undefined;
1189
1223
  }
1190
- function browserMcpServerNameFromAllowedTools(allowedTools) {
1224
+ function workflowMcpServerNameFromAllowedTools(allowedTools) {
1191
1225
  if (!Array.isArray(allowedTools))
1192
1226
  return undefined;
1193
- return allowedTools.includes("mcp__gsd-browser__*") ? "gsd-browser" : undefined;
1227
+ const browserServerName = browserMcpServerNameFromAllowedTools(allowedTools);
1228
+ for (const toolName of allowedTools) {
1229
+ if (typeof toolName !== "string")
1230
+ continue;
1231
+ const parsed = parseAllowedMcpToolName(toolName);
1232
+ if (!parsed || parsed.server === browserServerName || parsed.tool.startsWith("browser_"))
1233
+ continue;
1234
+ return parsed.server;
1235
+ }
1236
+ return undefined;
1237
+ }
1238
+ function isRecord(value) {
1239
+ return !!value && typeof value === "object" && !Array.isArray(value);
1240
+ }
1241
+ function isStringRecord(value) {
1242
+ return isRecord(value) && Object.values(value).every((entry) => typeof entry === "string");
1243
+ }
1244
+ function cloneSdkMcpServerConfig(config) {
1245
+ if (!isRecord(config))
1246
+ return undefined;
1247
+ const cloned = {};
1248
+ for (const key of ["type", "command", "cwd", "url"]) {
1249
+ if (typeof config[key] === "string")
1250
+ cloned[key] = config[key];
1251
+ }
1252
+ if (Array.isArray(config.args)) {
1253
+ cloned.args = config.args.filter((arg) => typeof arg === "string");
1254
+ }
1255
+ if (isStringRecord(config.env))
1256
+ cloned.env = { ...config.env };
1257
+ if (isStringRecord(config.headers))
1258
+ cloned.headers = { ...config.headers };
1259
+ if (isRecord(config.oauth))
1260
+ cloned.oauth = { ...config.oauth };
1261
+ return Object.keys(cloned).length > 0 ? cloned : undefined;
1262
+ }
1263
+ function resolveProjectMcpServerConfig(projectRoot, serverName, fallbackServers) {
1264
+ if (!serverName)
1265
+ return undefined;
1266
+ const projectServer = discoverMcpServers(projectRoot).find((server) => server.name === serverName);
1267
+ return cloneSdkMcpServerConfig(projectServer?.config) ?? cloneSdkMcpServerConfig(fallbackServers?.[serverName]);
1268
+ }
1269
+ function resolveProjectMcpServerConfigs(projectRoot, serverNames, fallbackServers) {
1270
+ const resolved = {};
1271
+ for (const serverName of serverNames) {
1272
+ const serverConfig = resolveProjectMcpServerConfig(projectRoot, serverName, fallbackServers);
1273
+ if (serverName && serverConfig)
1274
+ resolved[serverName] = serverConfig;
1275
+ }
1276
+ return Object.keys(resolved).length > 0 ? resolved : undefined;
1277
+ }
1278
+ function resolveExactWorkflowMcpToolsForPhase(gsdPhase, workflowServerName, workflowExplicitlyBlocked) {
1279
+ if (!gsdPhase || !workflowServerName || workflowExplicitlyBlocked)
1280
+ return [];
1281
+ const requiredTools = gsdPhase === "run-uat"
1282
+ ? [...RUN_UAT_WORKFLOW_TOOL_NAMES]
1283
+ : getRequiredWorkflowToolsForAutoUnit(gsdPhase);
1284
+ const supportTools = gsdPhase === "run-uat" ? [] : ["gsd_milestone_status"];
1285
+ const requestedToolNames = [...new Set([...requiredTools, ...supportTools])];
1286
+ if (requestedToolNames.length === 0)
1287
+ return [];
1288
+ return resolveToolPresentationPlan({
1289
+ phase: gsdPhase,
1290
+ surface: "claude-code-sdk",
1291
+ workflowMcpServerName: workflowServerName,
1292
+ requestedToolNames,
1293
+ }).presentedToolNames;
1294
+ }
1295
+ export function autoInitClaudeCodeWorkflowMcp(cwd) {
1296
+ const projectRoot = resolveWorkflowMcpProjectRoot(cwd);
1297
+ try {
1298
+ ensureProjectWorkflowMcpConfig(projectRoot);
1299
+ }
1300
+ catch (err) {
1301
+ if (process.env.GSD_DEBUG === "1") {
1302
+ console.warn(`[claude-code] workflow MCP auto-init failed: ${err instanceof Error ? err.message : String(err)}`);
1303
+ }
1304
+ }
1194
1305
  }
1195
1306
  /**
1196
1307
  * Build the options object passed to the Claude Agent SDK's `query()` call.
@@ -1204,7 +1315,7 @@ function browserMcpServerNameFromAllowedTools(allowedTools) {
1204
1315
  * behaviour pass `permissionMode: "bypassPermissions"` explicitly.
1205
1316
  */
1206
1317
  export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
1207
- const { reasoning, cwd, ...sdkExtraOptions } = extraOptions;
1318
+ const { reasoning, cwd, gsdPhase, ...sdkExtraOptions } = extraOptions;
1208
1319
  const sdkCwd = typeof cwd === "string" && cwd.trim().length > 0 ? cwd : process.cwd();
1209
1320
  // Claude Code runs in the milestone worktree for file/shell work, but workflow MCP
1210
1321
  // config (.mcp.json) and server discovery live at the project root.
@@ -1283,13 +1394,38 @@ export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
1283
1394
  const browserMcpTools = !browserExplicitlyBlocked && browserServerName
1284
1395
  ? [`mcp__${browserServerName}__*`]
1285
1396
  : [];
1286
- const gsdMcpTools = [...workflowMcpTools, ...browserMcpTools];
1397
+ const phaseUsesBrowserMcp = !gsdPhase || gsdPhase === "run-uat";
1398
+ const allowedBrowserMcpTools = phaseUsesBrowserMcp ? browserMcpTools : [];
1399
+ const inlinePhaseMcpServers = gsdPhase
1400
+ ? resolveProjectMcpServerConfigs(projectRoot, [
1401
+ workflowExplicitlyBlocked ? undefined : workflowServerName,
1402
+ phaseUsesBrowserMcp && !browserExplicitlyBlocked ? browserServerName : undefined,
1403
+ ], defaultMcpServers.servers)
1404
+ : undefined;
1405
+ const sdkMcpServers = inlinePhaseMcpServers ?? filteredMcpServers;
1406
+ const strictMcpConfig = !!inlinePhaseMcpServers;
1407
+ // Strict phase configs inline the exact MCP servers GSD needs. Loading
1408
+ // project/local settings at the same time can duplicate those servers and
1409
+ // leave allowed mcp__... tools with no registered backing tool.
1410
+ const settingSources = strictMcpConfig ? [] : ["project", "local"];
1411
+ const exactWorkflowMcpTools = resolveExactWorkflowMcpToolsForPhase(gsdPhase, workflowServerName, workflowExplicitlyBlocked);
1412
+ const runUatDisallowedTools = gsdPhase === "run-uat" && workflowServerName
1413
+ ? [
1414
+ ...RUN_UAT_FORBIDDEN_TOOL_NAMES.filter((toolName) => !toolName.startsWith("mcp__")),
1415
+ "WebFetch",
1416
+ "Agent",
1417
+ `mcp__${workflowServerName}__gsd_exec`,
1418
+ `mcp__${workflowServerName}__gsd_summary_save`,
1419
+ `mcp__${workflowServerName}__gsd_save_gate_result`,
1420
+ ]
1421
+ : [];
1287
1422
  const disallowedTools = [...new Set([
1288
1423
  "ToolSearch",
1289
- ...(workflowMcpTools.length > 0 ? ["AskUserQuestion"] : []),
1424
+ ...(workflowMcpTools.length > 0 || exactWorkflowMcpTools.length > 0 ? ["AskUserQuestion"] : []),
1425
+ ...runUatDisallowedTools,
1290
1426
  ...extraDisallowedTools,
1291
1427
  ])];
1292
- const allowedTools = [
1428
+ const standardClaudeTools = [
1293
1429
  "Read",
1294
1430
  "Write",
1295
1431
  "Edit",
@@ -1299,8 +1435,19 @@ export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
1299
1435
  "Agent",
1300
1436
  "WebFetch",
1301
1437
  "WebSearch",
1302
- ...(workflowMcpTools.length > 0 ? gsdMcpTools : ["AskUserQuestion", ...browserMcpTools]),
1303
1438
  ];
1439
+ const allowedTools = gsdPhase === "run-uat"
1440
+ ? [
1441
+ ...RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES,
1442
+ ...(exactWorkflowMcpTools.length > 0 ? exactWorkflowMcpTools : []),
1443
+ ...allowedBrowserMcpTools,
1444
+ ]
1445
+ : [
1446
+ ...standardClaudeTools,
1447
+ ...exactWorkflowMcpTools,
1448
+ ...(workflowMcpTools.length > 0 ? workflowMcpTools : ["AskUserQuestion"]),
1449
+ ...allowedBrowserMcpTools,
1450
+ ];
1304
1451
  const supportsAdaptive = modelSupportsAdaptiveThinking(modelId);
1305
1452
  const effort = reasoning && supportsAdaptive
1306
1453
  ? mapThinkingLevelToAnthropicEffort(reasoning, modelId)
@@ -1321,11 +1468,12 @@ export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
1321
1468
  cwd: sdkCwd,
1322
1469
  permissionMode,
1323
1470
  allowDangerouslySkipPermissions: permissionMode === "bypassPermissions",
1324
- settingSources: ["project"],
1471
+ settingSources,
1325
1472
  systemPrompt: { type: "preset", preset: "claude_code" },
1326
1473
  disallowedTools,
1327
1474
  ...(allowedTools.length > 0 ? { allowedTools } : {}),
1328
- ...(filteredMcpServers ? { mcpServers: filteredMcpServers } : {}),
1475
+ ...(sdkMcpServers ? { mcpServers: sdkMcpServers } : {}),
1476
+ ...(strictMcpConfig ? { strictMcpConfig: true } : {}),
1329
1477
  betas: (modelId.includes("sonnet")
1330
1478
  || modelId.includes("opus-4-7")
1331
1479
  || modelId.includes("opus-4.7")
@@ -1599,6 +1747,8 @@ async function pumpSdkMessages(model, context, options, stream) {
1599
1747
  const onExternalToolCall = options?.onExternalToolCall;
1600
1748
  const onExternalToolResult = options?.onExternalToolResult;
1601
1749
  const cwd = resolveClaudeCodeCwd(options);
1750
+ autoInitClaudeCodeWorkflowMcp(cwd);
1751
+ const gsdPhase = inferGsdPhaseFromContext(context);
1602
1752
  const canUseToolHandler = createClaudeCodeCanUseToolHandler(uiContext);
1603
1753
  // When no UI is available (headless / auto-mode), auto-approve all
1604
1754
  // tool requests. This replaces the old bypassPermissions workaround.
@@ -1606,6 +1756,7 @@ async function pumpSdkMessages(model, context, options, stream) {
1606
1756
  ?? (async (_toolName, _input, opts) => ({ behavior: "allow", toolUseID: opts.toolUseID }));
1607
1757
  const sdkOpts = buildSdkOptions(modelId, "", { permissionMode }, {
1608
1758
  cwd,
1759
+ gsdPhase,
1609
1760
  reasoning: options?.reasoning,
1610
1761
  canUseTool: canUseToolFallback,
1611
1762
  ...(uiContext
@@ -256,7 +256,6 @@ export class AutoOrchestrator {
256
256
  this.status.activeUnit = { unitType: decision.unitType, unitId: decision.unitId };
257
257
  this.status.phase = "running";
258
258
  this.lastAdvanceKey = nextKey;
259
- this.lastFinalizedUnitKey = null;
260
259
  this.bumpTransition();
261
260
  await this.deps.runtime.journalTransition({
262
261
  name: "advance",
@@ -51,13 +51,13 @@ import { resolveManifest } from "../unit-context-manifest.js";
51
51
  import { createWorktreeSafetyModule } from "../worktree-safety.js";
52
52
  import { isSuspiciousGhostCompletion } from "../auto-unit-closeout.js";
53
53
  import { decideVerificationRetry, verificationRetryKey } from "./verification-retry-policy.js";
54
- import { buildPhaseHandoffOutcome, setAutoOutcomeWidget } from "../auto-dashboard.js";
54
+ import { buildPhaseHandoffOutcome, setAutoActiveStatus, setAutoOutcomeWidget } from "../auto-dashboard.js";
55
55
  import { getConsecutiveDispatchBlocker } from "../dispatch-guard.js";
56
56
  import { captureRootDirtySnapshot, detectRootWriteLeak, formatRootWriteLeakMessage, } from "../root-write-leak-guard.js";
57
57
  import { classifyError, isTransient } from "../error-classifier.js";
58
58
  export const STUCK_WINDOW_SIZE = 6;
59
59
  const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
60
- const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE = /^(?: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;
60
+ const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE = /^(?: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;
61
61
  const ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE = /(?:\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;
62
62
  function classifyZeroToolProviderMessage(message) {
63
63
  const firstLine = message.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
@@ -67,6 +67,7 @@ function classifyZeroToolProviderMessage(message) {
67
67
  return null;
68
68
  return classifyError(firstLine);
69
69
  }
70
+ export const _classifyZeroToolProviderMessageForTest = classifyZeroToolProviderMessage;
70
71
  export function resolveDispatchRecoveryAttempts(unitRecoveryCount, unitType, unitId) {
71
72
  return (unitRecoveryCount.get(`${unitType}/${unitId}`) ?? 0) > 0
72
73
  ? 0
@@ -1582,7 +1583,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
1582
1583
  const dispatchKey = `${unitType}/${unitId}`;
1583
1584
  const nextDispatchCount = (s.unitDispatchCount.get(dispatchKey) ?? 0) + 1;
1584
1585
  // Status bar (widget + preconditions deferred until after model selection — see #2899)
1585
- ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
1586
+ setAutoActiveStatus(ctx, s.stepMode ? "next" : "auto");
1586
1587
  if (mid)
1587
1588
  deps.updateSliceProgressCache(s.basePath, mid, state.activeSlice?.id);
1588
1589
  // ── Safety harness: reset evidence + create checkpoint ──
@@ -1,6 +1,6 @@
1
1
  // gsd-pi + src/resources/extensions/gsd/auto-dashboard.ts - Auto-mode progress widget rendering and dashboard helpers.
2
2
  import { getActiveHook } from "./post-unit-hooks.js";
3
- import { getLedger } from "./metrics.js";
3
+ import { getLedger, getProjectTotals } from "./metrics.js";
4
4
  import { getErrorMessage } from "./error-utils.js";
5
5
  import { nativeIsRepo } from "./native-git-bridge.js";
6
6
  import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
@@ -196,6 +196,39 @@ export function formatRuntimeHealthSignal(record, now = Date.now()) {
196
196
  export function shouldRenderRoadmapProgress(progress) {
197
197
  return !!progress && progress.total > 0;
198
198
  }
199
+ function widgetGridLabel(theme, text, color = "borderAccent") {
200
+ return theme.fg(color, theme.bold(text.toUpperCase()));
201
+ }
202
+ function widgetGridColumn(content, width) {
203
+ return padRightVisible(truncateToWidth(content, width, "…"), width);
204
+ }
205
+ function widgetGridColumns(theme, width, parts) {
206
+ if (parts.length === 0)
207
+ return "";
208
+ const gap = theme.fg("dim", " │ ");
209
+ const gapWidth = visibleWidth(gap) * (parts.length - 1);
210
+ const available = Math.max(parts.length * 8, width - gapWidth);
211
+ const base = Math.floor(available / parts.length);
212
+ let remaining = available - base * parts.length;
213
+ const columns = parts.map((part) => {
214
+ const columnWidth = base + (remaining > 0 ? 1 : 0);
215
+ remaining--;
216
+ return widgetGridColumn(part, columnWidth);
217
+ });
218
+ return truncateToWidth(columns.join(gap), width, "…");
219
+ }
220
+ function formatSmallWidgetSpend() {
221
+ const ledger = getLedger();
222
+ if (!ledger || ledger.units.length === 0)
223
+ return "--";
224
+ const totals = getProjectTotals(ledger.units);
225
+ const parts = [];
226
+ if (totals.tokens.total > 0)
227
+ parts.push(formatWidgetTokens(totals.tokens.total));
228
+ if (totals.cost > 0)
229
+ parts.push(`$${totals.cost.toFixed(2)}`);
230
+ return parts.length > 0 ? parts.join(" · ") : "--";
231
+ }
199
232
  // ─── ETA Estimation ──────────────────────────────────────────────────────────
200
233
  /**
201
234
  * Estimate remaining time based on average unit duration from the metrics ledger.
@@ -369,8 +402,9 @@ export const hideFooter = (_tui, theme, footerData) => ({
369
402
  invalidate() { },
370
403
  dispose() { },
371
404
  });
405
+ export const DEFAULT_WIDGET_MODE = "small";
372
406
  const WIDGET_MODES = ["full", "small", "min", "off"];
373
- let widgetMode = "full";
407
+ let widgetMode = DEFAULT_WIDGET_MODE;
374
408
  let widgetModeInitialized = false;
375
409
  let widgetModePreferencePath = null;
376
410
  function safeReadTextFile(path) {
@@ -473,10 +507,19 @@ export function getWidgetMode(projectPath, globalPath) {
473
507
  }
474
508
  /** Test-only reset for widget mode caching. */
475
509
  export function _resetWidgetModeForTests() {
476
- widgetMode = "full";
510
+ widgetMode = DEFAULT_WIDGET_MODE;
477
511
  widgetModeInitialized = false;
478
512
  widgetModePreferencePath = null;
479
513
  }
514
+ function clearAutoOutcomeWidget(ctx) {
515
+ if (!ctx.hasUI)
516
+ return;
517
+ ctx.ui.setWidget("gsd-outcome", undefined);
518
+ }
519
+ export function setAutoActiveStatus(ctx, status) {
520
+ ctx.ui.setStatus("gsd-auto", status);
521
+ clearAutoOutcomeWidget(ctx);
522
+ }
480
523
  export function updateProgressWidget(ctx, unitType, unitId, state, accessors, tierBadge) {
481
524
  if (!ctx.hasUI)
482
525
  return;
@@ -495,7 +538,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
495
538
  ctx.ui.setStatus("gsd-step", undefined);
496
539
  }
497
540
  if (!accessors.isSessionSwitching()) {
498
- ctx.ui.setWidget("gsd-outcome", undefined);
541
+ clearAutoOutcomeWidget(ctx);
499
542
  }
500
543
  const verb = unitVerb(unitType);
501
544
  const phaseLabel = unitPhaseLabel(unitType);
@@ -548,6 +591,7 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
548
591
  logWarning("dashboard", `DB status update failed: ${err instanceof Error ? err.message : String(err)}`);
549
592
  }
550
593
  }, 15_000);
594
+ progressRefreshTimer.unref?.();
551
595
  return {
552
596
  render(width) {
553
597
  if (cachedLines && cachedWidth === width)
@@ -631,26 +675,57 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
631
675
  cachedWidth = width;
632
676
  return lines;
633
677
  }
634
- // ── Mode: small — header + active work progress ───────────────
678
+ // ── Mode: small — dense horizontal grid ───────────────────────
635
679
  if (widgetMode === "small") {
636
- lines.push("");
637
- // Action line
638
- const target = task ? `${task.id}: ${task.title}` : unitId;
639
- const actionLeft = `${pad}${theme.fg("accent", "▸")} ${theme.fg("accent", verb)} ${theme.fg("text", target)}`;
640
- lines.push(rightAlign(actionLeft, theme.fg("dim", phaseLabel), width));
641
- // Progress bar
680
+ lines.length = 0;
681
+ lines.push(...ui.bar());
642
682
  const roadmapSlices = mid ? getRoadmapSlicesSync() : null;
683
+ const unitLabel = unitId || [mid?.id, slice?.id, task?.id].filter(Boolean).join("/");
684
+ const statusParts = [
685
+ spinner,
686
+ theme.fg("success", modeTag),
687
+ theme.fg(stateColor, activeState),
688
+ ];
689
+ if (runtimeSignal?.summary) {
690
+ statusParts.push(theme.fg(healthColor, healthSummary));
691
+ }
692
+ else if (healthLevel !== "green") {
693
+ statusParts.push(`${theme.fg(healthColor, healthIcon)} ${theme.fg(healthColor, healthSummary)}`);
694
+ }
695
+ const timeValue = [elapsed, etaShort].filter(Boolean).join(" · ") || "--";
696
+ const rowOne = widgetGridColumns(theme, width, [
697
+ `${widgetGridLabel(theme, "status", "border")} ${statusParts.join(" ")}`,
698
+ `${widgetGridLabel(theme, "unit")} ${theme.fg("text", unitLabel || "--")}`,
699
+ `${widgetGridLabel(theme, "spend", "border")} ${theme.fg("dim", formatSmallWidgetSpend())}`,
700
+ `${widgetGridLabel(theme, "time")} ${theme.fg("dim", timeValue)}`,
701
+ ]);
702
+ const target = task
703
+ ? `${task.id}: ${task.title}`
704
+ : slice
705
+ ? `${slice.id}: ${slice.title}`
706
+ : unitId;
707
+ let taskValue = task?.id ?? "--";
708
+ let sliceValue = slice?.id ?? "--";
643
709
  if (shouldRenderRoadmapProgress(roadmapSlices)) {
644
710
  const { done, total, activeSliceTasks } = roadmapSlices;
645
- const barWidth = Math.max(6, Math.min(18, Math.floor(width * 0.25)));
711
+ const barWidth = Math.max(4, Math.min(14, Math.floor(width * 0.12)));
646
712
  const bar = renderProgressBar(theme, done, total, barWidth);
647
- let meta = `${theme.fg("text", `${done}`)}${theme.fg("dim", `/${total} slices`)}`;
713
+ sliceValue = `${bar} ${theme.fg("text", `${done}/${total}`)}`;
648
714
  if (activeSliceTasks && activeSliceTasks.total > 0) {
649
- const tn = Math.min(activeSliceTasks.done + 1, activeSliceTasks.total);
650
- meta += `${theme.fg("dim", " · task ")}${theme.fg("accent", `${tn}`)}${theme.fg("dim", `/${activeSliceTasks.total}`)}`;
715
+ const taskNum = isHook
716
+ ? Math.max(activeSliceTasks.done, 1)
717
+ : Math.min(activeSliceTasks.done + 1, activeSliceTasks.total);
718
+ taskValue = `${theme.fg("accent", `${taskNum}`)}${theme.fg("dim", `/${activeSliceTasks.total}`)}`;
651
719
  }
652
- lines.push(`${pad}${bar} ${meta}`);
653
720
  }
721
+ const rowTwo = widgetGridColumns(theme, width, [
722
+ `${widgetGridLabel(theme, "phase", "border")} ${theme.fg("dim", unitType)}`,
723
+ `${widgetGridLabel(theme, "work")} ${theme.fg("text", target || "--")}`,
724
+ `${widgetGridLabel(theme, "task", "border")} ${taskValue}`,
725
+ `${widgetGridLabel(theme, "slice")} ${sliceValue}`,
726
+ ]);
727
+ lines.push(rowOne);
728
+ lines.push(rowTwo);
654
729
  lines.push(...ui.bar());
655
730
  cachedLines = lines;
656
731
  cachedWidth = width;
@@ -789,7 +864,7 @@ export function setCompletionProgressWidget(ctx, snapshot) {
789
864
  if (!ctx.hasUI)
790
865
  return;
791
866
  const widgetKey = "gsd-progress";
792
- ctx.ui.setWidget("gsd-outcome", undefined);
867
+ clearAutoOutcomeWidget(ctx);
793
868
  if (typeof ctx.ui?.setHeader === "function") {
794
869
  ctx.ui.setHeader(() => ({
795
870
  render() { return []; },
@@ -30,6 +30,7 @@ import { nativeHasChanges, nativeIsRepo, _resetHasChangesCache } from "./native-
30
30
  import { debugLog, isDebugEnabled } from "./debug-logger.js";
31
31
  import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
32
32
  import { resolveWorktreeProjectRoot } from "./worktree-root.js";
33
+ import { detectWorktreeName } from "./worktree.js";
33
34
  import { probeGitConflictState } from "./git-conflict-state.js";
34
35
  import { runTurnGitAction } from "./git-service.js";
35
36
  import { parseUnitId } from "./unit-id.js";
@@ -178,6 +179,24 @@ function missingSliceStop(mid, phase) {
178
179
  function isRegistryMilestoneComplete(state, mid) {
179
180
  return state.registry.some((milestone) => milestone.id === mid && milestone.status === "complete");
180
181
  }
182
+ function normalizeMilestoneScope(value) {
183
+ const trimmed = value?.trim();
184
+ if (!trimmed || !MILESTONE_ID_RE.test(trimmed))
185
+ return null;
186
+ return trimmed;
187
+ }
188
+ function resolveDispatchMilestoneScope(ctx) {
189
+ const sessionMilestone = normalizeMilestoneScope(ctx.session?.currentMilestoneId);
190
+ if (sessionMilestone)
191
+ return { id: sessionMilestone, source: "session.currentMilestoneId" };
192
+ const sessionWorktree = normalizeMilestoneScope(ctx.session?.basePath ? detectWorktreeName(ctx.session.basePath) : null);
193
+ if (sessionWorktree)
194
+ return { id: sessionWorktree, source: "session.basePath worktree" };
195
+ const baseWorktree = normalizeMilestoneScope(detectWorktreeName(ctx.basePath));
196
+ if (baseWorktree)
197
+ return { id: baseWorktree, source: "basePath worktree" };
198
+ return null;
199
+ }
181
200
  function hasMilestonePassedDiscuss(basePath, mid) {
182
201
  if (isDbAvailable()) {
183
202
  try {
@@ -424,6 +443,7 @@ export const DISPATCH_RULES = [
424
443
  unitType: "discuss-milestone",
425
444
  unitId: mid,
426
445
  prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
446
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
427
447
  };
428
448
  },
429
449
  },
@@ -559,6 +579,7 @@ export const DISPATCH_RULES = [
559
579
  unitType: "discuss-milestone",
560
580
  unitId: mid,
561
581
  prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
582
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
562
583
  };
563
584
  },
564
585
  },
@@ -598,6 +619,7 @@ export const DISPATCH_RULES = [
598
619
  unitType: "discuss-project",
599
620
  unitId: "PROJECT",
600
621
  prompt: await buildDiscussProjectPrompt(basePath, structuredQuestionsAvailable),
622
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
601
623
  };
602
624
  },
603
625
  },
@@ -623,6 +645,7 @@ export const DISPATCH_RULES = [
623
645
  unitType: "discuss-requirements",
624
646
  unitId: "REQUIREMENTS",
625
647
  prompt: await buildDiscussRequirementsPrompt(basePath, structuredQuestionsAvailable),
648
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
626
649
  };
627
650
  },
628
651
  },
@@ -738,6 +761,7 @@ export const DISPATCH_RULES = [
738
761
  unitType: "discuss-milestone",
739
762
  unitId: mid,
740
763
  prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable, { headless: !!process.env.GSD_HEADLESS }),
764
+ pauseAfterDispatch: !process.env.GSD_HEADLESS,
741
765
  };
742
766
  },
743
767
  },
@@ -1351,6 +1375,17 @@ import { getRegistry } from "./rule-registry.js";
1351
1375
  * resolveDispatch directly without registry initialization).
1352
1376
  */
1353
1377
  export async function resolveDispatch(ctx) {
1378
+ if (ctx.mid && isDbAvailable()) {
1379
+ const milestone = getMilestone(ctx.mid);
1380
+ if (milestone && isClosedStatus(milestone.status)) {
1381
+ return {
1382
+ action: "stop",
1383
+ reason: `Milestone ${ctx.mid} is closed (status: ${milestone.status}); auto-mode will not reopen or recover it implicitly. ` +
1384
+ "Use an explicit reopen command before planning or executing more work for this milestone.",
1385
+ level: "warning",
1386
+ };
1387
+ }
1388
+ }
1354
1389
  const activeMid = ctx.state.activeMilestone?.id;
1355
1390
  if (activeMid && ctx.mid !== activeMid) {
1356
1391
  return {
@@ -1360,6 +1395,15 @@ export async function resolveDispatch(ctx) {
1360
1395
  level: "warning",
1361
1396
  };
1362
1397
  }
1398
+ const scopedMilestone = resolveDispatchMilestoneScope(ctx);
1399
+ if (scopedMilestone && ctx.mid !== scopedMilestone.id) {
1400
+ return {
1401
+ action: "stop",
1402
+ reason: `Dispatch milestone mismatch: context mid "${ctx.mid}" does not match ${scopedMilestone.source} "${scopedMilestone.id}". ` +
1403
+ "The active worktree/session and derived project state disagree; recover, park, or discard the stranded milestone before continuing.",
1404
+ level: "warning",
1405
+ };
1406
+ }
1363
1407
  // Delegate to registry when available
1364
1408
  try {
1365
1409
  const registry = getRegistry();