@opengsd/gsd-core 1.11.0 → 1.12.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 (395) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/agents/gsd-code-fixer.md +1 -1
  4. package/agents/gsd-debug-session-manager.md +1 -1
  5. package/agents/gsd-debugger.md +1 -1
  6. package/agents/gsd-dom-verifier.md +169 -0
  7. package/agents/gsd-eval-auditor.md +1 -1
  8. package/agents/gsd-executor.md +17 -9
  9. package/agents/gsd-framework-selector.md +1 -3
  10. package/agents/gsd-intel-updater.md +1 -1
  11. package/agents/gsd-mempalace-curator.md +0 -1
  12. package/agents/gsd-pattern-mapper.md +11 -0
  13. package/agents/gsd-phase-researcher.md +3 -1
  14. package/agents/gsd-plan-checker.md +15 -55
  15. package/agents/gsd-planner.md +6 -4
  16. package/agents/gsd-project-researcher.md +1 -1
  17. package/agents/gsd-research-synthesizer.md +2 -2
  18. package/agents/gsd-roadmapper.md +15 -11
  19. package/agents/gsd-ui-checker.md +63 -4
  20. package/agents/gsd-ui-researcher.md +41 -3
  21. package/agents/gsd-verifier.md +1 -1
  22. package/bin/install.js +609 -134
  23. package/commands/gsd/discuss-phase.md +1 -1
  24. package/commands/gsd/import.md +1 -1
  25. package/commands/gsd/quick.md +8 -4
  26. package/gsd-core/bin/gsd-tools.cjs +567 -51
  27. package/gsd-core/bin/lib/active-workstream-store.cjs +8 -0
  28. package/gsd-core/bin/lib/adr-parser.cjs +13 -7
  29. package/gsd-core/bin/lib/agent-install-check.cjs +162 -0
  30. package/gsd-core/bin/lib/api-coverage.cjs +30 -9
  31. package/gsd-core/bin/lib/artifacts.cjs +2 -0
  32. package/gsd-core/bin/lib/assumption-delta.cjs +30 -11
  33. package/gsd-core/bin/lib/audit.cjs +163 -41
  34. package/gsd-core/bin/lib/broken-windows.cjs +306 -28
  35. package/gsd-core/bin/lib/capability-lock.cjs +10 -4
  36. package/gsd-core/bin/lib/capability-registry.cjs +336 -95
  37. package/gsd-core/bin/lib/capability-state.cjs +18 -3
  38. package/gsd-core/bin/lib/capability-validator.cjs +205 -18
  39. package/gsd-core/bin/lib/check-command-router.cjs +145 -5
  40. package/gsd-core/bin/lib/cli-exit.cjs +496 -10
  41. package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
  42. package/gsd-core/bin/lib/codex-agent-toml.cjs +410 -4
  43. package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
  44. package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
  45. package/gsd-core/bin/lib/commands.cjs +543 -44
  46. package/gsd-core/bin/lib/complexity-trigger.cjs +26 -6
  47. package/gsd-core/bin/lib/config-loader.cjs +118 -29
  48. package/gsd-core/bin/lib/config.cjs +92 -2
  49. package/gsd-core/bin/lib/configuration.cjs +129 -37
  50. package/gsd-core/bin/lib/core-utils.cjs +84 -7
  51. package/gsd-core/bin/lib/edge-probe.cjs +9 -1
  52. package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
  53. package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
  54. package/gsd-core/bin/lib/frontmatter.cjs +840 -305
  55. package/gsd-core/bin/lib/gap-checker.cjs +27 -3
  56. package/gsd-core/bin/lib/git-base-branch.cjs +174 -39
  57. package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +7 -3
  58. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +6 -3
  59. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +22 -8
  60. package/gsd-core/bin/lib/health-diagnostic.cjs +23 -3
  61. package/gsd-core/bin/lib/host-integration.cjs +39 -6
  62. package/gsd-core/bin/lib/init-command-router.cjs +118 -21
  63. package/gsd-core/bin/lib/init.cjs +120 -41
  64. package/gsd-core/bin/lib/install-engine.cjs +68 -3
  65. package/gsd-core/bin/lib/install-model-override-resolver.cjs +33 -1
  66. package/gsd-core/bin/lib/install-profiles.cjs +78 -4
  67. package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
  68. package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
  69. package/gsd-core/bin/lib/installer-migrations.cjs +10 -7
  70. package/gsd-core/bin/lib/intel.cjs +101 -26
  71. package/gsd-core/bin/lib/io.cjs +160 -15
  72. package/gsd-core/bin/lib/learnings.cjs +85 -14
  73. package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
  74. package/gsd-core/bin/lib/markdown-table.cjs +52 -4
  75. package/gsd-core/bin/lib/milestone.cjs +90 -5
  76. package/gsd-core/bin/lib/model-catalog.cjs +177 -19
  77. package/gsd-core/bin/lib/model-resolver.cjs +10 -28
  78. package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
  79. package/gsd-core/bin/lib/phase-estimation.cjs +17 -8
  80. package/gsd-core/bin/lib/phase-id.cjs +70 -4
  81. package/gsd-core/bin/lib/phase-lifecycle.cjs +24 -16
  82. package/gsd-core/bin/lib/phase-locator.cjs +138 -17
  83. package/gsd-core/bin/lib/phase.cjs +405 -84
  84. package/gsd-core/bin/lib/plan-document.cjs +263 -0
  85. package/gsd-core/bin/lib/plan-scan.cjs +13 -2
  86. package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
  87. package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
  88. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -14
  89. package/gsd-core/bin/lib/planning-workspace.cjs +56 -0
  90. package/gsd-core/bin/lib/probe-core.cjs +4 -1
  91. package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
  92. package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
  93. package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
  94. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +71 -45
  95. package/gsd-core/bin/lib/review-lane-descriptor.cjs +9 -9
  96. package/gsd-core/bin/lib/roadmap-command-router.cjs +45 -31
  97. package/gsd-core/bin/lib/roadmap-parser.cjs +79 -16
  98. package/gsd-core/bin/lib/roadmap.cjs +74 -19
  99. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +96 -8
  100. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +34 -1
  101. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +287 -55
  102. package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
  103. package/gsd-core/bin/lib/runtime-slash.cjs +72 -2
  104. package/gsd-core/bin/lib/shell-command-projection.cjs +71 -8
  105. package/gsd-core/bin/lib/smart-entry.cjs +12 -22
  106. package/gsd-core/bin/lib/spec-section.cjs +12 -7
  107. package/gsd-core/bin/lib/state-command-router.cjs +47 -18
  108. package/gsd-core/bin/lib/state-contract.cjs +359 -0
  109. package/gsd-core/bin/lib/state-document.cjs +186 -0
  110. package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
  111. package/gsd-core/bin/lib/state-transition.cjs +517 -101
  112. package/gsd-core/bin/lib/state.cjs +946 -163
  113. package/gsd-core/bin/lib/surface.cjs +10 -2
  114. package/gsd-core/bin/lib/task-command-router.cjs +111 -1
  115. package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
  116. package/gsd-core/bin/lib/teams-status.cjs +4 -1
  117. package/gsd-core/bin/lib/uat-predicate.cjs +58 -20
  118. package/gsd-core/bin/lib/uat.cjs +1376 -125
  119. package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
  120. package/gsd-core/bin/lib/ui-safety-gate.cjs +37 -7
  121. package/gsd-core/bin/lib/unusable-input.cjs +13 -0
  122. package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
  123. package/gsd-core/bin/lib/vendor/README.md +43 -5
  124. package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
  125. package/gsd-core/bin/lib/verification.cjs +14 -1
  126. package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
  127. package/gsd-core/bin/lib/verify.cjs +95 -40
  128. package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
  129. package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
  130. package/gsd-core/bin/lib/worktree-safety.cjs +177 -21
  131. package/gsd-core/bin/shared/config-defaults.manifest.json +7 -1
  132. package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
  133. package/gsd-core/bin/shared/exit-codes.json +8 -0
  134. package/gsd-core/bin/shared/exit-codes.sh +20 -0
  135. package/gsd-core/bin/shared/model-catalog.json +8 -1
  136. package/gsd-core/references/agent-contracts.md +3 -2
  137. package/gsd-core/references/api-coverage.md +24 -2
  138. package/gsd-core/references/autonomous-smart-discuss.md +3 -3
  139. package/gsd-core/references/checkpoints.md +37 -19
  140. package/gsd-core/references/decimal-phase-calculation.md +5 -5
  141. package/gsd-core/references/edge-probe.md +8 -0
  142. package/gsd-core/references/execute-mvp-tdd.md +1 -3
  143. package/gsd-core/references/execute-phase-between-wave-reset.md +9 -12
  144. package/gsd-core/references/execute-phase-wave-guard.md +11 -9
  145. package/gsd-core/references/failing-direction.md +78 -0
  146. package/gsd-core/references/gate-prompts.md +1 -1
  147. package/gsd-core/references/git-integration.md +5 -5
  148. package/gsd-core/references/git-planning-commit.md +3 -3
  149. package/gsd-core/references/gsd-run-resolver.md +1 -1
  150. package/gsd-core/references/loop-hook-dispatch.md +22 -0
  151. package/gsd-core/references/model-profiles.md +1 -1
  152. package/gsd-core/references/nyquist-compliance.md +74 -0
  153. package/gsd-core/references/offer-next.md +3 -5
  154. package/gsd-core/references/phase-argument-parsing.md +3 -3
  155. package/gsd-core/references/planner-failing-direction.md +53 -0
  156. package/gsd-core/references/planner-human-verify-mode.md +15 -1
  157. package/gsd-core/references/planner-revision.md +1 -1
  158. package/gsd-core/references/planner-verify-command-grounding.md +17 -0
  159. package/gsd-core/references/planning-config.md +37 -8
  160. package/gsd-core/references/reviewer-instances.md +31 -0
  161. package/gsd-core/references/runtime-aware-dispatch.md +1 -1
  162. package/gsd-core/references/tdd.md +1 -3
  163. package/gsd-core/references/ui-brand.md +65 -21
  164. package/gsd-core/references/ui-consideration-probe.md +1 -1
  165. package/gsd-core/references/universal-anti-patterns.md +2 -2
  166. package/gsd-core/references/verify-command-path-resolvability.md +42 -0
  167. package/gsd-core/references/verify-mvp-mode.md +1 -1
  168. package/gsd-core/references/workstream-flag.md +11 -11
  169. package/gsd-core/templates/README.md +1 -1
  170. package/gsd-core/templates/SECURITY.md +3 -3
  171. package/gsd-core/templates/UI-SPEC.md +25 -3
  172. package/gsd-core/templates/VALIDATION.md +3 -3
  173. package/gsd-core/templates/phase-prompt.md +3 -0
  174. package/gsd-core/templates/state.md +7 -0
  175. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  176. package/gsd-core/workflows/add-backlog.md +1 -1
  177. package/gsd-core/workflows/add-phase.md +3 -3
  178. package/gsd-core/workflows/add-tests.md +3 -8
  179. package/gsd-core/workflows/add-todo.md +1 -1
  180. package/gsd-core/workflows/ai-integration-phase.md +4 -9
  181. package/gsd-core/workflows/audit-fix.md +12 -3
  182. package/gsd-core/workflows/audit-milestone.md +9 -9
  183. package/gsd-core/workflows/audit-uat.md +17 -2
  184. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
  185. package/gsd-core/workflows/autonomous.md +10 -26
  186. package/gsd-core/workflows/check-todos.md +1 -1
  187. package/gsd-core/workflows/cleanup.md +2 -2
  188. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
  189. package/gsd-core/workflows/code-review-fix.md +1 -1
  190. package/gsd-core/workflows/code-review.md +121 -40
  191. package/gsd-core/workflows/complete-milestone.md +15 -10
  192. package/gsd-core/workflows/debug.md +5 -3
  193. package/gsd-core/workflows/diagnose-issues.md +12 -6
  194. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  195. package/gsd-core/workflows/discuss-phase/modes/chain.md +3 -7
  196. package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
  197. package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
  198. package/gsd-core/workflows/discuss-phase-assumptions.md +2 -2
  199. package/gsd-core/workflows/discuss-phase.md +1 -1
  200. package/gsd-core/workflows/do.md +3 -6
  201. package/gsd-core/workflows/docs-update.md +5 -4
  202. package/gsd-core/workflows/edit-phase.md +1 -1
  203. package/gsd-core/workflows/eval-review.md +4 -9
  204. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  205. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +113 -11
  206. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  207. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  208. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  209. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +22 -4
  210. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
  211. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
  212. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
  213. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
  214. package/gsd-core/workflows/execute-phase.md +38 -54
  215. package/gsd-core/workflows/execute-plan.md +17 -12
  216. package/gsd-core/workflows/explore.md +1 -1
  217. package/gsd-core/workflows/extract-learnings.md +1 -1
  218. package/gsd-core/workflows/fast.md +2 -2
  219. package/gsd-core/workflows/forensics.md +1 -1
  220. package/gsd-core/workflows/graduation.md +5 -5
  221. package/gsd-core/workflows/health.md +3 -6
  222. package/gsd-core/workflows/import.md +14 -11
  223. package/gsd-core/workflows/inbox.md +4 -5
  224. package/gsd-core/workflows/ingest-docs.md +44 -11
  225. package/gsd-core/workflows/insert-phase.md +5 -5
  226. package/gsd-core/workflows/list-seeds.md +5 -3
  227. package/gsd-core/workflows/list-workspaces.md +1 -1
  228. package/gsd-core/workflows/manager.md +12 -23
  229. package/gsd-core/workflows/map-codebase.md +1 -1
  230. package/gsd-core/workflows/milestone-summary.md +1 -1
  231. package/gsd-core/workflows/mvp-phase.md +2 -2
  232. package/gsd-core/workflows/new-milestone.md +9 -21
  233. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  234. package/gsd-core/workflows/new-project.md +12 -26
  235. package/gsd-core/workflows/new-workspace.md +1 -1
  236. package/gsd-core/workflows/next.md +2 -2
  237. package/gsd-core/workflows/pause-work.md +1 -1
  238. package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
  239. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
  240. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
  241. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
  242. package/gsd-core/workflows/plan-phase.md +121 -42
  243. package/gsd-core/workflows/plan-review-convergence.md +46 -9
  244. package/gsd-core/workflows/plant-seed.md +2 -2
  245. package/gsd-core/workflows/pr-branch.md +187 -51
  246. package/gsd-core/workflows/profile-user.md +16 -14
  247. package/gsd-core/workflows/progress.md +27 -12
  248. package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
  249. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -3
  250. package/gsd-core/workflows/quick/steps/quick-verification.md +2 -4
  251. package/gsd-core/workflows/quick/steps/research-phase.md +2 -4
  252. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
  253. package/gsd-core/workflows/quick.md +20 -29
  254. package/gsd-core/workflows/remove-phase.md +4 -4
  255. package/gsd-core/workflows/remove-workspace.md +2 -2
  256. package/gsd-core/workflows/resume-project.md +8 -12
  257. package/gsd-core/workflows/review.md +193 -15
  258. package/gsd-core/workflows/scan.md +1 -1
  259. package/gsd-core/workflows/secure-phase.md +2 -2
  260. package/gsd-core/workflows/settings-advanced.md +7 -9
  261. package/gsd-core/workflows/settings-integrations.md +64 -31
  262. package/gsd-core/workflows/settings.md +3 -5
  263. package/gsd-core/workflows/ship.md +12 -6
  264. package/gsd-core/workflows/sketch-wrap-up.md +11 -17
  265. package/gsd-core/workflows/sketch.md +12 -18
  266. package/gsd-core/workflows/smart-entry.md +3 -5
  267. package/gsd-core/workflows/spec-phase.md +23 -1
  268. package/gsd-core/workflows/spike-wrap-up.md +7 -11
  269. package/gsd-core/workflows/spike.md +20 -31
  270. package/gsd-core/workflows/stats.md +2 -2
  271. package/gsd-core/workflows/sync-skills.md +1 -1
  272. package/gsd-core/workflows/thread.md +11 -7
  273. package/gsd-core/workflows/transition.md +5 -5
  274. package/gsd-core/workflows/ui-phase.md +10 -16
  275. package/gsd-core/workflows/ui-review.md +6 -10
  276. package/gsd-core/workflows/ultraplan-phase.md +5 -13
  277. package/gsd-core/workflows/undo.md +8 -16
  278. package/gsd-core/workflows/update.md +6 -10
  279. package/gsd-core/workflows/validate-phase.md +2 -2
  280. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
  281. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  282. package/gsd-core/workflows/verify-work.md +57 -18
  283. package/hooks/dist/gsd-agent-isolation-guard.js +77 -38
  284. package/hooks/dist/gsd-config-reload.js +18 -12
  285. package/hooks/dist/gsd-context-monitor.js +19 -10
  286. package/hooks/dist/gsd-cursor-post-tool.js +3 -1
  287. package/hooks/dist/gsd-cursor-pre-tool.js +3 -1
  288. package/hooks/dist/gsd-cursor-session-start.js +2 -1
  289. package/hooks/dist/gsd-cursor-stop.js +2 -1
  290. package/hooks/dist/gsd-cursor-subagent-start.js +28 -23
  291. package/hooks/dist/gsd-cursor-subagent-stop.js +3 -1
  292. package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
  293. package/hooks/dist/gsd-graphify-update.sh +22 -18
  294. package/hooks/dist/gsd-node-runner.sh +76 -0
  295. package/hooks/dist/gsd-phase-boundary.sh +1 -0
  296. package/hooks/dist/gsd-prompt-guard.js +16 -7
  297. package/hooks/dist/gsd-read-guard.js +16 -7
  298. package/hooks/dist/gsd-read-injection-scanner.js +17 -8
  299. package/hooks/dist/gsd-session-state.sh +1 -0
  300. package/hooks/dist/gsd-statusline.js +215 -26
  301. package/hooks/dist/gsd-validate-commit.sh +80 -6
  302. package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
  303. package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
  304. package/hooks/dist/gsd-workflow-guard.js +34 -16
  305. package/hooks/dist/gsd-worktree-path-guard.js +36 -21
  306. package/hooks/dist/gsd-write-guard.js +35 -25
  307. package/hooks/dist/lib/cli-exit.js +560 -0
  308. package/hooks/dist/lib/exit-code-registry.js +98 -0
  309. package/hooks/dist/lib/git-probe.js +84 -0
  310. package/hooks/dist/lib/hook-exit.js +81 -0
  311. package/hooks/dist/managed-hooks-registry.cjs +3 -0
  312. package/hooks/gsd-agent-isolation-guard.js +77 -38
  313. package/hooks/gsd-config-reload.js +18 -12
  314. package/hooks/gsd-context-monitor.js +19 -10
  315. package/hooks/gsd-cursor-post-tool.js +3 -1
  316. package/hooks/gsd-cursor-pre-tool.js +3 -1
  317. package/hooks/gsd-cursor-session-start.js +2 -1
  318. package/hooks/gsd-cursor-stop.js +2 -1
  319. package/hooks/gsd-cursor-subagent-start.js +28 -23
  320. package/hooks/gsd-cursor-subagent-stop.js +3 -1
  321. package/hooks/gsd-ensure-canonical-path.js +2 -1
  322. package/hooks/gsd-graphify-update.sh +22 -18
  323. package/hooks/gsd-node-runner.sh +76 -0
  324. package/hooks/gsd-phase-boundary.sh +1 -0
  325. package/hooks/gsd-prompt-guard.js +16 -7
  326. package/hooks/gsd-read-guard.js +16 -7
  327. package/hooks/gsd-read-injection-scanner.js +17 -8
  328. package/hooks/gsd-session-state.sh +1 -0
  329. package/hooks/gsd-statusline.js +215 -26
  330. package/hooks/gsd-validate-commit.sh +80 -6
  331. package/hooks/gsd-windsurf-pre-command.js +16 -11
  332. package/hooks/gsd-windsurf-pre-write.js +22 -13
  333. package/hooks/gsd-workflow-guard.js +34 -16
  334. package/hooks/gsd-worktree-path-guard.js +36 -21
  335. package/hooks/gsd-write-guard.js +35 -25
  336. package/hooks/lib/cli-exit.js +560 -0
  337. package/hooks/lib/exit-code-registry.js +98 -0
  338. package/hooks/lib/git-probe.js +84 -0
  339. package/hooks/lib/hook-exit.js +81 -0
  340. package/hooks/managed-hooks-registry.cjs +3 -0
  341. package/package.json +12 -7
  342. package/scripts/base64-scan.sh +74 -12
  343. package/scripts/build-hooks.js +5 -0
  344. package/scripts/check-glossary-refs.cjs +77 -15
  345. package/scripts/check-mutation-score-ratchet.cjs +156 -0
  346. package/scripts/ci-check-job-near-cap.cjs +49 -0
  347. package/scripts/ci-pr-mergeability.cjs +262 -0
  348. package/scripts/ci-test-scope.cjs +45 -12
  349. package/scripts/ci-timeout-report.cjs +230 -0
  350. package/scripts/docs-guard-registry.cjs +396 -0
  351. package/scripts/gen-capability-registry.cjs +8 -6
  352. package/scripts/gen-exit-code-docs.cjs +318 -0
  353. package/scripts/gen-exit-code-registry.cjs +891 -0
  354. package/scripts/gen-features.cjs +836 -0
  355. package/scripts/gen-hooks-cli-exit.cjs +239 -0
  356. package/scripts/gen-install-tree-fixtures.cjs +2 -2
  357. package/scripts/gen-loop-host-contract.cjs +134 -1
  358. package/scripts/gen-scripts-cli-exit.cjs +185 -0
  359. package/scripts/gen-state-md-docs.cjs +727 -0
  360. package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
  361. package/scripts/lib/ci-job-timing.cjs +72 -0
  362. package/scripts/lib/cli-exit.cjs +546 -44
  363. package/scripts/lib/drift-scan.cjs +32 -2
  364. package/scripts/lib/exit-code-registry.cjs +98 -0
  365. package/scripts/lib/ndjson-reporter.cjs +119 -0
  366. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  367. package/scripts/lint-docs-guard-registration.cjs +495 -0
  368. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
  369. package/scripts/lint-eslint-glob-coverage.allowlist.json +4 -0
  370. package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
  371. package/scripts/lint-health-diagnostic-rule-table.cjs +65 -8
  372. package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
  373. package/scripts/lint-phase-enumeration-drift.cjs +21 -8
  374. package/scripts/lint-planning-prompt-drift.cjs +38 -1
  375. package/scripts/lint-removed-but-needed.cjs +184 -16
  376. package/scripts/lint-seam-enforcement.cjs +182 -0
  377. package/scripts/lint-slug-derivation-drift.cjs +921 -0
  378. package/scripts/lint-source-test-name-collision.cjs +241 -0
  379. package/scripts/lint-state-write-path-drift.cjs +337 -432
  380. package/scripts/lint-test-file-count.allowlist.json +122 -4
  381. package/scripts/lint-test-file-count.cjs +25 -3
  382. package/scripts/lint-unreachable-guard-drift.cjs +51 -64
  383. package/scripts/lint-vendored-deps.cjs +208 -35
  384. package/scripts/mutation-matrix.cjs +599 -50
  385. package/scripts/prompt-injection-scan.sh +75 -14
  386. package/scripts/secret-scan.sh +75 -13
  387. package/scripts/select-docs-guards.cjs +56 -0
  388. package/scripts/sync-runtime-launcher.cjs +22 -3
  389. package/skills/gsd-discuss-phase/SKILL.md +1 -1
  390. package/skills/gsd-import/SKILL.md +1 -1
  391. package/skills/gsd-quick/SKILL.md +8 -4
  392. package/vscode/package.json +1 -1
  393. package/bin/lib/ui-safety-gate.cjs +0 -109
  394. package/scripts/lint-emitted-drift-ack.cjs +0 -344
  395. package/scripts/state-write-path-drift-baseline.json +0 -19
