@opengsd/gsd-pi 1.1.1-dev.74e8dd1 → 1.1.1-dev.75048e7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/dist/cli.js +3 -2
  2. package/dist/help-text.js +10 -6
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
  5. package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
  6. package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
  7. package/dist/resources/extensions/browser-tools/index.js +57 -9
  8. package/dist/resources/extensions/browser-tools/package.json +5 -1
  9. package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
  10. package/dist/resources/extensions/gsd/auto-dashboard.js +77 -13
  11. package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
  12. package/dist/resources/extensions/gsd/auto-post-unit.js +21 -3
  13. package/dist/resources/extensions/gsd/auto-prompts.js +63 -22
  14. package/dist/resources/extensions/gsd/auto-recovery.js +3 -4
  15. package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
  16. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  17. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +18 -66
  18. package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
  19. package/dist/resources/extensions/gsd/auto.js +9 -2
  20. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +20 -14
  21. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +28 -13
  22. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +18 -29
  23. package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
  24. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
  25. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
  26. package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
  27. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -1
  28. package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
  29. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  30. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
  31. package/dist/resources/extensions/gsd/escalation.js +4 -4
  32. package/dist/resources/extensions/gsd/forensics.js +74 -2
  33. package/dist/resources/extensions/gsd/gsd-db.js +5 -2
  34. package/dist/resources/extensions/gsd/guided-flow.js +118 -175
  35. package/dist/resources/extensions/gsd/mcp-project-config.js +9 -76
  36. package/dist/resources/extensions/gsd/memory-store.js +4 -1
  37. package/dist/resources/extensions/gsd/milestone-closeout.js +3 -1
  38. package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
  39. package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
  40. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  41. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  42. package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
  43. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  44. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  45. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  46. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  47. package/dist/resources/extensions/gsd/prompts/run-uat.md +25 -21
  48. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  49. package/dist/resources/extensions/gsd/recovery-classification.js +20 -0
  50. package/dist/resources/extensions/gsd/rule-registry.js +428 -52
  51. package/dist/resources/extensions/gsd/state.js +2 -2
  52. package/dist/resources/extensions/gsd/templates/plan.md +3 -1
  53. package/dist/resources/extensions/gsd/tool-contract.js +5 -0
  54. package/dist/resources/extensions/gsd/tool-presentation-plan.js +30 -7
  55. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
  56. package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
  57. package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
  58. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +132 -18
  59. package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
  60. package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
  61. package/dist/resources/extensions/gsd/verification-gate.js +72 -1
  62. package/dist/resources/extensions/gsd/workflow-mcp.js +3 -75
  63. package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
  64. package/dist/rtk.d.ts +7 -1
  65. package/dist/rtk.js +27 -11
  66. package/dist/update-check.d.ts +15 -1
  67. package/dist/update-check.js +87 -12
  68. package/dist/update-cmd.d.ts +1 -0
  69. package/dist/update-cmd.js +53 -2
  70. package/dist/web/standalone/.next/BUILD_ID +1 -1
  71. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  72. package/dist/web/standalone/.next/build-manifest.json +2 -2
  73. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  74. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/index.html +1 -1
  92. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  99. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  100. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  102. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  103. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  104. package/package.json +4 -2
  105. package/packages/cloud-mcp-gateway/package.json +2 -2
  106. package/packages/contracts/package.json +1 -1
  107. package/packages/daemon/package.json +4 -4
  108. package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
  109. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  110. package/packages/gsd-agent-core/dist/agent-session.js +32 -0
  111. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  112. package/packages/gsd-agent-core/dist/index.d.ts +1 -0
  113. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  114. package/packages/gsd-agent-core/dist/index.js +1 -0
  115. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  116. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
  117. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
  118. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
  119. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
  120. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
  121. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  122. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  123. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  124. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
  125. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  126. package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
  127. package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
  128. package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
  129. package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
  130. package/packages/gsd-agent-core/package.json +6 -6
  131. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
  132. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
  133. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
  134. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
  135. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  136. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  137. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  138. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  139. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +20 -0
  140. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  141. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  142. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
  143. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  144. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
  145. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
  146. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
  147. package/packages/gsd-agent-modes/package.json +7 -7
  148. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  149. package/packages/mcp-server/dist/remote-questions.js +23 -9
  150. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  151. package/packages/mcp-server/dist/workflow-tools.js +2 -2
  152. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  153. package/packages/mcp-server/package.json +3 -3
  154. package/packages/native/package.json +1 -1
  155. package/packages/pi-agent-core/dist/agent-loop.js +42 -3
  156. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  157. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  158. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  159. package/packages/pi-agent-core/dist/agent.js +2 -0
  160. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  161. package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  162. package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
  163. package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  164. package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
  165. package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  166. package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
  167. package/packages/pi-agent-core/dist/types.d.ts +6 -1
  168. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  169. package/packages/pi-agent-core/dist/types.js.map +1 -1
  170. package/packages/pi-agent-core/package.json +1 -1
  171. package/packages/pi-ai/dist/api-registry.d.ts +2 -0
  172. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  173. package/packages/pi-ai/dist/api-registry.js +23 -0
  174. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  175. package/packages/pi-ai/dist/models.generated.d.ts +74 -23
  176. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  177. package/packages/pi-ai/dist/models.generated.js +82 -31
  178. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  179. package/packages/pi-ai/dist/stream.js +6 -6
  180. package/packages/pi-ai/dist/stream.js.map +1 -1
  181. package/packages/pi-ai/package.json +1 -1
  182. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
  183. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  187. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  188. package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
  189. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  190. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
  192. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
  194. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
  196. package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
  197. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
  199. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  200. package/packages/pi-coding-agent/package.json +7 -7
  201. package/packages/pi-tui/package.json +1 -1
  202. package/packages/rpc-client/package.json +2 -2
  203. package/pkg/package.json +1 -1
  204. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
  205. package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
  206. package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
  207. package/src/resources/extensions/browser-tools/index.ts +60 -9
  208. package/src/resources/extensions/browser-tools/package.json +5 -1
  209. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
  210. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
  211. package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
  212. package/src/resources/extensions/gsd/auto-dashboard.ts +82 -14
  213. package/src/resources/extensions/gsd/auto-dispatch.ts +19 -0
  214. package/src/resources/extensions/gsd/auto-post-unit.ts +28 -2
  215. package/src/resources/extensions/gsd/auto-prompts.ts +97 -15
  216. package/src/resources/extensions/gsd/auto-recovery.ts +3 -3
  217. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
  218. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  219. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -74
  220. package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
  221. package/src/resources/extensions/gsd/auto.ts +12 -2
  222. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +20 -14
  223. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +32 -13
  224. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +50 -54
  225. package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
  226. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
  227. package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -2
  228. package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
  229. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -1
  230. package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
  231. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  232. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
  233. package/src/resources/extensions/gsd/escalation.ts +4 -4
  234. package/src/resources/extensions/gsd/forensics.ts +99 -5
  235. package/src/resources/extensions/gsd/gsd-db.ts +5 -2
  236. package/src/resources/extensions/gsd/guided-flow.ts +214 -216
  237. package/src/resources/extensions/gsd/mcp-project-config.ts +13 -78
  238. package/src/resources/extensions/gsd/memory-store.ts +4 -1
  239. package/src/resources/extensions/gsd/milestone-closeout.ts +3 -1
  240. package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
  241. package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
  242. package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
  243. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  244. package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
  245. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  246. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  247. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  248. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  249. package/src/resources/extensions/gsd/prompts/run-uat.md +25 -21
  250. package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  251. package/src/resources/extensions/gsd/recovery-classification.ts +20 -0
  252. package/src/resources/extensions/gsd/rule-registry.ts +558 -58
  253. package/src/resources/extensions/gsd/rule-types.ts +2 -0
  254. package/src/resources/extensions/gsd/state.ts +2 -2
  255. package/src/resources/extensions/gsd/templates/plan.md +3 -1
  256. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +105 -4
  257. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +37 -0
  258. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +10 -2
  259. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
  260. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +12 -2
  261. package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
  262. package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
  263. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
  264. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
  265. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
  266. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  267. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
  268. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
  269. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
  270. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +40 -1
  271. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
  272. package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
  273. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
  274. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
  275. package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
  276. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +31 -79
  277. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
  278. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
  279. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +5 -3
  280. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
  281. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
  282. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
  283. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
  284. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
  285. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +72 -10
  286. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +32 -0
  287. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +2 -0
  288. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
  289. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +63 -0
  290. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
  291. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
  292. package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
  293. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
  294. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
  295. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
  296. package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
  297. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +73 -1
  298. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
  299. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
  300. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +44 -0
  301. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
  302. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +4 -0
  303. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
  304. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
  305. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +139 -0
  306. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -4
  307. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  308. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
  309. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
  310. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
  311. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
  312. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +410 -0
  313. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -0
  314. package/src/resources/extensions/gsd/tool-contract.ts +6 -0
  315. package/src/resources/extensions/gsd/tool-presentation-plan.ts +63 -7
  316. package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
  317. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
  318. package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
  319. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +163 -20
  320. package/src/resources/extensions/gsd/types.ts +69 -5
  321. package/src/resources/extensions/gsd/unit-tool-contracts.ts +186 -0
  322. package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
  323. package/src/resources/extensions/gsd/verification-gate.ts +87 -1
  324. package/src/resources/extensions/gsd/workflow-mcp.ts +3 -75
  325. package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
  326. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
  327. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
  328. /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → h4TGni4xJzlZjGkxaT6uU}/_buildManifest.js +0 -0
  329. /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → h4TGni4xJzlZjGkxaT6uU}/_ssgManifest.js +0 -0
