@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
@@ -36,6 +36,8 @@ After the opening answer, classify project shape as **`simple`** or **`complex`*
36
36
 
37
37
  Persist the verdict through `gsd_summary_save` with `artifact_type: "PROJECT"` into `## Project Shape`; downstream `discuss-requirements`, `discuss-milestone`, and `discuss-slice` read the rendered projection.
38
38
 
39
+ When the project is browser-facing (web app, SPA, static site with UI, Next/React/Vue, etc.), also record **`Web stack:`** under `## Project Shape` (framework + whether Playwright or browser UAT is expected). Downstream planning uses this to choose `browser-executable` / `runtime-executable` UAT instead of deferring UI proof to humans.
40
+
39
41
  ### Before deeper rounds
40
42
 
41
43
  Ground your questions in the **Preparation Context snapshot above** (stack, structure, greenfield/brownfield and framework signals) plus any prior `.planning/` or `.gsd/` artifacts — those are authoritative. **Do not survey the codebase** with `rg`/`find`/`scout` before asking; read a specific file only when a question's answer genuinely hinges on it.
@@ -103,7 +105,7 @@ Once the user confirms depth:
103
105
 
104
106
  1. Use the **Project** output template (inlined above).
105
107
  2. Call `gsd_summary_save` with `artifact_type: "PROJECT"` and full project markdown as `content`; omit `milestone_id`. The tool persists the DB-backed PROJECT artifact and renders `.gsd/PROJECT.md`. Preserve the user's terms and framing.
106
- 3. The `## Project Shape` section MUST contain `**Complexity:** simple` or `**Complexity:** complex` (matching the verdict you announced) plus a one-line `**Why:**` rationale. Downstream stages read this line.
108
+ 3. The `## Project Shape` section MUST contain `**Complexity:** simple` or `**Complexity:** complex` (matching the verdict you announced) plus a one-line `**Why:**` rationale. For browser-facing projects, also include `**Web stack:**` (framework and expected browser/Playwright UAT approach). Downstream stages read these lines.
107
109
  4. The `## Capability Contract` section MUST reference `.gsd/REQUIREMENTS.md` — that file does not yet exist; the next stage (`discuss-requirements`) will produce it.
108
110
  5. The `## Milestone Sequence` MUST list at least M001 with title and one-liner. Subsequent milestones may be listed as known intents; they will be elaborated in their own discuss-milestone stages.
109
111
  6. Do NOT use `artifact_type: "CONTEXT"` and do NOT pass `milestone_id: "PROJECT"`; that creates a fake milestone named PROJECT.
@@ -47,6 +47,8 @@ If milestone research is inlined, trust it and skip redundant exploration. If fi
47
47
 
48
48
  Narrate decomposition reasoning in complete sentences: grouping, risk order, verification strategy.
49
49
 
50
+ **Web apps:** when inlined Web App UAT guidance is present, set milestone `Verification Classes` → UAT to browser-observable acceptance (Playwright spec or `browser_*` checks). Order an early slice to add Playwright smoke scaffolding when the dependency is missing.
51
+
50
52
  Then:
51
53
  1. Use the **Roadmap** output template from the inlined context above
52
54
  2. {{skillActivation}}
@@ -41,6 +41,7 @@ If slice research is inlined, trust its architectural findings, but verify every
41
41
  3. Use the inlined Output Template sections already present in this prompt. Do not read template files from disk.
42
42
  4. {{skillActivation}} Record expected executor skills in each task plan's `skills_used` frontmatter.
43
43
  5. Define slice verification before tasks. Non-trivial slices need real tests or executable assertions; boundary contracts need contract-exercising checks. Tests must not read .gitignore/gitignored paths such as `.gsd/`, `.planning/`, or `.audits/`.
44
+ **Web apps:** when inlined Web App UAT guidance is present, follow it — add Playwright smoke scaffolding on the first UI slice if missing, name localhost preconditions, and plan verification commands that match browser-capable UAT modes at slice closeout.
44
45
  6. Include Threat Surface (Q3), Requirement Impact (Q4), proof level, observability, integration closure, Failure Modes (Q5), Load Profile (Q6), and Negative Tests (Q7) only where applicable.
45
46
  7. Right-size tasks. Simple slices can be one task; split only when context, ownership, or verification boundaries justify it.
