@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
@@ -3,13 +3,13 @@
3
3
  import { ensureDbOpen } from "../bootstrap/dynamic-tools.js";
4
4
  import { sanitizeCompleteMilestoneParams } from "../bootstrap/sanitize-complete-milestone.js";
5
5
  import { loadWriteGateSnapshot, shouldBlockContextArtifactSaveInSnapshot, shouldBlockRootArtifactSaveInSnapshot } from "../bootstrap/write-gate.js";
6
- import { getActiveRequirements, insertMilestone, getMilestone, getSliceStatusSummary, getSliceTaskCounts, readTransaction, saveGateResult, } from "../gsd-db.js";
6
+ import { getActiveRequirements, insertMilestone, getMilestone, getSliceStatusSummary, getSliceTaskCounts, insertGateRun, readTransaction, saveGateResult, upsertQualityGate, } from "../gsd-db.js";
7
7
  import { GATE_REGISTRY } from "../gate-registry.js";
8
8
  import { generateRequirementsMd, saveArtifactToDb } from "../db-writer.js";
9
9
  import { clearPathCache, resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile } from "../paths.js";
10
10
  import { saveFile, clearParseCache } from "../files.js";
11
- import { unlinkSync } from "node:fs";
12
- import { join } from "node:path";
11
+ import { existsSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
12
+ import { isAbsolute, join, resolve } from "node:path";
13
13
  import { handleCompleteMilestone } from "./complete-milestone.js";
14
14
  import { handleCompleteTask } from "./complete-task.js";
15
15
  import { handleCompleteSlice } from "./complete-slice.js";
@@ -26,6 +26,7 @@ import { invalidateStateCache } from "../state.js";
26
26
  import { loadEffectiveGSDPreferences } from "../preferences.js";
27
27
  import { parseProject } from "../schemas/parsers.js";
28
28
  import { getAutoRuntimeSnapshot } from "../auto-runtime-state.js";
29
+ import { canonicalWorkflowToolName, parseMcpToolName, RUN_UAT_FORBIDDEN_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES, } from "../tool-presentation-plan.js";
29
30
  export const SUPPORTED_SUMMARY_ARTIFACT_TYPES = [
30
31
  "SUMMARY",
31
32
  "RESEARCH",
@@ -333,6 +334,28 @@ export async function executeTaskComplete(params, basePath = process.cwd()) {
333
334
  isError: true,
334
335
  };
335
336
  }
337
+ if (result.escalation) {
338
+ const recommended = result.escalation.options.find((option) => option.id === result.escalation?.recommendation);
339
+ const optionIds = result.escalation.options.map((option) => option.id).join("|");
340
+ return {
341
+ content: [{
342
+ type: "text",
343
+ text: [
344
+ `Task completed with escalation decision required: ${result.escalation.question}`,
345
+ `Recommendation: ${result.escalation.recommendation}${recommended ? ` (${recommended.label})` : ""} — ${result.escalation.recommendationRationale}`,
346
+ `Resolve with: /gsd escalate resolve ${result.taskId} <${optionIds}|accept|reject-blocker> [rationale...]`,
347
+ ].join("\n"),
348
+ }],
349
+ details: {
350
+ operation: "complete_task",
351
+ taskId: result.taskId,
352
+ sliceId: result.sliceId,
353
+ milestoneId: result.milestoneId,
354
+ summaryPath: result.summaryPath,
355
+ escalation: result.escalation,
356
+ },
357
+ };
358
+ }
336
359
  return {
337
360
  content: [{ type: "text", text: `Completed task ${result.taskId} (${result.sliceId}/${result.milestoneId})` }],
338
361
  details: {
@@ -775,6 +798,383 @@ export async function executeSaveGateResult(params, basePath = process.cwd()) {
775
798
  };
776
799
  }
777
800
  }
801
+ function errorResult(operation, message, error) {
802
+ return {
803
+ content: [{ type: "text", text: `Error: ${message}` }],
804
+ details: { operation, error },
805
+ isError: true,
806
+ };
807
+ }
808
+ function isNonEmptyString(value) {
809
+ return typeof value === "string" && value.trim().length > 0;
810
+ }
811
+ function ensureUatRequiredFields(params) {
812
+ if (!isNonEmptyString(params.milestoneId))
813
+ return "milestoneId is required";
814
+ if (!isNonEmptyString(params.sliceId))
815
+ return "sliceId is required";
816
+ if (!isNonEmptyString(params.uatType))
817
+ return "uatType is required";
818
+ if (!["PASS", "FAIL", "PARTIAL"].includes(params.verdict))
819
+ return "verdict must be PASS, FAIL, or PARTIAL";
820
+ if (!Array.isArray(params.checks) || params.checks.length === 0)
821
+ return "checks must contain at least one UAT check";
822
+ if (!params.presentation || !Array.isArray(params.presentation.presentedTools))
823
+ return "presentation.presentedTools is required";
824
+ if (!Array.isArray(params.presentation.blockedTools))
825
+ return "presentation.blockedTools is required";
826
+ return null;
827
+ }
828
+ function approvedEvidenceRoots(basePath) {
829
+ const contract = resolveGsdPathContract(basePath);
830
+ return [contract.worktreeGsd, contract.projectGsd].filter((root) => typeof root === "string");
831
+ }
832
+ function approvedBrowserArtifactRoots(basePath) {
833
+ const contract = resolveGsdPathContract(basePath);
834
+ const roots = [contract.workRoot, contract.projectRoot].map((root) => join(root, ".artifacts", "browser"));
835
+ return [...new Set(roots)];
836
+ }
837
+ function pathStartsWithin(parent, target) {
838
+ const normalizedParent = parent.replace(/\\/g, "/").replace(/\/+$/, "");
839
+ const normalizedTarget = target.replace(/\\/g, "/").replace(/\/+$/, "");
840
+ return normalizedTarget === normalizedParent || normalizedTarget.startsWith(`${normalizedParent}/`);
841
+ }
842
+ function pushUnique(paths, candidate) {
843
+ if (!paths.includes(candidate))
844
+ paths.push(candidate);
845
+ }
846
+ function execMetaPathCandidates(basePath, ref) {
847
+ const trimmed = ref.trim();
848
+ const candidates = [];
849
+ const execDirs = approvedEvidenceRoots(basePath).map((root) => join(root, "exec"));
850
+ const normalizedRef = trimmed.replace(/\\/g, "/");
851
+ const pathLike = normalizedRef.endsWith(".meta.json") || normalizedRef.includes("/.gsd/exec/");
852
+ if (pathLike) {
853
+ const rawPath = isAbsolute(trimmed) ? resolve(trimmed) : resolve(basePath, trimmed);
854
+ pushUnique(candidates, rawPath);
855
+ const relativeExecMarker = ".gsd/exec/";
856
+ const markerIndex = normalizedRef.indexOf(relativeExecMarker);
857
+ if (markerIndex >= 0) {
858
+ const execRelative = normalizedRef.slice(markerIndex + relativeExecMarker.length);
859
+ for (const execDir of execDirs) {
860
+ pushUnique(candidates, join(execDir, execRelative));
861
+ }
862
+ }
863
+ return candidates.filter((candidate) => execDirs.some((execDir) => pathStartsWithin(execDir, candidate)));
864
+ }
865
+ for (const execDir of execDirs) {
866
+ pushUnique(candidates, join(execDir, `${trimmed}.meta.json`));
867
+ }
868
+ return candidates;
869
+ }
870
+ function resolveExecMetaPath(basePath, ref) {
871
+ for (const candidate of execMetaPathCandidates(basePath, ref)) {
872
+ if (existsSync(candidate))
873
+ return candidate;
874
+ }
875
+ return null;
876
+ }
877
+ function evidencePathIsApproved(basePath, ref) {
878
+ const normalizedRef = ref.replace(/\\/g, "/");
879
+ if (normalizedRef.startsWith(".gsd/exec/") || normalizedRef.startsWith(".gsd/uat/"))
880
+ return true;
881
+ if (normalizedRef.startsWith(".artifacts/browser/")) {
882
+ const resolvedRef = resolve(basePath, ref);
883
+ return approvedBrowserArtifactRoots(basePath).some((root) => pathStartsWithin(root, resolvedRef));
884
+ }
885
+ const gsdEvidenceApproved = approvedEvidenceRoots(basePath).some((root) => {
886
+ return pathStartsWithin(join(root, "exec"), ref) || pathStartsWithin(join(root, "uat"), ref);
887
+ });
888
+ if (gsdEvidenceApproved)
889
+ return true;
890
+ return approvedBrowserArtifactRoots(basePath).some((root) => pathStartsWithin(root, ref));
891
+ }
892
+ function validateEvidenceRef(basePath, evidence) {
893
+ if (!isNonEmptyString(evidence.ref))
894
+ return "evidence.ref is required";
895
+ if (evidence.kind === "gsd_uat_exec" || evidence.kind === "gsd_exec") {
896
+ const path = resolveExecMetaPath(basePath, evidence.ref.trim());
897
+ if (!path)
898
+ return `missing gsd_exec metadata for evidence id "${evidence.ref}"`;
899
+ if (evidence.kind === "gsd_uat_exec") {
900
+ try {
901
+ const meta = JSON.parse(readFileSync(path, "utf-8"));
902
+ if (meta.metadata?.kind !== "uat_exec")
903
+ return `evidence id "${evidence.ref}" is not typed as uat_exec`;
904
+ }
905
+ catch {
906
+ return `invalid gsd_exec metadata JSON for evidence id "${evidence.ref}"`;
907
+ }
908
+ }
909
+ return null;
910
+ }
911
+ if (evidence.kind === "url") {
912
+ try {
913
+ const parsed = new URL(evidence.ref);
914
+ return parsed.protocol === "http:" || parsed.protocol === "https:"
915
+ ? null
916
+ : `invalid URL evidence ref "${evidence.ref}"`;
917
+ }
918
+ catch {
919
+ return `invalid URL evidence ref "${evidence.ref}"`;
920
+ }
921
+ }
922
+ return evidencePathIsApproved(basePath, evidence.ref)
923
+ ? null
924
+ : `evidence ref "${evidence.ref}" is outside approved evidence locations`;
925
+ }
926
+ function validateUatChecks(basePath, params) {
927
+ for (const check of params.checks) {
928
+ if (!isNonEmptyString(check.id))
929
+ return "every check must have a non-empty id";
930
+ if (!isNonEmptyString(check.description))
931
+ return `check ${check.id} must have a description`;
932
+ if (!["artifact", "runtime", "browser", "human-follow-up"].includes(check.mode)) {
933
+ return `check ${check.id} has invalid mode "${check.mode}"`;
934
+ }
935
+ if (!["PASS", "FAIL", "NEEDS-HUMAN"].includes(check.result)) {
936
+ return `check ${check.id} has invalid result "${check.result}"`;
937
+ }
938
+ if (check.result === "PASS" || check.result === "FAIL") {
939
+ if (!Array.isArray(check.evidence) || check.evidence.length === 0) {
940
+ return `check ${check.id} is ${check.result} but has no objective evidence`;
941
+ }
942
+ for (const evidence of check.evidence) {
943
+ const error = validateEvidenceRef(basePath, evidence);
944
+ if (error)
945
+ return `check ${check.id}: ${error}`;
946
+ }
947
+ }
948
+ else if (!isNonEmptyString(check.notes)) {
949
+ return `check ${check.id} is NEEDS-HUMAN but has no manual instruction or reason`;
950
+ }
951
+ }
952
+ return null;
953
+ }
954
+ function validateUatMode(params) {
955
+ const modes = new Set(params.checks.map((check) => check.mode));
956
+ const hasHuman = params.checks.some((check) => check.result === "NEEDS-HUMAN");
957
+ if (params.uatType === "artifact-driven" && hasHuman && params.verdict === "PASS") {
958
+ return "artifact-driven UAT cannot PASS with human-only checks";
959
+ }
960
+ if (hasHuman &&
961
+ params.verdict === "PASS" &&
962
+ !["human-experience", "mixed", "live-runtime"].includes(params.uatType) &&
963
+ !params.checks.every((check) => check.result !== "NEEDS-HUMAN" || check.nonAutomatable === true)) {
964
+ return "NEEDS-HUMAN checks can only coexist with PASS for human-experience, mixed, live-runtime, or explicitly non-automatable checks";
965
+ }
966
+ if (params.uatType === "runtime-executable" && !modes.has("runtime")) {
967
+ return "runtime-executable UAT requires at least one runtime check";
968
+ }
969
+ if (params.uatType === "browser-executable" && !modes.has("browser")) {
970
+ return "browser-executable UAT requires at least one browser check";
971
+ }
972
+ if (params.uatType === "live-runtime" && !modes.has("runtime") && !modes.has("browser")) {
973
+ return "live-runtime UAT requires runtime or browser evidence";
974
+ }
975
+ return null;
976
+ }
977
+ function quoteToolNames(toolNames) {
978
+ return toolNames.map((toolName) => `"${toolName}"`).join(", ");
979
+ }
980
+ function validateCanonicalPresentation(params) {
981
+ const aliasHints = {
982
+ gsd_save_summary: "gsd_summary_save",
983
+ gsd_complete_task: "gsd_task_complete",
984
+ gsd_complete_slice: "gsd_slice_complete",
985
+ gsd_milestone_complete: "gsd_complete_milestone",
986
+ };
987
+ const errors = [];
988
+ for (const toolName of params.presentation.presentedTools) {
989
+ const baseName = parseMcpToolName(toolName)?.tool ?? toolName;
990
+ const canonical = aliasHints[baseName];
991
+ if (canonical)
992
+ errors.push(`presentation tool "${toolName}" uses an alias; use canonical "${canonical}"`);
993
+ }
994
+ const presentedCanonical = new Set(params.presentation.presentedTools.map((toolName) => canonicalWorkflowToolName(parseMcpToolName(toolName)?.tool ?? toolName)));
995
+ const missingRequiredTools = RUN_UAT_WORKFLOW_TOOL_NAMES.filter((requiredTool) => !presentedCanonical.has(requiredTool));
996
+ if (missingRequiredTools.length === 1) {
997
+ errors.push(`presentation is missing required UAT tool "${missingRequiredTools[0]}"`);
998
+ }
999
+ else if (missingRequiredTools.length > 1) {
1000
+ errors.push(`presentation is missing required UAT tools ${quoteToolNames(missingRequiredTools)}`);
1001
+ }
1002
+ const forbiddenCanonical = new Set(RUN_UAT_FORBIDDEN_TOOL_NAMES
1003
+ .filter((toolName) => !toolName.includes("*"))
1004
+ .map((toolName) => canonicalWorkflowToolName(parseMcpToolName(toolName)?.tool ?? toolName)));
1005
+ const forbiddenPresentedTools = [];
1006
+ for (const toolName of params.presentation.presentedTools) {
1007
+ const canonical = canonicalWorkflowToolName(parseMcpToolName(toolName)?.tool ?? toolName);
1008
+ if (toolName === "mcp__gsd-workflow__*" || forbiddenCanonical.has(canonical)) {
1009
+ forbiddenPresentedTools.push(toolName);
1010
+ }
1011
+ }
1012
+ if (forbiddenPresentedTools.length === 1) {
1013
+ errors.push(`presentation includes forbidden run-uat tool "${forbiddenPresentedTools[0]}"`);
1014
+ }
1015
+ else if (forbiddenPresentedTools.length > 1) {
1016
+ errors.push(`presentation includes forbidden run-uat tools ${quoteToolNames(forbiddenPresentedTools)}`);
1017
+ }
1018
+ const blockedCanonical = new Set(params.presentation.blockedTools.map((entry) => canonicalWorkflowToolName(parseMcpToolName(entry.name)?.tool ?? entry.name)));
1019
+ const missingBlockedTools = ["gsd_exec", "gsd_summary_save", "gsd_save_gate_result"].filter((blockedTool) => !blockedCanonical.has(blockedTool));
1020
+ if (missingBlockedTools.length === 1) {
1021
+ errors.push(`presentation must record "${missingBlockedTools[0]}" as blocked during run-uat`);
1022
+ }
1023
+ else if (missingBlockedTools.length > 1) {
1024
+ errors.push(`presentation must record ${quoteToolNames(missingBlockedTools)} as blocked during run-uat`);
1025
+ }
1026
+ return errors.length > 0 ? errors.join("; ") : null;
1027
+ }
1028
+ function nextUatAttempt(basePath, milestoneId, sliceId) {
1029
+ const contract = resolveGsdPathContract(basePath);
1030
+ const dir = join(contract.projectGsd, "uat", milestoneId, sliceId);
1031
+ if (!existsSync(dir))
1032
+ return 1;
1033
+ let max = 0;
1034
+ for (const entry of readdirSync(dir)) {
1035
+ const match = /^attempt-(\d+)\.json$/.exec(entry);
1036
+ if (match)
1037
+ max = Math.max(max, Number(match[1]));
1038
+ }
1039
+ return max + 1;
1040
+ }
1041
+ function escapeMarkdownTableCell(value) {
1042
+ return String(value ?? "")
1043
+ .replace(/[\\|]/g, (char) => `\\${char}`)
1044
+ .replace(/\r?\n/g, "<br>");
1045
+ }
1046
+ function renderUatAssessment(params, attempt, gateVerdict) {
1047
+ const lines = [
1048
+ "---",
1049
+ `sliceId: ${params.sliceId}`,
1050
+ `uatType: ${params.uatType}`,
1051
+ `verdict: ${params.verdict}`,
1052
+ `attempt: ${attempt}`,
1053
+ `date: ${new Date().toISOString()}`,
1054
+ "---",
1055
+ "",
1056
+ `# UAT Result - ${params.sliceId}`,
1057
+ "",
1058
+ "## Checks",
1059
+ "",
1060
+ "| Check | Mode | Result | Evidence | Notes |",
1061
+ "|-------|------|--------|----------|-------|",
1062
+ ...params.checks.map((check) => {
1063
+ const evidence = (check.evidence ?? []).map((entry) => `${entry.kind}:${entry.ref}`).join("<br>") || "-";
1064
+ return `| ${escapeMarkdownTableCell(check.description)} | ${escapeMarkdownTableCell(check.mode)} | ${escapeMarkdownTableCell(check.result)} | ${escapeMarkdownTableCell(evidence)} | ${escapeMarkdownTableCell(check.notes)} |`;
1065
+ }),
1066
+ "",
1067
+ "## Overall Verdict",
1068
+ "",
1069
+ `${params.verdict} - ${params.notes ?? "UAT result saved."}`,
1070
+ "",
1071
+ "## Tool Presentation",
1072
+ "",
1073
+ "```json",
1074
+ JSON.stringify(params.presentation, null, 2),
1075
+ "```",
1076
+ "",
1077
+ "## Gate",
1078
+ "",
1079
+ `Aggregate UAT gate saved as ${gateVerdict}.`,
1080
+ ];
1081
+ return `${lines.join("\n")}\n`;
1082
+ }
1083
+ async function saveUatAttemptArtifact(basePath, params, attempt) {
1084
+ const contract = resolveGsdPathContract(basePath);
1085
+ const relativePath = `uat/${params.milestoneId}/${params.sliceId}/attempt-${attempt}.json`;
1086
+ await saveFile(join(contract.projectGsd, relativePath), `${JSON.stringify({ ...params, attempt }, null, 2)}\n`);
1087
+ return relativePath;
1088
+ }
1089
+ export async function executeUatResultSave(params, basePath = process.cwd()) {
1090
+ const dbAvailable = await ensureDbOpen(basePath);
1091
+ if (!dbAvailable)
1092
+ return errorResult("save_uat_result", "GSD database is not available.", "db_unavailable");
1093
+ const requiredError = ensureUatRequiredFields(params);
1094
+ if (requiredError)
1095
+ return errorResult("save_uat_result", requiredError, "invalid_params");
1096
+ const presentationError = validateCanonicalPresentation(params);
1097
+ if (presentationError)
1098
+ return errorResult("save_uat_result", presentationError, "alias_tool_name");
1099
+ const checkError = validateUatChecks(basePath, params);
1100
+ if (checkError)
1101
+ return errorResult("save_uat_result", checkError, "invalid_evidence");
1102
+ const modeError = validateUatMode(params);
1103
+ if (modeError)
1104
+ return errorResult("save_uat_result", modeError, "uat_mode_mismatch");
1105
+ try {
1106
+ const attempt = params.attempt === "auto" || params.attempt === undefined
1107
+ ? nextUatAttempt(basePath, params.milestoneId, params.sliceId)
1108
+ : typeof params.attempt === "string"
1109
+ ? Number.parseInt(params.attempt, 10)
1110
+ : params.attempt;
1111
+ if (!Number.isInteger(attempt) || attempt < 1) {
1112
+ return errorResult("save_uat_result", "attempt must be a positive integer or auto", "invalid_attempt");
1113
+ }
1114
+ const gateVerdict = params.verdict === "PASS" ? "pass" : "flag";
1115
+ const rationale = params.notes ?? `UAT ${params.verdict} for ${params.sliceId}.`;
1116
+ const assessment = renderUatAssessment(params, attempt, gateVerdict);
1117
+ const summary = await executeSummarySave({
1118
+ milestone_id: params.milestoneId,
1119
+ slice_id: params.sliceId,
1120
+ artifact_type: "ASSESSMENT",
1121
+ content: assessment,
1122
+ }, basePath);
1123
+ if (summary.isError)
1124
+ return summary;
1125
+ const attemptPath = await saveUatAttemptArtifact(basePath, params, attempt);
1126
+ const evaluatedAt = new Date().toISOString();
1127
+ upsertQualityGate({
1128
+ milestoneId: params.milestoneId,
1129
+ sliceId: params.sliceId,
1130
+ gateId: "UAT",
1131
+ scope: "slice",
1132
+ taskId: "",
1133
+ status: "complete",
1134
+ verdict: gateVerdict,
1135
+ rationale,
1136
+ findings: assessment,
1137
+ evaluatedAt,
1138
+ });
1139
+ insertGateRun({
1140
+ traceId: `uat:${params.milestoneId}:${params.sliceId}`,
1141
+ turnId: `uat:${params.sliceId}:attempt-${attempt}`,
1142
+ gateId: "UAT",
1143
+ gateType: "uat",
1144
+ unitType: "run-uat",
1145
+ unitId: `run-uat:${params.milestoneId}/${params.sliceId}`,
1146
+ milestoneId: params.milestoneId,
1147
+ sliceId: params.sliceId,
1148
+ outcome: params.verdict === "PASS" ? "pass" : "fail",
1149
+ failureClass: params.verdict === "PASS" ? "none" : "verification",
1150
+ rationale,
1151
+ findings: assessment,
1152
+ attempt,
1153
+ maxAttempts: attempt,
1154
+ retryable: params.verdict !== "PASS",
1155
+ evaluatedAt,
1156
+ });
1157
+ invalidateStateCache();
1158
+ return {
1159
+ content: [{ type: "text", text: `UAT result saved for ${params.milestoneId}/${params.sliceId}: ${params.verdict}` }],
1160
+ details: {
1161
+ operation: "save_uat_result",
1162
+ milestoneId: params.milestoneId,
1163
+ sliceId: params.sliceId,
1164
+ verdict: params.verdict,
1165
+ gateVerdict,
1166
+ attempt,
1167
+ attemptPath,
1168
+ recommendedNextUnit: params.verdict === "PASS" ? null : "reactive-execute",
1169
+ },
1170
+ };
1171
+ }
1172
+ catch (err) {
1173
+ const msg = err instanceof Error ? err.message : String(err);
1174
+ logError("tool", `gsd_uat_result_save failed: ${msg}`, { tool: "gsd_uat_result_save", error: String(err) });
1175
+ return errorResult("save_uat_result", `saving UAT result failed: ${msg}`, msg);
1176
+ }
1177
+ }
778
1178
  export async function executePlanMilestone(params, basePath = process.cwd()) {
779
1179
  const dbAvailable = await ensureDbOpen(basePath);
780
1180
  if (!dbAvailable) {
@@ -83,6 +83,10 @@ const COMMON_BUDGET_SMALL = 250_000; // ~65K tokens
83
83
  const TOOLS_ALL = { mode: "all" };
84
84
  const TOOLS_PLANNING = { mode: "planning" };
85
85
  const TOOLS_VERIFICATION = { mode: "verification" };
86
+ const TOOLS_VERIFICATION_DISPATCH_UAT = {
87
+ mode: "verification",
88
+ allowedSubagents: ["mnemo", "scout", "reviewer", "tester"],
89
+ };
86
90
  // Like TOOLS_PLANNING but permits dispatch to read-only recon/planning
87
91
  // specialists. Runtime-enforced by write-gate.ts before the subagent tool runs.
88
92
  const TOOLS_PLANNING_DISPATCH_RECON = {
@@ -372,7 +376,7 @@ export const UNIT_MANIFESTS = {
372
376
  codebaseMap: false,
373
377
  preferences: "active-only",
374
378
  contextMode: "verification",
375
- tools: TOOLS_VERIFICATION,
379
+ tools: TOOLS_VERIFICATION_DISPATCH_UAT,
376
380
  artifacts: {
377
381
  inline: ["slice-uat"],
378
382
  excerpt: ["slice-summary"],
@@ -551,9 +555,10 @@ export function compileSubagentPermissionContract(policy) {
551
555
  if (policy.mode === "all") {
552
556
  return { allowed: true, allowedSubagents: ["*"], toolsMode: policy.mode };
553
557
  }
554
- if (policy.mode === "planning-dispatch") {
558
+ if ((policy.mode === "planning-dispatch" || policy.mode === "verification") &&
559
+ Array.isArray(policy.allowedSubagents)) {
555
560
  return {
556
- allowed: true,
561
+ allowed: policy.allowedSubagents.length > 0,
557
562
  allowedSubagents: [...policy.allowedSubagents],
558
563
  toolsMode: policy.mode,
559
564
  };
@@ -8,6 +8,8 @@ import { deriveState } from "./state.js";
8
8
  import { detectWorktreeName } from "./worktree.js";
9
9
  const VALIDATION_BLOCK_RE = /milestone validation returned needs-(?:attention|remediation)|validation verdict is needs-(?:attention|remediation)/i;
10
10
  const VALIDATION_SAFE_DISPATCH_COMMANDS = new Set([
11
+ "reassess",
12
+ "reassess-roadmap",
11
13
  "validate",
12
14
  "validate-milestone",
13
15
  ]);
@@ -5,7 +5,62 @@
5
5
  * (e.g. `passed` → `pass`) are applied consistently across the codebase.
6
6
  */
7
7
  import { extractUatType } from "./files.js";
8
+ import { splitFrontmatter, parseFrontmatterMap } from "../shared/frontmatter.js";
9
+ import { parse as parseYaml } from "yaml";
10
+ function normalizeVerdict(value) {
11
+ if (typeof value !== "string")
12
+ return undefined;
13
+ let verdict = value.trim().toLowerCase();
14
+ if (!verdict)
15
+ return undefined;
16
+ if (verdict === "passed")
17
+ verdict = "pass";
18
+ return verdict;
19
+ }
20
+ function getCaseInsensitive(obj, key) {
21
+ const lowerKey = key.toLowerCase();
22
+ for (const [candidate, value] of Object.entries(obj)) {
23
+ if (candidate.toLowerCase() === lowerKey)
24
+ return value;
25
+ }
26
+ return undefined;
27
+ }
8
28
  // ── Verdict extraction ──────────────────────────────────────────────────
29
+ /**
30
+ * Extract and normalize the frontmatter `verdict` value.
31
+ *
32
+ * Supports both top-level `verdict` and the hook outcome shape
33
+ * `outcome.verdict`. Returns `undefined` when frontmatter is absent or has no
34
+ * verdict field.
35
+ */
36
+ export function extractFrontmatterVerdict(content) {
37
+ const [frontmatterLines] = splitFrontmatter(content);
38
+ if (!frontmatterLines)
39
+ return undefined;
40
+ try {
41
+ const parsed = parseYaml(frontmatterLines.join("\n"));
42
+ if (parsed && typeof parsed === "object") {
43
+ const root = parsed;
44
+ const topLevel = normalizeVerdict(getCaseInsensitive(root, "verdict"));
45
+ if (topLevel)
46
+ return topLevel;
47
+ const outcome = getCaseInsensitive(root, "outcome");
48
+ if (outcome && typeof outcome === "object") {
49
+ const nested = normalizeVerdict(getCaseInsensitive(outcome, "verdict"));
50
+ if (nested)
51
+ return nested;
52
+ }
53
+ }
54
+ }
55
+ catch {
56
+ // Fall through to the permissive parser used by legacy frontmatter paths.
57
+ }
58
+ const frontmatter = parseFrontmatterMap(frontmatterLines);
59
+ const topLevel = normalizeVerdict(getCaseInsensitive(frontmatter, "verdict"));
60
+ if (topLevel)
61
+ return topLevel;
62
+ return undefined;
63
+ }
9
64
  /**
10
65
  * Extract and normalize the `verdict` value from YAML frontmatter.
11
66
  *
@@ -17,25 +72,14 @@ import { extractUatType } from "./files.js";
17
72
  */
18
73
  export function extractVerdict(content) {
19
74
  // Primary: YAML frontmatter verdict (canonical format)
20
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
21
- if (fmMatch) {
22
- const verdictMatch = fmMatch[1].match(/verdict:\s*([\w-]+)/i);
23
- if (verdictMatch) {
24
- let v = verdictMatch[1].toLowerCase();
25
- if (v === "passed")
26
- v = "pass";
27
- return v;
28
- }
29
- return undefined;
30
- }
75
+ const [frontmatterLines] = splitFrontmatter(content);
76
+ if (frontmatterLines)
77
+ return extractFrontmatterVerdict(content);
31
78
  // Fallback: detect verdict in markdown body (LLM manual writes, #2960).
32
79
  // Matches patterns like: **Verdict:** PASS, **Verdict:** ✅ PASS, **Verdict** needs-remediation
33
80
  const bodyMatch = content.match(/\*\*Verdict:?\*\*\s*(?:✅\s*)?(\w[\w-]*)/i);
34
81
  if (bodyMatch) {
35
- let v = bodyMatch[1].toLowerCase();
36
- if (v === "passed")
37
- v = "pass";
38
- return v;
82
+ return normalizeVerdict(bodyMatch[1]);
39
83
  }
40
84
  return undefined;
41
85
  }
@@ -246,6 +246,76 @@ function hasUnsafeShellSyntax(cmd) {
246
246
  }
247
247
  return false;
248
248
  }
249
+ function splitLeadingShellWords(cmd) {
250
+ const words = [];
251
+ let current = "";
252
+ let inSingle = false;
253
+ let inDouble = false;
254
+ let escaped = false;
255
+ for (let i = 0; i < cmd.length; i += 1) {
256
+ const ch = cmd[i];
257
+ if (escaped) {
258
+ current += ch;
259
+ escaped = false;
260
+ continue;
261
+ }
262
+ if (ch === "\\" && !inSingle) {
263
+ escaped = true;
264
+ continue;
265
+ }
266
+ if (ch === "'" && !inDouble) {
267
+ inSingle = !inSingle;
268
+ continue;
269
+ }
270
+ if (ch === "\"" && !inSingle) {
271
+ inDouble = !inDouble;
272
+ continue;
273
+ }
274
+ if (!inSingle && !inDouble) {
275
+ if (/\s/.test(ch)) {
276
+ if (current) {
277
+ words.push(current);
278
+ current = "";
279
+ }
280
+ continue;
281
+ }
282
+ if ([";", "|", "&", "<", ">"].includes(ch)) {
283
+ break;
284
+ }
285
+ }
286
+ current += ch;
287
+ }
288
+ if (current) {
289
+ words.push(current);
290
+ }
291
+ return words;
292
+ }
293
+ function isCountFlag(token) {
294
+ return (token === "--count" ||
295
+ token.startsWith("--count=") ||
296
+ token === "--count-matches" ||
297
+ token.startsWith("--count-matches=") ||
298
+ /^-[A-Za-z]*c[A-Za-z]*$/.test(token));
299
+ }
300
+ function countSearchWarning(command, exitCode) {
301
+ if (exitCode !== 1)
302
+ return null;
303
+ const trimmed = command.trim();
304
+ if (trimmed.startsWith("!"))
305
+ return null;
306
+ const [tool, ...args] = splitLeadingShellWords(trimmed);
307
+ if (tool !== "grep" && tool !== "rg")
308
+ return null;
309
+ if (!args.some(isCountFlag))
310
+ return null;
311
+ return `verification-gate: warning: '${tool} -c' returns exit 1 when count=0; for absence checks use '! ${tool} -q ...' instead.`;
312
+ }
313
+ function appendStderrWarning(stderr, warning) {
314
+ if (!warning)
315
+ return stderr;
316
+ const trimmed = stderr.trimEnd();
317
+ return trimmed ? `${trimmed}\n${warning}` : warning;
318
+ }
249
319
  /**
250
320
  * Known executable first-tokens that are safe to run.
251
321
  * Lowercase commands, common build/test tools, and npm/yarn/pnpm invocations.
@@ -411,11 +481,12 @@ export function runVerificationGate(options) {
411
481
  exitCode = result.status ?? 1;
412
482
  stderr = truncate(result.stderr, MAX_OUTPUT_BYTES);
413
483
  }
484
+ const warning = countSearchWarning(command, exitCode);
414
485
  checks.push({
415
486
  command,
416
487
  exitCode,
417
488
  stdout: truncate(result.stdout, MAX_OUTPUT_BYTES),
418
- stderr,
489
+ stderr: truncate(appendStderrWarning(stderr, warning), MAX_OUTPUT_BYTES),
419
490
  durationMs,
420
491
  });
421
492
  }
@@ -33,6 +33,8 @@ export function shouldAutoPrepareWorkflowMcp(ctx) {
33
33
  const authMode = getAuthModeSafe(ctx, provider);
34
34
  if (provider !== "claude-code")
35
35
  return false;
36
+ if (authMode === undefined)
37
+ return true;
36
38
  return usesWorkflowMcpTransport(authMode, baseUrl) || authMode === "externalCli";
37
39
  }
38
40
  export function prepareWorkflowMcpForProject(ctx, projectRoot, modelOverride) {
@@ -42,7 +44,7 @@ export function prepareWorkflowMcpForProject(ctx, projectRoot, modelOverride) {
42
44
  try {
43
45
  const result = ensureProjectWorkflowMcpConfig(projectRoot);
44
46
  if (result.status !== "unchanged") {
45
- prepCtx.ui?.notify?.(`Claude Code MCP prepared at ${result.configPath}`, "info");
47
+ prepCtx.ui?.notify?.(`GSD MCP Server Prepared at ${result.configPath}`, "info");
46
48
  }
47
49
  return result;
48
50
  }