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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/dist/cli-web-branch.d.ts +2 -0
  2. package/dist/cli-web-branch.js +9 -2
  3. package/dist/help-text.js +5 -0
  4. package/dist/resources/.managed-resources-content-hash +1 -1
  5. package/dist/resources/extensions/ask-user-questions.js +78 -23
  6. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +84 -228
  7. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
  8. package/dist/resources/extensions/github-sync/templates.js +3 -3
  9. package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
  10. package/dist/resources/extensions/gsd/auto/loop.js +74 -56
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +109 -11
  12. package/dist/resources/extensions/gsd/auto/phases.js +28 -3
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
  14. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  15. package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
  17. package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
  19. package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
  20. package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
  21. package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
  22. package/dist/resources/extensions/gsd/auto-start.js +12 -23
  23. package/dist/resources/extensions/gsd/auto-timers.js +16 -2
  24. package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
  25. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
  26. package/dist/resources/extensions/gsd/auto-verification.js +7 -7
  27. package/dist/resources/extensions/gsd/auto-worktree.js +21 -19
  28. package/dist/resources/extensions/gsd/auto.js +11 -7
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
  30. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -138
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
  34. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
  35. package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
  36. package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
  37. package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
  38. package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
  39. package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
  40. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  41. package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
  42. package/dist/resources/extensions/gsd/db-workspace.js +103 -0
  43. package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
  44. package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
  45. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  46. package/dist/resources/extensions/gsd/doctor.js +16 -9
  47. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  48. package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
  49. package/dist/resources/extensions/gsd/gsd-db.js +12 -0
  50. package/dist/resources/extensions/gsd/guided-flow.js +34 -468
  51. package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
  52. package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
  53. package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
  54. package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
  55. package/dist/resources/extensions/gsd/md-importer.js +4 -3
  56. package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
  57. package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
  58. package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
  59. package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
  60. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
  61. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
  62. package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
  63. package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
  64. package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
  65. package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
  66. package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
  67. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
  68. package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
  69. package/dist/resources/extensions/gsd/preferences.js +147 -29
  70. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  71. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  73. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  75. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  76. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  77. package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
  78. package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
  79. package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
  80. package/dist/resources/extensions/gsd/question-transport.js +86 -0
  81. package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
  82. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
  83. package/dist/resources/extensions/gsd/state.js +13 -5
  84. package/dist/resources/extensions/gsd/templates/plan.md +7 -0
  85. package/dist/resources/extensions/gsd/templates/project.md +1 -0
  86. package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
  87. package/dist/resources/extensions/gsd/templates/uat.md +5 -1
  88. package/dist/resources/extensions/gsd/tool-contract.js +52 -8
  89. package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
  90. package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
  91. package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
  92. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
  93. package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
  94. package/dist/resources/extensions/gsd/uat-policy.js +16 -10
  95. package/dist/resources/extensions/gsd/uat-run.js +9 -14
  96. package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
  97. package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
  98. package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
  99. package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
  100. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  101. package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
  102. package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
  103. package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
  104. package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
  105. package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
  106. package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
  107. package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
  108. package/dist/resources/extensions/shared/interview-ui.js +2 -2
  109. package/dist/resources/shared/claude-runtime-floor.js +182 -0
  110. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  111. package/dist/update-cmd.js +20 -0
  112. package/dist/web/standalone/.next/BUILD_ID +1 -1
  113. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  114. package/dist/web/standalone/.next/build-manifest.json +3 -3
  115. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  116. package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
  117. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/index.html +1 -1
  134. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  141. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  142. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  145. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  146. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  147. package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
  148. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
  149. package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
  150. package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
  151. package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
  152. package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
  153. package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
  155. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  156. package/dist/web-mode.d.ts +2 -0
  157. package/dist/web-mode.js +20 -8
  158. package/package.json +2 -1
  159. package/packages/cloud-mcp-gateway/package.json +2 -2
  160. package/packages/contracts/package.json +1 -1
  161. package/packages/daemon/package.json +4 -4
  162. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
  163. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  164. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
  165. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  166. package/packages/gsd-agent-core/package.json +5 -5
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  171. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
  172. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  173. package/packages/gsd-agent-modes/package.json +7 -7
  174. package/packages/mcp-server/dist/server.d.ts +10 -0
  175. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  176. package/packages/mcp-server/dist/server.js +8 -0
  177. package/packages/mcp-server/dist/server.js.map +1 -1
  178. package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
  179. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  180. package/packages/mcp-server/dist/workflow-tools.js +2 -1
  181. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  182. package/packages/mcp-server/package.json +3 -3
  183. package/packages/native/package.json +1 -1
  184. package/packages/pi-agent-core/package.json +1 -1
  185. package/packages/pi-ai/dist/models.generated.d.ts +8 -93
  186. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  187. package/packages/pi-ai/dist/models.generated.js +35 -120
  188. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  189. package/packages/pi-ai/package.json +1 -1
  190. package/packages/pi-coding-agent/package.json +7 -7
  191. package/packages/pi-tui/dist/components/input.js +1 -1
  192. package/packages/pi-tui/dist/components/input.js.map +1 -1
  193. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  194. package/packages/pi-tui/dist/keys.js +39 -30
  195. package/packages/pi-tui/dist/keys.js.map +1 -1
  196. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  197. package/packages/pi-tui/dist/stdin-buffer.js +22 -0
  198. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  199. package/packages/pi-tui/package.json +2 -2
  200. package/packages/rpc-client/package.json +2 -2
  201. package/pkg/package.json +1 -1
  202. package/src/resources/extensions/ask-user-questions.ts +87 -24
  203. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +108 -281
  204. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +240 -0
  205. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
  206. package/src/resources/extensions/github-sync/templates.ts +3 -3
  207. package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
  208. package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
  209. package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
  210. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  211. package/src/resources/extensions/gsd/auto/loop.ts +83 -61
  212. package/src/resources/extensions/gsd/auto/orchestrator.ts +125 -12
  213. package/src/resources/extensions/gsd/auto/phases.ts +35 -3
  214. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
  215. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  216. package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
  217. package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
  218. package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
  219. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
  220. package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
  221. package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
  222. package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
  223. package/src/resources/extensions/gsd/auto-start.ts +17 -20
  224. package/src/resources/extensions/gsd/auto-timers.ts +16 -2
  225. package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
  226. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
  227. package/src/resources/extensions/gsd/auto-verification.ts +7 -8
  228. package/src/resources/extensions/gsd/auto-worktree.ts +33 -26
  229. package/src/resources/extensions/gsd/auto.ts +15 -8
  230. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
  231. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
  232. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  233. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +116 -151
  234. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
  235. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
  236. package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
  237. package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
  238. package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
  239. package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
  240. package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
  241. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  242. package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
  243. package/src/resources/extensions/gsd/db-workspace.ts +170 -0
  244. package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
  245. package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
  246. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  247. package/src/resources/extensions/gsd/doctor.ts +15 -5
  248. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  249. package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
  250. package/src/resources/extensions/gsd/gsd-db.ts +12 -0
  251. package/src/resources/extensions/gsd/guided-flow.ts +47 -558
  252. package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
  253. package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
  254. package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
  255. package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
  256. package/src/resources/extensions/gsd/md-importer.ts +3 -3
  257. package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
  258. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  259. package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
  260. package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
  261. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
  262. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
  263. package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
  264. package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
  265. package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
  266. package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
  267. package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
  268. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
  269. package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
  270. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  271. package/src/resources/extensions/gsd/preferences.ts +173 -28
  272. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  273. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
  274. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  275. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  276. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  277. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  278. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  279. package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
  280. package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
  281. package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
  282. package/src/resources/extensions/gsd/question-transport.ts +138 -0
  283. package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
  284. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
  285. package/src/resources/extensions/gsd/state.ts +15 -5
  286. package/src/resources/extensions/gsd/templates/plan.md +7 -0
  287. package/src/resources/extensions/gsd/templates/project.md +1 -0
  288. package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
  289. package/src/resources/extensions/gsd/templates/uat.md +5 -1
  290. package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
  291. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
  292. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
  293. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
  294. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
  295. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
  296. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
  297. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
  298. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  299. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
  300. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
  301. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
  302. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
  303. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
  304. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
  305. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
  306. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
  307. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
  308. package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
  309. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
  310. package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
  311. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
  312. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
  313. package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
  314. package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
  315. package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
  316. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
  317. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  318. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
  319. package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
  320. package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
  321. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
  322. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
  323. package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
  324. package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
  325. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
  326. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
  327. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
  328. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
  329. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
  330. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
  331. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
  332. package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
  333. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
  334. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
  335. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
  336. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
  337. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
  338. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
  339. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
  340. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
  341. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
  342. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
  343. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
  344. package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
  345. package/src/resources/extensions/gsd/tool-contract.ts +86 -8
  346. package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
  347. package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
  348. package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
  349. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
  350. package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
  351. package/src/resources/extensions/gsd/uat-policy.ts +19 -10
  352. package/src/resources/extensions/gsd/uat-run.ts +10 -14
  353. package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
  354. package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
  355. package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
  356. package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
  357. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  358. package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
  359. package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
  360. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  361. package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
  362. package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
  363. package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
  364. package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
  365. package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
  366. package/src/resources/extensions/shared/interview-ui.ts +15 -2
  367. package/src/resources/shared/claude-runtime-floor.ts +248 -0
  368. package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
  369. package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
  370. package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
  371. package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
  372. package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
  373. package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
  374. /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_buildManifest.js +0 -0
  375. /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_ssgManifest.js +0 -0
