@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
@@ -19,6 +19,14 @@ test("shouldAutoPrepareWorkflowMcp enables prep for externalCli local transport"
19
19
  assert.equal(result, true);
20
20
  });
21
21
 
22
+ test("shouldAutoPrepareWorkflowMcp enables prep when Claude Code provider is known before auth mode settles", () => {
23
+ const result = shouldAutoPrepareWorkflowMcp({
24
+ model: { provider: "claude-code", baseUrl: "local://claude-code" },
25
+ });
26
+
27
+ assert.equal(result, true);
28
+ });
29
+
22
30
  test("prepareWorkflowMcpForProject uses the selected unit model when session provider differs", (t) => {
23
31
  const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-unit-model-"));
24
32
  const notifications: Array<{ message: string; level: "info" | "warning" | "error" | "success" }> = [];
@@ -46,7 +54,7 @@ test("prepareWorkflowMcpForProject uses the selected unit model when session pro
46
54
 
47
55
  assert.equal(result?.status, "created");
48
56
  assert.equal(existsSync(join(projectRoot, ".mcp.json")), true);
49
- assert.match(notifications.map((entry) => entry.message).join("\n"), /Claude Code MCP prepared/);
57
+ assert.match(notifications.map((entry) => entry.message).join("\n"), /GSD MCP Server Prepared/);
50
58
  });
51
59
 
52
60
  test("shouldAutoPrepareWorkflowMcp stays disabled for non-Claude active provider even when claude-code is ready", () => {
@@ -163,7 +171,14 @@ test("before_agent_start auto-prepares project workflow MCP for Claude Code CLI"
163
171
  };
164
172
  assert.ok(parsed.mcpServers?.[GSD_WORKFLOW_MCP_SERVER_NAME]);
165
173
  assert.ok(parsed.mcpServers?.[GSD_BROWSER_MCP_SERVER_NAME]);
166
- assert.match(notifications.join("\n"), /Claude Code MCP prepared/);
174
+ const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
175
+ enabledMcpjsonServers?: string[];
176
+ };
177
+ assert.deepEqual(settings.enabledMcpjsonServers, [
178
+ GSD_WORKFLOW_MCP_SERVER_NAME,
179
+ GSD_BROWSER_MCP_SERVER_NAME,
180
+ ]);
181
+ assert.match(notifications.join("\n"), /GSD MCP Server Prepared/);
167
182
  });
168
183
 
