@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.75048e7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (452) hide show
  1. package/dist/cli.js +3 -2
  2. package/dist/help-text.js +10 -6
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
  5. package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
  6. package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
  7. package/dist/resources/extensions/browser-tools/index.js +57 -9
  8. package/dist/resources/extensions/browser-tools/package.json +5 -1
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +167 -16
  10. package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
  11. package/dist/resources/extensions/gsd/auto/phases.js +4 -3
  12. package/dist/resources/extensions/gsd/auto-dashboard.js +92 -17
  13. package/dist/resources/extensions/gsd/auto-dispatch.js +55 -0
  14. package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
  15. package/dist/resources/extensions/gsd/auto-prompts.js +72 -22
  16. package/dist/resources/extensions/gsd/auto-recovery.js +7 -8
  17. package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
  18. package/dist/resources/extensions/gsd/auto-start.js +94 -15
  19. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  20. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +18 -65
  21. package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
  22. package/dist/resources/extensions/gsd/auto.js +31 -6
  23. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -4
  24. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +56 -20
  26. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +33 -38
  27. package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
  28. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
  29. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  30. package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
  31. package/dist/resources/extensions/gsd/commands/handlers/ops.js +9 -5
  32. package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
  33. package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
  34. package/dist/resources/extensions/gsd/commands-mcp-status.js +109 -60
  35. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
  36. package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
  37. package/dist/resources/extensions/gsd/config-overlay.js +2 -1
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
  41. package/dist/resources/extensions/gsd/error-classifier.js +2 -1
  42. package/dist/resources/extensions/gsd/escalation.js +4 -4
  43. package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
  44. package/dist/resources/extensions/gsd/forensics.js +74 -2
  45. package/dist/resources/extensions/gsd/gsd-db.js +42 -6
  46. package/dist/resources/extensions/gsd/guided-flow.js +119 -176
  47. package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
  48. package/dist/resources/extensions/gsd/mcp-project-config.js +76 -84
  49. package/dist/resources/extensions/gsd/memory-store.js +4 -1
  50. package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
  51. package/dist/resources/extensions/gsd/milestone-closeout.js +3 -1
  52. package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
  53. package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
  54. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  55. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  56. package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
  57. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  58. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  59. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  60. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  61. package/dist/resources/extensions/gsd/prompts/run-uat.md +33 -23
  62. package/dist/resources/extensions/gsd/prompts/system.md +3 -1
  63. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  64. package/dist/resources/extensions/gsd/recovery-classification.js +20 -0
  65. package/dist/resources/extensions/gsd/rule-registry.js +428 -52
  66. package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
  67. package/dist/resources/extensions/gsd/skill-activation.js +20 -3
  68. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +4 -2
  69. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
  70. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
  71. package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
  72. package/dist/resources/extensions/gsd/state.js +17 -14
  73. package/dist/resources/extensions/gsd/templates/plan.md +3 -1
  74. package/dist/resources/extensions/gsd/tool-contract.js +5 -0
  75. package/dist/resources/extensions/gsd/tool-presentation-plan.js +143 -0
  76. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
  77. package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
  78. package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
  79. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
  80. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  81. package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
  82. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +483 -6
  83. package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
  84. package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
  85. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  86. package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
  87. package/dist/resources/extensions/gsd/verification-gate.js +72 -1
  88. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -1
  89. package/dist/resources/extensions/gsd/workflow-mcp.js +5 -73
  90. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
  91. package/dist/resources/extensions/mcp-client/manager.js +31 -1
  92. package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
  93. package/dist/rtk.d.ts +7 -1
  94. package/dist/rtk.js +27 -11
  95. package/dist/update-check.d.ts +15 -1
  96. package/dist/update-check.js +87 -12
  97. package/dist/update-cmd.d.ts +1 -0
  98. package/dist/update-cmd.js +53 -2
  99. package/dist/web/standalone/.next/BUILD_ID +1 -1
  100. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  101. package/dist/web/standalone/.next/build-manifest.json +2 -2
  102. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  103. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  112. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/index.html +1 -1
  121. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  128. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  129. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  131. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  132. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  133. package/package.json +5 -3
  134. package/packages/cloud-mcp-gateway/package.json +2 -2
  135. package/packages/contracts/dist/workflow.d.ts +14 -0
  136. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  137. package/packages/contracts/dist/workflow.js +16 -0
  138. package/packages/contracts/dist/workflow.js.map +1 -1
  139. package/packages/contracts/package.json +1 -1
  140. package/packages/daemon/package.json +4 -4
  141. package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
  142. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  143. package/packages/gsd-agent-core/dist/agent-session.js +32 -0
  144. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  145. package/packages/gsd-agent-core/dist/index.d.ts +1 -0
  146. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  147. package/packages/gsd-agent-core/dist/index.js +1 -0
  148. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  149. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
  150. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
  151. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
  152. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
  153. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
  154. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  155. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  156. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  157. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
  158. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  159. package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
  160. package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
  161. package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
  162. package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
  163. package/packages/gsd-agent-core/package.json +6 -6
  164. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
  165. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
  167. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
  168. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  169. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  171. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  172. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  173. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
  176. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  177. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +92 -31
  178. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  179. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
  181. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  188. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  190. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
  194. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  196. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
  197. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  198. package/packages/gsd-agent-modes/package.json +7 -7
  199. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  200. package/packages/mcp-server/dist/remote-questions.js +23 -9
  201. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  203. package/packages/mcp-server/dist/workflow-tools.js +84 -2
  204. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  205. package/packages/mcp-server/package.json +3 -3
  206. package/packages/native/package.json +1 -1
  207. package/packages/pi-agent-core/dist/agent-loop.js +42 -3
  208. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  209. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  210. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  211. package/packages/pi-agent-core/dist/agent.js +2 -0
  212. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  213. package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  214. package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
  215. package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  216. package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
  217. package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  218. package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
  219. package/packages/pi-agent-core/dist/types.d.ts +6 -1
  220. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  221. package/packages/pi-agent-core/dist/types.js.map +1 -1
  222. package/packages/pi-agent-core/package.json +1 -1
  223. package/packages/pi-ai/dist/api-registry.d.ts +2 -0
  224. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  225. package/packages/pi-ai/dist/api-registry.js +23 -0
  226. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  227. package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
  228. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  229. package/packages/pi-ai/dist/image-models.generated.js +15 -0
  230. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  231. package/packages/pi-ai/dist/models.generated.d.ts +411 -39
  232. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  233. package/packages/pi-ai/dist/models.generated.js +504 -153
  234. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  235. package/packages/pi-ai/dist/stream.js +6 -6
  236. package/packages/pi-ai/dist/stream.js.map +1 -1
  237. package/packages/pi-ai/package.json +1 -1
  238. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
  239. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  240. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  243. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  245. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  246. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  247. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
  249. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  251. package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
  252. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  253. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
  254. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
  256. package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
  257. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
  259. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  260. package/packages/pi-coding-agent/package.json +7 -7
  261. package/packages/pi-tui/dist/terminal.d.ts +1 -0
  262. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  263. package/packages/pi-tui/dist/terminal.js +8 -4
  264. package/packages/pi-tui/dist/terminal.js.map +1 -1
  265. package/packages/pi-tui/package.json +1 -1
  266. package/packages/rpc-client/package.json +2 -2
  267. package/pkg/package.json +1 -1
  268. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
  269. package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
  270. package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
  271. package/src/resources/extensions/browser-tools/index.ts +60 -9
  272. package/src/resources/extensions/browser-tools/package.json +5 -1
  273. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
  274. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
  275. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
  276. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
  277. package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
  278. package/src/resources/extensions/gsd/auto/phases.ts +5 -3
  279. package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
  280. package/src/resources/extensions/gsd/auto-dispatch.ts +67 -0
  281. package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
  282. package/src/resources/extensions/gsd/auto-prompts.ts +106 -15
  283. package/src/resources/extensions/gsd/auto-recovery.ts +7 -7
  284. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
  285. package/src/resources/extensions/gsd/auto-start.ts +112 -17
  286. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  287. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -73
  288. package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
  289. package/src/resources/extensions/gsd/auto.ts +47 -5
  290. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +96 -4
  291. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
  292. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +81 -25
  293. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +70 -63
  294. package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
  295. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
  296. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  297. package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
  298. package/src/resources/extensions/gsd/commands/handlers/ops.ts +9 -5
  299. package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
  300. package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
  301. package/src/resources/extensions/gsd/commands-mcp-status.ts +136 -58
  302. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
  303. package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
  304. package/src/resources/extensions/gsd/config-overlay.ts +3 -1
  305. package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
  306. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  307. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
  308. package/src/resources/extensions/gsd/error-classifier.ts +2 -1
  309. package/src/resources/extensions/gsd/escalation.ts +4 -4
  310. package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
  311. package/src/resources/extensions/gsd/forensics.ts +99 -5
  312. package/src/resources/extensions/gsd/gsd-db.ts +46 -8
  313. package/src/resources/extensions/gsd/guided-flow.ts +215 -217
  314. package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
  315. package/src/resources/extensions/gsd/mcp-project-config.ts +105 -88
  316. package/src/resources/extensions/gsd/memory-store.ts +4 -1
  317. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  318. package/src/resources/extensions/gsd/milestone-closeout.ts +3 -1
  319. package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
  320. package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
  321. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  322. package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
  323. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  324. package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
  325. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  326. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  327. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  328. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  329. package/src/resources/extensions/gsd/prompts/run-uat.md +33 -23
  330. package/src/resources/extensions/gsd/prompts/system.md +3 -1
  331. package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  332. package/src/resources/extensions/gsd/recovery-classification.ts +20 -0
  333. package/src/resources/extensions/gsd/rule-registry.ts +558 -58
  334. package/src/resources/extensions/gsd/rule-types.ts +2 -0
  335. package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
  336. package/src/resources/extensions/gsd/skill-activation.ts +20 -2
  337. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +4 -2
  338. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
  339. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
  340. package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
  341. package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
  342. package/src/resources/extensions/gsd/state.ts +18 -14
  343. package/src/resources/extensions/gsd/templates/plan.md +3 -1
  344. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
  345. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +123 -0
  346. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +10 -2
  347. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
  348. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
  349. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
  350. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +12 -2
  351. package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
  352. package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
  353. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
  354. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
  355. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
  356. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
  357. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
  358. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  359. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
  360. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
  361. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
  362. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
  363. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
  364. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +40 -1
  365. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -0
  366. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
  367. package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
  368. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
  369. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
  370. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
  371. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
  372. package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
  373. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +31 -79
  374. package/src/resources/extensions/gsd/tests/gsd-rebuild.test.ts +199 -0
  375. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -0
  376. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
  377. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
  378. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +5 -3
  379. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
  380. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
  381. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
  382. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
  383. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
  384. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +72 -10
  385. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +13 -6
  386. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
  387. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +100 -0
  388. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +179 -0
  389. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
  390. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +63 -0
  391. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
  392. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
  394. package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
  395. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
  396. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
  397. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +39 -1
  398. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
  399. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
  400. package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
  401. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +83 -1
  402. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
  403. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
  404. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
  405. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
  406. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +79 -0
  407. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
  408. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
  409. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +4 -0
  410. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
  411. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
  412. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
  413. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
  414. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  415. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
  416. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  417. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
  418. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
  419. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
  420. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
  421. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
  422. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
  423. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
  424. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
  425. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +17 -2
  426. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +493 -0
  427. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +40 -0
  428. package/src/resources/extensions/gsd/tool-contract.ts +6 -0
  429. package/src/resources/extensions/gsd/tool-presentation-plan.ts +223 -0
  430. package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
  431. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
  432. package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
  433. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
  434. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  435. package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
  436. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +589 -8
  437. package/src/resources/extensions/gsd/types.ts +69 -5
  438. package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
  439. package/src/resources/extensions/gsd/unit-tool-contracts.ts +186 -0
  440. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  441. package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
  442. package/src/resources/extensions/gsd/verification-gate.ts +87 -1
  443. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -1
  444. package/src/resources/extensions/gsd/workflow-mcp.ts +5 -73
  445. package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
  446. package/src/resources/extensions/mcp-client/manager.ts +33 -1
  447. package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
  448. package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
  449. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
  450. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
  451. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_buildManifest.js +0 -0
  452. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_ssgManifest.js +0 -0
