@opengsd/gsd-pi 1.1.1-dev.b2556262 → 1.2.0-dev.4813ead6

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 (500) 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/project-sessions.js +4 -2
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/extensions/ask-user-questions.js +78 -23
  7. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +101 -237
  8. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
  9. package/dist/resources/extensions/github-sync/templates.js +3 -3
  10. package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
  11. package/dist/resources/extensions/gsd/auto/contracts.js +8 -1
  12. package/dist/resources/extensions/gsd/auto/loop.js +74 -56
  13. package/dist/resources/extensions/gsd/auto/orchestrator.js +763 -63
  14. package/dist/resources/extensions/gsd/auto/phases.js +28 -3
  15. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
  16. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  17. package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
  18. package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
  19. package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
  20. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
  21. package/dist/resources/extensions/gsd/auto-prompts.js +191 -9
  22. package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
  23. package/dist/resources/extensions/gsd/auto-runtime-state.js +17 -0
  24. package/dist/resources/extensions/gsd/auto-start.js +12 -23
  25. package/dist/resources/extensions/gsd/auto-timers.js +16 -2
  26. package/dist/resources/extensions/gsd/auto-tool-tracking.js +37 -0
  27. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +33 -29
  28. package/dist/resources/extensions/gsd/auto-verification.js +7 -7
  29. package/dist/resources/extensions/gsd/auto-worktree.js +45 -36
  30. package/dist/resources/extensions/gsd/auto.js +73 -471
  31. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
  32. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
  33. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +103 -138
  35. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
  36. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
  37. package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
  38. package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
  39. package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
  40. package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
  41. package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
  42. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  43. package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
  44. package/dist/resources/extensions/gsd/db-workspace.js +103 -0
  45. package/dist/resources/extensions/gsd/debug-logger.js +10 -0
  46. package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
  47. package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
  48. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  49. package/dist/resources/extensions/gsd/doctor-proactive.js +7 -2
  50. package/dist/resources/extensions/gsd/doctor.js +16 -9
  51. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  52. package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
  53. package/dist/resources/extensions/gsd/gsd-db.js +12 -0
  54. package/dist/resources/extensions/gsd/guided-flow.js +36 -470
  55. package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
  56. package/dist/resources/extensions/gsd/markdown-renderer.js +33 -33
  57. package/dist/resources/extensions/gsd/mcp-filter.js +8 -1
  58. package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
  59. package/dist/resources/extensions/gsd/md-importer.js +4 -3
  60. package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
  61. package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
  62. package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
  63. package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
  64. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
  65. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
  66. package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
  67. package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
  68. package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
  69. package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
  70. package/dist/resources/extensions/gsd/native-git-bridge.js +45 -0
  71. package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
  72. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
  73. package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
  74. package/dist/resources/extensions/gsd/preferences.js +147 -29
  75. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  76. package/dist/resources/extensions/gsd/prompts/discuss.md +6 -7
  77. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
  78. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
  79. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
  80. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
  81. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
  82. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  83. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -1
  84. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  85. package/dist/resources/extensions/gsd/prompts/research-milestone.md +2 -2
  86. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  87. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -3
  88. package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
  89. package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
  90. package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
  91. package/dist/resources/extensions/gsd/question-transport.js +86 -0
  92. package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
  93. package/dist/resources/extensions/gsd/schemas/parsers.js +6 -1
  94. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
  95. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +21 -1
  96. package/dist/resources/extensions/gsd/state.js +13 -5
  97. package/dist/resources/extensions/gsd/templates/plan.md +7 -0
  98. package/dist/resources/extensions/gsd/templates/project.md +1 -0
  99. package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
  100. package/dist/resources/extensions/gsd/templates/uat.md +5 -1
  101. package/dist/resources/extensions/gsd/tool-contract.js +52 -8
  102. package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
  103. package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
  104. package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
  105. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
  106. package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
  107. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +169 -20
  108. package/dist/resources/extensions/gsd/uat-policy.js +16 -10
  109. package/dist/resources/extensions/gsd/uat-run.js +9 -14
  110. package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
  111. package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
  112. package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
  113. package/dist/resources/extensions/gsd/user-input-boundary.js +65 -4
  114. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  115. package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
  116. package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
  117. package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
  118. package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
  119. package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
  120. package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
  121. package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
  122. package/dist/resources/extensions/shared/interview-ui.js +2 -2
  123. package/dist/resources/shared/claude-runtime-floor.js +182 -0
  124. package/dist/tsconfig.extensions.tsbuildinfo +1 -0
  125. package/dist/update-cmd.js +20 -0
  126. package/dist/web/standalone/.next/BUILD_ID +1 -1
  127. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  128. package/dist/web/standalone/.next/build-manifest.json +3 -3
  129. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  130. package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
  131. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  145. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  156. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  162. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  164. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  174. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  176. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  178. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  180. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  182. package/dist/web/standalone/.next/server/app/index.html +1 -1
  183. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  184. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  185. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  186. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  187. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  188. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  189. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  190. package/dist/web/standalone/.next/server/chunks/5047.js +2 -0
  191. package/dist/web/standalone/.next/server/chunks/5124.js +1 -0
  192. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  193. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  196. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  197. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  198. package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
  199. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
  200. package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
  201. package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
  202. package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
  203. package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
  204. package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
  205. package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
  206. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  207. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  208. package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
  209. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
  210. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  211. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  212. package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
  213. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
  214. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
  215. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
  216. package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
  217. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  218. package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
  219. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  220. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
  221. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  222. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  223. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  224. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
  225. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
  226. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  227. package/dist/web-mode.d.ts +2 -0
  228. package/dist/web-mode.js +20 -8
  229. package/package.json +17 -11
  230. package/packages/cloud-mcp-gateway/package.json +2 -2
  231. package/packages/contracts/package.json +1 -1
  232. package/packages/daemon/package.json +4 -4
  233. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
  234. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  235. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
  236. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  237. package/packages/gsd-agent-core/package.json +5 -5
  238. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  239. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -0
  240. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  241. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +1 -1
  242. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  243. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  244. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
  245. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  246. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  247. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
  248. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  249. package/packages/gsd-agent-modes/package.json +7 -7
  250. package/packages/mcp-server/dist/server.d.ts +10 -0
  251. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  252. package/packages/mcp-server/dist/server.js +8 -0
  253. package/packages/mcp-server/dist/server.js.map +1 -1
  254. package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
  255. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  256. package/packages/mcp-server/dist/workflow-tools.js +2 -1
  257. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  258. package/packages/mcp-server/package.json +3 -3
  259. package/packages/native/package.json +1 -1
  260. package/packages/pi-agent-core/package.json +1 -1
  261. package/packages/pi-ai/dist/image-models.generated.d.ts +30 -0
  262. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  263. package/packages/pi-ai/dist/image-models.generated.js +30 -0
  264. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  265. package/packages/pi-ai/dist/models.generated.d.ts +8 -127
  266. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  267. package/packages/pi-ai/dist/models.generated.js +47 -166
  268. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  269. package/packages/pi-ai/package.json +1 -1
  270. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/auth-storage.js +11 -3
  272. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  273. package/packages/pi-coding-agent/package.json +7 -7
  274. package/packages/pi-tui/dist/components/input.js +1 -1
  275. package/packages/pi-tui/dist/components/input.js.map +1 -1
  276. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  277. package/packages/pi-tui/dist/keys.js +39 -30
  278. package/packages/pi-tui/dist/keys.js.map +1 -1
  279. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  280. package/packages/pi-tui/dist/stdin-buffer.js +22 -0
  281. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  282. package/packages/pi-tui/package.json +2 -2
  283. package/packages/rpc-client/package.json +2 -2
  284. package/pkg/package.json +1 -1
  285. package/scripts/install/deps.js +10 -0
  286. package/scripts/link-workspace-packages.cjs +7 -40
  287. package/src/resources/extensions/ask-user-questions.ts +87 -24
  288. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +126 -289
  289. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +242 -2
  290. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
  291. package/src/resources/extensions/github-sync/templates.ts +3 -3
  292. package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
  293. package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
  294. package/src/resources/extensions/gsd/auto/contracts.ts +40 -121
  295. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  296. package/src/resources/extensions/gsd/auto/loop.ts +83 -61
  297. package/src/resources/extensions/gsd/auto/orchestrator.ts +913 -64
  298. package/src/resources/extensions/gsd/auto/phases.ts +35 -3
  299. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
  300. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  301. package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
  302. package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
  303. package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
  304. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
  305. package/src/resources/extensions/gsd/auto-prompts.ts +220 -9
  306. package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
  307. package/src/resources/extensions/gsd/auto-runtime-state.ts +30 -0
  308. package/src/resources/extensions/gsd/auto-start.ts +17 -20
  309. package/src/resources/extensions/gsd/auto-timers.ts +16 -2
  310. package/src/resources/extensions/gsd/auto-tool-tracking.ts +40 -0
  311. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +42 -30
  312. package/src/resources/extensions/gsd/auto-verification.ts +7 -8
  313. package/src/resources/extensions/gsd/auto-worktree.ts +57 -42
  314. package/src/resources/extensions/gsd/auto.ts +96 -508
  315. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
  316. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
  317. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  318. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +120 -151
  319. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
  320. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
  321. package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
  322. package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
  323. package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
  324. package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
  325. package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
  326. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  327. package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
  328. package/src/resources/extensions/gsd/db-workspace.ts +170 -0
  329. package/src/resources/extensions/gsd/debug-logger.ts +11 -0
  330. package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
  331. package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
  332. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  333. package/src/resources/extensions/gsd/doctor-proactive.ts +8 -2
  334. package/src/resources/extensions/gsd/doctor.ts +15 -5
  335. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  336. package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
  337. package/src/resources/extensions/gsd/gsd-db.ts +12 -0
  338. package/src/resources/extensions/gsd/guided-flow.ts +49 -560
  339. package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
  340. package/src/resources/extensions/gsd/markdown-renderer.ts +40 -20
  341. package/src/resources/extensions/gsd/mcp-filter.ts +9 -1
  342. package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
  343. package/src/resources/extensions/gsd/md-importer.ts +3 -3
  344. package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
  345. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  346. package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
  347. package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
  348. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
  349. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
  350. package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
  351. package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
  352. package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
  353. package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
  354. package/src/resources/extensions/gsd/native-git-bridge.ts +48 -0
  355. package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
  356. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
  357. package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
  358. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  359. package/src/resources/extensions/gsd/preferences.ts +173 -28
  360. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  361. package/src/resources/extensions/gsd/prompts/discuss.md +6 -7
  362. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
  363. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
  364. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
  365. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
  366. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
  367. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  368. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -1
  369. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  370. package/src/resources/extensions/gsd/prompts/research-milestone.md +2 -2
  371. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  372. package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -3
  373. package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
  374. package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
  375. package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
  376. package/src/resources/extensions/gsd/question-transport.ts +138 -0
  377. package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
  378. package/src/resources/extensions/gsd/schemas/parsers.ts +6 -1
  379. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
  380. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +31 -10
  381. package/src/resources/extensions/gsd/state.ts +15 -5
  382. package/src/resources/extensions/gsd/templates/plan.md +7 -0
  383. package/src/resources/extensions/gsd/templates/project.md +1 -0
  384. package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
  385. package/src/resources/extensions/gsd/templates/uat.md +5 -1
  386. package/src/resources/extensions/gsd/tests/artifact-db-drift-memo.test.ts +66 -0
  387. package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
  388. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
  389. package/src/resources/extensions/gsd/tests/auto-dispatch-baseline-harness.test.ts +53 -0
  390. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
  391. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
  392. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
  393. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +709 -845
  394. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +38 -10
  395. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
  396. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
  397. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  398. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
  399. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
  400. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +15 -0
  401. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
  402. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
  403. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
  404. package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +64 -1
  405. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
  406. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
  407. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
  408. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
  409. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +157 -0
  410. package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +75 -0
  411. package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
  412. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
  413. package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
  414. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
  415. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
  416. package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
  417. package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
  418. package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
  419. package/src/resources/extensions/gsd/tests/native-merge-regular.test.ts +139 -0
  420. package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +127 -0
  421. package/src/resources/extensions/gsd/tests/parse-project-milestone-bridge.test.ts +77 -0
  422. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
  423. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +6 -2
  424. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
  425. package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
  426. package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
  427. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +75 -2
  428. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
  429. package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
  430. package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
  431. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
  432. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +65 -0
  433. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
  434. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
  435. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
  436. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
  437. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
  438. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +21 -6
  439. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +38 -0
  440. package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
  441. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
  442. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
  443. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
  444. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +147 -0
  445. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
  446. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
  447. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
  448. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
  449. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
  450. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
  451. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +24 -0
  452. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
  453. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -3
  454. package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
  455. package/src/resources/extensions/gsd/tool-contract.ts +86 -8
  456. package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
  457. package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
  458. package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
  459. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
  460. package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
  461. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +183 -21
  462. package/src/resources/extensions/gsd/uat-policy.ts +19 -10
  463. package/src/resources/extensions/gsd/uat-run.ts +10 -14
  464. package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
  465. package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
  466. package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
  467. package/src/resources/extensions/gsd/user-input-boundary.ts +55 -5
  468. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  469. package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
  470. package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
  471. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  472. package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
  473. package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
  474. package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
  475. package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
  476. package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
  477. package/src/resources/extensions/shared/interview-ui.ts +15 -2
  478. package/src/resources/shared/claude-runtime-floor.ts +248 -0
  479. package/dist/web/standalone/.next/server/chunks/678.js +0 -2
  480. package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
  481. package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
  482. package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
  483. package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
  484. package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
  485. package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
  486. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +0 -21
  487. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +0 -1
  488. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +0 -213
  489. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +0 -1
  490. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts +0 -28
  491. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts.map +0 -1
  492. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js +0 -249
  493. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js.map +0 -1
  494. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts +0 -19
  495. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts.map +0 -1
  496. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js +0 -797
  497. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js.map +0 -1
  498. package/scripts/ensure-workspace-builds.cjs +0 -129
  499. /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → tkLHUSzPA2kMmWz4DmGwI}/_buildManifest.js +0 -0
  500. /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → tkLHUSzPA2kMmWz4DmGwI}/_ssgManifest.js +0 -0