@@ -25,21 +25,25 @@ import { getSessionLockStatus } from "../session-lock.js";
25
25
  import { resolveUokFlags } from "../uok/flags.js";
26
26
  import { emitJournalEvent as _emitJournalEvent } from "../journal.js";
27
27
  import { loadEffectiveGSDPreferences, getIsolationMode } from "../preferences.js";
28
- import { detectWorktreeName, resolveProjectRoot } from "../worktree.js";
28
+ import { detectWorktreeName, getMainBranch, resolveProjectRoot, resolveWorktreeProjectRoot, } from "../worktree.js";
29
+ import { getPriorSliceCompletionBlocker } from "../dispatch-guard.js";
29
30
  import { GitServiceImpl } from "../git-service.js";
30
31
  import { WorktreeStateProjection } from "../worktree-state-projection.js";
31
32
  import { WorktreeLifecycle } from "../worktree-lifecycle.js";
33
+ import { createMilestoneMergeTransaction } from "../milestone-merge-transaction.js";
32
34
  import { createWorkspace, scopeMilestone } from "../workspace.js";
33
35
  import { supportsStructuredQuestions } from "../workflow-mcp.js";
34
- import { getToolBaselineSnapshot } from "../auto-model-selection.js";
36
+ import { getRegisteredToolSnapshot, getToolBaselineSnapshot } from "../auto-model-selection.js";
35
37
  import { deriveState } from "../state.js";
36
38
  import { parseUnitId } from "../unit-id.js";
37
39
  import { isClosedStatus } from "../status-guards.js";
38
- import { isDbAvailable, getSlice, getTask, refreshOpenDatabaseFromDisk, } from "../gsd-db.js";
40
+ import { isDbAvailable, getSlice, getTask, } from "../gsd-db.js";
41
+ import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
39
42
  import { getErrorMessage } from "../error-utils.js";
40
43
  import { logWarning } from "../workflow-logger.js";
41
44
  import { existsSync, readFileSync } from "node:fs";
42
45
  import { join } from "node:path";
46
+ import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
43
47
  function now() {
44
48
  return Date.now();
45
49
  }
