@opengsd/gsd-core 1.18.0 → 1.20.0

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 (308) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -1
  3. package/.opencode/plugins/gsd-core.js +2 -3
  4. package/agents/gsd-code-fixer.compact.md +7 -7
  5. package/agents/gsd-code-fixer.md +13 -7
  6. package/agents/gsd-code-reviewer.compact.md +49 -8
  7. package/agents/gsd-code-reviewer.md +53 -14
  8. package/agents/gsd-executor.md +8 -4
  9. package/agents/gsd-verifier.md +1 -1
  10. package/bin/install.js +422 -103
  11. package/commands/gsd/update.md +5 -2
  12. package/gsd-core/bin/gsd-tools.cjs +179 -30
  13. package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
  14. package/gsd-core/bin/lib/args-terminator.cjs +114 -0
  15. package/gsd-core/bin/lib/broken-windows.cjs +59 -1
  16. package/gsd-core/bin/lib/capability-lifecycle.cjs +1 -12
  17. package/gsd-core/bin/lib/capability-lock.cjs +13 -2
  18. package/gsd-core/bin/lib/capability-registry.cjs +376 -103
  19. package/gsd-core/bin/lib/capability-state.cjs +14 -8
  20. package/gsd-core/bin/lib/capability-validator.cjs +32 -0
  21. package/gsd-core/bin/lib/commands.cjs +27 -17
  22. package/gsd-core/bin/lib/config-loader.cjs +13 -3
  23. package/gsd-core/bin/lib/config.cjs +256 -58
  24. package/gsd-core/bin/lib/core-utils.cjs +45 -0
  25. package/gsd-core/bin/lib/decision-coverage-support.cjs +74 -0
  26. package/gsd-core/bin/lib/frontmatter.cjs +21 -3
  27. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +2 -2
  28. package/gsd-core/bin/lib/gate-context-drift.cjs +9 -4
  29. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +6 -1
  30. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +6 -1
  31. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
  32. package/gsd-core/bin/lib/gate-phase-context.cjs +7 -8
  33. package/gsd-core/bin/lib/gate-schema-drift.cjs +1 -1
  34. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +63 -22
  35. package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
  36. package/gsd-core/bin/lib/git-info-exclude.cjs +52 -0
  37. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +31 -12
  38. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +9 -7
  39. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +3 -3
  40. package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
  41. package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
  42. package/gsd-core/bin/lib/host-integration.cjs +13 -6
  43. package/gsd-core/bin/lib/init.cjs +245 -68
  44. package/gsd-core/bin/lib/install-engine.cjs +246 -32
  45. package/gsd-core/bin/lib/install-profiles.cjs +9 -4
  46. package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
  47. package/gsd-core/bin/lib/io.cjs +6 -0
  48. package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
  49. package/gsd-core/bin/lib/markdown-sectionizer.cjs +147 -1
  50. package/gsd-core/bin/lib/markdown-table.cjs +23 -0
  51. package/gsd-core/bin/lib/mcp-server.cjs +8 -5
  52. package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
  53. package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
  54. package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
  55. package/gsd-core/bin/lib/milestone.cjs +61 -51
  56. package/gsd-core/bin/lib/model-catalog.cjs +8 -0
  57. package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
  58. package/gsd-core/bin/lib/phase-entry-grammar.cjs +119 -0
  59. package/gsd-core/bin/lib/phase-id-display.cjs +2 -0
  60. package/gsd-core/bin/lib/phase-id.cjs +629 -38
  61. package/gsd-core/bin/lib/phase-lifecycle.cjs +12 -44
  62. package/gsd-core/bin/lib/phase-locator.cjs +328 -19
  63. package/gsd-core/bin/lib/phase.cjs +3066 -653
  64. package/gsd-core/bin/lib/planning-document.cjs +26 -5
  65. package/gsd-core/bin/lib/planning-inspect.cjs +27 -35
  66. package/gsd-core/bin/lib/planning-snapshot.cjs +15 -8
  67. package/gsd-core/bin/lib/planning-workspace.cjs +21 -3
  68. package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
  69. package/gsd-core/bin/lib/read-only-git-env.cjs +79 -0
  70. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +2 -2
  71. package/gsd-core/bin/lib/review-lane-descriptor.cjs +57 -2
  72. package/gsd-core/bin/lib/review-lane-invocation.cjs +125 -18
  73. package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
  74. package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +11 -9
  75. package/gsd-core/bin/lib/roadmap-parser.cjs +735 -137
  76. package/gsd-core/bin/lib/roadmap-progress.cjs +136 -0
  77. package/gsd-core/bin/lib/roadmap-upgrade.cjs +47 -7
  78. package/gsd-core/bin/lib/roadmap.cjs +383 -123
  79. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +381 -14
  80. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
  81. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
  82. package/gsd-core/bin/lib/shell-command-projection.cjs +151 -19
  83. package/gsd-core/bin/lib/smart-entry.cjs +35 -11
  84. package/gsd-core/bin/lib/state-contract.cjs +39 -15
  85. package/gsd-core/bin/lib/state-document.cjs +344 -27
  86. package/gsd-core/bin/lib/state-transition.cjs +156 -32
  87. package/gsd-core/bin/lib/state.cjs +527 -186
  88. package/gsd-core/bin/lib/surface.cjs +9 -0
  89. package/gsd-core/bin/lib/task-command-router.cjs +5 -25
  90. package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
  91. package/gsd-core/bin/lib/template.cjs +2 -2
  92. package/gsd-core/bin/lib/validate.cjs +3 -2
  93. package/gsd-core/bin/lib/vendor/re2js.cjs +863 -577
  94. package/gsd-core/bin/lib/vendor/re2js.d.cts +284 -219
  95. package/gsd-core/bin/lib/verification.cjs +96 -9
  96. package/gsd-core/bin/lib/verify.cjs +4 -2
  97. package/gsd-core/bin/lib/workstream-inventory.cjs +26 -20
  98. package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
  99. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  100. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  101. package/gsd-core/bin/verify-reapply-patches.cjs +411 -10
  102. package/gsd-core/references/cicd-review-patterns.md +45 -0
  103. package/gsd-core/references/git-integration.md +11 -0
  104. package/gsd-core/references/loop-hook-dispatch.md +13 -6
  105. package/gsd-core/references/necessity-review.md +48 -0
  106. package/gsd-core/references/planning-config.md +2 -0
  107. package/gsd-core/references/tdd.md +2 -2
  108. package/gsd-core/templates/DEBUG.md +16 -0
  109. package/gsd-core/templates/config.json +2 -1
  110. package/gsd-core/templates/verification-report.md +1 -1
  111. package/gsd-core/workflows/audit-fix.md +2 -1
  112. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
  113. package/gsd-core/workflows/code-review-fix.md +46 -5
  114. package/gsd-core/workflows/code-review.md +64 -7
  115. package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
  116. package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
  117. package/gsd-core/workflows/complete-milestone.md +37 -150
  118. package/gsd-core/workflows/diagnose-issues.md +29 -5
  119. package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
  120. package/gsd-core/workflows/discuss-phase-assumptions.md +33 -2
  121. package/gsd-core/workflows/discuss-phase-power.md +19 -2
  122. package/gsd-core/workflows/discuss-phase.md +6 -10
  123. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
  124. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +7 -2
  125. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -1
  126. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +2 -2
  127. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
  128. package/gsd-core/workflows/execute-phase.md +10 -6
  129. package/gsd-core/workflows/execute-plan.md +1 -1
  130. package/gsd-core/workflows/health.md +2 -1
  131. package/gsd-core/workflows/import.md +1 -1
  132. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +2 -2
  133. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +13 -9
  134. package/gsd-core/workflows/plan-phase.md +14 -14
  135. package/gsd-core/workflows/pr-branch.md +2 -0
  136. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
  137. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
  138. package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
  139. package/gsd-core/workflows/quick.md +1 -1
  140. package/gsd-core/workflows/reapply-patches.md +104 -0
  141. package/gsd-core/workflows/review.md +70 -154
  142. package/gsd-core/workflows/section-manifest.json +5 -0
  143. package/gsd-core/workflows/secure-phase.md +1 -1
  144. package/gsd-core/workflows/settings-advanced.md +57 -9
  145. package/gsd-core/workflows/settings.md +1 -0
  146. package/gsd-core/workflows/ship.md +15 -4
  147. package/gsd-core/workflows/spec-phase.md +3 -6
  148. package/gsd-core/workflows/verify-work.md +4 -3
  149. package/hooks/dist/gsd-agent-isolation-guard.js +11 -1
  150. package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
  151. package/hooks/dist/gsd-graphify-update.sh +6 -0
  152. package/hooks/dist/gsd-path-export.js +95 -0
  153. package/hooks/dist/gsd-secret-read-guard.js +172 -39
  154. package/hooks/dist/gsd-statusline.js +37 -3
  155. package/hooks/dist/gsd-windsurf-pre-write.js +29 -2
  156. package/hooks/dist/gsd-workflow-guard.js +3 -2
  157. package/hooks/dist/gsd-worktree-path-guard.js +29 -2
  158. package/hooks/dist/lib/git-probe.js +16 -0
  159. package/hooks/dist/lib/isolation-sentinel.js +44 -0
  160. package/hooks/dist/managed-hooks-registry.cjs +1 -0
  161. package/hooks/gsd-agent-isolation-guard.js +11 -1
  162. package/hooks/gsd-cursor-subagent-start.js +6 -2
  163. package/hooks/gsd-graphify-update.sh +6 -0
  164. package/hooks/gsd-path-export.js +95 -0
  165. package/hooks/gsd-secret-read-guard.js +172 -39
  166. package/hooks/gsd-statusline.js +37 -3
  167. package/hooks/gsd-windsurf-pre-write.js +29 -2
  168. package/hooks/gsd-workflow-guard.js +3 -2
  169. package/hooks/gsd-worktree-path-guard.js +29 -2
  170. package/hooks/hooks.json +1 -0
  171. package/hooks/lib/git-probe.js +16 -0
  172. package/hooks/lib/isolation-sentinel.js +44 -0
  173. package/hooks/managed-hooks-registry.cjs +1 -0
  174. package/package.json +15 -8
  175. package/pi/gsd.cjs +1047 -10
  176. package/pi/package-agents/gsd-advisor-researcher.md +113 -0
  177. package/pi/package-agents/gsd-ai-researcher.md +111 -0
  178. package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
  179. package/pi/package-agents/gsd-code-fixer.md +774 -0
  180. package/pi/package-agents/gsd-code-reviewer.md +441 -0
  181. package/pi/package-agents/gsd-codebase-mapper.md +850 -0
  182. package/pi/package-agents/gsd-debug-session-manager.md +416 -0
  183. package/pi/package-agents/gsd-debugger.md +1274 -0
  184. package/pi/package-agents/gsd-doc-classifier.md +269 -0
  185. package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
  186. package/pi/package-agents/gsd-doc-verifier.md +212 -0
  187. package/pi/package-agents/gsd-doc-writer.md +626 -0
  188. package/pi/package-agents/gsd-dom-verifier.md +164 -0
  189. package/pi/package-agents/gsd-domain-researcher.md +144 -0
  190. package/pi/package-agents/gsd-eval-auditor.md +185 -0
  191. package/pi/package-agents/gsd-eval-planner.md +149 -0
  192. package/pi/package-agents/gsd-executor.md +898 -0
  193. package/pi/package-agents/gsd-framework-selector.md +159 -0
  194. package/pi/package-agents/gsd-integration-checker.md +476 -0
  195. package/pi/package-agents/gsd-intel-updater.md +338 -0
  196. package/pi/package-agents/gsd-mempalace-curator.md +49 -0
  197. package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
  198. package/pi/package-agents/gsd-pattern-mapper.md +340 -0
  199. package/pi/package-agents/gsd-phase-researcher.md +897 -0
  200. package/pi/package-agents/gsd-plan-checker.md +1077 -0
  201. package/pi/package-agents/gsd-planner.md +1003 -0
  202. package/pi/package-agents/gsd-project-researcher.md +611 -0
  203. package/pi/package-agents/gsd-research-synthesizer.md +259 -0
  204. package/pi/package-agents/gsd-roadmapper.md +779 -0
  205. package/pi/package-agents/gsd-security-auditor.md +171 -0
  206. package/pi/package-agents/gsd-ui-auditor.md +581 -0
  207. package/pi/package-agents/gsd-ui-checker.md +417 -0
  208. package/pi/package-agents/gsd-ui-researcher.md +469 -0
  209. package/pi/package-agents/gsd-user-profiler.md +174 -0
  210. package/pi/package-agents/gsd-verifier.md +963 -0
  211. package/pi/package-agents/manifest.json +39 -0
  212. package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
  213. package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
  214. package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
  215. package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
  216. package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
  217. package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
  218. package/pi/package-skills/gsd-capture/SKILL.md +68 -0
  219. package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
  220. package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
  221. package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
  222. package/pi/package-skills/gsd-config/SKILL.md +60 -0
  223. package/pi/package-skills/gsd-debug/SKILL.md +64 -0
  224. package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
  225. package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
  226. package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
  227. package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
  228. package/pi/package-skills/gsd-explore/SKILL.md +26 -0
  229. package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
  230. package/pi/package-skills/gsd-fast/SKILL.md +33 -0
  231. package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
  232. package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
  233. package/pi/package-skills/gsd-health/SKILL.md +36 -0
  234. package/pi/package-skills/gsd-help/SKILL.md +37 -0
  235. package/pi/package-skills/gsd-import/SKILL.md +46 -0
  236. package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
  237. package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
  238. package/pi/package-skills/gsd-manager/SKILL.md +46 -0
  239. package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
  240. package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
  241. package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
  242. package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
  243. package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
  244. package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
  245. package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
  246. package/pi/package-skills/gsd-next/SKILL.md +34 -0
  247. package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
  248. package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
  249. package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
  250. package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
  251. package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
  252. package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
  253. package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
  254. package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
  255. package/pi/package-skills/gsd-phase/SKILL.md +61 -0
  256. package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
  257. package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
  258. package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
  259. package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
  260. package/pi/package-skills/gsd-progress/SKILL.md +51 -0
  261. package/pi/package-skills/gsd-quick/SKILL.md +179 -0
  262. package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
  263. package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
  264. package/pi/package-skills/gsd-review/SKILL.md +50 -0
  265. package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
  266. package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
  267. package/pi/package-skills/gsd-settings/SKILL.md +30 -0
  268. package/pi/package-skills/gsd-ship/SKILL.md +27 -0
  269. package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
  270. package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
  271. package/pi/package-skills/gsd-spike/SKILL.md +53 -0
  272. package/pi/package-skills/gsd-stats/SKILL.md +22 -0
  273. package/pi/package-skills/gsd-surface/SKILL.md +177 -0
  274. package/pi/package-skills/gsd-thread/SKILL.md +29 -0
  275. package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
  276. package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
  277. package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
  278. package/pi/package-skills/gsd-undo/SKILL.md +38 -0
  279. package/pi/package-skills/gsd-update/SKILL.md +54 -0
  280. package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
  281. package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
  282. package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
  283. package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
  284. package/scripts/build-hooks.js +4 -0
  285. package/scripts/ci-next-health.cjs +246 -23
  286. package/scripts/command-contract-helpers.cjs +1 -1
  287. package/scripts/docs-guard-registry.cjs +22 -7
  288. package/scripts/gen-features.cjs +14 -2
  289. package/scripts/gen-health-docs.cjs +13 -1
  290. package/scripts/gen-pi-package-skills.cjs +217 -0
  291. package/scripts/lib/drift-scan.cjs +27 -0
  292. package/scripts/lib/macos-conformance-tier.generated.cjs +17 -1
  293. package/scripts/lib/platform-conformance-tier.generated.cjs +37 -1
  294. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
  295. package/scripts/lint-phase-enumeration-drift.cjs +8 -4
  296. package/scripts/lint-retired-runtime-name.cjs +5 -0
  297. package/scripts/lint-roadmap-progress-drift.cjs +421 -0
  298. package/scripts/mutation-matrix.cjs +23 -1
  299. package/scripts/npm-audit-baseline.cjs +41 -7
  300. package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
  301. package/scripts/select-docs-guards.cjs +1 -1
  302. package/scripts/self-test-report-policy.cjs +350 -0
  303. package/scripts/sync-next-version.cjs +38 -6
  304. package/skills/gsd-update/SKILL.md +5 -2
  305. package/vscode/package.json +1 -1
  306. package/scripts/diagnose-validate-commit-in-tier.cjs +0 -270
  307. package/scripts/diagnose-validate-commit-phases.cjs +0 -348
  308. package/scripts/xtrace-phase-timing.cjs +0 -205