@@ -10,13 +10,13 @@ import { parseRoadmap } from "./parsers-legacy.js";
10
10
  import { resolveMilestoneFile } from "./paths.js";
11
11
  import { getMilestone, getMilestoneSlices, isDbAvailable } from "./gsd-db.js";
12
12
  import { isClosedStatus } from "./status-guards.js";
13
- import { verifyExpectedArtifact } from "./auto-recovery.js";
14
13
  import { runSafely } from "./auto-utils.js";
15
14
  import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
16
15
  import { logWarning } from "./workflow-logger.js";
17
16
  import { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
18
17
  import { buildCompleteMilestonePrompt } from "./auto-prompts.js";
19
- import { checkCloseoutConsistencyGate } from "./closeout-consistency-gate.js";
18
+ import { proveMilestoneCloseout } from "./milestone-closeout-proof.js";
19
+ import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
20
20
  import type { DispatchAction, DispatchContext } from "./auto-dispatch.js";
21
21
  import {
22
22
  commitPendingMilestoneCloseoutChanges,
@@ -38,8 +38,16 @@ export async function isMilestoneCloseoutSettled(mid: string, basePath: string):
38
38
  if (isDbAvailable()) {
39
39
  const milestone = getMilestone(mid);
40
40
  if (milestone && isClosedStatus(milestone.status)) {
41
- const closeoutGate = checkCloseoutConsistencyGate(mid, { refreshFromDisk: true });
42
- if (closeoutGate.ok && verifyExpectedArtifact("complete-milestone", mid, basePath)) {
41
+ const artifactBasePath = resolveCanonicalMilestoneRoot(basePath, mid);
42
+ const closeoutProof = proveMilestoneCloseout(mid, {
43
+ refreshFromDisk: true,
44
+ summaryArtifactBasePath: artifactBasePath,
45
+ implementationEvidence: {
46
+ basePath,
47
+ requirement: "not-absent",
48
+ },
49
+ });
50
+ if (closeoutProof.ok) {
43
51
  return true;
44
52
  }
45
53
  }
@@ -0,0 +1,47 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Process-level transaction wrapper for milestone merge closeout.
3
+
4
+ export interface MilestoneMergeTransactionResult {
5
+ pushed: boolean;
6
+ codeFilesChanged: boolean;
7
+ commitMessage?: string;
8
+ prCreated?: boolean;
9
+ }
10
+
11
+ export interface MilestoneMergeTransactionInput {
12
+ basePath: string;
13
+ milestoneId: string;
14
+ roadmapContent: string;
15
+ }
16
+
17
+ export type MilestoneMergeTransactionRunner = (
18
+ basePath: string,
19
+ milestoneId: string,
20
+ roadmapContent: string,
21
+ ) => MilestoneMergeTransactionResult;
22
+
23
+ export interface MilestoneMergeTransactionDeps {
24
+ mergeMilestoneToMain: MilestoneMergeTransactionRunner;
25
+ }
26
+
27
+ export function runMilestoneMergeTransaction(
28
+ deps: MilestoneMergeTransactionDeps,
29
+ input: MilestoneMergeTransactionInput,
30
+ ): MilestoneMergeTransactionResult {
31
+ return deps.mergeMilestoneToMain(
32
+ input.basePath,
33
+ input.milestoneId,
34
+ input.roadmapContent,
35
+ );
36
+ }
37
+
38
+ export function createMilestoneMergeTransaction(
39
+ mergeMilestoneToMain: MilestoneMergeTransactionRunner,
40
+ ): MilestoneMergeTransactionRunner {
41
+ return function mergeMilestoneTransaction(basePath, milestoneId, roadmapContent) {
42
+ return runMilestoneMergeTransaction(
43
+ { mergeMilestoneToMain },
44
+ { basePath, milestoneId, roadmapContent },
45
+ );
46
+ };
47
+ }
@@ -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
+ }