@@ -21,6 +21,51 @@ const cjsCommandRouterAdapter = require("./cjs-command-router-adapter.cjs");
21
21
  const { routeCjsCommandFamily } = cjsCommandRouterAdapter;
22
22
  const command_arg_projection_cjs_1 = require("./command-arg-projection.cjs");
23
23
  // ─── Implementation ───────────────────────────────────────────────────────────
24
+ /**
25
+ * #3865: `--phase <N>` / `--phase=<N>` alias for the positional phase token
26
+ * the phase-taking init.* queries read at args[2]. Normalizes the pair into
27
+ * that caller-owned slot so (a) the handler's own args[2] read sees the
28
+ * value, and (b) the strict flag validation it runs sees exactly the argv
29
+ * the positional form produces (a bare `--phase 60` at index 2-3 would
30
+ * otherwise leave `60` as a rejected stray positional — or, pre-ADR-3473
31
+ * §8.4, silently answer `phase_found:false, plan_count:0` for a phase with
32
+ * plans on disk). A valueless `--phase` is a usage error naming the flag.
33
+ * Any other flag-shaped args[2] resolves to `undefined` — the commands'
34
+ * no-position-given input (execute-phase/plan-phase/verify-work usage-error
35
+ * "phase required"; the find-based queries answer phase_found:false; todos
36
+ * drops its area filter) — instead of passing the flag text down as a phase
37
+ * name.
38
+ */
39
+ function normalizePhaseAlias(args, error) {
40
+ const tok = args[2];
41
+ if (tok === undefined)
42
+ return { args, phase: undefined };
43
+ if (tok === '--phase=') {
44
+ error('--phase requires a value: use --phase <N> (or the positional form <N>)');
45
+ // Fail-closed backstop, mirroring parseNamedArgsOrExit: the wired error()
46
+ // exits, but a returning fail() must not fall through to the splices below.
47
+ throw new Error('normalizePhaseAlias: error() returned instead of exiting');
48
+ }
49
+ if (tok.startsWith('--phase=')) {
50
+ const value = tok.slice('--phase='.length);
51
+ const out = args.slice();
52
+ out.splice(2, 1, value);
53
+ return { args: out, phase: value };
54
+ }
55
+ if (tok === '--phase') {
56
+ const next = args[3];
57
+ if (next === undefined || (0, command_arg_projection_cjs_1.isFlagToken)(next)) {
58
+ error('--phase requires a value: use --phase <N> (or the positional form <N>)');
59
+ throw new Error('normalizePhaseAlias: error() returned instead of exiting');
60
+ }
61
+ const out = args.slice();
62
+ out.splice(2, 2, next);
63
+ return { args: out, phase: next };
64
+ }
65
+ if ((0, command_arg_projection_cjs_1.isFlagToken)(tok))
66
+ return { args, phase: undefined };
67
+ return { args, phase: tok };
68
+ }
24
69
  function routeInitCommand({ init, args, cwd, raw, error }) {
25
70
  routeCjsCommandFamily({
26
71
  args,
@@ -34,17 +79,37 @@ function routeInitCommand({ init, args, cwd, raw, error }) {
34
79
  // `buildSectionManifestField`'s flags-Set builder (src/init.cts) is the
35
80
  // single source of truth for flag ABSENCE and gates on value truthiness,
36
81
  // so `namedArgs` is passed through here uncoerced.
82
+ //
83
+ // #3865: the phase-taking init.* queries accept `--phase <N>` /
84
+ // `--phase=<N>` as an alias for the positional form (matching
85
+ // `phase list-plans`, which accepts both). Pre-normalizing here moves
86
+ // the value into the caller-owned args[2] slot every handler below
87
+ // already reads, so the strict flag validation those handlers run sees
88
+ // exactly the argv the positional form produces. A valueless --phase is
89
+ // a usage error naming the flag — never a silent `phase_found:false`
90
+ // for a phase that has plans (the reported incident: 7 plans read as 0).
37
91
  'execute-phase': () => {
38
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['validate', 'tdd', 'wave']);
39
- init.cmdInitExecutePhase(cwd, args[2], raw, {
92
+ const norm = normalizePhaseAlias(args, error);
93
+ // `wave` is an optionalValueFlags entry, not a booleanFlags entry:
94
+ // `--wave N` is a documented, shipped form (commands/gsd/execute-phase.md:4,48)
95
+ // whose value is consumed by the workflow layer
96
+ // (gsd-core/workflows/execute-phase.md:84), not by this CLI seam — see
97
+ // NamedArgSpec.optionalValueFlags in command-arg-projection.cts.
98
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(norm.args, { booleanFlags: ['validate', 'tdd'], optionalValueFlags: ['wave'], positionals: 3 }, error);
99
+ init.cmdInitExecutePhase(cwd, norm.phase, raw, {
40
100
  validate: namedArgs['validate'],
41
101
  tdd: namedArgs['tdd'],
42
102
  wave: namedArgs['wave'],
43
103
  });
44
104
  },
45
105
  'plan-phase': () => {
46
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, ['granularity', 'prd', 'ingest', 'research-phase'], ['validate', 'tdd', 'reviews', 'chunked']);
47
- init.cmdInitPlanPhase(cwd, args[2], raw, {
106
+ const norm = normalizePhaseAlias(args, error);
107
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(norm.args, {
108
+ valueFlags: ['granularity', 'prd', 'ingest', 'research-phase'],
109
+ booleanFlags: ['validate', 'tdd', 'reviews', 'chunked'],
110
+ positionals: 3,
111
+ }, error);
112
+ init.cmdInitPlanPhase(cwd, norm.phase, raw, {
48
113
  validate: namedArgs['validate'],
49
114
  tdd: namedArgs['tdd'],
50
115
  granularity: namedArgs['granularity'],
@@ -56,21 +121,25 @@ function routeInitCommand({ init, args, cwd, raw, error }) {
56
121
  });
57
122
  },
58
123
  'new-project': () => {
59
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['auto']);
124
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { booleanFlags: ['auto'], positionals: 2 }, error);
60
125
  init.cmdInitNewProject(cwd, raw, { auto: namedArgs['auto'] });
61
126
  },
62
127
  'new-milestone': () => {
63
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['reset-phase-numbers']);
128
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { booleanFlags: ['reset-phase-numbers'], positionals: 2 }, error);
64
129
  init.cmdInitNewMilestone(cwd, raw, {
65
130
  'reset-phase-numbers': namedArgs['reset-phase-numbers'],
66
131
  });
67
132
  },
68
133
  onboard: () => {
69
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['fast', 'text']);
134
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { booleanFlags: ['fast', 'text'], positionals: 2 }, error);
70
135
  init.cmdInitOnboard(cwd, raw, { fast: namedArgs['fast'], text: namedArgs['text'] });
71
136
  },
72
137
  quick: () => {
73
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['discuss', 'research', 'validate', 'full']);
138
+ // #3180 Decision 4a / L2 (ADR-3473 §8.4): `positionals: 'rest'` because
139
+ // everything after `init quick` is a free-text description — strict
140
+ // undeclared-flag rejection would break
141
+ // `/gsd-quick add a --dry-run option`, which works today.
142
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { booleanFlags: ['discuss', 'research', 'validate', 'full'], positionals: 'rest' }, error);
74
143
  // #2994: `args.slice(2)` is the free-text description, but section-manifest
