@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
@@ -135,37 +135,56 @@ export async function composeUnitContext(unitType, opts) {
135
135
  const manifest = resolveManifest(unitType);
136
136
  if (!manifest)
137
137
  return { prepend: "", inline: "" };
138
- // Single-source `unitType`: the manifest is resolved against the
138
+ const composed = await composeDeclaredUnitContext({
139
+ unitType,
140
+ artifacts: {
141
+ inline: manifest.artifacts.inline,
142
+ excerpt: manifest.artifacts.excerpt,
143
+ onDemand: manifest.artifacts.onDemand,
144
+ computed: manifest.artifacts.computed ?? [],
145
+ prepend: manifest.prepend ?? [],
146
+ },
147
+ }, opts);
148
+ return {
149
+ prepend: composed.prepend,
150
+ inline: composed.inline,
151
+ };
152
+ }
153
+ export async function composeContractedUnitContext(contract, opts) {
154
+ return composeDeclaredUnitContext(contract, opts);
155
+ }
156
+ async function composeDeclaredUnitContext(contract, opts) {
157
+ // Single-source `unitType`: contract/manifest selection comes from the
139
158
  // function arg, but computed builders read it from `base.unitType`.
140
- // If those ever diverge (caller passes one type to composeUnitContext
141
- // but a different one in opts.base), the composer would silently
142
- // mix one unit's manifest with another unit's computed context.
143
- // Normalize here so the composer dispatches a consistent identity
144
- // through to every builder.
159
+ // Normalize here so every builder sees the same Unit identity.
145
160
  const normalizedOpts = {
146
161
  ...opts,
147
- base: { ...opts.base, unitType },
162
+ base: { ...opts.base, unitType: contract.unitType },
148
163
  };
149
- const prependBlocks = await runComputed(manifest.prepend ?? [], normalizedOpts);
164
+ const prependBlocks = await runComputedBlocks(contract.artifacts.prepend, normalizedOpts, "prepend");
150
165
  const inlineBlocks = [];
151
- for (const key of manifest.artifacts.inline) {
166
+ for (const key of contract.artifacts.inline) {
152
167
  if (!normalizedOpts.resolveArtifact)
153
168
  break;
154
169
  const body = await normalizedOpts.resolveArtifact(key);
155
- if (body && body.length > 0)
156
- inlineBlocks.push(body);
170
+ if (body && body.length > 0) {
171
+ inlineBlocks.push({ key, mode: "inline", body });
172
+ }
157
173
  }
158
- for (const key of manifest.artifacts.excerpt) {
174
+ for (const key of contract.artifacts.excerpt) {
159
175
  if (!normalizedOpts.resolveExcerpt)
160
176
  break;
161
177
  const body = await normalizedOpts.resolveExcerpt(key);
162
- if (body && body.length > 0)
163
- inlineBlocks.push(body);
178
+ if (body && body.length > 0) {
179
+ inlineBlocks.push({ key, mode: "excerpt", body });
180
+ }
164
181
  }
165
- inlineBlocks.push(...await runComputed(manifest.artifacts.computed ?? [], normalizedOpts));
182
+ inlineBlocks.push(...await runComputedBlocks(contract.artifacts.computed, normalizedOpts, "computed"));
166
183
  return {
167
- prepend: prependBlocks.join(SECTION_SEPARATOR),
168
- inline: inlineBlocks.join(SECTION_SEPARATOR),
184
+ prepend: prependBlocks.map((block) => block.body).join(SECTION_SEPARATOR),
185
+ inline: inlineBlocks.map((block) => block.body).join(SECTION_SEPARATOR),
186
+ blocks: [...prependBlocks, ...inlineBlocks],
187
+ onDemand: contract.artifacts.onDemand,
169
188
  };
170
189
  }
171
190
  /**
@@ -173,7 +192,7 @@ export async function composeUnitContext(unitType, opts) {
173
192
  * Missing registry entries (manifest declares the id but caller didn't
174
193
  * register it) are skipped silently — see composeUnitContext rationale.
175
194
  */
176
- async function runComputed(ids, opts) {
195
+ async function runComputedBlocks(ids, opts, mode) {
177
196
  if (ids.length === 0 || !opts.computed)
178
197
  return [];
179
198
  const registry = opts.computed;
@@ -183,8 +202,9 @@ async function runComputed(ids, opts) {
183
202
  if (!entry)
184
203
  continue;
185
204
  const body = await entry.build(entry.inputs, opts.base);
186
- if (body && body.length > 0)
187
- out.push(body);
205
+ if (body && body.length > 0) {
206
+ out.push({ key: id, mode, body });
207
+ }
188
208
  }
189
209
  return out;
190
210
  }
@@ -4,7 +4,8 @@ import { atomicWriteSync } from "./atomic-write.js";
4
4
  import { gsdRoot, relSliceFile, relTaskFile, resolveSliceFile, resolveTaskFile, } from "./paths.js";
5
5
  import { loadFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
6
6
  import { parseUnitId } from "./unit-id.js";
7
- import { getTask, isDbAvailable, refreshOpenDatabaseFromDisk } from "./gsd-db.js";
7
+ import { getTask, isDbAvailable } from "./gsd-db.js";
8
+ import { refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
8
9
  import { isClosedStatus } from "./status-guards.js";
9
10
  // Per-record advisory lock — prevents read-modify-write races between
10
11
  // concurrent writers updating disjoint fields of the same runtime record.
@@ -169,7 +170,7 @@ export async function inspectExecuteTaskDurability(basePath, unitId) {
169
170
  const nextActionAdvanced = !new RegExp(`Execute ${tid}\\b`).test(stateContent);
170
171
  let dbComplete = false;
171
172
  if (isDbAvailable()) {
172
- refreshOpenDatabaseFromDisk();
173
+ refreshWorkflowDatabaseFromDisk();
173
174
  const task = getTask(mid, sid, tid);
174
175
  dbComplete = !!task && isClosedStatus(task.status);
175
176
  }
@@ -60,6 +60,7 @@ export const UNIT_TOOL_CONTRACTS = {
60
60
  "gsd_milestone_generate_id",
61
61
  ],
62
62
  requiredWorkflowTools: [
63
+ "ask_user_questions",
63
64
  "gsd_summary_save",
64
65
  "gsd_requirement_save",
65
66
  "gsd_requirement_update",
@@ -69,7 +70,7 @@ export const UNIT_TOOL_CONTRACTS = {
69
70
  },
70
71
  "discuss-slice": {
71
72
  allowedGsdTools: ["gsd_summary_save", "gsd_decision_save"],
72
- requiredWorkflowTools: ["gsd_summary_save"],
73
+ requiredWorkflowTools: ["ask_user_questions", "gsd_summary_save"],
73
74
  },
74
75
  "validate-milestone": {
75
76
  allowedGsdTools: ["gsd_milestone_status", "gsd_validate_milestone", "gsd_reassess_roadmap", "subagent"],
@@ -177,6 +177,29 @@ export function isAwaitingApprovalBoundary(messages) {
177
177
  return true;
178
178
  return hasApprovalQuestion(text);
179
179
  }
180
+ /** True when an assistant message already has an in-flight ask_user_questions tool call. */
181
+ export function messageHasPendingAskUserQuestionsTool(message) {
182
+ if (!message || typeof message !== "object")
183
+ return false;
184
+ const content = message.content;
185
+ if (!Array.isArray(content))
186
+ return false;
187
+ return content.some((block) => {
188
+ if (!block || typeof block !== "object")
189
+ return false;
190
+ // Claude Code marks completion by attaching externalResult, not by setting state.
191
+ // Streaming blocks often carry no state; serverToolUse is the claude-code-cli MCP path.
192
+ const tool = block;
193
+ if (tool.type !== "toolCall" && tool.type !== "serverToolUse")
194
+ return false;
195
+ const name = String(tool.name ?? "").toLowerCase();
196
+ if (!name.includes("ask_user_questions"))
197
+ return false;
198
+ if (tool.externalResult !== undefined)
199
+ return false;
200
+ return tool.state !== "completed" && tool.state !== "done";
201
+ });
202
+ }
180
203
  export function shouldPauseForUserApprovalQuestion(unitType, messages) {
181
204
  if (!unitType || !USER_APPROVAL_UNIT_TYPES.has(unitType))
182
205
  return false;
@@ -3,6 +3,7 @@
3
3
  import { existsSync } from "node:fs";
4
4
  import { getAutoWorktreePath, isInAutoWorktree } from "./auto-worktree.js";
5
5
  import { ensureDbOpen } from "./bootstrap/dynamic-tools.js";
6
+ import { refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
6
7
  import { getIsolationMode } from "./preferences.js";
7
8
  import { deriveState } from "./state.js";
8
9
  import { detectWorktreeName } from "./worktree.js";
@@ -72,6 +73,7 @@ export function formatValidationBlockedMessage(state, attemptedCommand = "") {
72
73
  }
73
74
  export async function getValidationBlockMessageForBase(base, attemptedCommand = "") {
74
75
  await ensureDbOpen(base);
76
+ refreshWorkflowDatabaseFromDisk();
75
77
  let state = await deriveState(base);
76
78
  if (state.activeMilestone &&
77
79
  getIsolationMode(base) === "worktree" &&
@@ -0,0 +1,80 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Web-app detection and Playwright/UAT guidance for planning and slice closeout.
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ import { detectWebApp } from "../browser-tools/web-app-detect.js";
6
+ export { detectWebApp };
7
+ function readPackageJson(projectRoot) {
8
+ const packageJsonPath = resolve(projectRoot, "package.json");
9
+ if (!existsSync(packageJsonPath))
10
+ return null;
11
+ try {
12
+ const parsed = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
13
+ return parsed && typeof parsed === "object" ? parsed : null;
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ export function hasPlaywrightTestDependency(projectRoot) {
20
+ const pkg = readPackageJson(projectRoot);
21
+ if (!pkg)
22
+ return false;
23
+ const names = [
24
+ ...Object.keys(pkg.dependencies ?? {}),
25
+ ...Object.keys(pkg.devDependencies ?? {}),
26
+ ];
27
+ return names.some((name) => name === "playwright" || name === "@playwright/test");
28
+ }
29
+ export function findPlaywrightTestScript(projectRoot) {
30
+ const pkg = readPackageJson(projectRoot);
31
+ if (!pkg?.scripts)
32
+ return null;
33
+ for (const [name, value] of Object.entries(pkg.scripts)) {
34
+ if (typeof value !== "string")
35
+ continue;
36
+ if (/\bplaywright\s+test\b/.test(value)) {
37
+ return `npm run ${name}`;
38
+ }
39
+ }
40
+ return null;
41
+ }
42
+ /**
43
+ * Markdown block injected into plan/complete-slice prompts when the project
44
+ * looks browser-facing. Returns null for CLI/library-only repos.
45
+ */
46
+ export function buildWebAppUatGuidanceBlock(projectRoot) {
47
+ if (!detectWebApp(projectRoot))
48
+ return null;
49
+ const playwrightScript = findPlaywrightTestScript(projectRoot);
50
+ const hasPlaywright = hasPlaywrightTestDependency(projectRoot) || playwrightScript !== null;
51
+ const lines = [
52
+ "### Web App UAT (detected)",
53
+ "",
54
+ "This project looks browser-facing. GSD exposes Playwright-backed `browser_*` tools by default for run-uat.",
55
+ "",
56
+ "**UAT modes (pick one per slice — do not use `artifact-driven` for browser steps):**",
57
+ "- `browser-executable` — navigate to `http://localhost:…`, click, screenshot, assert via `browser_*` tools during run-uat",
58
+ "- `runtime-executable` — run an automated browser test command via `gsd_uat_exec` (for example `npx playwright test`)",
59
+ "- `mixed` / `live-runtime` — combine runtime startup checks with interactive browser verification",
60
+ "",
61
+ "**Planning / closeout rules:**",
62
+ "- Preconditions must name the dev-server command and URL (for example `npm run dev` → `http://localhost:3000`)",
63
+ "- Slice Verification and UAT test cases must not say \"open in browser\" under `artifact-driven` — complete-slice rejects that",
64
+ "- Milestone `Verification Classes` → UAT row must describe browser-observable acceptance, not \"manual spot check\" alone",
65
+ ];
66
+ if (hasPlaywright) {
67
+ lines.push("", "**Playwright:** dependency detected.");
68
+ if (playwrightScript) {
69
+ lines.push(`- Prefer slice verification and runtime-executable UAT referencing \`${playwrightScript}\` or a focused \`npx playwright test <spec>\` command`);
70
+ }
71
+ else {
72
+ lines.push("- Prefer runtime-executable UAT with `npx playwright test` (or a focused spec path) when UI behavior is covered by specs");
73
+ }
74
+ lines.push("- Name concrete spec paths in slice Verification (for example `e2e/smoke.spec.ts`)");
75
+ }
76
+ else {
77
+ lines.push("", "**Playwright scaffolding (first UI slice):** no `playwright` / `@playwright/test` dependency yet.", "- Add a planning task that installs Playwright, adds `playwright.config.ts`, and creates a minimal smoke spec (for example `e2e/smoke.spec.ts`)", "- Task `verify` should run `npx playwright test` (or the focused spec) with a safe, simple command", "- Until specs exist, use `browser-executable` UAT with localhost preconditions and interactive `browser_*` checks at slice closeout");
78
+ }
79
+ return lines.join("\n");
80
+ }
@@ -1,8 +1,12 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { existsSync, realpathSync } from "node:fs";
3
- import { dirname, resolve, sep } from "node:path";
3
+ import { basename, dirname, resolve, sep } from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import { getRequiredWorkflowToolsForUnit } from "./unit-tool-contracts.js";
6
+ import { mcpToolMatchesBaseName } from "./mcp-tool-name.js";
7
+ import { supportsStructuredQuestions, usesWorkflowMcpTransport, } from "./question-transport.js";
8
+ import { WORKFLOW_TOOL_SURFACE_NAMES, isWorkflowToolSurfaceName, } from "./workflow-tool-surface.js";
9
+ export { supportsStructuredQuestions, usesWorkflowMcpTransport };
6
10
  /** Session cwd may be a milestone worktree; MCP config and server discovery use the project root. */
7
11
  export function resolveWorkflowMcpProjectRoot(sessionCwd) {
8
12
  let resolved;
@@ -19,72 +23,9 @@ export function resolveWorkflowMcpProjectRoot(sessionCwd) {
19
23
  }
20
24
  return resolved;
21
25
  }
22
- const MCP_WORKFLOW_TOOL_SURFACE = new Set([
23
- "gsd_cancel",
24
- "gsd_captures",
25
- "ask_user_questions",
26
- "gsd_capture_thought",
27
- "gsd_doctor",
28
- "gsd_execute",
29
- "gsd_memory_query",
30
- "gsd_memory_graph",
31
- "gsd_decision_save",
32
- "gsd_exec",
33
- "gsd_exec_search",
34
- "gsd_graph",
35
- "gsd_history",
36
- "gsd_knowledge",
37
- "gsd_progress",
38
- "gsd_query",
39
- "gsd_resume",
40
- "gsd_result",
41
- "gsd_resolve_blocker",
42
- "gsd_roadmap",
43
- "gsd_status",
44
- "gsd_complete_milestone",
45
- "gsd_complete_task",
46
- "gsd_complete_slice",
47
- "gsd_generate_milestone_id",
48
- "gsd_journal_query",
49
- "gsd_milestone_complete",
50
- "gsd_milestone_generate_id",
51
- "gsd_milestone_reopen",
52
- "gsd_checkpoint_db",
53
- "gsd_milestone_plan",
54
- "gsd_milestone_status",
55
- "gsd_milestone_validate",
56
- "gsd_plan_task",
57
- "gsd_plan_milestone",
58
- "gsd_plan_slice",
59
- "gsd_replan_slice",
60
- "gsd_reassess_roadmap",
61
- "gsd_reopen_milestone",
62
- "gsd_reopen_slice",
63
- "gsd_reopen_task",
64
- "gsd_requirement_save",
65
- "gsd_requirement_update",
66
- "gsd_roadmap_reassess",
67
- "gsd_save_decision",
68
- "gsd_save_gate_result",
69
- "gsd_save_requirement",
70
- "gsd_save_summary",
71
- "gsd_skip_slice",
72
- "gsd_slice_plan",
73
- "gsd_slice_replan",
74
- "gsd_slice_complete",
75
- "gsd_slice_reopen",
76
- "gsd_summary_save",
77
- "gsd_task_plan",
78
- "gsd_task_complete",
79
- "gsd_task_reopen",
80
- "gsd_update_requirement",
81
- "gsd_uat_exec",
82
- "gsd_uat_result_save",
83
- "gsd_validate_milestone",
84
- ]);
85
26
  /** Workflow MCP tools are validated by transport compatibility, not pi tool-compat profiles. */
86
27
  export function isWorkflowMcpSurfaceTool(toolName) {
87
- return MCP_WORKFLOW_TOOL_SURFACE.has(toolName);
28
+ return isWorkflowToolSurfaceName(toolName);
88
29
  }
89
30
  function parseLookupOutput(output) {
90
31
  return output
@@ -239,8 +180,12 @@ function getBundledWorkflowWriteGateModulePath() {
239
180
  }
240
181
  function getResolveTsHookPath() {
241
182
  const repoRoot = findGsdPiRepoRoot(dirname(fileURLToPath(import.meta.url)));
183
+ const sourceRepoRoot = repoRoot && basename(repoRoot) === "dist-test" ? dirname(repoRoot) : repoRoot;
242
184
  return firstExistingPath([
243
- ...(repoRoot
185
+ ...(sourceRepoRoot
186
+ ? [resolve(sourceRepoRoot, "src", "resources", "extensions", "gsd", "tests", "resolve-ts.mjs")]
187
+ : []),
188
+ ...(repoRoot && repoRoot !== sourceRepoRoot
244
189
  ? [resolve(repoRoot, "src", "resources", "extensions", "gsd", "tests", "resolve-ts.mjs")]
245
190
  : []),
246
191
  resolve(fileURLToPath(new URL("./tests/resolve-ts.mjs", import.meta.url))),
@@ -355,45 +300,13 @@ export function getRequiredWorkflowToolsForGuidedUnit(unitType) {
355
300
  export function getRequiredWorkflowToolsForAutoUnit(unitType) {
356
301
  return getRequiredWorkflowToolsForUnit(unitType);
357
302
  }
358
- export function usesWorkflowMcpTransport(authMode, baseUrl) {
359
- return authMode === "externalCli" && typeof baseUrl === "string" && baseUrl.startsWith("local://");
360
- }
361
- function hasAskUserQuestionsTool(activeTools) {
362
- return activeTools.some((toolName) => {
363
- if (toolName === "ask_user_questions")
364
- return true;
365
- if (!toolName.startsWith("mcp__"))
366
- return false;
367
- const toolSeparator = toolName.indexOf("__", "mcp__".length);
368
- return toolSeparator >= 0 && toolName.slice(toolSeparator + 2) === "ask_user_questions";
369
- });
370
- }
371
303
  function hasRequiredTool(requiredTool, activeTools) {
372
304
  return activeTools.some((toolName) => {
373
305
  if (toolName === requiredTool)
374
306
  return true;
375
- if (!toolName.startsWith("mcp__"))
376
- return false;
377
- const toolSeparator = toolName.indexOf("__", "mcp__".length);
378
- return toolSeparator >= 0 && toolName.slice(toolSeparator + 2) === requiredTool;
307
+ return mcpToolMatchesBaseName(toolName, requiredTool);
379
308
  });
380
309
  }
381
- function workflowMcpStructuredQuestionsOptIn(env = process.env) {
382
- const value = env.GSD_WORKFLOW_MCP_STRUCTURED_QUESTIONS;
383
- return value === "1" || value === "true";
384
- }
385
- export function supportsStructuredQuestions(activeTools, options = {}) {
386
- if (!hasAskUserQuestionsTool(activeTools))
387
- return false;
388
- if (usesWorkflowMcpTransport(options.authMode, options.baseUrl)) {
389
- // Claude Code local workflow-MCP exposes ask_user_questions, but form
390
- // elicitation can return an immediate cancel outside GSD's chat turn. Keep
391
- // checkpoints in plain chat unless a caller deliberately opts into testing
392
- // that transport.
393
- return workflowMcpStructuredQuestionsOptIn(options.env);
394
- }
395
- return true;
396
- }
397
310
  export function getWorkflowTransportSupportError(provider, requiredTools, options = {}) {
398
311
  if (!provider || requiredTools.length === 0)
399
312
  return null;
@@ -410,12 +323,12 @@ export function getWorkflowTransportSupportError(provider, requiredTools, option
410
323
  }
411
324
  const uniqueRequired = [...new Set(requiredTools)];
412
325
  const missing = (options.activeTools && options.activeTools.length > 0)
413
- ? uniqueRequired.filter((tool) => !hasRequiredTool(tool, options.activeTools))
414
- : uniqueRequired.filter((tool) => !MCP_WORKFLOW_TOOL_SURFACE.has(tool));
326
+ ? uniqueRequired.filter((tool) => !isWorkflowToolSurfaceName(tool) && !hasRequiredTool(tool, options.activeTools))
327
+ : uniqueRequired.filter((tool) => !isWorkflowToolSurfaceName(tool));
415
328
  if (missing.length === 0)
416
329
  return null;
417
330
  if (options.activeTools && options.activeTools.length > 0) {
418
331
  return `Provider ${providerLabel} cannot run ${surface}${unitLabel}: this unit requires ${missing.join(", ")}, but the active runtime toolset currently exposes only ${options.activeTools.slice().sort().join(", ")}.`;
419
332
  }
420
- return `Provider ${providerLabel} cannot run ${surface}${unitLabel}: this unit requires ${missing.join(", ")}, but the workflow MCP transport currently exposes only ${Array.from(MCP_WORKFLOW_TOOL_SURFACE).sort().join(", ")}.`;
333
+ return `Provider ${providerLabel} cannot run ${surface}${unitLabel}: this unit requires ${missing.join(", ")}, but the workflow MCP transport currently exposes only ${[...WORKFLOW_TOOL_SURFACE_NAMES].sort().join(", ")}.`;
421
334
  }
@@ -2,7 +2,8 @@ import { join } from "node:path";
2
2
  import { mkdirSync, existsSync, readFileSync, unlinkSync } from "node:fs";
3
3
  import { logWarning, logError } from "./workflow-logger.js";
4
4
  import { readEvents, findForkPoint, getSessionId } from "./workflow-events.js";
5
- import { transaction, updateTaskStatus, updateSliceStatus, updateMilestoneStatus, getSliceTasks, insertMilestone, getMilestoneSlices, insertVerificationEvidence, upsertDecision, openDatabase, setTaskBlockerDiscovered, insertOrIgnoreSlice, insertOrIgnoreTask, } from "./gsd-db.js";
5
+ import { transaction, updateTaskStatus, updateSliceStatus, updateMilestoneStatus, getSliceTasks, insertMilestone, getMilestoneSlices, insertVerificationEvidence, upsertDecision, setTaskBlockerDiscovered, insertOrIgnoreSlice, insertOrIgnoreTask, } from "./gsd-db.js";
6
+ import { openWorkflowDatabasePath } from "./db-workspace.js";
6
7
  import { isClosedStatus } from "./status-guards.js";
7
8
  import { invalidateStateCache } from "./state.js";
8
9
  import { clearPathCache, resolveGsdPathContract } from "./paths.js";
@@ -415,7 +416,7 @@ function _reconcileWorktreeLogsInner(mainBasePath, worktreeBasePath) {
415
416
  mkdirSync(join(mainBasePath, ".gsd"), { recursive: true });
416
417
  atomicWriteSync(join(mainBasePath, ".gsd", "event-log.jsonl"), logContent);
417
418
  // Step 8: Replay into DB (wrapped in a transaction by replayEvents)
418
- openDatabase(resolveGsdPathContract(mainBasePath).projectDb);
419
+ openWorkflowDatabasePath(resolveGsdPathContract(mainBasePath).projectDb);
419
420
  replayEvents(merged);
420
421
  // Step 9: Write manifest
421
422
  try {
@@ -548,7 +549,7 @@ pick) {
548
549
  const targetBaseEvents = pick === "main" ? wtBaseEvents : mainBaseEvents;
549
550
  writeEventLog(targetBasePath, targetBaseEvents.concat(rewrittenTargetEvents));
550
551
  // Replay resolved events through the DB (updates DB state)
551
- openDatabase(resolveGsdPathContract(basePath).projectDb);
552
+ openWorkflowDatabasePath(resolveGsdPathContract(basePath).projectDb);
552
553
  replayEvents(eventsToReplay);
553
554
  invalidateStateCache();
554
555
  clearPathCache();
@@ -0,0 +1,46 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Adapts shared workflow tool contracts into the extension runtime surface.
3
+ import { CANONICAL_WORKFLOW_TOOL_NAMES as CONTRACT_CANONICAL_WORKFLOW_TOOL_NAMES, WORKFLOW_TOOL_ALIAS_NAMES as CONTRACT_WORKFLOW_TOOL_ALIAS_NAMES, WORKFLOW_TOOL_CONTRACTS as CONTRACT_WORKFLOW_TOOL_CONTRACTS, WORKFLOW_TOOL_NAMES as CONTRACT_WORKFLOW_TOOL_NAMES, } from "@opengsd/contracts";
4
+ import { stripMcpToolPrefix } from "./mcp-tool-name.js";
5
+ export const WORKFLOW_TOOL_CONTRACTS = CONTRACT_WORKFLOW_TOOL_CONTRACTS;
6
+ export const CANONICAL_WORKFLOW_TOOL_NAMES = CONTRACT_CANONICAL_WORKFLOW_TOOL_NAMES;
7
+ export const WORKFLOW_TOOL_ALIAS_NAMES = CONTRACT_WORKFLOW_TOOL_ALIAS_NAMES;
8
+ export const DB_WORKFLOW_TOOL_NAMES = CONTRACT_WORKFLOW_TOOL_NAMES;
9
+ export const WORKFLOW_TOOL_ALIAS_PAIRS = WORKFLOW_TOOL_CONTRACTS.flatMap((tool) => tool.aliases.map((alias) => ({ canonical: tool.canonicalName, alias })));
10
+ export const WORKFLOW_TOOL_ALIAS_TO_CANONICAL = Object.fromEntries(WORKFLOW_TOOL_ALIAS_PAIRS.map(({ alias, canonical }) => [alias, canonical]));
11
+ const WORKFLOW_MCP_ADAPTER_TOOL_NAMES = [
12
+ "gsd_cancel",
13
+ "gsd_captures",
14
+ "ask_user_questions",
15
+ "gsd_doctor",
16
+ "gsd_execute",
17
+ "gsd_graph",
18
+ "gsd_history",
19
+ "gsd_knowledge",
20
+ "gsd_progress",
21
+ "gsd_query",
22
+ "gsd_result",
23
+ "gsd_resolve_blocker",
24
+ "gsd_roadmap",
25
+ "gsd_status",
26
+ ];
27
+ export const WORKFLOW_TOOL_SURFACE_NAMES = [
28
+ ...WORKFLOW_MCP_ADAPTER_TOOL_NAMES,
29
+ ...DB_WORKFLOW_TOOL_NAMES,
30
+ ];
31
+ const WORKFLOW_TOOL_SURFACE_NAME_SET = new Set(WORKFLOW_TOOL_SURFACE_NAMES);
32
+ export { stripMcpToolPrefix } from "./mcp-tool-name.js";
33
+ export function canonicalWorkflowSurfaceToolName(toolName) {
34
+ const baseName = stripMcpToolPrefix(toolName);
35
+ return WORKFLOW_TOOL_ALIAS_TO_CANONICAL[baseName] ?? baseName;
36
+ }
37
+ export function isWorkflowSurfaceAliasTool(toolName) {
38
+ const baseName = stripMcpToolPrefix(toolName);
39
+ return WORKFLOW_TOOL_ALIAS_TO_CANONICAL[baseName] !== undefined;
40
+ }
41
+ export function isWorkflowToolSurfaceName(toolName) {
42
+ return WORKFLOW_TOOL_SURFACE_NAME_SET.has(stripMcpToolPrefix(toolName));
43
+ }
44
+ export function aliasesForWorkflowTool(canonicalName) {
45
+ return WORKFLOW_TOOL_CONTRACTS.find((tool) => tool.canonicalName === canonicalName)?.aliases ?? [];
46
+ }
@@ -12,6 +12,8 @@ export function isWorkspaceGitAllowedCommand(trimmed) {
12
12
  const [name, subcommand] = command.split(/\s+/, 2);
13
13
  if (name === "doctor")
14
14
  return true;
15
+ if (name === "forensics")
16
+ return true;
15
17
  if (name === "closeout" || command.startsWith("closeout"))
16
18
  return true;
17
19
  if (name === "dispatch") {
@@ -60,6 +60,23 @@ const VERDICT_RE = /verdict:\s*[\w-]+/i;
60
60
  * Only overwrites when the source has a verdict — never clobbers a
61
61
  * worktree ASSESSMENT with a verdictless project-root copy.
62
62
  */
63
+ function forceOverwriteValidationWithVerdict(srcMilestoneDir, dstMilestoneDir, milestoneId) {
64
+ if (!existsSync(srcMilestoneDir) || !milestoneId)
65
+ return;
66
+ const srcFile = join(srcMilestoneDir, `${milestoneId}-VALIDATION.md`);
67
+ if (!existsSync(srcFile))
68
+ return;
69
+ try {
70
+ const srcContent = readFileSync(srcFile, "utf-8");
71
+ if (!VERDICT_RE.test(srcContent))
72
+ return;
73
+ mkdirSync(dstMilestoneDir, { recursive: true });
74
+ safeCopy(srcFile, join(dstMilestoneDir, `${milestoneId}-VALIDATION.md`), { force: true });
75
+ }
76
+ catch (err) {
77
+ logWarning("worktree", `validation force-copy failed: ${err instanceof Error ? err.message : String(err)}`);
78
+ }
79
+ }
63
80
  function forceOverwriteAssessmentsWithVerdict(srcMilestoneDir, dstMilestoneDir) {
64
81
  if (!existsSync(srcMilestoneDir))
65
82
  return;
@@ -211,7 +228,10 @@ export function _projectRootToWorktreeImpl(projectRoot, worktreePath_, milestone
211
228
  // session resume the DB is rebuilt from disk, and if the stale ASSESSMENT
212
229
  // persists, checkNeedsRunUat finds no passing verdict → re-dispatches
213
230
  // run-uat indefinitely (stuck-loop ×9).
214
- forceOverwriteAssessmentsWithVerdict(join(prGsd, "milestones", milestoneId), join(wtGsd, "milestones", milestoneId));
231
+ const prMilestoneDir = join(prGsd, "milestones", milestoneId);
232
+ const wtMilestoneDir = join(wtGsd, "milestones", milestoneId);
233
+ forceOverwriteValidationWithVerdict(prMilestoneDir, wtMilestoneDir, milestoneId);
234
+ forceOverwriteAssessmentsWithVerdict(prMilestoneDir, wtMilestoneDir);
215
235
  // Forward-sync completed-units.json from project root to worktree.
216
236
  // Project root is authoritative for completion state after crash recovery;
217
237
  // without this, the worktree re-dispatches already-completed units (#1886).
@@ -354,14 +374,20 @@ export class WorktreeStateProjection {
354
374
  * any Unit dispatches.
355
375
  */
356
376
  projectRootToWorktree(scope) {
357
- _projectRootToWorktreeImpl(scope.workspace.projectRoot, scope.workspace.worktreeRoot ?? scope.workspace.projectRoot, scope.milestoneId);
377
+ this.projectRootToWorktreePaths(scope.workspace.projectRoot, scope.workspace.worktreeRoot ?? scope.workspace.projectRoot, scope.milestoneId);
378
+ }
379
+ projectRootToWorktreePaths(projectRoot, worktreePath, milestoneId) {
380
+ _projectRootToWorktreeImpl(projectRoot, worktreePath, milestoneId);
358
381
  }
359
382
  /**
360
383
  * Project state from the auto-worktree back onto the project root for `scope`.
361
384
  * Called by the post-unit pipeline between Units.
362
385
  */
363
386
  projectWorktreeToRoot(scope) {
364
- _projectWorktreeToRootImpl(scope.workspace.worktreeRoot ?? scope.workspace.projectRoot, scope.workspace.projectRoot, scope.milestoneId);
387
+ this.projectWorktreeToRootPaths(scope.workspace.worktreeRoot ?? scope.workspace.projectRoot, scope.workspace.projectRoot, scope.milestoneId);
388
+ }
389
+ projectWorktreeToRootPaths(worktreePath, projectRoot, milestoneId) {
390
+ _projectWorktreeToRootImpl(worktreePath, projectRoot, milestoneId);
365
391
  }
366
392
  /**
367
393
  * Final projection from the auto-worktree to the project root before
@@ -373,6 +399,9 @@ export class WorktreeStateProjection {
373
399
  * telemetry on what crossed the boundary.
374
400
  */
375
401
  finalizeProjectionForMerge(scope) {
376
- return _finalizeProjectionForMergeImpl(scope.workspace.projectRoot, scope.workspace.worktreeRoot ?? scope.workspace.projectRoot, scope.milestoneId);
402
+ return this.finalizeProjectionForMergePaths(scope.workspace.projectRoot, scope.workspace.worktreeRoot ?? scope.workspace.projectRoot, scope.milestoneId);
403
+ }
404
+ finalizeProjectionForMergePaths(projectRoot, worktreePath, milestoneId) {
405
+ return _finalizeProjectionForMergeImpl(projectRoot, worktreePath, milestoneId);
377
406
  }
378
407
  }
@@ -63,6 +63,18 @@ export function normalizeAutoExitReason(rawReason) {
63
63
  ? reasonLc
64
64
  : "other";
65
65
  }
66
+ export function autoExitReasonForTerminalOutcome(outcome) {
67
+ switch (outcome?.code) {
68
+ case "all-complete":
69
+ return "all-complete";
70
+ case "settlement-blocked":
71
+ return "blocked";
72
+ case "no-remaining-units":
73
+ return "stop";
74
+ default:
75
+ return null;
76
+ }
77
+ }
66
78
  // ─── Emitters ────────────────────────────────────────────────────────────
67
79
  export function emitWorktreeCreated(projectRoot, milestoneId, meta = {}) {
68
80
  emitJournalEvent(projectRoot, baseEntry("worktree-created", {
@@ -146,7 +146,7 @@ export async function showInterviewRound(questions, opts, ctx) {
146
146
  }
147
147
  // External cancellation (e.g. remote channel won the race)
148
148
  if (opts.signal) {
149
- const onAbort = () => finish({ endInterview: false, answers: {} });
149
+ const onAbort = () => finish({ endInterview: false, answers: {}, interrupted: true });
150
150
  if (opts.signal.aborted) {
151
151
  onAbort();
152
152
  }
@@ -800,5 +800,5 @@ export async function showInterviewRound(questions, opts, ctx) {
800
800
  invalidate: () => { cachedLines = undefined; },
801
801
  handleInput,
802
802
  };
803
- });
803
+ }, opts.overlay ? { overlay: true } : undefined);
804
804
  }