@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.b1abb545

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 (375) hide show
  1. package/dist/cli-web-branch.d.ts +2 -0
  2. package/dist/cli-web-branch.js +9 -2
  3. package/dist/help-text.js +5 -0
  4. package/dist/resources/.managed-resources-content-hash +1 -1
  5. package/dist/resources/extensions/ask-user-questions.js +78 -23
  6. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +84 -228
  7. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
  8. package/dist/resources/extensions/github-sync/templates.js +3 -3
  9. package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
  10. package/dist/resources/extensions/gsd/auto/loop.js +74 -56
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +109 -11
  12. package/dist/resources/extensions/gsd/auto/phases.js +28 -3
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
  14. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  15. package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
  17. package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
  19. package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
  20. package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
  21. package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
  22. package/dist/resources/extensions/gsd/auto-start.js +12 -23
  23. package/dist/resources/extensions/gsd/auto-timers.js +16 -2
  24. package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
  25. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
  26. package/dist/resources/extensions/gsd/auto-verification.js +7 -7
  27. package/dist/resources/extensions/gsd/auto-worktree.js +21 -19
  28. package/dist/resources/extensions/gsd/auto.js +11 -7
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
  30. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -138
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
  34. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
  35. package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
  36. package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
  37. package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
  38. package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
  39. package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
  40. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  41. package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
  42. package/dist/resources/extensions/gsd/db-workspace.js +103 -0
  43. package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
  44. package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
  45. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  46. package/dist/resources/extensions/gsd/doctor.js +16 -9
  47. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  48. package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
  49. package/dist/resources/extensions/gsd/gsd-db.js +12 -0
  50. package/dist/resources/extensions/gsd/guided-flow.js +34 -468
  51. package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
  52. package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
  53. package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
  54. package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
  55. package/dist/resources/extensions/gsd/md-importer.js +4 -3
  56. package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
  57. package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
  58. package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
  59. package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
  60. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
  61. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
  62. package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
  63. package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
  64. package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
  65. package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
  66. package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
  67. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
  68. package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
  69. package/dist/resources/extensions/gsd/preferences.js +147 -29
  70. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  71. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  73. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  75. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  76. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  77. package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
  78. package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
  79. package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
  80. package/dist/resources/extensions/gsd/question-transport.js +86 -0
  81. package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
  82. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
  83. package/dist/resources/extensions/gsd/state.js +13 -5
  84. package/dist/resources/extensions/gsd/templates/plan.md +7 -0
  85. package/dist/resources/extensions/gsd/templates/project.md +1 -0
  86. package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
  87. package/dist/resources/extensions/gsd/templates/uat.md +5 -1
  88. package/dist/resources/extensions/gsd/tool-contract.js +52 -8
  89. package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
  90. package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
  91. package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
  92. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
  93. package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
  94. package/dist/resources/extensions/gsd/uat-policy.js +16 -10
  95. package/dist/resources/extensions/gsd/uat-run.js +9 -14
  96. package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
  97. package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
  98. package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
  99. package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
  100. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  101. package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
  102. package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
  103. package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
  104. package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
  105. package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
  106. package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
  107. package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
  108. package/dist/resources/extensions/shared/interview-ui.js +2 -2
  109. package/dist/resources/shared/claude-runtime-floor.js +182 -0
  110. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  111. package/dist/update-cmd.js +20 -0
  112. package/dist/web/standalone/.next/BUILD_ID +1 -1
  113. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  114. package/dist/web/standalone/.next/build-manifest.json +3 -3
  115. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  116. package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
  117. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/index.html +1 -1
  134. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  141. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  142. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  145. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  146. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  147. package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
  148. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
  149. package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
  150. package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
  151. package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
  152. package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
  153. package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
  155. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  156. package/dist/web-mode.d.ts +2 -0
  157. package/dist/web-mode.js +20 -8
  158. package/package.json +2 -1
  159. package/packages/cloud-mcp-gateway/package.json +2 -2
  160. package/packages/contracts/package.json +1 -1
  161. package/packages/daemon/package.json +4 -4
  162. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
  163. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  164. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
  165. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  166. package/packages/gsd-agent-core/package.json +5 -5
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  171. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
  172. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  173. package/packages/gsd-agent-modes/package.json +7 -7
  174. package/packages/mcp-server/dist/server.d.ts +10 -0
  175. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  176. package/packages/mcp-server/dist/server.js +8 -0
  177. package/packages/mcp-server/dist/server.js.map +1 -1
  178. package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
  179. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  180. package/packages/mcp-server/dist/workflow-tools.js +2 -1
  181. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  182. package/packages/mcp-server/package.json +3 -3
  183. package/packages/native/package.json +1 -1
  184. package/packages/pi-agent-core/package.json +1 -1
  185. package/packages/pi-ai/dist/models.generated.d.ts +8 -93
  186. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  187. package/packages/pi-ai/dist/models.generated.js +35 -120
  188. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  189. package/packages/pi-ai/package.json +1 -1
  190. package/packages/pi-coding-agent/package.json +7 -7
  191. package/packages/pi-tui/dist/components/input.js +1 -1
  192. package/packages/pi-tui/dist/components/input.js.map +1 -1
  193. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  194. package/packages/pi-tui/dist/keys.js +39 -30
  195. package/packages/pi-tui/dist/keys.js.map +1 -1
  196. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  197. package/packages/pi-tui/dist/stdin-buffer.js +22 -0
  198. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  199. package/packages/pi-tui/package.json +2 -2
  200. package/packages/rpc-client/package.json +2 -2
  201. package/pkg/package.json +1 -1
  202. package/src/resources/extensions/ask-user-questions.ts +87 -24
  203. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +108 -281
  204. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +240 -0
  205. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
  206. package/src/resources/extensions/github-sync/templates.ts +3 -3
  207. package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
  208. package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
  209. package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
  210. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  211. package/src/resources/extensions/gsd/auto/loop.ts +83 -61
  212. package/src/resources/extensions/gsd/auto/orchestrator.ts +125 -12
  213. package/src/resources/extensions/gsd/auto/phases.ts +35 -3
  214. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
  215. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  216. package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
  217. package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
  218. package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
  219. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
  220. package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
  221. package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
  222. package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
  223. package/src/resources/extensions/gsd/auto-start.ts +17 -20
  224. package/src/resources/extensions/gsd/auto-timers.ts +16 -2
  225. package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
  226. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
  227. package/src/resources/extensions/gsd/auto-verification.ts +7 -8
  228. package/src/resources/extensions/gsd/auto-worktree.ts +33 -26
  229. package/src/resources/extensions/gsd/auto.ts +15 -8
  230. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
  231. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
  232. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  233. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +116 -151
  234. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
  235. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
  236. package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
  237. package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
  238. package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
  239. package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
  240. package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
  241. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  242. package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
  243. package/src/resources/extensions/gsd/db-workspace.ts +170 -0
  244. package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
  245. package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
  246. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  247. package/src/resources/extensions/gsd/doctor.ts +15 -5
  248. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  249. package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
  250. package/src/resources/extensions/gsd/gsd-db.ts +12 -0
  251. package/src/resources/extensions/gsd/guided-flow.ts +47 -558
  252. package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
  253. package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
  254. package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
  255. package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
  256. package/src/resources/extensions/gsd/md-importer.ts +3 -3
  257. package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
  258. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  259. package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
  260. package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
  261. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
  262. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
  263. package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
  264. package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
  265. package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
  266. package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
  267. package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
  268. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
  269. package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
  270. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  271. package/src/resources/extensions/gsd/preferences.ts +173 -28
  272. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  273. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
  274. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  275. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  276. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  277. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  278. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  279. package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
  280. package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
  281. package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
  282. package/src/resources/extensions/gsd/question-transport.ts +138 -0
  283. package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
  284. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
  285. package/src/resources/extensions/gsd/state.ts +15 -5
  286. package/src/resources/extensions/gsd/templates/plan.md +7 -0
  287. package/src/resources/extensions/gsd/templates/project.md +1 -0
  288. package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
  289. package/src/resources/extensions/gsd/templates/uat.md +5 -1
  290. package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
  291. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
  292. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
  293. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
  294. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
  295. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
  296. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
  297. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
  298. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  299. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
  300. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
  301. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
  302. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
  303. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
  304. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
  305. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
  306. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
  307. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
  308. package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
  309. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
  310. package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
  311. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
  312. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
  313. package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
  314. package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
  315. package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
  316. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
  317. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  318. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
  319. package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
  320. package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
  321. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
  322. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
  323. package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
  324. package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
  325. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
  326. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
  327. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
  328. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
  329. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
  330. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
  331. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
  332. package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
  333. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
  334. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
  335. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
  336. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
  337. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
  338. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
  339. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
  340. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
  341. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
  342. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
  343. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
  344. package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
  345. package/src/resources/extensions/gsd/tool-contract.ts +86 -8
  346. package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
  347. package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
  348. package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
  349. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
  350. package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
  351. package/src/resources/extensions/gsd/uat-policy.ts +19 -10
  352. package/src/resources/extensions/gsd/uat-run.ts +10 -14
  353. package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
  354. package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
  355. package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
  356. package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
  357. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  358. package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
  359. package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
  360. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  361. package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
  362. package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
  363. package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
  364. package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
  365. package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
  366. package/src/resources/extensions/shared/interview-ui.ts +15 -2
  367. package/src/resources/shared/claude-runtime-floor.ts +248 -0
  368. package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
  369. package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
  370. package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
  371. package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
  372. package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
  373. package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
  374. /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_buildManifest.js +0 -0
  375. /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_ssgManifest.js +0 -0