@@ -98,6 +98,7 @@ import {
98
98
  getDiscussionMilestoneId,
99
99
  hasPendingAutoStart,
100
100
  setPendingAutoStart,
101
+ type PendingAutoStartEntry,
101
102
  } from "./pending-auto-start.js";
102
103
  import { clearGuidedUnitContext, setGuidedUnitContext } from "./guided-unit-context.js";
103
104
 
@@ -227,21 +228,22 @@ async function dispatchDiscussForNextMilestoneWithBacklog(
227
228
  nextId: string,
228
229
  ): Promise<void> {
229
230
  const backlogContext = buildRequirementsBacklogDiscussContext(nextId);
230
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
231
231
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
232
- const basePrompt = loadPrompt("guided-discuss-milestone", {
233
- workingDirectory: basePath,
234
- milestoneId: nextId,
235
- milestoneTitle: `New milestone ${nextId}`,
236
- inlinedTemplates: discussMilestoneTemplates,
232
+ const basePrompt = await buildDiscussMilestonePrompt(
233
+ nextId,
234
+ `New milestone ${nextId}`,
235
+ basePath,
237
236
  structuredQuestionsAvailable,
238
- commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
239
- fastPathInstruction: [
240
- "> **Requirements backlog active.**",
241
- "> Map unmapped active requirements to this milestone before finalizing context.",
242
- "> Confirm ownership with the user when scope is ambiguous.",
243
- ].join("\n"),
244
- });
237
+ {
238
+ commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
239
+ includeContextMode: false,
240
+ fastPathInstruction: [
241
+ "> **Requirements backlog active.**",
242
+ "> Map unmapped active requirements to this milestone before finalizing context.",
243
+ "> Confirm ownership with the user when scope is ambiguous.",
244
+ ].join("\n"),
245
+ },
246
+ );
245
247
  const prompt = backlogContext ? `${basePrompt}\n\n${backlogContext}` : basePrompt;
246
248
  await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
247
249
  }