46
47
  8. Task `verify` commands must be safe, simple commands. Do not use shell pipes, redirects, semicolons, backticks, command substitution, output trimming, or grep regex alternation with `|`. If multiple checks are needed, create a small test file and run it with `node --test` or a package test script, or use separate simple commands joined only with `&&`. For absence checks, verify a pattern does not exist with `! grep -q 'pattern' file` or `! rg -q 'pattern' file`; do not use `grep -c` or `rg -c` to assert zero matches because count commands exit 1 when they find zero matches, and the verification gate treats that as failure.
@@ -63,6 +63,7 @@ Then:
63
63
  - `{{taskPlanTemplatePath}}`
64
64
  2. {{skillActivation}} Record the installed skills you expect executors to use in each task plan's `skills_used` frontmatter.
65
65
  3. Define slice-level verification: the objective stopping condition. Plan real test files with real assertions; for simple slices, executable commands are fine.
66
+ **Web apps:** when inlined Web App UAT guidance is present, follow it for Playwright scaffolding and browser-capable verification commands.
66
67
  4. For non-trivial slices, plan observability / proof level / integration closure, threat surface, and requirement impact. Omit entirely for simple slices.
67
68
  5. Decompose the slice into tasks that fit one context window each. Every task passed to `gsd_plan_slice` must use the exact keys `taskId`, `title`, `description`, `estimate`, `files`, `verify`, `inputs`, `expectedOutput`, and optional `observabilityImpact`. Put Why / Do / Done-when detail in `description`. `files`, `inputs`, and `expectedOutput` must be JSON arrays of strings, even for one path (for example, `"expectedOutput": ["src/index.ts"]`, never `"expectedOutput": "src/index.ts"`). `expectedOutput` is path-only: list only files the task creates or overwrites, and use `[]` for pure verification tasks.
68
69
  6. **Persist planning state through `gsd_plan_slice`.** Call it with the full payload. The tool writes to the DB and renders `{{outputPath}}` and `{{slicePath}}/tasks/T##-PLAN.md` automatically. Do NOT rely on direct `PLAN.md` writes.
@@ -158,7 +158,7 @@ Fix root causes, not symptoms. If applying temporary mitigation, label it and pr
158
158
  - State uncertainty plainly: "Not sure this handles X - testing it." No performed confidence, no hedging paragraphs.
159
159
  - All user-visible narration must be grammatical English. Do not emit compressed planner notes like "Need inspect X". If it fits a commit comment or standup note, it is acceptable.
160
160
  - When debugging, stay curious. Problems are puzzles. Say what's interesting about the failure before reaching for fixes.
161
- - After completing a task, give a brief summary and 2-4 numbered next-step options; last option is always "Other". Omit the list for strict output formats.
161
+ - After completing a task, give a brief summary and 2-4 numbered next-step options; last option is always "Other". Omit the list for strict output formats, or when the active workflow prompt already ends with its own explicit "Next steps:" handoff block — in that case follow the workflow's handoff and do not add a second list.
162
162
 
163
163
  If any next step is destructive/outward-facing, present it via `ask_user_questions` and wait for the user's answer before execution. Do not execute a next-step item from a prior plain-text numbered list without fresh confirmation.