@@ -52,16 +56,24 @@ function now() {
52
56
  * preserved across the eventual cutover (issue #5791).
53
57
  */
54
58
  export const STUCK_WINDOW_SIZE = 6;
55
- function noRemainingUnitsReason(stateSnapshot) {
59
+ function noRemainingUnitsOutcome(stateSnapshot) {
56
60
  if (stateSnapshot.phase === "complete") {
57
- return "all milestones complete";
61
+ return {
62
+ code: "all-complete",
63
+ displayReason: "All milestones complete",
64
+ allMilestonesComplete: true,
65
+ };
58
66
  }
59
- return "no remaining units";
67
+ return {
68
+ code: "no-remaining-units",
69
+ displayReason: "No remaining units",
70
+ allMilestonesComplete: false,
71
+ };
60
72
  }
61
73
  function getAlreadyClosedDispatchReason(unitType, unitId) {
62
74
  if (!isDbAvailable())
63
75
  return null;
64
- refreshOpenDatabaseFromDisk();
76
+ refreshWorkflowDatabaseFromDisk();
65
77
  const { milestone, slice, task } = parseUnitId(unitId);
66
78
  if (unitType === "execute-task" && milestone && slice && task) {
67
79
  const row = getTask(milestone, slice, task);
@@ -127,6 +139,7 @@ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, sess
127
139
  // active set may be narrowed by the prior unit before selectAndApplyModel
128
140
  // restores it, causing false transport-preflight failures (#477 follow-up).
129
141
  const activeTools = getToolBaselineSnapshot(pi);
142
+ const registeredTools = getRegisteredToolSnapshot(pi);
130
143
  // Mirrors runDispatch: deep-planning keeps approval gates in plain chat
131
144
  // because structured questions can be cancelled outside the chat turn on
132
145
  // some transports.
@@ -168,6 +181,7 @@ export async function decideOrchestratorDispatch(ctx, pi, dispatchBasePath, sess
168
181
  sessionProvider,
169
182
  modelRegistry,
170
183
  activeTools,
184
+ registeredTools,
171
185
  sessionAuthMode: authMode,
172
186
  sessionBaseUrl: ctx.model?.baseUrl,
173
187
  });
@@ -412,6 +426,47 @@ export class AutoOrchestrator {
412
426
  decideNextUnit(input) {
413
427
  return decideOrchestratorDispatch(this.ctx, this.pi, this.dispatchBasePath, this.s, input);
414
428
  }
429
+ evaluateNoRemainingUnitsSettlement(stateSnapshot) {
430
+ const settlement = evaluateAllCompleteSettlement({
431
+ milestoneId: this.s.currentMilestoneId ?? stateSnapshot.activeMilestone?.id,
432
+ statePhase: stateSnapshot.phase,
433
+ basePath: this.s.basePath || this.getLiveDispatchBasePath(),
434
+ originalBasePath: this.s.originalBasePath || this.runtimeBasePath,
435
+ milestoneMerged: this.s.milestoneMergedInPhases,
436
+ });
437
+ this.s.milestoneSettlement = settlement;
438
+ if (settlement.ok)
439
+ return null;
440
+ return {
441
+ kind: "blocked",
442
+ reason: settlement.message,
443
+ action: settlement.action,
444
+ stateSnapshot,
445
+ terminalOutcome: {
446
+ code: "settlement-blocked",
447
+ displayReason: settlement.message,
448
+ nextAction: settlement.nextAction,
449
+ milestoneId: settlement.milestoneId,
450
+ allMilestonesComplete: false,
451
+ },
452
+ };
453
+ }
454
+ clearPendingDispatch() {
455
+ this.s.pendingOrchestrationDispatch = null;
456
+ }
457
+ findPriorSliceCompletionBlocker(unitType, unitId) {
458
+ const guardBasePath = resolveWorktreeProjectRoot(this.getLiveDispatchBasePath(), this.s.originalBasePath);
459
+ let mainBranch = "main";
460
+ try {
461
+ mainBranch = getMainBranch(guardBasePath);
462
+ }
463
+ catch (err) {
464
+ // Preserve legacy dispatch behavior: fall back to main when branch
465
+ // discovery fails, then let the guard make the progression decision.
466
+ logWarning("engine", `branch discovery failed, falling back to main: ${getErrorMessage(err)}`, { file: "orchestrator.ts" });
467
+ }
468
+ return getPriorSliceCompletionBlocker(guardBasePath, mainBranch, unitType, unitId);
469
+ }
415
470
  // ── ToolContractAdapter (folded) ─────────────────────────────────────────
416
471
  compileUnitToolContract(unitType) {
417
472
  const result = compileUnitToolContract(unitType);
@@ -431,7 +486,7 @@ export class AutoOrchestrator {
431
486
  return new GitServiceImpl(basePath, gitConfig);
432
487
  },
433
488
  worktreeProjection: new WorktreeStateProjection(),
434
- mergeMilestoneToMain,
489
+ mergeMilestoneToMain: createMilestoneMergeTransaction(mergeMilestoneToMain),
435
490
  });
436
491
  }
437
492
  rebuildScope(rawPath, milestoneId) {
@@ -668,10 +723,23 @@ export class AutoOrchestrator {
668
723
  }
669
724
  const decision = await this.decideNextUnit({ stateSnapshot: reconciliation.stateSnapshot });
670
725
  if (!decision) {
726
+ const settlementBlock = this.evaluateNoRemainingUnitsSettlement(reconciliation.stateSnapshot);
727
+ if (settlementBlock) {
728
+ this.status.phase = "paused";
729
+ this.status.activeUnit = undefined;
730
+ this.lastAdvanceKey = null;
731
+ this.dispatchKeyWindow = [];
732
+ this.bumpTransition();
733
+ this.journalTransition({ name: "advance-blocked", reason: settlementBlock.reason });
734
+ this.postAdvanceRecord(settlementBlock);
735
+ return settlementBlock;
736
+ }
737
+ const terminalOutcome = noRemainingUnitsOutcome(reconciliation.stateSnapshot);
671
738
  const stopped = {
672
739
  kind: "stopped",
673
- reason: noRemainingUnitsReason(reconciliation.stateSnapshot),
740
+ reason: terminalOutcome.displayReason,
674
741
  stateSnapshot: reconciliation.stateSnapshot,
742
+ terminalOutcome,
675
743
  };
676
744
  this.status.phase = "stopped";
677
745
  this.status.activeUnit = undefined;
@@ -706,6 +774,24 @@ export class AutoOrchestrator {
706
774
  this.postAdvanceRecord(blocked);
707
775
  return blocked;
708
776
  }
777
+ const priorSliceBlocker = this.findPriorSliceCompletionBlocker(decision.unitType, decision.unitId);
778
+ if (priorSliceBlocker) {
779
+ this.clearPendingDispatch();
780
+ const blocked = {
781
+ kind: "blocked",
782
+ reason: priorSliceBlocker,
783
+ action: "stop",
784
+ stateSnapshot: reconciliation.stateSnapshot,
785
+ };
786
+ this.journalTransition({
787
+ name: "advance-blocked",
788
+ reason: blocked.reason,
789
+ unitType: decision.unitType,
790
+ unitId: decision.unitId,
791
+ });
792
+ this.postAdvanceRecord(blocked);
793
+ return blocked;
794
+ }
709
795
  const nextKey = `${decision.unitType}:${decision.unitId}`;
710
796
  // Record every dispatch decision in the ring buffer before pre-flight
711
797
  // checks so the stuck-loop detector observes the full decision history
@@ -721,8 +807,10 @@ export class AutoOrchestrator {
721
807
  // actually completed on disk with a stale DB. Verify + recover before
722
808
  // hard-stopping (legacy graduated stuck-recovery parity).
723
809
  if (this.tryStuckArtifactRecovery(decision.unitType, decision.unitId)) {
810
+ this.clearPendingDispatch();
724
811
  return this.stuckRecovered(decision, reconciliation.stateSnapshot);
725
812
  }
813
+ this.clearPendingDispatch();
726
814
  const blocked = {
727
815
  kind: "blocked",
728
816
  reason: `state did not advance after finalized ${decision.unitType} ${decision.unitId}`,
@@ -745,6 +833,7 @@ export class AutoOrchestrator {
745
833
  // checks coexist: idempotency for the common immediate-repeat case,
746
834
  // stuck-loop for the saturated-window case.
747
835
  if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
836
+ this.clearPendingDispatch();
748
837
  const blocked = { kind: "blocked", reason: "idempotent advance: unit already active", action: "pause" };
749
838
  this.journalTransition({
750
839
  name: "advance-blocked",
@@ -764,8 +853,10 @@ export class AutoOrchestrator {
764
853
  // complete on disk (stale DB) and recover if so — legacy graduated
765
854
  // stuck-recovery parity. Otherwise hard-stop with a diagnosable reason.
766
855
  if (this.tryStuckArtifactRecovery(decision.unitType, decision.unitId)) {
856
+ this.clearPendingDispatch();
767
857
  return this.stuckRecovered(decision, reconciliation.stateSnapshot);
768
858
  }
859
+ this.clearPendingDispatch();
769
860
  const blocked = {
770
861
  kind: "blocked",
771
862
  reason: `stuck-loop: ${nextKey} picked ${matchingCount} times`,
@@ -782,6 +873,7 @@ export class AutoOrchestrator {
782
873
  }
783
874
  const contract = this.compileUnitToolContract(decision.unitType);
784
875
  if (!contract.ok) {
876
+ this.clearPendingDispatch();
785
877
  const blocked = {
786
878
  kind: "blocked",
787
879
  reason: contract.reason,
@@ -799,6 +891,7 @@ export class AutoOrchestrator {
799
891
  }
800
892
  const worktree = await this.prepareWorktreeForUnit(decision.unitType, decision.unitId);
801
893
  if (!worktree.ok) {
894
+ this.clearPendingDispatch();
802
895
  const blocked = {
803
896
  kind: "blocked",
804
897
  reason: worktree.reason,
@@ -885,7 +978,8 @@ export class AutoOrchestrator {
885
978
  async resume() {
886
979
  this.lastAdvanceKey = null;
887
980
  this.lastFinalizedUnitKey = null;
888
- this.dispatchKeyWindow = [];
981
+ // Preserve dispatchKeyWindow across resume so stuck-loop detection
982
+ // accumulates across pause/resume cycles rather than resetting each time.
889
983
  this.lastStuckRecoveryKey = null;
890
984
  this.status.phase = "running";
891
985
  this.bumpTransition();
@@ -902,7 +996,11 @@ export class AutoOrchestrator {
902
996
  this.status.activeUnit = undefined;
903
997
  this.lastAdvanceKey = null;
904
998
  this.lastFinalizedUnitKey = null;
905
- this.dispatchKeyWindow = [];
999
+ // Preserve dispatchKeyWindow on pause so stuck-loop detection accumulates
1000
+ // across pause/resume cycles. Only clear on a hard stop.
1001
+ if (reason !== "pause") {
1002
+ this.dispatchKeyWindow = [];
1003
+ }
906
1004
  this.lastStuckRecoveryKey = null;
907
1005
  this.bumpTransition();
908
1006
  this.journalTransition({ name: "stop", reason });
@@ -33,7 +33,8 @@ import { writeUnitRuntimeRecord } from "../unit-runtime.js";
33
33
  import { withTimeout, FINALIZE_PRE_TIMEOUT_MS, FINALIZE_POST_TIMEOUT_MS } from "./finalize-timeout.js";
34
34
  import { getEligibleSlices } from "../slice-parallel-eligibility.js";
35
35
  import { isSliceParallelActive, startSliceParallel } from "../slice-parallel-orchestrator.js";
36
- import { isDbAvailable, getMilestoneSlices, getSlice, getTask, refreshOpenDatabaseFromDisk } from "../gsd-db.js";
36
+ import { isDbAvailable, getMilestoneSlices, getSlice, getTask } from "../gsd-db.js";
37
+ import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
37
38
  import { isClosedStatus } from "../status-guards.js";
38
39
  import { setRuntimeKv } from "../db/runtime-kv.js";
39
40
  import { getLatestForUnit } from "../db/unit-dispatches.js";
@@ -49,7 +50,7 @@ import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
49
50
  import { getContextPauseAction } from "../auto-budget.js";
50
51
  import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, supportsStructuredQuestions, } from "../workflow-mcp.js";
51
52
  import { prepareWorkflowMcpForProject } from "../workflow-mcp-auto-prep.js";
52
- import { getToolBaselineSnapshot, applyThinkingLevelForModel, floorThinkingLevelForUnit } from "../auto-model-selection.js";
53
+ import { applyThinkingLevelForModel, floorThinkingLevelForUnit, getRegisteredToolSnapshot, getToolBaselineSnapshot, } from "../auto-model-selection.js";
53
54
  import { resolveManifest } from "../unit-context-manifest.js";
54
55
  import { createWorktreeSafetyModule } from "../worktree-safety.js";
55
56
  import { isSuspiciousGhostCompletion } from "../auto-unit-closeout.js";
@@ -156,7 +157,7 @@ function rememberRetryDispatch(s, unit, iterData) {
156
157
  function getAlreadyClosedDispatchReason(unitType, unitId) {
157
158
  if (!isDbAvailable())
158
159
  return null;
159
- refreshOpenDatabaseFromDisk();
160
+ refreshWorkflowDatabaseFromDisk();
160
161
  const { milestone, slice, task } = parseUnitId(unitId);
161
162
  if (unitType === "execute-task" && milestone && slice && task) {
162
163
  const row = getTask(milestone, slice, task);
@@ -447,6 +448,14 @@ export async function _runMilestoneMergeWithStashRestore(ic, milestoneId, option
447
448
  const exitResult = deps.lifecycle.exitMilestone(milestoneId, { merge: true }, ctx.ui);
448
449
  if (exitResult.ok) {
449
450
  s.milestoneMergedInPhases = true;
451
+ try {
452
+ const projectRoot = s.originalBasePath || s.canonicalProjectRoot || s.basePath;
453
+ const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.js");
454
+ await rebuildMarkdownProjectionsFromDb(projectRoot);
455
+ }
456
+ catch (err) {
457
+ logWarning("engine", `markdown projection rebuild after milestone merge failed: ${err instanceof Error ? err.message : String(err)}`);
458
+ }
450
459
  }
451
460
  else {
452
461
  mergeError = exitResult.cause ?? new Error(`exit ${exitResult.reason}`);
@@ -929,6 +938,19 @@ export async function runPreDispatch(ic, loopState) {
929
938
  catch (e) {
930
939
  logWarning("engine", "STATE.md rebuild failed after milestone transition", { error: String(e) });
931
940
  }
941
+ // Re-project ROADMAP/PLAN markdown from the authoritative DB. Worktree DB
942
+ // reconciliation during merge can leave main-branch markdown stale relative
943
+ // to gsd.db (the 3M/3S/10T vs 3M/5S/16T drift class at /gsd startup).
944
+ try {
945
+ const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.js");
946
+ await rebuildMarkdownProjectionsFromDb(s.canonicalProjectRoot);
947
+ if (s.basePath !== s.canonicalProjectRoot) {
948
+ await rebuildMarkdownProjectionsFromDb(s.basePath);
949
+ }
950
+ }
951
+ catch (e) {
952
+ logWarning("engine", "markdown projection rebuild failed after milestone transition", { error: String(e) });
953
+ }
932
954
  }
933
955
  if (mid) {
934
956
  s.currentMilestoneId = mid;
@@ -1082,6 +1104,7 @@ export async function runDispatch(ic, preData, loopState) {
1082
1104
  // Checking a stale-narrowed set causes false transport-preflight warnings
1083
1105
  // that repeat on every /gsd auto resume (#477 follow-up).
1084
1106
  const activeTools = getToolBaselineSnapshot(pi);
1107
+ const registeredTools = getRegisteredToolSnapshot(pi);
1085
1108
  // Deep planning intentionally keeps human checkpoints in plain chat. In
1086
1109
  // Claude Code/local MCP transports, structured question requests can be
1087
1110
  // cancelled outside the normal chat flow, which made approval gates easy to
@@ -1105,6 +1128,7 @@ export async function runDispatch(ic, preData, loopState) {
1105
1128
  sessionProvider: ctx.model?.provider,
1106
1129
  modelRegistry: ctx.modelRegistry,
1107
1130
  activeTools,
1131
+ registeredTools,
1108
1132
  sessionBaseUrl: ctx.model?.baseUrl,
1109
1133
  sessionAuthMode: authMode,
1110
1134
  });
@@ -1131,6 +1155,7 @@ export async function runDispatch(ic, preData, loopState) {
1131
1155
  sessionProvider: ctx.model?.provider,
1132
1156
  modelRegistry: ctx.modelRegistry,
1133
1157
  activeTools,
1158
+ registeredTools,
1134
1159
  sessionBaseUrl: ctx.model?.baseUrl,
1135
1160
  sessionAuthMode: authMode,
1136
1161
  });
@@ -95,7 +95,8 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
95
95
  unitId,
96
96
  error: msg,
97
97
  });
98
- return { status: "cancelled", errorContext: { message: `Session creation failed: ${msg}`, category: "session-failed", isTransient: true } };
98
+ const isStructural = sessionErr instanceof TypeError || /is not a function/i.test(msg);
99
+ return { status: "cancelled", errorContext: { message: `Session creation failed: ${msg}`, category: "session-failed", isTransient: !isStructural } };
99
100
  }
100
101
  if (sessionTimeoutHandle)
101
102
  clearTimeout(sessionTimeoutHandle);
@@ -143,6 +143,8 @@ export class AutoSession {
143
143
  /** Set to true after phases.ts successfully calls mergeAndExit, so that
144
144
  * stopAuto does not attempt the same merge a second time (#2645). */
145
145
  milestoneMergedInPhases = false;
146
+ /** Last milestone settlement result observed by Auto Orchestration. */
147
+ milestoneSettlement = null;
146
148
  // #4765 — slice-cadence collapse: main-branch SHAs at the moment each
147
149
  // milestone's first slice merge began. Used by resquashMilestoneOnMain at
148
150
  // milestone completion to collapse N slice commits into one. Cleared when
@@ -311,6 +313,7 @@ export class AutoSession {
311
313
  this.strandedRecoveryIsolationMode = null;
312
314
  this.rootWriteBaseline = null;
313
315
  this.milestoneMergedInPhases = false;
316
+ this.milestoneSettlement = null;
314
317
  this.milestoneStartShas = new Map();
315
318
  this.checkpointSha = null;
316
319
  // Signal handler
@@ -16,6 +16,7 @@ import { parseUnitId } from "./unit-id.js";
16
16
  import { logWarning } from "./workflow-logger.js";
17
17
  import { formattedShortcutPair } from "./shortcut-defs.js";
18
18
  import { readUnitRuntimeRecord } from "./unit-runtime.js";
19
+ import { describeMilestoneReadinessPhase } from "./milestone-readiness.js";
19
20
  const ACTIVE_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
20
21
  // ─── UAT Slice Extraction ─────────────────────────────────────────────────────
21
22
  /**
@@ -84,6 +85,18 @@ export function unitPhaseLabel(unitType) {
84
85
  default: return unitType.toUpperCase();
85
86
  }
86
87
  }
88
+ export function formatToolSurfaceSnapshot(snapshot) {
89
+ if (!snapshot)
90
+ return null;
91
+ const counts = [
92
+ `model ${snapshot.modelFacingToolNames.length}`,
93
+ `registered ${snapshot.registeredToolNames.length}`,
94
+ `scoped ${snapshot.scopedToolNames.length}`,
95
+ `presented ${snapshot.presentedToolNames.length}`,
96
+ ];
97
+ const label = snapshot.unitType ?? snapshot.phase ?? snapshot.source;
98
+ return `${label}: ${counts.join(" / ")}`;
99
+ }
87
100
  function peekNext(unitType, state) {
88
101
  // Show active hook info in progress display
89
102
  const activeHookState = getActiveHook();
@@ -118,11 +131,10 @@ export function describeNextUnit(state) {
118
131
  const sTitle = state.activeSlice?.title;
119
132
  const tid = state.activeTask?.id;
120
133
  const tTitle = state.activeTask?.title;
134
+ const readinessDescription = describeMilestoneReadinessPhase(state.phase);
135
+ if (readinessDescription)
136
+ return readinessDescription;
121
137
  switch (state.phase) {
122
- case "needs-discussion":
123
- return { label: "Discuss milestone draft", description: "Milestone has a draft context — needs discussion before planning." };
124
- case "pre-planning":
125
- return { label: "Research & plan milestone", description: "Scout the landscape and create the roadmap." };
126
138
  case "planning":
127
139
  return { label: `Plan ${sid}: ${sTitle}`, description: "Research and decompose into tasks." };
128
140
  case "executing":
@@ -37,7 +37,7 @@ import { probeGitConflictState } from "./git-conflict-state.js";
37
37
  import { runTurnGitAction } from "./git-service.js";
38
38
  import { parseUnitId } from "./unit-id.js";
39
39
  import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
40
- import { checkCloseoutConsistencyGate, formatCloseoutConsistencyBlock, } from "./closeout-consistency-gate.js";
40
+ import { formatCloseoutProofBlock, proveMilestoneCloseout, } from "./milestone-closeout-proof.js";
41
41
  function resolveExistingExpectedArtifact(unitType, unitId, basePath) {
42
42
  const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
43
43
  return artifactPath && existsSync(artifactPath) ? artifactPath : null;
@@ -518,7 +518,7 @@ export const DISPATCH_RULES = [
518
518
  },
519
519
  {
520
520
  name: "run-uat (post-completion)",
521
- match: async ({ state, mid, basePath, prefs, sessionProvider, sessionAuthMode, activeTools, sessionBaseUrl }) => {
521
+ match: async ({ state, mid, basePath, prefs, sessionProvider, sessionAuthMode, activeTools, registeredTools, sessionBaseUrl, }) => {
522
522
  const needsRunUat = await checkNeedsRunUat(basePath, mid, state, prefs);
523
523
  if (!needsRunUat)
524
524
  return null;
@@ -533,6 +533,7 @@ export const DISPATCH_RULES = [
533
533
  const browserToolError = getUatBrowserToolSupportError({
534
534
  uatType,
535
535
  activeTools,
536
+ registeredTools,
536
537
  milestoneId: mid,
537
538
  sliceId,
538
539
  });
@@ -1425,11 +1426,11 @@ export const DISPATCH_RULES = [
1425
1426
  };
1426
1427
  }
1427
1428
  if (milestone) {
1428
- const closeoutGate = checkCloseoutConsistencyGate(mid, { refreshFromDisk: true });
1429
- if (!closeoutGate.ok) {
1429
+ const closeoutProof = proveMilestoneCloseout(mid, { refreshFromDisk: true });
1430
+ if (!closeoutProof.ok) {
1430
1431
  return {
1431
1432
  action: "stop",
1432
- reason: formatCloseoutConsistencyBlock(closeoutGate),
1433
+ reason: formatCloseoutProofBlock(closeoutProof),
1433
1434
  level: "warning",
1434
1435
  };
1435
1436
  }
@@ -90,6 +90,14 @@ export function getToolBaselineSnapshot(pi) {
90
90
  return live;
91
91
  return [...new Set([...baseline, ...live])];
92
92
  }
93
+ export function getRegisteredToolSnapshot(pi) {
94
+ if (typeof pi.getAllTools !== "function")
95
+ return getToolBaselineSnapshot(pi);
96
+ const names = pi.getAllTools()
97
+ .map((tool) => tool.name)
98
+ .filter((name) => typeof name === "string" && name.length > 0);
99
+ return [...new Set(names)];
100
+ }
93
101
  /**
94
102
  * Models eligible for the pre-dispatch policy gate. Prefer registry-available
95
103
  * models; when that list is empty (common after worktree resume before registry
@@ -28,7 +28,8 @@ import { regenerateIfMissing } from "./workflow-projections.js";
28
28
  import { WorktreeStateProjection } from "./worktree-state-projection.js";
29
29
  import { createWorkspace, scopeMilestone } from "./workspace.js";
30
30
  import { normalizeWorktreePathForCompare } from "./worktree-root.js";
31
- import { isDbAvailable, getDbPath, refreshOpenDatabaseFromDisk, getTask, getSlice, getMilestone, getMilestoneSlices, updateTaskStatus, _getAdapter, getVerificationEvidence } from "./gsd-db.js";
31
+ import { isDbAvailable, getTask, getSlice, getMilestone, getMilestoneSlices, updateTaskStatus, _getAdapter, getVerificationEvidence } from "./gsd-db.js";
32
+ import { getWorkflowDatabasePath, refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
32
33
  import { renderPlanCheckboxes, renderRoadmapFromDb } from "./markdown-renderer.js";
33
34
  import { parseRoadmap as parseLegacyRoadmap } from "./parsers-legacy.js";
34
35
  import { consumeSignal } from "./session-status-io.js";
@@ -1052,9 +1053,9 @@ export async function postUnitPreVerification(pctx, opts) {
1052
1053
  if (!opts?.skipSettleDelay) {
1053
1054
  await new Promise(r => setTimeout(r, 100));
1054
1055
  }
1055
- const dbPath = getDbPath();
1056
+ const dbPath = getWorkflowDatabasePath();
1056
1057
  if (isDbAvailable() && dbPath && dbPath !== ":memory:") {
1057
- const refreshed = refreshOpenDatabaseFromDisk();
1058
+ const refreshed = refreshWorkflowDatabaseFromDisk();
1058
1059
  if (!refreshed) {
1059
1060
  logWarning("db", "post-unit database refresh failed; derived state may be stale");
1060
1061
  }
@@ -21,8 +21,9 @@ import { getPendingGatesForTurn } from "./gsd-db.js";
21
21
  import { assertGateCoverage, getGatesForTurn, } from "./gate-registry.js";
22
22
  import { formatDecisionsCompact, formatRequirementsCompact } from "./structured-data-formatter.js";
23
23
  import { readPhaseAnchor, formatAnchorForPrompt } from "./phase-anchor.js";
24
- import { composeContextModeInstructions, composeInlinedContext, composeUnitContext } from "./unit-context-composer.js";
24
+ import { composeContextModeInstructions, composeContractedUnitContext, composeInlinedContext, composeUnitContext, } from "./unit-context-composer.js";
25
25
  import { resolveManifest } from "./unit-context-manifest.js";
26
+ import { compileUnitContextContract } from "./tool-contract.js";
26
27
  import { readCompactionSnapshot } from "./compaction-snapshot.js";
27
28
  import { logWarning } from "./workflow-logger.js";
28
29
  import { inlineGraphSubgraph } from "./graph-context.js";
@@ -33,6 +34,7 @@ import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-acti
33
34
  import { findMilestoneIds } from "./milestone-ids.js";
34
35
  import { buildRunUatPresentationForType, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from "./tool-presentation-plan.js";
35
36
  import { resolveEffectiveUatType, shouldDispatchUatForContent } from "./uat-policy.js";
37
+ import { buildWebAppUatGuidanceBlock } from "./web-app-uat.js";
36
38
  export { buildSkillActivationBlock, buildSkillDiscoveryVars };
37
39
  // ─── Preamble Cap ─────────────────────────────────────────────────────────────
38
40
  /**
@@ -229,6 +231,29 @@ function prependContextModeToBlock(unitType, base, block, renderMode = "standalo
229
231
  return contextMode;
230
232
  return `${contextMode}\n\n${block}`;
231
233
  }
234
+ function requireUnitPromptContextContract(unitType) {
235
+ const result = compileUnitContextContract(unitType);
236
+ if (result.ok)
237
+ return result.contract;
238
+ throw new Error(result.detail);
239
+ }
240
+ function requireComposedArtifactBlock(blocks, unitType, key) {
241
+ const block = blocks.find((item) => item.key === key);
242
+ if (!block) {
243
+ throw new Error(`Unit Context Contract for ${unitType} did not compose required artifact ${key}`);
244
+ }
245
+ return block.body;
246
+ }
247
+ function renderExecuteTaskOnDemandContext(base, mid, sid, artifacts) {
248
+ if (!artifacts.includes("slice-research"))
249
+ return "";
250
+ const researchPath = relSliceFile(base, mid, sid, "RESEARCH");
251
+ return [
252
+ "## On-demand Context",
253
+ "",
254
+ `Slice research is available at \`${researchPath}\`. Read it only if the inlined task plan, slice plan excerpt, and carry-forward context do not explain a required implementation detail.`,
255
+ ].join("\n");
256
+ }
232
257
  // ─── Executor Constraints ─────────────────────────────────────────────────────
233
258
  /**
234
259
  * Format executor context constraints for injection into the plan-slice prompt.
@@ -1745,6 +1770,13 @@ export async function buildPlanMilestonePrompt(mid, midTitle, base, level) {
1745
1770
  else {
1746
1771
  trackPromptContext(contextTelemetry, "knowledge", "skipped", null, "missing");
1747
1772
  }
1773
+ const webAppUatGuidance = buildWebAppUatGuidanceBlock(base);
1774
+ if (webAppUatGuidance) {
1775
+ pushTracked("web-app-uat", webAppUatGuidance);
1776
+ }
1777
+ else {
1778
+ trackPromptContext(contextTelemetry, "web-app-uat", "skipped", null, "not a web app");
1779
+ }
1748
1780
  pushTracked("templates", inlineTemplate("roadmap", "Roadmap"));
1749
1781
  if (inlineLevel === "full") {
1750
1782
  pushTracked("templates", inlineTemplate("decisions", "Decisions"));
@@ -2032,6 +2064,14 @@ async function renderSlicePrompt(options) {
2032
2064
  else {
2033
2065
  trackPromptContext(contextTelemetry, "graph-subgraph", "skipped", null, "missing");
2034
2066
  }
2067
+ const webAppUatGuidance = buildWebAppUatGuidanceBlock(base);
2068
+ if (webAppUatGuidance) {
2069
+ inlined.push(webAppUatGuidance);
2070
+ trackPromptContext(contextTelemetry, "web-app-uat", "inline", webAppUatGuidance);
2071
+ }
2072
+ else {
2073
+ trackPromptContext(contextTelemetry, "web-app-uat", "skipped", null, "not a web app");
2074
+ }
2035
2075
  const planTemplateInline = level === "minimal" ? inlineCompactTemplate("plan", "Slice Plan") : inlineTemplate("plan", "Slice Plan");
2036
2076
  inlined.push(planTemplateInline);
2037
2077
  trackPromptContext(contextTelemetry, "templates", "inline", planTemplateInline);
@@ -2173,7 +2213,7 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
2173
2213
  const taskPlanPath = resolveTaskFile(base, mid, sid, tid, "PLAN");
2174
2214
  const taskPlanContent = taskPlanPath ? await loadFile(taskPlanPath) : null;
2175
2215
  const taskPlanRelPath = relSlicePath(base, mid, sid) + `/tasks/${tid}-PLAN.md`;
2176
- const taskPlanInline = taskPlanContent
2216
+ const taskPlanContext = taskPlanContent
2177
2217
  ? [
2178
2218
  "## Inlined Task Plan (authoritative local execution contract)",
2179
2219
  `Source: \`${taskPlanRelPath}\``,
@@ -2184,11 +2224,11 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
2184
2224
  "## Inlined Task Plan (authoritative local execution contract)",
2185
2225
  `Task plan not found at dispatch time. Read \`${taskPlanRelPath}\` before executing.`,
2186
2226
  ].join("\n");
2187
- trackPromptContext(contextTelemetry, "task-plan", taskPlanContent ? "inline" : "on-demand", taskPlanInline, taskPlanContent ? undefined : "missing at dispatch");
2227
+ trackPromptContext(contextTelemetry, "task-plan", taskPlanContent ? "inline" : "on-demand", taskPlanContext, taskPlanContent ? undefined : "missing at dispatch");
2188
2228
  const slicePlanPath = resolveSliceFile(base, mid, sid, "PLAN");
2189
2229
  const slicePlanContent = slicePlanPath ? await loadFile(slicePlanPath) : null;
2190
- const slicePlanExcerpt = extractSliceExecutionExcerpt(slicePlanContent, relSliceFile(base, mid, sid, "PLAN"));
2191
- trackPromptContext(contextTelemetry, "slice-plan", slicePlanExcerpt ? "excerpt" : "skipped", slicePlanExcerpt, slicePlanExcerpt ? undefined : "missing");
2230
+ const slicePlanContext = extractSliceExecutionExcerpt(slicePlanContent, relSliceFile(base, mid, sid, "PLAN"));
2231
+ trackPromptContext(contextTelemetry, "slice-plan", slicePlanContext ? "excerpt" : "skipped", slicePlanContext, slicePlanContext ? undefined : "missing");
2192
2232
  // Check for continue file (new naming or legacy)
2193
2233
  const continueFile = resolveSliceFile(base, mid, sid, "CONTINUE");
2194
2234
  const legacyContinueDir = resolveSlicePath(base, mid, sid);
@@ -2287,6 +2327,30 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
2287
2327
  trackPromptContext(contextTelemetry, "decisions-template", "on-demand", decisionsOnDemandET);
2288
2328
  }
2289
2329
  trackPromptContext(contextTelemetry, "templates", "inline", inlinedTemplates, inlineLevel);
2330
+ const contextContract = requireUnitPromptContextContract("execute-task");
2331
+ const contractedContext = await composeContractedUnitContext(contextContract, {
2332
+ base: { unitType: "execute-task", basePath: base, milestoneId: mid, sliceId: sid, taskId: tid },
2333
+ resolveArtifact: async (key) => {
2334
+ switch (key) {
2335
+ case "task-plan":
2336
+ return taskPlanContext;
2337
+ case "slice-plan":
2338
+ return slicePlanContext;
2339
+ case "prior-task-summaries":
2340
+ return finalCarryForward;
2341
+ case "templates":
2342
+ return inlinedTemplates;
2343
+ default:
2344
+ return null;
2345
+ }
2346
+ },
2347
+ });
2348
+ const taskPlanInline = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "task-plan");
2349
+ const slicePlanExcerpt = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "slice-plan");
2350
+ const contractedCarryForward = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "prior-task-summaries");
2351
+ const contractedTemplates = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "templates");
2352
+ const onDemandContext = renderExecuteTaskOnDemandContext(base, mid, sid, contractedContext.onDemand);
2353
+ trackPromptContext(contextTelemetry, "slice-research", onDemandContext ? "on-demand" : "skipped", onDemandContext, onDemandContext ? undefined : "not declared by contract");
2290
2354
  const prompt = loadPrompt("execute-task", {
2291
2355
  overridesSection,
2292
2356
  runtimeContext,
@@ -2298,11 +2362,12 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
2298
2362
  taskPlanPath: taskPlanRelPath,
2299
2363
  taskPlanInline,
2300
2364
  slicePlanExcerpt,
2301
- carryForwardSection: finalCarryForward,
2365
+ carryForwardSection: contractedCarryForward,
2302
2366
  resumeSection,
2303
2367
  priorTaskLines: priorLines,
2368
+ onDemandContext,
2304
2369
  taskSummaryPath,
2305
- inlinedTemplates,
2370
+ inlinedTemplates: contractedTemplates,
2306
2371
  verificationBudget,
2307
2372
  gatesToClose,
2308
2373
  skillActivation: buildSkillActivationBlock({
@@ -2313,7 +2378,7 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
2313
2378
  taskId: tid,
2314
2379
  taskTitle: tTitle,
2315
2380
  taskPlanContent,
2316
- extraContext: [taskPlanInline, slicePlanExcerpt, finalCarryForward, resumeSection],
2381
+ extraContext: [taskPlanInline, slicePlanExcerpt, contractedCarryForward, resumeSection],
2317
2382
  unitType: "execute-task",
2318
2383
  }),
2319
2384
  });
@@ -2424,6 +2489,14 @@ export async function buildCompleteSlicePrompt(mid, midTitle, sid, sTitle, base,
2424
2489
  body = `${body}\n\n---\n\n${knowledgeInlineCS}`;
2425
2490
  }
2426
2491
  }
2492
+ const webAppUatGuidance = buildWebAppUatGuidanceBlock(base);
2493
+ if (webAppUatGuidance && body) {
2494
+ body = `${webAppUatGuidance}\n\n---\n\n${body}`;
2495
+ trackPromptContext(contextTelemetry, "web-app-uat", "inline", webAppUatGuidance);
2496
+ }
2497
+ else {
2498
+ trackPromptContext(contextTelemetry, "web-app-uat", "skipped", null, webAppUatGuidance ? "missing composed body" : "not a web app");
2499
+ }
2427
2500
  // Overrides section prepends to the top of the inlined context —
2428
2501
  // standard pattern for slice-level builders (until composer v2 lands
2429
2502
  // the prepend contract).