@@ -319,6 +321,116 @@ export function _roadmapHasParseableSlicesForTest(
319
321
  return parseRoadmapSlices(roadmapContent).length > 0;
320
322
  }
321
323
 
324
+ function hasExecutablePlanForHandoff(milestoneId: string, roadmapFile: string | null): boolean {
325
+ if (isDbAvailable()) {
326
+ return getMilestoneSlices(milestoneId).length > 0;
327
+ }
328
+ if (!roadmapFile) return false;
329
+ try {
330
+ return parseRoadmapSlices(readFileSync(roadmapFile, "utf-8")).length > 0;
331
+ } catch (e) {
332
+ logWarning(
333
+ "guided",
334
+ `failed to parse roadmap slices for ${milestoneId}: ${(e as Error).message}`,
335
+ );
336
+ return false;
337
+ }
338
+ }
339
+
340
+ function formatAcceptedDiscussHandoffMessage(
341
+ milestoneId: string,
342
+ contextFile: string | null,
343
+ hasExecutablePlan: boolean,
344
+ ): string {
345
+ if (hasExecutablePlan) return `Milestone ${milestoneId} ready.`;
346
+ if (contextFile) return `Milestone ${milestoneId} context captured. Continuing the planning pipeline.`;
347
+ return `Milestone ${milestoneId} planning artifacts captured. Continuing the planning pipeline.`;
348
+ }
349
+
350
+ function manifestContainsMilestone(basePath: string, milestoneId: string): boolean {
351
+ try {
352
+ const manifest = readManifest(basePath);
353
+ return (
354
+ Array.isArray(manifest?.milestones) &&
355
+ manifest.milestones.some(m => m.id === milestoneId)
356
+ );
357
+ } catch (e) {
358
+ logWarning("guided", `R3b: failed to read state manifest: ${(e as Error).message}`);
359
+ return false;
360
+ }
361
+ }
362
+
363
+ function notifyDbRowRecoveryFailed(entry: PendingAutoStartEntry): void {
364
+ entry.ctx.ui.notify(
365
+ `Milestone ${entry.milestoneId}: DB row recovery failed ${entry.r3bRecoveryCount} times. ` +
366
+ `Re-run /gsd to reset the recovery counter, or run /gsd-debug to diagnose without resetting.`,
367
+ "error",
368
+ );
369
+ }
370
+
371
+ function noteDbRowRecoveryMiss(entry: PendingAutoStartEntry): void {
372
+ entry.r3bRecoveryCount += 1;
373
+ if (entry.r3bRecoveryCount >= MAX_DB_ROW_RECOVERIES) {
374
+ notifyDbRowRecoveryFailed(entry);
375
+ }
376
+ }
377
+
378
+ function ensureMilestoneRowForAcceptedHandoff(
379
+ entry: PendingAutoStartEntry,
380
+ contextFile: string | null,
381
+ ): boolean {
382
+ if (!isDbAvailable()) return true;
383
+
384
+ const { basePath, milestoneId } = entry;
385
+ const milestoneRow = getMilestone(milestoneId);
386
+ if (milestoneRow) return true;
387
+
388
+ if (manifestContainsMilestone(basePath, milestoneId)) {
389
+ logWarning(
390
+ "guided",
391
+ `R3b: getMilestone(${milestoneId}) returned null but manifest has the row — treating as stale read`,
392
+ );
393
+ return true;
394
+ }
395
+
396
+ if (!contextFile) {
397
+ entry.ctx.ui.notify(
398
+ `Milestone ${milestoneId}: discuss artifacts on disk but no DB row exists. ` +
399
+ `PROJECT.md may have failed to register milestones. ` +
400
+ `Re-save PROJECT.md with canonical "- [ ] M001: Title — One-liner" lines, ` +
401
+ `then re-run /gsd to recover.`,
402
+ "error",
403
+ );
404
+ return false;
405
+ }
406
+
407
+ if (entry.r3bRecoveryCount >= MAX_DB_ROW_RECOVERIES) {
408
+ logWarning(
409
+ "guided",
410
+ `R3b: milestone ${milestoneId} DB-row recovery limit reached ` +
411
+ `(${entry.r3bRecoveryCount}/${MAX_DB_ROW_RECOVERIES}); user already notified`,
412
+ );
413
+ return false;
414
+ }
415
+
416
+ logWarning(
417
+ "guided",
418
+ `R3b: ${milestoneId} has CONTEXT.md but no DB row — inserting placeholder "queued" row ` +
419
+ `(attempt ${entry.r3bRecoveryCount + 1}/${MAX_DB_ROW_RECOVERIES})`,
420
+ );
421
+
422
+ try {
423
+ insertMilestone({ id: milestoneId, title: milestoneId, status: "queued" });
424
+ } catch (e) {
425
+ logWarning("guided", `R3b: insertMilestone failed: ${(e as Error).message}`);
426
+ }
427
+
428
+ if (getMilestone(milestoneId)) return true;
429
+
430
+ noteDbRowRecoveryMiss(entry);
431
+ return false;
432
+ }
433
+
322
434
  // ─── Commit Instruction Helpers ──────────────────────────────────────────────
