@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
@@ -1,12 +1,11 @@
1
- import { createHash } from "node:crypto";
2
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
- import { createRequire } from "node:module";
4
- import { basename, resolve } from "node:path";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
5
3
  import { fileURLToPath } from "node:url";
4
+ import { GSD_BROWSER_MCP_SERVER_NAME, resolveBundledGsdBrowserCliPath, resolveGsdBrowserMcpLaunchConfig, } from "../shared/gsd-browser-cli.js";
6
5
  import { assertSafeDirectory } from "./validate-directory.js";
7
6
  import { detectWorkflowMcpLaunchConfig } from "./workflow-mcp.js";
8
7
  export const GSD_WORKFLOW_MCP_SERVER_NAME = "gsd-workflow";
9
- export const GSD_BROWSER_MCP_SERVER_NAME = "gsd-browser";
8
+ export { GSD_BROWSER_MCP_SERVER_NAME, resolveBundledGsdBrowserCliPath };
10
9
  export function resolveBundledGsdCliPath(env = process.env) {
11
10
  const explicit = env.GSD_CLI_PATH?.trim() || env.GSD_BIN_PATH?.trim();
12
11
  if (explicit)
@@ -22,30 +21,6 @@ export function resolveBundledGsdCliPath(env = process.env) {
22
21
  }
23
22
  return null;
24
23
  }
25
- export function resolveBundledGsdBrowserCliPath(env = process.env) {
26
- const explicit = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
27
- if (explicit)
28
- return explicit;
29
- try {
30
- const requireFromHere = createRequire(import.meta.url);
31
- const packageJsonPath = requireFromHere.resolve("@opengsd/gsd-browser/package.json");
32
- const candidate = resolve(packageJsonPath, "..", "bin", "gsd-browser");
33
- if (existsSync(candidate))
34
- return candidate;
35
- }
36
- catch {
37
- // Fall through to path candidates for source/dist layouts.
38
- }
39
- const candidates = [
40
- resolve(fileURLToPath(new URL("../../../../node_modules/@opengsd/gsd-browser/bin/gsd-browser", import.meta.url))),
41
- resolve(fileURLToPath(new URL("../../../../node_modules/.bin/gsd-browser", import.meta.url))),
42
- ];
43
- for (const candidate of candidates) {
44
- if (existsSync(candidate))
45
- return candidate;
46
- }
47
- return null;
48
- }
49
24
  export function buildProjectWorkflowMcpServerConfig(projectRoot, env = process.env) {
50
25
  return buildProjectWorkflowMcpServerSpec(projectRoot, env).server;
51
26
  }
@@ -69,68 +44,26 @@ function buildProjectWorkflowMcpServerSpec(projectRoot, env = process.env) {
69
44
  },
70
45
  };
71
46
  }
72
- function parseJsonEnv(env, name) {
73
- const raw = env[name];
74
- if (!raw)
75
- return undefined;
76
- try {
77
- return JSON.parse(raw);
78
- }
79
- catch {
80
- throw new Error(`Invalid JSON in ${name}`);
81
- }
82
- }
83
47
  function isEnvDisabled(value) {
84
48
  if (!value)
85
49
  return false;
86
50
  const normalized = value.trim().toLowerCase();
87
51
  return normalized === "0" || normalized === "false" || normalized === "off";
88
52
  }
89
- function buildBrowserSessionName(projectRoot) {
90
- const resolvedProjectRoot = resolve(projectRoot);
91
- const base = basename(resolvedProjectRoot)
92
- .replace(/[^a-zA-Z0-9._-]+/g, "-")
93
- .replace(/^-+|-+$/g, "") || "project";
94
- const hash = createHash("sha1").update(resolvedProjectRoot).digest("hex").slice(0, 8);
95
- return `gsd-${base}-${hash}`;
96
- }
97
53
  export function buildProjectBrowserMcpServerConfig(projectRoot, env = process.env) {
98
54
  return buildProjectBrowserMcpServerSpec(projectRoot, env)?.server ?? null;
99
55
  }
100
56
  function buildProjectBrowserMcpServerSpec(projectRoot, env = process.env) {
101
57
  if (isEnvDisabled(env.GSD_BROWSER_MCP_ENABLED))
102
58
  return null;
103
- const resolvedProjectRoot = resolve(projectRoot);
104
- const serverName = env.GSD_BROWSER_MCP_NAME?.trim() || GSD_BROWSER_MCP_SERVER_NAME;
105
- const explicitArgs = parseJsonEnv(env, "GSD_BROWSER_MCP_ARGS");
106
- const explicitEnv = parseJsonEnv(env, "GSD_BROWSER_MCP_ENV");
107
- const explicitCommand = env.GSD_BROWSER_MCP_COMMAND?.trim();
108
- const explicitCliPath = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
109
- const bundledCliPath = !explicitCommand && !explicitCliPath ? resolveBundledGsdBrowserCliPath(env) : null;
110
- const command = explicitCommand
111
- || explicitCliPath
112
- || (bundledCliPath ? process.execPath : undefined)
113
- || "gsd-browser";
114
- const args = Array.isArray(explicitArgs) && explicitArgs.length > 0
115
- ? explicitArgs.map(String)
116
- : [
117
- ...(bundledCliPath ? [bundledCliPath] : []),
118
- "mcp",
119
- "--session",
120
- buildBrowserSessionName(resolvedProjectRoot),
121
- "--identity-scope",
122
- "project",
123
- "--identity-project",
124
- resolvedProjectRoot,
125
- ];
126
- const cwd = env.GSD_BROWSER_MCP_CWD?.trim() || resolvedProjectRoot;
59
+ const launch = resolveGsdBrowserMcpLaunchConfig(projectRoot, env);
127
60
  return {
128
- serverName,
61
+ serverName: launch.serverName,
129
62
  server: {
130
- command,
131
- args,
132
- cwd,
133
- ...(explicitEnv ? { env: explicitEnv } : {}),
63
+ command: launch.command,
64
+ args: launch.args,
65
+ cwd: launch.cwd,
66
+ ...(launch.env ? { env: launch.env } : {}),
134
67
  },
135
68
  };
136
69
  }
