@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
@@ -305,10 +305,18 @@ This config sets a parent workspace with two child repositories. The implicit `p
305
305
  - `max_cycles`: number — max times this hook fires per trigger (default: 1, max: 10).
306
306
  - `model`: string — optional model override.
307
307
  - `artifact`: string — expected output file name (relative to task/slice dir). Hook is skipped if file already exists (idempotent).
308
+ - `criticality`: `"advisory"` or `"blocking"` — advisory preserves current best-effort behavior; blocking requires clean hook completion plus a valid outcome verdict before auto-mode advances. Default: `"advisory"`.
308
309
  - `retry_on`: string — if this file is produced instead of the artifact, re-run the trigger unit then re-run hooks.
310
+ - `on_block`: object — optional routing for blocking findings:
311
+ - `action`: `"retry-unit"`, `"retry-task"`, `"queue-task"`, `"queue-slice"`, or `"pause"`.
312
+ - `artifact`: string — optional compatibility artifact for retry routing.
309
313
  - `agent`: string — agent definition file to use for hook execution.
310
314
  - `enabled`: boolean — toggle without removing (default: `true`).
311
315
 
316
+ Blocking hook artifacts must begin with YAML frontmatter containing either `verdict` or `outcome.verdict`.
317
+ Supported verdicts are `pass`, `advisory`, `needs-rework`, `needs-remediation`, and `needs-attention`.
318
+ `pass` and `advisory` continue; `needs-rework` retries the trigger unit when routed with `retry-unit`/`retry-task`; `needs-remediation` and `needs-attention` pause with recovery guidance.
319
+
312
320
  - `pre_dispatch_hooks`: array — hooks that fire before a unit is dispatched. Each entry has:
313
321
  - `name`: string — unique hook identifier.
314
322
  - `before`: string[] — unit types to intercept.
@@ -269,14 +269,14 @@ export async function checkRuntimeHealth(
269
269
  } catch {
270
270
  count = MAX_UAT_ATTEMPTS + 1;
271
271
  }
272
- if (count <= MAX_UAT_ATTEMPTS) continue;
272
+ if (count < MAX_UAT_ATTEMPTS) continue;
273
273
 
274
274
  issues.push({
275
275
  severity: "warning",
276
276
  code: "uat_retry_exhausted",
277
277
  scope: "slice",
278
278
  unitId: `${mid}/${sid}`,
279
- message: `run-uat for ${mid}/${sid} exhausted ${count - 1} retry attempt(s) without an ASSESSMENT verdict. Reset the retry counter after fixing the underlying UAT/tool issue, then rerun /gsd auto.`,
279
+ message: `run-uat for ${mid}/${sid} exhausted ${count} attempt(s) without an ASSESSMENT verdict. Reset the retry counter after fixing the underlying UAT/tool issue, then rerun /gsd auto.`,
280
280
  file: `.gsd/runtime/${fileName}`,
281
281
  fixable: true,
282
282
  });
@@ -47,9 +47,10 @@ export function resetRetryState(state: RetryState): void {
47
47
  const PERMANENT_RE = /auth|unauthorized|forbidden|invalid.*key|invalid.*api|billing|quota exceeded|account/i;
48
48
  // Include provider-specific quota-window phrasing like:
49
49
  // - "You've hit your limit"
50
+ // - "You've reached your limit"
50
51
  // - "usage limit" / "quota reached"
51
52
  // - "out of extra usage"
52
- const RATE_LIMIT_RE = /rate.?limit|too many requests|429|hit your limit|usage limit|out of extra usage|quota (?:reached|hit)|limit.*resets?/i;
53
+ const RATE_LIMIT_RE = /rate.?limit|too many requests|429|(?:hit|reached) your (?:\w+ )?limit|(?:usage|session|weekly|daily|monthly|quota) limit|out of extra usage|quota (?:reached|hit)|limit.*resets?/i;
53
54
  // OpenRouter affordability-style quota errors should be treated as transient
54
55
  // so core retry logic can lower maxTokens and continue in-session.
55
56
  const AFFORDABILITY_RE = /requires more credits|can only afford|insufficient credits|not enough credits|fewer max_tokens/i;
@@ -159,13 +159,13 @@ export function readEscalationArtifact(path: string): EscalationArtifact | null
159
159
  // ─── Detection ────────────────────────────────────────────────────────────
160
160
 
161
161
  /**
162
- * Returns the task id of the first task with an un-resolved pause-escalation
163
- * (escalation_pending=1, not yet respondedAt). awaiting_review slices are NOT
164
- * returned they don't pause the loop.
162
+ * Returns the task id of the first task with an unresolved escalation.
163
+ * `continueWithDefault=true` artifacts keep the awaiting_review flag for
164
+ * compatibility, but still pause dispatch until the user explicitly responds.
165
165
  */
166
166
  export function detectPendingEscalation(tasks: TaskRow[], basePath: string): string | null {
167
167
  for (const t of tasks) {
168
- if (t.escalation_pending !== 1) continue;
168
+ if (t.escalation_pending !== 1 && t.escalation_awaiting_review !== 1) continue;
169
169
  if (!t.escalation_artifact_path) continue;
170
170
  const art = readEscalationArtifact(t.escalation_artifact_path);
171
171
  if (art && !art.respondedAt) return t.id;
@@ -20,6 +20,8 @@ export interface ExecSandboxRequest {
20
20
  script: string;
21
21
  /** Optional purpose/label recorded in meta.json. */
22
22
  purpose?: string;
23
+ /** Optional structured metadata recorded in meta.json. */
24
+ metadata?: Record<string, unknown>;
23
25
  /** Per-invocation timeout in ms. Clamped to `clamp_timeout_ms`. */
24
26
  timeout_ms?: number;
25
27
  }
@@ -315,6 +317,7 @@ function writeMeta(
315
317
  id: result.id,
316
318
  runtime: result.runtime,
317
319
  purpose: request.purpose ?? null,
320
+ ...(request.metadata ? { metadata: request.metadata } : {}),
318
321
  script_chars: request.script.length,
319
322
  started_at: now.toISOString(),
320
323
  finished_at: new Date(now.getTime() + result.duration_ms).toISOString(),
@@ -328,6 +331,7 @@ function writeMeta(
328
331
  stderr_truncated: result.stderr_truncated,
329
332
  stdout_path: result.stdout_path,
330
333
  stderr_path: result.stderr_path,
334
+ ...(request.metadata ? { metadata: request.metadata } : {}),
331
335
  };
332
336
  writeFileSync(path, `${JSON.stringify(meta, null, 2)}\n`);
333
337
  }
@@ -123,6 +123,91 @@ interface ForensicReport {
123
123
  worktreeTelemetry: WorktreeTelemetrySummary | null;
124
124
  }
125
125
 
126
+ // ─── Filing Tool Scope ───────────────────────────────────────────────────────
127
+
128
+ const FORENSICS_FILING_TOOLS = ["bash", "write"] as const;
129
+
130
+ type ForensicsFilingTool = typeof FORENSICS_FILING_TOOLS[number];
131
+
132
+ export interface ForensicsToolScope {
133
+ savedTools: string[];
134
+ activeToolsForTurn: string[];
135
+ availableFilingTools: ForensicsFilingTool[];
136
+ missingFilingTools: ForensicsFilingTool[];
137
+ toolsChanged: boolean;
138
+ }
139
+
140
+ function uniqueAppend(base: readonly string[], additions: readonly string[]): string[] {
141
+ const seen = new Set(base);
142
+ const next = [...base];
143
+ for (const name of additions) {
144
+ if (seen.has(name)) continue;
145
+ seen.add(name);
146
+ next.push(name);
147
+ }
148
+ return next;
149
+ }
150
+
151
+ function sameOrderedTools(a: readonly string[], b: readonly string[]): boolean {
152
+ return a.length === b.length && a.every((name, index) => name === b[index]);
153
+ }
154
+
155
+ function getRegisteredToolNames(
156
+ pi: Pick<ExtensionAPI, "getActiveTools"> & Partial<Pick<ExtensionAPI, "getAllTools">>,
157
+ fallback: readonly string[],
158
+ ): string[] {
159
+ if (typeof pi.getAllTools === "function") {
160
+ return pi.getAllTools().map((tool) => tool.name);
161
+ }
162
+ return [...fallback];
163
+ }
164
+
165
+ export function createForensicsToolScope(
166
+ pi: Pick<ExtensionAPI, "getActiveTools"> & Partial<Pick<ExtensionAPI, "getAllTools">>,
167
+ ): ForensicsToolScope {
168
+ const savedTools = [...pi.getActiveTools()];
169
+ const registeredTools = new Set([...getRegisteredToolNames(pi, savedTools), ...savedTools]);
170
+ const availableFilingTools = FORENSICS_FILING_TOOLS.filter((name) => registeredTools.has(name));
171
+ const missingFilingTools = FORENSICS_FILING_TOOLS.filter((name) => !registeredTools.has(name));
172
+ const activeToolsForTurn = uniqueAppend(savedTools, availableFilingTools);
173
+
174
+ return {
175
+ savedTools,
176
+ activeToolsForTurn,
177
+ availableFilingTools,
178
+ missingFilingTools,
179
+ toolsChanged: !sameOrderedTools(savedTools, activeToolsForTurn),
180
+ };
181
+ }
182
+
183
+ export function applyForensicsToolScope(pi: Pick<ExtensionAPI, "setActiveTools">, scope: ForensicsToolScope): void {
184
+ if (scope.toolsChanged) pi.setActiveTools(scope.activeToolsForTurn);
185
+ }
186
+
187
+ export function restoreForensicsToolScope(pi: Pick<ExtensionAPI, "setActiveTools">, scope: ForensicsToolScope): void {
188
+ if (scope.toolsChanged) pi.setActiveTools(scope.savedTools);
189
+ }
190
+
191
+ export function buildForensicsToolingSection(scope: ForensicsToolScope): string {
192
+ const available = new Set(scope.availableFilingTools);
193
+ const requested = scope.availableFilingTools.length
194
+ ? scope.availableFilingTools.map((name) => `\`${name}\``).join(", ")
195
+ : "none";
196
+ const statusFor = (name: ForensicsFilingTool) => available.has(name)
197
+ ? `- \`${name}\`: available for this queued forensics turn`
198
+ : `- \`${name}\`: unavailable in this host session`;
199
+
200
+ return `
201
+ ## Filing Tool Availability
202
+
203
+ For this queued forensic turn, the extension requested the registered filing tools: ${requested}.
204
+
205
+ ${FORENSICS_FILING_TOOLS.map(statusFor).join("\n")}
206
+
207
+ If \`bash\` is available, use the GitHub duplicate-check and issue-creation protocols below. If \`bash\` is unavailable, do not attempt duplicate-check or issue-creation tool calls with another tool; provide the paste-once shell script fallback instead.
208
+ `;
209
+ }
210
+
126
211
  // ─── Duplicate Detection ──────────────────────────────────────────────────────