323
435
 
324
436
  /** Build commit instruction for planning prompts. .gsd/ is managed externally and always gitignored. */
@@ -343,10 +455,8 @@ interface PendingDeepProjectSetupEntry {
343
455
  // phrase before giving up and asking the user to re-run /gsd.
344
456
  const MAX_READY_REJECTS = 2;
345
457
 
346
- // H1 (#5012): cap for Gate 1b plan-blocked recovery hints. After this many
347
- // consecutive recovery attempts the loop is stopped and the user is directed
348
- // to investigate manually.
349
- const MAX_PLAN_BLOCKED_RECOVERIES = 3;
458
+ // Cap failed in-flight DB row repair attempts before escalating to the user.
459
+ const MAX_DB_ROW_RECOVERIES = 3;
350
460
 
351
461
  // #4573: matches the canonical ready phrase the discuss prompt asks the LLM
352
462
  // to emit. Accepts any M-prefixed milestone ID (three digits + optional
@@ -612,72 +722,12 @@ export function checkAutoStartAfterDiscuss(lookupBasePath?: string): boolean {
612
722
  }
613
723
  }
614
724
 
615
- // Gate 1b: Discriminate plan-blocked from discuss-incomplete when the DB row is queued.
616
- // If the DB is available and the row is still "queued" but CONTEXT.md already exists on
617
- // disk, the discuss phase completed but gsd_plan_milestone was hard-blocked by the
618
- // depth-verification gate. Emit a recovery hint so the next agent turn can retry
619
- // gsd_plan_milestone, then return false (keep blocking auto-start).
620
- // If CONTEXT.md does not exist (discuss-incomplete), Gate 1 already blocked above.
621
- if (isDbAvailable()) {
622
- const dbRow = getMilestone(milestoneId);
623
- if (dbRow?.status === "queued" && contextFile) {
624
- if (entry.planBlockedRecoveryCount >= MAX_PLAN_BLOCKED_RECOVERIES) {
625
- // H1: recovery loop cap reached — stop triggering new turns, escalate to user.
626
- logWarning(
627
- "guided",
628
- `Gate 1b: milestone ${milestoneId} plan-blocked recovery limit reached ` +
629
- `(${entry.planBlockedRecoveryCount}/${MAX_PLAN_BLOCKED_RECOVERIES}); escalating to user`,
630
- );
631
- ctx.ui.notify(
632
- `Milestone ${milestoneId} plan_milestone has been blocked ${entry.planBlockedRecoveryCount} times. ` +
633
- `Re-run /gsd to reset the recovery counter, or run /gsd-debug to diagnose without resetting.`,
634
- "error",
635
- );
636
- return false;
637
- }
638
- logWarning(
639
- "guided",
640
- `Gate 1b: milestone ${milestoneId} queued with CONTEXT.md present — ` +
641
- `plan_milestone was blocked; emitting recovery hint ` +
642
- `(attempt ${entry.planBlockedRecoveryCount + 1}/${MAX_PLAN_BLOCKED_RECOVERIES})`,
643
- );
644
- ctx.ui.notify(
645
- `Milestone ${milestoneId}: context file exists but milestone is still queued. ` +
646
- `Retrying gsd_plan_milestone to complete the blocked planning step.`,
647
- "warning",
648
- );
649
- try {
650
- pi.sendMessage(
651
- {
652
- customType: "gsd-plan-milestone-blocked-recovery",
653
- content:
654
- `Milestone ${milestoneId} has ${contextFile} on disk but its DB row is still ` +
655
- `"queued". The gsd_plan_milestone tool was previously blocked by the ` +
656
- `depth-verification gate. Call gsd_plan_milestone now to complete the ` +
657
- `planning phase.`,
658
- display: false,
659
- },
660
- { triggerTurn: true },
661
- );
662
- // Increment only after a successful dispatch so transient sendMessage
663
- // failures do not consume recovery budget.
664
- entry.planBlockedRecoveryCount += 1;
665
- } catch (e) {
666
- logWarning("guided", `Gate 1b recovery sendMessage failed: ${(e as Error).message}`);
667
- }
668
- return false;
669
- }
670
- }
725
+ // Gate 1b: accept the in-flight discuss handoff. A queued DB row with pinned
726
+ // CONTEXT.md is Discussion Complete, Planning Pending, not a plan-blocked
727
+ // failure. If the row is missing, only this pending handoff may repair it.
728
+ if (!ensureMilestoneRowForAcceptedHandoff(entry, contextFile)) return false;
671
729
 