75
144
  // gating (buildSectionManifestField, src/init.cts) now requires forwarding
76
145
  // --discuss/--research/--validate/--full alongside it — a plain `.join(' ')`
@@ -91,22 +160,47 @@ function routeInitCommand({ init, args, cwd, raw, error }) {
91
160
  },
92
161
  'ingest-docs': () => init.cmdInitIngestDocs(cwd, raw),
93
162
  resume: () => init.cmdInitResume(cwd, raw),
94
- 'verify-work': () => init.cmdInitVerifyWork(cwd, args[2], raw),
95
- 'phase-op': () => init.cmdInitPhaseOp(cwd, args[2], raw),
163
+ // ADR-3473 §8.4 / #3358 gap: these handlers read args[2] positionally
164
+ // without ever calling parseNamedArgsOrExit, so an unrecognized flag or
165
+ // stray positional was silently dropped instead of rejected. No flags
166
+ // are declared because none are documented for these subcommands
167
+ // (docs/CLI-TOOLS.md); `--ws` seen in shipped workflows targets the
168
+ // separate `query init.verify-work` seam and is stripped before
169
+ // reaching `init verify-work` (gsd-core/workflows/verify-work.md:42-45).
170
+ 'verify-work': () => {
171
+ const norm = normalizePhaseAlias(args, error);
172
+ (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(norm.args, { positionals: 3 }, error);
173
+ init.cmdInitVerifyWork(cwd, norm.phase, raw);
174
+ },
175
+ 'phase-op': () => {
176
+ const norm = normalizePhaseAlias(args, error);
177
+ (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(norm.args, { positionals: 3 }, error);
178
+ init.cmdInitPhaseOp(cwd, norm.phase, raw);
179
+ },
96
180
  'code-review': () => {
97
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['fix']);
98
- init.cmdInitCodeReview(cwd, args[2], raw, { fix: namedArgs['fix'] });
181
+ const norm = normalizePhaseAlias(args, error);
182
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(norm.args, { booleanFlags: ['fix'], positionals: 3 }, error);
183
+ init.cmdInitCodeReview(cwd, norm.phase, raw, { fix: namedArgs['fix'] });
184
+ },
185
+ review: () => {
186
+ const norm = normalizePhaseAlias(args, error);
187
+ (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(norm.args, { positionals: 3 }, error);
188
+ init.cmdInitReview(cwd, norm.phase, raw, {});
99
189
  },
100
- review: () => init.cmdInitReview(cwd, args[2], raw, {}),
101
190
  'discuss-phase-assumptions': () => {
102
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['auto']);
103
- init.cmdInitDiscussPhaseAssumptions(cwd, args[2], raw, { auto: namedArgs['auto'] });
191
+ const norm = normalizePhaseAlias(args, error);
192
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(norm.args, { booleanFlags: ['auto'], positionals: 3 }, error);
193
+ init.cmdInitDiscussPhaseAssumptions(cwd, norm.phase, raw, { auto: namedArgs['auto'] });
194
+ },
195
+ todos: () => {
196
+ const norm = normalizePhaseAlias(args, error);
197
+ (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(norm.args, { positionals: 3 }, error);
198
+ init.cmdInitTodos(cwd, norm.phase, raw);
104
199
  },
105
- todos: () => init.cmdInitTodos(cwd, args[2], raw),
106
200
  'milestone-op': () => init.cmdInitMilestoneOp(cwd, raw),
107
201
  'map-codebase': () => init.cmdInitMapCodebase(cwd, raw),
108
202
  progress: () => {
109
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['forensic']);
203
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { booleanFlags: ['forensic'], positionals: 2 }, error);
110
204
  init.cmdInitProgress(cwd, raw, { forensic: namedArgs['forensic'] });
111
205
  },