@@ -1,6 +1,6 @@
1
1
  <purpose>
2
2
 
3
- Mark a shipped version (v1.0, v1.1, v2.0) as complete. Creates historical record in MILESTONES.md, performs full PROJECT.md evolution review, reorganizes ROADMAP.md with milestone groupings, and tags the release in git.
3
+ Mark a shipped version (v1.0, v1.1, v2.0) as complete. Creates historical record in MILESTONES.md, performs the full PROJECT.md evolution review (flat mode only; skipped under `--ws`, because PROJECT.md is shared across workstreams), reorganizes ROADMAP.md with milestone groupings, and tags the release in git.
4
4
 
5
5
  </purpose>
6
6
 
@@ -22,7 +22,7 @@ When a milestone completes:
22
22
  2. Archive requirements to `.planning/milestones/v[X.Y]-REQUIREMENTS.md`
23
23
  3. Update ROADMAP.md — overwrite in place with milestone grouping (preserve Backlog section)
24
24
  4. Safety commit archive files + updated ROADMAP.md, then `git rm REQUIREMENTS.md` (fresh for next milestone)
25
- 5. Perform full PROJECT.md evolution review
25
+ 5. Perform full PROJECT.md evolution review (flat mode only — skipped under an active workstream, #5195)
26
26
  6. Offer to create next milestone inline
27
27
  7. Archive UI artifacts (`*-UI-SPEC.md`, `*-UI-REVIEW.md`) alongside other phase documents
28
28
  8. Clean up `.planning/ui-reviews/` screenshot files (binary assets, never archived)
@@ -244,151 +244,22 @@ If additional details are needed (e.g., user-provided "Delivered" summary, git r
244
244
 
245
245
  </step>
246
246
 
247
- <step name="evolve_project_full_review">
248
-
249
- Full PROJECT.md evolution review at milestone completion.
250
-
251
- Read all phase summaries:
247
+ **Resolve the PROJECT.md review gate first.** This is the first `init.complete-milestone` call in the workflow, so the section manifest does not exist before it; reading `section_manifest` without making this call would fall into the fail-open `null` branch below and rewrite the shared PROJECT.md under `--ws` (#5195). `init.complete-milestone` is a pure read, so the later full call in `reorganize_roadmap_and_delete_originals` is unaffected.
252
248
 
253
249
  ```bash
254
- _SUMMARIES=( .planning/phases/*-*/*-SUMMARY.md )
255
- if [ -e "${_SUMMARIES[0]}" ]; then cat "${_SUMMARIES[@]}"; fi
256
- ```
257
-
258
- **Full review checklist:**
259
-
260
- 1. **"What This Is" accuracy:**
261
- - Compare current description to what was built
262
- - Update if product has meaningfully changed
263
-
264
- 2. **Core Value check:**
265
- - Still the right priority? Did shipping reveal a different core value?
266
- - Update if the ONE thing has shifted
267
-
268
- 3. **Business Context check (only if the section is present):**
269
- - Skip entirely if PROJECT.md has no `## Business Context` section
270
- - Customer, revenue model, and success metric still accurate after shipping?
271
- - Update any field that drifted; refresh the linked strategy doc reference if it moved
272
-
273
- 4. **Requirements audit:**
274
-
275
- **Validated section:**
276
- - All Active requirements shipped this milestone → Move to Validated
277
- - Format: `- ✓ [Requirement] — v[X.Y]`
278
-
279
- **Active section:**
280
- - Remove requirements moved to Validated
281
- - Add new requirements for next milestone
282
- - Keep unaddressed requirements
283
-
284
- **Out of Scope audit:**
285
- - Review each item — reasoning still valid?
286
- - Remove irrelevant items
287
- - Add requirements invalidated during milestone
288
-
289
- 5. **Context update:**
290
- - Current codebase state (LOC, tech stack)
291
- - User feedback themes (if any)
292
- - Known issues or technical debt
293
-
294
- 6. **Key Decisions audit:**
295
- - Extract all decisions from milestone phase summaries
296
- - Add to Key Decisions table with outcomes
297
- - Mark ✓ Good, ⚠️ Revisit, or — Pending
298
-
299
- 7. **Constraints check:**
300
- - Any constraints changed during development? Update as needed
301
-
302
- Update PROJECT.md inline. Update "Last updated" footer:
303
-
304
- ```markdown
305
- ---
306
- *Last updated: [date] after v[X.Y] milestone*
307
- ```
308
-
309
- **Example full evolution (v1.0 → v1.1 prep):**
310
-
311
- Before:
312
-
313
- ```markdown
314
- ## What This Is
315
-
316
- A real-time collaborative whiteboard for remote teams.
317
-
318
- ## Core Value
319
-
320
- Real-time sync that feels instant.
321
-
322
- ## Requirements
323
-
324
- ### Validated
325
-
326
- (None yet — ship to validate)
327
-
328
- ### Active
329
-
330
- - [ ] Canvas drawing tools
331
- - [ ] Real-time sync < 500ms
332
- - [ ] User authentication
333
- - [ ] Export to PNG
334
-
335
- ### Out of Scope
336
-
337
- - Mobile app — web-first approach
338
- - Video chat — use external tools
339
- ```
340
-
341
- After v1.0:
342
-
343
- ```markdown
344
- ## What This Is
345
-
346
- A real-time collaborative whiteboard for remote teams with instant sync and drawing tools.
347
-
348
- ## Core Value
349
-
350
- Real-time sync that feels instant.
351
-
352
- ## Requirements
353
-
354
- ### Validated
355
-
356
- - ✓ Canvas drawing tools — v1.0
357
- - ✓ Real-time sync < 500ms — v1.0 (achieved 200ms avg)
358
- - ✓ User authentication — v1.0
359
-
360
- ### Active
361
-
362
- - [ ] Export to PNG
363
- - [ ] Undo/redo history
364
- - [ ] Shape tools (rectangles, circles)
365
-
366
- ### Out of Scope
367
-
368
- - Mobile app — web-first approach, PWA works well
369
- - Video chat — use external tools
370
- - Offline mode — real-time is core value
371
-
372
- ## Context
373
-
374
- Shipped v1.0 with 2,400 LOC TypeScript.
375
- Tech stack: Next.js, Supabase, Canvas API.
376
- Initial user testing showed demand for shape tools.
250
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
251
+ $ARGUMENTS
252
+ GSD_ARGS_END
253
+ GSD_ARGS=${GSD_ARGS%$'\n'}
254
+ GSD_WS=$(echo " $GSD_ARGS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
255
+ INIT_EARLY=$(gsd_run query init.complete-milestone ${GSD_WS:+--ws=${GSD_WS##* }})
256
+ if [[ "$INIT_EARLY" == @file:* ]]; then INIT_EARLY=$(cat "${INIT_EARLY#@file:}"); fi
257
+ node -e "const m=JSON.parse(process.argv[1]).section_manifest; console.log('PROJECT_MD_REVIEW=' + (m==null||m.included.includes('project-md-evolution-review') ? 'run' : 'skip'))" "$INIT_EARLY"
377
258
  ```
378
259
 
379
- **Step complete when:**
380
-
381
- - [ ] "What This Is" reviewed and updated if needed
382
- - [ ] Core Value verified as still correct
383
- - [ ] Business Context checked (or confirmed absent)
384
- - [ ] All shipped requirements moved to Validated
385
- - [ ] New requirements added to Active for next milestone
386
- - [ ] Out of Scope reasoning audited
387
- - [ ] Context updated with current state
388
- - [ ] All milestone decisions added to Key Decisions
389
- - [ ] "Last updated" footer reflects milestone completion
390
-
391
- </step>
260
+ <!-- gsd:section id="project-md-evolution-review" when="state:flat-mode" -->
261
+ If the line above printed `PROJECT_MD_REVIEW=run` (the manifest is `null` or lists `"project-md-evolution-review"` in `included`): read and execute `gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md`. If it printed `PROJECT_MD_REVIEW=skip` (a workstream is active) — do not read the file; PROJECT.md is shared across workstreams, so a workstream's milestone close never rewrites it (#2308, #5195); proceed to `archive_milestone`.
262
+ <!-- /gsd:section -->
392
263
 
393
264
  <step name="archive_milestone">
394
265
 
@@ -402,6 +273,8 @@ AskUserQuestion: "Archive completed quick tasks into this milestone too?" with o
402
273
 
403
274
  If "Yes": set `ARCHIVE_QUICK_FLAG="--archive-quick"`. If "Skip" (or `.planning/quick/` is empty): set `ARCHIVE_QUICK_FLAG=""`.
404
275
 
276
+ **Per-repository release mapping (opt-in, #3628).** Set `PER_REPO_TAGGING=true` only when `INIT_EARLY` has `repo_tagging` equal to `per_repo` AND a non-empty `sub_repos`; otherwise it is `false` and this paragraph changes nothing. Shell state does not persist between commands, so later steps recompute it from their own `init.complete-milestone` JSON (`INIT_REORG`). When `true`, read and execute `gsd-core/workflows/complete-milestone/steps/release-map.md` Part 1 now (collect, validate, one consolidated confirmation, create the tags, record the outcome in `release-map.json`), and append `--release-map "${TMPDIR:-/tmp}/gsd-release-map-v[X.Y]/release-map.json"` to EVERY `milestone complete` call below (including the `--no-archive-phases` form); when `false`, append nothing. A GSD milestone version may differ from every repository's release version.
277
+
405
278
  **Delegate archival to `gsd_run query milestone.complete`:**
406
279
 
407
280
  ```bash
@@ -438,11 +311,13 @@ If the user explicitly wants to keep phase directories in place as raw execution
438
311
  gsd_run query milestone complete v[X.Y] --no-archive-phases --confirm
439
312
  ```
440
313
 
314
+ (When `PER_REPO_TAGGING` is `true`, this form takes the same `--release-map` argument.)
315
+
441
316
  Verify after a default (archived) completion: `✅ Phase directories archived to .planning/milestones/v[X.Y]-phases/`
442
317
 
443
318
  After archival, the AI still handles:
444
319
  - Reorganizing ROADMAP.md with milestone grouping (requires judgment) — overwrite in place after extracting Backlog section, with the write-guard's single-use sentinel armed first (a per-step env var cannot reach a hook — see the reorganize step for the sentinel mechanics)
445
- - Full PROJECT.md evolution review (requires understanding)
320
+ - Full PROJECT.md evolution review (requires understanding; flat mode only — skipped under `--ws`)
446
321
  - Safety commit of archive files + updated ROADMAP.md, then `git rm .planning/REQUIREMENTS.md`
447
322
  - These are NOT fully delegated because they require AI interpretation of content
448
323
 
@@ -535,12 +410,15 @@ ROADMAP_PATH=$(_gsd_field "$INIT_REORG" roadmap_path)
535
410
  ARCHIVE_DIR=$(_gsd_field "$INIT_REORG" archive_dir)
536
411
  MILESTONES_PATH=$(_gsd_field "$INIT_REORG" milestones_path)
537
412
  PROJECT_PATH=$(_gsd_field "$INIT_REORG" project_path)
538
- gsd_run query commit "chore: archive v[X.Y] milestone files" --files "${ARCHIVE_DIR}/v[X.Y]-ROADMAP.md" "${ARCHIVE_DIR}/v[X.Y]-REQUIREMENTS.md" "${ARCHIVE_DIR}/v[X.Y]-MILESTONE-AUDIT.md" "$MILESTONES_PATH" "$PROJECT_PATH" "$STATE_PATH" "$ROADMAP_PATH"
413
+ # #5195: PROJECT.md is shared across workstreams. Stage it only when init's own section manifest says this run edited it (the evolution review is included in flat mode only) — the same source the review step is gated on, so the two cannot disagree.
414
+ _gsd_has_section() { node -e "const m=JSON.parse(process.argv[1]).section_manifest; process.exit(m==null||m.included.includes(process.argv[2])?0:1)" "$1" "$2"; }
415
+ _gsd_has_section "$INIT_REORG" project-md-evolution-review || PROJECT_PATH=""
416
+ gsd_run query commit "chore: archive v[X.Y] milestone files" --files "${ARCHIVE_DIR}/v[X.Y]-ROADMAP.md" "${ARCHIVE_DIR}/v[X.Y]-REQUIREMENTS.md" "${ARCHIVE_DIR}/v[X.Y]-MILESTONE-AUDIT.md" "$MILESTONES_PATH" ${PROJECT_PATH:+"$PROJECT_PATH"} "$STATE_PATH" "$ROADMAP_PATH"
539
417
  ```
540
418
 
541
419
  This creates a durable checkpoint in git history. If anything fails after this point, the working tree can be reconstructed from git.
542
420
 
543
- MILESTONES.md and PROJECT.md are workstream-scoped the same way STATE.md/ROADMAP.md are (`planningPaths(cwd).planning`/`.project`) — under an active workstream this commits the actual files `milestone complete` wrote, not the root copies.
421
+ MILESTONES.md is workstream-scoped the same way STATE.md/ROADMAP.md are (`planningPaths(cwd).planning`) — under an active workstream this commits the actual files `milestone complete` wrote, not the root copies. PROJECT.md is NOT: it is shared across workstreams, so under an active workstream it is neither reviewed nor staged here (#5195).
544
422
 
545
423
  **Remove REQUIREMENTS.md via git rm** (preserves history, stages deletion atomically):
546
424
 
@@ -656,9 +534,15 @@ Exact bash for each of the four options (squash, history-preserving merge, delet
656
534
  </step>
657
535
 
658
536
  <!-- gsd:section id="git-tag" when="state:git-create-tag" -->
659
- If `section_manifest` is `null` or `"git-tag"` is in its `included` list: read and execute `gsd-core/workflows/complete-milestone/steps/git-tag.md`. Otherwise skip — do not read the file; proceed to `git_commit_milestone`.
537
+ If `PER_REPO_TAGGING` is `true`, skip this section: the per-repository tags were created in `archive_milestone`, and no `v[X.Y]` tag is created in the current directory. Otherwise, if `section_manifest` is `null` or `"git-tag"` is in its `included` list: read and execute `gsd-core/workflows/complete-milestone/steps/git-tag.md`. Otherwise skip — do not read the file; proceed to `git_commit_milestone`.
660
538
  <!-- /gsd:section -->
661
539
 
540
+ <step name="push_release_tags">
541
+
542
+ Recompute `PER_REPO_TAGGING` and `git_create_tag` from the latest `init.complete-milestone` JSON (`INIT_REORG`). If `PER_REPO_TAGGING` is `true` and `git_create_tag` is not `false`: read and execute `gsd-core/workflows/complete-milestone/steps/release-map.md` Part 2 (a separate push confirmation per repository naming the repository and its remote; nothing is pushed by default). Otherwise skip this step.
543
+
544
+ </step>
545
+
662
546
  <step name="git_commit_milestone">
663
547
 
664
548
  Commit the REQUIREMENTS.md deletion (archive files and ROADMAP.md were already committed in the safety commit in `reorganize_roadmap_and_delete_originals`).
@@ -669,6 +553,8 @@ git commit -m "chore: remove REQUIREMENTS.md for v[X.Y] milestone"
669
553
 
670
554
  Confirm: "Committed: chore: remove REQUIREMENTS.md for v[X.Y] milestone"
671
555
 
556
+ When `PER_REPO_TAGGING` was `true`, remove the scratch directory: `rm -rf "${TMPDIR:-/tmp}/gsd-release-map-v[X.Y]"` (the archived copy lives in `.planning/milestones/`).
557
+
672
558
  </step>
673
559
 
674
560
  <step name="offer_next">
@@ -734,8 +620,8 @@ Milestone completion is successful when:
734
620
  - [ ] Known deferred items count noted in MILESTONES.md entry
735
621
 
736
622
  - [ ] MILESTONES.md entry created with stats and accomplishments
737
- - [ ] PROJECT.md full evolution review completed
738
- - [ ] All shipped requirements moved to Validated in PROJECT.md
623
+ - [ ] PROJECT.md full evolution review completed (flat mode only; skipped under `--ws`)
624
+ - [ ] All shipped requirements moved to Validated in PROJECT.md (flat mode only; skipped under `--ws`)
739
625
  - [ ] Key Decisions updated with outcomes
740
626
  - [ ] ROADMAP.md Backlog section extracted before rewrite, re-appended after (skipped if absent)
741
627
  - [ ] ROADMAP.md reorganized with milestone grouping (overwritten in place, not deleted)
@@ -744,7 +630,8 @@ Milestone completion is successful when:
744
630
  - [ ] Safety commit made (archive files + updated ROADMAP.md) BEFORE deleting REQUIREMENTS.md
745
631
  - [ ] REQUIREMENTS.md removed via `git rm` (fresh for next milestone, history preserved)
746
632
  - [ ] STATE.md updated with fresh project reference
747
- - [ ] Git tag created (v[X.Y]) (if `git.create_tag` enabled)
633
+ - [ ] Git tag created (v[X.Y]) (if `git.create_tag` enabled and `PER_REPO_TAGGING` is not `true`)
634
+ - [ ] Release map archived and per-repository tags created (if `PER_REPO_TAGGING` is `true`); no tag pushed without a per-repository confirmation
748
635
  - [ ] Milestone commit made (includes archive files and deletion)
749
636
  - [ ] Requirements completion checked against REQUIREMENTS.md traceability table
750
637
  - [ ] Incomplete requirements surfaced with proceed/audit/abort options
@@ -85,7 +85,7 @@ Spawning parallel debug agents to investigate root causes:
85
85
  | Delete removes comment | blocker |
86
86
 
87
87
  Each agent will:
88
- 1. Create DEBUG-{slug}.md with symptoms pre-filled
88
+ 1. Create .planning/debug/{slug}.md with symptoms pre-filled
89
89
  2. Investigate autonomously (read code, form hypotheses, test)
90
90
  3. Return root cause
91
91
 
@@ -147,7 +147,32 @@ return before spawning the next. Fanning out unisolated debuggers is the outcome
147
147
  `orchestrator-worktree` degrade exists to avoid; degrading the flag while keeping the
148
148
  parallelism would announce sequential mode and then do the opposite.
149
149
 
150
- For each gap, fill the debug-subagent-prompt template and spawn:
150
+ For each gap, fill this prompt (the `Template placeholders` below define every `{…}` field) as `filled_debug_prompt`, then spawn:
151
+
152
+ ```markdown
153
+ <objective>
154
+ Investigate issue: {slug}
155
+
156
+ **Summary:** {truth}
157
+ </objective>
158
+
159
+ <symptoms>
160
+ expected: {expected}
161
+ actual: {actual}
162
+ errors: {errors}
163
+ reproduction: {reproduction}
164
+ timeline: {timeline}
165
+ </symptoms>
166
+
167
+ <mode>
168
+ symptoms_prefilled: true
169
+ goal: find_root_cause_only
170
+ </mode>
171
+
172
+ <debug_file>
173
+ Create: .planning/debug/{slug}.md
174
+ </debug_file>
175
+ ```
151
176
 
152
177
  Print: `◆ Spawning diagnostics agent... (each runs in a subagent — no output until they return, ~1–5 min; expected, not a freeze)`
153
178
 
@@ -173,7 +198,7 @@ placeholder, not a shell variable.
173
198
 
174
199
  ```
175
200
  Agent(
176
- prompt=filled_debug_subagent_prompt + "\n\n" + WORKTREE_GUARD + "\n\n<required_reading>\n- {phase_dir}/{phase_num}-UAT.md\n- {state_path}\n</required_reading>\n${AGENT_SKILLS_DEBUGGER}",
201
+ prompt=filled_debug_prompt + "\n\n" + WORKTREE_GUARD + "\n\n<required_reading>\n- {phase_dir}/{phase_num}-UAT.md\n- {state_path}\n</required_reading>\n${AGENT_SKILLS_DEBUGGER}",
177
202
  subagent_type="gsd-debugger",
178
203
  model="{DEBUGGER_MODEL}",
179
204
  {harnessFlag}
@@ -192,7 +217,6 @@ Template placeholders:
192
217
  - `{errors}`: Any error messages from UAT (or "None reported")
193
218
  - `{reproduction}`: "Test {test_num} in UAT"
194
219
  - `{timeline}`: "Discovered during UAT"
195
- - `{goal}`: `find_root_cause_only` (UAT flow - plan-phase --gaps handles fixes)
196
220
  - `{slug}`: Generated from truth
197
221
  </step>
198
222
 
@@ -298,7 +322,7 @@ Agents only diagnose—plan-phase --gaps handles fixes (no fix application).
298
322
  - Report incomplete diagnosis
299
323
 
300
324
  **Agent times out:**
301
- - Check DEBUG-{slug}.md for partial progress
325
+ - Check .planning/debug/{slug}.md for partial progress
302
326
  - Can resume with /gsd:debug
303
327
 
304
328
  **All agents fail:**
@@ -21,7 +21,7 @@ The power user mode generates ALL questions upfront into machine-readable
21
21
  and human-friendly files, then waits for the user to answer at their own
22
22
  pace before processing all answers in a single pass.
23
23
 
24
- 1. Run the same phase analysis (gray area identification) as standard mode
24
+ 1. Load the phase SPEC (`check_spec`, from the init facts `has_spec` / `spec_path`), then run the same phase analysis (gray area identification) as standard mode, about HOW only when a SPEC locks the requirements
25
25
  2. Write all questions to
26
26
  `{phase_dir}/{padded_phase}-QUESTIONS.json` and
27
27
  `{phase_dir}/{padded_phase}-QUESTIONS.html`
@@ -82,7 +82,7 @@ ANALYZER_MODEL=$(gsd_run query resolve-model gsd-assumptions-analyzer --raw)
82
82
 
83
83
  Parse JSON for: `commit_docs`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`,
84
84
  `phase_slug`, `padded_phase`, `has_research`, `has_context`, `has_plans`, `has_verification`,
85
- `plan_count`, `roadmap_exists`, `planning_exists`.
85
+ `plan_count`, `roadmap_exists`, `planning_exists`, `has_spec`, `spec_path`.
86
86
 
87
87
  **If `phase_found` is false:**
88
88
  ```
@@ -92,7 +92,7 @@ Use /gsd:progress to see available phases.
92
92
  ```
93
93
  Exit workflow.
94
94
 
95
- **If `phase_found` is true:** Continue to check_existing.
95
+ **If `phase_found` is true:** Continue to check_spec.
96
96
 
97
97
  **Auto mode** — If `--auto` is present in ARGUMENTS:
98
98
  - In `check_existing`: auto-select "Update it" (if context exists) or continue without prompting
@@ -102,6 +102,21 @@ Exit workflow.
102
102
  - After completion, auto-advance to plan-phase
103
103
  </step>
104
104
 
105
+ <step name="check_spec">
106
+ Check whether the phase has a SPEC.md (from the spec-phase workflow). SPEC.md locks requirements before implementation decisions. Init already resolved it: use `has_spec` and `spec_path`, which come from one shared definition of "the phase SPEC" (a plain `*-SPEC.md`, never `*-AI-SPEC.md` or `*-UI-SPEC.md`). Do not glob for it.
107
+
108
+ **If `has_spec` is true:**
109
+ 1. Read the SPEC.md file at `spec_path`.
110
+ 2. Count requirements (numbered items in `## Requirements`).
111
+ 3. Display: `Found SPEC.md — {N} requirements locked. Focusing on implementation decisions.`
112
+ 4. Set `spec_loaded = true`.
113
+ 5. Store requirements, boundaries, and acceptance criteria as `<locked_requirements>` — these flow directly into CONTEXT.md without re-asking.
114
+
115
+ **If `has_spec` is false:** Continue with `spec_loaded = false`.
116
+
117
+ **Note:** `*-AI-SPEC.md` (from the ai-integration-phase workflow) and `*-UI-SPEC.md` (from the ui-phase workflow) are different artifacts and never count as the phase SPEC.
118
+ </step>
119
+
105
120
  <step name="check_existing">
106
121
  Check if CONTEXT.md already exists using `has_context` from init.
107
122
 
@@ -280,6 +295,7 @@ Phase goal: {roadmap_description}
280
295
  Prior decisions: {prior_decisions_summary}
281
296
  Codebase scout hints: {codebase_context_summary}
282
297
  Calibration: {calibration_tier}
298
+ Locked requirements (already answered by SPEC.md; omit this line when spec_loaded = false): {locked_requirements}
283
299
 
284
300
  Your job:
285
301
  1. Read ROADMAP.md phase {PHASE} description
@@ -287,6 +303,7 @@ Your job:
287
303
  3. Glob/Grep for files related to: {phase_relevant_terms}
288
304
  4. Read 5-15 most relevant source files
289
305
  5. Return structured assumptions
306
+ 6. When locked requirements are given, treat them as decided: form assumptions about HOW to implement them only, never about WHAT to build or WHY
290
307
 
291
308
  ## Output Format
292
309
 
@@ -437,6 +454,7 @@ Map assumptions to CONTEXT.md sections:
437
454
  - Areas where all assumptions were Confident → marked as locked decisions
438
455
  - Areas with corrections → include user's chosen alternative as the decision
439
456
  - Folded todos → included in `<decisions>` under "### Folded Todos"
457
+ - When `spec_loaded = true`: add `<spec_lock>` immediately after `<domain>`, add the SPEC.md file to `<canonical_refs>` with the note "Locked requirements — MUST read before planning", and do NOT copy SPEC.md requirements into `<decisions>` (agents read SPEC.md directly); `<decisions>` holds only the HOW decisions from this discussion
440
458
 
441
459
  ```markdown
442
460
  # Phase {PHASE}: {phase_name} - Context
@@ -450,6 +468,19 @@ Map assumptions to CONTEXT.md sections:
450
468
  {Domain boundary from ROADMAP.md — clear statement of scope anchor}
451
469
  </domain>
452
470
 
471
+ [If spec_loaded = true, insert this section:]
472
+ <spec_lock>
473
+ ## Requirements (locked via SPEC.md)
474
+
475
+ **{N} requirements are locked.** See `{padded_phase}-SPEC.md` for full requirements, boundaries, and acceptance criteria.
476
+
477
+ Downstream agents MUST read `{padded_phase}-SPEC.md` before planning or implementing. Requirements are not duplicated here.
478
+
479
+ **In scope (from SPEC.md):** [copy the "In scope" bullet list from SPEC.md Boundaries]
480
+ **Out of scope (from SPEC.md):** [copy the "Out of scope" bullet list from SPEC.md Boundaries]
481
+
482
+ </spec_lock>
483
+
453
484
  <decisions>
454
485
  ## Implementation Decisions
455
486
 
@@ -11,18 +11,33 @@ This workflow executes when `--power` flag is present in ARGUMENTS to `/gsd:disc
11
11
 
12
12
  The caller (discuss-phase.md) has already:
13
13
  - Validated the phase exists
14
- - Provided init context: `phase_dir`, `padded_phase`, `phase_number`, `phase_name`, `phase_slug`
14
+ - Provided init context: `phase_dir`, `padded_phase`, `phase_number`, `phase_name`, `phase_slug`, `has_spec`, `spec_path`
15
15
 
16
16
  Begin at **Step 1** immediately.
17
17
  </trigger>
18
18
 
19
+ <step name="check_spec">
20
+ Check whether the phase has a SPEC.md (from the spec-phase workflow). SPEC.md locks requirements before implementation decisions. Init already resolved it: use `has_spec` and `spec_path`, which come from one shared definition of "the phase SPEC" (a plain `*-SPEC.md`, never `*-AI-SPEC.md` or `*-UI-SPEC.md`). Do not glob for it.
21
+
22
+ **If `has_spec` is true:**
23
+ 1. Read the SPEC.md file at `spec_path`.
24
+ 2. Count requirements (numbered items in `## Requirements`).
25
+ 3. Display: `Found SPEC.md — {N} requirements locked. Focusing on implementation decisions.`
26
+ 4. Set `spec_loaded = true`.
27
+ 5. Store requirements, boundaries, and acceptance criteria as `<locked_requirements>` — these flow directly into CONTEXT.md without re-asking.
28
+
29
+ **If `has_spec` is false:** Continue with `spec_loaded = false`.
30
+
31
+ **Note:** `*-AI-SPEC.md` (from the ai-integration-phase workflow) and `*-UI-SPEC.md` (from the ui-phase workflow) are different artifacts and never count as the phase SPEC.
32
+ </step>
33
+
19
34
  <step name="analyze">
20
35
  Run the same gray area identification as standard discuss-phase mode.
21
36
 
22
37
  1. Load prior context (PROJECT.md, REQUIREMENTS.md, STATE.md, prior CONTEXT.md files)
23
38
  2. Scout codebase for reusable assets and patterns relevant to this phase
24
39
  3. Read the phase goal from ROADMAP.md
25
- 4. Identify ALL gray areas — specific implementation decisions the user should weigh in on
40
+ 4. Identify ALL gray areas — specific implementation decisions the user should weigh in on. If `spec_loaded = true`, the locked requirements are pre-answered: identify gray areas about HOW to implement only, never about WHAT to build or WHY
26
41
  5. For each gray area, generate 2–4 concrete options with tradeoff descriptions
27
42
 
28
43
  Group questions by topic into sections (e.g., "Visual Style", "Data Model", "Interactions", "Error Handling"). Each section should have 2–6 questions.
@@ -257,6 +272,8 @@ Process all answered questions from the JSON file and generate CONTEXT.md.
257
272
  - Status: "Decided" if fully answered, "Needs clarification" if only chat_more with no option selected
258
273
 
259
274
  5. Write CONTEXT.md using the standard context template format:
275
+ - `<spec_lock>` section immediately after `<domain>` when `spec_loaded = true` (template: `discuss-phase/templates/context.md`); do NOT copy SPEC.md requirements into `<decisions>`
276
+ - the SPEC.md file in `<canonical_refs>` with the note "Locked requirements — MUST read before planning" when `spec_loaded = true`
260
277
  - `<decisions>` section with all answered questions grouped by section
261
278
  - `<deferred_ideas>` section for unanswered questions (carry forward for future discussion)
262
279
  - `<specifics>` section for any chat_more content that adds nuance
@@ -125,7 +125,7 @@ INIT=$(gsd_run query init.phase-op ${GSD_WS:+--ws=${GSD_WS##* }} "${PHASE}"); [[
125
125
  AGENT_SKILLS_ADVISOR=$(gsd_run query agent-skills gsd-advisor-researcher ${GSD_WS:+--ws=${GSD_WS##* }})
126
126
  ```
127
127
 
128
- Parse JSON for: `commit_docs`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `has_research`, `has_context`, `has_plans`, `has_verification`, `plan_count`, `roadmap_exists`, `planning_exists`, `response_language`.
128
+ Parse JSON for: `commit_docs`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `has_research`, `has_context`, `has_plans`, `has_verification`, `plan_count`, `roadmap_exists`, `planning_exists`, `has_spec`, `spec_path`, `response_language`.
129
129
 
130
130
  **If `response_language` is set:** All user-facing output of this workflow — narration between tool calls, status updates, progress notes, findings, questions, prompts, and explanations — MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
131
131
 
@@ -183,22 +183,18 @@ Write these answers inline before continuing. If a blocking anti-pattern cannot
183
183
  </step>
184
184
 
185
185
  <step name="check_spec">
186
- Check if a SPEC.md (from `/gsd:spec-phase`) exists for this phase. SPEC.md locks requirements before implementation decisions.
186
+ Check whether the phase has a SPEC.md (from the spec-phase workflow). SPEC.md locks requirements before implementation decisions. Init already resolved it: use `has_spec` and `spec_path`, which come from one shared definition of "the phase SPEC" (a plain `*-SPEC.md`, never `*-AI-SPEC.md` or `*-UI-SPEC.md`). Do not glob for it.
187
187
 
188
- ```bash
189
- ls ${phase_dir}/*-SPEC.md 2>/dev/null | grep -v AI-SPEC | head -1 || true
190
- ```
191
-
192
- **If SPEC.md is found:**
193
- 1. Read the SPEC.md file.
188
+ **If `has_spec` is true:**
189
+ 1. Read the SPEC.md file at `spec_path`.
194
190
  2. Count requirements (numbered items in `## Requirements`).
195
191
  3. Display: `Found SPEC.md — {N} requirements locked. Focusing on implementation decisions.`
196
192
  4. Set `spec_loaded = true`.
197
193
  5. Store requirements, boundaries, and acceptance criteria as `<locked_requirements>` — these flow directly into CONTEXT.md without re-asking.
198
194
 
199
- **If no SPEC.md is found:** Continue with `spec_loaded = false`.
195
+ **If `has_spec` is false:** Continue with `spec_loaded = false`.
200
196
 
201
- **Note:** SPEC.md files named `AI-SPEC.md` (from `/gsd:ai-integration-phase`) are excluded — different purpose.
197
+ **Note:** `*-AI-SPEC.md` (from the ai-integration-phase workflow) and `*-UI-SPEC.md` (from the ui-phase workflow) are different artifacts and never count as the phase SPEC.
202
198
  </step>
203
199
 
204
200
  <step name="check_existing">
@@ -1,6 +1,6 @@
1
- # Per-plan worktree decision (#2772)
2
-
3
- Run this for **each plan in the current wave** before its `Agent()` dispatch. The output `USE_WORKTREES_FOR_PLAN` gates the dispatch branch (worktree mode vs sequential mode) for that plan only — other plans in the same wave can still take the worktree path.
1
+ # Per-plan worktree decision (#2772) and per-dispatch isolation record (#3045, #5516)
2
+ ## Part 1 — Decide (run for each plan in the wave, up front, at `execute_waves` step 2.5)
3
+ This gate has two parts that run at **different times**. **Part 1** (this part) decides, for every plan in the wave, whether it uses worktree isolation, and stores each plan's answer; it runs for the whole wave before any dispatch. **Part 2** (below) writes the plan-scoped isolation record and runs once per plan, immediately before that plan's `Agent()` dispatch in step 3. The output `USE_WORKTREES_FOR_PLAN` gates the dispatch branch (worktree mode vs sequential mode) for that plan only — other plans in the same wave can still take the worktree path.
4
4
 
5
5
  `SUBMODULE_PATHS` is computed once in the `initialize` step (parsed from `.gitmodules`).
6
6
 
@@ -115,23 +115,29 @@ fi
115
115
 
116
116
  After running this for the plan, the dispatch branches in `execute_waves` step 3 MUST gate on `USE_WORKTREES_FOR_PLAN` for the current plan, not on the project-level `USE_WORKTREES`. Track which plans in this wave actually used worktrees (append `plan_id` to a `WAVE_WORKTREE_PLANS` accumulator when `USE_WORKTREES_FOR_PLAN != false`) — the post-wave cleanup step (5.5) uses this to decide whether worktree-merge cleanup is needed at all.
117
117
 
118
- **Re-record the dispatch-isolation sentinel, scoped to THIS plan (#3045 BLOCKER 1):**
118
+ **Store the decision per plan (#5516).** `USE_WORKTREES_FOR_PLAN` is one shared value: the next plan's decision overwrites it. Keep each plan's answer as `plan_id → value` (for example `WAVE_PLAN_ISOLATION="03-01-api=false 03-02-docs=true"`) so step 3 can restore the dispatched plan's own value just before its dispatch (the value after `<plan_id>=`). `PLAN_FILES` and `PLAN_DELETIONS` above are shared the same way, and step 3 passes them to `worktree.record-agent` / `worktree.create`: re-run the extraction block above on the dispatched plan's JSON to restore them. This part does **not** write the isolation record.
119
+
120
+ ## Part 2 — Re-record the dispatch-isolation sentinel, scoped to THIS plan (#3045 BLOCKER 1, #5516)
121
+
122
+ Run this in `execute_waves` step 3, **immediately before dispatching THIS plan**, after restoring that plan's **stored decision** from Part 1 (`plan_id` := this plan's `id`, `USE_WORKTREES_FOR_PLAN` := the value stored for it, and `PLAN_FILES` / `PLAN_DELETIONS` re-extracted from this plan's JSON). Never run it at step 2.5 and never for a plan other than the one about to dispatch: the sentinel is a single slot, so recording every plan up front leaves only the wave's last plan in it, and every earlier plan is dispatched against a record naming a different plan (the isolation guard discards it and its registry fallback denies a sequential dispatch the plan's own decision allowed, #5516).
119
123
 
120
- The phase-level sentinel (written by the "Resolve ISOLATION" step, before any per-plan decision exists) authorizes/denies at the PHASE level. This per-plan gate can override that decision (submodule intersection forcing `USE_WORKTREES_FOR_PLAN=false` on an otherwise harness-worktree phase) — without a fresh, plan-scoped re-record, the isolation guard hooks would still be reading the STALE phase-level `harness-worktree` sentinel when this plan's dispatch omits the isolation kwarg (correctly, since it isn't worktree-isolated), producing a false DENY; or, symmetrically, a plan-level submodule degrade elsewhere in the wave could leave a stale `none` sentinel that a LATER, genuinely harness-worktree plan's own dispatch could be misread against. Run this immediately before dispatching THIS plan (right after computing `USE_WORKTREES_FOR_PLAN` above), so the sentinel is always fresh at the moment of dispatch and always keyed to the plan it authorizes:
124
+ The phase-level sentinel (written by the "Resolve ISOLATION" step, before any per-plan decision exists) authorizes/denies at the PHASE level. The per-plan decision can override that (submodule intersection forcing `USE_WORKTREES_FOR_PLAN=false` on an otherwise harness-worktree phase) — without a fresh, plan-scoped record at dispatch time, the isolation guard hooks would still be reading the STALE phase-level `harness-worktree` sentinel when this plan's dispatch omits the isolation kwarg (correctly, since it isn't worktree-isolated), producing a false DENY; or, symmetrically, a plan-level degrade elsewhere in the wave could leave a stale `none` sentinel that a LATER, genuinely harness-worktree plan's own dispatch could be misread against. Running it right before the dispatch keeps the sentinel always fresh and always keyed to the plan it authorizes:
121
125
 
122
126
  ```bash
123
127
  _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
124
- if [ "$USE_WORKTREES_FOR_PLAN" = "false" ]; then
128
+ if [ "${USE_WORKTREES_FOR_PLAN:-}" = "false" ]; then
125
129
  # Submodule intersection (or an inherited USE_WORKTREES=false) forces
126
130
  # sequential dispatch for this plan specifically — force the resolver's
127
131
  # single write path to record `none`, scoped to this plan, even though the
128
132
  # phase/registry would otherwise resolve harness-worktree.
129
133
  gsd_run query dispatch-isolation --raw --phase "${PHASE_NUMBER:-}" --plan "$plan_id" --force-isolation none >/dev/null 2>&1 || true
130
- else
134
+ elif [ -n "${USE_WORKTREES_FOR_PLAN:-}" ]; then
131
135
  # No plan-level override — re-resolve normally, still scoped to this plan,
132
136
  # so the sentinel's `plan` field always matches the plan about to dispatch.
133
137
  gsd_run query dispatch-isolation --raw --phase "${PHASE_NUMBER:-}" --plan "$plan_id" >/dev/null 2>&1 || true
134
138
  fi
139
+ # An EMPTY value (the plan state was lost with an earlier tool call's shell) writes
140
+ # nothing, so a recorded phase-level degrade is never re-persisted as harness-worktree (#5479).
135
141
  ```
136
142
 
137
143
  **`PLAN_FILES` is reused after dispatch (#2596):** pass it as `--files "$PLAN_FILES"` on the step-3 `worktree.record-agent` call (and on `worktree.create` in the orchestrator-worktree path) so the post-wave cleanup gauntlet can compare each plan branch's actual committed diff against the scope the plan declared, and report any path outside it. That check is advisory — it warns, it never blocks the merge — and omitting the flag simply skips it for that plan.
@@ -55,7 +55,10 @@ if [ -z "$BUILD_CMD" ]; then
55
55
  elif [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then
56
56
  BUILD_CMD="python -m py_compile $(find . -name '*.py' -not -path './.planning/*' -not -path './node_modules/*' | head -20 | tr '\n' ' ')"
57
57
  elif [ -f "package.json" ] && grep -q '"build"' package.json; then
58
- BUILD_CMD="npm run build"
58
+ # #5346: the project's own package manager (packageManager field, then lockfile), npm if unresolved.
59
+ BUILD_CMD=$(gsd_run query resolve-package-manager build --cwd . 2>/dev/null || echo "npm run build")
60
+ [ -n "$BUILD_CMD" ] || BUILD_CMD="npm run build"
61
+ echo "⚠ Build command not configured — running this project's build script (${BUILD_CMD}). Set workflow.build_command to pin it."
59
62
  else
60
63
  BUILD_CMD=""
61
64
  echo "⚠ No build command detected — skipping build gate"
@@ -122,7 +125,9 @@ if [ -z "$TEST_CMD" ]; then
122
125
  elif [ -f "Justfile" ] || [ -f "justfile" ]; then
123
126
  TEST_CMD="just test"
124
127
  elif [ -f "package.json" ]; then
125
- TEST_CMD="npm test"
128
+ # #5346: same resolver as the build gate.
129
+ TEST_CMD=$(gsd_run query resolve-package-manager test --cwd . 2>/dev/null || echo "npm test")
130
+ [ -n "$TEST_CMD" ] || TEST_CMD="npm test"
126
131
  elif [ -f "Cargo.toml" ]; then
127
132
  TEST_CMD="cargo test"
128
133
  elif [ -f "go.mod" ]; then
@@ -29,7 +29,8 @@ if [ -z "$REG_TEST_CMD" ]; then
29
29
  elif [ -f "Justfile" ] || [ -f "justfile" ]; then
30
30
  REG_TEST_CMD="just test"
31
31
  elif [ -f "package.json" ]; then
32
- REG_TEST_CMD="npm test"
32
+ REG_TEST_CMD=$(gsd_run query resolve-package-manager test --cwd . 2>/dev/null || echo "npm test")
33
+ [ -n "$REG_TEST_CMD" ] || REG_TEST_CMD="npm test"
33
34
  elif [ -f "Cargo.toml" ]; then
34
35
  REG_TEST_CMD="cargo test"
35
36
  elif [ -f "go.mod" ]; then
@@ -89,7 +89,7 @@ advisory throughout: it never blocks.
89
89
 
90
90
  **Error handling:** If the Skill invocation fails or throws, catch the error, display "Code review encountered an error (non-blocking): {error}" and proceed to gate dispatch. Review failures must never block execution.
91
91
 
92
- **Execute:post gate hook dispatch.** After code review, dispatch all active gate hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "gate"`. ⚠ **Validate `check` before shell use** (third-party manifest input) — `loop-hook-dispatch.md` § `gate`. For each, run the form below, or — for a `predicate` gate (ADR-2008 / #2008) — `gsd_run check predicate --predicate '<predicate JSON>' --phase-number "${PHASE_NUMBER}" --raw`:
92
+ **Execute:post gate hook dispatch.** After code review, dispatch all active gate hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "gate"`. ⚠ **Validate `check` before shell use** (third-party manifest input; wherever `${hook.check.query}` appears, write the dot-normalized query, each `.` as `-`, and validate and pass that same value) — `loop-hook-dispatch.md` § `gate`. For each, run the form below, or — for a `predicate` gate (ADR-2008 / #2008) — `gsd_run check predicate --predicate '<predicate JSON>' --phase-dir "${PHASE_DIR}" --phase-number "${PHASE_NUMBER}" --raw`:
93
93
 
94
94
  ```bash
95
95
  GATE_RESULT=$(gsd_run check ${hook.check.query} "${PHASE_NUMBER}" --raw) && CHECK_EXIT=0 || CHECK_EXIT=$?
@@ -99,7 +99,7 @@ GATE_RESULT=$(gsd_run check ${hook.check.query} "${PHASE_NUMBER}" --raw) && CHEC
99
99
 
100
100
  **Gate evaluation** uses the same two-step contract as the `execute:wave:post` gates (`execute-phase/steps/wave-post-gate-hooks.md`).
101
101
 
102
- **TDD review escalation (overrides the advisory default for the `tdd.review-checkpoint` gate only).** The tdd `execute:post` gate is declared `blocking: false`, so by the generic contract above it displays its `message`/table and continues. There is ONE documented exception (see `~/.claude/gsd-core/references/execute-mvp-tdd.md`): when `TDD_MODE=true` AND `GATE_RESULT.block == true` (one or more TDD plans miss a RED or GREEN gate commit; #4011 — no MVP condition), the end-of-phase TDD review escalates from advisory to **blocking under TDD** — refuse to mark the phase complete and present:
102
+ **TDD review escalation (overrides the advisory default for the `tdd.review-checkpoint` gate only).** The tdd `execute:post` gate is declared `blocking: false`, so by the generic contract above it displays its `message`/table and continues. There is ONE documented exception (see `~/.claude/gsd-core/references/execute-mvp-tdd.md`): when `TDD_MODE=true` AND `GATE_RESULT.block == true` (one or more TDD plans miss a RED or GREEN gate commit, or have no GREEN commit that follows a RED commit — `reason: green_before_red`, #5275; #4011 — no MVP condition), the end-of-phase TDD review escalates from advisory to **blocking under TDD** — refuse to mark the phase complete and present:
103
103
 
104
104
  ```
105
105
  Phase blocked: {N} TDD plan(s) violate the RED→GREEN gate sequence under TDD.