672
- // Gate 2: STATE.md must exist — written as the last step in the discuss
673
- // output phase. This prevents auto-start from firing during Phase 3
674
- // (sequential readiness gates for remaining milestones) in multi-milestone
675
- // discussions, where M001-CONTEXT.md exists but M002/M003 haven't been
676
- // processed yet.
677
- const stateFilePath = entry.scope.stateFile();
678
- if (!existsSync(stateFilePath)) return false; // discussion not finalized yet
679
-
680
- // Gate 3: Multi-milestone completeness warning
730
+ // Gate 2: Multi-milestone completeness warning
681
731
  // Parse PROJECT.md for milestone sequence, warn if any are missing context.
682
732
  // Don't block — milestones can be intentionally queued without context.
683
733
  const projectFile = resolveGsdRootFile(basePath, "PROJECT");
@@ -704,7 +754,7 @@ export function checkAutoStartAfterDiscuss(lookupBasePath?: string): boolean {
704
754
  } catch (e) { logWarning("guided", `PROJECT.md parsing failed: ${(e as Error).message}`); }
705
755
  }
706
756
 
707
- // Gate 4: Discussion manifest process verification (multi-milestone only)
757
+ // Gate 3: Discussion manifest process verification (multi-milestone only)
708
758
  // The LLM writes DISCUSSION-MANIFEST.json after each Phase 3 gate decision.
709
759
  // When it exists, validate it before auto-starting. Project history alone is
710
760
  // not a reliable signal for the current discussion mode.
@@ -746,71 +796,12 @@ export function checkAutoStartAfterDiscuss(lookupBasePath?: string): boolean {
746
796
  try { unlinkSync(manifestPath); } catch (e) { logWarning("guided", `manifest unlink failed: ${(e as Error).message}`); }
747
797
  }
748
798
 