112
206
  // Keep manager on CJS for now so runtime-specific command rendering
@@ -114,7 +208,7 @@ function routeInitCommand({ init, args, cwd, raw, error }) {
114
208
  manager: () => init.cmdInitManager(cwd, raw),
115
209
  'complete-milestone': () => init.cmdInitCompleteMilestone(cwd, raw),
116
210
  autonomous: () => {
117
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['converge', 'cross-ai']);
211
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { booleanFlags: ['converge', 'cross-ai'], positionals: 2 }, error);
118
212
  init.cmdInitAutonomous(cwd, raw, {
119
213
  converge: namedArgs['converge'],
120
214
  'cross-ai': namedArgs['cross-ai'],
@@ -122,17 +216,20 @@ function routeInitCommand({ init, args, cwd, raw, error }) {
122
216
  },
123
217
  'docs-update': () => init.cmdInitDocsUpdate(cwd, raw, {}),
124
218
  update: () => {
125
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['next', 'rc']);
219
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { booleanFlags: ['next', 'rc'], positionals: 2 }, error);
126
220
  init.cmdInitUpdate(cwd, raw, { next: namedArgs['next'], rc: namedArgs['rc'] });
127
221
  },
128
222
  transition: () => init.cmdInitTransition(cwd, raw, {}),
