@opengsd/gsd-pi 1.2.0-dev.5457a158 → 1.2.0-dev.822c9439

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 (489) hide show
  1. package/dist/headless-events.js +7 -5
  2. package/dist/mcp-server.js +2 -1
  3. package/dist/resource-loader.d.ts +9 -5
  4. package/dist/resource-loader.js +114 -6
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/GSD-WORKFLOW.md +5 -4
  7. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  8. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  9. package/dist/resources/extensions/async-jobs/index.js +65 -0
  10. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  11. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  12. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  13. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  14. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  15. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  16. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  17. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  18. package/dist/resources/extensions/browser-tools/index.js +69 -12
  19. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +3 -2
  20. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  21. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  22. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  23. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  25. package/dist/resources/extensions/gsd/auto/orchestrator.js +89 -54
  26. package/dist/resources/extensions/gsd/auto/phases.js +49 -6
  27. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  28. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  29. package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
  30. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
  31. package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
  32. package/dist/resources/extensions/gsd/auto-prompts.js +78 -19
  33. package/dist/resources/extensions/gsd/auto-start.js +12 -12
  34. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  35. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
  36. package/dist/resources/extensions/gsd/auto-verification.js +23 -30
  37. package/dist/resources/extensions/gsd/auto-worktree.js +14 -1
  38. package/dist/resources/extensions/gsd/auto.js +37 -1
  39. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  40. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
  41. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
  42. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  43. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  44. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +172 -59
  45. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
  46. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  47. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  48. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  49. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  50. package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
  51. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  52. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  53. package/dist/resources/extensions/gsd/constants.js +0 -2
  54. package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
  55. package/dist/resources/extensions/gsd/db/queries.js +26 -0
  56. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  57. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  58. package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
  59. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  60. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  61. package/dist/resources/extensions/gsd/files.js +33 -19
  62. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  63. package/dist/resources/extensions/gsd/gsd-db.js +2 -1
  64. package/dist/resources/extensions/gsd/guidance.js +60 -0
  65. package/dist/resources/extensions/gsd/guided-flow.js +6 -3
  66. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  67. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  68. package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
  69. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  70. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  71. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  72. package/dist/resources/extensions/gsd/preferences-models.js +2 -2
  73. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  74. package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  75. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  77. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  79. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  80. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  81. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  82. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  83. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  84. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  85. package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
  86. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  87. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  88. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  89. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  90. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  91. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  92. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  93. package/dist/resources/extensions/gsd/state.js +5 -0
  94. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  95. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  96. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  97. package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
  98. package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
  99. package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -0
  100. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
  101. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  102. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  103. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  104. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  105. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  106. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  107. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
  108. package/dist/resources/extensions/gsd/uat-policy.js +42 -16
  109. package/dist/resources/extensions/gsd/unit-context-composer.js +65 -0
  110. package/dist/resources/extensions/gsd/unit-registry.js +7 -20
  111. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  112. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  113. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  114. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  115. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  116. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  117. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  118. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  119. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  120. package/dist/resources/extensions/gsd/worktree.js +8 -1
  121. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  122. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  123. package/dist/resources/extensions/shared/gsd-browser-cli.js +116 -6
  124. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  125. package/dist/resources/shared/package-manager-detection.js +1 -1
  126. package/dist/resources/shared/package.json +3 -0
  127. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  128. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  129. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  130. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  131. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  132. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  133. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  134. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  135. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  136. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  137. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  138. package/dist/update-check.d.ts +2 -0
  139. package/dist/update-check.js +24 -1
  140. package/dist/update-cmd.js +20 -3
  141. package/dist/web/standalone/.next/BUILD_ID +1 -1
  142. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  143. package/dist/web/standalone/.next/build-manifest.json +3 -3
  144. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  145. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  146. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  147. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  153. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  154. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  155. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  156. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  158. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  159. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  161. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  164. package/dist/web/standalone/.next/server/app/index.html +1 -1
  165. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  166. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  167. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  168. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  169. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  170. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  171. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  172. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  173. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  176. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  177. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  178. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  179. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  180. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  181. package/dist/web/standalone/package.json +1 -1
  182. package/package.json +1 -1
  183. package/packages/cloud-mcp-gateway/package.json +2 -2
  184. package/packages/contracts/dist/rpc.d.ts +1 -0
  185. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  186. package/packages/contracts/dist/rpc.js.map +1 -1
  187. package/packages/contracts/package.json +1 -1
  188. package/packages/daemon/package.json +4 -4
  189. package/packages/gsd-agent-core/package.json +5 -5
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  198. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  201. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  202. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  203. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  204. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  205. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  206. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  207. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  208. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  209. package/packages/gsd-agent-modes/package.json +7 -7
  210. package/packages/mcp-server/dist/cli.js +10 -5
  211. package/packages/mcp-server/dist/cli.js.map +1 -1
  212. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  213. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  214. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  215. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  216. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  217. package/packages/mcp-server/dist/server.js +4 -0
  218. package/packages/mcp-server/dist/server.js.map +1 -1
  219. package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
  220. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  221. package/packages/mcp-server/dist/workflow-tools.js +99 -38
  222. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  223. package/packages/mcp-server/package.json +5 -4
  224. package/packages/native/package.json +1 -1
  225. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  226. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  227. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  228. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  229. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  230. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  231. package/packages/pi-agent-core/dist/index.js +3 -0
  232. package/packages/pi-agent-core/dist/index.js.map +1 -1
  233. package/packages/pi-agent-core/package.json +1 -1
  234. package/packages/pi-ai/README.md +1 -0
  235. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  236. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  237. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  238. package/packages/pi-ai/dist/index.d.ts +2 -0
  239. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  240. package/packages/pi-ai/dist/index.js +2 -0
  241. package/packages/pi-ai/dist/index.js.map +1 -1
  242. package/packages/pi-ai/dist/models.generated.d.ts +239 -153
  243. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  244. package/packages/pi-ai/dist/models.generated.js +256 -145
  245. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  246. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  247. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  248. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  249. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  250. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  252. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  255. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  256. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  257. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  258. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  259. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  260. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  261. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  262. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  263. package/packages/pi-ai/package.json +3 -2
  264. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  265. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  267. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  270. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  272. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  274. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  276. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/index.js +1 -1
  278. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  280. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  282. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  283. package/packages/pi-coding-agent/package.json +7 -7
  284. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  285. package/packages/pi-tui/dist/tui.js +9 -0
  286. package/packages/pi-tui/dist/tui.js.map +1 -1
  287. package/packages/pi-tui/package.json +2 -2
  288. package/packages/rpc-client/package.json +2 -2
  289. package/pkg/package.json +1 -1
  290. package/src/resources/GSD-WORKFLOW.md +5 -4
  291. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  292. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  293. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  294. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  295. package/src/resources/extensions/async-jobs/index.ts +79 -0
  296. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  297. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  298. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  299. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  300. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  301. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  302. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  303. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  304. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  305. package/src/resources/extensions/browser-tools/index.ts +71 -13
  306. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  307. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
  308. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  309. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +3 -2
  310. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  311. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  312. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  313. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  314. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  315. package/src/resources/extensions/gsd/auto/orchestrator.ts +98 -56
  316. package/src/resources/extensions/gsd/auto/phases.ts +65 -26
  317. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  318. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  319. package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
  320. package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
  321. package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
  322. package/src/resources/extensions/gsd/auto-prompts.ts +115 -35
  323. package/src/resources/extensions/gsd/auto-start.ts +12 -14
  324. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  325. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
  326. package/src/resources/extensions/gsd/auto-verification.ts +26 -28
  327. package/src/resources/extensions/gsd/auto-worktree.ts +14 -1
  328. package/src/resources/extensions/gsd/auto.ts +44 -1
  329. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  330. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
  331. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
  332. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  333. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  334. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +211 -59
  335. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
  336. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  337. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  338. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  339. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  340. package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
  341. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  342. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  343. package/src/resources/extensions/gsd/constants.ts +0 -3
  344. package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
  345. package/src/resources/extensions/gsd/db/queries.ts +37 -0
  346. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  347. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  348. package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
  349. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  350. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  351. package/src/resources/extensions/gsd/files.ts +33 -12
  352. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  353. package/src/resources/extensions/gsd/gsd-db.ts +4 -3
  354. package/src/resources/extensions/gsd/guidance.ts +78 -0
  355. package/src/resources/extensions/gsd/guided-flow.ts +21 -26
  356. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  357. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  358. package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
  359. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  360. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  361. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  362. package/src/resources/extensions/gsd/preferences-models.ts +2 -1
  363. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  364. package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  365. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
  366. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  367. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  368. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  369. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  370. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  371. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  372. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  373. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  374. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  375. package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
  376. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  377. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  378. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  379. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  380. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  381. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  382. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  383. package/src/resources/extensions/gsd/state.ts +5 -0
  384. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
  385. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
  386. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  387. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  388. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  389. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  390. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  391. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  392. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  393. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  394. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  395. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  396. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  397. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  398. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  399. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  400. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  401. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  402. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  403. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  404. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  405. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  406. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  407. package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
  408. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
  409. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +7 -11
  410. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +20 -58
  411. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  412. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  413. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  414. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
  415. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  416. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  417. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  418. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
  419. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  420. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  421. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  422. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  423. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +19 -1
  424. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  425. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  426. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  427. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  428. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
  429. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +44 -0
  430. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  431. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  432. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  433. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  434. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  435. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
  436. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  437. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  438. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  439. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  440. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  441. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  442. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  443. package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
  444. package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
  445. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -0
  446. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
  447. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  448. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  449. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  450. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  451. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  452. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  453. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
  454. package/src/resources/extensions/gsd/uat-policy.ts +62 -16
  455. package/src/resources/extensions/gsd/unit-context-composer.ts +99 -0
  456. package/src/resources/extensions/gsd/unit-registry.ts +7 -20
  457. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  458. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  459. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  460. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  461. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  462. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  463. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  464. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  465. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  466. package/src/resources/extensions/gsd/worktree.ts +7 -1
  467. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  468. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  469. package/src/resources/extensions/shared/gsd-browser-cli.ts +141 -6
  470. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  471. package/src/resources/shared/package-manager-detection.ts +1 -1
  472. package/src/resources/shared/package.json +3 -0
  473. package/src/resources/skills/create-skill/SKILL.md +3 -0
  474. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  475. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  476. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  477. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  478. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  479. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  480. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  481. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  482. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  483. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  484. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  485. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  486. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  487. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  488. /package/dist/web/standalone/.next/static/{2p9Rv9pQflAxCBbGVI2vb → yWwBo-w09Y_W-nmeeWFRp}/_buildManifest.js +0 -0
  489. /package/dist/web/standalone/.next/static/{2p9Rv9pQflAxCBbGVI2vb → yWwBo-w09Y_W-nmeeWFRp}/_ssgManifest.js +0 -0