749
- // R3b: belt-and-suspenders for silent registration failure. The discuss flow
750
- // finished and STATE.md exists, but the milestone may never have landed in
751
- // the DB. Without this guard, the user sees "Milestone M001 ready." and then
752
- // /gsd reports "No Active Milestone".
753
- if (isDbAvailable()) {
754
- const milestoneRow = getMilestone(milestoneId);
755
- if (!milestoneRow) {
756
- let manifestHasMilestone = false;
757
- try {
758
- const manifest = readManifest(basePath);
759
- manifestHasMilestone = Array.isArray(manifest?.milestones) && manifest.milestones.some(m => m.id === milestoneId);
760
- } catch (e) {
761
- logWarning("guided", `R3b: failed to read state manifest: ${(e as Error).message}`);
762
- }
763
- if (manifestHasMilestone) {
764
- logWarning("guided", `R3b: getMilestone(${milestoneId}) returned null but manifest has the row — treating as stale read`);
765
- } else if (contextFile) {
766
- // R3b-recovery: CONTEXT.md is on disk but gsd_plan_milestone was never called
767
- // (likely blocked by the depth-verification gate re-firing on post-verification
768
- // text). Auto-register as "queued" so Gate 1b can pick it up and retry
769
- // gsd_plan_milestone on the next checkAutoStartAfterDiscuss call.
770
- if (entry.r3bRecoveryCount >= MAX_PLAN_BLOCKED_RECOVERIES) {
771
- logWarning(
772
- "guided",
773
- `R3b: milestone ${milestoneId} DB-row recovery limit reached ` +
774
- `(${entry.r3bRecoveryCount}/${MAX_PLAN_BLOCKED_RECOVERIES}); escalating to user`,
775
- );
776
- ctx.ui.notify(
777
- `Milestone ${milestoneId}: DB row recovery failed ${entry.r3bRecoveryCount} times. ` +
778
- `Re-run /gsd to reset the recovery counter, or run /gsd-debug to diagnose without resetting.`,
779
- "error",
780
- );
781
- return false;
782
- }
783
- logWarning(
784
- "guided",
785
- `R3b: ${milestoneId} has CONTEXT.md but no DB row — inserting placeholder "queued" row ` +
786
- `for Gate 1b recovery (attempt ${entry.r3bRecoveryCount + 1}/${MAX_PLAN_BLOCKED_RECOVERIES})`,
787
- );
788
- try {
789
- insertMilestone({ id: milestoneId, title: milestoneId, status: "queued" });
790
- } catch (e) {
791
- logWarning("guided", `R3b: insertMilestone failed: ${(e as Error).message}`);
792
- }
793
- entry.r3bRecoveryCount += 1;
794
- ctx.ui.notify(
795
- `Milestone ${milestoneId}: context file exists but DB row was missing — recovering. Retrying gsd_plan_milestone.`,
796
- "warning",
797
- );
798
- return false;
799
- } else {
800
- ctx.ui.notify(
801
- `Milestone ${milestoneId}: discuss artifacts on disk but no DB row exists. ` +
802
- `PROJECT.md may have failed to register milestones. ` +
803
- `Re-save PROJECT.md with canonical "- [ ] M001: Title — One-liner" lines, ` +
804
- `then re-run /gsd to recover.`,
805
- "error",
806
- );
807
- return false;
808
- }
809
- }
810
- }
811
-
812
799
  deletePendingAutoStart(basePath);
813
- ctx.ui.notify(`Milestone ${milestoneId} ready.`, "success");
800
+ const hasExecutablePlan = hasExecutablePlanForHandoff(milestoneId, roadmapFile);
801
+ ctx.ui.notify(
802
+ formatAcceptedDiscussHandoffMessage(milestoneId, contextFile, hasExecutablePlan),
803
+ "success",
804
+ );
814
805
  if (entry.startAuto !== false) {
815
806
  scheduleAutoStartAfterIdle(ctx, pi, basePath, false, { step: step ?? true });
816
807
  }