129
223
  debug: () => {
130
- const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgs)(args, [], ['diagnose']);
224
+ const namedArgs = (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { booleanFlags: ['diagnose'], positionals: 2 }, error);
131
225
  init.cmdInitDebug(cwd, raw, { diagnose: namedArgs['diagnose'] });
132
226
  },
133
227
  'new-workspace': () => init.cmdInitNewWorkspace(cwd, raw),
134
228
  'list-workspaces': () => init.cmdInitListWorkspaces(cwd, raw),
135
- 'remove-workspace': () => init.cmdInitRemoveWorkspace(cwd, args[2], raw),
229
+ 'remove-workspace': () => {
230
+ (0, command_arg_projection_cjs_1.parseNamedArgsOrExit)(args, { positionals: 3 }, error);
231
+ init.cmdInitRemoveWorkspace(cwd, args[2], raw);
232
+ },
136
233
  },
137
234
  });
138
235
  }
@@ -74,10 +74,13 @@ const resolution_cjs_1 = require("./resolution.cjs");
74
74
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- onboard-projection.cjs is an export= CommonJS module
75
75
  const onboardProjection = require("./onboard-projection.cjs");
76
76
  const { REQUIRED_CODEBASE_MAP_FILES, buildOnboardProjection, hasCodeFilesInternal, hasPackageFileInternal, listCodebaseMapFiles, } = onboardProjection;