@@ -11,6 +11,7 @@ import { fileURLToPath } from 'node:url';
11
11
  import { extractUatType } from '../../files.ts';
12
12
  import { resolveSliceFile } from '../../paths.ts';
13
13
  import { buildRunUatPrompt, checkNeedsRunUat } from '../../auto-prompts.ts';
14
+ import { buildRunUatResultPresentation, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from '../../tool-presentation-plan.ts';
14
15
 
15
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
16
17
  const worktreePromptsDir = join(__dirname, '../..', 'prompts');
@@ -20,6 +21,8 @@ function loadPromptFromWorktree(name: string, vars: Record<string, string> = {})
20
21
  let content = readFileSync(path, 'utf-8');
21
22
  const effectiveVars = {
22
23
  skillActivation: 'If no installed skill clearly matches this unit, skip explicit skill activation and continue with the required workflow.',
24
+ canonicalPresentation: JSON.stringify(buildRunUatResultPresentation(), null, 2),
25
+ toolPresentationPlanId: RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
23
26
  ...vars,
24
27
  };
25
28
  for (const [key, value] of Object.entries(effectiveVars)) {
@@ -72,6 +75,38 @@ function makeBrowserObservableUatContent(mode = 'artifact-driven'): string {
72
75
  ].join('\n');
73
76
  }
74
77
 
78
+ function makeDeferredBrowserUatContent(): string {
79
+ return [
80
+ '# UAT File',
81
+ '',
82
+ '## UAT Type',
83
+ '',
84
+ '- UAT mode: artifact-driven',
85
+ '- Why this mode is sufficient: Node interaction tests exercise the real app.js render/event/localStorage loop through a DOM harness. Live browser, keyboard, responsive, and visual-polish UAT remain intentionally deferred to S02.',
86
+ '',
87
+ '## Smoke Test',
88
+ '',
89
+ 'Run `node --test tests/s01-static-interactions.test.js` and confirm all tests pass.',
90
+ '',
91
+ '## Test Cases',
92
+ '',
93
+ '1. Click the todo row edit control in the DOM harness.',
94
+ '2. Save changed text and reload/recreate the app from persisted localStorage.',
95
+ '3. Expected: the stored record shape remains unchanged.',
96
+ '',
97
+ '## Not Proven By This UAT',
98
+ '',
99
+ '- Final visual polish of edit controls.',
100
+ '- Keyboard usability through a real browser.',
101
+ '- Browser console and local network cleanliness.',
102
+ '',
103
+ '## Notes for Tester',
104
+ '',
105
+ 'S02 should capture browser evidence for the full loop rather than changing this persisted model.',
106
+ '',
107
+ ].join('\n');
108
+ }
109
+
75
110
  describe('run-uat', () => {
76
111
  test('(a) artifact-driven', () => {
77
112
  assert.deepStrictEqual(
@@ -232,8 +267,8 @@ test('(k) run-uat prompt template', () => {
232
267
  `prompt contains detected dynamic uatType value "${uatType}" after substitution`,
233
268
  );
234
269
  assert.ok(
235
- promptResult?.includes(`uatType: ${uatType}`) ?? false,
236
- `prompt contains dynamic uatType frontmatter value "${uatType}" after substitution`,
270
+ promptResult?.includes(`uatType: "${uatType}"`) ?? false,
271
+ `prompt contains dynamic uatType field "${uatType}" after substitution`,
237
272
  );
238
273
  assert.ok(
239
274
  !/\{\{[^}]+\}\}/.test(promptResult ?? ''),
@@ -249,7 +284,7 @@ test('(k) run-uat prompt template', () => {
249
284
  );
250
285
  });
251
286
 
252
- test('(k2) run-uat prompt references gsd_summary_save, not direct write', () => {
287
+ test('(k2) run-uat prompt references gsd_uat_result_save, not direct write', () => {
253
288
  const promptResult = loadPromptFromWorktree('run-uat', {
254
289
  workingDirectory: '/tmp/test-project',
255
290
  milestoneId: 'M001',
@@ -261,17 +296,25 @@ test('(k2) run-uat prompt references gsd_summary_save, not direct write', () =>
261
296
  });
262
297
 
263
298
  assert.ok(
264
- promptResult.includes('gsd_summary_save'),
265
- 'run-uat prompt should reference gsd_summary_save tool',
299
+ promptResult.includes('gsd_uat_result_save'),
300
+ 'run-uat prompt should reference gsd_uat_result_save tool',
301
+ );
302
+ assert.ok(
303
+ promptResult.includes('presentedTools') && promptResult.includes('blockedTools'),
304
+ 'run-uat prompt should specify the tool presentation contract',
266
305
  );
267
306
  assert.ok(
268
- promptResult.includes('artifact_type: "ASSESSMENT"'),
269
- 'run-uat prompt should specify ASSESSMENT artifact type',
307
+ !promptResult.includes('Call `gsd_summary_save`'),
308
+ 'run-uat prompt should not instruct direct summary-save UAT persistence',
270
309
  );
271
310
  assert.ok(
272
311
  !promptResult.includes('MUST write'),
273
312
  'run-uat prompt should not instruct direct file write in footer',
274
313
  );
314
+ assert.ok(
315
+ !promptResult.includes('Call `gsd_summary_save` with `artifact_type: "ASSESSMENT"`'),
316
+ 'run-uat prompt should not instruct the legacy summary-save UAT path',
317
+ );
275
318
  });
276
319
 
277
320
  test('(l) dispatch preconditions via resolveSliceFile', () => {
@@ -482,8 +525,8 @@ test('(n) stale replay guard', async () => {
482
525
  });
483
526
 
484
527
  test('(q) verdict in ASSESSMENT file skips UAT dispatch (file-based path)', async () => {
485
- // Regression test for #2644: run-uat prompt writes the verdict to
486
- // S{sid}-ASSESSMENT.md (via gsd_summary_save artifact_type:"ASSESSMENT"),
528
+ // Regression test for #2644: run-uat writes the verdict to
529
+ // S{sid}-ASSESSMENT.md through the structured UAT save path,
487
530
  // but checkNeedsRunUat only checked S{sid}-UAT.md — causing a stuck loop.
488
531
  const base = createFixtureBase();
489
532
  try {
@@ -679,11 +722,30 @@ test('(u) run-uat prompt promotes artifact-driven browser specs to browser-execu
679
722
  const prompt = await buildRunUatPrompt('M001', 'S01', uatRel, uatContent, base);
680
723
 
681
724
  assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`browser-executable`/);
682
- assert.match(prompt, /uatType: browser-executable/);
725
+ assert.match(prompt, /uatType: "browser-executable"/);
683
726
  assert.match(prompt, /use gsd-browser tools/i);
727
+ assert.match(prompt, /"browser_navigate"/);
728
+ assert.match(prompt, /"browser_assert"/);
684
729
  } finally {
685
730
  cleanup(base);
686
731
  }
687
732
  });
688
733
 
734
+ test('(v) run-uat prompt keeps deferred browser work artifact-driven', async () => {
735
+ const base = createFixtureBase();
736
+ try {
737
+ const uatRel = '.gsd/milestones/M001/slices/S01/S01-UAT.md';
738
+ const uatContent = makeDeferredBrowserUatContent();
739
+ writeSliceFile(base, 'M001', 'S01', 'UAT', uatContent);
740
+
741
+ const prompt = await buildRunUatPrompt('M001', 'S01', uatRel, uatContent, base);
742
+
743
+ assert.match(prompt, /\*\*Detected UAT mode:\*\*\s*`artifact-driven`/);
744
+ assert.match(prompt, /uatType: "artifact-driven"/);
745
+ assert.doesNotMatch(prompt, /uatType: "browser-executable"/);
746
+ assert.doesNotMatch(prompt, /"browser_navigate"/);
747
+ } finally {
748
+ cleanup(base);
749
+ }
750
+ });
689
751
  });
@@ -50,6 +50,7 @@ import { handleCompleteSlice } from "../../tools/complete-slice.ts";
50
50
  import { handleCompleteMilestone } from "../../tools/complete-milestone.ts";
51
51
  import { handleReopenTask } from "../../tools/reopen-task.ts";
52
52
  import { handleReopenSlice } from "../../tools/reopen-slice.ts";
53
+ import { handleReopenMilestone } from "../../tools/reopen-milestone.ts";
53
54
 
54
55
  // ── State derivation ──────────────────────────────────────────────────────
55
56
  import {
@@ -700,9 +701,7 @@ describe("state-machine-live-validation", () => {
700
701
  assert.match((result as any).error, /closed milestone/);
701
702
  });
702
703
 
703
- test("no reopen-milestone tool exists milestone completion is irrevocable (H5)", async () => {
704
- // This test documents the H5 finding: there is no handleReopenMilestone function.
705
- // A completed milestone can only be undone via direct DB manipulation.
704
+ test("closed milestone cannot be reopened by generic DB update", async () => {
706
705
  base = createFullFixture();
707
706
  openDatabase(join(base, ".gsd", "gsd.db"));
708
707
  insertMilestone({ id: "M001", title: "Done", status: "complete" });
@@ -710,10 +709,18 @@ describe("state-machine-live-validation", () => {
710
709
  const milestone = getMilestone("M001");
711
710
  assert.ok(isClosedStatus(milestone!.status), "milestone is closed");
712
711
 
713
- // The only escape is direct DB manipulation — no handler exists
714
- updateMilestoneStatus("M001", "active", null);
712
+ assert.throws(
713
+ () => updateMilestoneStatus("M001", "active", null),
714
+ /use gsd_milestone_reopen for an explicit reopen/,
715
+ );
716
+
717
+ const result = await handleReopenMilestone(
718
+ { milestoneId: "M001", reason: "regression surfaced after closure" },
719
+ base,
720
+ );
721
+ assert.ok(!("error" in result), `unexpected reopen error: ${"error" in result ? result.error : ""}`);
715
722
  const reopened = getMilestone("M001");
716
- assert.equal(reopened!.status, "active", "direct DB manipulation can reopen, but no tool exposes this");
723
+ assert.equal(reopened!.status, "active", "explicit reopen handler reopens the milestone");
717
724
  });
718
725
  });
719
726
 
@@ -48,6 +48,21 @@ describe("discoverMcpServerNames", () => {
48
48
  assert.deepEqual(result.sort(), ["server-a", "server-b", "shared"]);
49
49
  });
50
50
 
51
+ it("reads from .claude/settings.local.json for Claude Code project-local servers", () => {
52
+ const dir = mkdtempSync(join(tmpdir(), "mcp-filter-test-"));
53
+ mkdirSync(join(dir, ".claude"), { recursive: true });
54
+ writeFileSync(
55
+ join(dir, ".claude", "settings.local.json"),
56
+ JSON.stringify({ mcpServers: { "local-server": {}, "shared": {} } }),
57
+ );
58
+ writeFileSync(
59
+ join(dir, ".claude", "settings.json"),
60
+ JSON.stringify({ mcpServers: { "project-server": {}, "shared": {} } }),
61
+ );
62
+ const result = discoverMcpServerNames(dir);
63
+ assert.deepEqual(result.sort(), ["local-server", "project-server", "shared"]);
64
+ });
65
+
51
66
  it("handles .claude/settings.json missing gracefully", () => {
52
67
  const dir = mkdtempSync(join(tmpdir(), "mcp-filter-test-"));
53
68
  writeFileSync(
@@ -5,6 +5,8 @@ import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
 
7
7
  import {
8
+ buildProjectBrowserMcpServerConfig,
9
+ ensureClaudeCodeMcpJsonServerEnabled,
8
10
  ensureProjectWorkflowMcpConfig,
9
11
  GSD_BROWSER_MCP_SERVER_NAME,
10
12
  GSD_WORKFLOW_MCP_SERVER_NAME,
@@ -54,6 +56,14 @@ test("ensureProjectWorkflowMcpConfig creates .mcp.json with workflow and browser
54
56
  ]);
55
57
  assert.equal(browserArgs[mcpArgIndex + 6], projectRoot);
56
58
  assert.equal((browserServer as { cwd?: string })?.cwd, projectRoot);
59
+
60
+ const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
61
+ enabledMcpjsonServers?: string[];
62
+ };
63
+ assert.deepEqual(settings.enabledMcpjsonServers, [
64
+ GSD_WORKFLOW_MCP_SERVER_NAME,
65
+ GSD_BROWSER_MCP_SERVER_NAME,
66
+ ]);
57
67
  } finally {
58
68
  rmSync(projectRoot, { recursive: true, force: true });
59
69
  }
@@ -115,6 +125,11 @@ test("ensureProjectWorkflowMcpConfig uses custom workflow server name from env",
115
125
  assert.ok(parsed.mcpServers?.["custom-workflow"]);
116
126
  assert.ok(parsed.mcpServers?.[GSD_BROWSER_MCP_SERVER_NAME]);
117
127
  assert.equal(parsed.mcpServers?.[GSD_WORKFLOW_MCP_SERVER_NAME], undefined);
128
+
129
+ const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
130
+ enabledMcpjsonServers?: string[];
131
+ };
132
+ assert.deepEqual(settings.enabledMcpjsonServers, ["custom-workflow", GSD_BROWSER_MCP_SERVER_NAME]);
118
133
  } finally {
119
134
  rmSync(projectRoot, { recursive: true, force: true });
120
135
  }
@@ -136,6 +151,42 @@ test("ensureProjectWorkflowMcpConfig can disable the default browser MCP server"
136
151
  };
137
152
  assert.ok(parsed.mcpServers?.[GSD_WORKFLOW_MCP_SERVER_NAME]);
138
153
  assert.equal(parsed.mcpServers?.[GSD_BROWSER_MCP_SERVER_NAME], undefined);
154
+
155
+ const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
156
+ enabledMcpjsonServers?: string[];
157
+ };
158
+ assert.deepEqual(settings.enabledMcpjsonServers, [GSD_WORKFLOW_MCP_SERVER_NAME]);
159
+ } finally {
160
+ rmSync(projectRoot, { recursive: true, force: true });
161
+ }
162
+ });
163
+
164
+ test("buildProjectBrowserMcpServerConfig prefers newer gsd-browser on PATH", () => {
165
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-browser-"));
166
+
167
+ try {
168
+ const config = buildProjectBrowserMcpServerConfig(projectRoot, {
169
+ GSD_BROWSER_PATH_VERSION: "99.0.0",
170
+ });
171
+
172
+ assert.equal(config?.command, "gsd-browser");
173
+ assert.equal(config?.args?.[0], "mcp");
174
+ } finally {
175
+ rmSync(projectRoot, { recursive: true, force: true });
176
+ }
177
+ });
178
+
179
+ test("buildProjectBrowserMcpServerConfig keeps bundled browser when PATH version is older", () => {
180
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-browser-"));
181
+
182
+ try {
183
+ const config = buildProjectBrowserMcpServerConfig(projectRoot, {
184
+ GSD_BROWSER_PATH_VERSION: "0.0.1",
185
+ });
186
+
187
+ assert.equal(config?.command, process.execPath);
188
+ assert.match(config?.args?.[0] ?? "", /@opengsd[\/\\]gsd-browser[\/\\]bin[\/\\]gsd-browser/);
189
+ assert.equal(config?.args?.[1], "mcp");
139
190
  } finally {
140
191
  rmSync(projectRoot, { recursive: true, force: true });
141
192
  }
@@ -156,3 +207,52 @@ test("ensureProjectWorkflowMcpConfig is idempotent when config is already curren
156
207
  rmSync(projectRoot, { recursive: true, force: true });
157
208
  }
158
209
  });
210
+
211
+ test("ensureProjectWorkflowMcpConfig updates stale Claude Code MCP approval state", () => {
212
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-init-"));
213
+ mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
214
+ const settingsPath = join(projectRoot, ".claude", "settings.local.json");
215
+
216
+ try {
217
+ const first = ensureProjectWorkflowMcpConfig(projectRoot);
218
+ assert.equal(first.status, "created");
219
+
220
+ writeFileSync(
221
+ settingsPath,
222
+ `${JSON.stringify({
223
+ permissions: { allow: ["Bash(gh issue *)"] },
224
+ enabledMcpjsonServers: [],
225
+ disabledMcpjsonServers: [GSD_WORKFLOW_MCP_SERVER_NAME, GSD_BROWSER_MCP_SERVER_NAME],
226
+ }, null, 2)}\n`,
227
+ "utf-8",
228
+ );
229
+
230
+ const second = ensureProjectWorkflowMcpConfig(projectRoot);
231
+ assert.equal(second.status, "updated");
232
+
233
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8")) as {
234
+ permissions?: { allow?: string[] };
235
+ enabledMcpjsonServers?: string[];
236
+ disabledMcpjsonServers?: string[];
237
+ };
238
+ assert.deepEqual(settings.permissions?.allow, ["Bash(gh issue *)"]);
239
+ assert.deepEqual(settings.enabledMcpjsonServers, [
240
+ GSD_WORKFLOW_MCP_SERVER_NAME,
241
+ GSD_BROWSER_MCP_SERVER_NAME,
242
+ ]);
243
+ assert.deepEqual(settings.disabledMcpjsonServers, []);
244
+ } finally {
245
+ rmSync(projectRoot, { recursive: true, force: true });
246
+ }
247
+ });
248
+
249
+ test("ensureClaudeCodeMcpJsonServerEnabled is idempotent", () => {
250
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-init-"));
251
+
252
+ try {
253
+ assert.equal(ensureClaudeCodeMcpJsonServerEnabled(projectRoot, "gsd-workflow"), true);
254
+ assert.equal(ensureClaudeCodeMcpJsonServerEnabled(projectRoot, "gsd-workflow"), false);
255
+ } finally {
256
+ rmSync(projectRoot, { recursive: true, force: true });
257
+ }
258
+ });
@@ -1,14 +1,23 @@
1
1
  import test, { describe } from "node:test";
2
2
  import assert from "node:assert/strict";
3
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { createRequire } from "node:module";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+ import { pathToFileURL } from "node:url";
8
+ import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
3
9
 
4
10
  import {
11
+ formatMcpDiscoveryResult,
5
12
  formatMcpInitResult,
6
13
  formatMcpConnectionTestResult,
7
14
  formatMcpStatusReport,
8
15
  formatMcpServerDetail,
9
16
  hasHostMcpTool,
17
+ handleMcpStatus,
10
18
  type McpServerStatus,
11
19
  } from "../commands-mcp-status.ts";
20
+ import { clearMcpConfigCache } from "../../mcp-client/manager.ts";
12
21
 
13
22
  // ─── formatMcpStatusReport ──────────────────────────────────────────────────
14
23
 
@@ -49,6 +58,16 @@ describe("formatMcpStatusReport", () => {
49
58
  assert.match(result, /disabled/i);
50
59
  });
51
60
 
61
+ test("shows available state for servers that pass a status probe", () => {
62
+ const servers: McpServerStatus[] = [
63
+ { name: "gsd-workflow", transport: "stdio", connected: false, available: true, toolCount: 62, error: undefined },
64
+ ];
65
+ const result = formatMcpStatusReport(servers);
66
+ assert.match(result, /gsd-workflow/);
67
+ assert.match(result, /available — 62 tools/);
68
+ assert.doesNotMatch(result, /disconnected/);
69
+ });
70
+
52
71
  test("includes server count in header", () => {
53
72
  const servers: McpServerStatus[] = [
54
73
  { name: "a", transport: "stdio", connected: true, toolCount: 3, error: undefined },
@@ -113,6 +132,20 @@ describe("formatMcpServerDetail", () => {
113
132
  assert.match(result, /disconnected/i);
114
133
  });
115
134
 
135
+ test("shows available status with tool names", () => {
136
+ const result = formatMcpServerDetail({
137
+ name: "gsd-workflow",
138
+ transport: "stdio",
139
+ connected: false,
140
+ available: true,
141
+ toolCount: 1,
142
+ tools: ["gsd_milestone_status"],
143
+ error: undefined,
144
+ });
145
+ assert.match(result, /available/i);
146
+ assert.match(result, /gsd_milestone_status/);
147
+ });
148
+
116
149
  test("shows env warnings for server detail", () => {
117
150
  const result = formatMcpServerDetail({
118
151
  name: "warned",
@@ -128,6 +161,150 @@ describe("formatMcpServerDetail", () => {
128
161
  });
129
162
  });
130
163
 
164
+ describe("handleMcpStatus", () => {
165
+ test("probes configured stdio servers before reporting disconnected", async () => {
166
+ const previousGsdHome = process.env.GSD_HOME;
167
+ const originalCwd = process.cwd();
168
+ const projectDir = mkdtempSync(join(tmpdir(), "gsd-mcp-status-project-"));
169
+ const gsdHomeDir = mkdtempSync(join(tmpdir(), "gsd-mcp-status-home-"));
170
+ try {
171
+ process.env.GSD_HOME = gsdHomeDir;
172
+ process.chdir(projectDir);
173
+ mkdirSync(join(projectDir, ".gsd"), { recursive: true });
174
+
175
+ const require = createRequire(import.meta.url);
176
+ const mcpModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/mcp.js")).href;
177
+ const stdioModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/stdio.js")).href;
178
+ const serverPath = join(projectDir, "fake-mcp-server.mjs");
179
+ writeFileSync(
180
+ serverPath,
181
+ [
182
+ `const { McpServer } = await import(${JSON.stringify(mcpModuleUrl)});`,
183
+ `const { StdioServerTransport } = await import(${JSON.stringify(stdioModuleUrl)});`,
184
+ 'const server = new McpServer({ name: "fake", version: "1.0.0" }, { capabilities: { tools: {} } });',
185
+ 'server.tool("fake_tool", "Probe-visible tool", {}, async () => ({ content: [{ type: "text", text: "ok" }] }));',
186
+ 'await server.connect(new StdioServerTransport());',
187
+ ].join("\n"),
188
+ "utf-8",
189
+ );
190
+ writeFileSync(
191
+ join(projectDir, ".mcp.json"),
192
+ JSON.stringify({ mcpServers: { "gsd-workflow": { command: process.execPath, args: [serverPath] } } }),
193
+ "utf-8",
194
+ );
195
+
196
+ let message = "";
197
+ const ctx = {
198
+ getSystemPrompt: () => "",
199
+ ui: {
200
+ notify: (text: string) => {
201
+ message = text;
202
+ },
203
+ },
204
+ };
205
+
206
+ await handleMcpStatus("status", ctx as unknown as ExtensionCommandContext);
207
+
208
+ assert.match(message, /gsd-workflow/);
209
+ assert.match(message, /available — 1 tools/);
210
+ assert.doesNotMatch(message, /disconnected/);
211
+ } finally {
212
+ process.chdir(originalCwd);
213
+ if (previousGsdHome === undefined) delete process.env.GSD_HOME;
214
+ else process.env.GSD_HOME = previousGsdHome;
215
+ rmSync(projectDir, { recursive: true, force: true });
216
+ rmSync(gsdHomeDir, { recursive: true, force: true });
217
+ clearMcpConfigCache();
218
+ }
219
+ });
220
+
221
+ test("discovers the only configured server when no server name is provided", async () => {
222
+ const previousGsdHome = process.env.GSD_HOME;
223
+ const originalCwd = process.cwd();
224
+ const projectDir = mkdtempSync(join(tmpdir(), "gsd-mcp-discover-project-"));
225
+ const gsdHomeDir = mkdtempSync(join(tmpdir(), "gsd-mcp-discover-home-"));
226
+ try {
227
+ process.env.GSD_HOME = gsdHomeDir;
228
+ process.chdir(projectDir);
229
+
230
+ const require = createRequire(import.meta.url);
231
+ const mcpModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/mcp.js")).href;
232
+ const stdioModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/stdio.js")).href;
233
+ const serverPath = join(projectDir, "discover-mcp-server.mjs");
234
+ writeFileSync(
235
+ serverPath,
236
+ [
237
+ `const { McpServer } = await import(${JSON.stringify(mcpModuleUrl)});`,
238
+ `const { StdioServerTransport } = await import(${JSON.stringify(stdioModuleUrl)});`,
239
+ 'const server = new McpServer({ name: "fake", version: "1.0.0" }, { capabilities: { tools: {} } });',
240
+ 'server.tool("discover_tool", "Discover-visible tool", {}, async () => ({ content: [{ type: "text", text: "ok" }] }));',
241
+ 'await server.connect(new StdioServerTransport());',
242
+ ].join("\n"),
243
+ "utf-8",
244
+ );
245
+ writeFileSync(
246
+ join(projectDir, ".mcp.json"),
247
+ JSON.stringify({ mcpServers: { "gsd-workflow": { command: process.execPath, args: [serverPath] } } }),
248
+ "utf-8",
249
+ );
250
+
251
+ let message = "";
252
+ const ctx = {
253
+ getSystemPrompt: () => "",
254
+ ui: {
255
+ notify: (text: string) => {
256
+ message = text;
257
+ },
258
+ },
259
+ };
260
+
261
+ await handleMcpStatus("discover", ctx as unknown as ExtensionCommandContext);
262
+
263
+ assert.match(message, /MCP discovery completed for gsd-workflow/);
264
+ assert.match(message, /discover_tool/);
265
+ assert.doesNotMatch(message, /Usage: \/gsd mcp/);
266
+ } finally {
267
+ process.chdir(originalCwd);
268
+ if (previousGsdHome === undefined) delete process.env.GSD_HOME;
269
+ else process.env.GSD_HOME = previousGsdHome;
270
+ rmSync(projectDir, { recursive: true, force: true });
271
+ rmSync(gsdHomeDir, { recursive: true, force: true });
272
+ clearMcpConfigCache();
273
+ }
274
+ });
275
+ });
276
+
277
+ describe("formatMcpDiscoveryResult", () => {
278
+ test("summarizes discovered tools", () => {
279
+ const result = formatMcpDiscoveryResult({
280
+ ok: true,
281
+ server: "demo",
282
+ transport: "stdio",
283
+ toolCount: 1,
284
+ tools: ["ping"],
285
+ warnings: [],
286
+ });
287
+ assert.match(result, /discovery completed/i);
288
+ assert.match(result, /ping/);
289
+ assert.match(result, /mcp_call/);
290
+ });
291
+
292
+ test("summarizes discovery failures", () => {
293
+ const result = formatMcpDiscoveryResult({
294
+ ok: false,
295
+ server: "demo",
296
+ transport: "http",
297
+ toolCount: 0,
298
+ tools: [],
299
+ warnings: ["url references unset environment variable TOKEN."],
300
+ error: "bad config",
301
+ });
302
+ assert.match(result, /discovery failed/i);
303
+ assert.match(result, /bad config/);
304
+ assert.match(result, /TOKEN/);
305
+ });
306
+ });
307
+
131
308
  describe("formatMcpConnectionTestResult", () => {
132
309
  test("summarizes successful tools/list", () => {
133
310
  const result = formatMcpConnectionTestResult({
@@ -164,6 +341,8 @@ describe("formatMcpInitResult", () => {
164
341
  assert.match(result, /created project mcp config/i);
165
342
  assert.match(result, /\/tmp\/project\/\.mcp\.json/);
166
343
  assert.match(result, /mcp-capable clients/i);
344
+ assert.match(result, /workflow and gsd-browser MCP servers/i);
345
+ assert.match(result, /Pi Providers use the managed gsd-browser engine/i);
167
346
  assert.doesNotMatch(result, /claude code/i);
168
347
  });
169
348
 
@@ -11,6 +11,16 @@ import {
11
11
  import { createMemoryRelation, listRelationsFor } from '../memory-relations.ts';
12
12
  import { saveEmbedding, getEmbeddingForMemory } from '../memory-embeddings.ts';
13
13
 
14
+ function markProcessedUnits(count = 21): void {
15
+ const now = Date.now();
16
+ for (let i = 0; i < count; i++) {
17
+ markUnitProcessed(`unit/${i}`, `file-${i}`);
18
+ _getAdapter()!
19
+ .prepare('UPDATE memory_processed_units SET processed_at = :ts WHERE unit_key = :key')
20
+ .run({ ':ts': new Date(now + i * 1000).toISOString(), ':key': `unit/${i}` });
21
+ }
22
+ }
23
+
14
24
  // ═══════════════════════════════════════════════════════════════════════════
15
25
  // enforceMemoryCap — cascade cleanup of embeddings and relations
16
26
  // ═══════════════════════════════════════════════════════════════════════════
@@ -71,14 +81,7 @@ test('memory-decay: returns decayed memory IDs', () => {
71
81
  openDatabase(':memory:');
72
82
 
73
83
  // Insert processed units — decayStaleMemories needs at least N rows.
74
- const now = Date.now();
75
- for (let i = 0; i < 21; i++) {
76
- markUnitProcessed(`unit/${i}`, `file-${i}`);
77
- // small spacing to create deterministic ordering
78
- const row = _getAdapter()!
79
- .prepare('UPDATE memory_processed_units SET processed_at = :ts WHERE unit_key = :key');
80
- row.run({ ':ts': new Date(now + i * 1000).toISOString(), ':key': `unit/${i}` });
81
- }
84
+ markProcessedUnits();
82
85
 
83
86
  // Create memory with updated_at in the distant past
84
87
  createMemory({ category: 'pattern', content: 'stale entry', confidence: 0.9 });
@@ -98,6 +101,34 @@ test('memory-decay: returns decayed memory IDs', () => {
98
101
  closeDatabase();
99
102
  });
100
103
 
104
+ test('memory-decay: skips stale decision-sourced memories', () => {
105
+ openDatabase(':memory:');
106
+ markProcessedUnits();
107
+
108
+ createMemory({ category: 'pattern', content: 'stale working note', confidence: 0.9 });
109
+ createMemory({
110
+ category: 'architecture',
111
+ content: 'decision-backed architecture memory',
112
+ confidence: 0.85,
113
+ structuredFields: { sourceDecisionId: 'D001' },
114
+ });
115
+ _getAdapter()!
116
+ .prepare("UPDATE memories SET updated_at = '2000-01-01T00:00:00Z' WHERE id IN ('MEM001', 'MEM002')")
117
+ .run({});
118
+
119
+ const decayed = decayStaleMemories(20);
120
+ assert.ok(decayed.includes('MEM001'));
121
+ assert.ok(!decayed.includes('MEM002'));
122
+
123
+ const rows = _getAdapter()!
124
+ .prepare("SELECT id, confidence FROM memories WHERE id IN ('MEM001', 'MEM002') ORDER BY id")
125
+ .all() as Array<{ id: string; confidence: number }>;
126
+ assert.ok(rows.find((row) => row.id === 'MEM001')!.confidence < 0.9);
127
+ assert.equal(rows.find((row) => row.id === 'MEM002')!.confidence, 0.85);
128
+
129
+ closeDatabase();
130
+ });
131
+
101
132
  test('memory-decay: returns empty when there are fewer processed units than the threshold', () => {
102
133
  openDatabase(':memory:');
103
134
  createMemory({ category: 'pattern', content: 'fresh' });