@@ -0,0 +1,224 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Persist planned milestone roadmaps and their DB-backed projections.
3
+
4
+ import { clearParseCache } from "./files.js";
5
+ import { isClosedStatus } from "./status-guards.js";
6
+ import {
7
+ transaction,
8
+ getMilestone,
9
+ getMilestoneSlices,
10
+ getSlice,
11
+ insertMilestone,
12
+ insertSlice,
13
+ upsertMilestonePlanning,
14
+ upsertSlicePlanning,
15
+ } from "./gsd-db.js";
16
+ import { invalidateStateCache } from "./state.js";
17
+ import { renderRoadmapFromDb } from "./markdown-renderer.js";
18
+ import { renderAllProjections } from "./workflow-projections.js";
19
+ import { writeManifest } from "./workflow-manifest.js";
20
+ import { appendEvent } from "./workflow-events.js";
21
+ import { logWarning } from "./workflow-logger.js";
22
+
23
+ export interface PersistMilestonePlanSlice {
24
+ sliceId: string;
25
+ title: string;
26
+ risk: string;
27
+ depends: string[];
28
+ demo: string;
29
+ goal: string;
30
+ successCriteria: string;
31
+ proofLevel: string;
32
+ integrationClosure: string;
33
+ observabilityImpact: string;
34
+ isSketch?: boolean;
35
+ sketchScope?: string;
36
+ }
37
+
38
+ export interface PersistMilestonePlanParams {
39
+ milestoneId: string;
40
+ title: string;
41
+ vision: string;
42
+ slices: PersistMilestonePlanSlice[];
43
+ status?: string;
44
+ dependsOn?: string[];
45
+ actorName?: string;
46
+ triggerReason?: string;
47
+ successCriteria?: string[];
48
+ keyRisks?: Array<{ risk: string; whyItMatters: string }>;
49
+ proofStrategy?: Array<{ riskOrUnknown: string; retireIn: string; whatWillBeProven: string }>;
50
+ verificationContract?: string;
51
+ verificationIntegration?: string;
52
+ verificationOperational?: string;
53
+ verificationUat?: string;
54
+ definitionOfDone?: string[];
55
+ requirementCoverage?: string;
56
+ boundaryMapMarkdown?: string;
57
+ }
58
+
59
+ export interface PersistMilestonePlanResult {
60
+ milestoneId: string;
61
+ roadmapPath: string;
62
+ }
63
+
64
+ function validatePlanPromotion(params: PersistMilestonePlanParams): string | null {
65
+ const existingMilestone = getMilestone(params.milestoneId);
66
+ if (existingMilestone && isClosedStatus(existingMilestone.status)) {
67
+ return `cannot re-plan milestone ${params.milestoneId}: it is already complete`;
68
+ }
69
+
70
+ // Guard: refuse to re-plan a milestone that would drop completed slices (#2960).
71
+ // Allow re-planning when all completed slices are still present in the
72
+ // incoming plan — their status is preserved below (#2558). Block only when
73
+ // the new plan omits a completed slice, which could shadow completed work.
74
+ const existingSlices = getMilestoneSlices(params.milestoneId);
75
+ const completedSlices = existingSlices.filter(s => isClosedStatus(s.status));
76
+ if (completedSlices.length > 0) {
77
+ const incomingSliceIds = new Set(params.slices.map(s => s.sliceId));
78
+ const droppedCompleted = completedSlices.filter(s => !incomingSliceIds.has(s.id));
79
+ if (droppedCompleted.length > 0) {
80
+ return `cannot re-plan milestone ${params.milestoneId}: ${droppedCompleted.length} completed slice(s) would be dropped (${droppedCompleted.map(s => s.id).join(", ")}). Use gsd_reassess_roadmap to modify the roadmap.`;
81
+ }
82
+ }
83
+
84
+ // Validate depends_on: all dependencies must exist and be complete
85
+ if (params.dependsOn && params.dependsOn.length > 0) {
86
+ for (const depId of params.dependsOn) {
87
+ const dep = getMilestone(depId);
88
+ if (!dep) {
89
+ return `depends_on references unknown milestone: ${depId}`;
90
+ }
91
+ if (!isClosedStatus(dep.status)) {
92
+ return `depends_on milestone ${depId} is not yet complete (status: ${dep.status})`;
93
+ }
94
+ }
95
+ }
96
+
97
+ return null;
98
+ }
99
+
100
+ function writePlanRows(params: PersistMilestonePlanParams): void {
101
+ insertMilestone({
102
+ id: params.milestoneId,
103
+ title: params.title,
104
+ status: params.status ?? "active",
105
+ depends_on: params.dependsOn ?? [],
106
+ });
107
+
108
+ upsertMilestonePlanning(params.milestoneId, {
109
+ title: params.title,
110
+ status: params.status ?? "active",
111
+ depends_on: params.dependsOn ?? [],
112
+ vision: params.vision,
113
+ successCriteria: params.successCriteria,
114
+ keyRisks: params.keyRisks,
115
+ proofStrategy: params.proofStrategy,
116
+ verificationContract: params.verificationContract,
117
+ verificationIntegration: params.verificationIntegration,
118
+ verificationOperational: params.verificationOperational,
119
+ verificationUat: params.verificationUat,
120
+ definitionOfDone: params.definitionOfDone,
121
+ requirementCoverage: params.requirementCoverage,
122
+ boundaryMapMarkdown: params.boundaryMapMarkdown,
123
+ });
124
+
125
+ for (let i = 0; i < params.slices.length; i++) {
126
+ const slice = params.slices[i]!;
127
+ // Preserve completed/done status on re-plan (#2558).
128
+ // Without this, a re-plan after milestone transition would reset
129
+ // already-completed slices back to "pending".
130
+ const existing = getSlice(params.milestoneId, slice.sliceId);
131
+ const status = existing && (existing.status === "complete" || existing.status === "done")
132
+ ? existing.status
133
+ : "pending";
134
+ insertSlice({
135
+ id: slice.sliceId,
136
+ milestoneId: params.milestoneId,
137
+ title: slice.title,
138
+ status,
139
+ risk: slice.risk,
140
+ depends: slice.depends,
141
+ demo: slice.demo,
142
+ sequence: i + 1, // Preserve agent-ordered sequence (#3356)
143
+ // ADR-011: pass undefined through so ON CONFLICT preserves existing values
144
+ // when the caller omitted the fields on a re-plan.
145
+ isSketch: slice.isSketch,
146
+ sketchScope: slice.sketchScope,
147
+ });
148
+ upsertSlicePlanning(params.milestoneId, slice.sliceId, {
149
+ goal: slice.goal,
150
+ successCriteria: slice.successCriteria,
151
+ proofLevel: slice.proofLevel,
152
+ integrationClosure: slice.integrationClosure,
153
+ observabilityImpact: slice.observabilityImpact,
154
+ });
155
+ }
156
+ }
157
+
158
+ async function renderPlanArtifacts(
159
+ basePath: string,
160
+ params: PersistMilestonePlanParams,
161
+ ): Promise<string | { error: string }> {
162
+ try {
163
+ const renderResult = await renderRoadmapFromDb(basePath, params.milestoneId);
164
+ return renderResult.roadmapPath;
165
+ } catch (renderErr) {
166
+ logWarning("tool", `plan_milestone — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}`);
167
+ invalidateStateCache();
168
+ return { error: `render failed: ${(renderErr as Error).message}` };
169
+ }
170
+ }
171
+
172
+ async function runPostPlanHooks(basePath: string, params: PersistMilestonePlanParams): Promise<void> {
173
+ try {
174
+ await renderAllProjections(basePath, params.milestoneId);
175
+ writeManifest(basePath);
176
+ appendEvent(basePath, {
177
+ cmd: "plan-milestone",
178
+ params: { milestoneId: params.milestoneId },
179
+ ts: new Date().toISOString(),
180
+ actor: "agent",
181
+ actor_name: params.actorName,
182
+ trigger_reason: params.triggerReason,
183
+ });
184
+ } catch (hookErr) {
185
+ logWarning("tool", `plan-milestone post-mutation hook warning: ${(hookErr as Error).message}`);
186
+ }
187
+ }
188
+
189
+ export async function persistMilestonePlan(
190
+ params: PersistMilestonePlanParams,
191
+ basePath: string,
192
+ ): Promise<PersistMilestonePlanResult | { error: string }> {
193
+ // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
194
+ // Guards must be inside the transaction so the state they check cannot
195
+ // change between the read and the write (#2723).
196
+ let guardError: string | null = null;
197
+
198
+ try {
199
+ transaction(() => {
200
+ guardError = validatePlanPromotion(params);
201
+ if (guardError) return;
202
+ writePlanRows(params);
203
+ });
204
+ } catch (err) {
205
+ return { error: `db write failed: ${(err as Error).message}` };
206
+ }
207
+
208
+ if (guardError) {
209
+ return { error: guardError };
210
+ }
211
+
212
+ const roadmapPath = await renderPlanArtifacts(basePath, params);
213
+ if (typeof roadmapPath !== "string") return roadmapPath;
214
+
215
+ invalidateStateCache();
216
+ clearParseCache();
217
+
218
+ await runPostPlanHooks(basePath, params);
219
+
220
+ return {
221
+ milestoneId: params.milestoneId,
222
+ roadmapPath,
223
+ };
224
+ }
@@ -0,0 +1,125 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Classify milestone readiness from DB status, slices, and artifacts.
3
+
4
+ import { readFileSync } from "node:fs";
5
+ import type { Phase } from "./types.js";
6
+ import { getMilestone, getMilestoneSlices, isDbAvailable } from "./gsd-db.js";
7
+ import { parseRoadmapSlices } from "./roadmap-slices.js";
8
+ import { logWarning } from "./workflow-logger.js";
9
+
10
+ export type MilestoneReadinessKind =
11
+ | "queued-shell"
12
+ | "needs-discussion"
13
+ | "planning-pending"
14
+ | "executable-plan"
15
+ | "terminal";
16
+
17
+ export interface MilestoneReadiness {
18
+ kind: MilestoneReadinessKind;
19
+ hasContext: boolean;
20
+ hasDraftContext: boolean;
21
+ hasExecutablePlan: boolean;
22
+ }
23
+
24
+ export interface MilestoneReadinessInput {
25
+ status?: string | null;
26
+ hasContext?: boolean;
27
+ hasDraftContext?: boolean;
28
+ hasSummary?: boolean;
29
+ sliceCount?: number;
30
+ }
31
+
32
+ export interface HandoffReadinessInput {
33
+ milestoneId: string;
34
+ contextFile: string | null;
35
+ roadmapFile: string | null;
36
+ }
37
+
38
+ export function classifyMilestoneReadiness(input: MilestoneReadinessInput): MilestoneReadiness {
39
+ const hasContext = input.hasContext === true;
40
+ const hasDraftContext = !hasContext && input.hasDraftContext === true;
41
+ const hasSummary = input.hasSummary === true;
42
+ const sliceCount = input.sliceCount ?? 0;
43
+ const hasExecutablePlan = sliceCount > 0;
44
+ const status = input.status ?? null;
45
+
46
+ if (status === "complete" || hasSummary) {
47
+ return { kind: "terminal", hasContext, hasDraftContext, hasExecutablePlan };
48
+ }
49
+
50
+ if (status === "queued" && !hasContext && sliceCount === 0) {
51
+ return { kind: "queued-shell", hasContext, hasDraftContext, hasExecutablePlan };
52
+ }
53
+
54
+ if ((status === "needs-discussion" && !hasContext) || hasDraftContext) {
55
+ return { kind: "needs-discussion", hasContext, hasDraftContext, hasExecutablePlan };
56
+ }
57
+
58
+ if (hasExecutablePlan) {
59
+ return { kind: "executable-plan", hasContext, hasDraftContext, hasExecutablePlan };
60
+ }
61
+
62
+ return { kind: "planning-pending", hasContext, hasDraftContext, hasExecutablePlan };
63
+ }
64
+
65
+ export function readinessNeedsDiscussion(readiness: MilestoneReadiness): boolean {
66
+ return readiness.kind === "needs-discussion" ||
67
+ (readiness.kind === "queued-shell" && readiness.hasDraftContext);
68
+ }
69
+
70
+ export function describeMilestoneReadinessPhase(
71
+ phase: Phase,
72
+ ): { label: string; description: string } | null {
73
+ switch (phase) {
74
+ case "needs-discussion":
75
+ return {
76
+ label: "Discuss milestone draft",
77
+ description: "Milestone has a draft context — needs discussion before planning.",
78
+ };
79
+ case "pre-planning":
80
+ return {
81
+ label: "Research & plan milestone",
82
+ description: "Scout the landscape and create the roadmap.",
83
+ };
84
+ default:
85
+ return null;
86
+ }
87
+ }
88
+
89
+ function executablePlanSliceCount(milestoneId: string, roadmapFile: string | null): number {
90
+ if (isDbAvailable()) {
91
+ return getMilestoneSlices(milestoneId).length;
92
+ }
93
+ if (!roadmapFile) return 0;
94
+ try {
95
+ return parseRoadmapSlices(readFileSync(roadmapFile, "utf-8")).length;
96
+ } catch (e) {
97
+ logWarning(
98
+ "guided",
99
+ `failed to parse roadmap slices for ${milestoneId}: ${(e as Error).message}`,
100
+ );
101
+ return 0;
102
+ }
103
+ }
104
+
105
+ export function assessMilestoneHandoffReadiness(
106
+ input: HandoffReadinessInput,
107
+ ): MilestoneReadiness {
108
+ const milestone = isDbAvailable() ? getMilestone(input.milestoneId) : null;
109
+ return classifyMilestoneReadiness({
110
+ status: milestone?.status,
111
+ hasContext: input.contextFile != null,
112
+ sliceCount: executablePlanSliceCount(input.milestoneId, input.roadmapFile),
113
+ });
114
+ }
115
+
116
+ export function formatAcceptedDiscussHandoffMessage(
117
+ milestoneId: string,
118
+ readiness: MilestoneReadiness,
119
+ ): string {
120
+ if (readiness.hasExecutablePlan) return `Milestone ${milestoneId} ready.`;
121
+ if (readiness.hasContext) {
122
+ return `Milestone ${milestoneId} context captured. Continuing the planning pipeline.`;
123
+ }
124
+ return `Milestone ${milestoneId} planning artifacts captured. Continuing the planning pipeline.`;
125
+ }
@@ -0,0 +1,81 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Milestone closeout settlement state across DB proof, artifacts, merge, and cleanup.
3
+
4
+ import { isInAutoWorktree } from "./auto-worktree.js";
5
+ import {
6
+ formatCloseoutProofBlock,
7
+ proveMilestoneCloseout,
8
+ } from "./milestone-closeout-proof.js";
9
+ import { resolveCloseoutArtifactProjection } from "./artifact-projection.js";
10
+
11
+ export type MilestoneSettlementOutcome =
12
+ | { ok: true; reason: "settled" | "not-applicable" }
13
+ | {
14
+ ok: false;
15
+ reason: "closeout-blocked" | "merge-pending";
16
+ action: "pause";
17
+ message: string;
18
+ nextAction: string;
19
+ milestoneId: string;
20
+ };
21
+
22
+ export interface MilestoneSettlementInput {
23
+ milestoneId: string | null | undefined;
24
+ statePhase: string;
25
+ basePath: string;
26
+ originalBasePath: string;
27
+ milestoneMerged: boolean;
28
+ }
29
+
30
+ function isActiveUnmergedWorktree(input: MilestoneSettlementInput): boolean {
31
+ if (!input.milestoneId || input.milestoneMerged) return false;
32
+ return isInAutoWorktree(input.basePath);
33
+ }
34
+
35
+ export function evaluateAllCompleteSettlement(
36
+ input: MilestoneSettlementInput,
37
+ ): MilestoneSettlementOutcome {
38
+ if (input.statePhase !== "complete") {
39
+ return { ok: true, reason: "not-applicable" };
40
+ }
41
+ if (!isActiveUnmergedWorktree(input)) {
42
+ return { ok: true, reason: "settled" };
43
+ }
44
+
45
+ const milestoneId = input.milestoneId;
46
+ if (!milestoneId) {
47
+ return { ok: true, reason: "settled" };
48
+ }
49
+
50
+ const projection = resolveCloseoutArtifactProjection({
51
+ milestoneId,
52
+ basePath: input.basePath,
53
+ originalBasePath: input.originalBasePath,
54
+ });
55
+ const proof = proveMilestoneCloseout(milestoneId, {
56
+ refreshFromDisk: true,
57
+ summaryArtifactBasePath: projection.summaryArtifactBasePath,
58
+ });
59
+
60
+ if (!proof.ok) {
61
+ return {
62
+ ok: false,
63
+ reason: "closeout-blocked",
64
+ action: "pause",
65
+ message: `${formatCloseoutProofBlock(proof)} The milestone branch has not been merged to main.`,
66
+ nextAction: `Resolve closeout blockers, then retry \`/gsd dispatch complete-milestone ${milestoneId}\`.`,
67
+ milestoneId,
68
+ };
69
+ }
70
+
71
+ return {
72
+ ok: false,
73
+ reason: "merge-pending",
74
+ action: "pause",
75
+ message:
76
+ `Milestone ${milestoneId} is complete, but its worktree branch has not been merged to main. ` +
77
+ `Retry with \`/gsd dispatch complete-milestone ${milestoneId}\` or merge manually.`,
78
+ nextAction: `Retry \`/gsd dispatch complete-milestone ${milestoneId}\` or merge manually.`,
79
+ milestoneId,
80
+ };
81
+ }
@@ -0,0 +1,95 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Forwarded validation evidence rules for milestone validation.
3
+
4
+ import { getArtifact, getMilestone, getMilestoneSlices } from "./gsd-db.js";
5
+ import { loadFile } from "./files.js";
6
+ import { resolveSliceFile } from "./paths.js";
7
+ import {
8
+ compactTextParts,
9
+ hasBrowserEvidenceText,
10
+ hasBrowserRequiredText,
11
+ } from "./browser-evidence.js";
12
+
13
+ export interface MilestoneValidationEvidenceParams {
14
+ milestoneId: string;
15
+ verdict: "pass" | "needs-attention" | "needs-remediation";
16
+ successCriteriaChecklist: string;
17
+ verificationClasses?: string;
18
+ verdictRationale: string;
19
+ remediationPlan?: string;
20
+ }
21
+
22
+ export function hasRuntimeExecutableUatEvidenceText(text: string): boolean {
23
+ if (!/\buatType:\s*runtime-executable\b/i.test(text)) return false;
24
+ if (!/\bverdict:\s*PASS\b/i.test(text)) return false;
25
+ return /^\|\s*[^|\n]+\s*\|\s*runtime\s*\|\s*PASS\s*\|[^|\n]*\bgsd_uat_exec\b/mi.test(text);
26
+ }
27
+
28
+ export async function browserEvidenceGateRequiresAttention(
29
+ params: MilestoneValidationEvidenceParams,
30
+ basePath: string,
31
+ ): Promise<boolean> {
32
+ if (params.verdict !== "pass") return false;
33
+
34
+ const milestone = getMilestone(params.milestoneId);
35
+ const slices = getMilestoneSlices(params.milestoneId);
36
+ const requirementText = compactTextParts([
37
+ milestone?.vision,
38
+ milestone?.success_criteria,
39
+ milestone?.verification_uat,
40
+ params.successCriteriaChecklist,
41
+ params.verificationClasses,
42
+ ...slices.flatMap((slice) => [
43
+ slice.demo,
44
+ slice.goal,
45
+ slice.success_criteria,
46
+ ]),
47
+ ]);
48
+ if (!hasBrowserRequiredText(requirementText)) return false;
49
+
50
+ const sliceEvidencePairs: Array<{ sliceRequirementText: string; evidenceText: string }> = [];
51
+ for (const slice of slices) {
52
+ const chunks: string[] = [];
53
+ const artifactPath = `milestones/${params.milestoneId}/slices/${slice.id}/${slice.id}-ASSESSMENT.md`;
54
+ const artifact = getArtifact(artifactPath);
55
+ if (artifact?.full_content) chunks.push(artifact.full_content);
56
+ const assessmentPath = resolveSliceFile(basePath, params.milestoneId, slice.id, "ASSESSMENT");
57
+ const assessmentContent = assessmentPath ? await loadFile(assessmentPath) : null;
58
+ if (assessmentContent) chunks.push(assessmentContent);
59
+ sliceEvidencePairs.push({
60
+ sliceRequirementText: compactTextParts([slice.demo, slice.goal, slice.success_criteria]),
61
+ evidenceText: chunks.join("\n\n"),
62
+ });
63
+ }
64
+
65
+ const browserRequiringSlices = sliceEvidencePairs.filter((slice) =>
66
+ hasBrowserRequiredText(slice.sliceRequirementText),
67
+ );
68
+ const runtimeBypasses =
69
+ browserRequiringSlices.length > 0
70
+ ? browserRequiringSlices.every((slice) => hasRuntimeExecutableUatEvidenceText(slice.evidenceText))
71
+ : sliceEvidencePairs.some((slice) => hasRuntimeExecutableUatEvidenceText(slice.evidenceText));
72
+ if (runtimeBypasses) return false;
73
+
74
+ const persistedEvidence = sliceEvidencePairs.map((slice) => slice.evidenceText).join("\n\n");
75
+ const validationEvidence = compactTextParts([
76
+ params.successCriteriaChecklist,
77
+ params.verificationClasses,
78
+ params.verdictRationale,
79
+ params.remediationPlan,
80
+ ]);
81
+ return !hasBrowserEvidenceText(`${persistedEvidence}\n\n${validationEvidence}`);
82
+ }
83
+
84
+ export function applyBrowserEvidenceGate<T extends MilestoneValidationEvidenceParams>(
85
+ params: T,
86
+ ): Omit<T, "verdict" | "verdictRationale"> & { verdict: "needs-attention"; verdictRationale: string } {
87
+ const note = "Browser evidence gate: Browser-observable acceptance criteria were detected, but no persisted ASSESSMENT or validation evidence recorded browser actions with assertions. Downgraded from pass to needs-attention.";
88
+ return {
89
+ ...params,
90
+ verdict: "needs-attention",
91
+ verdictRationale: params.verdictRationale.trim()
92
+ ? `${params.verdictRationale.trim()}\n\n${note}`
93
+ : note,
94
+ };
95
+ }
@@ -0,0 +1,80 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Resolve the authoritative milestone validation verdict across DB and disk projections.
3
+
4
+ import { existsSync } from "node:fs";
5
+ import { join } from "node:path";
6
+
7
+ import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
8
+ import { loadFile } from "./files.js";
9
+ import { getLatestAssessmentByScope, isDbAvailable } from "./gsd-db.js";
10
+ import { gsdProjectionRoot } from "./paths.js";
11
+ import {
12
+ extractVerdict,
13
+ isValidMilestoneVerdict,
14
+ type ValidationVerdict,
15
+ } from "./verdict-parser.js";
16
+ import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
17
+ import { resolveWorktreeProjectRoot } from "./worktree-root.js";
18
+
19
+ function verdictFromContent(content: string | null | undefined): ValidationVerdict | undefined {
20
+ if (!content) return undefined;
21
+ const verdict = extractVerdict(content);
22
+ return verdict && isValidMilestoneVerdict(verdict) ? verdict : undefined;
23
+ }
24
+
25
+ function verdictFromDb(milestoneId: string): ValidationVerdict | undefined {
26
+ if (!isDbAvailable()) return undefined;
27
+ const assessment = getLatestAssessmentByScope(milestoneId, "milestone-validation");
28
+ const status = typeof assessment?.status === "string" ? assessment.status : undefined;
29
+ return status && isValidMilestoneVerdict(status) ? status : undefined;
30
+ }
31
+
32
+ async function verdictFromValidationPath(path: string | null): Promise<ValidationVerdict | undefined> {
33
+ if (!path || !existsSync(path)) return undefined;
34
+ return verdictFromContent(await loadFile(path));
35
+ }
36
+
37
+ /**
38
+ * Resolve the milestone validation verdict using the same authority order as
39
+ * DB-backed state derivation, with filesystem fallbacks that mirror
40
+ * `resolveExpectedArtifactPath` (canonical worktree projection, then project
41
+ * root). Manual `/gsd verdict` overrides persist to the DB first; a stale
42
+ * worktree-local VALIDATION.md must not re-block auto-mode after the override.
43
+ */
44
+ export async function resolveMilestoneValidationVerdict(
45
+ basePath: string,
46
+ milestoneId: string,
47
+ ): Promise<ValidationVerdict | undefined> {
48
+ const dbVerdict = verdictFromDb(milestoneId);
49
+ if (dbVerdict) return dbVerdict;
50
+
51
+ const canonicalBase = resolveCanonicalMilestoneRoot(basePath, milestoneId);
52
+ const canonicalPath = resolveExpectedArtifactPath(
53
+ "validate-milestone",
54
+ milestoneId,
55
+ canonicalBase,
56
+ );
57
+ const canonicalVerdict = await verdictFromValidationPath(canonicalPath);
58
+ if (canonicalVerdict) return canonicalVerdict;
59
+
60
+ const projectRoot = resolveWorktreeProjectRoot(basePath);
61
+ if (projectRoot !== canonicalBase) {
62
+ const projectPath = resolveExpectedArtifactPath(
63
+ "validate-milestone",
64
+ milestoneId,
65
+ projectRoot,
66
+ );
67
+ const projectVerdict = await verdictFromValidationPath(projectPath);
68
+ if (projectVerdict) return projectVerdict;
69
+ }
70
+
71
+ // Last resort: direct canonical projection path even when resolveDir helpers
72
+ // have not materialized the milestone directory yet.
73
+ const directPath = join(
74
+ gsdProjectionRoot(canonicalBase),
75
+ "milestones",
76
+ milestoneId,
77
+ `${milestoneId}-VALIDATION.md`,
78
+ );
79
+ return verdictFromValidationPath(directPath);
80
+ }
@@ -5,11 +5,11 @@
5
5
  * dependency satisfaction and file overlap across slice plans.