@@ -1371,6 +1362,7 @@ async function buildDiscussPreparationContext(
1371
1362
  ctx: ExtensionCommandContext,
1372
1363
  basePath: string,
1373
1364
  mode: "greenfield" | "milestone" = "greenfield",
1365
+ skipPriorContext = false,
1374
1366
  ): Promise<string> {
1375
1367
  const prefs = loadEffectiveGSDPreferences()?.preferences ?? {};
1376
1368
  if (prefs.discuss_preparation === false) return "";
@@ -1388,7 +1380,7 @@ async function buildDiscussPreparationContext(
1388
1380
  const priorContextBrief = prepResult.priorContextBrief || formatPriorContextBrief(prepResult.priorContext);
1389
1381
  const parts: string[] = [];
1390
1382
  if (codebaseBrief) parts.push(`### Codebase Brief\n\n${codebaseBrief}`);
1391
- if (priorContextBrief) parts.push(`### Prior Context Brief\n\n${priorContextBrief}`);
1383
+ if (priorContextBrief && !skipPriorContext) parts.push(`### Prior Context Brief\n\n${priorContextBrief}`);
1392
1384
  if (parts.length === 0) return "";
1393
1385
 
1394
1386
  const guidance = mode === "milestone"
@@ -1441,18 +1433,18 @@ async function dispatchNewMilestoneDiscuss(
1441
1433
  return;
1442
1434
  }
1443
1435
 
1444
- const preparationContext = await buildDiscussPreparationContext(ctx, basePath, "milestone");
1445
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
1436
+ const preparationContext = await buildDiscussPreparationContext(ctx, basePath, "milestone", true);
1446
1437
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
1447
- let prompt = loadPrompt("guided-discuss-milestone", {
1448
- workingDirectory: basePath,
1449
- milestoneId: nextId,
1450
- milestoneTitle: `New milestone ${nextId}`,
1451
- inlinedTemplates: discussMilestoneTemplates,
1438
+ let prompt = await buildDiscussMilestonePrompt(
1439
+ nextId,
1440
+ `New milestone ${nextId}`,
1441
+ basePath,
1452
1442
  structuredQuestionsAvailable,
1453
- commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
1454
- fastPathInstruction: "",
1455
- });
1443
+ {
1444
+ commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): milestone context from discuss`),
1445
+ includeContextMode: false,
1446
+ },
1447
+ );
1456
1448
  if (preparationContext) prompt += preparationContext;
1457
1449
  await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
1458
1450
  }
@@ -1759,9 +1751,6 @@ export async function showDiscuss(
1759
1751
  // Special case: milestone is in needs-discussion phase (has CONTEXT-DRAFT.md but no roadmap yet).
1760
1752
  // Route to the draft discussion flow instead of erroring — the discussion IS how the roadmap gets created.
1761
1753
  if (state.phase === "needs-discussion") {
1762
- const draftFile = resolveMilestoneFile(basePath, mid, "CONTEXT-DRAFT");
1763
- const draftContent = draftFile ? await loadFile(draftFile) : null;
1764
-
1765
1754
  const choice = await showNextAction(ctx, {
1766
1755
  title: `GSD — ${mid}: ${milestoneTitle}`,
1767
1756
  summary: ["This milestone has a draft context from a prior discussion.", "It needs a dedicated discussion before auto-planning can begin."],
@@ -1787,29 +1776,34 @@ export async function showDiscuss(
1787
1776
  });
1788
1777
 
1789
1778
  if (choice === "discuss_draft") {
1790
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
1791
1779
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
1792
- const basePrompt = loadPrompt("guided-discuss-milestone", {
1793
- workingDirectory: basePath,
1794
- milestoneId: mid, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
1795
- commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
1796
- fastPathInstruction: "",
1797
- });
1798
- const seed = draftContent
1799
- ? `${basePrompt}\n\n## Prior Discussion (Draft Seed)\n\n${draftContent}`
1800
- : basePrompt;
1780
+ const seed = await buildDiscussMilestonePrompt(
1781
+ mid,
1782
+ milestoneTitle,
1783
+ basePath,
1784
+ structuredQuestionsAvailable,
1785
+ {
1786
+ commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
1787
+ includeContextMode: false,
1788
+ },
1789
+ );
1801
1790
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: mid, step: true });
1802
1791
  await dispatchWorkflow(pi, seed, "gsd-discuss", ctx, "discuss-milestone", { basePath });
1803
1792
  } else if (choice === "discuss_fresh") {
1804
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
1805
1793
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
1794
+ const prompt = await buildDiscussMilestonePrompt(
1795
+ mid,
1796
+ milestoneTitle,
1797
+ basePath,
1798
+ structuredQuestionsAvailable,
1799
+ {
1800
+ commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
1801
+ includeContextMode: false,
1802
+ includeDraftSeed: false,
1803
+ },
1804
+ );
1806
1805
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: mid, step: true });
1807
- await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
1808
- workingDirectory: basePath,
1809
- milestoneId: mid, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
1810
- commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
1811
- fastPathInstruction: "",
1812
- }), "gsd-discuss", ctx, "discuss-milestone", { basePath });
1806
+ await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
1813
1807
  } else if (choice === "skip_milestone") {
1814
1808
  const { ensureDbOpen } = await import("./bootstrap/dynamic-tools.js");
1815
1809
  await ensureDbOpen(basePath);
@@ -2068,20 +2062,18 @@ async function dispatchDiscussForMilestone(
2068
2062
  "> Ask only questions where the answer would materially change scope.",
2069
2063
  ].join("\n")
2070
2064
  : "";
2071
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
2072
2065
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
2073
- const basePrompt = loadPrompt("guided-discuss-milestone", {
2074
- workingDirectory: basePath,
2075
- milestoneId: mid,
2066
+ const prompt = await buildDiscussMilestonePrompt(
2067
+ mid,
2076
2068
  milestoneTitle,
2077
- inlinedTemplates: discussMilestoneTemplates,
2069
+ basePath,
2078
2070
  structuredQuestionsAvailable,
2079
- commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
2080
- fastPathInstruction,
2081
- });
2082
- const prompt = draftContent
2083
- ? `${basePrompt}\n\n## Prior Discussion (Draft Seed)\n\n${draftContent}`
2084
- : basePrompt;
2071
+ {
2072
+ commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
2073
+ includeContextMode: false,
2074
+ fastPathInstruction,
2075
+ },
2076
+ );
2085
2077
  await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
2086
2078
  }