127
212
 
128
213
  const DEDUP_PROMPT_SECTION = `
@@ -134,6 +219,8 @@ Before reading GSD source code or performing deep analysis, you MUST search for
134
219
 
135
220
  Use keywords from the user's problem description and the anomaly summaries in the forensic report above.
136
221
 
222
+ If \`bash\` is unavailable in the Filing Tool Availability section, do not attempt live duplicate-search tool calls. Say the live duplicate search must be run by the user, continue the source investigation, and include the duplicate-search commands in the paste-once fallback when issue filing is accepted.
223
+
137
224
  1. **Search closed issues** for similar keywords:
138
225
  \`\`\`
139
226
  gh issue list --repo open-gsd/gsd-pi --state closed --search "<keywords from root cause>" --limit 20
@@ -265,21 +352,28 @@ export async function handleForensics(
265
352
  }
266
353
 
267
354
  const forensicData = formatReportForPrompt(report);
355
+ const toolScope = createForensicsToolScope(pi);
268
356
  const content = loadPrompt("forensics", {
269
357
  problemDescription,
270
358
  forensicData,
271
359
  gsdSourceDir,
272
360
  dedupSection,
361
+ toolingSection: buildForensicsToolingSection(toolScope),
273
362
  });
274
363
 
275
364
  ctx.ui.notify(`Forensic report saved: ${relative(basePath, savedPath)}`, "info");
276
365
  ctx.ui.setStatus("gsd-forensics", "running");
277
366
 
278
- pi.sendMessage(
279
- { customType: "gsd-forensics", content, display: false },
280
- { triggerTurn: true },
281
- );
282
- ctx.ui.setStatus("gsd-forensics", undefined);
367
+ try {
368
+ applyForensicsToolScope(pi, toolScope);
369
+ await pi.sendMessage(
370
+ { customType: "gsd-forensics", content, display: false },
371
+ { triggerTurn: true },
372
+ );
373
+ } finally {
374
+ restoreForensicsToolScope(pi, toolScope);
375
+ ctx.ui.setStatus("gsd-forensics", undefined);
376
+ }
283
377
 
284
378
  // Persist forensics context so follow-up turns can re-inject it (#2941)
285
379
  writeForensicsMarker(basePath, savedPath, content);
@@ -55,6 +55,7 @@ import {
55
55
  import { rowToGate } from "./db-gate-rows.js";
56
56
  import { rowToArtifact, rowToMilestone, type ArtifactRow, type MilestoneRow } from "./db-milestone-artifact-rows.js";
57
57
  import { backupDatabaseBeforeMigration } from "./db-migration-backup.js";
58
+ import { isClosedStatus } from "./status-guards.js";
58
59
  import {
59
60
  applyMigrationV2Artifacts,
60
61
  applyMigrationV3Memories,
@@ -1487,7 +1488,7 @@ export function setTaskEscalationPending(
1487
1488
  ).run({ ":path": artifactPath, ":mid": milestoneId, ":sid": sliceId, ":tid": taskId });
1488
1489
  }
1489
1490
 
1490
- /** Set awaiting-review state (artifact exists but continueWithDefault=true, no pause). Mutually exclusive with pending. */
1491
+ /** Set awaiting-review state (artifact exists and requires explicit user review). Mutually exclusive with pending. */
1491
1492
  export function setTaskEscalationAwaitingReview(
1492
1493
  milestoneId: string, sliceId: string, taskId: string,
1493
1494
  artifactPath: string,
@@ -1665,16 +1666,50 @@ export function setMilestoneQueueOrder(order: string[]): void {
1665
1666
  }
1666
1667
  }
1667
1668
 
1669
+ function getMilestoneStatusForUpdate(milestoneId: string): string | null {
1670
+ if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1671
+ const row = currentDb.prepare("SELECT status FROM milestones WHERE id = :id").get({ ":id": milestoneId });
1672
+ return typeof row?.["status"] === "string" ? row["status"] : null;
1673
+ }
1674
+
1675
+ function writeMilestoneStatus(milestoneId: string, status: string, completedAt?: string | null): void {
1676
+ if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1677
+ currentDb.prepare(
1678
+ `UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`,
1679
+ ).run({ ":status": status, ":completed_at": completedAt ?? null, ":id": milestoneId });
1680
+ }
1681
+
1668
1682
  /**
1669
1683
  * Update a milestone's status in the database.
1670
- * Used by park/unpark to keep the DB in sync with the filesystem marker.
1671
- * See: https://github.com/open-gsd/gsd-pi/issues/2694
1684
+ *
1685
+ * Generic status updates may close milestones, park/unpark open milestones, or
1686
+ * advance planned milestones. They may not reopen a closed milestone; callers
1687
+ * must use reopenMilestoneStatus(), which is reserved for gsd_milestone_reopen.
1672
1688
  */
1673
1689
  export function updateMilestoneStatus(milestoneId: string, status: string, completedAt?: string | null): void {
1674
1690
  if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1675
- currentDb.prepare(
1676
- `UPDATE milestones SET status = :status, completed_at = :completed_at WHERE id = :id`,
1677
- ).run({ ":status": status, ":completed_at": completedAt ?? null, ":id": milestoneId });
1691
+ const currentStatus = getMilestoneStatusForUpdate(milestoneId);
1692
+ if (currentStatus && isClosedStatus(currentStatus) && !isClosedStatus(status)) {
1693
+ throw new Error(
1694
+ `Cannot update closed milestone ${milestoneId} from ${currentStatus} to ${status}; use gsd_milestone_reopen for an explicit reopen.`,
1695
+ );
1696
+ }
1697
+ writeMilestoneStatus(milestoneId, status, completedAt);
1698
+ }
1699
+
1700
+ /**
1701
+ * Explicit closed -> active transition for gsd_milestone_reopen only.
1702
+ */
1703
+ export function reopenMilestoneStatus(milestoneId: string): void {
1704
+ if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1705
+ const currentStatus = getMilestoneStatusForUpdate(milestoneId);
1706
+ if (!currentStatus) {
1707
+ throw new Error(`Cannot reopen missing milestone ${milestoneId}`);
1708
+ }
1709
+ if (!isClosedStatus(currentStatus)) {
1710
+ throw new Error(`Cannot reopen milestone ${milestoneId} from status ${currentStatus}; milestone is not closed.`);
1711
+ }
1712
+ writeMilestoneStatus(milestoneId, "active", null);
1678
1713
  }
1679
1714
 
1680
1715
  export function getActiveMilestoneFromDb(): MilestoneRow | null {
@@ -2708,7 +2743,7 @@ export function deleteArtifactByPath(path: string): void {
2708
2743
 
2709
2744
  /**
2710
2745
  * Drop hierarchy rows in dependency order inside a transaction. Used by
2711
- * `gsd recover` to rebuild engine state from markdown.
2746
+ * `gsd recover --confirm` to rebuild engine state from markdown.
2712
2747
  */
2713
2748
  export function clearEngineHierarchy(): void {
2714
2749
  if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
@@ -3198,7 +3233,10 @@ export function decayMemoriesBefore(cutoffTs: string, now: string): void {
3198
3233
  currentDb.prepare(
3199
3234
  `UPDATE memories