@@ -157,6 +90,62 @@ function readExistingConfig(configPath) {
157
90
  throw new Error(`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
158
91
  }
159
92
  }
93
+ function readExistingClaudeCodeSettings(settingsPath) {
94
+ if (!existsSync(settingsPath))
95
+ return {};
96
+ const raw = readFileSync(settingsPath, "utf-8");
97
+ try {
98
+ const parsed = JSON.parse(raw);
99
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
100
+ }
101
+ catch (err) {
102
+ throw new Error(`Failed to parse ${settingsPath}: ${err instanceof Error ? err.message : String(err)}`);
103
+ }
104
+ }
105
+ export function ensureClaudeCodeMcpJsonServersEnabled(projectRoot, serverNames) {
106
+ const resolvedProjectRoot = resolve(projectRoot);
107
+ assertSafeDirectory(resolvedProjectRoot);
108
+ const targetServerNames = [...new Set(serverNames.filter((name) => name.trim().length > 0))];
109
+ if (targetServerNames.length === 0)
110
+ return false;
111
+ const settingsDir = resolve(resolvedProjectRoot, ".claude");
112
+ const settingsPath = resolve(settingsDir, "settings.local.json");
113
+ const existing = readExistingClaudeCodeSettings(settingsPath);
114
+ const enabled = Array.isArray(existing.enabledMcpjsonServers)
115
+ ? [...existing.enabledMcpjsonServers]
116
+ : [];
117
+ const enabledNames = new Set(enabled.filter((value) => typeof value === "string"));
118
+ let changed = !Array.isArray(existing.enabledMcpjsonServers);
119
+ for (const serverName of targetServerNames) {
120
+ if (!enabledNames.has(serverName)) {
121
+ enabled.push(serverName);
122
+ enabledNames.add(serverName);
123
+ changed = true;
124
+ }
125
+ }
126
+ let nextDisabled = existing.disabledMcpjsonServers;
127
+ if (Array.isArray(existing.disabledMcpjsonServers)) {
128
+ const blockedNames = new Set(targetServerNames);
129
+ const filtered = existing.disabledMcpjsonServers.filter((value) => !blockedNames.has(String(value)));
130
+ if (filtered.length !== existing.disabledMcpjsonServers.length) {
131
+ nextDisabled = filtered;
132
+ changed = true;
133
+ }
134
+ }
135
+ if (!changed)
136
+ return false;
137
+ const nextSettings = {
138
+ ...existing,
139
+ enabledMcpjsonServers: enabled,
140
+ ...(Array.isArray(existing.disabledMcpjsonServers) ? { disabledMcpjsonServers: nextDisabled } : {}),
141
+ };
142
+ mkdirSync(settingsDir, { recursive: true });
143
+ writeFileSync(settingsPath, `${JSON.stringify(nextSettings, null, 2)}\n`, "utf-8");
144
+ return true;
145
+ }
146
+ export function ensureClaudeCodeMcpJsonServerEnabled(projectRoot, serverName) {
147
+ return ensureClaudeCodeMcpJsonServersEnabled(projectRoot, [serverName]);
148
+ }
160
149
  export function ensureProjectWorkflowMcpConfig(projectRoot, env = process.env) {
161
150
  const resolvedProjectRoot = resolve(projectRoot);
162
151
  assertSafeDirectory(resolvedProjectRoot);
@@ -170,10 +159,18 @@ export function ensureProjectWorkflowMcpConfig(projectRoot, env = process.env) {
170
159
  };
171
160
  const desiredServerNames = Object.keys(desiredServers);
172
161
  const alreadyPresent = existsSync(configPath);
173
- const unchanged = desiredServerNames.every((serverName) => (JSON.stringify(previousServers[serverName] ?? null)
162
+ const mcpConfigUnchanged = desiredServerNames.every((serverName) => (JSON.stringify(previousServers[serverName] ?? null)
174
163
  === JSON.stringify(desiredServers[serverName])))
175
164
  && existing.mcpServers !== undefined;
176
- if (unchanged) {
165
+ if (!mcpConfigUnchanged) {
166
+ const nextConfig = {
167
+ ...existing,
168
+ mcpServers: nextServers,
169
+ };
170
+ writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf-8");
171
+ }
172
+ const localSettingsChanged = ensureClaudeCodeMcpJsonServersEnabled(resolvedProjectRoot, desiredServerNames);
173
+ if (mcpConfigUnchanged && !localSettingsChanged) {
177
174
  return {
178
175
  configPath,
179
176
  serverName: workflowServerName,
@@ -181,11 +178,6 @@ export function ensureProjectWorkflowMcpConfig(projectRoot, env = process.env) {
181
178
  status: "unchanged",
182
179
  };
183
180
  }
184
- const nextConfig = {
185
- ...existing,
186
- mcpServers: nextServers,
187
- };
188
- writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf-8");
189
181
  return {
190
182
  configPath,
191
183
  serverName: workflowServerName,
@@ -614,7 +614,10 @@ export function decayStaleMemories(thresholdUnits = 20) {
614
614
  return []; // not enough processed units yet
615
615
  const cutoff = row['processed_at'];
616
616
  const affected = adapter.prepare(`SELECT id FROM memories
617
- WHERE superseded_by IS NULL AND updated_at < :cutoff AND confidence > 0.1`).all({ ':cutoff': cutoff }).map((r) => r['id']);
617
+ WHERE superseded_by IS NULL
618
+ AND updated_at < :cutoff
619
+ AND confidence > 0.1
620
+ AND (structured_fields IS NULL OR structured_fields NOT LIKE '%"sourceDecisionId"%')`).all({ ':cutoff': cutoff }).map((r) => r['id']);
618
621
  decayMemoriesBefore(cutoff, new Date().toISOString());
619
622
  return affected;
620
623
  }