77
- const { output, error, ERROR_REASON } = io;
77
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- verify-command-grounding.cjs is an export= CommonJS module
78
+ const verifyCommandGrounding = require("./verify-command-grounding.cjs");
79
+ const { harvestPriorVerifyCommands } = verifyCommandGrounding;
80
+ const { output, error, ERROR_REASON, formatDiagnosticToken } = io;
78
81
  const { loadConfig, loadConfigResolved } = configLoader;
79
82
  const { resolveModelInternal, resolveGranularityInternal, assertValidGranularityOverride } = modelResolver;
80
- const { findPhaseInternal, listMilestonePhaseDirs } = phaseLocator;
83
+ const { findPhaseInternal, listMilestonePhaseDirs, listAllPhaseDirs } = phaseLocator;
81
84
  const { getRoadmapPhaseInternal, getMilestoneInfo, stripShippedMilestones, extractCurrentMilestone, } = roadmapParser;
82
85
  const { pathExistsInternal, generateSlugInternal, toPosixPath } = coreUtils;
83
86
  const { normalizePhaseName, matchPhaseDirs, stripProjectCodePrefix, PHASE_NUMBER_TOKEN_SOURCE, isForeignPrefixedPhaseQuery, isSentinelPhaseId, extractPhaseToken, scopeToPhase } = phaseId;
@@ -129,9 +132,12 @@ function guardedGetRoadmapPhase(cwd, phase, projectCode) {
129
132
  // directory exists yet) identically at every synthetic-fallback call site
130
133
  // below — factored out once so the slugification formula itself cannot drift.
131
134
  function slugifyPhaseName(phaseName) {
132
- return phaseName
133
- ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '')
134
- : null;
135
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
136
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing it.
137
+ // `maxLen: null` preserves this site's pre-migration untruncated contract —
138
+ // the 60-char default would collapse two distinct >60-char phase names onto
139
+ // the same reported phase_slug.
140
+ return phaseName ? coreUtils.generateSlugInternal(phaseName, null) : null;
135
141
  }
136
142
  /**
137
143
  * #2994 (review finding, DEFECT.GENERATIVE-FIX): shared archived/not-found
@@ -1028,8 +1034,21 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
1028
1034
  result['patterns_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, patternsFile));
1029
1035
  }
1030
1036
  }
1031
- catch {
1032
- /* intentionally empty */
1037
+ catch (err) {
1038
+ // #3885 (ADR-3473 §8.5): this branch means `phaseInfo['directory']` was
1039
+ // set (the phase was already resolved to an on-disk directory) yet
1040
+ // `readdirSync` still failed — ENOENT here would be a genuine race
1041
+ // (the directory vanished between resolution and this read) and stays
1042
+ // a silent degrade like the prior behavior; any other errno
1043
+ // (EACCES/EIO/...) is an unreadable-not-absent directory and must be
1044
+ // named, or every conditional field this block sets (context_path,
1045
+ // research_path, verification_path, uat_path, reviews_path,
1046
+ // patterns_path) silently reads as "none of these exist".
1047
+ const code = err?.code;
1048
+ if (code !== 'ENOENT') {
1049
+ result['context_read_error'] =
1050
+ `Could not read phase directory ${formatDiagnosticToken(phaseDirFull)}: ${formatDiagnosticToken(err?.message ?? String(err))}`;
1051
+ }
1033
1052
  }
1034
1053
  }
1035
1054
  if (options['validate']) {
@@ -1056,6 +1075,29 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
1056
1075
  }
1057
1076
  // #2992 (Phase 6.1): additive, optional field — degrades to null, never throws.
1058
1077
  result['section_manifest'] = buildSectionManifestField(cwd, phaseInfo, options, 'plan-phase');
