@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
@@ -906,6 +906,51 @@ test("ADR-017 (#5704): registered milestone (DB row present) → no drift", asyn
906
906
 
907
907
  // ─── #5705: roadmap-divergence drift ─────────────────────────────────────────
908
908
 
909
+ test("ADR-017 (#391): roadmap-divergence skips slices before task planning completes", async (t) => {
910
+ const base = mkdtempSync(join(tmpdir(), "gsd-adr017-roadmap-unplanned-"));
911
+ const milestoneDir = join(base, ".gsd", "milestones", "M001");
912
+ const roadmapPath = join(milestoneDir, "M001-ROADMAP.md");
913
+ mkdirSync(milestoneDir, { recursive: true });
914
+ const originalRoadmap = [
915
+ "# M001: Test",
916
+ "",
917
+ "**Vision:** Verify transient milestone planning state",
918
+ "",
919
+ "## Slices",
920
+ "",
921
+ "- [ ] **S01: Foundation** `risk:medium` `depends:[]`",
922
+ "- [ ] **S02: Feature** `risk:medium` `depends:[S01]`",
923
+ "",
924
+ ].join("\n");
925
+ writeFileSync(roadmapPath, originalRoadmap);
926
+ t.after(() => {
927
+ try { closeDatabase(); } catch { /* noop */ }
928
+ rmSync(base, { recursive: true, force: true });
929
+ });
930
+
931
+ openDatabase(join(base, ".gsd", "gsd.db"));
932
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
933
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
934
+ insertSlice({ id: "S02", milestoneId: "M001", title: "Feature", status: "pending", risk: "medium", depends: [], demo: "", sequence: 2 });
935
+
936
+ assert.equal(getSliceTasks("M001", "S01").length, 0, "pre: S01 has not been planned");
937
+ assert.equal(getSliceTasks("M001", "S02").length, 0, "pre: S02 has not been planned");
938
+
939
+ const result = await reconcileBeforeDispatch(base, {
940
+ invalidateStateCache: () => {},
941
+ deriveState: async () => makeState(),
942
+ });
943
+
944
+ assert.equal(result.ok, true);
945
+ assert.equal(
946
+ result.repaired.some((d) => d.kind === "roadmap-divergence"),
947
+ false,
948
+ "unplanned slices should not trigger roadmap-divergence repair",
949
+ );
950
+ assert.equal(readFileSync(roadmapPath, "utf-8"), originalRoadmap);
951
+ assert.deepEqual(getSlice("M001", "S02")?.depends, [], "DB remains unchanged");
952
+ });
953
+
909
954
  test("ADR-017 (#5705): roadmap-divergence re-renders projection without syncing depends into DB", async (t) => {
910
955
  const base = mkdtempSync(join(tmpdir(), "gsd-adr017-roadmap-"));
911
956
  const milestoneDir = join(base, ".gsd", "milestones", "M001");
@@ -936,6 +981,8 @@ test("ADR-017 (#5705): roadmap-divergence re-renders projection without syncing
936
981
  // Seed DB with S02 depending on [] — diverges from ROADMAP.md
937
982
  insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
938
983
  insertSlice({ id: "S02", milestoneId: "M001", title: "Feature", status: "pending", risk: "medium", depends: [], demo: "", sequence: 2 });
984
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
985
+ insertTask({ id: "T01", sliceId: "S02", milestoneId: "M001", title: "Plan S02", status: "pending" });
939
986
 
940
987
  assert.deepEqual(getSlice("M001", "S02")?.depends, [], "pre: DB has S02.depends = []");
941
988
 
@@ -987,6 +1034,7 @@ test("ADR-017 (#5705): ROADMAP-only slice is removed from projection and not ins
987
1034
  insertMilestone({ id: "M001", title: "Test", status: "active" });
988
1035
  // Only insert S01 — S02 is intentionally absent from the DB.
989
1036
  insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
1037
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
990
1038
 
991
1039
  assert.equal(getSlice("M001", "S02"), null, "pre: S02 has no DB row");
992
1040
 
@@ -1035,6 +1083,8 @@ test("ADR-017 (#5705): ROADMAP sequence drift re-renders from DB order without m
1035
1083
  insertMilestone({ id: "M001", title: "Test", status: "active" });
1036
1084
  insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
1037
1085
  insertSlice({ id: "S02", milestoneId: "M001", title: "Feature", status: "pending", risk: "medium", depends: [], demo: "", sequence: 2 });
1086
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
1087
+ insertTask({ id: "T01", sliceId: "S02", milestoneId: "M001", title: "Plan S02", status: "pending" });
1038
1088
 
1039
1089
  const result = await reconcileBeforeDispatch(base, {
1040
1090
  invalidateStateCache: () => {},
@@ -1078,6 +1128,7 @@ test("ADR-017 (#5705): ROADMAP checkbox drift re-renders from DB status without
1078
1128
  openDatabase(join(base, ".gsd", "gsd.db"));
1079
1129
  insertMilestone({ id: "M001", title: "Test", status: "active" });
1080
1130
  insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "medium", depends: [], demo: "", sequence: 1 });
1131
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
1081
1132
 
1082
1133
  const result = await reconcileBeforeDispatch(base, {
1083
1134
  invalidateStateCache: () => {},
@@ -1119,6 +1170,7 @@ test("ADR-017 (#5705): in-sync ROADMAP and DB → no roadmap-divergence drift",
1119
1170
  openDatabase(join(base, ".gsd", "gsd.db"));
1120
1171
  insertMilestone({ id: "M001", title: "Test", status: "active" });
1121
1172
  insertSlice({ id: "S01", milestoneId: "M001", title: "Foundation", status: "pending", risk: "low", depends: [], demo: "", sequence: 1 });
1173
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Plan S01", status: "pending" });
1122
1174
 
1123
1175
  const result = await reconcileBeforeDispatch(base, {
1124
1176
  invalidateStateCache: () => {},
@@ -1300,6 +1352,145 @@ test("ADR-017: orphan task completion artifact fails closed", async (t) => {
1300
1352
  assert.match(result.blockers.join("\n"), /Artifact\/DB status drift/);
1301
1353
  });
1302
1354
 
1355
+ test("ADR-017 (#414): failure-path summary artifact blocker matches auto.ts filter phrase", async (t) => {
1356
+ // When gsd_summary_save writes a SUMMARY artifact row for a task that never
1357
+ // called gsd_task_complete, the task stays pending and the artifact DB row
1358
+ // produces an artifact-db-status-divergence blocker. The auto.ts dispatch
1359
+ // wrapper must be able to filter this class of blocker to allow re-dispatch.
1360
+ // If this test fails, update the filter strings in auto.ts to match.
1361
+ const base = mkdtempSync(join(tmpdir(), "gsd-failure-path-summary-drift-"));
1362
+ t.after(() => cleanup(base));
1363
+
1364
+ mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S04"), { recursive: true });
1365
+ openDatabase(join(base, ".gsd", "gsd.db"));
1366
+ insertMilestone({ id: "M001", title: "Milestone", status: "active" });
1367
+ insertSlice({ id: "S04", milestoneId: "M001", title: "Slice", status: "pending" });
1368
+ insertTask({ id: "T01", sliceId: "S04", milestoneId: "M001", title: "Task", status: "pending" });
1369
+ insertArtifact({
1370
+ path: join(base, ".gsd", "milestones", "M001", "slices", "S04", "tasks", "T01", "T01-SUMMARY.md"),
1371
+ artifact_type: "SUMMARY",
1372
+ milestone_id: "M001",
1373
+ slice_id: "S04",
1374
+ task_id: "T01",
1375
+ full_content: "# T01 Failure Summary\n",
1376
+ });
1377
+
1378
+ const result = await reconcileBeforeDispatch(base, {
1379
+ invalidateStateCache: () => {},
1380
+ deriveState: async () => makeState({ activeMilestone: { id: "M001", title: "Milestone" } }),
1381
+ });
1382
+
1383
+ assert.equal(result.ok, true);
1384
+ assert.ok(result.blockers.length > 0, "blocker must be produced for pending-task SUMMARY drift");
1385
+ const blocker = result.blockers.join("\n");
1386
+ assert.match(
1387
+ blocker,
1388
+ /has SUMMARY artifact while DB status is/,
1389
+ "blocker phrase must match the filter in auto.ts reconcileBeforeDispatch wrapper",
1390
+ );
1391
+ });
1392
+
1393
+ test("ADR-017 (#414): no-db-tasks summary artifact blocker matches auto.ts filter phrase", async (t) => {
1394
+ // When a slice has SUMMARY artifacts in the DB but no DB tasks, the auto.ts
1395
+ // filter must be able to recognise this as a failure-path case and skip it.
1396
+ const base = mkdtempSync(join(tmpdir(), "gsd-no-db-tasks-summary-drift-"));
1397
+ t.after(() => cleanup(base));
1398
+
1399
+ mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S04"), { recursive: true });
1400
+ openDatabase(join(base, ".gsd", "gsd.db"));
1401
+ insertMilestone({ id: "M001", title: "Milestone", status: "active" });
1402
+ insertSlice({ id: "S04", milestoneId: "M001", title: "Slice", status: "pending" });
1403
+ // No tasks inserted — slice has SUMMARY artifacts for a task that no longer exists.
1404
+ insertArtifact({
1405
+ path: join(base, ".gsd", "milestones", "M001", "slices", "S04", "tasks", "T01", "T01-SUMMARY.md"),
1406
+ artifact_type: "SUMMARY",
1407
+ milestone_id: "M001",
1408
+ slice_id: "S04",
1409
+ task_id: "T01",
1410
+ full_content: "# T01 Failure Summary\n",
1411
+ });
1412
+
1413
+ const result = await reconcileBeforeDispatch(base, {
1414
+ invalidateStateCache: () => {},
1415
+ deriveState: async () => makeState({ activeMilestone: { id: "M001", title: "Milestone" } }),
1416
+ });
1417
+
1418
+ assert.equal(result.ok, true);
1419
+ assert.ok(result.blockers.length > 0, "blocker must be produced for no-db-tasks SUMMARY drift");
1420
+ const blocker = result.blockers.join("\n");
1421
+ assert.match(
1422
+ blocker,
1423
+ /has task SUMMARY artifacts but no DB tasks/,
1424
+ "blocker phrase must match the filter in auto.ts reconcileBeforeDispatch wrapper",
1425
+ );
1426
+ });
1427
+
1428
+ test("ADR-017 (#414): task-level on-disk summary blocker matches auto.ts filter phrase", async (t) => {
1429
+ // When gsd_summary_save writes a SUMMARY file to disk for a task that never
1430
+ // called gsd_task_complete, but the artifact DB row was not yet written (or
1431
+ // the process crashed before insertion), reconciliation emits
1432
+ // "has SUMMARY on disk while DB status is". The auto.ts filter must match
1433
+ // this phrase so re-dispatch is not blocked.
1434
+ const base = mkdtempSync(join(tmpdir(), "gsd-task-disk-summary-drift-"));
1435
+ t.after(() => cleanup(base));
1436
+
1437
+ const tasksDir = join(base, ".gsd", "milestones", "M001", "slices", "S04", "tasks");
1438
+ mkdirSync(tasksDir, { recursive: true });
1439
+ writeFileSync(join(tasksDir, "T01-SUMMARY.md"), "# T01 Failure Summary\n");
1440
+
1441
+ openDatabase(join(base, ".gsd", "gsd.db"));
1442
+ insertMilestone({ id: "M001", title: "Milestone", status: "active" });
1443
+ insertSlice({ id: "S04", milestoneId: "M001", title: "Slice", status: "pending" });
1444
+ insertTask({ id: "T01", sliceId: "S04", milestoneId: "M001", title: "Task", status: "pending" });
1445
+ // No artifact row inserted — SUMMARY exists only on disk.
1446
+
1447
+ const result = await reconcileBeforeDispatch(base, {
1448
+ invalidateStateCache: () => {},
1449
+ deriveState: async () => makeState({ activeMilestone: { id: "M001", title: "Milestone" } }),
1450
+ });
1451
+
1452
+ assert.equal(result.ok, true);
1453
+ assert.ok(result.blockers.length > 0, "blocker must be produced for on-disk task SUMMARY drift");
1454
+ const blocker = result.blockers.join("\n");
1455
+ assert.match(
1456
+ blocker,
1457
+ /has SUMMARY on disk while DB status is/,
1458
+ "blocker phrase must match the filter in auto.ts reconcileBeforeDispatch wrapper",
1459
+ );
1460
+ });
1461
+
1462
+ test("ADR-017 (#414): slice-level on-disk summary blocker matches auto.ts filter phrase", async (t) => {
1463
+ // When a SUMMARY file exists on disk for a slice that is still pending
1464
+ // (no gsd_task_complete for the slice), reconciliation emits
1465
+ // "has SUMMARY on disk while DB status is". The auto.ts filter must match
1466
+ // this phrase so re-dispatch is not blocked.
1467
+ const base = mkdtempSync(join(tmpdir(), "gsd-slice-disk-summary-drift-"));
1468
+ t.after(() => cleanup(base));
1469
+
1470
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S04");
1471
+ mkdirSync(sliceDir, { recursive: true });
1472
+ writeFileSync(join(sliceDir, "S04-SUMMARY.md"), "# S04 Failure Summary\n");
1473
+
1474
+ openDatabase(join(base, ".gsd", "gsd.db"));
1475
+ insertMilestone({ id: "M001", title: "Milestone", status: "active" });
1476
+ insertSlice({ id: "S04", milestoneId: "M001", title: "Slice", status: "pending" });
1477
+ // No artifact row inserted — SUMMARY exists only on disk.
1478
+
1479
+ const result = await reconcileBeforeDispatch(base, {
1480
+ invalidateStateCache: () => {},
1481
+ deriveState: async () => makeState({ activeMilestone: { id: "M001", title: "Milestone" } }),
1482
+ });
1483
+
1484
+ assert.equal(result.ok, true);
1485
+ assert.ok(result.blockers.length > 0, "blocker must be produced for on-disk slice SUMMARY drift");
1486
+ const blocker = result.blockers.join("\n");
1487
+ assert.match(
1488
+ blocker,
1489
+ /has SUMMARY on disk while DB status is/,
1490
+ "blocker phrase must match the filter in auto.ts reconcileBeforeDispatch wrapper",
1491
+ );
1492
+ });
1493
+
1303
1494
  test("ADR-017: completed milestone dispatch history blocks accidental re-planning", async (t) => {
1304
1495
  const base = mkdtempSync(join(tmpdir(), "gsd-completed-reopened-drift-"));
1305
1496
  t.after(() => cleanup(base));
@@ -4,8 +4,11 @@
4
4
  import assert from "node:assert/strict";
5
5
  import test from "node:test";
6
6
 
7
+ import { registerToolCompatibility } from "@gsd/pi-coding-agent";
8
+
7
9
  import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
8
10
  import { buildMinimalAutoGsdToolSet, buildMinimalGsdToolSet, buildMinimalGsdWorkflowToolSet, buildRequestScopedGsdToolSet, MINIMAL_AUTO_BASE_TOOL_NAMES, MINIMAL_GSD_TOOL_NAMES, requestHasGsdCustomType, restoreGsdWorkflowTools, scopeGsdWorkflowToolsForDispatch } from "../bootstrap/register-hooks.ts";
11
+ import { filterToolsForProvider } from "../model-router.ts";
9
12
  import { applyUnitSkillVisibility } from "../skill-scope.ts";
10
13
 
11
14
  test("buildMinimalGsdToolSet preserves non-GSD tools and replaces broad GSD surface", () => {
@@ -31,7 +34,7 @@ test("buildMinimalGsdToolSet preserves non-GSD tools and replaces broad GSD surf
31
34
  for (const toolName of MINIMAL_GSD_TOOL_NAMES) {
32
35
  assert.ok(result.includes(toolName), `expected ${toolName}`);
33
36
  }
34
- assert.ok(!result.includes("gsd_plan_milestone"));
37
+ assert.ok(result.includes("gsd_plan_milestone"));
35
38
  assert.ok(!result.includes("gsd_task_complete"));
36
39
  assert.ok(!result.includes("gsd_graph"));
37
40
  });
@@ -98,22 +101,39 @@ test("buildMinimalAutoGsdToolSet keeps unit-specific completion tools without al
98
101
  assert.ok(!result.includes("gsd_complete_slice"));
99
102
  });
100
103
 
101
- test("buildMinimalAutoGsdToolSet re-resolves run-uat browser tools from the registry when dropped from the active set", () => {
102
- // B2 drops the browser surface from the advertised interactive set, but the
103
- // tools stay registered. run-uat must still get them: resolution reads the
104
- // full registry, not just the (browser-stripped) active set.
105
- const active = ["ask_user_questions", "bash", "read", "gsd_summary_save"];
104
+ test("buildMinimalAutoGsdToolSet scopes run-uat to UAT-specific tools", () => {
105
+ const active = ["ask_user_questions", "bash", "read", "edit", "write", "gsd_summary_save"];
106
106
  const registered = [
107
107
  ...active,
108
+ "gsd_uat_exec",
109
+ "gsd_uat_result_save",
110
+ "gsd_resume",
111
+ "gsd_milestone_status",
112
+ "gsd_journal_query",
113
+ "gsd_exec",
114
+ "gsd_save_gate_result",
115
+ "search-the-web",
108
116
  "browser_navigate",
109
117
  "browser_click",
110
118
  "browser_snapshot_refs",
111
- "gsd_exec",
112
119
  ];
113
120
  const result = buildMinimalAutoGsdToolSet(active, "run-uat", registered);
121
+ assert.ok(result.includes("gsd_uat_exec"));
122
+ assert.ok(result.includes("gsd_uat_result_save"));
123
+ assert.ok(result.includes("gsd_resume"));
124
+ assert.ok(result.includes("gsd_milestone_status"));
125
+ assert.ok(result.includes("gsd_journal_query"));
114
126
  assert.ok(result.includes("browser_navigate"), "run-uat needs browser_navigate");
115
127
  assert.ok(result.includes("browser_click"), "run-uat needs browser_click");
116
- assert.ok(result.includes("gsd_summary_save"));
128
+ assert.ok(!result.includes("ToolSearch"));
129
+ assert.ok(!result.includes("bash"));
130
+ assert.ok(!result.includes("read"));
131
+ assert.ok(!result.includes("edit"));
132
+ assert.ok(!result.includes("write"));
133
+ assert.ok(!result.includes("gsd_exec"));
134
+ assert.ok(!result.includes("gsd_summary_save"));
135
+ assert.ok(!result.includes("gsd_save_gate_result"));
136
+ assert.ok(!result.includes("search-the-web"));
117
137
  });
118
138
 
119
139
  test("buildMinimalAutoGsdToolSet keeps only the auto base non-GSD tools", () => {
@@ -175,17 +195,27 @@ test("buildMinimalAutoGsdToolSet re-injects registered base tools filtered from
175
195
  assert.ok(result.includes("search-the-web"));
176
196
  });
177
197
 
178
- test("buildMinimalAutoGsdToolSet preserves browser tools for run-uat", () => {
198
+ test("buildMinimalAutoGsdToolSet preserves compatible browser add-ons for run-uat", () => {
179
199
  const result = buildMinimalAutoGsdToolSet([
180
200
  "bash",
181
201
  "read",
202
+ "edit",
203
+ "write",
182
204
  "browser_navigate",
183
205
  "browser_click",
184
206
  "browser_type",
185
207
  "browser_assert",
186
208
  "browser_screenshot",
187
209
  "browser_wait_for",
210
+ "gsd_uat_exec",
211
+ "gsd_uat_result_save",
212
+ "gsd_resume",
213
+ "gsd_milestone_status",
214
+ "gsd_journal_query",
215
+ "subagent",
188
216
  "gsd_summary_save",
217
+ "gsd_exec",
218
+ "gsd_save_gate_result",
189
219
  "gsd_task_complete",
190
220
  "memory_query",
191
221
  "capture_thought",
@@ -197,7 +227,17 @@ test("buildMinimalAutoGsdToolSet preserves browser tools for run-uat", () => {
197
227
  assert.ok(result.includes("browser_assert"));
198
228
  assert.ok(result.includes("browser_screenshot"));
199
229
  assert.ok(result.includes("browser_wait_for"));
200
- assert.ok(result.includes("gsd_summary_save"));
230
+ assert.ok(result.includes("gsd_uat_exec"));
231
+ assert.ok(result.includes("gsd_uat_result_save"));
232
+ assert.ok(result.includes("subagent"));
233
+ assert.ok(!result.includes("ToolSearch"));
234
+ assert.ok(!result.includes("bash"));
235
+ assert.ok(!result.includes("read"));
236
+ assert.ok(!result.includes("edit"));
237
+ assert.ok(!result.includes("write"));
238
+ assert.ok(!result.includes("gsd_exec"));
239
+ assert.ok(!result.includes("gsd_summary_save"));
240
+ assert.ok(!result.includes("gsd_save_gate_result"));
201
241
  assert.ok(!result.includes("gsd_task_complete"));
202
242
  });
203
243
 
@@ -218,6 +258,40 @@ test("buildMinimalAutoGsdToolSet prefers MCP browser tools for run-uat when avai
218
258
  assert.ok(!result.includes("browser_click"));
219
259
  });
220
260
 
261
+ test("buildMinimalAutoGsdToolSet honors provider-compatible registered tools for run-uat", () => {
262
+ registerToolCompatibility("browser_screenshot", { producesImages: true });
263
+ const registered = [
264
+ "bash",
265
+ "read",
266
+ "ToolSearch",
267
+ "browser_navigate",
268
+ "browser_click",
269
+ "browser_screenshot",
270
+ "gsd_uat_exec",
271
+ "gsd_uat_result_save",
272
+ "gsd_resume",
273
+ "gsd_milestone_status",
274
+ "gsd_journal_query",
275
+ "gsd_exec",
276
+ "gsd_summary_save",
277
+ "gsd_save_gate_result",
278
+ ];
279
+ const providerCompatible = filterToolsForProvider(registered, "openai-responses").compatible;
280
+ const result = buildMinimalAutoGsdToolSet(["gsd_uat_exec"], "run-uat", providerCompatible);
281
+
282
+ assert.ok(result.includes("gsd_uat_exec"));
283
+ assert.ok(result.includes("gsd_uat_result_save"));
284
+ assert.ok(result.includes("browser_navigate"));
285
+ assert.ok(result.includes("browser_click"));
286
+ assert.ok(!result.includes("browser_screenshot"), "provider-filtered screenshot tool must stay filtered");
287
+ assert.ok(!result.includes("ToolSearch"));
288
+ assert.ok(!result.includes("bash"));
289
+ assert.ok(!result.includes("read"));
290
+ assert.ok(!result.includes("gsd_exec"));
291
+ assert.ok(!result.includes("gsd_summary_save"));
292
+ assert.ok(!result.includes("gsd_save_gate_result"));
293
+ });
294
+
221
295
  test("buildMinimalAutoGsdToolSet includes discuss-slice persistence tools", () => {
222
296
  const result = buildMinimalAutoGsdToolSet([
223
297
  "bash",
@@ -102,6 +102,25 @@ describe("#2883: isToolInvocationError classification", () => {
102
102
  );
103
103
  });
104
104
 
105
+ test("detects MCP -32602 Input validation error (wire format)", () => {
106
+ assert.equal(
107
+ isToolInvocationError("MCP error -32602: Input validation error: Invalid arguments for tool gsd_slice_complete [path: verification, expected string, invalid_type]"),
108
+ true,
109
+ );
110
+ });
111
+
112
+ test("detects standalone 'Input validation error' prefix", () => {
113
+ assert.equal(isToolInvocationError("Input validation error: expected string"), true);
114
+ });
115
+
116
+ test("detects 'Invalid arguments for tool' prefix", () => {
117
+ assert.equal(isToolInvocationError("Invalid arguments for tool gsd_slice_complete"), true);
118
+ });
119
+
120
+ test("detects 'No such tool available' error", () => {
121
+ assert.equal(isToolInvocationError("No such tool available: mcp__gsd-workflow__memory_query"), true);
122
+ });
123
+
105
124
  test("detects ESM export-link errors", () => {
106
125
  assert.equal(
107
126
  isToolInvocationError("The requested module '../paths.js' does not provide an export named 'gsdProjectionRoot'"),
@@ -39,6 +39,12 @@ const RENAME_MAP: Array<{ canonical: string; alias: string }> = [
39
39
  { canonical: "gsd_milestone_reopen", alias: "gsd_reopen_milestone" },
40
40
  ];
41
41
 
42
+ const STANDALONE_TOOLS = [
43
+ "gsd_save_gate_result",
44
+ "gsd_skip_slice",
45
+ "gsd_uat_result_save",
46
+ ];
47
+
42
48
  // ─── Registration count ──────────────────────────────────────────────────────
43
49
 
44
50
  console.log('\n── Tool naming: registration count ──');
@@ -48,10 +54,14 @@ registerDbTools(pi);
48
54
 
49
55
  assert.deepStrictEqual(
50
56
  pi.tools.length,
51
- RENAME_MAP.length * 2 + 2,
52
- 'Should register canonical/alias tool pairs plus 1 gate tool and 1 gsd_skip_slice',
57
+ RENAME_MAP.length * 2 + STANDALONE_TOOLS.length,
58
+ 'Should register canonical/alias tool pairs plus standalone DB tools',
53
59
  );
54
60
 
61
+ for (const name of STANDALONE_TOOLS) {
62
+ assert.ok(pi.tools.some((t: any) => t.name === name), `Standalone tool "${name}" should be registered`);
63
+ }
64
+
55
65
  // ─── Both names exist for each pair ──────────────────────────────────────────
56
66
 
57
67
  console.log('\n── Tool naming: canonical and alias names exist ──');
@@ -101,13 +101,19 @@ test("gsd_slice_complete — enrichment arrays are optional", () => {
101
101
  "sliceTitle",
102
102
  "oneLiner",
103
103
  "narrative",
104
- "verification",
105
104
  "uatContent",
106
105
  ];
107
106
  for (const field of coreRequired) {
108
107
  assert.ok(required.has(field), `core field "${field}" must be required`);
109
108
  }
110
109
 
110
+ // verification is intentionally optional — models that omit it avoid -32602;
111
+ // the summary records verification as passed without detail in that case.
112
+ assert.ok(
113
+ !required.has("verification"),
114
+ "verification must be optional — omitting it avoids -32602; summary records verification as passed without detail",
115
+ );
116
+
111
117
  // Enrichment/metadata arrays MUST be optional
112
118
  const enrichmentFields = [
113
119
  "keyFiles",
@@ -7,12 +7,17 @@
7
7
 
8
8
  import test from "node:test";
9
9
  import assert from "node:assert/strict";
10
- import { mkdirSync, rmSync } from "node:fs";
10
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  import { tmpdir } from "node:os";
13
13
  import { visibleWidth } from "@gsd/pi-tui";
14
14
 
15
- import { setCompletionProgressWidget, updateProgressWidget } from "../auto-dashboard.ts";
15
+ import {
16
+ _resetWidgetModeForTests,
17
+ setCompletionProgressWidget,
18
+ setWidgetMode,
19
+ updateProgressWidget,
20
+ } from "../auto-dashboard.ts";
16
21
  import type { GSDState } from "../types.ts";
17
22
 
18
23
  interface CapturedSetHeader {
@@ -143,10 +148,18 @@ test("updateProgressWidget gracefully no-ops when ctx.ui lacks setHeader/setStat
143
148
 
144
149
  // ── NEXT-mode footer guidance ───────────────────────────────────────────
145
150
 
146
- test("auto-dashboard widget render output includes /gsd next guidance when isStepMode is true", (t) => {
151
+ test("auto-dashboard full widget render output includes /gsd next guidance when isStepMode is true", (t) => {
147
152
  const dir = makeTempDir("step-hint");
148
153
  mkdirSync(join(dir, ".gsd"), { recursive: true });
149
- t.after(() => cleanup(dir));
154
+ const projectPrefsPath = join(dir, ".gsd", "preferences.md");
155
+ const globalPrefsPath = join(dir, ".gsd", "global-preferences.md");
156
+ writeFileSync(projectPrefsPath, "---\nversion: 1\n---\n", "utf-8");
157
+ _resetWidgetModeForTests();
158
+ setWidgetMode("full", projectPrefsPath, globalPrefsPath);
159
+ t.after(() => {
160
+ _resetWidgetModeForTests();
161
+ cleanup(dir);
162
+ });
150
163
 
151
164
  let widgetFactory: ((tui: unknown, theme: unknown) => any) | undefined;
152
165
 
@@ -173,6 +186,7 @@ test("auto-dashboard widget render output includes /gsd next guidance when isSte
173
186
  bold: (text: string) => text,
174
187
  };
175
188
  const component = widgetFactory!(fakeTui, fakeTheme);
189
+ t.after(() => component.dispose?.());
176
190
  const lines = component.render(120);
177
191
 
178
192
  const hasStepHint = lines.some((line: string) => line.includes("/gsd next to advance one step"));
@@ -181,10 +195,18 @@ test("auto-dashboard widget render output includes /gsd next guidance when isSte
181
195
  if (component.dispose) component.dispose();
182
196
  });
183
197
 
184
- test("auto-dashboard widget render output omits /gsd next guidance when isStepMode is false", (t) => {
198
+ test("auto-dashboard full widget render output omits /gsd next guidance when isStepMode is false", (t) => {
185
199
  const dir = makeTempDir("no-step-hint");
186
200
  mkdirSync(join(dir, ".gsd"), { recursive: true });
187
- t.after(() => cleanup(dir));
201
+ const projectPrefsPath = join(dir, ".gsd", "preferences.md");
202
+ const globalPrefsPath = join(dir, ".gsd", "global-preferences.md");
203
+ writeFileSync(projectPrefsPath, "---\nversion: 1\n---\n", "utf-8");
204
+ _resetWidgetModeForTests();
205
+ setWidgetMode("full", projectPrefsPath, globalPrefsPath);
206
+ t.after(() => {
207
+ _resetWidgetModeForTests();
208
+ cleanup(dir);
209
+ });
188
210
 
189
211
  let widgetFactory: ((tui: unknown, theme: unknown) => any) | undefined;
190
212
 
@@ -211,6 +233,7 @@ test("auto-dashboard widget render output omits /gsd next guidance when isStepMo
211
233
  bold: (text: string) => text,
212
234
  };
213
235
  const component = widgetFactory!(fakeTui, fakeTheme);
236
+ t.after(() => component.dispose?.());
214
237
  const lines = component.render(120);
215
238
 
216
239
  const hasStepHint = lines.some((line: string) => line.includes("/gsd next to advance one step"));
@@ -344,6 +344,7 @@ test("#5843: run-uat uses verification tools policy so build/test commands can r
344
344
  const manifest = UNIT_MANIFESTS["run-uat"];
345
345
 
346
346
  assert.strictEqual(manifest.tools.mode, "verification");
347
+ assert.deepEqual(manifest.tools.allowedSubagents, ["mnemo", "scout", "reviewer", "tester"]);
347
348
 
348
349
  const buildResult = shouldBlockPlanningUnit(
349
350
  "bash",
@@ -367,6 +368,20 @@ test("#5843: run-uat uses verification tools policy so build/test commands can r
367
368
  );
368
369
  assert.strictEqual(sourceWriteResult.block, true);
369
370
  assert.match(sourceWriteResult.reason!, /tools-policy "verification"/);
371
+
372
+ const subagentResult = shouldBlockPlanningUnit(
373
+ "subagent",
374
+ "",
375
+ process.cwd(),
376
+ "run-uat",
377
+ manifest.tools,
378
+ ["mnemo"],
379
+ );
380
+ assert.strictEqual(
381
+ subagentResult.block,
382
+ false,
383
+ `run-uat must allow listed verification subagents: ${subagentResult.reason}`,
384
+ );
370
385
  });
371
386
 
372
387
  test("planning-dispatch hard block message omits internal tracker references", () => {
@@ -420,6 +435,11 @@ test('Unit Tool Contract exposes subagent dispatch permissions', () => {
420
435
  allowedSubagents: ["reviewer", "security", "tester"],
421
436
  toolsMode: "planning-dispatch",
422
437
  });
438
+ assert.deepEqual(resolveSubagentPermissionContract("run-uat"), {
439
+ allowed: true,
440
+ allowedSubagents: ["mnemo", "scout", "reviewer", "tester"],
441
+ toolsMode: "verification",
442
+ });
423
443
  assert.deepEqual(resolveSubagentPermissionContract("discuss-milestone"), {
424
444
  allowed: false,
425
445
  allowedSubagents: [],
@@ -427,21 +447,24 @@ test('Unit Tool Contract exposes subagent dispatch permissions', () => {
427
447
  });
428
448
  });
429
449
 
430
- test('planning-dispatch manifests declare non-empty allowedSubagents lists', () => {
450
+ test('dispatch-capable manifests declare globally allowed subagents', () => {
431
451
  for (const [unitType, manifest] of Object.entries(UNIT_MANIFESTS)) {
432
- if (manifest.tools.mode !== "planning-dispatch") continue;
452
+ const allowedSubagents = "allowedSubagents" in manifest.tools
453
+ ? manifest.tools.allowedSubagents
454
+ : undefined;
455
+ if (!allowedSubagents) continue;
433
456
  assert.ok(
434
- Array.isArray(manifest.tools.allowedSubagents) && manifest.tools.allowedSubagents.length > 0,
435
- `manifest "${unitType}" has planning-dispatch policy but no allowedSubagents — explicit allowlist is required for runtime dispatch gating`,
457
+ Array.isArray(allowedSubagents) && allowedSubagents.length > 0,
458
+ `manifest "${unitType}" enables subagent dispatch but has no allowedSubagents — explicit allowlist is required for runtime dispatch gating`,
436
459
  );
437
- for (const agent of manifest.tools.allowedSubagents) {
460
+ for (const agent of allowedSubagents) {
438
461
  assert.ok(
439
462
  typeof agent === "string" && agent.length > 0,
440
463
  `manifest "${unitType}" has empty/invalid allowedSubagents entry: ${JSON.stringify(agent)}`,
441
464
  );
442
465
  assert.ok(
443
466
  ALLOWED_PLANNING_DISPATCH_AGENTS.has(agent),
444
- `manifest "${unitType}" allows "${agent}", but the runtime planning-dispatch registry will hard-block it`,
467
+ `manifest "${unitType}" allows "${agent}", but the runtime controlled-dispatch registry will hard-block it`,
445
468
  );
446
469
  }
447
470
  }
@@ -11,11 +11,14 @@ const prompt = readFileSync(promptPath, "utf-8");
11
11
 
12
12
  test("validate-milestone reviewer C requires canonical verification class names", () => {
13
13
  assert.match(prompt, /\*\*Reviewer C[\s\S]*Verification Classes/i);
14
- assert.match(prompt, /exact class names [`']?Contract[`']?, [`']?Integration[`']?, [`']?Operational[`']?, and [`']?UAT[`']?/i);
14
+ assert.match(prompt, /must be exactly `Contract`, `Integration`, `Operational`, or `UAT`/i);
15
+ assert.match(prompt, /Preserve every planned non-empty class row/i);
16
+ assert.match(prompt, /first cell of each row must be exactly `Contract`, `Integration`, `Operational`, or `UAT`/i);
15
17
  assert.match(prompt, /If no verification classes were planned, say that explicitly/i);
16
18
  });
17
19
 
18
20
  test("validate-milestone prompt routes verification class analysis into verificationClasses", () => {
19
- assert.match(prompt, /pass it in `verificationClasses`/i);
20
- assert.match(prompt, /Extract the `Verification Classes` subsection from Reviewer C and pass it verbatim in `verificationClasses`/);
21
+ assert.match(prompt, /pass a complete canonical table in `verificationClasses`/i);
22
+ assert.match(prompt, /If Reviewer C omitted a planned class, reconstruct the missing row/i);
23
+ assert.match(prompt, /Do not call `gsd_validate_milestone` with a partial `verificationClasses` table/i);
21
24
  });