@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
@@ -1,12 +1,9 @@
1
1
  /**
2
- * gsd-pi / guided-flow — regression tests for Gate 1b orphan discrimination
2
+ * gsd-pi / guided-flow — regression tests for Gate 1b discussion handoff
3
3
  *
4
- * Gate 1b in checkAutoStartAfterDiscuss discriminates between two "queued" states:
5
- * (a) plan-blocked: discuss completed (CONTEXT.md on disk), but gsd_plan_milestone
6
- * was hard-blocked by the depth-verification gate. DB row stuck at "queued".
7
- * → emit recovery hint directing the LLM to retry gsd_plan_milestone.
8
- * (b) discuss-incomplete: discuss did not finish, no CONTEXT.md, DB row "queued".
9
- * → silent block (no recovery hint).
4
+ * Gate 1b treats queued + pinned CONTEXT.md as Discussion Complete, Planning
5
+ * Pending. It must accept the handoff without warning the user or injecting a
6
+ * hidden gsd_plan_milestone retry.
10
7
  */
11
8
 
12
9
  import { describe, test, beforeEach, afterEach } from "node:test";
@@ -27,8 +24,6 @@ import {
27
24
  insertMilestone,
28
25
  } from "../gsd-db.ts";
29
26
 
30
- // ─── Harness ───────────────────────────────────────────────────────────────
31
-
32
27
  interface MockCapture {
33
28
  notifies: Array<{ msg: string; level: string }>;
34
29
  messages: Array<{ payload: any; options: any }>;
@@ -58,24 +53,26 @@ function mkPi(cap: MockCapture): any {
58
53
  };
59
54
  }
60
55
 
61
- /**
62
- * Create a minimal temp tree with a .gsd/milestones/M001 directory.
63
- */
64
56
  function mkBase(): string {
65
57
  const base = mkdtempSync(join(tmpdir(), "gsd-gate1b-"));
66
58
  mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
67
59
  return base;
68
60
  }
69
61
 