3200
3235
  SET confidence = MAX(0.1, confidence - 0.1), updated_at = :now
3201
- WHERE superseded_by IS NULL AND updated_at < :cutoff AND confidence > 0.1`,
3236
+ WHERE superseded_by IS NULL
3237
+ AND updated_at < :cutoff
3238
+ AND confidence > 0.1
3239
+ AND (structured_fields IS NULL OR structured_fields NOT LIKE '%"sourceDecisionId"%')`,
3202
3240
  ).run({ ":now": now, ":cutoff": cutoffTs });
3203
3241
  }
3204
3242
 
@@ -227,21 +227,22 @@ async function dispatchDiscussForNextMilestoneWithBacklog(
227
227
  nextId: string,
228
228
  ): Promise<void> {
229
229
  const backlogContext = buildRequirementsBacklogDiscussContext(nextId);
230
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
231
230
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
232
- const basePrompt = loadPrompt("guided-discuss-milestone", {
233
- workingDirectory: basePath,
234
- milestoneId: nextId,
235
- milestoneTitle: `New milestone ${nextId}`,
236
- inlinedTemplates: discussMilestoneTemplates,
231
+ const basePrompt = await buildDiscussMilestonePrompt(
232
+ nextId,
233
+ `New milestone ${nextId}`,
234
+ basePath,
237
235
  structuredQuestionsAvailable,
238
- commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
239
- fastPathInstruction: [
240
- "> **Requirements backlog active.**",
241
- "> Map unmapped active requirements to this milestone before finalizing context.",
242
- "> Confirm ownership with the user when scope is ambiguous.",
243
- ].join("\n"),
244
- });
236
+ {
237
+ commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
238
+ includeContextMode: false,
239
+ fastPathInstruction: [
240
+ "> **Requirements backlog active.**",
241
+ "> Map unmapped active requirements to this milestone before finalizing context.",
242
+ "> Confirm ownership with the user when scope is ambiguous.",
243
+ ].join("\n"),
244
+ },
245
+ );
245
246
  const prompt = backlogContext ? `${basePrompt}\n\n${backlogContext}` : basePrompt;
246
247
  await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
247
248
  }