@@ -1,6 +1,7 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { resolve } from "node:path";
4
+ import { isGsdBrowserMcpServerConfig } from "../shared/gsd-browser-cli.js";
4
5
  import { toMcpWildcardToolName } from "./mcp-tool-name.js";
5
6
  import { resolveModelMcpConfig } from "./preferences-mcp.js";
6
7
  function isRecord(value) {
@@ -63,29 +64,11 @@ function isWorkflowMcpServerConfig(config) {
63
64
  const args = Array.isArray(config.args) ? config.args.filter((arg) => typeof arg === "string") : [];
64
65
  return args.some((arg) => arg.includes("gsd-mcp-server") || arg.includes("packages/mcp-server"));
65
66
  }
66
- function isBrowserMcpServerConfig(config) {
67
- if (!isRecord(config))
68
- return false;
69
- const command = typeof config.command === "string" ? config.command : "";
70
- if (command.includes("gsd-browser") || command.includes("@opengsd/gsd-browser")) {
71
- return true;
72
- }
73
- const env = config.env;
74
- if (isRecord(env)) {
75
- if (typeof env.GSD_BROWSER_CLI_PATH === "string"
76
- || typeof env.GSD_BROWSER_BIN_PATH === "string"
77
- || typeof env.GSD_BROWSER_MCP_COMMAND === "string") {
78
- return true;
79
- }
80
- }
81
- const args = Array.isArray(config.args) ? config.args.filter((arg) => typeof arg === "string") : [];
82
- return args.some((arg) => arg.includes("gsd-browser") || arg.includes("@opengsd/gsd-browser"));
83
- }
84
67
  export function discoverWorkflowMcpServerName(projectDir) {
85
68
  return discoverMcpServers(projectDir).find((server) => isWorkflowMcpServerConfig(server.config))?.name;
86
69
  }
87
70
  export function discoverBrowserMcpServerName(projectDir) {
88
- return discoverMcpServers(projectDir).find((server) => isBrowserMcpServerConfig(server.config))?.name;
71
+ return discoverMcpServers(projectDir).find((server) => isGsdBrowserMcpServerConfig(server.config))?.name;
89
72
  }
90
73
  export function discoverMcpServerNames(projectDir) {
91
74
  return discoverMcpServers(projectDir).map((server) => server.name);
@@ -4,13 +4,16 @@
4
4
  // - preflight: dispatch git clean before complete-milestone agent (auto-dispatch)
5
5
  // - postUnit: git commit, artifact verify, DB settle, then GitHub finalize
6
6
  // - recovery: DB repair from artifacts, then GitHub finalize
7
+ import { existsSync } from "node:fs";
7
8
  import { loadFile } from "./files.js";
8
- import { parseRoadmap } from "./parsers-legacy.js";
9
9
  import { resolveMilestoneFile } from "./paths.js";
10
- import { getMilestone, getMilestoneSlices, isDbAvailable } from "./gsd-db.js";
10
+ import { getMilestone, getClosedSliceIds, getLatestAssessmentByScope, getMilestoneSlices, isDbAvailable, } from "./gsd-db.js";
11
11
  import { isClosedStatus } from "./status-guards.js";
12
+ import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
13
+ import { handleCompleteMilestone } from "./tools/complete-milestone.js";
12
14
  import { runSafely } from "./auto-utils.js";
13
15
  import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
16
+ import { uatSignoffBlockerGuidance } from "./guidance.js";
14
17
  import { logWarning } from "./workflow-logger.js";
15
18
  import { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
16
19
  import { buildCompleteMilestonePrompt } from "./auto-prompts.js";
@@ -19,6 +22,60 @@ import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
19
22
  import { commitPendingMilestoneCloseoutChanges, findMissingSummaries, isVerificationNotApplicable, readUatGateVerdict, } from "./auto-dispatch.js";
20
23
  const COMPLETE_MILESTONE_DB_SETTLE_MS = 1500;
21
24
  const COMPLETE_MILESTONE_DB_SETTLE_POLL_MS = 100;
25
+ /**
26
+ * True when a milestone is terminal for git cleanup (orphaned worktrees, stale branches).
27
+ * DB-authoritative (ADR-017): closed status, or validation-pass with all slices closed.
28
+ * When the DB is unavailable we cannot make this decision and conservatively
29
+ * return false so callers leave the worktree/branch alone instead of cleaning
30
+ * up based on parsed projections.
31
+ */
32
+ export async function isCompletedMilestoneTerminal(_basePath, milestoneId) {
33
+ if (!isDbAvailable())
34
+ return false;
35
+ const milestone = getMilestone(milestoneId);
36
+ if (!milestone)
37
+ return false;
38
+ if (isClosedStatus(milestone.status)) {
39
+ return true;
40
+ }
41
+ const validation = getLatestAssessmentByScope(milestoneId, "milestone-validation");
42
+ if (validation?.status !== "pass") {
43
+ return false;
44
+ }
45
+ const slices = getMilestoneSlices(milestoneId);
46
+ if (slices.length === 0)
47
+ return false;
48
+ return slices.every((slice) => isClosedStatus(slice.status));
49
+ }
50
+ /** Write a missing milestone SUMMARY projection when canonical DB closeout already settled. */
51
+ export async function repairMissingMilestoneSummaryProjection(basePath, milestoneId) {
52
+ const milestone = getMilestone(milestoneId);
53
+ if (!milestone) {
54
+ return { ok: false, error: `milestone not found: ${milestoneId}` };
55
+ }
56
+ const artifactBasePath = resolveCanonicalMilestoneRoot(basePath, milestoneId);
57
+ const summaryPath = resolveExpectedArtifactPath("complete-milestone", milestoneId, artifactBasePath);
58
+ if (summaryPath && existsSync(summaryPath)) {
59
+ return { ok: true };
60
+ }
61
+ const result = await handleCompleteMilestone({
62
+ milestoneId,
63
+ title: milestone.title,
64
+ oneLiner: "Canonical closeout completed; summary projection repaired automatically.",
65
+ narrative: "The workflow database recorded this milestone as complete, but the milestone SUMMARY artifact was missing on disk. " +
66
+ "Dispatch policy repaired the projection so closeout proof and cleanup can proceed.",
67
+ verificationPassed: true,
68
+ triggerReason: "closeout-projection-repair",
69
+ }, basePath);
70
+ if ("error" in result) {
71
+ return { ok: false, error: result.error };
72
+ }
73
+ const writtenSummaryPath = result.summaryPath;
74
+ if (result.stale || !writtenSummaryPath || !existsSync(writtenSummaryPath)) {
75
+ return { ok: false, error: "milestone SUMMARY projection write failed" };
76
+ }
77
+ return { ok: true };
78
+ }
22
79
  /**
23
80
  * True when the milestone is closed in the DB and the completion summary artifact exists.
24
81
  * Polls briefly so post-unit verification can observe the tool's DB write.
@@ -65,38 +122,42 @@ export async function evaluateCompleteMilestoneDispatch(ctx) {
65
122
  if (isDbAvailable()) {
66
123
  const milestone = getMilestone(mid);
67
124
  if (milestone && isClosedStatus(milestone.status)) {
68
- return { action: "skip" };
125
+ const artifactBasePath = resolveCanonicalMilestoneRoot(basePath, mid);
126
+ const summaryPath = resolveExpectedArtifactPath("complete-milestone", mid, artifactBasePath);
127
+ const summaryMissing = !summaryPath || !existsSync(summaryPath);
128
+ if (summaryMissing) {
129
+ const repair = await repairMissingMilestoneSummaryProjection(basePath, mid);
130
+ if (!repair.ok) {
131
+ logWarning("dispatch", `Milestone ${mid} is closed in DB but SUMMARY repair failed: ${repair.error}. Dispatching complete-milestone to retry.`);
132
+ }
133
+ else {
134
+ return { action: "skip" };
135
+ }
136
+ }
137
+ else {
138
+ return { action: "skip" };
139
+ }
69
140
  }
70
141
  }
71
142
  const closeoutGitStop = commitPendingMilestoneCloseoutChanges(basePath, mid);
72
143
  if (closeoutGitStop)
73
144
  return closeoutGitStop;
74
145
  if (prefs?.uat_dispatch) {
75
- let closedSliceIds;
76
- if (isDbAvailable()) {
77
- closedSliceIds = getMilestoneSlices(mid)
78
- .filter((slice) => isClosedStatus(slice.status))
79
- .map((slice) => slice.id);
80
- }
81
- else {
82
- const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
83
- const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
84
- if (!roadmapContent) {
85
- return {
86
- action: "stop",
87
- reason: `Cannot complete milestone ${mid}: unable to verify UAT verdicts because ROADMAP is unavailable while DB is not accessible.`,
88
- level: "warning",
89
- };
90
- }
91
- const roadmap = parseRoadmap(roadmapContent);
92
- closedSliceIds = roadmap.slices.filter((slice) => slice.done).map((slice) => slice.id);
146
+ // DB-authoritative (ADR-017): UAT sign-off gating never parses the
147
+ // ROADMAP projection. Without a DB we cannot verify — stop conservatively.
148
+ if (!isDbAvailable()) {
149
+ return {
150
+ action: "stop",
151
+ reason: `Cannot complete milestone ${mid}: unable to verify UAT verdicts because the workflow DB is not accessible.`,
152
+ level: "warning",
153
+ };
93
154
  }
94
- for (const sliceId of closedSliceIds) {
155
+ for (const sliceId of getClosedSliceIds(mid)) {
95
156
  const result = await readUatGateVerdict(basePath, mid, sliceId);
96
157
  if (!result) {
97
158
  return {
98
159
  action: "stop",
99
- reason: `Cannot complete milestone ${mid}: missing UAT PASS verdict for ${sliceId}. Manual UAT sign-off (PASS) is required before milestone closure.`,
160
+ reason: uatSignoffBlockerGuidance(mid, sliceId),
100
161
  level: "warning",
101
162
  };
102
163
  }
@@ -104,7 +165,7 @@ export async function evaluateCompleteMilestoneDispatch(ctx) {
104
165
  if (!isAcceptableUatVerdict(verdict, uatType)) {
105
166
  return {
106
167
  action: "stop",
107
- reason: `Cannot complete milestone ${mid}: UAT verdict for ${sliceId} is "${verdict}". Manual UAT sign-off (PASS) is required before milestone closure.`,
168
+ reason: uatSignoffBlockerGuidance(mid, sliceId, verdict),
108
169
  level: "warning",
109
170
  };
110
171
  }
@@ -5,7 +5,7 @@ import { isClosedStatus } from "./status-guards.js";
5
5
  import { transaction, getMilestone, getMilestoneSlices, getSlice, insertMilestone, insertSlice, upsertMilestonePlanning, upsertSlicePlanning, } from "./gsd-db.js";
6
6
  import { invalidateStateCache } from "./state.js";
7
7
  import { renderRoadmapFromDb } from "./markdown-renderer.js";
8
- import { renderAllProjections } from "./workflow-projections.js";
8
+ import { flushWorkflowProjections } from "./projection-flush.js";
9
9
  import { writeManifest } from "./workflow-manifest.js";
10
10
  import { appendEvent } from "./workflow-events.js";
11
11
  import { logWarning } from "./workflow-logger.js";
@@ -109,7 +109,7 @@ async function renderPlanArtifacts(basePath, params) {
109
109
  }
110
110
  async function runPostPlanHooks(basePath, params) {
111
111
  try {
112
- await renderAllProjections(basePath, params.milestoneId);
112
+ await flushWorkflowProjections(basePath, { milestoneId: params.milestoneId });
113
113
  writeManifest(basePath);
114
114
  appendEvent(basePath, {
115
115
  cmd: "plan-milestone",
@@ -1,11 +1,9 @@
1
- import { join } from "node:path";
2
- import { gsdRoot } from "./paths.js";
1
+ import { workflowEventArchivePath, workflowEventLogPath } from "./workflow-event-ledger.js";
3
2
  import { readEvents } from "./workflow-events.js";
4
3
  export function latestExplicitReopenAt(basePath, milestoneId) {
5
- const root = gsdRoot(basePath);
6
4
  const candidates = [
7
- join(root, "event-log.jsonl"),
8
- join(root, `event-log-${milestoneId}.jsonl.archived`),
5
+ workflowEventLogPath(basePath),
6
+ workflowEventArchivePath(basePath, milestoneId),
9
7
  ];
10
8
  let latest = null;
11
9
  for (const file of candidates) {
@@ -1,10 +1,22 @@
1
1
  // GSD Extension - Legacy Parsers
2
2
  // parseRoadmap() and parsePlan() extracted from files.ts.
3
- // Used only by: md-importer.ts (migration), state.ts (pre-migration fallback),
4
- // markdown-renderer.ts (detectStaleRenders disk-vs-DB comparison),
5
- // commands-maintenance.ts (cold-path branch cleanup), and tests.
6
3
  //
7
- // NOT used in the dispatch loop or any hot-path runtime code.
4
+ // ADR-017: the DB is the single source of truth; `.gsd/*.md` files are
5
+ // projections. These parsers may be imported ONLY for:
6
+ // - migration/import (md-importer, workflow-migration, migration-auto-check)
7
+ // - drift detection that compares both sources by design
8
+ // (state-reconciliation/drift, markdown-renderer stale-render detection)
9
+ // - explicit pre-migration / DB-unavailable fallbacks (state.ts,
10
+ // reactive-graph.ts, auto-recovery.ts)
11
+ // - diagnostics and display/telemetry-only surfaces (doctor,
12
+ // doctor-git-checks, workspace-index, visualizer-data, auto-prompts
13
+ // context text, commands-maintenance, milestone-closeout, github-sync)
14
+ // - tests
15
+ //
16
+ // Dispatch/gate/completion DECISION paths must NOT import this module — they
17
+ // read the DB via gsd-db queries (e.g. getMilestoneSliceSummaries). Enforced
18
+ // by tests/parsers-legacy-importers.test.ts; new importers must be added to
19
+ // its allowlist with a one-line justification.
8
20
  import { extractSection, parseBullets, extractBoldField, extractAllSections, registerCacheClearCallback } from './files.js';
9
21
  import { splitFrontmatter } from '../shared/frontmatter.js';
10
22
  import { nativeParseRoadmap, nativeParsePlanFile } from './native-parser-bridge.js';
@@ -162,8 +162,8 @@ export function resolveThinkingLevelForUnit(unitType) {
162
162
  * Returns `{ provider, id }` or `undefined` if no model preference is
163
163
  * configured.
164
164
  */
165
- export function resolveDefaultSessionModel(sessionProvider) {
166
- const prefs = loadEffectiveGSDPreferences(undefined, { availableModelIds: [] });
165
+ export function resolveDefaultSessionModel(sessionProvider, basePath) {
166
+ const prefs = loadEffectiveGSDPreferences(basePath, { availableModelIds: [] });
167
167
  const models = prefs?.preferences?.models;
168
168
  if (!models)
169
169
  return undefined;
@@ -0,0 +1,7 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Single workflow projection flush seam for mutation exits.
3
+ import { renderAllProjections } from "./workflow-projections.js";
4
+ export async function flushWorkflowProjections(basePath, scope) {
5
+ await renderAllProjections(basePath, scope.milestoneId);
6
+ return { milestoneId: scope.milestoneId };
7
+ }
@@ -24,7 +24,7 @@ Use `subagent` only when useful: reviewer, security, or tester. Apply findings b
24
24
 
25
25
  1. Use the inlined Slice Summary and UAT templates.
26
26
  2. {{skillActivation}}
27
- 3. Run all slice-level verification through `gsd_exec` / Context Mode evidence; refresh current state if needed. Do not use direct `bash` for verification commands.
27
+ 3. Run all slice-level verification through `gsd_exec` / Context Mode evidence; refresh current state if needed. Do not use direct `bash` for verification commands. See the prepended **Tool Surface** block for unavailable tools.
28
28
  4. Complete only when every required check passes. If verification fails or source changes are needed, do **not** edit source files in this unit and do **not** call `gsd_slice_complete`.
29
29
  5. If verification fails:
30
30
  - Task-specific regressions: if the failure is in files the task touched and pre-task verification evidence shows it was absent before that task ran, call `gsd_task_reopen` with that task and reason.
@@ -36,7 +36,7 @@ Use `subagent` only when useful: reviewer, security, or tester. Apply findings b
36
36
  8. Address every Gate to Close. Q8 = **Operational Readiness**: health signal, failure signal, recovery, monitoring gaps. Omit empty sections.
37
37
  9. If requirement status changed, call `gsd_requirement_update`; do not write `.gsd/REQUIREMENTS.md` directly.
38
38
  10. Prepare `gsd_slice_complete` content with camelCase fields `milestoneId`, `sliceId`, `sliceTitle`, `oneLiner`, `narrative`, `verification`, and `uatContent`.
39
- 11. Draft concrete UAT with preconditions, steps, expected outcomes, edge cases, and UAT Type.
39
+ 11. Draft concrete UAT with preconditions, steps, expected outcomes, edge cases, and UAT Type. Declare the type as a bullet under a `## UAT Type` heading, exactly like `- UAT mode: browser-executable`.
40
40
  **Web apps:** when inlined Web App UAT guidance is present, declare `browser-executable` or `runtime-executable` (not `artifact-driven`) for localhost/browser/screenshot steps; include dev-server preconditions and name Playwright specs when they exist.
41
41
  12. Review the inlined task-summary excerpts for DECISIONS.md/KNOWLEDGE.md-worthy decisions and gotchas. Read full `*-SUMMARY.md` only if needed. Capture with `capture_thought`; do not append knowledge files.
42
42
  13. When verification passes, call `gsd_slice_complete`. The DB-backed tool is the canonical write path. Do **not** manually write `{{sliceSummaryPath}}`. Do **not** manually write `{{sliceUatPath}}`. Do not edit roadmap checkboxes.
@@ -49,4 +49,4 @@ Use `subagent` only when useful: reviewer, security, or tester. Apply findings b
49
49
 
50
50
  **You MUST call `gsd_slice_complete` with summary and UAT content only after verification passes.**
51
51
 
52
- When done, say: "Slice {{sliceId}} complete."
52
+ When done, say: "Slice {{sliceId}} complete." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -76,4 +76,4 @@ Keep about **{{verificationBudget}}** for verification and summary. If context i
76
76
 
77
77
  **You MUST call `gsd_task_complete` before finishing, including when the stale-path safety rule stops execution.**
78
78
 
79
- When done, say: "Task {{taskId}} complete."
79
+ When done, say: "Task {{taskId}} complete." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -118,4 +118,4 @@ If external API keys or secrets are required, use the inlined **Secrets Manifest
118
118
 
119
119
  If no external API keys or secrets are required, skip this step; do not create an empty manifest.
120
120
 
121
- When done, say: "Milestone {{milestoneId}} planned."
121
+ When done, say: "Milestone {{milestoneId}} planned." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -57,4 +57,4 @@ The slice directory already exists. Do not mkdir.
57
57
 
58
58
  **You MUST call `gsd_plan_slice` to persist planning state before finishing, unless the stale-path safety rule above stops the unit before safe planning can occur.**
59
59
 
60
- When done, say: "Slice {{sliceId}} planned."
60
+ When done, say: "Slice {{sliceId}} planned." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -37,4 +37,4 @@ You are executing a GSD quick task — a lightweight, focused unit of work outsi
37
37
  - <what was tested/verified>
38
38
  ```
39
39
 
40
- When done, say: "Quick task {{taskNum}} complete."
40
+ When done, say: "Quick task {{taskNum}} complete." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -67,4 +67,4 @@ If `.gsd/REQUIREMENTS.md` exists and requirement ownership or status changed, up
67
67
 
68
68
  **DB access safety:** Do NOT query `.gsd/gsd.db` directly via `sqlite3` or `node -e require('better-sqlite3')`. Use `gsd_milestone_status` to read current milestone and slice state. All roadmap mutations go through `gsd_reassess_roadmap` — the tool writes to the DB and re-renders ROADMAP.md atomically.
69
69
 
70
- When done, say: "Roadmap reassessed."
70
+ When done, say: "Roadmap reassessed." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -77,4 +77,4 @@ The slice directory and tasks/ subdirectory already exist. Do NOT mkdir.
77
77
 
78
78
  **You MUST call `gsd_plan_slice` to persist planning state before finishing.** After success, the pipeline clears the sketch flag on next state derivation; the on-disk PLAN file is the signal.
79
79
 
80
- When done, say: "Slice {{sliceId}} refined."
80
+ When done, say: "Slice {{sliceId}} refined." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -38,4 +38,4 @@ Consider these captures when rewriting the remaining tasks — they represent th
38
38
  4. If any incomplete task had a `T0x-PLAN.md`, remove or rewrite it to match the new task description.
39
39
  5. Do not commit manually — the system auto-commits your changes after this unit completes.
40
40
 
41
- When done, say: "Slice {{sliceId}} replanned."
41
+ When done, say: "Slice {{sliceId}} replanned." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -46,4 +46,4 @@ Then research the codebase and relevant technologies. Narrate key findings and s
46
46
 
47
47
  **You MUST call `gsd_summary_save` with the research content before finishing.**
48
48
 
49
- When done, say: "Milestone {{milestoneId}} researched."
49
+ When done, say: "Milestone {{milestoneId}} researched." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -55,4 +55,4 @@ The slice directory already exists at `{{slicePath}}/`. Do NOT mkdir.
55
55
 
56
56
  **You MUST call `gsd_summary_save` with the research content before finishing.**
57
57
 
58
- When done, say: "Slice {{sliceId}} researched."
58
+ When done, say: "Slice {{sliceId}} researched." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -30,4 +30,4 @@ An override was issued by the user that changes a fundamental decision or approa
30
30
 
31
31
  **You MUST update the relevant documents AND mark overrides as resolved in `{{overridesPath}}` before finishing.**
32
32
 
33
- When done, say: "Override applied across all documents."
33
+ When done, say: "Override applied across all documents." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -27,21 +27,23 @@ You are the UAT runner. Execute every check defined in `{{uatPath}}` as deeply a
27
27
  ### Automation rules by mode
28
28
 
29
29
  - `artifact-driven` — verify with shell commands, scripts, file reads, and artifact structure checks.
30
- - `browser-executable` — use browser tools to navigate to the target URL and verify expected behavior. Prefer direct `browser_*` tools when available. Capture screenshots as evidence. Record pass/fail with specific assertions.
31
- - `runtime-executable` — execute the specified command or script. Capture stdout/stderr as evidence. Record pass/fail based on exit code and output.
30
+ - `browser-executable` — use browser tools to navigate to the target URL and verify expected behavior. Prefer direct `browser_*` tools when available. Capture screenshots as evidence. Record pass/fail with specific assertions. When the UAT **Evidence** section names a self-contained runtime harness (for example `npm run test:uat` or `node tests/browser/search-uat.mjs`), treat the effective mode as **runtime-executable** instead: run that command only and do not start a separate server or `browser_navigate` to a hardcoded localhost port.
31
+ - `runtime-executable` — execute the specified command or script. Capture stdout/stderr as evidence. Record pass/fail based on exit code and output. When the verification script starts its own dev/static server (for example `node tests/browser/search-uat.mjs`), do **not** start a separate server with `uat-service-start` — the script owns server lifecycle and binds an ephemeral port. If a server is already running, pass its URL via `UAT_BASE_URL` or `PORT` in the `gsd_uat_exec` environment instead of hardcoding a fixed port like 4173.
32
32
  - `live-runtime` — exercise the real runtime path. Start or connect to the app/service if needed, use browser/runtime/network checks, and verify observable behavior.
33
33
  - `mixed` — run all automatable artifact-driven and live-runtime checks. Separate any remaining human-only checks explicitly.
34
34
  - `human-experience` — automate setup, preconditions, screenshots, logs, and objective checks, but do **not** invent subjective PASS results. Mark taste-based, experiential, or purely human-judgment checks as `NEEDS-HUMAN`. Use an overall verdict of `PASS` when all automatable checks succeed (even if human-only checks remain as `NEEDS-HUMAN`). Use `PARTIAL` only when automatable checks themselves were inconclusive.
35
35
 
36
36
  ### Evidence tools
37
37
 
38
- Choose the lightest tool that proves the check honestly:
38
+ The **Tool Surface** block prepended above lists unavailable tools for this unit. In short:
39
39
 
40
40
  - Run automated checks with `gsd_uat_exec`
41
41
  - Use `uat-artifact-check` as `intent` for static file, grep, structure, or artifact checks.
42
42
  - Use `uat-runtime-check` as `intent` for executing tests, scripts, or runtime assertions.
43
43
  - Use `uat-browser-check` as `intent` for browser interaction or screenshot-backed UI checks.
44
- - Use `uat-service-start` as `intent` only when starting or connecting to an app/service.
44
+ - Use `uat-service-start` as `intent` only when starting or connecting to an app/service that the UAT checks will not start themselves.
45
+ - Do not start a dev/static server separately when a runtime test script owns server lifecycle — run the script directly instead.
46
+ - When you do start a service, capture the URL from its stdout (for example `Ready at http://127.0.0.1:PORT`) and pass it to downstream checks via `UAT_BASE_URL` rather than assuming a fixed port.
45
47
  - Use `uat-log-inspection` as `intent` for checking logs or captured output files.
46
48
  - The result-table evidence mode is separate; do not use `artifact`, `runtime`, or `human-follow-up` as `intent`.
47
49
  - Run `grep` / `rg` checks against files
@@ -98,4 +100,4 @@ checks: [{
98
100
 
99
101
  **You MUST call `gsd_uat_result_save` before finishing. Do not write the assessment file directly, and do not call `gsd_summary_save` as a substitute.**
100
102
 
101
- When done, say: "UAT {{sliceId}} complete."
103
+ When done, say: "UAT {{sliceId}} complete." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -110,9 +110,12 @@ Templates are in `{{templatesDir}}`.
110
110
 
111
111
  **External facts:** Use `search-the-web` + `fetch_page`, or `search_and_read`; use `freshness` for recency. Never state current facts from training data without verification.
112
112
 
113
- **Background processes:** Use `bg_shell` `start` + `wait_for_ready` for servers/watchers/daemons. Never use `bash` with `&` or `nohup`; inherited stdout can hang. Never poll with `sleep`; use `wait_for_ready`. For status use `digest`, `highlights` for significant lines, and `output` only when debugging.
113
+ **Choosing a shell tool decide by how the command runs, not how long it takes:**
114
114
 
115
- **One-shot commands:** Use `async_bash` for builds, tests, and installs. Results are pushed on exit; use `await_job` only to block on a specific job.
115
+ - **Runs and exits (a batch command):** anything that does work and finishes — `terraform apply`, DB migrations, builds, tests, installs, long scripts. Use synchronous `bash` when you want to block and read the result now (uncapped; in auto-mode genuine hangs are caught by the stalled-tool watchdog, interactively they end on human ESC). Use `async_bash` when you want it non-blocking — it returns a job ID immediately and you `await_job` later. **Never** put a run-to-completion command under `bg_shell` `wait_for_ready`: it exits instead of staying alive, so readiness never trips and a clean exit looks like a failure.
116
+ - **Stays alive and you interact with it over time:** servers, watchers, daemons, REPLs. Use `bg_shell` `start`, then `wait_for_ready` (block until it listens/prints its ready pattern), `output`/`digest`/`highlights` to inspect, `send`/`send_and_wait` to drive it, and `kill`/`restart` to manage it. Never use `bash` with `&` or `nohup` (inherited stdout can hang); never poll with `sleep` (use `wait_for_ready`).
117
+
118
+ Quick rule of thumb: if the command would exit on its own, it's `bash`/`async_bash`; if it would keep running until you stop it, it's `bg_shell`.
116
119
 
117
120
  **Stale job hygiene:** After editing source to fix a failure, `cancel_job` every in-flight `async_bash` job before rerunning. Changed inputs make in-flight outputs untrusted.
118
121
 
@@ -65,4 +65,4 @@ Classify each capture as one of:
65
65
 
66
66
  **Important:** Do NOT execute any resolutions. Only classify and update CAPTURES.md. Resolution execution happens separately (in auto-mode dispatch or manually by the user).
67
67
 
68
- When done, say: "Triage complete."
68
+ When done, say: "Triage complete." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -87,4 +87,4 @@ If verdict is `needs-remediation`:
87
87
 
88
88
  **File system safety:** When scanning milestone directories, use `ls` or `find` first. Never pass a directory path such as `tasks/` or `slices/` directly to `read`; it only accepts files.
89
89
 
90
- When done, say: "Milestone {{milestoneId}} validation complete — verdict: <verdict>."
90
+ When done, say: "Milestone {{milestoneId}} validation complete — verdict: <verdict>." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -10,7 +10,11 @@
10
10
  */
11
11
  import { loadFile, parseTaskPlanIO } from "./files.js";
12
12
  import { isDbAvailable, getSliceTasks } from "./gsd-db.js";
13
+ // Explicit degraded-mode fallback ONLY (ADR-017): parsePlan is consulted when
14
+ // the DB is unavailable or has no task rows for the slice; the DB path in
15
+ // loadSliceTaskIO always wins when rows exist, and the fallback logs a warning.
13
16
  import { parsePlan } from "./parsers-legacy.js";
17
+ import { logWarning } from "./workflow-logger.js";
14
18
  import { resolveTasksDir, resolveTaskFiles } from "./paths.js";
15
19
  import { join } from "node:path";
16
20
  import { loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
@@ -178,7 +182,10 @@ export async function loadSliceTaskIO(basePath, mid, sid) {
178
182
  }
179
183
  catch { /* fall through */ }
180
184
  if (!taskEntries) {
181
- // File-based fallback: parse slice plan for task entries
185
+ // Degraded-mode fallback (ADR-017): no DB task rows for this slice —
186
+ // parse the PLAN.md projection instead. Warn so silent drift from the
187
+ // DB-authoritative path is visible in logs.
188
+ logWarning("projection", `reactive-graph: DB unavailable or no task rows for ${mid}/${sid}; falling back to PLAN.md parsing`);
182
189
  const parsed = parsePlan(planContent);
183
190
  if (parsed.tasks.length > 0) {
184
191
  taskEntries = parsed.tasks.map(t => ({
@@ -161,6 +161,26 @@ function parseTableSlices(section) {
161
161
  }
162
162
  return slices;
163
163
  }
164
+ function looksLikeTable(section) {
165
+ const lines = section.split("\n");
166
+ // Checkbox format takes precedence — embedded demo tables must not switch mode (#721).
167
+ if (lines.some(line => /^\s*-\s+\[[ xX]\]/.test(line))) {
168
+ return false;
169
+ }
170
+ const pipeLines = lines.filter(line => /^\s*\|/.test(line));
171
+ if (pipeLines.length < 2)
172
+ return false;
173
+ const hasSeparatorRow = pipeLines.some((line, index) => {
174
+ if (index === 0)
175
+ return false;
176
+ const cells = line.split("|").map(c => c.trim()).filter(Boolean);
177
+ return /^\s*\|[\s:-]+\|/.test(line) && cells.length >= 2 && cells.every(c => /^[\s:-]+$/.test(c));
178
+ });
179
+ if (hasSeparatorRow)
180
+ return true;
181
+ // Tables without a separator row still expose slice IDs in data rows.
182
+ return pipeLines.some(line => /\bS\d+\b/.test(line));
183
+ }
164
184
  export function parseRoadmapSlices(content) {
165
185
  const slicesSection = extractSlicesSection(content);
166
186
  if (!slicesSection) {
@@ -171,9 +191,11 @@ export function parseRoadmapSlices(content) {
171
191
  }
172
192
  // Try table format first — if the section contains pipe-delimited rows with
173
193
  // slice IDs, parse them as a table (#1736).
174
- const tableSlices = parseTableSlices(slicesSection);
175
- if (tableSlices.length > 0) {
176
- return tableSlices;
194
+ if (looksLikeTable(slicesSection)) {
195
+ const tableSlices = parseTableSlices(slicesSection);
196
+ if (tableSlices.length > 0) {
197
+ return tableSlices;
198
+ }
177
199
  }
178
200
  // Standard checkbox format
179
201
  const slices = [];
@@ -0,0 +1,108 @@
1
+ /**
2
+ * One-shot confirmation token for destructive bash commands.
3
+ *
4
+ * The destructive-command guard hard-blocks classified commands (force push,
5
+ * rm -rf, SQL drop, etc.) in all modes. The block instructs the model to
6
+ * confirm via ask_user_questions and re-issue the command. This module is the
7
+ * missing escape hatch: it records the user's confirmation and lets the exact
8
+ * confirmed command through exactly once.
9
+ *
10
+ * Design constraints:
11
+ * - In-memory only, never persisted. A confirmation token written to disk
12
+ * could silently auto-approve a destructive command in a later session —
13
+ * confirmation must be re-obtained every process lifetime.
14
+ * - One-shot. Consuming a token clears it, so a second destructive command
15
+ * (even an identical one) re-blocks and re-prompts.
16
+ * - Command-bound. The token only matches the exact (normalized) command
17
+ * string the user confirmed. A reworded command re-blocks, which is safe.
18
+ * - Per basePath, so concurrent workspaces in one process never share tokens.
19
+ *
20
+ * Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
21
+ */
22
+ import { resolve } from "node:path";
23
+ /**
24
+ * Question-id substring that marks an ask_user_questions call as a
25
+ * destructive-command confirmation. The tool_result handler promotes the
26
+ * pending command to a confirmed token when an affirmative answer arrives for
27
+ * a question whose id contains this marker.
28
+ */
29
+ export const DESTRUCTIVE_CONFIRM_GATE_MARKER = "destructive_confirm";
30
+ const statesByBasePath = new Map();
31
+ function stateKey(basePath) {
32
+ return resolve(basePath);
33
+ }
34
+ function getState(basePath) {
35
+ const key = stateKey(basePath);
36
+ let state = statesByBasePath.get(key);
37
+ if (!state) {
38
+ state = { pendingCommand: null, confirmedCommand: null };
39
+ statesByBasePath.set(key, state);
40
+ }
41
+ return state;
42
+ }
43
+ /**
44
+ * Normalize a command for stable matching across block → confirm → retry.
45
+ * Trims surrounding whitespace and collapses internal runs of whitespace so
46
+ * cosmetic reformatting of the same command still matches the token.
47
+ */
48
+ export function normalizeDestructiveCommand(command) {
49
+ return command.replace(/\s+/g, " ").trim();
50
+ }
51
+ /**
52
+ * Whether an ask_user_questions question id is a destructive-confirm gate.
53
+ */
54
+ export function isDestructiveConfirmGateId(questionId) {
55
+ return typeof questionId === "string" && questionId.includes(DESTRUCTIVE_CONFIRM_GATE_MARKER);
56
+ }
57
+ /**
58
+ * Record that a destructive command was blocked and is awaiting confirmation.
59
+ * Called by the guard at block time. Overwrites any prior pending command —
60
+ * only the most recently blocked command can be confirmed.
61
+ */
62
+ export function requestDestructiveConfirmation(command, basePath = process.cwd()) {
63
+ const state = getState(basePath);
64
+ state.pendingCommand = normalizeDestructiveCommand(command);
65
+ // A fresh request invalidates any stale confirmed token for a different
66
+ // command so confirmation cannot leak across distinct destructive actions.
67
+ state.confirmedCommand = null;
68
+ }
69
+ /**
70
+ * Promote the pending command to a confirmed, one-shot token. Called by the
71
+ * tool_result handler when the user gives an affirmative answer to a
72
+ * destructive-confirm gate. Returns the confirmed command, or null if there
73
+ * was nothing pending (e.g. confirmation arrived without a preceding block).
74
+ */
75
+ export function confirmDestructiveCommand(basePath = process.cwd()) {
76
+ const state = getState(basePath);
77
+ if (!state.pendingCommand)
78
+ return null;
79
+ state.confirmedCommand = state.pendingCommand;
80
+ state.pendingCommand = null;
81
+ return state.confirmedCommand;
82
+ }
83
+ /**
84
+ * Check whether the given command has been confirmed, consuming the token if
85
+ * so. Returns true exactly once per confirmation; subsequent calls (or a
86
+ * non-matching command) return false. Called by the guard before blocking.
87
+ */
88
+ export function consumeDestructiveConfirmation(command, basePath = process.cwd()) {
89
+ const state = getState(basePath);
90
+ if (!state.confirmedCommand)
91
+ return false;
92
+ if (state.confirmedCommand !== normalizeDestructiveCommand(command))
93
+ return false;
94
+ state.confirmedCommand = null;
95
+ return true;
96
+ }
97
+ /**
98
+ * Inspect the pending command without consuming it (diagnostics/tests).
99
+ */
100
+ export function peekPendingDestructiveCommand(basePath = process.cwd()) {
101
+ return getState(basePath).pendingCommand;
102
+ }
103
+ /**
104
+ * Clear all destructive-confirmation state for a basePath (tests / flow reset).
105
+ */
106
+ export function resetDestructiveConfirmation(basePath = process.cwd()) {
107
+ statesByBasePath.delete(stateKey(basePath));
108
+ }
@@ -329,7 +329,7 @@ export function acquireSessionLock(basePath) {
329
329
  // #3218: Provide actionable workaround when lock recovery fails
330
330
  const lockDirPath = lockTarget + ".lock";
331
331
  const reason = existingPid
332
- ? `Another auto-mode session (PID ${existingPid}) appears to be running.\nStop it with \`kill ${existingPid}\` before starting a new session.`
332
+ ? `Another auto-mode session (PID ${existingPid}) appears to be running.\nRun \`/gsd stop\` for graceful shutdown, or choose "Force start" from \`/gsd auto\` to terminate it.`
333
333
  : `Another auto-mode session lock is stuck on this project.\nRun: rm -rf "${lockDirPath}" && rm -f "${lp}"`;
334
334
  return { acquired: false, reason, existingPid };
335
335
  }