169
184
  test("before_agent_start returns discovered skill fallback without project .gsd", async (t) => {
@@ -30,6 +30,7 @@ import {
30
30
  executeSliceComplete,
31
31
  executeSliceReopen,
32
32
  executeValidateMilestone,
33
+ executeUatResultSave,
33
34
  } from "../tools/workflow-tool-executors.ts";
34
35
 
35
36
  function makeTmpBase(): string {
@@ -74,6 +75,11 @@ test("closeout executors reject phase escalation from the wrong active auto unit
74
75
  const milestone = await executeCompleteMilestone({} as Parameters<typeof executeCompleteMilestone>[0], "/tmp/project");
75
76
  assert.equal(milestone.isError, true);
76
77
  assert.match(String(milestone.details.error), /complete_milestone may only run from complete-milestone/);
78
+
79
+ const uat = await executeUatResultSave({} as Parameters<typeof executeUatResultSave>[0], "/tmp/project");
80
+ assert.equal(uat.isError, true);
81
+ assert.match(String(uat.details.error), /save_uat_result may only run from run-uat/);
82
+ assert.match(String(uat.details.error), /Tool Contract failure/);
77
83
  } finally {
78
84
  autoSession.reset();
79
85
  }
@@ -234,6 +240,62 @@ test("executeTaskComplete derives missing verification from evidence", async ()
234
240
  }
235
241
  });
236
242
 
243
+ test("executeTaskComplete surfaces escalation questions and metadata", async () => {
244
+ const base = makeTmpBase();
245
+ try {
246
+ openTestDb(base);
247
+ writeFileSync(join(base, ".gsd", "PREFERENCES.md"), [
248
+ "---",
249
+ "version: 1",
250
+ "phases:",
251
+ " mid_execution_escalation: true",
252
+ "---",
253
+ ].join("\n"));
254
+ const planDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
255
+ mkdirSync(planDir, { recursive: true });
256
+ writeFileSync(join(planDir, "S01-PLAN.md"), "# S01\n\n- [ ] **T01: Demo** `est:5m`\n");
257
+
258
+ const result = await inProjectDir(base, () => executeTaskComplete({
259
+ milestoneId: "M001",
260
+ sliceId: "S01",
261
+ taskId: "T01",
262
+ oneLiner: "Completed task",
263
+ narrative: "Did the work but found an ambiguity.",
264
+ verification: "npm test",
265
+ escalation: {
266
+ question: "Should the cache use write-through or write-back?",
267
+ options: [
268
+ { id: "A", label: "Write-through", tradeoffs: "Simpler reads; slower writes." },
269
+ { id: "B", label: "Write-back", tradeoffs: "Faster writes; more flush complexity." },
270
+ ],
271
+ recommendation: "A",
272
+ recommendationRationale: "Current usage favors correctness over write latency.",
273
+ continueWithDefault: true,
274
+ },
275
+ }, base));
276
+
277
+ assert.equal(result.details.operation, "complete_task");
278
+ assert.match(
279
+ String(result.content[0]?.text),
280
+ /Task completed with escalation decision required: Should the cache use write-through or write-back\?/,
281
+ );
282
+ assert.match(String(result.content[0]?.text), /Resolve with: \/gsd escalate resolve T01/);
283
+ assert.equal((result.details.escalation as { question?: string }).question, "Should the cache use write-through or write-back?");
284
+
285
+ const db = _getAdapter();
286
+ assert.ok(db, "DB should be open");
287
+ const row = db!.prepare(
288
+ "SELECT escalation_pending, escalation_awaiting_review, escalation_artifact_path FROM tasks WHERE milestone_id = ? AND slice_id = ? AND id = ?",
289
+ ).get("M001", "S01", "T01") as Record<string, unknown> | undefined;
290
+ assert.equal(row?.escalation_pending, 0);
291
+ assert.equal(row?.escalation_awaiting_review, 1);
292
+ assert.ok(String(row?.escalation_artifact_path ?? "").endsWith("T01-ESCALATION.json"));
293
+ } finally {
294
+ closeDatabase();
295
+ cleanup(base);
296
+ }
297
+ });
298
+
237
299
  test("executeTaskComplete returns a tool error when verification cannot be derived", async () => {
238
300
  const base = makeTmpBase();
239
301
  try {
@@ -504,6 +566,425 @@ test("executePlanSlice marks validation failures with isError", async () => {
504
566
  }
505
567
  });
506
568
 
569
+ test("executeUatResultSave accepts gsd_uat_exec evidence written in a milestone worktree", async () => {
570
+ const base = makeTmpBase();
571
+ const worktree = join(base, ".gsd", "worktrees", "M001");
572
+ const worktreeExecDir = join(worktree, ".gsd", "exec");
573
+ const browserTimelineDir = join(base, ".artifacts", "browser", "session");
574
+ const evidenceId = "worktree-uat-evidence";
575
+ const browserTimelinePath = join(browserTimelineDir, "s02-uat-browser-timeline.json");
576
+ try {
577
+ openTestDb(base);
578
+ seedMilestone("M001", "Milestone One");
579
+ seedSlice("M001", "S02", "complete");
580
+ mkdirSync(worktreeExecDir, { recursive: true });
581
+ mkdirSync(browserTimelineDir, { recursive: true });
582
+ writeFileSync(browserTimelinePath, JSON.stringify({ summary: "browser timeline evidence" }), "utf-8");
583
+ writeFileSync(
584
+ join(worktreeExecDir, `${evidenceId}.meta.json`),
585
+ JSON.stringify({
586
+ id: evidenceId,
587
+ metadata: {
588
+ kind: "uat_exec",
589
+ milestoneId: "M001",
590
+ sliceId: "S02",
591
+ checkId: "UAT-01",
592
+ intent: "uat-runtime-check",
593
+ },
594
+ }),
595
+ "utf-8",
596
+ );
597
+
598
+ const result = await inProjectDir(worktree, () => executeUatResultSave({
599
+ milestoneId: "M001",
600
+ sliceId: "S02",
601
+ uatType: "runtime-executable",
602
+ verdict: "PASS",
603
+ checks: [{
604
+ id: "UAT-01",
605
+ description: "Runtime path C:\\tmp|uat evidence was captured in the active worktree",
606
+ mode: "runtime",
607
+ result: "PASS",
608
+ evidence: [
609
+ { kind: "gsd_uat_exec", ref: evidenceId },
610
+ { kind: "browser", ref: browserTimelinePath },
611
+ ],
612
+ notes: "Worktree-local gsd_uat_exec metadata should resolve with backslash \\ and pipe |.",
613
+ }],
614
+ presentation: {
615
+ surface: "mcp",
616
+ presentedTools: [
617
+ "gsd_uat_exec",
618
+ "gsd_uat_result_save",
619
+ "gsd_resume",
620
+ "gsd_milestone_status",
621
+ "gsd_journal_query",
622
+ ],
623
+ blockedTools: [
624
+ { name: "gsd_exec", reason: "forbidden during run-uat" },
625
+ { name: "gsd_summary_save", reason: "forbidden during run-uat" },
626
+ { name: "gsd_save_gate_result", reason: "forbidden during run-uat" },
627
+ ],
628
+ },
629
+ notes: "UAT passed with worktree-local evidence.",
630
+ }, worktree));
631
+
632
+ assert.equal(result.isError, undefined);
633
+ assert.equal(result.details.operation, "save_uat_result");
634
+ assert.equal(result.details.verdict, "PASS");
635
+ assert.ok(
636
+ existsSync(join(base, ".gsd", "uat", "M001", "S02", "attempt-1.json")),
637
+ "attempt JSON should be persisted under the authoritative project .gsd",
638
+ );
639
+ const assessment = readFileSync(
640
+ join(base, ".gsd", "milestones", "M001", "slices", "S02", "S02-ASSESSMENT.md"),
641
+ "utf-8",
642
+ );
643
+ assert.match(assessment, /Runtime path C:\\\\tmp\\\|uat evidence/);
644
+ assert.match(assessment, /backslash \\\\ and pipe \\\|/);
645
+ } finally {
646
+ closeDatabase();
647
+ cleanup(base);
648
+ }
649
+ });
650
+
651
+ test("executeUatResultSave supplies canonical presentation and normalizes verdict casing", async () => {
652
+ const base = makeTmpBase();
653
+ const worktree = join(base, ".gsd", "worktrees", "M001");
654
+ const worktreeExecDir = join(worktree, ".gsd", "exec");
655
+ const evidenceId = "uat-lowercase-verdict";
656
+ try {
657
+ openTestDb(base);
658
+ seedMilestone("M001", "Milestone One");
659
+ seedSlice("M001", "S03", "complete");
660
+ mkdirSync(worktreeExecDir, { recursive: true });
661
+ writeFileSync(
662
+ join(worktreeExecDir, `${evidenceId}.meta.json`),
663
+ JSON.stringify({
664
+ id: evidenceId,
665
+ metadata: {
666
+ kind: "uat_exec",
667
+ milestoneId: "M001",
668
+ sliceId: "S03",
669
+ checkId: "UAT-01",
670
+ intent: "uat-artifact-check",
671
+ },
672
+ }),
673
+ "utf-8",
674
+ );
675
+
676
+ const result = await inProjectDir(worktree, () => executeUatResultSave({
677
+ milestoneId: "M001",
678
+ sliceId: "S03",
679
+ uatType: "artifact-driven",
680
+ verdict: "pass",
681
+ checks: [{
682
+ id: "UAT-01",
683
+ description: "Static artifact contract passes",
684
+ mode: "artifact",
685
+ result: "PASS",
686
+ evidence: [{ kind: "gsd_uat_exec", ref: evidenceId }],
687
+ notes: "Artifact check passed.",
688
+ }],
689
+ notes: "UAT passed with canonical presentation supplied by the executor.",
690
+ } as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
691
+
692
+ assert.equal(result.isError, undefined);
693
+ assert.equal(result.details.verdict, "PASS");
694
+
695
+ const attempt = JSON.parse(readFileSync(
696
+ join(base, ".gsd", "uat", "M001", "S03", "attempt-1.json"),
697
+ "utf-8",
698
+ )) as { presentation?: { toolPresentationPlanId?: string; presentedTools?: string[] } };
699
+ assert.equal(attempt.presentation?.toolPresentationPlanId, "run-uat/default-v1");
700
+ assert.ok(attempt.presentation?.presentedTools?.includes("gsd_uat_result_save"));
701
+ assert.ok(attempt.presentation?.presentedTools?.includes("read"));
702
+ } finally {
703
+ closeDatabase();
704
+ cleanup(base);
705
+ }
706
+ });
707
+
708
+ test("executeUatResultSave supplies direct browser tools for browser-executable UAT", async () => {
709
+ const base = makeTmpBase();
710
+ const worktree = join(base, ".gsd", "worktrees", "M001");
711
+ const worktreeExecDir = join(worktree, ".gsd", "exec");
712
+ const evidenceId = "uat-direct-browser-evidence";
713
+ try {
714
+ openTestDb(base);
715
+ seedMilestone("M001", "Milestone One");
716
+ seedSlice("M001", "S06", "complete");
717
+ mkdirSync(worktreeExecDir, { recursive: true });
718
+ writeFileSync(
719
+ join(worktreeExecDir, `${evidenceId}.meta.json`),
720
+ JSON.stringify({
721
+ id: evidenceId,
722
+ metadata: {
723
+ kind: "uat_exec",
724
+ milestoneId: "M001",
725
+ sliceId: "S06",
726
+ checkId: "UAT-01",
727
+ intent: "uat-browser-check",
728
+ },
729
+ }),
730
+ "utf-8",
731
+ );
732
+
733
+ const result = await inProjectDir(worktree, () => executeUatResultSave({
734
+ milestoneId: "M001",
735
+ sliceId: "S06",
736
+ uatType: "browser-executable",
737
+ verdict: "PASS",
738
+ checks: [{
739
+ id: "UAT-01",
740
+ description: "Browser flow used managed gsd-browser tools",
741
+ mode: "browser",
742
+ result: "PASS",
743
+ evidence: [{ kind: "gsd_uat_exec", ref: evidenceId }],
744
+ notes: "Browser check passed.",
745
+ }],
746
+ notes: "UAT passed with managed browser evidence.",
747
+ } as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
748
+
749
+ assert.equal(result.isError, undefined);
750
+ const attempt = JSON.parse(readFileSync(
751
+ join(base, ".gsd", "uat", "M001", "S06", "attempt-1.json"),
752
+ "utf-8",
753
+ )) as { presentation?: { presentedTools?: string[] } };
754
+
755
+ assert.ok(attempt.presentation?.presentedTools?.includes("browser_navigate"));
756
+ assert.ok(attempt.presentation?.presentedTools?.includes("browser_assert"));
757
+ assert.equal(
758
+ attempt.presentation?.presentedTools?.some((toolName) => toolName.startsWith("mcp__gsd-browser__")),
759
+ false,
760
+ );
761
+ } finally {
762
+ closeDatabase();
763
+ cleanup(base);
764
+ }
765
+ });
766
+
767
+ test("executeUatResultSave merges canonical plan ID and read-only tools when presentation lacks plan ID", async () => {
768
+ const base = makeTmpBase();
769
+ const worktree = join(base, ".gsd", "worktrees", "M001");
770
+ const worktreeExecDir = join(worktree, ".gsd", "exec");
771
+ const evidenceId = "uat-no-plan-id-evidence";
772
+ try {
773
+ openTestDb(base);
774
+ seedMilestone("M001", "Milestone One");
775
+ seedSlice("M001", "S05", "complete");
776
+ mkdirSync(worktreeExecDir, { recursive: true });
777
+ writeFileSync(
778
+ join(worktreeExecDir, `${evidenceId}.meta.json`),
779
+ JSON.stringify({
780
+ id: evidenceId,
781
+ metadata: {
782
+ kind: "uat_exec",
783
+ milestoneId: "M001",
784
+ sliceId: "S05",
785
+ checkId: "UAT-01",
786
+ intent: "uat-artifact-check",
787
+ },
788
+ }),
789
+ "utf-8",
790
+ );
791
+
792
+ const result = await inProjectDir(worktree, () => executeUatResultSave({
793
+ milestoneId: "M001",
794
+ sliceId: "S05",
795
+ uatType: "artifact-driven",
796
+ verdict: "PASS",
797
+ checks: [{
798
+ id: "UAT-01",
799
+ description: "Presentation plan ID absent from provider call",
800
+ mode: "artifact",
801
+ result: "PASS",
802
+ evidence: [{ kind: "gsd_uat_exec", ref: evidenceId }],
803
+ notes: "Canonical merge should apply even when toolPresentationPlanId is absent.",
804
+ }],
805
+ presentation: {
806
+ surface: "mcp",
807
+ presentedTools: [
808
+ "gsd_uat_exec",
809
+ "gsd_uat_result_save",
810
+ "gsd_resume",
811
+ "gsd_milestone_status",
812
+ "gsd_journal_query",
813
+ ],
814
+ blockedTools: [
815
+ { name: "gsd_exec", reason: "forbidden during run-uat" },
816
+ { name: "gsd_summary_save", reason: "forbidden during run-uat" },
817
+ { name: "gsd_save_gate_result", reason: "forbidden during run-uat" },
818
+ ],
819
+ },
820
+ notes: "Provider omitted toolPresentationPlanId; executor must canonicalize.",
821
+ } as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
822
+
823
+ assert.equal(result.isError, undefined);
824
+ assert.equal(result.details.verdict, "PASS");
825
+
826
+ const attempt = JSON.parse(readFileSync(
827
+ join(base, ".gsd", "uat", "M001", "S05", "attempt-1.json"),
828
+ "utf-8",
829
+ )) as { presentation?: { toolPresentationPlanId?: string; presentedTools?: string[] } };
830
+ assert.equal(attempt.presentation?.toolPresentationPlanId, "run-uat/default-v1");
831
+ assert.ok(attempt.presentation?.presentedTools?.includes("read"), "read-only tool must be merged in");
832
+ assert.ok(attempt.presentation?.presentedTools?.includes("gsd_uat_result_save"));
833
+ } finally {
834
+ closeDatabase();
835
+ cleanup(base);
836
+ }
837
+ });
838
+
839
+ test("executeUatResultSave rejects saved UAT without fresh UAT-owned evidence", async () => {
840
+ const base = makeTmpBase();
841
+ const worktree = join(base, ".gsd", "worktrees", "M001");
842
+ const worktreeExecDir = join(worktree, ".gsd", "exec");
843
+ const evidenceId = "generic-exec-evidence";
844
+ try {
845
+ openTestDb(base);
846
+ seedMilestone("M001", "Milestone One");
847
+ seedSlice("M001", "S04", "complete");
848
+ mkdirSync(worktreeExecDir, { recursive: true });
849
+ writeFileSync(
850
+ join(worktreeExecDir, `${evidenceId}.meta.json`),
851
+ JSON.stringify({
852
+ id: evidenceId,
853
+ metadata: { kind: "exec" },
854
+ }),
855
+ "utf-8",
856
+ );
857
+
858
+ const result = await inProjectDir(worktree, () => executeUatResultSave({
859
+ milestoneId: "M001",
860
+ sliceId: "S04",
861
+ uatType: "artifact-driven",
862
+ verdict: "PASS",
863
+ checks: [{
864
+ id: "UAT-01",
865
+ description: "Static artifact contract passes",
866
+ mode: "artifact",
867
+ result: "PASS",
868
+ evidence: [{ kind: "gsd_exec", ref: evidenceId }],
869
+ notes: "Generic evidence should not satisfy fresh UAT evidence.",
870
+ }],
871
+ notes: "UAT should not pass without fresh UAT-owned evidence.",
872
+ } as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
873
+
874
+ assert.equal(result.isError, true);
875
+ assert.match(String(result.content[0]?.text), /fresh gsd_uat_exec evidence/);
876
+ } finally {
877
+ closeDatabase();
878
+ cleanup(base);
879
+ }
880
+ });
881
+
882
+ test("executeUatResultSave rejects an unrecognized uatType", async () => {
883
+ const base = makeTmpBase();
884
+ const worktree = join(base, ".gsd", "worktrees", "M001");
885
+ try {
886
+ openTestDb(base);
887
+ mkdirSync(worktree, { recursive: true });
888
+ seedMilestone("M001", "Milestone One");
889
+ seedSlice("M001", "S06", "complete");
890
+
891
+ const result = await inProjectDir(worktree, () => executeUatResultSave({
892
+ milestoneId: "M001",
893
+ sliceId: "S06",
894
+ uatType: "hallucinated-mode",
895
+ verdict: "PASS",
896
+ checks: [{
897
+ id: "UAT-01",
898
+ description: "Static artifact contract passes",
899
+ mode: "artifact",
900
+ result: "PASS",
901
+ evidence: [{ kind: "gsd_uat_exec", ref: "some-ref" }],
902
+ }],
903
+ notes: "Should fail before evidence validation.",
904
+ } as unknown as Parameters<typeof executeUatResultSave>[0], worktree));
905
+
906
+ assert.equal(result.isError, true);
907
+ assert.match(String(result.content[0]?.text), /uatType must be one of/);
908
+ } finally {
909
+ closeDatabase();
910
+ cleanup(base);
911
+ }
912
+ });
913
+
914
+ test("executeUatResultSave rejects artifact-driven PASS with human follow-up checks", async () => {
915
+ const base = makeTmpBase();
916
+ const worktree = join(base, ".gsd", "worktrees", "M001");
917
+ const evidenceId = "uat-artifact-nonautomatable";
918
+ const worktreeExecDir = join(worktree, ".gsd", "exec");
919
+ try {
920
+ openTestDb(base);
921
+ seedMilestone("M001", "Milestone One");
922
+ seedSlice("M001", "S01", "complete");
923
+ mkdirSync(worktreeExecDir, { recursive: true });
924
+ writeFileSync(
925
+ join(worktreeExecDir, `${evidenceId}.meta.json`),
926
+ JSON.stringify({
927
+ id: evidenceId,
928
+ metadata: {
929
+ kind: "uat_exec",
930
+ milestoneId: "M001",
931
+ sliceId: "S01",
932
+ checkId: "UAT-01",
933
+ intent: "uat-artifact-check",
934
+ },
935
+ }),
936
+ "utf-8",
937
+ );
938
+
939
+ const result = await inProjectDir(worktree, () => executeUatResultSave({
940
+ milestoneId: "M001",
941
+ sliceId: "S01",
942
+ uatType: "artifact-driven",
943
+ verdict: "PASS",
944
+ checks: [
945
+ {
946
+ id: "UAT-01",
947
+ description: "Static contract passes",
948
+ mode: "artifact",
949
+ result: "PASS",
950
+ evidence: [{ kind: "gsd_uat_exec", ref: evidenceId }],
951
+ notes: "Artifact check passed.",
952
+ },
953
+ {
954
+ id: "UAT-02",
955
+ description: "Browser polish is deferred to the next slice",
956
+ mode: "human-follow-up",
957
+ result: "NEEDS-HUMAN",
958
+ notes: "Out of scope for this artifact-driven UAT.",
959
+ nonAutomatable: true,
960
+ },
961
+ ],
962
+ presentation: {
963
+ surface: "mcp",
964
+ presentedTools: [
965
+ "gsd_uat_exec",
966
+ "gsd_uat_result_save",
967
+ "gsd_resume",
968
+ "gsd_milestone_status",
969
+ "gsd_journal_query",
970
+ ],
971
+ blockedTools: [
972
+ { name: "gsd_exec", reason: "forbidden during run-uat" },
973
+ { name: "gsd_summary_save", reason: "forbidden during run-uat" },
974
+ { name: "gsd_save_gate_result", reason: "forbidden during run-uat" },
975
+ ],
976
+ },
977
+ notes: "UAT passed; non-automatable browser polish is deferred.",
978
+ }, worktree));
979
+
980
+ assert.equal(result.isError, true);
981
+ assert.match(String(result.content[0]?.text), /artifact-driven UAT cannot PASS with human-only checks/);
982
+ } finally {
983
+ closeDatabase();
984
+ cleanup(base);
985
+ }
986
+ });
987
+
507
988
  test("executeSliceComplete coerces string enrichment entries and writes summary/UAT artifacts", async () => {
508
989
  const base = makeTmpBase();
509
990
  try {
@@ -1196,6 +1677,10 @@ test("executeSummarySave blocks final root artifacts while approval gate is pend
1196
1677
 
1197
1678
  assert.equal(result.isError, true);
1198
1679
  assert.equal(result.details.error, "root_artifact_write_blocked");
1680
+ assert.equal(
1681
+ result.details.displayReason,
1682
+ "Approval confirmation required before saving final project setup artifacts.",
1683
+ );
1199
1684
  assert.match(result.content[0].text, /has not been confirmed/);
1200
1685
  assert.equal(existsSync(join(base, ".gsd", "REQUIREMENTS.md")), false);
1201
1686
 
@@ -1238,6 +1723,10 @@ test("executeSummarySave requires verified root approval in deep mode", async ()
1238
1723
 
1239
1724
  assert.equal(blocked.isError, true);
1240
1725
  assert.equal(blocked.details.error, "root_artifact_write_blocked");
1726
+ assert.equal(
1727
+ blocked.details.displayReason,
1728
+ "Approval confirmation required before saving final project setup artifacts.",
1729
+ );
1241
1730
  assert.match(blocked.content[0].text, /fail-closed/);
1242
1731
  assert.equal(existsSync(join(base, ".gsd", "PROJECT.md")), false);
1243
1732
 
@@ -1454,6 +1943,10 @@ test("executeSummarySave CONTEXT HARD BLOCK clears after write-gate state file i
1454
1943
  content: "# Context\n\ncontent",
1455
1944
  }, base));
1456
1945
  assert.equal(blocked.isError, true, "should be blocked without depth verification");
1946
+ assert.equal(
1947
+ blocked.details.displayReason,
1948
+ "Depth check required before writing milestone context.",
1949
+ );
1457
1950
  assert.match(
1458
1951
  blocked.content[0].text,
1459
1952
  /HARD BLOCK/,
@@ -9,6 +9,7 @@ import test from 'node:test';
9
9
  import assert from 'node:assert/strict';
10
10
  import { join, sep } from 'node:path';
11
11
 
12
+ import { GSD_PHASE_SCOPE_DISPLAY_REASON } from '../auto-unit-tool-scope.ts';
12
13
  import { ALLOWED_PLANNING_DISPATCH_AGENTS, shouldBlockPlanningUnit } from '../bootstrap/write-gate.ts';
13
14
  import { extractSubagentAgentClasses } from '../bootstrap/subagent-input.ts';
14
15
  import { isDeterministicPolicyError } from '../auto-tool-tracking.ts';
@@ -27,6 +28,10 @@ const PLANNING_DISPATCH_REVIEW: ToolsPolicy = {
27
28
  const READ_ONLY: ToolsPolicy = { mode: 'read-only' };
28
29
  const ALL: ToolsPolicy = { mode: 'all' };
29
30
  const VERIFICATION: ToolsPolicy = { mode: 'verification' };
31
+ const VERIFICATION_UAT: ToolsPolicy = {
32
+ mode: 'verification',
33
+ allowedSubagents: ['mnemo', 'scout', 'reviewer', 'tester'],
34
+ };
30
35
  const DOCS: ToolsPolicy = {
31
36
  mode: 'docs',
32
37
  allowedPathGlobs: ['docs/**', 'README.md', 'README.*.md', 'CHANGELOG.md', '*.md'],
@@ -61,6 +66,19 @@ test('planning-unit: deterministic block reason is suitable for retry short-circ
61
66
  assert.strictEqual(isDeterministicPolicyError(r.reason!), true);
62
67
  });
63
68
 
69
+ test('planning-unit: blocked tool-policy calls include UI-safe display reason', () => {
70
+ const r = shouldBlockPlanningUnit(
71
+ 'edit',
72
+ 'src/main.ts',
73
+ BASE,
74
+ 'discuss-milestone',
75
+ PLANNING,
76
+ );
77
+ assert.strictEqual(r.block, true);
78
+ assert.match(r.reason!, /HARD BLOCK/);
79
+ assert.strictEqual(r.displayReason, GSD_PHASE_SCOPE_DISPLAY_REASON);
80
+ });
81
+
64
82
  test('planning-unit: blocks write to user source via relative path', () => {
65
83
  const r = shouldBlockPlanningUnit('write', 'src/main.ts', BASE, 'plan-milestone', PLANNING);
66
84
  assert.strictEqual(r.block, true);
@@ -363,6 +381,7 @@ test('auto-unit scope: execute-task allows only its task completion lifecycle to
363
381
  assert.strictEqual(blocked.block, true);
364
382
  assert.match(blocked.reason!, /HARD BLOCK/);
365
383
  assert.match(blocked.reason!, /gsd_save_gate_result/);
384
+ assert.strictEqual(blocked.displayReason, GSD_PHASE_SCOPE_DISPLAY_REASON);
366
385
  assert.strictEqual(isDeterministicPolicyError(blocked.reason!), true);
367
386
  });
368
387
 
@@ -469,6 +488,27 @@ test('verification-mode: run-uat still blocks subagent dispatch', () => {
469
488
  assert.match(r.reason!, /subagent dispatch is not permitted/);
470
489
  });
471
490
 
491
+ test('verification-mode: run-uat allows explicit UAT specialist subagents', () => {
492
+ for (const agent of ['mnemo', 'scout', 'reviewer', 'tester']) {
493
+ const r = shouldBlockPlanningUnit('subagent', '', BASE, 'run-uat', VERIFICATION_UAT, [agent]);
494
+ assert.strictEqual(r.block, false, `expected ${agent} to be allowed: ${r.reason}`);
495
+ }
496
+ });
497
+
498
+ test('verification-mode: run-uat blocks implementation-tier subagents', () => {
499
+ const r = shouldBlockPlanningUnit('subagent', '', BASE, 'run-uat', VERIFICATION_UAT, ['worker']);
500
+ assert.strictEqual(r.block, true);
501
+ assert.match(r.reason!, /"worker"/);
502
+ assert.match(r.reason!, /read-only specialists/);
503
+ });
504
+
505
+ test('verification-mode: run-uat blocks read-only specialists not listed by policy', () => {
506
+ const r = shouldBlockPlanningUnit('subagent', '', BASE, 'run-uat', VERIFICATION_UAT, ['security']);
507
+ assert.strictEqual(r.block, true);
508
+ assert.match(r.reason!, /"security"/);
509
+ assert.match(r.reason!, /ToolsPolicy\.allowedSubagents|permitted agents for this unit/);
510
+ });
511
+
472
512
  // ─── read-only mode ───────────────────────────────────────────────────────
473
513
 
474
514
  test('read-only: blocks any edit even to .gsd/', () => {
@@ -8,12 +8,14 @@ import {
8
8
  type ToolsPolicy,
9
9
  } from "./unit-context-manifest.js";
10
10
  import { getRequiredWorkflowToolsForAutoUnit } from "./workflow-mcp.js";
11
+ import { getUnitToolSurfaceContract } from "./unit-tool-contracts.js";
11
12
 
12
13
  export interface UnitToolContract {
13
14
  unitType: string;
14
15
  contextMode: ContextModePolicy;
15
16
  toolsPolicy: ToolsPolicy;
16
17
  requiredWorkflowTools: readonly string[];
18
+ forbiddenWorkflowTools: readonly { name: string; reason: string }[];
17
19
  promptObligations: readonly string[];
18
20
  validationRules: readonly string[];
19
21
  closeoutTools: readonly string[];
@@ -30,6 +32,7 @@ export type ToolContractResult =
30
32
 
31
33
  export function compileUnitToolContract(unitType: string): ToolContractResult {
32
34
  const manifest = resolveManifest(unitType);
35
+ const surfaceContract = getUnitToolSurfaceContract(unitType);
33
36
  if (!manifest) {
34
37
  return {
35
38
  ok: false,
@@ -39,6 +42,8 @@ export function compileUnitToolContract(unitType: string): ToolContractResult {
39
42
  }
40
43
 
41
44
  const requiredWorkflowTools = getRequiredWorkflowToolsForAutoUnit(unitType);
45
+ const forbiddenWorkflowTools = Object.entries(surfaceContract?.forbiddenGsdTools ?? {})
46
+ .map(([name, reason]) => ({ name, reason }));
42
47
  const closeoutTools = requiredWorkflowTools.filter((tool) =>
43
48
  /^gsd_(?:task|slice|milestone|complete|validate|save|summary)/.test(tool),
44
49
  );
@@ -58,6 +63,7 @@ export function compileUnitToolContract(unitType: string): ToolContractResult {
58
63
  contextMode: manifest.contextMode,
59
64
  toolsPolicy: manifest.tools,
60
65
  requiredWorkflowTools,
66
+ forbiddenWorkflowTools,
61
67
  promptObligations: [
62
68
  `context-mode:${manifest.contextMode}`,
63
69
  `tools-policy:${manifest.tools.mode}`,