1078
+ // #2401: prior-phase verify commands, surfaced UNGATED — additive field, never
1079
+ // conditioned on context_window. Before this, the planner only inherited
1080
+ // prior-phase verify-command context when context_window >= 500000, so at
1081
+ // lower context windows it re-invented (and mis-resolved) the command. The
1082
+ // harvest already degrades to `{commands: [], readError}` rather than
1083
+ // throwing; the try/catch is defense-in-depth so init never breaks on this.
1084
+ let priorVerifyCommands = [];
1085
+ try {
1086
+ // #2401 review fix: harvestPriorVerifyCommands accepts a phase-id token
1087
+ // (string) directly, so a decimal phase like '2.1' is no longer silently
1088
+ // dropped by `Number('2.1')` producing a value the old `number`-only
1089
+ // parameter mishandled for lettered/decimal tokens.
1090
+ if (phaseNumberPlan !== null) {
1091
+ priorVerifyCommands = harvestPriorVerifyCommands({
1092
+ planningDir: planningPaths(cwd).phases,
1093
+ beforePhase: phaseNumberPlan,
1094
+ }).commands;
1095
+ }
1096
+ }
1097
+ catch {
1098
+ priorVerifyCommands = [];
1099
+ }
1100
+ result['prior_verify_commands'] = priorVerifyCommands;
1059
1101
  output(withProjectRoot(cwd, result), raw);
1060
1102
  }