@@ -78,9 +78,9 @@ export async function checkMarkdownHierarchyAgainstDb(basePath) {
78
78
  markdown,
79
79
  beforeDb,
80
80
  afterDb: beforeDb,
81
- recoveryCommand: "/gsd recover",
81
+ recoveryCommand: "/gsd recover --confirm",
82
82
  message: `Markdown planning artifacts (${markdown.milestones}M/${markdown.slices}S/${markdown.tasks}T) ` +
83
83
  `do not match the authoritative DB (${beforeDb.milestones}M/${beforeDb.slices}S/${beforeDb.tasks}T). ` +
84
- "Runtime startup will not import markdown automatically; run `/gsd recover` if markdown should repopulate the database.",
84
+ "Runtime startup will not import markdown automatically; run `/gsd recover --confirm` if markdown should repopulate the database.",
85
85
  };
86
86
  }
@@ -19,6 +19,15 @@ export function isRetryPending() {
19
19
  export function consumeRetryTrigger() {
20
20
  return getOrCreateRegistry().consumeRetryTrigger();
21
21
  }
22
+ export function consumeHookFailure() {
23
+ return getOrCreateRegistry().consumeHookFailure();
24
+ }
25
+ export function isGateBlockPending() {
26
+ return getOrCreateRegistry().isGateBlockPending();
27
+ }
28
+ export function consumeGateBlock() {
29
+ return getOrCreateRegistry().consumeGateBlock();
30
+ }
22
31
  export function resetHookState() {
23
32
  getOrCreateRegistry().resetState();
24
33
  }
@@ -15,6 +15,14 @@ const VALID_UOK_TURN_ACTIONS = new Set([
15
15
  "snapshot",
16
16
  "status-only",
17
17
  ]);
18
+ const VALID_POST_UNIT_HOOK_CRITICALITIES = new Set(["advisory", "blocking"]);
19
+ const VALID_POST_UNIT_HOOK_ON_BLOCK_ACTIONS = new Set([
20
+ "retry-unit",
21
+ "retry-task",
22
+ "queue-task",
23
+ "queue-slice",
24
+ "pause",
25
+ ]);
18
26
  export function validatePreferences(preferences) {
19
27
  const errors = [];
20
28
  const warnings = [];
@@ -474,9 +482,40 @@ export function validatePreferences(preferences) {
474
482
  if (typeof hook.artifact === "string" && hook.artifact.trim()) {
475
483
  validHook.artifact = hook.artifact.trim();
476
484
  }
485
+ if (hook.criticality !== undefined) {
486
+ const criticality = typeof hook.criticality === "string" ? hook.criticality.trim() : "";
487
+ if (VALID_POST_UNIT_HOOK_CRITICALITIES.has(criticality)) {
488
+ validHook.criticality = criticality;
489
+ }
490
+ else {
491
+ errors.push(`post_unit_hooks "${name}" invalid criticality: ${String(hook.criticality)}`);
492
+ }
493
+ }
477
494
  if (typeof hook.retry_on === "string" && hook.retry_on.trim()) {
478
495
  validHook.retry_on = hook.retry_on.trim();
479
496
  }
497
+ if (hook.on_block !== undefined) {
498
+ if (!hook.on_block || typeof hook.on_block !== "object") {
499
+ errors.push(`post_unit_hooks "${name}" on_block must be an object`);
500
+ }
501
+ else {
502
+ const onBlock = hook.on_block;
503
+ const action = typeof onBlock.action === "string" ? onBlock.action.trim() : "";
504
+ if (!VALID_POST_UNIT_HOOK_ON_BLOCK_ACTIONS.has(action)) {
505
+ errors.push(`post_unit_hooks "${name}" invalid on_block action: ${String(onBlock.action)}`);
506
+ }
507
+ else {
508
+ validHook.on_block = { action: action };
509
+ if (typeof onBlock.artifact === "string" && onBlock.artifact.trim()) {
510
+ validHook.on_block.artifact = onBlock.artifact.trim();
511
+ }
512
+ }
513
+ }
514
+ }
515
+ if (validHook.criticality === "blocking" && !validHook.artifact) {
516
+ errors.push(`post_unit_hooks "${name}" criticality blocking requires artifact`);
517
+ continue;
518
+ }
480
519
  if (typeof hook.agent === "string" && hook.agent.trim()) {
481
520
  validHook.agent = hook.agent.trim();
482
521
  }
@@ -26,9 +26,16 @@ function hasRequiredExtensionAssets(rootDir, exists = existsSync) {
26
26
  return (exists(join(rootDir, "prompts")) &&
27
27
  exists(join(rootDir, "templates", "task-summary.md")));
28
28
  }
29
+ function isSourceExtensionDir(moduleDir) {
30
+ return moduleDir.replaceAll("\\", "/").endsWith("/src/resources/extensions/gsd");
31
+ }
29
32
  export function resolveExtensionDirFromCandidates(moduleDir, agentGsdDir, exists = existsSync) {
30
33
  const moduleUsable = hasRequiredExtensionAssets(moduleDir, exists);
31
34
  const agentUsable = hasRequiredExtensionAssets(agentGsdDir, exists);
35
+ // Source checkouts must use their own prompt tree. Otherwise local tests and
36
+ // dev runs can silently render stale prompts from ~/.gsd/agent/extensions/gsd.
37
+ if (moduleUsable && isSourceExtensionDir(moduleDir))
38
+ return moduleDir;
32
39
  // Prefer the user-local extension tree when both are valid. This avoids
33
40
  // leaking npm/global-install paths into prompts on Windows.
34
41
  if (agentUsable)
@@ -12,6 +12,8 @@ Debug GSD itself. Trace the symptom to root cause in current source and produce
12
12
 
13
13
  GSD extension source: `{{gsdSourceDir}}`
14
14
 
15
+ {{toolingSection}}
16
+
15
17
  ### Source Map by Domain
16
18
 
17
19
  | Domain | Files |
@@ -101,7 +103,7 @@ Then **offer GitHub issue creation**: "Would you like me to create a GitHub issu
101
103
 
102
104
  **CRITICAL:** The `github_issues` tool targets only the current user's repository and has no `repo` parameter. Use `gh issue create --repo open-gsd/gsd-pi` via `bash`. Do NOT use the `github_issues` tool.
103
105
 
104
- If yes, create using the `bash` tool:
106
+ If yes and `bash` is available, create using the `bash` tool:
105
107
 
106
108
  ```bash
107
109
  ISSUE_BODY_FILE="${TMPDIR:-${TEMP:-${TMP:-.}}}/gsd-forensic-issue.md"
@@ -142,6 +144,64 @@ TYPE_ID=$(gh api graphql -f query='{ repository(owner:"open-gsd",name:"gsd-pi")
142
144
  gh api graphql -f query='mutation { updateIssue(input:{id:"'"$ISSUE_ID"'",issueTypeId:"'"$TYPE_ID"'"}) { issue { number } } }'
143
145
  ```
144
146
 
147
+ If `bash` is unavailable, do not attempt `bash`, `write`, or `github_issues` tool calls. Instead, provide exactly one paste-once shell script for the user to run locally and say that the live duplicate check / issue creation must be run by the user:
148
+
149
+ ```bash
150
+ KEYWORDS="..."
151
+ echo "Searching closed issues for possible duplicates..."
152
+ gh issue list --repo open-gsd/gsd-pi --state closed --search "$KEYWORDS" --limit 20
153
+
154
+ echo "Searching open PRs for possible fixes..."
155
+ gh pr list --repo open-gsd/gsd-pi --state open --search "$KEYWORDS" --limit 10
156
+
157
+ echo "Searching merged PRs for possible fixes..."
158
+ gh pr list --repo open-gsd/gsd-pi --state merged --search "$KEYWORDS" --limit 10
159
+
160
+ read -r -p "Review the duplicate search above. Continue filing a new issue? [y/N] " SHOULD_FILE
161
+ case "$SHOULD_FILE" in
162
+ y|Y|yes|YES) ;;
163
+ *) echo "Issue filing aborted."; exit 0 ;;
164
+ esac
165
+
166
+ ISSUE_BODY_FILE="${TMPDIR:-${TEMP:-${TMP:-.}}}/gsd-forensic-issue.md"
167
+ cat > "$ISSUE_BODY_FILE" << 'GSD_ISSUE_BODY'
168
+ ## Problem
169
+ [1-2 sentence summary]
170
+
171
+ ## Root Cause
172
+ [Specific file:line in GSD source, with code snippet showing the bug]
173
+
174
+ ## Expected Behavior
175
+ [What the code should do instead — concrete fix suggestion]
176
+
177
+ ## Environment
178
+ - GSD version: [from report]
179
+ - Model: [from report]
180
+ - Unit: [type/id that failed]
181
+
182
+ ## Reproduction Context
183
+ [Phase, milestone, slice, what was happening when it failed]
184
+
185
+ ## Forensic Evidence
186
+ [Key anomalies, error traces, relevant tool call sequences from the report]
187
+
188
+ ---
189
+ *Auto-generated by `/gsd forensics`*
190
+ GSD_ISSUE_BODY
191
+
192
+ ISSUE_URL=$(gh issue create --repo open-gsd/gsd-pi \
193
+ --title "..." \
194
+ --label "auto-generated" \
195
+ --body-file "$ISSUE_BODY_FILE")
196
+ rm -f "$ISSUE_BODY_FILE"
197
+
198
+ ISSUE_NUM=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
199
+ ISSUE_ID=$(gh api graphql -f query='{ repository(owner:"open-gsd",name:"gsd-pi") { issue(number:'"$ISSUE_NUM"') { id } } }' --jq '.data.repository.issue.id')
200
+ TYPE_ID=$(gh api graphql -f query='{ repository(owner:"open-gsd",name:"gsd-pi") { issueTypes(first:20) { nodes { id name } } } }' --jq '.data.repository.issueTypes.nodes[] | select(.name=="Bug") | .id')
201
+ gh api graphql -f query='mutation { updateIssue(input:{id:"'"$ISSUE_ID"'",issueTypeId:"'"$TYPE_ID"'"}) { issue { number } } }'
202
+ echo "$ISSUE_URL"
203
+ ```
204
+
145
205
  ### Redaction Rules (CRITICAL)
146
206
 
147
207
  Before creating the issue, you MUST:
@@ -8,6 +8,8 @@
8
8
 
9
9
  You are evaluating **quality gates in parallel** for this slice. Each gate is an independent question that must be answered before task execution begins. Use the `subagent` tool to dispatch all gate evaluations simultaneously.
10
10
 
11
+ **Tool call format:** Call `subagent` with `tasks: [...]` as a **native JSON array** — one object per gate. Do NOT JSON.stringify the array into a string; the tool validates that `tasks` is an array, and a serialized string will be rejected with "must be array".
12
+
11
13
  ## Slice Plan Context
12
14
 
13
15
  {{slicePlanContent}}
@@ -20,7 +22,7 @@ You are evaluating **quality gates in parallel** for this slice. Each gate is an
20
22
 
21
23
  ## Execution Protocol
22
24
 
23
- 1. **Dispatch all gates** using `subagent` in parallel mode. Each subagent prompt is provided below.
25
+ 1. **Dispatch all gates** using `subagent` in parallel mode. Call `subagent` with `tasks: [{ agent: "tester", task: "<prompt>" }, ...]` — one object per gate. Each subagent prompt is provided below.
24
26
  Pass `tasks` as a **JSON array**, not a string. Example shape:
25
27
 
26
28
  ```json
@@ -12,9 +12,11 @@ You are dispatching parallel research agents for **{{sliceCount}} slices** in mi
12
12
 
13
13
  Dispatch ALL slices simultaneously using the `subagent` tool in **parallel mode**. Each subagent will independently research its slice and write a RESEARCH file.
14
14
 
15
+ **Tool call format:** Call `subagent` with `tasks: [...]` as a **native JSON array** — one object per slice. Do NOT JSON.stringify the array into a string; the tool validates that `tasks` is an array, and a serialized string will be rejected with "must be array".
16
+
15
17
  ## Execution Protocol
16
18
 
17
- 1. Call `subagent` with `tasks: [...]` containing one entry per slice below
19
+ 1. Call `subagent` with `tasks: [{ agent: "scout", task: "<prompt>" }, ...]` containing one entry per slice below
18
20
  2. Wait for ALL subagents to complete
19
21
  3. Verify each slice's RESEARCH file was written (check `.gsd/milestones/{{mid}}/slices/<slice-id>/`)
20
22
  4. If a subagent failed to write its RESEARCH file, retry it **once** individually
@@ -43,7 +43,7 @@ If slice research is inlined, trust its architectural findings, but verify every
43
43
  5. Define slice verification before tasks. Non-trivial slices need real tests or executable assertions; boundary contracts need contract-exercising checks. Tests must not read .gitignore/gitignored paths such as `.gsd/`, `.planning/`, or `.audits/`.
44
44
  6. Include Threat Surface (Q3), Requirement Impact (Q4), proof level, observability, integration closure, Failure Modes (Q5), Load Profile (Q6), and Negative Tests (Q7) only where applicable.
45
45
  7. Right-size tasks. Simple slices can be one task; split only when context, ownership, or verification boundaries justify it.
46
- 8. Task `verify` commands must be safe, simple commands. Do not use shell pipes, redirects, semicolons, backticks, command substitution, output trimming, or grep regex alternation with `|`. If multiple checks are needed, create a small test file and run it with `node --test` or a package test script, or use separate simple commands joined only with `&&`.
46
+ 8. Task `verify` commands must be safe, simple commands. Do not use shell pipes, redirects, semicolons, backticks, command substitution, output trimming, or grep regex alternation with `|`. If multiple checks are needed, create a small test file and run it with `node --test` or a package test script, or use separate simple commands joined only with `&&`. For absence checks, verify a pattern does not exist with `! grep -q 'pattern' file` or `! rg -q 'pattern' file`; do not use `grep -c` or `rg -c` to assert zero matches because count commands exit 1 when they find zero matches, and the verification gate treats that as failure.
47
47
  9. Each task needs the exact `gsd_plan_slice.tasks[]` shape: `taskId`, `title`, `description`, `estimate`, `files`, `verify`, `inputs`, `expectedOutput`, and optional `observabilityImpact`. `description` should contain the Why / Do / Done-when narrative. `files`, `inputs`, and `expectedOutput` must be JSON arrays of strings, even when there is only one path (for example, `"inputs": ["src/index.ts"]`, never `"inputs": "src/index.ts"`). Use paths relative to `{{workingDirectory}}`; do not put absolute paths to the original checkout or any directory outside `{{workingDirectory}}` in `files`, `inputs`, `expectedOutput`, or verification commands. **`expectedOutput` must only list files the task actually creates or overwrites on disk.** Do NOT include files the task merely reads, verifies, or tests — those belong only in `inputs`. If a task is a pure verification or test task that produces no new files, `expectedOutput` may be `[]` or limited to test-result artifacts (e.g. a log or assertion output). A file that does not yet exist on disk and is needed as an `input` must be produced by an earlier task's `expectedOutput` — if no prior task creates it, add a task before this one that does.
48
48
  10. Persist with `gsd_plan_slice` using `milestoneId`, `sliceId`, `goal`, optional `successCriteria`/`proofLevel`/`integrationClosure`/`observabilityImpact`, and `tasks`. `gsd_plan_slice` handles task persistence transactionally and renders `{{outputPath}}` plus task plans; do not call `gsd_plan_task`. The DB-backed tool is the canonical write path. Do **not** rely on direct `PLAN.md` writes as the source of truth.
49
49
  11. Self-audit before finishing: goal/demo closure, requirement coverage, deliverable coverage audit (cross-check every file listed in CONTEXT.md `## Scope` / `### In Scope` against task `files` or `expectedOutput`), locked decisions, concrete paths, dependency order, wiring, scope size, proof truthfulness, feature completeness, and quality gates. Quality gates: non-trivial slices/tasks include specific Q3-Q7 coverage where applicable.
@@ -10,6 +10,8 @@ You are executing **multiple tasks in parallel** for this slice. The task graph
10
10
 
11
11
  **Critical rule:** Use the `subagent` tool in **parallel mode** to dispatch all ready tasks simultaneously. Each subagent gets a task-specific execution packet (task plan + dependency carry-forward + completion contract) and is responsible for its own implementation, verification, task summary, and completion tool calls. The parent batch agent orchestrates, verifies, and records failures only when a dispatched task failed before it could leave its own summary behind.
12
12
 
13
+ **Tool call format:** Call `subagent` with `tasks: [...]` as a **native JSON array** — one object per ready task. Do NOT JSON.stringify the array into a string; the tool validates that `tasks` is an array, and a serialized string will be rejected with "must be array".
14
+
13
15
  ## Task Dependency Graph
14
16
 
15
17
  {{graphContext}}
@@ -22,7 +24,7 @@ You are executing **multiple tasks in parallel** for this slice. The task graph
22
24
 
23
25
  ## Execution Protocol
24
26
 
25
- 1. **Dispatch all ready tasks** using `subagent` in parallel mode. Each subagent prompt is provided below.
27
+ 1. **Dispatch all ready tasks** using `subagent` in parallel mode. Call `subagent` with `tasks: [{ agent: "worker", task: "<prompt>" }, ...]` — one object per ready task. Each subagent prompt is provided below.
26
28
  2. **Wait for all subagents** to complete.
27
29
  3. **Verify each dispatched task's outputs** — check that expected files were created/modified, that verification commands pass where applicable, and that each task wrote its own `T##-SUMMARY.md`.
28
30
  4. **Do not rewrite successful task summaries or duplicate completion tool calls.** Treat a subagent-written summary as authoritative for that task.
@@ -37,7 +37,13 @@ You are the UAT runner. Execute every check defined in `{{uatPath}}` as deeply a
37
37
 
38
38
  Choose the lightest tool that proves the check honestly:
39
39
 
40
- - Run shell commands with `bash`
40
+ - Run automated checks with `gsd_uat_exec`
41
+ - Use `uat-artifact-check` as `intent` for static file, grep, structure, or artifact checks.
42
+ - Use `uat-runtime-check` as `intent` for executing tests, scripts, or runtime assertions.
43
+ - Use `uat-browser-check` as `intent` for browser interaction or screenshot-backed UI checks.
44
+ - Use `uat-service-start` as `intent` only when starting or connecting to an app/service.
45
+ - Use `uat-log-inspection` as `intent` for checking logs or captured output files.
46
+ - The result-table evidence mode is separate; do not use `artifact`, `runtime`, or `human-follow-up` as `intent`.
41
47
  - Run `grep` / `rg` checks against files
42
48
  - Run `node` / other script invocations
43
49
  - Read files and verify their contents
@@ -48,7 +54,7 @@ Choose the lightest tool that proves the check honestly:
48
54
  For each check, record:
49
55
  - The check description (from the UAT file)
50
56
  - The evidence mode used: `artifact`, `runtime`, or `human-follow-up`
51
- - The command or action taken
57
+ - The command or action taken, including the `gsd_uat_exec` evidence ID for automated checks
52
58
  - The actual result observed
53
59
  - `PASS`, `FAIL`, or `NEEDS-HUMAN`
54
60
 
@@ -57,35 +63,53 @@ After running all checks, compute the **overall verdict**:
57
63
  - `FAIL` — one or more automatable checks failed
58
64
  - `PARTIAL` — one or more automatable checks were skipped or returned inconclusive results (not the same as `NEEDS-HUMAN` — use PARTIAL only when the agent itself could not determine pass/fail for a check it was supposed to automate)
59
65
 
60
- Call `gsd_summary_save` with `milestone_id: {{milestoneId}}`, `slice_id: {{sliceId}}`, `artifact_type: "ASSESSMENT"`, and the full UAT result markdown as `content` — the tool computes the file path and persists to both DB and disk. The content should follow this format:
66
+ Call `gsd_uat_result_save` once after all checks are complete. The tool computes the assessment path, persists to DB/disk, saves attempt history, and saves the aggregate UAT gate.
61
67
 
62
- ```markdown
63
- ---
64
- sliceId: {{sliceId}}
65
- uatType: {{uatType}}
66
- verdict: PASS | FAIL | PARTIAL
67
- date: <ISO 8601 timestamp>
68
- ---
69
-
70
- # UAT Result — {{sliceId}}
71
-
72
- ## Checks
68
+ Pass these top-level fields:
73
69
 
74
- | Check | Mode | Result | Notes |
75
- |-------|------|--------|-------|
76
- | <check description> | artifact / runtime / human-follow-up | PASS / FAIL / NEEDS-HUMAN | <observed output, evidence, or reason> |
77
-
78
- ## Overall Verdict
79
-
80
- <PASS / FAIL / PARTIAL> — <one sentence summary>
70
+ ```ts
71
+ milestoneId: "{{milestoneId}}",
72
+ sliceId: "{{sliceId}}",
73
+ uatType: "{{uatType}}",
74
+ verdict: "PASS" | "FAIL" | "PARTIAL",
75
+ notes: "<one sentence overall verdict rationale>",
76
+ ```
81
77
 
82
- ## Notes
78
+ Use this exact `presentation` shape in the save call so the audit can verify the run-uat tool surface without retrying missing fields one by one:
79
+
80
+ ```ts
81
+ presentation: {
82
+ surface: "mcp",
83
+ presentedTools: [
84
+ "gsd_uat_exec",
85
+ "gsd_uat_result_save",
86
+ "gsd_resume",
87
+ "gsd_milestone_status",
88
+ "gsd_journal_query",
89
+ ],
90
+ blockedTools: [
91
+ { name: "gsd_exec", reason: "forbidden during run-uat" },
92
+ { name: "gsd_summary_save", reason: "forbidden during run-uat" },
93
+ { name: "gsd_save_gate_result", reason: "forbidden during run-uat" },
94
+ ],
95
+ }
96
+ ```
83
97
 
84
- <any additional context, errors encountered, screenshots/logs gathered, or manual follow-up still required>
98
+ Pass `checks` with this logical shape:
99
+
100
+ ```ts
101
+ checks: [{
102
+ id: "<stable check id>",
103
+ description: "<check description from the UAT file>",
104
+ mode: "artifact" | "runtime" | "browser" | "human-follow-up",
105
+ result: "PASS" | "FAIL" | "NEEDS-HUMAN",
106
+ evidence: [{ kind: "gsd_uat_exec", ref: "<evidence id>" }],
107
+ notes: "<observed output, evidence, reason, or manual follow-up>",
108
+ }]
85
109
  ```
86
110
 
87
111
  ---
88
112
 
89
- **You MUST call `gsd_summary_save` with the UAT result content before finishing.**
113
+ **You MUST call `gsd_uat_result_save` before finishing. Do not write the assessment file directly, and do not call `gsd_summary_save` as a substitute.**
90
114
 
91
115
  When done, say: "UAT {{sliceId}} complete."
@@ -32,7 +32,7 @@ GSD ships with bundled skills. Installed skills are listed in `<available_skills
32
32
  - Never print, echo, log, or restate secrets or credentials. Report only key names and applied/skipped status.
33
33
  - Never ask the user to edit `.env` files or set secrets manually. Use `secure_env_collect`.
34
34
  - In enduring files, write current state only unless the file is explicitly historical.
35
- - **Never take outward-facing actions on GitHub or external services without explicit user confirmation.** This includes creating/closing issues, merging/approving/commenting on PRs, pushing remote branches, publishing packages, or any state change outside local filesystem. Read-only listing/viewing/diffing is fine. Present intent and get a clear "yes" first. **Non-bypassable:** no response, ambiguity, or `ask_user_questions` failure means re-ask; never rationalize past the block. Missing "yes" means "no."
35
+ - **Never take outward-facing actions on GitHub or external services without explicit user confirmation.** This includes creating/closing issues, merging/approving/commenting on PRs, pushing remote branches, publishing packages, terragrunt/aws/kubectl mutations, or any state change outside local filesystem. Read-only listing/viewing/diffing is fine. Present intent and get a clear "yes" first. **Non-bypassable:** no response, ambiguity, or `ask_user_questions` failure means re-ask; never rationalize past the block. Missing "yes" means "no."
36
36
 
37
37
  If a `GSD Skill Preferences` block appears below, treat it as durable guidance for skills to use, prefer, or avoid unless it conflicts with artifact rules, verification, or higher-priority instructions.
38
38
 
@@ -160,4 +160,6 @@ Fix root causes, not symptoms. If applying temporary mitigation, label it and pr
160
160
  - When debugging, stay curious. Problems are puzzles. Say what's interesting about the failure before reaching for fixes.
161
161
  - After completing a task, give a brief summary and 2-4 numbered next-step options; last option is always "Other". Omit the list for strict output formats.
162
162
 
163
+ If any next step is destructive/outward-facing, present it via `ask_user_questions` and wait for the user's answer before execution. Do not execute a next-step item from a prior plain-text numbered list without fresh confirmation.
164
+
163
165
  Good narration states a decision or finding: "Three handlers follow a middleware pattern - using that instead of a custom wrapper." Bad narration just announces the next call ("Reading the file now.") or emits compressed planner notes ("Need create plan artifact maybe read existing plans.").
@@ -33,7 +33,7 @@ Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directo
33
33
  Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Read `{{roadmapPath}}` and find the boundary map (produces/consumes contracts). For each boundary, confirm producer SUMMARY produced the artifact and consumer SUMMARY consumed it. Output table: Boundary | Producer Summary | Consumer Summary | Status. End with one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."
34
34
 
35
35
  **Reviewer C - Assessment & Acceptance Criteria**
36
- Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.gsd/milestones/{{milestoneId}}/{{milestoneId}}-CONTEXT.md` for criteria. Check slice SUMMARY and ASSESSMENT files under `.gsd/milestones/{{milestoneId}}/slices/`; UAT files are specs, not evidence. Verify each criterion maps to passing evidence. Then review inlined milestone verification classes. For each non-empty planned class, output table: Class | Planned Check | Evidence | Verdict. Use the exact class names `Contract`, `Integration`, `Operational`, and `UAT` whenever those classes are present. If a planned browser/UAT class has no ASSESSMENT with browser/runtime actions and assertions, return NEEDS-ATTENTION. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered by evidence, NEEDS-ATTENTION if gaps exist."
36
+ Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.gsd/milestones/{{milestoneId}}/{{milestoneId}}-CONTEXT.md` for criteria. Check slice SUMMARY and ASSESSMENT files under `.gsd/milestones/{{milestoneId}}/slices/`; UAT files are specs, not evidence. Verify each criterion maps to passing evidence. Then review the inlined `Verification Classes (from planning)` table. For every planned row in that table, output a `Verification Classes` table with columns `Class | Planned Check | Evidence | Verdict`. Preserve every planned non-empty class row; do not summarize, rename, combine, or omit planned classes. The first cell of each row must be exactly `Contract`, `Integration`, `Operational`, or `UAT` when that class is present in planning. If a planned class lacks evidence, still include its canonical row and mark the verdict NEEDS-ATTENTION or FAIL. If a planned browser/UAT class has no ASSESSMENT with browser/runtime actions and assertions, return NEEDS-ATTENTION. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered by evidence, NEEDS-ATTENTION if gaps exist."
37
37
 
38
38
  ### Step 2 - Synthesize Findings
39
39
 
@@ -71,8 +71,8 @@ reviewers: 3
71
71
  <if verdict is not pass: specific actions required>
72
72
  ```
73
73
 
74
- Call `gsd_validate_milestone` with the camelCase fields `milestoneId`, `verdict`, `remediationRound`, `successCriteriaChecklist`, `sliceDeliveryAudit`, `crossSliceIntegration`, `requirementCoverage`, `verdictRationale`, and `remediationPlan` when needed. If you include verification-class analysis, pass it in `verificationClasses`.
75
- Extract the `Verification Classes` subsection from Reviewer C and pass it verbatim in `verificationClasses` so the persisted validation output uses the canonical class names `Contract`, `Integration`, `Operational`, and `UAT`.
74
+ Call `gsd_validate_milestone` with the camelCase fields `milestoneId`, `verdict`, `remediationRound`, `successCriteriaChecklist`, `sliceDeliveryAudit`, `crossSliceIntegration`, `requirementCoverage`, `verdictRationale`, and `remediationPlan` when needed. If planning included verification classes, pass a complete canonical table in `verificationClasses`.
75
+ Set `verificationClasses` to the `Verification Classes` subsection from Reviewer C. It must include one canonical row for every non-empty planned class from `Verification Classes (from planning)`: `Contract`, `Integration`, `Operational`, and/or `UAT`. If Reviewer C omitted a planned class, reconstruct the missing row from the planning table, set Evidence to the gap, and use NEEDS-ATTENTION or FAIL. Do not call `gsd_validate_milestone` with a partial `verificationClasses` table.
76
76
 
77
77
  **DB access safety:** Do NOT query `.gsd/gsd.db` directly via `sqlite3` or `node -e require('better-sqlite3')` - the engine owns the WAL connection. Use `gsd_milestone_status` for milestone and slice state. Data is already inlined or available via `gsd_*` tools. Direct DB access risks WAL corruption and bypasses validation.
78
78