164
164
 
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Provider Payload Policy - ordered shaping of provider request payloads.
3
+ *
4
+ * The order is intentional:
5
+ * 1. observation budgeting masks old tool results in auto-mode,
6
+ * 2. display truncation caps tool-result text for every mode,
7
+ * 3. the protected Source Context Block is appended after truncation,
8
+ * 4. supported models receive the configured service tier.
9
+ */
10
+ import { createObservationMask, createResponsesInputObservationMask, truncateContextResultMessages, truncateResponsesInputResultItems, } from "./context-masker.js";
11
+ import { getSourceObservationStore, isAutoActive } from "./auto-runtime-state.js";
12
+ import { loadEffectiveGSDPreferences } from "./preferences.js";
13
+ import { getEffectiveServiceTier, supportsServiceTier } from "./service-tier.js";
14
+ import { injectSourceContextBlockIntoPayload } from "./source-observations.js";
15
+ const DEFAULT_OBSERVATION_MASK_TURNS = 8;
16
+ const DEFAULT_TOOL_RESULT_MAX_CHARS = 800;
17
+ export const DEFAULT_PROVIDER_PAYLOAD_POLICY_DEPS = {
18
+ isAutoActive,
19
+ loadContextManagementConfig: () => loadEffectiveGSDPreferences()?.preferences.context_management,
20
+ renderSourceContextBlock: () => getSourceObservationStore().renderActiveBlock(),
21
+ getEffectiveServiceTier,
22
+ supportsServiceTier,
23
+ };
24
+ export function applyProviderPayloadPolicy({ payload, modelId, deps: overrides, }) {
25
+ const deps = { ...DEFAULT_PROVIDER_PAYLOAD_POLICY_DEPS, ...overrides };
26
+ try {
27
+ applyContextManagement(payload, deps);
28
+ }
29
+ catch {
30
+ // Provider payload shaping should not block a request when optional
31
+ // context management preferences or adapters fail.
32
+ }
33
+ try {
34
+ applySourceContextBlock(payload, deps);
35
+ }
36
+ catch {
37
+ // Source observations are opportunistic; execution can continue without
38
+ // an injected block.
39
+ }
40
+ applyServiceTier(payload, modelId, deps);
41
+ return payload;
42
+ }
43
+ function applyContextManagement(payload, deps) {
44
+ const config = deps.loadContextManagementConfig();
45
+ applyObservationBudget(payload, config, deps.isAutoActive());
46
+ applyDisplayTruncation(payload, config);
47
+ }
48
+ function applyObservationBudget(payload, config, autoActive) {
49
+ if (!autoActive || config?.observation_masking === false)
50
+ return;
51
+ const keepTurns = config?.observation_mask_turns ?? DEFAULT_OBSERVATION_MASK_TURNS;
52
+ if (Array.isArray(payload.messages)) {
53
+ payload.messages = createObservationMask(keepTurns)(payload.messages);
54
+ }
55
+ if (Array.isArray(payload.input)) {
56
+ payload.input = createResponsesInputObservationMask(keepTurns)(payload.input);
57
+ }
58
+ }
59
+ function applyDisplayTruncation(payload, config) {
60
+ const maxChars = config?.tool_result_max_chars ?? DEFAULT_TOOL_RESULT_MAX_CHARS;
61
+ if (Array.isArray(payload.messages)) {
62
+ payload.messages = truncateContextResultMessages(payload.messages, maxChars);
63
+ }
64
+ if (Array.isArray(payload.input)) {
65
+ payload.input = truncateResponsesInputResultItems(payload.input, maxChars);
66
+ }
67
+ }
68
+ function applySourceContextBlock(payload, deps) {
69
+ if (!deps.isAutoActive())
70
+ return;
71
+ const sourceContextBlock = deps.renderSourceContextBlock();
72
+ if (!sourceContextBlock)
73
+ return;
74
+ Object.assign(payload, injectSourceContextBlockIntoPayload(payload, sourceContextBlock));
75
+ }
76
+ function applyServiceTier(payload, modelId, deps) {
77
+ if (!modelId)
78
+ return;
79
+ const tier = deps.getEffectiveServiceTier();
80
+ if (!tier || !deps.supportsServiceTier(modelId))
81
+ return;
82
+ payload.service_tier = tier;
83
+ }
@@ -0,0 +1,13 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Process-level pull request policy for GSD-generated PRs.
3
+ import { createDraftPR } from "./git-service.js";
4
+ import { buildPrEvidence, } from "./pr-evidence.js";
5
+ export function buildPullRequestEvidence(input) {
6
+ return buildPrEvidence({
7
+ ...input,
8
+ aiAssisted: false,
9
+ });
10
+ }
11
+ export function createDraftPullRequestFromEvidence(basePath, milestoneId, evidence, options, deps = { createDraftPR }) {
12
+ return deps.createDraftPR(basePath, milestoneId, evidence.title, evidence.body, options);
13
+ }
@@ -0,0 +1,109 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Canonical quality-gate closure from durable DB and artifact evidence.
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { extractSection } from "./files.js";
5
+ import { getGateDefinition } from "./gate-registry.js";
6
+ import { getMilestoneSlices, getPendingGates, saveGateResult } from "./gsd-db.js";
7
+ import { resolveSliceFile, resolveTaskFile } from "./paths.js";
8
+ const GATE_SECTION_HEADINGS = {
9
+ Q3: ["Threat Surface", "Abuse Surface"],
10
+ Q4: ["Requirement Impact", "Broken Promises"],
11
+ Q5: ["Failure Modes"],
12
+ Q6: ["Load Profile"],
13
+ Q7: ["Negative Tests"],
14
+ Q8: ["Operational Readiness"],
15
+ };
16
+ function readFile(path) {
17
+ if (!path || !existsSync(path))
18
+ return null;
19
+ return readFileSync(path, "utf-8");
20
+ }
21
+ function firstSection(content, gateId) {
22
+ if (!content)
23
+ return null;
24
+ for (const heading of GATE_SECTION_HEADINGS[gateId] ?? []) {
25
+ const section = extractSection(content, heading);
26
+ if (section)
27
+ return section;
28
+ }
29
+ return null;
30
+ }
31
+ function evidenceArtifactContent(row, basePath) {
32
+ const def = getGateDefinition(row.gate_id);
33
+ switch (def?.ownerTurn) {
34
+ case "gate-evaluate":
35
+ return readFile(resolveSliceFile(basePath, row.milestone_id, row.slice_id, "PLAN"));
36
+ case "execute-task":
37
+ return readFile(resolveTaskFile(basePath, row.milestone_id, row.slice_id, row.task_id, "SUMMARY"));
38
+ case "complete-slice":
39
+ return readFile(resolveSliceFile(basePath, row.milestone_id, row.slice_id, "SUMMARY"));
40
+ default:
41
+ return null;
42
+ }
43
+ }
44
+ function closureEvidence(row, options) {
45
+ const def = getGateDefinition(row.gate_id);
46
+ if (!def)
47
+ return null;
48
+ if (def.ownerTurn === "validate-milestone" && options.milestoneValidationPassed) {
49
+ return {
50
+ verdict: "pass",
51
+ rationale: `${def.promptSection} covered by passing milestone validation`,
52
+ findings: "",
53
+ };
54
+ }
55
+ if (!options.artifactBasePath)
56
+ return null;
57
+ const section = firstSection(evidenceArtifactContent(row, options.artifactBasePath), row.gate_id);
58
+ if (section) {
59
+ return {
60
+ verdict: "pass",
61
+ rationale: `${def.promptSection} evidence found in durable artifact`,
62
+ findings: section,
63
+ };
64
+ }
65
+ if (!options.milestoneValidationPassed)
66
+ return null;
67
+ return {
68
+ verdict: "omitted",
69
+ rationale: `${def.promptSection} has no durable artifact section; milestone validation passed`,
70
+ findings: "",
71
+ };
72
+ }
73
+ function closeGate(row, evidence) {
74
+ saveGateResult({
75
+ milestoneId: row.milestone_id,
76
+ sliceId: row.slice_id,
77
+ gateId: row.gate_id,
78
+ taskId: row.task_id,
79
+ verdict: evidence.verdict,
80
+ rationale: evidence.rationale,
81
+ findings: evidence.findings,
82
+ });
83
+ }
84
+ export function closeQualityGatesFromEvidence(milestoneId, options = {}) {
85
+ const repaired = [];
86
+ const unresolved = [];
87
+ for (const slice of getMilestoneSlices(milestoneId)) {
88
+ const sliceId = slice.id;
89
+ for (const row of getPendingGates(milestoneId, sliceId)) {
90
+ if (!getGateDefinition(row.gate_id)) {
91
+ unresolved.push(row);
92
+ continue;
93
+ }
94
+ const evidence = closureEvidence(row, options);
95
+ if (!evidence) {
96
+ unresolved.push(row);
97
+ continue;
98
+ }
99
+ closeGate(row, evidence);
100
+ repaired.push({
101
+ gateId: row.gate_id,
102
+ sliceId: row.slice_id,
103
+ ...(row.task_id ? { taskId: row.task_id } : {}),
104
+ verdict: evidence.verdict,
105
+ });
106
+ }
107
+ }
108
+ return { repaired, unresolved };
109
+ }
@@ -0,0 +1,86 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Resolve how workflow units should ask the user for input.
3
+ import { parseMcpToolName, toMcpToolName } from "./mcp-tool-name.js";
4
+ function isWorkflowMcpServerName(serverName) {
5
+ const normalized = serverName.toLowerCase();
6
+ return normalized === "gsd" || normalized.includes("workflow");
7
+ }
8
+ export function usesWorkflowMcpTransport(authMode, baseUrl) {
9
+ return authMode === "externalCli" && typeof baseUrl === "string" && baseUrl.startsWith("local://");
10
+ }
11
+ export function hasAskUserQuestionsTool(activeTools) {
12
+ return activeTools.some((toolName) => {
13
+ if (toolName === "ask_user_questions")
14
+ return true;
15
+ const mcp = parseMcpToolName(toolName);
16
+ if (!mcp)
17
+ return false;
18
+ if (mcp.toolName === "ask_user_questions")
19
+ return true;
20
+ return mcp.toolName === "*" && isWorkflowMcpServerName(mcp.serverName);
21
+ });
22
+ }
23
+ function workflowMcpStructuredQuestionsEnabled(env = process.env) {
24
+ const value = env.GSD_WORKFLOW_MCP_STRUCTURED_QUESTIONS?.trim().toLowerCase();
25
+ return value !== "0" && value !== "false" && value !== "off";
26
+ }
27
+ export function resolveQuestionTransport(options) {
28
+ const questionToolAvailable = hasAskUserQuestionsTool(options.activeTools);
29
+ const usesWorkflowMcp = usesWorkflowMcpTransport(options.authMode, options.baseUrl);
30
+ if (!questionToolAvailable) {
31
+ return {
32
+ structuredQuestionsAvailable: "false",
33
+ questionToolAvailable,
34
+ usesWorkflowMcp,
35
+ reason: "question-tool-missing",
36
+ };
37
+ }
38
+ if (options.authMode === "externalCli" && !workflowMcpStructuredQuestionsEnabled(options.env)) {
39
+ return {
40
+ structuredQuestionsAvailable: "false",
41
+ questionToolAvailable,
42
+ usesWorkflowMcp,
43
+ reason: "workflow-mcp-disabled",
44
+ };
45
+ }
46
+ return {
47
+ structuredQuestionsAvailable: "true",
48
+ questionToolAvailable,
49
+ usesWorkflowMcp,
50
+ reason: "question-tool-available",
51
+ };
52
+ }
53
+ export function supportsStructuredQuestions(activeTools, options = {}) {
54
+ return resolveQuestionTransport({
55
+ ...options,
56
+ activeTools,
57
+ }).structuredQuestionsAvailable === "true";
58
+ }
59
+ export function resolveWorkflowQuestionToolSurface(options) {
60
+ const questionToolName = options.workflowServerName && !options.workflowExplicitlyBlocked
61
+ ? toMcpToolName(options.workflowServerName, "ask_user_questions")
62
+ : undefined;
63
+ const activeTools = [
64
+ ...options.exactWorkflowMcpTools,
65
+ ...options.workflowMcpTools,
66
+ ...(questionToolName ? [questionToolName] : []),
67
+ ];
68
+ const transport = resolveQuestionTransport({
69
+ activeTools,
70
+ authMode: "externalCli",
71
+ baseUrl: "local://claude-code",
72
+ env: options.env,
73
+ });
74
+ const exactQuestionToolAllowed = !!questionToolName && options.exactWorkflowMcpTools.includes(questionToolName);
75
+ const workflowQuestionsEnabled = transport.structuredQuestionsAvailable === "true" &&
76
+ (options.workflowMcpTools.length > 0 || exactQuestionToolAllowed);
77
+ const disallowedTools = options.workflowServerName && transport.questionToolAvailable && !workflowQuestionsEnabled
78
+ ? [toMcpToolName(options.workflowServerName, "ask_user_questions")]
79
+ : [];
80
+ return {
81
+ ...transport,
82
+ questionToolName,
83
+ workflowQuestionsEnabled,
84
+ disallowedTools,
85
+ };
86
+ }
@@ -191,9 +191,15 @@ export function parseRoadmapSlices(content) {
191
191
  const riskMatch = rest.match(/`risk:(\w+)`/);
192
192
  const risk = (riskMatch ? riskMatch[1] : "low");
193
193
  const depsMatch = rest.match(/`depends:\[([^\]]*)\]`/);
194
- const depends = depsMatch && depsMatch[1].trim()
195
- ? expandDependencies(depsMatch[1].split(",").map(s => s.trim()))
194
+ // Recovery fallback: double-bracket form `[[id]]` from serialized bracket-wrapped IDs
195
+ const fallbackDepsMatch = depsMatch ? null : rest.match(/`depends:\[(\[(?:[^\]]*)\](?:,\[(?:[^\]]*)\])*)\]`/);
196
+ const rawDepContent = (depsMatch ?? fallbackDepsMatch)?.[1] ?? "";
197
+ const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
198
+ const RANGE_RE = /^[A-Za-z]+\d+(?:-|\.\.)[A-Za-z]+\d+$/;
199
+ const rawDepParts = rawDepContent.trim()
200
+ ? rawDepContent.replace(/\[|\]/g, "").split(",").map(s => s.trim()).filter(s => SLICE_ID_RE.test(s) || RANGE_RE.test(s))
196
201
  : [];
202
+ const depends = expandDependencies(rawDepParts);
197
203
  // ADR-011: the renderer writes a `[sketch]` badge for sketch slices.
198
204
  // Parse it back so the is_sketch flag survives a markdown → DB re-import
199
205
  // (e.g. /gsd recover); otherwise the flag was silently lost.
@@ -19,7 +19,8 @@ import { isAbsolute, join, dirname, resolve } from "node:path";
19
19
  import { fileURLToPath } from "node:url";
20
20
  import { gsdRoot } from "./paths.js";
21
21
  import { createWorktree, worktreePath, removeWorktree } from "./worktree-manager.js";
22
- import { runWorktreePostCreateHook, syncGsdStateToWorktree } from "./auto-worktree.js";
22
+ import { runWorktreePostCreateHook, syncGsdStateToWorktreeByScope } from "./auto-worktree.js";
23
+ import { createWorkspace, scopeMilestone } from "./workspace.js";
23
24
  import { writeSessionStatus, } from "./session-status-io.js";
24
25
  import { hasFileConflict } from "./slice-parallel-conflict.js";
25
26
  import { getErrorMessage } from "./error-utils.js";
@@ -108,7 +109,7 @@ function createSliceWorktree(basePath, milestoneId, sliceId) {
108
109
  if (hookError) {
109
110
  throw new Error(`slice worktree post-create hook failed (${wtName}): ${hookError}`);
110
111
  }
111
- syncGsdStateToWorktree(basePath, wtPath);
112
+ syncGsdStateToWorktreeByScope(scopeMilestone(createWorkspace(basePath), milestoneId), scopeMilestone(createWorkspace(wtPath), milestoneId));
112
113
  if (!existsSync(join(wtPath, ".gsd"))) {
113
114
  throw new Error(`slice worktree preflight failed (${wtName}): missing .gsd in worktree`);
114
115
  }
@@ -18,8 +18,10 @@ import { logWarning } from './workflow-logger.js';
18
18
  import { extractVerdict } from './verdict-parser.js';
19
19
  import { detectPendingEscalation } from './escalation.js';
20
20
  import { isTerminalMilestoneSummaryContent } from './milestone-summary-classifier.js';
21
- import { isDbAvailable, wasDbOpenAttempted, getAllMilestones, getMilestone, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, getRequirementCounts, getLatestAssessmentByScope, getPendingGateCountForTurn, } from './gsd-db.js';
21
+ import { isDbAvailable, getAllMilestones, getMilestone, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, getRequirementCounts, getLatestAssessmentByScope, getPendingGateCountForTurn, } from './gsd-db.js';
22
+ import { wasWorkflowDatabaseOpenAttempted } from './db-workspace.js';
22
23
  import { formatCompletePhaseNextAction, countUnmappedActiveRequirements } from './requirements-backlog.js';
24
+ import { classifyMilestoneReadiness, readinessNeedsDiscussion, } from './milestone-readiness.js';
23
25
  function formatNeedsAttentionBlocker(milestoneId) {
24
26
  return [
25
27
  `Milestone ${milestoneId} is blocked because milestone validation returned needs-attention.`,
@@ -301,7 +303,7 @@ export async function deriveState(basePath, opts) {
301
303
  _telemetry.dbDeriveCount++;
302
304
  }
303
305
  else {
304
- if (wasDbOpenAttempted()) {
306
+ if (wasWorkflowDatabaseOpenAttempted()) {
305
307
  logWarning("state", "DB unavailable — refusing implicit markdown state derivation");
306
308
  }
307
309
  result = {
@@ -396,6 +398,12 @@ async function buildRegistryAndFindActive(basePath, milestones, completeMileston
396
398
  const title = stripMilestonePrefix(m.title) || m.id;
397
399
  const hasContext = !!resolveMilestoneFile(basePath, m.id, "CONTEXT");
398
400
  const hasDraftContext = !hasContext && !!resolveMilestoneFile(basePath, m.id, "CONTEXT-DRAFT");
401
+ const readiness = classifyMilestoneReadiness({
402
+ status: m.status,
403
+ hasContext,
404
+ hasDraftContext,
405
+ sliceCount: slices.length,
406
+ });
399
407
  if (!activeMilestoneFound) {
400
408
  const deps = m.depends_on;
401
409
  const depsUnmet = deps.some(dep => !completeMilestoneIds.has(dep));
@@ -403,9 +411,9 @@ async function buildRegistryAndFindActive(basePath, milestones, completeMileston
403
411
  registry.push({ id: m.id, title, status: 'pending', dependsOn: deps });
404
412
  continue;
405
413
  }
406
- if (m.status === 'queued' && slices.length === 0 && !hasContext) {
414
+ if (readiness.kind === 'queued-shell') {
407
415
  if (!firstDeferredQueuedShell) {
408
- firstDeferredQueuedShell = { id: m.id, title, deps, hasDraftContext };
416
+ firstDeferredQueuedShell = { id: m.id, title, deps, hasDraftContext: readiness.hasDraftContext };
409
417
  }
410
418
  registry.push({ id: m.id, title, status: 'pending', ...(deps.length > 0 ? { dependsOn: deps } : {}) });
411
419
  continue;
@@ -417,7 +425,7 @@ async function buildRegistryAndFindActive(basePath, milestones, completeMileston
417
425
  registry.push({ id: m.id, title, status: 'active', ...(deps.length > 0 ? { dependsOn: deps } : {}) });
418
426
  continue;
419
427
  }
420
- if ((m.status === 'needs-discussion' && !hasContext) || hasDraftContext)
428
+ if (readinessNeedsDiscussion(readiness))
421
429
  activeMilestoneHasDraft = true;
422
430
  activeMilestone = { id: m.id, title };
423
431
  activeMilestoneSlices = slices;
@@ -46,6 +46,13 @@
46
46
  For simple projects or scripts:
47
47
  - Executable verification commands (bash assertions, curl checks, etc.) are sufficient
48
48
 
49
+ For browser-facing web apps (React, Next, Vue, Vite, static HTML, etc.):
50
+ - Prefer `npx playwright test <spec>` in Verification when `@playwright/test` exists
51
+ - If Playwright is not set up yet, the first UI slice should add `playwright.config.ts`,
52
+ a minimal smoke spec (for example `e2e/smoke.spec.ts`), and a safe verify command
53
+ - Slice closeout UAT must declare `browser-executable` or `runtime-executable` — not
54
+ `artifact-driven` — when checks navigate to localhost or exercise the live UI
55
+
49
56
  If the project has no test framework and the work is non-trivial,
50
57
  the first task should set one up. A test runner costs 2 minutes
51
58
  and pays for itself immediately.
@@ -20,6 +20,7 @@
20
20
 
21
21
  - **Complexity:** {{simple | complex}}
22
22
  - **Why:** {{one-line rationale citing the signals that decided it}}
23
+ - **Web stack:** {{browser-facing framework or "not a web UI" — e.g. Next.js + Playwright, static HTML, N/A for CLI/API-only}}
23
24
 
24
25
  ## Current State
25
26
 
@@ -42,7 +42,7 @@
42
42
  - Contract verification: {{tests / shell verifiers / fixtures / artifact checks}}
43
43
  - Integration verification: {{real subsystem interaction that must be exercised, or none}}
44
44
  - Operational verification: {{service lifecycle / restart / reconnect / supervision / deploy-install behavior, or none}}
45
- - UAT / human verification: {{what needs real human judgment, or none}}
45
+ - UAT / human verification: {{what needs real human judgment, or none — for web apps prefer browser-executable / runtime-executable Playwright checks over deferring UI proof to humans}}
46
46
 
47
47
  ## Milestone Definition of Done
48
48
 
@@ -5,9 +5,13 @@
5
5
 
6
6
  ## UAT Type
7
7
 
8
- - UAT mode: {{artifact-driven | live-runtime | human-experience | mixed}}
8
+ - UAT mode: {{artifact-driven | browser-executable | runtime-executable | live-runtime | human-experience | mixed}}
9
9
  - Why this mode is sufficient: {{reason}}
10
10
 
11
+ <!-- Web apps: never use artifact-driven when steps open a browser, navigate to localhost,
12
+ or capture screenshots. Use browser-executable (browser_* tools) or runtime-executable
13
+ (npx playwright test). Name dev-server preconditions below. -->
14
+
11
15
  ## Preconditions
12
16
 
13
17
  {{whatMustBeTrueBeforeTesting — server running, data seeded, etc.}}
@@ -4,6 +4,17 @@ import { resolveManifest, } from "./unit-context-manifest.js";
4
4
  import { getRequiredWorkflowToolsForAutoUnit } from "./workflow-mcp.js";
5
5
  import { getUnitToolSurfaceContract } from "./unit-tool-contracts.js";
6
6
  import { WHOLE_FILE_OBSERVATION_MAX_BYTES, WHOLE_FILE_OBSERVATION_MAX_LINES, } from "./source-observations.js";
7
+ export function compileUnitContextContract(unitType) {
8
+ const manifest = resolveManifest(unitType);
9
+ if (!manifest) {
10
+ return {
11
+ ok: false,
12
+ reason: "unknown-unit-type",
13
+ detail: `No Unit manifest is registered for ${unitType}`,
14
+ };
15
+ }
16
+ return { ok: true, contract: buildPromptContextContract(unitType, manifest) };
17
+ }
7
18
  export function compileUnitToolContract(unitType) {
8
19
  const manifest = resolveManifest(unitType);
9
20
  const surfaceContract = getUnitToolSurfaceContract(unitType);
@@ -25,6 +36,7 @@ export function compileUnitToolContract(unitType) {
25
36
  detail: `${unitType} has no closeout workflow tool`,
26
37
  };
27
38
  }
39
+ const promptContext = buildPromptContextContract(unitType, manifest);
28
40
  return {
29
41
  ok: true,
30
42
  contract: {
@@ -33,10 +45,8 @@ export function compileUnitToolContract(unitType) {
33
45
  toolsPolicy: manifest.tools,
34
46
  requiredWorkflowTools,
35
47
  forbiddenWorkflowTools,
36
- promptObligations: [
37
- `context-mode:${manifest.contextMode}`,
38
- `tools-policy:${manifest.tools.mode}`,
39
- ],
48
+ promptObligations: promptContext.obligations,
49
+ promptContext,
40
50
  validationRules: [
41
51
  "unit-manifest-present",
42
52
  "workflow-tool-surface-present",
@@ -44,15 +54,49 @@ export function compileUnitToolContract(unitType) {
44
54
  ...(unitType === "execute-task" ? ["source-observation-contract-present"] : []),
45
55
  ],
46
56
  closeoutTools,
47
- sourceObservations: sourceObservationContractForUnit(unitType),
57
+ sourceObservations: promptContext.sourceObservations,
48
58
  artifacts: {
49
- inline: manifest.artifacts.inline,
50
- excerpt: manifest.artifacts.excerpt,
51
- onDemand: manifest.artifacts.onDemand,
59
+ inline: promptContext.artifacts.inline,
60
+ excerpt: promptContext.artifacts.excerpt,
61
+ onDemand: promptContext.artifacts.onDemand,
52
62
  },
53
63
  },
54
64
  };
55
65
  }
66
+ function buildPromptContextContract(unitType, manifest) {
67
+ const sourceObservations = sourceObservationContractForUnit(unitType);
68
+ return {
69
+ unitType,
70
+ contextMode: manifest.contextMode,
71
+ toolsPolicy: manifest.tools,
72
+ obligations: promptContextObligations(manifest, sourceObservations),
73
+ sourceObservations,
74
+ artifacts: {
75
+ inline: manifest.artifacts.inline,
76
+ excerpt: manifest.artifacts.excerpt,
77
+ onDemand: manifest.artifacts.onDemand,
78
+ computed: manifest.artifacts.computed ?? [],
79
+ prepend: manifest.prepend ?? [],
80
+ },
81
+ maxSystemPromptChars: manifest.maxSystemPromptChars,
82
+ };
83
+ }
84
+ function promptContextObligations(manifest, sourceObservations) {
85
+ const obligations = [
86
+ `context-mode:${manifest.contextMode}`,
87
+ `tools-policy:${manifest.tools.mode}`,
88
+ artifactObligation("context-inline", manifest.artifacts.inline),
89
+ artifactObligation("context-excerpt", manifest.artifacts.excerpt),
90
+ artifactObligation("context-on-demand", manifest.artifacts.onDemand),
91
+ ];
92
+ if (sourceObservations.mode !== "none") {
93
+ obligations.push(`source-observations:${sourceObservations.mode}`);
94
+ }
95
+ return obligations;
96
+ }
97
+ function artifactObligation(label, artifacts) {
98
+ return `${label}:${artifacts.length > 0 ? artifacts.join(",") : "none"}`;
99
+ }
56
100
  function sourceObservationContractForUnit(unitType) {
57
101
  if (unitType !== "execute-task")
58
102
  return { mode: "none" };