@@ -1371,6 +1372,7 @@ async function buildDiscussPreparationContext(
1371
1372
  ctx: ExtensionCommandContext,
1372
1373
  basePath: string,
1373
1374
  mode: "greenfield" | "milestone" = "greenfield",
1375
+ skipPriorContext = false,
1374
1376
  ): Promise<string> {
1375
1377
  const prefs = loadEffectiveGSDPreferences()?.preferences ?? {};
1376
1378
  if (prefs.discuss_preparation === false) return "";
@@ -1388,7 +1390,7 @@ async function buildDiscussPreparationContext(
1388
1390
  const priorContextBrief = prepResult.priorContextBrief || formatPriorContextBrief(prepResult.priorContext);
1389
1391
  const parts: string[] = [];
1390
1392
  if (codebaseBrief) parts.push(`### Codebase Brief\n\n${codebaseBrief}`);
1391
- if (priorContextBrief) parts.push(`### Prior Context Brief\n\n${priorContextBrief}`);
1393
+ if (priorContextBrief && !skipPriorContext) parts.push(`### Prior Context Brief\n\n${priorContextBrief}`);
1392
1394
  if (parts.length === 0) return "";
1393
1395
 
1394
1396
  const guidance = mode === "milestone"
@@ -1441,18 +1443,18 @@ async function dispatchNewMilestoneDiscuss(
1441
1443
  return;
1442
1444
  }
1443
1445
 
1444
- const preparationContext = await buildDiscussPreparationContext(ctx, basePath, "milestone");
1445
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
1446
+ const preparationContext = await buildDiscussPreparationContext(ctx, basePath, "milestone", true);
1446
1447
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
1447
- let prompt = loadPrompt("guided-discuss-milestone", {
1448
- workingDirectory: basePath,
1449
- milestoneId: nextId,
1450
- milestoneTitle: `New milestone ${nextId}`,
1451
- inlinedTemplates: discussMilestoneTemplates,
1448
+ let prompt = await buildDiscussMilestonePrompt(
1449
+ nextId,
1450
+ `New milestone ${nextId}`,
1451
+ basePath,
1452
1452
  structuredQuestionsAvailable,
1453
- commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
1454
- fastPathInstruction: "",
1455
- });
1453
+ {
1454
+ commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
1455
+ includeContextMode: false,
1456
+ },
1457
+ );
1456
1458
  if (preparationContext) prompt += preparationContext;
1457
1459
  await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
1458
1460
  }
@@ -1759,9 +1761,6 @@ export async function showDiscuss(
1759
1761
  // Special case: milestone is in needs-discussion phase (has CONTEXT-DRAFT.md but no roadmap yet).
1760
1762
  // Route to the draft discussion flow instead of erroring — the discussion IS how the roadmap gets created.
1761
1763
  if (state.phase === "needs-discussion") {
1762
- const draftFile = resolveMilestoneFile(basePath, mid, "CONTEXT-DRAFT");
1763
- const draftContent = draftFile ? await loadFile(draftFile) : null;
1764
-
1765
1764
  const choice = await showNextAction(ctx, {
1766
1765
  title: `GSD — ${mid}: ${milestoneTitle}`,
1767
1766
  summary: ["This milestone has a draft context from a prior discussion.", "It needs a dedicated discussion before auto-planning can begin."],
@@ -1787,29 +1786,34 @@ export async function showDiscuss(
1787
1786
  });
1788
1787
 
1789
1788
  if (choice === "discuss_draft") {
1790
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
1791
1789
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
1792
- const basePrompt = loadPrompt("guided-discuss-milestone", {
1793
- workingDirectory: basePath,
1794
- milestoneId: mid, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
1795
- commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
1796
- fastPathInstruction: "",
1797
- });
1798
- const seed = draftContent
1799
- ? `${basePrompt}\n\n## Prior Discussion (Draft Seed)\n\n${draftContent}`
1800
- : basePrompt;
1790
+ const seed = await buildDiscussMilestonePrompt(
1791
+ mid,
1792
+ milestoneTitle,
1793
+ basePath,
1794
+ structuredQuestionsAvailable,
1795
+ {
1796
+ commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
1797
+ includeContextMode: false,
1798
+ },
1799
+ );
1801
1800
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: mid, step: true });
1802
1801
  await dispatchWorkflow(pi, seed, "gsd-discuss", ctx, "discuss-milestone", { basePath });
1803
1802
  } else if (choice === "discuss_fresh") {
1804
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
1805
1803
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
1804
+ const prompt = await buildDiscussMilestonePrompt(
1805
+ mid,
1806
+ milestoneTitle,
1807
+ basePath,
1808
+ structuredQuestionsAvailable,
1809
+ {
1810
+ commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
1811
+ includeContextMode: false,
1812
+ includeDraftSeed: false,
1813
+ },
1814
+ );
1806
1815
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: mid, step: true });
1807
- await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
1808
- workingDirectory: basePath,
1809
- milestoneId: mid, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
1810
- commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
1811
- fastPathInstruction: "",
1812
- }), "gsd-discuss", ctx, "discuss-milestone", { basePath });
1816
+ await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
1813
1817
  } else if (choice === "skip_milestone") {
1814
1818
  const { ensureDbOpen } = await import("./bootstrap/dynamic-tools.js");
1815
1819
  await ensureDbOpen(basePath);
@@ -2068,20 +2072,18 @@ async function dispatchDiscussForMilestone(
2068
2072
  "> Ask only questions where the answer would materially change scope.",
2069
2073
  ].join("\n")
2070
2074
  : "";
2071
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
2072
2075
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
2073
- const basePrompt = loadPrompt("guided-discuss-milestone", {
2074
- workingDirectory: basePath,
2075
- milestoneId: mid,
2076
+ const prompt = await buildDiscussMilestonePrompt(
2077
+ mid,
2076
2078
  milestoneTitle,
2077
- inlinedTemplates: discussMilestoneTemplates,
2079
+ basePath,
2078
2080
  structuredQuestionsAvailable,
2079
- commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
2080
- fastPathInstruction,
2081
- });
2082
- const prompt = draftContent
2083
- ? `${basePrompt}\n\n## Prior Discussion (Draft Seed)\n\n${draftContent}`
2084
- : basePrompt;
2081
+ {
2082
+ commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
2083
+ includeContextMode: false,
2084
+ fastPathInstruction,
2085
+ },
2086
+ );
2085
2087
  await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
2086
2088
  }