2087
2079
 
@@ -2612,9 +2604,6 @@ export async function showSmartEntry(
2612
2604
 
2613
2605
  // ── Draft milestone — needs discussion before planning ────────────────
2614
2606
  if (state.phase === "needs-discussion") {
2615
- const draftFile = resolveMilestoneFile(basePath, milestoneId, "CONTEXT-DRAFT");
2616
- const draftContent = draftFile ? await loadFile(draftFile) : null;
2617
-
2618
2607
  const choice = await showNextAction(ctx, {
2619
2608
  title: `GSD — ${milestoneId}: ${milestoneTitle}`,
2620
2609
  summary: ["This milestone has a draft context from a prior discussion.", "It needs a dedicated discussion before auto-planning can begin."],
@@ -2640,29 +2629,34 @@ export async function showSmartEntry(
2640
2629
  });
2641
2630
 
2642
2631
  if (choice === "discuss_draft") {
2643
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
2644
2632
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
2645
- const basePrompt = loadPrompt("guided-discuss-milestone", {
2646
- workingDirectory: basePath,
2647
- milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
2648
- commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2649
- fastPathInstruction: "",
2650
- });
2651
- const seed = draftContent
2652
- ? `${basePrompt}\n\n## Prior Discussion (Draft Seed)\n\n${draftContent}`
2653
- : basePrompt;
2633
+ const seed = await buildDiscussMilestonePrompt(
2634
+ milestoneId,
2635
+ milestoneTitle,
2636
+ basePath,
2637
+ structuredQuestionsAvailable,
2638
+ {
2639
+ commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2640
+ includeContextMode: false,
2641
+ },
2642
+ );
2654
2643
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId, step: stepMode });
2655
2644
  await dispatchWorkflow(pi, seed, "gsd-discuss", ctx, "discuss-milestone", { basePath });
2656
2645
  } else if (choice === "discuss_fresh") {
2657
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
2658
2646
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
2647
+ const prompt = await buildDiscussMilestonePrompt(
2648
+ milestoneId,
2649
+ milestoneTitle,
2650
+ basePath,
2651
+ structuredQuestionsAvailable,
2652
+ {
2653
+ commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2654
+ includeContextMode: false,
2655
+ includeDraftSeed: false,
2656
+ },
2657
+ );
2659
2658
  setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId, step: stepMode });
2660
- await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
2661
- workingDirectory: basePath,
2662
- milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
2663
- commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2664
- fastPathInstruction: "",
2665
- }), "gsd-discuss", ctx, "discuss-milestone", { basePath });
2659
+ await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "discuss-milestone", { basePath });
2666
2660
  } else if (choice === "skip_milestone") {
2667
2661
  const milestoneIds = findMilestoneIds(basePath);
2668
2662
  const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
@@ -2783,14 +2777,18 @@ export async function showSmartEntry(
2783
2777
  { basePath },
2784
2778
  );
2785
2779
  } else if (choice === "discuss") {
2786
- const discussMilestoneTemplates = inlineTemplate("context", "Context");
2787
2780
  const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
2788
- await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
2789
- workingDirectory: basePath,
2790
- milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
2791
- commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2792
- fastPathInstruction: "",
2793
- }), "gsd-run", ctx, "discuss-milestone", { basePath });
2781
+ const prompt = await buildDiscussMilestonePrompt(
2782
+ milestoneId,
2783
+ milestoneTitle,
2784
+ basePath,
2785
+ structuredQuestionsAvailable,
2786
+ {
2787
+ commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
2788
+ includeContextMode: false,
2789
+ },
2790
+ );
2791
+ await dispatchWorkflow(pi, prompt, "gsd-run", ctx, "discuss-milestone", { basePath });
2794
2792
  } else if (choice === "skip_milestone") {
2795
2793
  const milestoneIds = findMilestoneIds(basePath);
2796
2794
  const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;