6
6
  */
7
7
 
8
- import { existsSync } from "node:fs";
9
8
  import { deriveState } from "./state.js";
10
- import { resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile } from "./paths.js";
9
+ import { resolveMilestoneFile, resolveSliceFile } from "./paths.js";
11
10
  import { findMilestoneIds } from "./guided-flow.js";
12
- import { isDbAvailable, getMilestoneSlices, getSliceTasks, openDatabase } from "./gsd-db.js";
11
+ import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
12
+ import { openExistingWorkflowDatabase } from "./db-workspace.js";
13
13
  import type { MilestoneRegistryEntry } from "./types.js";
14
14
 
15
15
  // ─── Types ───────────────────────────────────────────────────────────────────
@@ -98,8 +98,7 @@ export async function analyzeParallelEligibility(
98
98
  basePath: string,
99
99
  ): Promise<ParallelCandidates> {
100
100
  if (!isDbAvailable()) {
101
- const { projectDb } = resolveGsdPathContract(basePath);
102
- if (existsSync(projectDb)) openDatabase(projectDb);
101
+ openExistingWorkflowDatabase(basePath);
103
102
  }
104
103
 
105
104
  const milestoneIds = findMilestoneIds(basePath);
@@ -21,9 +21,10 @@ import { join, dirname } from "node:path";
21
21
  import { fileURLToPath } from "node:url";
22
22
  import { gsdRoot } from "./paths.js";
23
23
  import { createWorktree, worktreePath } from "./worktree-manager.js";
24
- import { autoWorktreeBranch, fastForwardReusedMilestoneBranchIfSafe, runWorktreePostCreateHook, syncGsdStateToWorktree } from "./auto-worktree.js";
24
+ import { autoWorktreeBranch, fastForwardReusedMilestoneBranchIfSafe, runWorktreePostCreateHook, syncGsdStateToWorktreeByScope } from "./auto-worktree.js";
25
25
  import { nativeBranchExists } from "./native-git-bridge.js";
26
26
  import { readIntegrationBranch } from "./git-service.js";
27
+ import { createWorkspace, scopeMilestone } from "./workspace.js";
27
28
  import { resolveParallelConfig } from "./preferences.js";
28
29
  import type { GSDPreferences } from "./preferences.js";
29
30
  import type { ParallelConfig } from "./types.js";
@@ -561,7 +562,10 @@ export function _createMilestoneWorktree(basePath: string, milestoneId: string):
561
562
  // Copy .gsd/ planning artifacts (milestones, CONTEXT, ROADMAP, etc.) from the
562
563
  // project root into the worktree. Without this, workers for newly-planned
563
564
  // milestones can't find their roadmap and exit immediately (#2184 Bug 4).
564
- syncGsdStateToWorktree(basePath, info.path);
565
+ syncGsdStateToWorktreeByScope(
566
+ scopeMilestone(createWorkspace(basePath), milestoneId),
567
+ scopeMilestone(createWorkspace(info.path), milestoneId),
568
+ );
565
569
 
566
570
  return info.path;
567
571
  }