70
- // ─── Tests ─────────────────────────────────────────────────────────────────
62
+ function writeContext(base: string): void {
63
+ writeFileSync(
64
+ join(base, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
65
+ "# M001: Test Milestone\n\nContext written by discuss phase.\n",
66
+ );
67
+ }
71
68
 
72
- describe("Gate 1b orphan discrimination in checkAutoStartAfterDiscuss", () => {
69
+ describe("Gate 1b discussion handoff in checkAutoStartAfterDiscuss", () => {
73
70
  let base: string;
74
71
  let cap: MockCapture;
75
72
 
76
73
  beforeEach(() => {
77
74
  clearPendingAutoStart();
78
- drainLogs(); // discard noise from prior tests
75
+ drainLogs();
79
76
  });
80
77
 
81
78
  afterEach(() => {
@@ -86,104 +83,59 @@ describe("Gate 1b orphan discrimination in checkAutoStartAfterDiscuss", () => {
86
83
  }
87
84
  });
88
85
 
89
- test("plan-blocked: CONTEXT.md present + DB row queued → returns false + recovery hint emitted", () => {
86
+ test("queued row + CONTEXT.md accepts context-captured handoff without hidden retry", () => {
90
87
  base = mkBase();
91
88
  openDatabase(":memory:");
92
-
93
- // DB row exists with status "queued" (plan_milestone was blocked)
94
89
  insertMilestone({ id: "M001", title: "Test Milestone", status: "queued" });
95
-
96
- // CONTEXT.md on disk (discuss phase completed)
97
- writeFileSync(
98
- join(base, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
99
- "# M001: Test Milestone\n\nContext written by discuss phase.\n",
100
- );
90
+ writeContext(base);
101
91
 
102
92
  cap = mkCapture();
103
93
  setPendingAutoStart(base, {
104
94
  basePath: base,
105
95
  milestoneId: "M001",
96
+ startAuto: false,
106
97
  ctx: mkCtx(cap),
107
98
  pi: mkPi(cap),
108
99
  });
109
100
 
110
101
  const result = checkAutoStartAfterDiscuss();
111
102
 
112
- // Must return false auto-start should not proceed
113
- assert.equal(result, false, "checkAutoStartAfterDiscuss must return false (plan still blocked)");
114
-
115
- // Recovery hint must be sent to the LLM
116
- assert.equal(
117
- cap.messages.length,
118
- 1,
119
- "exactly one sendMessage call expected for the recovery hint",
120
- );
121
- assert.equal(
122
- cap.messages[0].payload.customType,
123
- "gsd-plan-milestone-blocked-recovery",
124
- "recovery message must have customType gsd-plan-milestone-blocked-recovery",
125
- );
103
+ assert.equal(result, true, "queued + context is a valid planning-pending handoff");
104
+ assert.equal(cap.messages.length, 0, "must not inject a hidden recovery turn");
105
+ assert.equal(cap.notifies.length, 1, "must emit one success notification");
106
+ assert.deepEqual(cap.notifies[0], {
107
+ msg: "Milestone M001 context captured. Continuing the planning pipeline.",
108
+ level: "success",
109
+ });
126
110
  assert.equal(
127
- cap.messages[0].options.triggerTurn,
128
- true,
129
- "recovery message must set triggerTurn: true",
130
- );
131
- assert.match(
132
- cap.messages[0].payload.content,
133
- /gsd_plan_milestone/,
134
- "recovery message content must mention gsd_plan_milestone",
111
+ cap.notifies.some(n => /queued|gsd_plan_milestone/i.test(n.msg)),
112
+ false,
113
+ "user-visible copy must not mention queued state or internal plan tool retry",
135
114
  );
136
-
137
- // User must be notified via ctx.ui.notify
138
- assert.ok(
139
- cap.notifies.some((n) => n.level === "warning" && /queued/.test(n.msg)),
140
- "user must be notified with a warning about the queued state",
141
- );
142
-
143
- // logWarning must have recorded the Gate 1b event
144
- const logs = drainLogs();
145
- const gate1bLog = logs.find(
146
- (e) => e.component === "guided" && /Gate 1b/.test(e.message),
147
- );
148
- assert.ok(gate1bLog, "Gate 1b warning must be logged via logWarning");
149
115
  });
150
116
 
151
- test("discuss-incomplete: no CONTEXT.md + DB row queued → returns false silently (no recovery hint)", () => {
117
+ test("queued row without CONTEXT.md still waits silently for discussion output", () => {
152
118
  base = mkBase();
153
119
  openDatabase(":memory:");
154
-
155
- // DB row exists with status "queued", but NO CONTEXT.md on disk
156
120
  insertMilestone({ id: "M001", title: "Test Milestone", status: "queued" });
157
121
 
158
- // No CONTEXT.md written — discuss phase is incomplete
159
122
  cap = mkCapture();
160
123
  setPendingAutoStart(base, {
161
124
  basePath: base,
162
125
  milestoneId: "M001",
126
+ startAuto: false,
163
127
  ctx: mkCtx(cap),
164
128
  pi: mkPi(cap),
165
129
  });
166
130
 
167
- drainLogs(); // clear any noise before the call
131
+ drainLogs();
168
132
 
169
133
  const result = checkAutoStartAfterDiscuss();
170
134
 
171
- // Must return false silent block
172
- assert.equal(result, false, "checkAutoStartAfterDiscuss must return false when discuss is incomplete");
173
-
174
- // No recovery hint — Gate 1 blocks before Gate 1b is reached
175
- assert.equal(
176
- cap.messages.length,
177
- 0,
178
- "no sendMessage calls expected when CONTEXT.md is absent",
179
- );
180
- assert.equal(
181
- cap.notifies.length,
182
- 0,
183
- "no user notifications expected for discuss-incomplete case",
184
- );
135
+ assert.equal(result, false, "must keep waiting while discuss has not written context");
136
+ assert.equal(cap.messages.length, 0, "no hidden recovery turn expected");
137
+ assert.equal(cap.notifies.length, 0, "no user notifications expected");
185
138
 
186
- // No Gate 1b log entry
187
139
  const logs = drainLogs();
188
140
  const gate1bLog = logs.find(
189
141
  (e) => e.component === "guided" && /Gate 1b/.test(e.message),
@@ -3,10 +3,11 @@
3
3
 
4
4
  import test from "node:test";
5
5
  import assert from "node:assert/strict";
6
- import { mkdtempSync, rmSync } from "node:fs";
6
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
9
9
  import { VISION_ASK_VARIANTS } from "../vision-ask.ts";
10
+ import { buildDiscussMilestonePrompt } from "../auto-prompts.ts";
10
11
 
11
12
  test("guided milestone prompt renders compact interview and context guidance", async (t) => {
12
13
  const previousGsdHome = process.env.GSD_HOME;
@@ -47,3 +48,41 @@ test("guided milestone prompt renders compact interview and context guidance", a
47
48
  assert.match(prompt, /milestone_id: M001/);
48
49
  assert.doesNotMatch(prompt, /\{\{[a-zA-Z][a-zA-Z0-9_]*\}\}/);
49
50
  });
51
+
52
+ test("guided milestone prompt builder preloads milestone planning context", async () => {
53
+ const base = mkdtempSync(join(tmpdir(), "gsd-guided-milestone-context-"));
54
+ try {
55
+ const milestonesRoot = join(base, ".gsd", "milestones");
56
+ const priorDir = join(milestonesRoot, "M001");
57
+ const currentDir = join(milestonesRoot, "M002");
58
+ const futureDir = join(milestonesRoot, "M003");
59
+ mkdirSync(priorDir, { recursive: true });
60
+ mkdirSync(currentDir, { recursive: true });
61
+ mkdirSync(futureDir, { recursive: true });
62
+
63
+ writeFileSync(join(base, ".gsd", "DECISIONS.md"), "# Decisions\n\nDECISION-SIGNAL", "utf-8");
64
+ writeFileSync(join(priorDir, "M001-SUMMARY.md"), "# M001 Summary\n\nPRIOR-SUMMARY-SIGNAL", "utf-8");
65
+ writeFileSync(join(currentDir, "M002-ROADMAP.md"), "# M002 Roadmap\n\nROADMAP-SIGNAL", "utf-8");
66
+ writeFileSync(join(currentDir, "M002-CONTEXT.md"), "# M002 Context\n\nCONTEXT-SIGNAL", "utf-8");
67
+ writeFileSync(join(currentDir, "M002-RESEARCH.md"), "# M002 Research\n\nRESEARCH-SIGNAL", "utf-8");
68
+ writeFileSync(join(futureDir, "M003-SUMMARY.md"), "# M003 Summary\n\nFUTURE-SUMMARY-SIGNAL", "utf-8");
69
+
70
+ const prompt = await buildDiscussMilestonePrompt("M002", "Checkout Polish", base, "true");
71
+
72
+ assert.match(prompt, /## Inlined Context \(preloaded — do not re-read these files\)/);
73
+ assert.match(prompt, /### Milestone Roadmap/);
74
+ assert.match(prompt, /ROADMAP-SIGNAL/);
75
+ assert.match(prompt, /### Milestone Context/);
76
+ assert.match(prompt, /CONTEXT-SIGNAL/);
77
+ assert.match(prompt, /### Milestone Research/);
78
+ assert.match(prompt, /RESEARCH-SIGNAL/);
79
+ assert.match(prompt, /### Decisions Register/);
80
+ assert.match(prompt, /DECISION-SIGNAL/);
81
+ assert.match(prompt, /### M001 Prior Milestone Summary/);
82
+ assert.match(prompt, /PRIOR-SUMMARY-SIGNAL/);
83
+ assert.doesNotMatch(prompt, /FUTURE-SUMMARY-SIGNAL/);
84
+ assert.match(prompt, /### Output Template: Context/);
85
+ } finally {
86
+ rmSync(base, { recursive: true, force: true });
87
+ }
88
+ });
@@ -104,3 +104,89 @@ test("guided dispatch passes the explicit project root through model and compati
104
104
  rmSync(otherRoot, { recursive: true, force: true });
105
105
  }
106
106
  });
107
+
108
+ test("guided dispatch accepts workflow MCP tools absent from parent active tool surface", async () => {
109
+ const explicitRoot = mkdtempSync(join(tmpdir(), "gsd-guided-mcp-surface-"));
110
+ const workflowPath = join(explicitRoot, "GSD-WORKFLOW.md");
111
+ const originalWorkflowPath = process.env.GSD_WORKFLOW_PATH;
112
+ const originalMcpCommand = process.env.GSD_WORKFLOW_MCP_COMMAND;
113
+ const notifications: string[] = [];
114
+ let sent = false;
115
+
116
+ const ctx = {
117
+ model: { provider: "claude-code", baseUrl: "local://claude-code" },
118
+ modelRegistry: {
119
+ getProviderAuthMode: () => "externalCli",
120
+ },
121
+ ui: {
122
+ notify: (message: string) => {
123
+ notifications.push(message);
124
+ },
125
+ },
126
+ };
127
+
128
+ let activeTools = [
129
+ "ScheduleWakeup",
130
+ "ToolSearch",
131
+ "ask_user_questions",
132
+ "bash",
133
+ "read",
134
+ "write",
135
+ ];
136
+
137
+ const pi = {
138
+ getActiveTools: () => [...activeTools],
139
+ setActiveTools: (tools: string[]) => {
140
+ activeTools = [...tools];
141
+ },
142
+ sendMessage: () => {
143
+ sent = true;
144
+ },
145
+ };
146
+
147
+ try {
148
+ writeFileSync(workflowPath, "# Workflow\n", "utf-8");
149
+ process.env.GSD_WORKFLOW_PATH = workflowPath;
150
+ process.env.GSD_WORKFLOW_MCP_COMMAND = "node";
151
+
152
+ await _dispatchWorkflowForTest(
153
+ pi as any,
154
+ "Discuss the milestone.",
155
+ "gsd-discuss",
156
+ ctx as any,
157
+ "discuss-milestone",
158
+ {
159
+ basePath: explicitRoot,
160
+ deps: {
161
+ loadPreferences: () => ({ preferences: {} }) as any,
162
+ selectModel: (async () => ({
163
+ routing: null,
164
+ appliedModel: {
165
+ provider: "claude-code",
166
+ id: "claude-opus-4-8",
167
+ baseUrl: "local://claude-code",
168
+ },
169
+ })) as any,
170
+ },
171
+ },
172
+ );
173
+
174
+ assert.equal(sent, true);
175
+ assert.equal(
176
+ notifications.some((message) => message.includes("cannot run guided flow")),
177
+ false,
178
+ );
179
+ } finally {
180
+ if (originalWorkflowPath === undefined) {
181
+ delete process.env.GSD_WORKFLOW_PATH;
182
+ } else {
183
+ process.env.GSD_WORKFLOW_PATH = originalWorkflowPath;
184
+ }
185
+ if (originalMcpCommand === undefined) {
186
+ delete process.env.GSD_WORKFLOW_MCP_COMMAND;
187
+ } else {
188
+ process.env.GSD_WORKFLOW_MCP_COMMAND = originalMcpCommand;
189
+ }
190
+ rmSync(explicitRoot, { recursive: true, force: true });
191
+ }
192
+ });
@@ -178,7 +178,7 @@ test("checkAutoStartAfterDiscuss(basePath) selects the matching pending entry wh
178
178
  }
179
179
  });
180
180
 
181
- test("checkAutoStartAfterDiscuss can emit ready without scheduling auto-start", () => {
181
+ test("checkAutoStartAfterDiscuss can accept context handoff without scheduling auto-start", () => {
182
182
  const base = mkdtempSync(join(tmpdir(), "gsd-auto-start-headless-owned-"));
183
183
  let waitForIdleCalls = 0;
184
184
  const notifications: string[] = [];
@@ -209,9 +209,11 @@ test("checkAutoStartAfterDiscuss can emit ready without scheduling auto-start",
209
209
  });
210
210
 
211
211
  assert.equal(checkAutoStartAfterDiscuss(base), true);
212
- assert.deepEqual(notifications, ["Milestone M001 ready."]);
212
+ assert.deepEqual(notifications, [
213
+ "Milestone M001 context captured. Continuing the planning pipeline.",
214
+ ]);
213
215
  assert.equal(waitForIdleCalls, 0, "headless-owned auto start must not schedule guided-flow auto");
214
- assert.equal(getDiscussionMilestoneId(base), null, "ready handoff should still be cleared");
216
+ assert.equal(getDiscussionMilestoneId(base), null, "accepted handoff should still be cleared");
215
217
  } finally {
216
218
  clearPendingAutoStart();
217
219
  rmSync(base, { recursive: true, force: true });
@@ -135,7 +135,13 @@ describe("guided-flow STATE.md rebuild (#3475)", () => {
135
135
 
136
136
  assert.equal(accepted, true);
137
137
  assert.equal(notifications.some(n => n.level === "error" && n.message.includes("no DB row exists")), false);
138
- assert.ok(notifications.some(n => n.level === "success" && n.message.includes("Milestone M001 ready.")));
138
+ assert.ok(
139
+ notifications.some(
140
+ n =>
141
+ n.level === "success" &&
142
+ n.message.includes("Milestone M001 context captured. Continuing the planning pipeline."),
143
+ ),
144
+ );
139
145
  clearPendingAutoStart(base);
140
146
  });
141
147
 
@@ -157,13 +163,13 @@ describe("guided-flow STATE.md rebuild (#3475)", () => {
157
163
  };
158
164
  setPendingAutoStart(base, { basePath: base, milestoneId: "M001", ctx: ctx as any, pi: {} as any });
159
165
 
160
- for (let i = 0; i < 4; i += 1) {
166
+ for (let i = 0; i < 3; i += 1) {
161
167
  assert.equal(checkAutoStartAfterDiscuss(), false);
162
168
  }
163
169
 
164
170
  assert.equal(
165
- notifications.filter(n => n.level === "warning" && n.message.includes("recovering. Retrying gsd_plan_milestone")).length,
166
- 3,
171
+ notifications.filter(n => n.level === "warning").length,
172
+ 0,
167
173
  );
168
174
  assert.equal(
169
175
  notifications.filter(n => n.level === "error" && n.message.includes("DB row recovery failed")).length,
@@ -171,4 +177,34 @@ describe("guided-flow STATE.md rebuild (#3475)", () => {
171
177
  );
172
178
  clearPendingAutoStart(base);
173
179
  });
180
+
181
+ test("checkAutoStartAfterDiscuss does not double-notify on 4th+ call after recovery limit", () => {
182
+ base = createFixtureBase();
183
+ openDatabase(":memory:");
184
+ const db = _getAdapter();
185
+ assert.ok(db, "database should be open");
186
+ db.exec("DROP TABLE milestones");
187
+ db.exec("CREATE TABLE milestones (id TEXT PRIMARY KEY)");
188
+
189
+ writeFile(base, "milestones/M001/M001-CONTEXT.md", "# M001: Planned\n");
190
+ writeFile(base, "STATE.md", "# GSD State\n\n**Active Milestone:** M001: Planned\n");
191
+
192
+ const notifications: Array<{ message: string; level: string }> = [];
193
+ const ctx = {
194
+ ui: { notify: (message: string, level: string) => notifications.push({ message, level }) },
195
+ waitForIdle: () => new Promise<void>(() => {}),
196
+ };
197
+ setPendingAutoStart(base, { basePath: base, milestoneId: "M001", ctx: ctx as any, pi: {} as any });
198
+
199
+ for (let i = 0; i < 5; i += 1) {
200
+ assert.equal(checkAutoStartAfterDiscuss(), false);
201
+ }
202
+
203
+ assert.equal(
204
+ notifications.filter(n => n.level === "error" && n.message.includes("DB row recovery failed")).length,
205
+ 1,
206
+ "user must see exactly one error notification even after repeated calls past the recovery limit",
207
+ );
208
+ clearPendingAutoStart(base);
209
+ });
174
210
  });
@@ -8,14 +8,17 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
8
8
 
9
9
  test("guided milestone discussion callsites pass workingDirectory to loadPrompt", () => {
10
10
  const source = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
11
- const calls = [...source.matchAll(/loadPrompt\("guided-discuss-milestone",\s*\{([\s\S]*?)\}\)/g)];
12
11
 
13
- assert.equal(calls.length, 8, "all guided-flow guided-discuss-milestone callsites should be covered");
14
- for (const call of calls) {
15
- assert.match(
16
- call[1] ?? "",
17
- /\bworkingDirectory:\s*basePath\b/,
18
- "guided-discuss-milestone prompts need workingDirectory so template validation does not crash",
19
- );
20
- }
12
+ // All guided-discuss-milestone dispatches now go through buildDiscussMilestonePrompt,
13
+ // which centralises the loadPrompt call and always passes workingDirectory.
14
+ // Verify no callsite bypasses the builder by calling loadPrompt directly.
15
+ const directCalls = [...source.matchAll(/loadPrompt\("guided-discuss-milestone"/g)];
16
+ assert.equal(
17
+ directCalls.length,
18
+ 0,
19
+ 'guided-flow.ts must not call loadPrompt("guided-discuss-milestone") directly — use buildDiscussMilestonePrompt',
20
+ );
21
+
22
+ const calls = [...source.matchAll(/\bawait buildDiscussMilestonePrompt\(/g)];
23
+ assert.equal(calls.length, 9, "all guided-flow guided-discuss-milestone callsites should be covered");
21
24
  });
@@ -119,8 +119,8 @@ test("resolveExpectedArtifactPath returns correct path for all slice-level types
119
119
  // ─── run-uat artifact path contract (#2873) ──────────────────────────────
120
120
 
121
121
  test("resolveExpectedArtifactPath for run-uat returns ASSESSMENT path, not UAT (#2873)", (t) => {
122
- // The run-uat prompt instructs the agent to call gsd_summary_save with
123
- // artifact_type: "ASSESSMENT", which writes S##-ASSESSMENT.md. The artifact
122
+ // The run-uat prompt instructs the agent to call gsd_uat_result_save, which
123
+ // writes S##-ASSESSMENT.md through the workflow persistence path. The artifact
124
124
  // verification path must match — otherwise verification fails and auto-mode
125
125
  // retries the unit in an infinite loop.
126
126
  const base = makeTmpBase();
@@ -147,12 +147,12 @@ test("diagnoseExpectedArtifact for run-uat references ASSESSMENT (#2873)", (t) =
147
147
  });
148
148
 
149
149
  test("verifyExpectedArtifact passes for run-uat when ASSESSMENT file exists (#2873)", (t) => {
150
- // Regression test: run-uat writes S##-ASSESSMENT.md via gsd_summary_save,
150
+ // Regression test: run-uat writes S##-ASSESSMENT.md via gsd_uat_result_save,
151
151
  // but verification looked for S##-UAT.md, causing false stuck retries.
152
152
  const base = makeTmpBase();
153
153
  t.after(() => cleanup(base));
154
154
 
155
- // Write the ASSESSMENT file (what gsd_summary_save actually produces)
155
+ // Write the ASSESSMENT file (what gsd_uat_result_save actually produces)
156
156
  const assessPath = join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-ASSESSMENT.md");
157
157
  writeFileSync(assessPath, "---\nverdict: PASS\n---\n# UAT Assessment\n");
158
158
 
@@ -29,6 +29,7 @@ import { nativeMergeSquash } from "../../native-git-bridge.ts";
29
29
  import { drainLogs, setStderrLoggingEnabled } from "../../workflow-logger.ts";
30
30
  import {
31
31
  closeDatabase,
32
+ insertAssessment,
32
33
  insertMilestone,
33
34
  insertSlice,
34
35
  insertTask,
@@ -207,6 +208,13 @@ describe("auto-worktree-milestone-merge", { timeout: 300_000 }, () => {
207
208
  });
208
209
  }
209
210
  }
211
+ insertAssessment({
212
+ path: "milestones/M020/M020-VALIDATION.md",
213
+ milestoneId: "M020",
214
+ status: "pass",
215
+ scope: "milestone-validation",
216
+ fullContent: "verdict: pass",
217
+ });
210
218
 
211
219
  const roadmap = makeRoadmap("M020", "Backend foundation", [
212
220
  { id: "S01", title: "Core API" },
@@ -41,6 +41,7 @@ import {
41
41
  import {
42
42
  openDatabase,
43
43
  closeDatabase,
44
+ insertAssessment,
44
45
  insertMilestone,
45
46
  insertSlice,
46
47
  updateMilestoneStatus,
@@ -347,6 +348,13 @@ test("mergeCompletedMilestone — synthesizes roadmap from DB when projection is
347
348
  title: "Search Bar",
348
349
  status: "complete",
349
350
  });
351
+ insertAssessment({
352
+ path: "milestones/M010/M010-VALIDATION.md",
353
+ milestoneId: "M010",
354
+ status: "pass",
355
+ scope: "milestone-validation",
356
+ fullContent: "verdict: pass",
357
+ });
350
358
 
351
359
  createMilestoneBranch(repo, "M010", [
352
360
  { name: "app.js", content: "export const app = true;\n" },
@@ -671,6 +679,14 @@ function setupCanonicalDbWithWorktree(basePath: string, mid: string): void {
671
679
  const dbPath = join(basePath, ".gsd", "gsd.db");
672
680
  openDatabase(dbPath);
673
681
  insertMilestone({ id: mid, title: `Milestone ${mid}`, status: "complete" });
682
+ insertSlice({ id: "S01", milestoneId: mid, title: "Done Slice", status: "complete" });
683
+ insertAssessment({
684
+ path: `milestones/${mid}/${mid}-VALIDATION.md`,
685
+ milestoneId: mid,
686
+ status: "pass",
687
+ scope: "milestone-validation",
688
+ fullContent: "verdict: pass",
689
+ });
674
690
  updateMilestoneStatus(mid, "complete", new Date().toISOString());
675
691
  closeDatabase();
676
692
  }