1061
1103
  function cmdInitNewProject(cwd, raw, options = {}) {
@@ -1077,7 +1119,7 @@ function cmdInitNewProject(cwd, raw, options = {}) {
1077
1119
  synthesizer_model: resolveModelInternal(cwd, 'gsd-research-synthesizer'),
1078
1120
  roadmapper_model: resolveModelInternal(cwd, 'gsd-roadmapper'),
1079
1121
  commit_docs: config.commit_docs,
1080
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1122
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1081
1123
  has_codebase_map: hasCodebaseMap,
1082
1124
  planning_exists: pathExistsInternal(cwd, '.planning'),
1083
1125
  has_existing_code: hasCode,
@@ -1136,7 +1178,7 @@ function cmdInitNewMilestone(cwd, raw, options = {}) {
1136
1178
  phase_archive_path: latestCompleted
1137
1179
  ? toPosixPath(node_path_1.default.join(planningRoot(cwd), 'milestones', `${latestCompleted.version}-phases`))
1138
1180
  : null,
1139
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1181
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1140
1182
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
1141
1183
  state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
1142
1184
  project_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'PROJECT.md')),
@@ -1242,7 +1284,7 @@ function cmdInitQuick(cwd, description, raw, options = {}) {
1242
1284
  function cmdInitIngestDocs(cwd, raw) {
1243
1285
  const config = loadConfig(cwd);
1244
1286
  const result = {
1245
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1287
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1246
1288
  planning_exists: node_fs_1.default.existsSync(planningRoot(cwd)),
1247
1289
  ...getInitGitState(cwd),
1248
1290
  // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase. The
@@ -1283,7 +1325,7 @@ function cmdInitResume(cwd, raw) {
1283
1325
  const result = {
1284
1326
  state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
1285
1327
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
1286
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1328
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1287
1329
  planning_exists: node_fs_1.default.existsSync(planningRoot(cwd)),
1288
1330
  // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
1289
1331
  state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
@@ -1600,9 +1642,11 @@ function cmdInitPhaseOp(cwd, phase, raw) {
1600
1642
  directory: null,
1601
1643
  phase_number: roadmapPhase['phase_number'],
1602
1644
  phase_name: phaseName,
1603
- phase_slug: phaseName
1604
- ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '')
1605
- : null,
1645
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
1646
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing
1647
+ // it. `maxLen: null` preserves this site's pre-migration untruncated
1648
+ // contract.
1649
+ phase_slug: phaseName ? coreUtils.generateSlugInternal(phaseName, null) : null,
1606
1650
  plans: [],
1607
1651
  summaries: [],
1608
1652
  incomplete_plans: [],
@@ -1621,9 +1665,11 @@ function cmdInitPhaseOp(cwd, phase, raw) {
1621
1665
  directory: null,
1622
1666
  phase_number: roadmapPhase['phase_number'],
1623
1667
  phase_name: phaseName,
1624
- phase_slug: phaseName
1625
- ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '')
1626
- : null,
1668
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
1669
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing
1670
+ // it. `maxLen: null` preserves this site's pre-migration untruncated
1671
+ // contract.
1672
+ phase_slug: phaseName ? coreUtils.generateSlugInternal(phaseName, null) : null,
1627
1673
  plans: [],
1628
1674
  summaries: [],
1629
1675
  incomplete_plans: [],
@@ -1738,8 +1784,18 @@ function cmdInitPhaseOp(cwd, phase, raw) {
1738
1784
  result['reviews_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, reviewsFile));
1739
1785
  }
1740
1786
  }
1741
- catch {
1742
- /* intentionally empty */
1787
+ catch (err) {
1788
+ // #3885 (ADR-3473 §8.5): see the parallel site in cmdInitPlanPhase —
1789
+ // ENOENT here is a genuine race (directory vanished after resolution)
1790
+ // and stays a silent degrade; any other errno (EACCES/EIO/...) means
1791
+ // the directory exists but could not be read, and must be named rather
1792
+ // than silently reported the same as "none of context_path/
1793
+ // research_path/verification_path/uat_path/reviews_path exist".
1794
+ const code = err?.code;
1795
+ if (code !== 'ENOENT') {
1796
+ result['context_read_error'] =
1797
+ `Could not read phase directory ${formatDiagnosticToken(phaseDirFull)}: ${formatDiagnosticToken(err?.message ?? String(err))}`;
1798
+ }
1743
1799
  }
1744
1800
  }
1745
1801
  output(withProjectRoot(cwd, result), raw);
@@ -1828,20 +1884,23 @@ function cmdInitMilestoneOp(cwd, raw) {
1828
1884
  const m = tok.match(/^(\d+)([A-Z]?(?:\.\d+)*)$/);
1829
1885
  return m ? String(parseInt(m[1], 10)) + m[2] : tok;
1830
1886
  };
1887
+ // #3882 (ADR-3473 §8.2): this used to hand-roll a readdirSync over the
1888
+ // phases directory (a heading->directory LOOKUP INDEX, same role as
1889
+ // cmdRoadmapAnalyze's `_phaseDirNames` — `roadmapPhaseNumbers` above is
1890
+ // already scoped/sentinel-excluded, so this map must see the PHYSICAL set
1891
+ // to resolve each heading's phase number to its actual directory name;
1892
+ // scoping it again would look up inside an already-scoped set for no
1893
+ // benefit). Routed through the named "physical set, sentinels included"
1894
+ // axis instead: every `num` looked up below came from `roadmapPhaseNumbers`
1895
+ // (sentinels already excluded there), so a sentinel entry surviving in
1896
+ // this map is never read — inclusion is output-invariant, this only
1897
+ // removes the re-derivation.
1831
1898
  const diskPhaseDirs = new Map();
1832
- try {
1833
- const entries = node_fs_1.default.readdirSync(phasesDir, { withFileTypes: true });
1834
- for (const e of entries) {
1835
- if (!e.isDirectory())
1836
- continue;
1837
- const m = stripProjectCodePrefix(e.name).match(new RegExp(`^(${PHASE_NUMBER_TOKEN_SOURCE})`));
1838
- if (!m)
1839
- continue;
1840
- diskPhaseDirs.set(canonicalizePhase(m[1]), e.name);
1841
- }
1842
- }
1843
- catch {
1844
- /* intentionally empty */
1899
+ for (const name of listAllPhaseDirs(phasesDir, { includeSentinels: true }).value) {
1900
+ const m = stripProjectCodePrefix(name).match(new RegExp(`^(${PHASE_NUMBER_TOKEN_SOURCE})`));
1901
+ if (!m)
1902
+ continue;
1903
+ diskPhaseDirs.set(canonicalizePhase(m[1]), name);
1845
1904
  }
1846
1905
  if (roadmapPhaseNumbers.length > 0) {
1847
1906
  phaseCount = roadmapPhaseNumbers.length;
@@ -1908,7 +1967,7 @@ function cmdInitMilestoneOp(cwd, raw) {
1908
1967
  all_phases_complete: phaseCount > 0 && phaseCount === completedPhases,
1909
1968
  archived_milestones: archivedMilestones,
1910
1969
  archive_count: archivedMilestones.length,
1911
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1970
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1912
1971
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
1913
1972
  state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
1914
1973
  archive_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningRoot(cwd), 'archive')),
@@ -1918,7 +1977,12 @@ function cmdInitMilestoneOp(cwd, raw) {
1918
1977
  }
1919
1978
  function cmdInitMapCodebase(cwd, raw) {
1920
1979
  const config = loadConfig(cwd);
1921
- const codebaseDir = node_path_1.default.join(planningRoot(cwd), 'codebase');
1980
+ // #3964: scoped like the payload's own codebase_dir/codebase_dir_exists
1981
+ // below (and verify.cts's codebase drift check) — has_maps/existing_maps
1982
+ // reading the flat root made the same payload claim a scoped codebase dir
1983
+ // exists while reporting zero maps, so map-codebase's Refresh/Skip gate
1984
+ // always forced a re-map under GSD_PROJECT.
1985
+ const codebaseDir = node_path_1.default.join(planningDir(cwd), 'codebase');
1922
1986
  let existingMaps = [];
1923
1987
  try {
1924
1988
  existingMaps = node_fs_1.default.readdirSync(codebaseDir).filter((f) => f.endsWith('.md'));
@@ -1935,11 +1999,14 @@ function cmdInitMapCodebase(cwd, raw) {
1935
1999
  date: clock_cjs_1.realClock.localToday(),
1936
2000
  timestamp: clock_cjs_1.realClock.nowIso(),
1937
2001
  // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
1938
- codebase_dir: toPosixPath(node_path_1.default.join(planningRoot(cwd), 'codebase')),
2002
+ // #3964: scoped like verify.cts's codebase drift check (planningDir, not
2003
+ // the flat planningRoot) so the two surfaces cannot disagree under
2004
+ // GSD_PROJECT.
2005
+ codebase_dir: toPosixPath(node_path_1.default.join(planningDir(cwd), 'codebase')),
1939
2006
  existing_maps: existingMaps,
1940
2007
  has_maps: existingMaps.length > 0,
1941
2008
  planning_exists: pathExistsInternal(cwd, '.planning'),
1942
- codebase_dir_exists: pathExistsInternal(cwd, '.planning/codebase'),
2009
+ codebase_dir_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'codebase')))),
1943
2010
  };
1944
2011
  output(withProjectRoot(cwd, result), raw);
1945
2012
  }
@@ -2156,7 +2223,13 @@ function cmdInitManager(cwd, raw) {
2156
2223
  }
2157
2224
  let waitingSignal = null;
2158
2225
  try {
2159
- const waitingPath = node_path_1.default.join(cwd, '.planning', 'WAITING.json');
2226
+ // #3964: mirror cmdSignalWaiting's write locations exactly — `.gsd/`
2227
+ // first when it exists, else the project-aware planning dir — so the
2228
+ // signal is read from the project (and location) it is written to.
2229
+ const gsdWaiting = node_path_1.default.join(cwd, '.gsd', 'WAITING.json');
2230
+ const waitingPath = node_fs_1.default.existsSync(node_path_1.default.join(cwd, '.gsd'))
2231
+ ? gsdWaiting
2232
+ : node_path_1.default.join(planningDir(cwd), 'WAITING.json');
2160
2233
  const waitingRaw = (0, shell_command_projection_cjs_1.platformReadSync)(waitingPath);
2161
2234
  if (waitingRaw !== null) {
2162
2235
  waitingSignal = JSON.parse(waitingRaw);
@@ -2261,7 +2334,7 @@ function cmdInitManager(cwd, raw) {
2261
2334
  recommended_actions: filteredActions,
2262
2335
  waiting_signal: waitingSignal,
2263
2336
  all_complete: completedCount === nonBacklogPhases.length && nonBacklogPhases.length > 0,
2264
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
2337
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
2265
2338
  roadmap_exists: true,
2266
2339
  state_exists: true,
2267
2340
  manager_flags: managerFlags,
@@ -2617,7 +2690,11 @@ function cmdInitProgress(cwd, raw, options = {}) {
2617
2690
  const status = 'not_started';
2618
2691
  const phaseInfo = {
2619
2692
  number: num,
2620
- name: name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''),
2693
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
2694
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing
2695
+ // it. `maxLen: null` preserves this site's pre-migration untruncated
2696
+ // contract.
2697
+ name: coreUtils.generateSlugInternal(name, null) ?? '',
2621
2698
  directory: null,
2622
2699
  status,
2623
2700
  plan_count: 0,
@@ -2691,7 +2768,7 @@ function cmdInitProgress(cwd, raw, options = {}) {
2691
2768
  paused_at: pausedAt,
2692
2769
  has_work_in_progress: !!currentPhase,
2693
2770
  phase_mvp_mode: phaseMvpMode,
2694
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
2771
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
2695
2772
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
2696
2773
  state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
2697
2774
  // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
@@ -3326,7 +3403,9 @@ function cmdSkillManifest(cwd, args, raw) {
3326
3403
  const skillsDir = skillsDirIdx >= 0 && args[skillsDirIdx + 1] ? args[skillsDirIdx + 1] : null;
3327
3404
  const manifest = buildSkillManifest(cwd, skillsDir);
3328
3405
  if (args.includes('--write')) {
3329
- const planDir = node_path_1.default.join(cwd, '.planning');
3406
+ // #3964: write beside the project's own artifacts (planningDir is
3407
+ // project- and workstream-aware), not the flat root.
3408
+ const planDir = planningDir(cwd);
3330
3409
  if (node_fs_1.default.existsSync(planDir)) {
3331
3410
  const manifestPath = node_path_1.default.join(planDir, 'skill-manifest.json');
3332
3411
  (0, shell_command_projection_cjs_1.platformWriteSync)(manifestPath, JSON.stringify(manifest, null, 2));