2087
2089
 
@@ -2374,7 +2376,7 @@ export async function showSmartEntry(
2374
2376
  if (result.action === "recovery-required") {
2375
2377
  ctx.ui.notify(
2376
2378
  result.message ??
2377
- `Markdown planning artifacts do not match the authoritative DB. Run \`${result.recoveryCommand ?? "/gsd recover"}\` to import markdown explicitly.`,
2379
+ `Markdown planning artifacts do not match the authoritative DB. Run \`${result.recoveryCommand ?? "/gsd recover --confirm"}\` to import markdown explicitly.`,
2378
2380
  "warning",
2379
2381
  );
2380
2382
  }
@@ -2612,9 +2614,6 @@ export async function showSmartEntry(
2612
2614
 
2613
2615
  // ── Draft milestone — needs discussion before planning ────────────────
2614
2616
  if (state.phase === "needs-discussion") {
2615
- const draftFile = resolveMilestoneFile(basePath, milestoneId, "CONTEXT-DRAFT");
2616
- const draftContent = draftFile ? await loadFile(draftFile) : null;
2617
-
2618
2617
  const choice = await showNextAction(ctx, {
2619
2618
  title: `GSD — ${milestoneId}: ${milestoneTitle}`,
2620
2619
  summary: ["This milestone has a draft context from a prior discussion.", "It needs a dedicated discussion before auto-planning can begin."],
@@ -2640,29 +2639,34 @@ export async function showSmartEntry(
2640
2639
  });
2641
2640
 
2642
2641
  if (choice === "discuss_draft") {
2643
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
2644
2642
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
2645
- const basePrompt = loadPrompt("guided-discuss-milestone", {
2646
- workingDirectory: basePath,
2647
- milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
2648
- commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2649
- fastPathInstruction: "",
2650
- });
2651
- const seed = draftContent
2652
- ? `${basePrompt}\n\n## Prior Discussion (Draft Seed)\n\n${draftContent}`
2653
- : basePrompt;
2643
+ const seed = await buildDiscussMilestonePrompt(
2644
+ milestoneId,
2645
+ milestoneTitle,
2646
+ basePath,
2647
+ structuredQuestionsAvailable,
2648
+ {
2649
+ commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2650
+ includeContextMode: false,
2651
+ },
2652
+ );
2654
2653
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId, step: stepMode });
2655
2654
  await dispatchWorkflow(pi, seed, "gsd-discuss", ctx, "discuss-milestone", { basePath });
2656
2655
  } else if (choice === "discuss_fresh") {
2657
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
2658
2656
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
2657
+ const prompt = await buildDiscussMilestonePrompt(
2658
+ milestoneId,
2659
+ milestoneTitle,
2660
+ basePath,
2661
+ structuredQuestionsAvailable,
2662
+ {
2663
+ commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2664
+ includeContextMode: false,
2665
+ includeDraftSeed: false,
2666
+ },
2667
+ );
2659
2668
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId, step: stepMode });
2660
- await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
2661
- workingDirectory: basePath,
2662
- milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
2663
- commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2664
- fastPathInstruction: "",
2665
- }), "gsd-discuss", ctx, "discuss-milestone", { basePath });
2669
+ await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
2666
2670
  } else if (choice === "skip_milestone") {
2667
2671
  const milestoneIds = findMilestoneIds(basePath);
2668
2672
  const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
@@ -2783,14 +2787,18 @@ export async function showSmartEntry(
2783
2787
  { basePath },
2784
2788
  );
2785
2789
  } else if (choice === "discuss") {
2786
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
2787
2790
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
2788
- await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
2789
- workingDirectory: basePath,
2790
- milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
2791
- commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2792
- fastPathInstruction: "",
2793
- }), "gsd-run", ctx, "discuss-milestone", { basePath });
2791
+ const prompt = await buildDiscussMilestonePrompt(
2792
+ milestoneId,
2793
+ milestoneTitle,
2794
+ basePath,
2795
+ structuredQuestionsAvailable,
2796
+ {
2797
+ commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2798
+ includeContextMode: false,
2799
+ },
2800
+ );
2801
+ await dispatchWorkflow(pi, prompt, "gsd-run", ctx, "discuss-milestone", { basePath });
2794
2802
  } else if (choice === "skip_milestone") {
2795
2803
  const milestoneIds = findMilestoneIds(basePath);
2796
2804
  const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
@@ -40,9 +40,11 @@ function collectServerEntries(servers: unknown): DiscoveredMcpServer[] {
40
40
  export function discoverMcpServers(projectDir: string): DiscoveredMcpServer[] {
41
41
  const mcpJsonPath = resolve(projectDir, ".mcp.json");
42
42
  const settingsPath = resolve(projectDir, ".claude", "settings.json");
43
+ const localSettingsPath = resolve(projectDir, ".claude", "settings.local.json");
43
44
 
44
45
  const mcpJson = readJsonFile(mcpJsonPath) as McpJsonFile | undefined;
45
46
  const settings = readJsonFile(settingsPath, true) as ClaudeSettingsFile | undefined;
47
+ const localSettings = readJsonFile(localSettingsPath, true) as ClaudeSettingsFile | undefined;
46
48
 
47
49
  const seen = new Set<string>();
48
50
  const discovered: DiscoveredMcpServer[] = [];
@@ -50,6 +52,7 @@ export function discoverMcpServers(projectDir: string): DiscoveredMcpServer[] {
50
52
  ...collectServerEntries(mcpJson?.mcpServers),
51
53
  ...collectServerEntries(mcpJson?.servers),
52
54
  ...collectServerEntries(settings?.mcpServers),
55
+ ...collectServerEntries(localSettings?.mcpServers),
53
56
  ]) {
54
57
  if (seen.has(entry.name)) continue;
55
58
  seen.add(entry.name);