@opengsd/gsd-core 1.11.0 → 1.13.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 (498) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +12 -0
  4. package/agents/gsd-code-fixer.md +1 -1
  5. package/agents/gsd-debug-session-manager.md +1 -1
  6. package/agents/gsd-debugger.md +1 -1
  7. package/agents/gsd-dom-verifier.md +169 -0
  8. package/agents/gsd-eval-auditor.md +1 -1
  9. package/agents/gsd-executor.md +78 -42
  10. package/agents/gsd-framework-selector.md +1 -3
  11. package/agents/gsd-intel-updater.md +1 -1
  12. package/agents/gsd-mempalace-curator.md +0 -1
  13. package/agents/gsd-pattern-mapper.md +11 -0
  14. package/agents/gsd-phase-researcher.md +3 -1
  15. package/agents/gsd-plan-checker.md +91 -112
  16. package/agents/gsd-planner.md +20 -4
  17. package/agents/gsd-project-researcher.md +1 -1
  18. package/agents/gsd-research-synthesizer.md +2 -2
  19. package/agents/gsd-roadmapper.md +15 -11
  20. package/agents/gsd-ui-checker.md +82 -7
  21. package/agents/gsd-ui-researcher.md +70 -3
  22. package/agents/gsd-verifier.md +24 -2
  23. package/bin/install.js +847 -200
  24. package/commands/gsd/discuss-phase.md +1 -1
  25. package/commands/gsd/execute-phase.md +1 -1
  26. package/commands/gsd/import.md +1 -1
  27. package/commands/gsd/ns-workflow.md +2 -1
  28. package/commands/gsd/phase.md +1 -1
  29. package/commands/gsd/quick-batch.md +105 -0
  30. package/commands/gsd/quick.md +8 -4
  31. package/commands/gsd/surface.md +18 -8
  32. package/gsd-core/bin/gsd-tools.cjs +761 -100
  33. package/gsd-core/bin/lib/active-workstream-store.cjs +8 -0
  34. package/gsd-core/bin/lib/adr-parser.cjs +13 -7
  35. package/gsd-core/bin/lib/agent-install-check.cjs +162 -0
  36. package/gsd-core/bin/lib/api-coverage.cjs +30 -9
  37. package/gsd-core/bin/lib/artifacts.cjs +2 -0
  38. package/gsd-core/bin/lib/assumption-delta.cjs +30 -11
  39. package/gsd-core/bin/lib/audit.cjs +163 -41
  40. package/gsd-core/bin/lib/broken-windows.cjs +306 -28
  41. package/gsd-core/bin/lib/capability-activation.cjs +27 -0
  42. package/gsd-core/bin/lib/capability-lock.cjs +10 -4
  43. package/gsd-core/bin/lib/capability-registry.cjs +785 -144
  44. package/gsd-core/bin/lib/capability-state.cjs +25 -4
  45. package/gsd-core/bin/lib/capability-validator.cjs +321 -18
  46. package/gsd-core/bin/lib/capability-writer.cjs +14 -4
  47. package/gsd-core/bin/lib/check-command-router.cjs +229 -6
  48. package/gsd-core/bin/lib/claude-orchestration.cjs +10 -25
  49. package/gsd-core/bin/lib/cli-exit.cjs +496 -10
  50. package/gsd-core/bin/lib/clusters.cjs +1 -0
  51. package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
  52. package/gsd-core/bin/lib/codex-agent-toml.cjs +410 -4
  53. package/gsd-core/bin/lib/command-aliases.cjs +16 -0
  54. package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
  55. package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
  56. package/gsd-core/bin/lib/commands.cjs +877 -54
  57. package/gsd-core/bin/lib/complexity-trigger.cjs +26 -6
  58. package/gsd-core/bin/lib/config-loader.cjs +121 -29
  59. package/gsd-core/bin/lib/config.cjs +92 -2
  60. package/gsd-core/bin/lib/configuration.cjs +129 -37
  61. package/gsd-core/bin/lib/core-utils.cjs +118 -14
  62. package/gsd-core/bin/lib/decisions.cjs +213 -1
  63. package/gsd-core/bin/lib/edge-probe.cjs +23 -2
  64. package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
  65. package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
  66. package/gsd-core/bin/lib/file-overlap-partitioner.cjs +74 -0
  67. package/gsd-core/bin/lib/frontmatter.cjs +975 -326
  68. package/gsd-core/bin/lib/gap-checker.cjs +41 -8
  69. package/gsd-core/bin/lib/git-base-branch.cjs +182 -39
  70. package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +7 -3
  71. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +8 -2
  72. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +60 -14
  73. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +75 -22
  74. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +22 -8
  75. package/gsd-core/bin/lib/health-diagnostic.cjs +23 -3
  76. package/gsd-core/bin/lib/host-integration.cjs +96 -11
  77. package/gsd-core/bin/lib/init-command-router.cjs +132 -21
  78. package/gsd-core/bin/lib/init.cjs +252 -56
  79. package/gsd-core/bin/lib/install-engine.cjs +252 -15
  80. package/gsd-core/bin/lib/install-model-override-resolver.cjs +78 -1
  81. package/gsd-core/bin/lib/install-profiles.cjs +100 -18
  82. package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
  83. package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
  84. package/gsd-core/bin/lib/installer-migrations.cjs +10 -7
  85. package/gsd-core/bin/lib/intel.cjs +101 -26
  86. package/gsd-core/bin/lib/io.cjs +195 -15
  87. package/gsd-core/bin/lib/learnings.cjs +85 -14
  88. package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
  89. package/gsd-core/bin/lib/loop-resolver.cjs +14 -8
  90. package/gsd-core/bin/lib/markdown-table.cjs +175 -4
  91. package/gsd-core/bin/lib/milestone.cjs +112 -7
  92. package/gsd-core/bin/lib/model-catalog.cjs +177 -19
  93. package/gsd-core/bin/lib/model-resolver.cjs +10 -28
  94. package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
  95. package/gsd-core/bin/lib/phase-command-router.cjs +13 -6
  96. package/gsd-core/bin/lib/phase-estimation.cjs +17 -8
  97. package/gsd-core/bin/lib/phase-id.cjs +321 -13
  98. package/gsd-core/bin/lib/phase-lifecycle.cjs +24 -16
  99. package/gsd-core/bin/lib/phase-locator.cjs +138 -17
  100. package/gsd-core/bin/lib/phase.cjs +1175 -115
  101. package/gsd-core/bin/lib/plan-document.cjs +273 -0
  102. package/gsd-core/bin/lib/plan-scan.cjs +13 -2
  103. package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
  104. package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
  105. package/gsd-core/bin/lib/planning-snapshot.cjs +165 -34
  106. package/gsd-core/bin/lib/planning-workspace.cjs +159 -28
  107. package/gsd-core/bin/lib/probe-core.cjs +4 -1
  108. package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
  109. package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
  110. package/gsd-core/bin/lib/quick-batch-command-router.cjs +285 -0
  111. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +250 -0
  112. package/gsd-core/bin/lib/quick-batch.cjs +840 -0
  113. package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
  114. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +71 -45
  115. package/gsd-core/bin/lib/review-lane-descriptor.cjs +62 -14
  116. package/gsd-core/bin/lib/review-lane-invocation.cjs +73 -1
  117. package/gsd-core/bin/lib/review-lane-runner.cjs +136 -10
  118. package/gsd-core/bin/lib/roadmap-command-router.cjs +45 -31
  119. package/gsd-core/bin/lib/roadmap-parser.cjs +577 -41
  120. package/gsd-core/bin/lib/roadmap.cjs +248 -64
  121. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +329 -41
  122. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +16 -17
  123. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +320 -109
  124. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +487 -83
  125. package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
  126. package/gsd-core/bin/lib/runtime-slash.cjs +72 -2
  127. package/gsd-core/bin/lib/shell-command-projection.cjs +75 -8
  128. package/gsd-core/bin/lib/smart-entry.cjs +19 -31
  129. package/gsd-core/bin/lib/spec-section.cjs +12 -7
  130. package/gsd-core/bin/lib/state-command-router.cjs +47 -18
  131. package/gsd-core/bin/lib/state-contract.cjs +359 -0
  132. package/gsd-core/bin/lib/state-document.cjs +216 -5
  133. package/gsd-core/bin/lib/state-md-schema.cjs +231 -0
  134. package/gsd-core/bin/lib/state-transition.cjs +850 -145
  135. package/gsd-core/bin/lib/state.cjs +1629 -287
  136. package/gsd-core/bin/lib/surface.cjs +33 -10
  137. package/gsd-core/bin/lib/task-command-router.cjs +111 -1
  138. package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
  139. package/gsd-core/bin/lib/tdd-red-evidence.cjs +133 -0
  140. package/gsd-core/bin/lib/teams-status.cjs +4 -1
  141. package/gsd-core/bin/lib/uat-predicate.cjs +58 -20
  142. package/gsd-core/bin/lib/uat.cjs +2542 -387
  143. package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
  144. package/gsd-core/bin/lib/ui-safety-gate.cjs +37 -7
  145. package/gsd-core/bin/lib/unusable-input.cjs +13 -0
  146. package/gsd-core/bin/lib/update-context.cjs +6 -2
  147. package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
  148. package/gsd-core/bin/lib/validate.cjs +230 -12
  149. package/gsd-core/bin/lib/vendor/README.md +43 -5
  150. package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
  151. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  152. package/gsd-core/bin/lib/verification.cjs +287 -13
  153. package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
  154. package/gsd-core/bin/lib/verify-command-router.cjs +1 -0
  155. package/gsd-core/bin/lib/verify.cjs +441 -56
  156. package/gsd-core/bin/lib/workstream-inventory.cjs +20 -2
  157. package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
  158. package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
  159. package/gsd-core/bin/lib/worktree-safety.cjs +185 -21
  160. package/gsd-core/bin/shared/config-defaults.manifest.json +7 -1
  161. package/gsd-core/bin/shared/config-schema.manifest.json +13 -0
  162. package/gsd-core/bin/shared/exit-codes.json +8 -0
  163. package/gsd-core/bin/shared/exit-codes.sh +20 -0
  164. package/gsd-core/bin/shared/model-catalog.json +8 -1
  165. package/gsd-core/bin/verify-reapply-patches.cjs +70 -3
  166. package/gsd-core/references/agent-contracts.md +6 -5
  167. package/gsd-core/references/api-coverage.md +24 -2
  168. package/gsd-core/references/autonomous-smart-discuss.md +3 -3
  169. package/gsd-core/references/checkpoints.md +37 -19
  170. package/gsd-core/references/decimal-phase-calculation.md +5 -5
  171. package/gsd-core/references/edge-probe.md +17 -5
  172. package/gsd-core/references/execute-mvp-tdd.md +18 -18
  173. package/gsd-core/references/execute-phase-between-wave-reset.md +9 -12
  174. package/gsd-core/references/execute-phase-response-language.md +6 -0
  175. package/gsd-core/references/execute-phase-wave-guard.md +11 -9
  176. package/gsd-core/references/executor-examples.md +42 -0
  177. package/gsd-core/references/failing-direction.md +78 -0
  178. package/gsd-core/references/few-shot-examples/plan-checker.md +15 -15
  179. package/gsd-core/references/gate-prompts.md +1 -1
  180. package/gsd-core/references/git-integration.md +5 -5
  181. package/gsd-core/references/git-planning-commit.md +3 -3
  182. package/gsd-core/references/gsd-run-resolver.md +1 -1
  183. package/gsd-core/references/loop-hook-dispatch.md +22 -0
  184. package/gsd-core/references/model-profiles.md +1 -1
  185. package/gsd-core/references/mvp-concepts.md +2 -2
  186. package/gsd-core/references/nyquist-compliance.md +74 -0
  187. package/gsd-core/references/offer-next.md +3 -5
  188. package/gsd-core/references/phase-argument-parsing.md +3 -3
  189. package/gsd-core/references/plan-checker-examples.md +41 -0
  190. package/gsd-core/references/planner-antipatterns.md +25 -0
  191. package/gsd-core/references/planner-chunked.md +5 -1
  192. package/gsd-core/references/planner-coupling.md +42 -0
  193. package/gsd-core/references/planner-failing-direction.md +53 -0
  194. package/gsd-core/references/planner-human-verify-mode.md +15 -1
  195. package/gsd-core/references/planner-quick-batch.md +71 -0
  196. package/gsd-core/references/planner-reviews.md +47 -0
  197. package/gsd-core/references/planner-revision.md +76 -3
  198. package/gsd-core/references/planner-verify-command-grounding.md +17 -0
  199. package/gsd-core/references/planning-config.md +39 -9
  200. package/gsd-core/references/response-language-directive.md +9 -0
  201. package/gsd-core/references/reviewer-instances.md +31 -0
  202. package/gsd-core/references/revision-loop.md +118 -11
  203. package/gsd-core/references/runtime-aware-dispatch.md +1 -1
  204. package/gsd-core/references/tdd.md +15 -12
  205. package/gsd-core/references/ui-brand.md +65 -21
  206. package/gsd-core/references/ui-consideration-probe.md +1 -1
  207. package/gsd-core/references/universal-anti-patterns.md +2 -2
  208. package/gsd-core/references/verifier-evidence-gate.md +160 -0
  209. package/gsd-core/references/verify-command-path-resolvability.md +42 -0
  210. package/gsd-core/references/verify-mvp-mode.md +1 -1
  211. package/gsd-core/references/workstream-flag.md +11 -11
  212. package/gsd-core/templates/README.md +1 -1
  213. package/gsd-core/templates/SECURITY.md +3 -3
  214. package/gsd-core/templates/UI-SPEC.md +25 -3
  215. package/gsd-core/templates/VALIDATION.md +3 -3
  216. package/gsd-core/templates/phase-prompt.md +7 -0
  217. package/gsd-core/templates/state.md +7 -0
  218. package/gsd-core/templates/verification-report.md +5 -0
  219. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  220. package/gsd-core/workflows/add-backlog.md +3 -1
  221. package/gsd-core/workflows/add-phase.md +5 -3
  222. package/gsd-core/workflows/add-tests.md +4 -9
  223. package/gsd-core/workflows/add-todo.md +2 -2
  224. package/gsd-core/workflows/ai-integration-phase.md +5 -10
  225. package/gsd-core/workflows/analyze-dependencies.md +2 -0
  226. package/gsd-core/workflows/audit-fix.md +14 -3
  227. package/gsd-core/workflows/audit-milestone.md +11 -9
  228. package/gsd-core/workflows/audit-uat.md +19 -2
  229. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
  230. package/gsd-core/workflows/autonomous.md +12 -26
  231. package/gsd-core/workflows/check-todos.md +2 -2
  232. package/gsd-core/workflows/cleanup.md +3 -3
  233. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +16 -14
  234. package/gsd-core/workflows/code-review-fix.md +3 -1
  235. package/gsd-core/workflows/code-review.md +192 -69
  236. package/gsd-core/workflows/complete-milestone.md +28 -14
  237. package/gsd-core/workflows/debug.md +6 -4
  238. package/gsd-core/workflows/diagnose-issues.md +17 -7
  239. package/gsd-core/workflows/discuss-phase/modes/advisor.md +3 -1
  240. package/gsd-core/workflows/discuss-phase/modes/all.md +2 -0
  241. package/gsd-core/workflows/discuss-phase/modes/analyze.md +2 -0
  242. package/gsd-core/workflows/discuss-phase/modes/auto.md +2 -0
  243. package/gsd-core/workflows/discuss-phase/modes/batch.md +2 -0
  244. package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -7
  245. package/gsd-core/workflows/discuss-phase/modes/default.md +2 -0
  246. package/gsd-core/workflows/discuss-phase/modes/power.md +2 -0
  247. package/gsd-core/workflows/discuss-phase/modes/text.md +3 -1
  248. package/gsd-core/workflows/discuss-phase/templates/context.md +2 -0
  249. package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +2 -0
  250. package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
  251. package/gsd-core/workflows/discuss-phase-assumptions.md +3 -3
  252. package/gsd-core/workflows/discuss-phase-power.md +2 -0
  253. package/gsd-core/workflows/discuss-phase.md +2 -2
  254. package/gsd-core/workflows/do.md +46 -19
  255. package/gsd-core/workflows/docs-update.md +6 -5
  256. package/gsd-core/workflows/edit-phase.md +3 -1
  257. package/gsd-core/workflows/eval-review.md +5 -10
  258. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +3 -1
  259. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +129 -11
  260. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  261. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  262. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  263. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +29 -5
  264. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
  265. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
  266. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +4 -2
  267. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +25 -0
  268. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
  269. package/gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md +2 -0
  270. package/gsd-core/workflows/execute-phase.md +68 -66
  271. package/gsd-core/workflows/execute-plan.md +25 -20
  272. package/gsd-core/workflows/explore.md +3 -1
  273. package/gsd-core/workflows/extract-learnings.md +3 -1
  274. package/gsd-core/workflows/fast.md +8 -2
  275. package/gsd-core/workflows/forensics.md +3 -1
  276. package/gsd-core/workflows/graduation.md +6 -6
  277. package/gsd-core/workflows/health.md +4 -7
  278. package/gsd-core/workflows/help/modes/brief.md +2 -0
  279. package/gsd-core/workflows/help/modes/default.md +2 -0
  280. package/gsd-core/workflows/help/modes/full.md +12 -0
  281. package/gsd-core/workflows/help/modes/topic.md +2 -0
  282. package/gsd-core/workflows/help.md +2 -0
  283. package/gsd-core/workflows/import.md +17 -14
  284. package/gsd-core/workflows/inbox.md +5 -6
  285. package/gsd-core/workflows/ingest-docs.md +45 -12
  286. package/gsd-core/workflows/insert-phase.md +7 -5
  287. package/gsd-core/workflows/list-phase-assumptions.md +2 -0
  288. package/gsd-core/workflows/list-seeds.md +7 -3
  289. package/gsd-core/workflows/list-workspaces.md +3 -1
  290. package/gsd-core/workflows/manager.md +15 -26
  291. package/gsd-core/workflows/map-codebase.md +3 -1
  292. package/gsd-core/workflows/milestone-summary.md +3 -1
  293. package/gsd-core/workflows/mvp-phase.md +3 -3
  294. package/gsd-core/workflows/new-milestone.md +10 -22
  295. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  296. package/gsd-core/workflows/new-project.md +17 -29
  297. package/gsd-core/workflows/new-workspace.md +2 -2
  298. package/gsd-core/workflows/next.md +4 -2
  299. package/gsd-core/workflows/node-repair.md +2 -0
  300. package/gsd-core/workflows/note.md +2 -0
  301. package/gsd-core/workflows/onboard.md +1 -1
  302. package/gsd-core/workflows/pause-work.md +20 -5
  303. package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
  304. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +100 -18
  305. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +4 -4
  306. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +12 -3
  307. package/gsd-core/workflows/plan-phase.md +251 -54
  308. package/gsd-core/workflows/plan-review-convergence.md +148 -19
  309. package/gsd-core/workflows/plant-seed.md +3 -3
  310. package/gsd-core/workflows/pr-branch.md +195 -51
  311. package/gsd-core/workflows/profile-user.md +17 -15
  312. package/gsd-core/workflows/progress/steps/forensic-audit.md +1 -1
  313. package/gsd-core/workflows/progress.md +52 -15
  314. package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
  315. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +38 -5
  316. package/gsd-core/workflows/quick/steps/quick-verification.md +2 -4
  317. package/gsd-core/workflows/quick/steps/research-phase.md +5 -7
  318. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
  319. package/gsd-core/workflows/quick-batch/steps/batch-init.md +55 -0
  320. package/gsd-core/workflows/quick-batch/steps/completion.md +65 -0
  321. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +100 -0
  322. package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +147 -0
  323. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +158 -0
  324. package/gsd-core/workflows/quick-batch/steps/research-phase.md +95 -0
  325. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +49 -0
  326. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +73 -0
  327. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +169 -0
  328. package/gsd-core/workflows/quick-batch.md +203 -0
  329. package/gsd-core/workflows/quick.md +33 -32
  330. package/gsd-core/workflows/reapply-patches.md +2 -0
  331. package/gsd-core/workflows/remove-phase.md +6 -4
  332. package/gsd-core/workflows/remove-workspace.md +3 -3
  333. package/gsd-core/workflows/resume-project.md +14 -14
  334. package/gsd-core/workflows/review.md +404 -21
  335. package/gsd-core/workflows/scan.md +3 -1
  336. package/gsd-core/workflows/section-manifest.json +12 -0
  337. package/gsd-core/workflows/secure-phase.md +3 -3
  338. package/gsd-core/workflows/session-report.md +2 -0
  339. package/gsd-core/workflows/settings-advanced.md +9 -9
  340. package/gsd-core/workflows/settings-integrations.md +66 -32
  341. package/gsd-core/workflows/settings.md +4 -6
  342. package/gsd-core/workflows/ship.md +22 -16
  343. package/gsd-core/workflows/sketch-wrap-up.md +13 -17
  344. package/gsd-core/workflows/sketch.md +13 -19
  345. package/gsd-core/workflows/smart-entry.md +4 -6
  346. package/gsd-core/workflows/spec-phase.md +31 -4
  347. package/gsd-core/workflows/spike-wrap-up.md +9 -11
  348. package/gsd-core/workflows/spike.md +21 -32
  349. package/gsd-core/workflows/stats.md +4 -2
  350. package/gsd-core/workflows/sync-skills.md +13 -5
  351. package/gsd-core/workflows/thread.md +13 -7
  352. package/gsd-core/workflows/transition.md +7 -5
  353. package/gsd-core/workflows/ui-phase.md +36 -21
  354. package/gsd-core/workflows/ui-review.md +7 -11
  355. package/gsd-core/workflows/ultraplan-phase.md +7 -13
  356. package/gsd-core/workflows/undo.md +9 -17
  357. package/gsd-core/workflows/update.md +47 -48
  358. package/gsd-core/workflows/validate-phase.md +3 -3
  359. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
  360. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  361. package/gsd-core/workflows/verify-work.md +106 -21
  362. package/hooks/dist/gsd-agent-isolation-guard.js +77 -38
  363. package/hooks/dist/gsd-check-update-worker.js +19 -2
  364. package/hooks/dist/gsd-config-reload.js +18 -12
  365. package/hooks/dist/gsd-context-monitor.js +302 -22
  366. package/hooks/dist/gsd-cursor-post-tool.js +3 -1
  367. package/hooks/dist/gsd-cursor-pre-tool.js +3 -1
  368. package/hooks/dist/gsd-cursor-session-start.js +2 -1
  369. package/hooks/dist/gsd-cursor-stop.js +2 -1
  370. package/hooks/dist/gsd-cursor-subagent-start.js +28 -23
  371. package/hooks/dist/gsd-cursor-subagent-stop.js +3 -1
  372. package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
  373. package/hooks/dist/gsd-graphify-update.sh +22 -18
  374. package/hooks/dist/gsd-node-runner.sh +77 -0
  375. package/hooks/dist/gsd-phase-boundary.sh +1 -0
  376. package/hooks/dist/gsd-prompt-guard.js +46 -12
  377. package/hooks/dist/gsd-read-guard.js +18 -7
  378. package/hooks/dist/gsd-read-injection-scanner.js +22 -13
  379. package/hooks/dist/gsd-secret-read-guard.js +1079 -0
  380. package/hooks/dist/gsd-session-state.sh +1 -0
  381. package/hooks/dist/gsd-statusline.js +222 -29
  382. package/hooks/dist/gsd-validate-commit.sh +523 -12
  383. package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
  384. package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
  385. package/hooks/dist/gsd-workflow-guard.js +36 -17
  386. package/hooks/dist/gsd-worktree-path-guard.js +36 -21
  387. package/hooks/dist/gsd-write-guard.js +35 -25
  388. package/hooks/dist/lib/cli-exit.js +560 -0
  389. package/hooks/dist/lib/exit-code-registry.js +98 -0
  390. package/hooks/dist/lib/git-cmd.js +210 -1
  391. package/hooks/dist/lib/git-probe.js +84 -0
  392. package/hooks/dist/lib/hook-exit.js +81 -0
  393. package/hooks/dist/lib/injection-patterns.js +36 -6
  394. package/hooks/dist/managed-hooks-registry.cjs +4 -0
  395. package/hooks/gsd-agent-isolation-guard.js +77 -38
  396. package/hooks/gsd-check-update-worker.js +19 -2
  397. package/hooks/gsd-config-reload.js +18 -12
  398. package/hooks/gsd-context-monitor.js +302 -22
  399. package/hooks/gsd-cursor-post-tool.js +3 -1
  400. package/hooks/gsd-cursor-pre-tool.js +3 -1
  401. package/hooks/gsd-cursor-session-start.js +2 -1
  402. package/hooks/gsd-cursor-stop.js +2 -1
  403. package/hooks/gsd-cursor-subagent-start.js +28 -23
  404. package/hooks/gsd-cursor-subagent-stop.js +3 -1
  405. package/hooks/gsd-ensure-canonical-path.js +2 -1
  406. package/hooks/gsd-graphify-update.sh +22 -18
  407. package/hooks/gsd-node-runner.sh +77 -0
  408. package/hooks/gsd-phase-boundary.sh +1 -0
  409. package/hooks/gsd-prompt-guard.js +46 -12
  410. package/hooks/gsd-read-guard.js +18 -7
  411. package/hooks/gsd-read-injection-scanner.js +22 -13
  412. package/hooks/gsd-secret-read-guard.js +1079 -0
  413. package/hooks/gsd-session-state.sh +1 -0
  414. package/hooks/gsd-statusline.js +222 -29
  415. package/hooks/gsd-validate-commit.sh +523 -12
  416. package/hooks/gsd-windsurf-pre-command.js +16 -11
  417. package/hooks/gsd-windsurf-pre-write.js +22 -13
  418. package/hooks/gsd-workflow-guard.js +36 -17
  419. package/hooks/gsd-worktree-path-guard.js +36 -21
  420. package/hooks/gsd-write-guard.js +35 -25
  421. package/hooks/hooks.json +6 -0
  422. package/hooks/lib/cli-exit.js +560 -0
  423. package/hooks/lib/exit-code-registry.js +98 -0
  424. package/hooks/lib/git-cmd.js +210 -1
  425. package/hooks/lib/git-probe.js +84 -0
  426. package/hooks/lib/hook-exit.js +81 -0
  427. package/hooks/lib/injection-patterns.js +36 -6
  428. package/hooks/managed-hooks-registry.cjs +4 -0
  429. package/package.json +14 -9
  430. package/scripts/base64-scan.sh +74 -12
  431. package/scripts/build-hooks.js +12 -0
  432. package/scripts/check-glossary-refs.cjs +77 -15
  433. package/scripts/check-mutation-score-ratchet.cjs +156 -0
  434. package/scripts/ci-check-job-near-cap.cjs +49 -0
  435. package/scripts/ci-pr-mergeability.cjs +262 -0
  436. package/scripts/ci-test-scope.cjs +52 -12
  437. package/scripts/ci-timeout-report.cjs +230 -0
  438. package/scripts/docs-guard-registry.cjs +406 -0
  439. package/scripts/gen-capability-registry.cjs +8 -6
  440. package/scripts/gen-exit-code-docs.cjs +318 -0
  441. package/scripts/gen-exit-code-registry.cjs +891 -0
  442. package/scripts/gen-features.cjs +836 -0
  443. package/scripts/gen-hooks-cli-exit.cjs +239 -0
  444. package/scripts/gen-install-tree-fixtures.cjs +2 -2
  445. package/scripts/gen-loop-host-contract.cjs +189 -4
  446. package/scripts/gen-scripts-cli-exit.cjs +185 -0
  447. package/scripts/gen-state-md-docs.cjs +727 -0
  448. package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
  449. package/scripts/lib/ci-job-timing.cjs +72 -0
  450. package/scripts/lib/cli-exit.cjs +546 -44
  451. package/scripts/lib/drift-scan.cjs +32 -2
  452. package/scripts/lib/exit-code-registry.cjs +98 -0
  453. package/scripts/lib/ndjson-reporter.cjs +119 -0
  454. package/scripts/lib/shellcheck-fetch.cjs +247 -0
  455. package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -6
  456. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  457. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  458. package/scripts/lint-docs-guard-registration.cjs +495 -0
  459. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +198 -0
  460. package/scripts/lint-eslint-glob-coverage.allowlist.json +4 -0
  461. package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
  462. package/scripts/lint-health-diagnostic-rule-table.cjs +65 -8
  463. package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
  464. package/scripts/lint-phase-enumeration-drift.cjs +45 -14
  465. package/scripts/lint-phase-id-drift.cjs +133 -8
  466. package/scripts/lint-planning-prompt-drift.cjs +38 -1
  467. package/scripts/lint-portable-grep.cjs +176 -0
  468. package/scripts/lint-removed-but-needed.cjs +184 -16
  469. package/scripts/lint-response-language-coverage.cjs +524 -0
  470. package/scripts/lint-seam-enforcement.cjs +182 -0
  471. package/scripts/lint-slug-derivation-drift.cjs +921 -0
  472. package/scripts/lint-source-test-name-collision.cjs +241 -0
  473. package/scripts/lint-state-write-path-drift.cjs +337 -432
  474. package/scripts/lint-test-file-count.allowlist.json +124 -4
  475. package/scripts/lint-test-file-count.cjs +25 -3
  476. package/scripts/lint-unreachable-guard-drift.cjs +51 -64
  477. package/scripts/lint-vendored-deps.cjs +208 -35
  478. package/scripts/lint-workflow-shellcheck-baseline.json +1027 -0
  479. package/scripts/lint-workflow-shellcheck.cjs +614 -0
  480. package/scripts/mutation-matrix.cjs +599 -50
  481. package/scripts/npm-audit-baseline.cjs +376 -0
  482. package/scripts/prompt-injection-scan.sh +83 -14
  483. package/scripts/require-issue-link-policy.cjs +16 -1
  484. package/scripts/secret-scan.sh +75 -13
  485. package/scripts/select-docs-guards.cjs +56 -0
  486. package/scripts/sync-runtime-launcher.cjs +22 -3
  487. package/skills/gsd-discuss-phase/SKILL.md +1 -1
  488. package/skills/gsd-execute-phase/SKILL.md +1 -1
  489. package/skills/gsd-import/SKILL.md +1 -1
  490. package/skills/gsd-ns-workflow/SKILL.md +1 -0
  491. package/skills/gsd-phase/SKILL.md +1 -1
  492. package/skills/gsd-quick/SKILL.md +8 -4
  493. package/skills/gsd-quick-batch/SKILL.md +105 -0
  494. package/skills/gsd-surface/SKILL.md +18 -8
  495. package/vscode/package.json +1 -1
  496. package/bin/lib/ui-safety-gate.cjs +0 -109
  497. package/scripts/lint-emitted-drift-ack.cjs +0 -344
  498. package/scripts/state-write-path-drift-baseline.json +0 -19
@@ -34,6 +34,9 @@ const phaseId = require("./phase-id.cjs");
34
34
  const worktreeSafety = require("./worktree-safety.cjs");
35
35
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- planning-workspace.cjs is an export= CommonJS module
36
36
  const planningWorkspace = require("./planning-workspace.cjs");
37
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
38
+ const planningScopeMod = require("./planning-scope.cjs");
39
+ const { SCOPE } = planningScopeMod;
37
40
  const secrets_cjs_1 = require("./secrets.cjs");
38
41
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- plan-scan.cjs is an export= CommonJS module
39
42
  const scanPhasePlans = require("./plan-scan.cjs");
@@ -74,13 +77,16 @@ const resolution_cjs_1 = require("./resolution.cjs");
74
77
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- onboard-projection.cjs is an export= CommonJS module
75
78
  const onboardProjection = require("./onboard-projection.cjs");
76
79
  const { REQUIRED_CODEBASE_MAP_FILES, buildOnboardProjection, hasCodeFilesInternal, hasPackageFileInternal, listCodebaseMapFiles, } = onboardProjection;
77
- const { output, error, ERROR_REASON } = io;
80
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- verify-command-grounding.cjs is an export= CommonJS module
81
+ const verifyCommandGrounding = require("./verify-command-grounding.cjs");
82
+ const { harvestPriorVerifyCommands } = verifyCommandGrounding;
83
+ const { output, error, ERROR_REASON, formatDiagnosticToken } = io;
78
84
  const { loadConfig, loadConfigResolved } = configLoader;
79
85
  const { resolveModelInternal, resolveGranularityInternal, assertValidGranularityOverride } = modelResolver;
80
- const { findPhaseInternal, listMilestonePhaseDirs } = phaseLocator;
86
+ const { findPhaseInternal, listMilestonePhaseDirs, listAllPhaseDirs } = phaseLocator;
81
87
  const { getRoadmapPhaseInternal, getMilestoneInfo, stripShippedMilestones, extractCurrentMilestone, } = roadmapParser;
82
88
  const { pathExistsInternal, generateSlugInternal, toPosixPath } = coreUtils;
83
- const { normalizePhaseName, matchPhaseDirs, stripProjectCodePrefix, PHASE_NUMBER_TOKEN_SOURCE, isForeignPrefixedPhaseQuery, isSentinelPhaseId, extractPhaseToken, scopeToPhase } = phaseId;
89
+ const { comparePhaseNum, normalizePhaseName, matchPhaseDirs, stripProjectCodePrefix, PHASE_NUMBER_TOKEN_SOURCE, isForeignPrefixedPhaseQuery, isSentinelPhaseId, extractPhaseToken, scopeToPhase } = phaseId;
84
90
  const { pruneOrphanedWorktrees } = worktreeSafety;
85
91
  const { planningPaths, planningDir, planningRoot, listAvailableWorkstreams, peekActiveWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, } = planningWorkspace;
86
92
  const { determinePhaseStatus } = commandsMod;
@@ -129,9 +135,12 @@ function guardedGetRoadmapPhase(cwd, phase, projectCode) {
129
135
  // directory exists yet) identically at every synthetic-fallback call site
130
136
  // below — factored out once so the slugification formula itself cannot drift.
131
137
  function slugifyPhaseName(phaseName) {
132
- return phaseName
133
- ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '')
134
- : null;
138
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
139
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing it.
140
+ // `maxLen: null` preserves this site's pre-migration untruncated contract —
141
+ // the 60-char default would collapse two distinct >60-char phase names onto
142
+ // the same reported phase_slug.
143
+ return phaseName ? coreUtils.generateSlugInternal(phaseName, null) : null;
135
144
  }
136
145
  /**
137
146
  * #2994 (review finding, DEFECT.GENERATIVE-FIX): shared archived/not-found
@@ -765,7 +774,6 @@ function cmdInitExecutePhase(cwd, phase, raw, options = {}) {
765
774
  ? reqMatch[1].replace(/[\[\]]/g, '').split(',').map((s) => s.trim()).filter(Boolean).join(', ')
766
775
  : null;
767
776
  const phase_req_ids = reqExtracted && reqExtracted !== 'TBD' ? reqExtracted : null;
768
- const wf = (config.workflow ?? {});
769
777
  // #3188: these paths are null when the file is absent, matching the contract
770
778
  // the conditional sibling fields (context_path, patterns_path, ...) already
771
779
  // honour and that ultraplan-phase.md / execute-phase.md gate on. Hoisted so
@@ -776,7 +784,7 @@ function cmdInitExecutePhase(cwd, phase, raw, options = {}) {
776
784
  const result = {
777
785
  executor_model: resolveModelInternal(cwd, 'gsd-executor'),
778
786
  verifier_model: resolveModelInternal(cwd, 'gsd-verifier'),
779
- tdd_mode: options['tdd'] || Boolean(wf['tdd_mode']) || false,
787
+ tdd_mode: options['tdd'] || Boolean(config.tdd_mode) || false,
780
788
  commit_docs: config.commit_docs,
781
789
  sub_repos: config.sub_repos,
782
790
  parallelization: config.parallelization,
@@ -918,7 +926,6 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
918
926
  const granularityOverride = options['granularity'];
919
927
  assertValidGranularityOverride(granularityOverride, error);
920
928
  const granularity = resolveGranularityInternal(cwd, 'planning', granularityOverride || undefined);
921
- const wf = (config.workflow ?? {});
922
929
  // #3188: see cmdInitExecutePhase — null when absent, parity with the
923
930
  // conditional sibling fields in this same result object.
924
931
  const statePath = node_path_1.default.join(planningDir(cwd), 'STATE.md');
@@ -928,11 +935,11 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
928
935
  researcher_model: resolveModelInternal(cwd, 'gsd-phase-researcher'),
929
936
  planner_model: resolveModelInternal(cwd, 'gsd-planner'),
930
937
  checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
931
- tdd_mode: options['tdd'] || Boolean(wf['tdd_mode']) || false,
938
+ tdd_mode: options['tdd'] || Boolean(config.tdd_mode) || false,
932
939
  granularity,
933
- research_enabled: wf['research'],
940
+ research_enabled: config.research,
934
941
  plan_checker_enabled: config.plan_checker,
935
- nyquist_validation_enabled: wf['nyquist_validation'],
942
+ nyquist_validation_enabled: config.nyquist_validation,
936
943
  commit_docs: config.commit_docs,
937
944
  text_mode: config.text_mode,
938
945
  auto_advance: !!(config.auto_advance),
@@ -954,6 +961,11 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
954
961
  : 'Pending',
955
962
  has_research: phaseInfo?.['has_research'] || false,
956
963
  has_context: phaseInfo?.['has_context'] || false,
964
+ // #4014 (epic #3473 B4-unreadable): additive scope signal adjacent to
965
+ // has_context — SCOPE.COMPLETE by default (no phase directory to read is
966
+ // a genuine, not-unreadable answer), overwritten below to whatever
967
+ // findContextMdIn(phaseDirFull) reports once a directory is known.
968
+ context_scope: SCOPE.COMPLETE,
957
969
  has_reviews: phaseInfo?.['has_reviews'] || false,
958
970
  has_plans: (phaseInfo?.['plans']?.length || 0) > 0,
959
971
  plan_count: phaseInfo?.['plans']?.length || 0,
@@ -968,6 +980,13 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
968
980
  };
969
981
  if (phaseInfo?.['directory']) {
970
982
  const phaseDirFull = node_path_1.default.join(cwd, phaseInfo['directory']);
983
+ // #4014 (epic #3473 B4-unreadable): findContextMdIn's directory-string
984
+ // form never throws, so this can record the real scope BEFORE the
985
+ // pre-existing `fs.readdirSync(phaseDirFull)` immediately below
986
+ // (unchanged) throws on the same unreadable directory and is caught
987
+ // exactly as before — additive only, the failure control-flow for
988
+ // context_path/research_path/etc. is untouched.
989
+ result['context_scope'] = findContextMdIn(phaseDirFull).scope;
971
990
  try {
972
991
  const files = node_fs_1.default.readdirSync(phaseDirFull);
973
992
  const phaseDirName = node_path_1.default.basename(phaseDirFull);
@@ -1028,8 +1047,21 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
1028
1047
  result['patterns_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, patternsFile));
1029
1048
  }
1030
1049
  }
1031
- catch {
1032
- /* intentionally empty */
1050
+ catch (err) {
1051
+ // #3885 (ADR-3473 §8.5): this branch means `phaseInfo['directory']` was
1052
+ // set (the phase was already resolved to an on-disk directory) yet
1053
+ // `readdirSync` still failed — ENOENT here would be a genuine race
1054
+ // (the directory vanished between resolution and this read) and stays
1055
+ // a silent degrade like the prior behavior; any other errno
1056
+ // (EACCES/EIO/...) is an unreadable-not-absent directory and must be
1057
+ // named, or every conditional field this block sets (context_path,
1058
+ // research_path, verification_path, uat_path, reviews_path,
1059
+ // patterns_path) silently reads as "none of these exist".
1060
+ const code = err?.code;
1061
+ if (code !== 'ENOENT') {
1062
+ result['context_read_error'] =
1063
+ `Could not read phase directory ${formatDiagnosticToken(phaseDirFull)}: ${formatDiagnosticToken(err?.message ?? String(err))}`;
1064
+ }
1033
1065
  }
1034
1066
  }
1035
1067
  if (options['validate']) {
@@ -1056,8 +1088,59 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
1056
1088
  }
1057
1089
  // #2992 (Phase 6.1): additive, optional field — degrades to null, never throws.
1058
1090
  result['section_manifest'] = buildSectionManifestField(cwd, phaseInfo, options, 'plan-phase');
1091
+ // #2401: prior-phase verify commands, surfaced UNGATED — additive field, never
1092
+ // conditioned on context_window. Before this, the planner only inherited
1093
+ // prior-phase verify-command context when context_window >= 500000, so at
1094
+ // lower context windows it re-invented (and mis-resolved) the command. The
1095
+ // harvest already degrades to `{commands: [], readError}` rather than
1096
+ // throwing; the try/catch is defense-in-depth so init never breaks on this.
1097
+ let priorVerifyCommands = [];
1098
+ try {
1099
+ // #2401 review fix: harvestPriorVerifyCommands accepts a phase-id token
1100
+ // (string) directly, so a decimal phase like '2.1' is no longer silently
1101
+ // dropped by `Number('2.1')` producing a value the old `number`-only
1102
+ // parameter mishandled for lettered/decimal tokens.
1103
+ if (phaseNumberPlan !== null) {
1104
+ priorVerifyCommands = harvestPriorVerifyCommands({
1105
+ planningDir: planningPaths(cwd).phases,
1106
+ beforePhase: phaseNumberPlan,
1107
+ }).commands;
1108
+ }
1109
+ }
1110
+ catch {
1111
+ priorVerifyCommands = [];
1112
+ }
1113
+ result['prior_verify_commands'] = priorVerifyCommands;
1059
1114
  output(withProjectRoot(cwd, result), raw);
1060
1115
  }
1116
+ // #4040: shared partial-init discriminator for the init.progress / init.resume /
1117
+ // init.new-project payloads. A bootstrap interrupted before the core quartet
1118
+ // (PROJECT.md / REQUIREMENTS.md / ROADMAP.md / STATE.md) all landed is a
1119
+ // DISTINCT routing state from "new project" and from "between milestones";
1120
+ // pre-#4040 the payloads could not express it, so progress.md mis-routed it to
1121
+ // Route F and resume-project.md offered STATE.md reconstruction.
1122
+ //
1123
+ // Negative-space guard: `milestone.complete` archives ROADMAP.md (and
1124
+ // REQUIREMENTS.md) but always leaves MILESTONES.md behind — so MILESTONES.md
1125
+ // present proves missing core files are archival (between-milestones), never an
1126
+ // unfinished bootstrap. REQUIREMENTS.md is written by new-project BEFORE
1127
+ // ROADMAP/STATE, so its absence also proves init never finished.
1128
+ function buildInitCompletenessFields(cwd) {
1129
+ const dir = planningDir(cwd);
1130
+ const planningExists = node_fs_1.default.existsSync(dir);
1131
+ const requirementsExists = node_fs_1.default.existsSync(node_path_1.default.join(dir, 'REQUIREMENTS.md'));
1132
+ const milestonesExists = node_fs_1.default.existsSync(node_path_1.default.join(dir, 'MILESTONES.md'));
1133
+ const coreComplete = node_fs_1.default.existsSync(node_path_1.default.join(dir, 'PROJECT.md')) &&
1134
+ requirementsExists &&
1135
+ node_fs_1.default.existsSync(node_path_1.default.join(dir, 'ROADMAP.md')) &&
1136
+ node_fs_1.default.existsSync(node_path_1.default.join(dir, 'STATE.md'));
1137
+ return {
1138
+ planning_exists: planningExists,
1139
+ requirements_exists: requirementsExists,
1140
+ milestones_exists: milestonesExists,
1141
+ init_incomplete: planningExists && !coreComplete && !milestonesExists,
1142
+ };
1143
+ }
1061
1144
  function cmdInitNewProject(cwd, raw, options = {}) {
1062
1145
  const config = loadConfig(cwd);
1063
1146
  const homedir = node_os_1.default.homedir();
@@ -1077,7 +1160,12 @@ function cmdInitNewProject(cwd, raw, options = {}) {
1077
1160
  synthesizer_model: resolveModelInternal(cwd, 'gsd-research-synthesizer'),
1078
1161
  roadmapper_model: resolveModelInternal(cwd, 'gsd-roadmapper'),
1079
1162
  commit_docs: config.commit_docs,
1080
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1163
+ // #4040: partial-init discriminator (see buildInitCompletenessFields).
1164
+ // Spread BEFORE this literal's own planning_exists so the existing
1165
+ // root-scoped (`pathExistsInternal(cwd, '.planning')`) semantics for that
1166
+ // one key stay byte-identical for existing consumers.
1167
+ ...buildInitCompletenessFields(cwd),
1168
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1081
1169
  has_codebase_map: hasCodebaseMap,
1082
1170
  planning_exists: pathExistsInternal(cwd, '.planning'),
1083
1171
  has_existing_code: hasCode,
@@ -1116,13 +1204,12 @@ function cmdInitNewMilestone(cwd, raw, options = {}) {
1116
1204
  // owns — routed through it instead of a local readdirSync + hand-rolled
1117
1205
  // window filter (which also never excluded sentinels, unlike the owner).
1118
1206
  const phaseDirCount = listMilestonePhaseDirs(phasesDir, { cwd }).value.length;
1119
- const wf = (config.workflow ?? {});
1120
1207
  const result = {
1121
1208
  researcher_model: resolveModelInternal(cwd, 'gsd-project-researcher'),
1122
1209
  synthesizer_model: resolveModelInternal(cwd, 'gsd-research-synthesizer'),
1123
1210
  roadmapper_model: resolveModelInternal(cwd, 'gsd-roadmapper'),
1124
1211
  commit_docs: config.commit_docs,
1125
- research_enabled: wf['research'],
1212
+ research_enabled: config.research,
1126
1213
  // #3216 review Finding 2: `?? null` so an unresolved milestone still emits
1127
1214
  // the key with an explicit `null` rather than letting JSON.stringify drop
1128
1215
  // it — an omitted key reaches the prompt layer's `{current_milestone}`
@@ -1136,7 +1223,7 @@ function cmdInitNewMilestone(cwd, raw, options = {}) {
1136
1223
  phase_archive_path: latestCompleted
1137
1224
  ? toPosixPath(node_path_1.default.join(planningRoot(cwd), 'milestones', `${latestCompleted.version}-phases`))
1138
1225
  : null,
1139
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1226
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1140
1227
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
1141
1228
  state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
1142
1229
  project_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'PROJECT.md')),
@@ -1204,6 +1291,10 @@ function cmdInitQuick(cwd, description, raw, options = {}) {
1204
1291
  executor_model: resolveModelInternal(cwd, 'gsd-executor'),
1205
1292
  checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
1206
1293
  verifier_model: resolveModelInternal(cwd, 'gsd-verifier'),
1294
+ // #3936: Step 4.75 dispatches gsd-phase-researcher; resolve its own tier
1295
+ // (parity with cmdInitPlanPhase) so the research spawn stops pinning
1296
+ // planner_model.
1297
+ researcher_model: resolveModelInternal(cwd, 'gsd-phase-researcher'),
1207
1298
  // #2072: the quick review step spawns gsd-code-reviewer; resolve its own model
1208
1299
  // so model_overrides / models.verification apply (was reusing executor_model).
1209
1300
  reviewer_model: resolveModelInternal(cwd, 'gsd-code-reviewer'),
@@ -1239,10 +1330,49 @@ function cmdInitQuick(cwd, description, raw, options = {}) {
1239
1330
  result['section_manifest'] = buildSectionManifestField(cwd, null, sectionManifestOptions, 'quick');
1240
1331
  output(withProjectRoot(cwd, result), raw);
1241
1332
  }
1333
+ /**
1334
+ * `init.quick-batch` (#3676, Phase 4 of epic #3344, ADR-1239 "Quick-batch
1335
+ * binding"). Unlike `cmdInitQuick`, this init bundle does NOT allocate a
1336
+ * quick id / slug / task directory itself — batch-level id allocation and
1337
+ * `BATCH.json` creation is the job of the `quick-batch create` CLI verb
1338
+ * (`src/quick-batch-command-router.cts`, wrapping `createBatch` in
1339
+ * `src/quick-batch.cts`). This bundle supplies the per-role model profiles,
1340
+ * `commit_docs`, the roadmap/planning existence checks `quick-batch.md`'s
1341
+ * ROADMAP.md gate needs (same check `cmdInitQuick` runs), the `.planning/quick`
1342
+ * directory path, and the `section_manifest` field gating the optional
1343
+ * `--research`/`--validate` step fragments — the same `flag:--research`/
1344
+ * `flag:--validate` atoms `quick`'s own section manifest already uses
1345
+ * (`WHEN_VOCABULARY` is workflow-agnostic; no new atom is needed). `--discuss`/
1346
+ * `--full` are rejected by `quick-batch-dispatch.cts`'s `parseQuickBatchArgs`
1347
+ * before this init bundle is ever reached, so no `discuss`/`full` flag key is
1348
+ * accepted here (unlike `cmdInitQuick`, which still supports both).
1349
+ */
1350
+ function cmdInitQuickBatch(cwd, raw, options = {}) {
1351
+ const config = loadConfig(cwd);
1352
+ const result = {
1353
+ planner_model: resolveModelInternal(cwd, 'gsd-planner'),
1354
+ executor_model: resolveModelInternal(cwd, 'gsd-executor'),
1355
+ checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
1356
+ verifier_model: resolveModelInternal(cwd, 'gsd-verifier'),
1357
+ researcher_model: resolveModelInternal(cwd, 'gsd-phase-researcher'),
1358
+ reviewer_model: resolveModelInternal(cwd, 'gsd-code-reviewer'),
1359
+ commit_docs: config.commit_docs,
1360
+ // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase; a
1361
+ // per-item task_dir is re-derived by the workflow itself (quick_id +
1362
+ // generate-slug over that item's description), never allocated here.
1363
+ quick_dir: toPosixPath(node_path_1.default.join(planningDir(cwd), 'quick')),
1364
+ quick_batches_dir: toPosixPath(node_path_1.default.join(planningDir(cwd), 'quick-batches')),
1365
+ roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
1366
+ planning_exists: node_fs_1.default.existsSync(planningRoot(cwd)),
1367
+ };
1368
+ // #2992 (Phase 6.1): additive, optional field — degrades to null, never throws.
1369
+ result['section_manifest'] = buildSectionManifestField(cwd, null, options, 'quick-batch');
1370
+ output(withProjectRoot(cwd, result), raw);
1371
+ }
1242
1372
  function cmdInitIngestDocs(cwd, raw) {
1243
1373
  const config = loadConfig(cwd);
1244
1374
  const result = {
1245
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1375
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1246
1376
  planning_exists: node_fs_1.default.existsSync(planningRoot(cwd)),
1247
1377
  ...getInitGitState(cwd),
1248
1378
  // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase. The
@@ -1263,12 +1393,11 @@ function cmdInitIngestDocs(cwd, raw) {
1263
1393
  }
1264
1394
  function cmdInitOnboard(cwd, raw, options = {}) {
1265
1395
  const config = loadConfig(cwd);
1266
- const workflowConfig = (config.workflow ?? {});
1267
1396
  const result = {
1268
1397
  ...buildOnboardProjection(cwd, {
1269
1398
  commitDocs: !!config.commit_docs,
1270
1399
  fast: options['fast'] === true,
1271
- textMode: options['text'] === true || !!config.text_mode || !!workflowConfig['text_mode'],
1400
+ textMode: options['text'] === true || !!config.text_mode,
1272
1401
  }),
1273
1402
  ...getInitGitState(cwd),
1274
1403
  };
@@ -1281,9 +1410,14 @@ function cmdInitResume(cwd, raw) {
1281
1410
  if (agentIdRaw !== null)
1282
1411
  interruptedAgentId = agentIdRaw.trim();
1283
1412
  const result = {
1413
+ // #4040: partial-init discriminator (see buildInitCompletenessFields).
1414
+ // Spread FIRST so this literal's own root-scoped planning_exists
1415
+ // (planningRoot) keeps its existing semantics; init_incomplete itself
1416
+ // keys off the artifact dir (planningDir) where the core docs live.
1417
+ ...buildInitCompletenessFields(cwd),
1284
1418
  state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
1285
1419
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
1286
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
1420
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1287
1421
  planning_exists: node_fs_1.default.existsSync(planningRoot(cwd)),
1288
1422
  // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
1289
1423
  state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
@@ -1600,9 +1734,11 @@ function cmdInitPhaseOp(cwd, phase, raw) {
1600
1734
  directory: null,
1601
1735
  phase_number: roadmapPhase['phase_number'],
1602
1736
  phase_name: phaseName,
1603
- phase_slug: phaseName
1604
- ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '')
1605
- : null,
1737
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
1738
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing
1739
+ // it. `maxLen: null` preserves this site's pre-migration untruncated
1740
+ // contract.
1741
+ phase_slug: phaseName ? coreUtils.generateSlugInternal(phaseName, null) : null,
1606
1742
  plans: [],
1607
1743
  summaries: [],
1608
1744
  incomplete_plans: [],
@@ -1621,9 +1757,11 @@ function cmdInitPhaseOp(cwd, phase, raw) {
1621
1757
  directory: null,
1622
1758
  phase_number: roadmapPhase['phase_number'],
1623
1759
  phase_name: phaseName,
1624
- phase_slug: phaseName
1625
- ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '')
1626
- : null,
1760
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
1761
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing
1762
+ // it. `maxLen: null` preserves this site's pre-migration untruncated
1763
+ // contract.
1764
+ phase_slug: phaseName ? coreUtils.generateSlugInternal(phaseName, null) : null,
1627
1765
  plans: [],
1628
1766
  summaries: [],
1629
1767
  incomplete_plans: [],
@@ -1674,6 +1812,9 @@ function cmdInitPhaseOp(cwd, phase, raw) {
1674
1812
  padded_phase: phaseNumber ? normalizePhaseName(phaseNumber) : null,
1675
1813
  has_research: phaseInfo?.['has_research'] || false,
1676
1814
  has_context: phaseInfo?.['has_context'] || false,
1815
+ // #4014 (epic #3473 B4-unreadable): see the parallel field in
1816
+ // cmdInitPlanPhase — additive scope signal adjacent to has_context.
1817
+ context_scope: SCOPE.COMPLETE,
1677
1818
  has_plans: (phaseInfo?.['plans']?.length || 0) > 0,
1678
1819
  has_verification: phaseInfo?.['has_verification'] || false,
1679
1820
  has_reviews: phaseInfo?.['has_reviews'] || false,
@@ -1688,6 +1829,9 @@ function cmdInitPhaseOp(cwd, phase, raw) {
1688
1829
  };
1689
1830
  if (phaseInfo?.['directory']) {
1690
1831
  const phaseDirFull = node_path_1.default.join(cwd, phaseInfo['directory']);
1832
+ // #4014 (epic #3473 B4-unreadable): see the parallel site in
1833
+ // cmdInitPlanPhase — additive only, failure control-flow below unchanged.
1834
+ result['context_scope'] = findContextMdIn(phaseDirFull).scope;
1691
1835
  try {
1692
1836
  const files = node_fs_1.default.readdirSync(phaseDirFull);
1693
1837
  const phaseDirName = node_path_1.default.basename(phaseDirFull);
@@ -1738,8 +1882,18 @@ function cmdInitPhaseOp(cwd, phase, raw) {
1738
1882
  result['reviews_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, reviewsFile));
1739
1883
  }
1740
1884
  }
1741
- catch {
1742
- /* intentionally empty */
1885
+ catch (err) {
1886
+ // #3885 (ADR-3473 §8.5): see the parallel site in cmdInitPlanPhase —
1887
+ // ENOENT here is a genuine race (directory vanished after resolution)
1888
+ // and stays a silent degrade; any other errno (EACCES/EIO/...) means
1889
+ // the directory exists but could not be read, and must be named rather
1890
+ // than silently reported the same as "none of context_path/
1891
+ // research_path/verification_path/uat_path/reviews_path exist".
1892
+ const code = err?.code;
1893
+ if (code !== 'ENOENT') {
1894
+ result['context_read_error'] =
1895
+ `Could not read phase directory ${formatDiagnosticToken(phaseDirFull)}: ${formatDiagnosticToken(err?.message ?? String(err))}`;
1896
+ }
1743
1897
  }
1744
1898
  }
1745
1899
  output(withProjectRoot(cwd, result), raw);
@@ -1828,20 +1982,23 @@ function cmdInitMilestoneOp(cwd, raw) {
1828
1982
  const m = tok.match(/^(\d+)([A-Z]?(?:\.\d+)*)$/);
1829
1983
  return m ? String(parseInt(m[1], 10)) + m[2] : tok;
1830
1984
  };
1985
+ // #3882 (ADR-3473 §8.2): this used to hand-roll a readdirSync over the
1986
+ // phases directory (a heading->directory LOOKUP INDEX, same role as
1987
+ // cmdRoadmapAnalyze's `_phaseDirNames` — `roadmapPhaseNumbers` above is
1988
+ // already scoped/sentinel-excluded, so this map must see the PHYSICAL set
1989
+ // to resolve each heading's phase number to its actual directory name;
1990
+ // scoping it again would look up inside an already-scoped set for no
1991
+ // benefit). Routed through the named "physical set, sentinels included"
1992
+ // axis instead: every `num` looked up below came from `roadmapPhaseNumbers`
1993
+ // (sentinels already excluded there), so a sentinel entry surviving in
1994
+ // this map is never read — inclusion is output-invariant, this only
1995
+ // removes the re-derivation.
1831
1996
  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 */
1997
+ for (const name of listAllPhaseDirs(phasesDir, { includeSentinels: true }).value) {
1998
+ const m = stripProjectCodePrefix(name).match(new RegExp(`^(${PHASE_NUMBER_TOKEN_SOURCE})`));
1999
+ if (!m)
2000
+ continue;
2001
+ diskPhaseDirs.set(canonicalizePhase(m[1]), name);
1845
2002
  }
1846
2003
  if (roadmapPhaseNumbers.length > 0) {
1847
2004
  phaseCount = roadmapPhaseNumbers.length;
@@ -1908,7 +2065,7 @@ function cmdInitMilestoneOp(cwd, raw) {
1908
2065
  all_phases_complete: phaseCount > 0 && phaseCount === completedPhases,
1909
2066
  archived_milestones: archivedMilestones,
1910
2067
  archive_count: archivedMilestones.length,
1911
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
2068
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
1912
2069
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
1913
2070
  state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
1914
2071
  archive_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningRoot(cwd), 'archive')),
@@ -1918,7 +2075,12 @@ function cmdInitMilestoneOp(cwd, raw) {
1918
2075
  }
1919
2076
  function cmdInitMapCodebase(cwd, raw) {
1920
2077
  const config = loadConfig(cwd);
1921
- const codebaseDir = node_path_1.default.join(planningRoot(cwd), 'codebase');
2078
+ // #3964: scoped like the payload's own codebase_dir/codebase_dir_exists
2079
+ // below (and verify.cts's codebase drift check) — has_maps/existing_maps
2080
+ // reading the flat root made the same payload claim a scoped codebase dir
2081
+ // exists while reporting zero maps, so map-codebase's Refresh/Skip gate
2082
+ // always forced a re-map under GSD_PROJECT.
2083
+ const codebaseDir = node_path_1.default.join(planningDir(cwd), 'codebase');
1922
2084
  let existingMaps = [];
1923
2085
  try {
1924
2086
  existingMaps = node_fs_1.default.readdirSync(codebaseDir).filter((f) => f.endsWith('.md'));
@@ -1935,11 +2097,14 @@ function cmdInitMapCodebase(cwd, raw) {
1935
2097
  date: clock_cjs_1.realClock.localToday(),
1936
2098
  timestamp: clock_cjs_1.realClock.nowIso(),
1937
2099
  // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
1938
- codebase_dir: toPosixPath(node_path_1.default.join(planningRoot(cwd), 'codebase')),
2100
+ // #3964: scoped like verify.cts's codebase drift check (planningDir, not
2101
+ // the flat planningRoot) so the two surfaces cannot disagree under
2102
+ // GSD_PROJECT.
2103
+ codebase_dir: toPosixPath(node_path_1.default.join(planningDir(cwd), 'codebase')),
1939
2104
  existing_maps: existingMaps,
1940
2105
  has_maps: existingMaps.length > 0,
1941
2106
  planning_exists: pathExistsInternal(cwd, '.planning'),
1942
- codebase_dir_exists: pathExistsInternal(cwd, '.planning/codebase'),
2107
+ codebase_dir_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'codebase')))),
1943
2108
  };
1944
2109
  output(withProjectRoot(cwd, result), raw);
1945
2110
  }
@@ -1995,6 +2160,9 @@ function cmdInitManager(cwd, raw) {
1995
2160
  let hasResearch = false;
1996
2161
  let lastActivity = null;
1997
2162
  let isActive = false;
2163
+ // #4014 (epic #3473 B4-unreadable): default COMPLETE — no directory at
2164
+ // all (dirMatch not found) is a genuine, not-unreadable answer.
2165
+ let contextScope = SCOPE.COMPLETE;
1998
2166
  let completion = buildPhaseCompletionProjection(cwd, phaseNum, null, planCount, summaryCount, _slashRuntime);
1999
2167
  try {
2000
2168
  // #3185 (ADR-3180 Decision 2) moved this lookup off the
@@ -2005,6 +2173,17 @@ function cmdInitManager(cwd, raw) {
2005
2173
  if (dirMatch) {
2006
2174
  const fullDir = node_path_1.default.join(phasesDir, dirMatch);
2007
2175
  const phaseDirRel = toPosixPath(node_path_1.default.relative(cwd, fullDir));
2176
+ // #4014 (epic #3473 B4-unreadable): this whole block used to swallow
2177
+ // ANY readdirSync failure below into the bare `catch { /* empty */ }`
2178
+ // at the bottom — an unreadable phase directory reported the exact
2179
+ // same `has_context: false` / `disk_status: 'no_directory'` as a
2180
+ // directory that never existed. findContextMdIn's directory-string
2181
+ // form never throws, so it can record the real scope (COMPLETE vs
2182
+ // UNREADABLE) here, BEFORE the pre-existing `fs.readdirSync(fullDir)`
2183
+ // immediately below (unchanged) throws on the exact same unreadable
2184
+ // directory and is caught exactly as before — this line is additive
2185
+ // only, the failure control-flow is untouched.
2186
+ contextScope = findContextMdIn(fullDir).scope;
2008
2187
  const phaseFiles = node_fs_1.default.readdirSync(fullDir);
2009
2188
  planCount = listPhasePlanFiles(fullDir).length;
2010
2189
  summaryCount = listPhaseSummaryFiles(fullDir).length;
@@ -2079,6 +2258,7 @@ function cmdInitManager(cwd, raw) {
2079
2258
  ...completion,
2080
2259
  last_activity: lastActivity,
2081
2260
  is_active: isActive,
2261
+ context_scope: contextScope,
2082
2262
  });
2083
2263
  }
2084
2264
  const MAX_NAME_WIDTH = 20;
@@ -2156,7 +2336,13 @@ function cmdInitManager(cwd, raw) {
2156
2336
  }
2157
2337
  let waitingSignal = null;
2158
2338
  try {
2159
- const waitingPath = node_path_1.default.join(cwd, '.planning', 'WAITING.json');
2339
+ // #3964: mirror cmdSignalWaiting's write locations exactly — `.gsd/`
2340
+ // first when it exists, else the project-aware planning dir — so the
2341
+ // signal is read from the project (and location) it is written to.
2342
+ const gsdWaiting = node_path_1.default.join(cwd, '.gsd', 'WAITING.json');
2343
+ const waitingPath = node_fs_1.default.existsSync(node_path_1.default.join(cwd, '.gsd'))
2344
+ ? gsdWaiting
2345
+ : node_path_1.default.join(planningDir(cwd), 'WAITING.json');
2160
2346
  const waitingRaw = (0, shell_command_projection_cjs_1.platformReadSync)(waitingPath);
2161
2347
  if (waitingRaw !== null) {
2162
2348
  waitingSignal = JSON.parse(waitingRaw);
@@ -2261,7 +2447,7 @@ function cmdInitManager(cwd, raw) {
2261
2447
  recommended_actions: filteredActions,
2262
2448
  waiting_signal: waitingSignal,
2263
2449
  all_complete: completedCount === nonBacklogPhases.length && nonBacklogPhases.length > 0,
2264
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
2450
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
2265
2451
  roadmap_exists: true,
2266
2452
  state_exists: true,
2267
2453
  manager_flags: managerFlags,
@@ -2449,7 +2635,7 @@ function cmdInitTransition(cwd, raw, options = {}) {
2449
2635
  * location has one source instead of two kept in sync by hand.
2450
2636
  * - `debugger_model` — `resolveModelInternal`, which IS what `query
2451
2637
  * resolve-model --pick model` returns (`cmdResolveModel`, src/commands.cts).
2452
- * - `tdd_mode` — the `Boolean(wf['tdd_mode'])` idiom `cmdInitExecutePhase` and
2638
+ * - `tdd_mode` — the `Boolean(config.tdd_mode)` idiom `cmdInitExecutePhase` and
2453
2639
  * `cmdInitPlanPhase` already use. `/gsd:debug` has no `--tdd` flag, so the
2454
2640
  * sibling handlers' `options['tdd'] ||` disjunct is deliberately omitted
2455
2641
  * rather than carried as a phantom.
@@ -2467,7 +2653,6 @@ function cmdInitTransition(cwd, raw, options = {}) {
2467
2653
  */
2468
2654
  function cmdInitDebug(cwd, raw, options = {}) {
2469
2655
  const config = loadConfig(cwd);
2470
- const wf = (config.workflow ?? {});
2471
2656
  const result = {
2472
2657
  commit_docs: config.commit_docs,
2473
2658
  // #2376: absolute — debug.md builds `debug_file_path` as
@@ -2475,7 +2660,7 @@ function cmdInitDebug(cwd, raw, options = {}) {
2475
2660
  // own cwd may differ from the orchestrator's.
2476
2661
  debug_dir: toPosixPath(planningPaths(cwd).debug),
2477
2662
  debugger_model: resolveModelInternal(cwd, 'gsd-debugger'),
2478
- tdd_mode: Boolean(wf['tdd_mode']),
2663
+ tdd_mode: Boolean(config.tdd_mode),
2479
2664
  diagnose: options['diagnose'] === true,
2480
2665
  };
2481
2666
  // Additive, optional field — degrades to null while `debug` has no key in
@@ -2617,7 +2802,11 @@ function cmdInitProgress(cwd, raw, options = {}) {
2617
2802
  const status = 'not_started';
2618
2803
  const phaseInfo = {
2619
2804
  number: num,
2620
- name: name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''),
2805
+ // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
2806
+ // (generateSlugInternal, core-utils.cts) rather than re-implementing
2807
+ // it. `maxLen: null` preserves this site's pre-migration untruncated
2808
+ // contract.
2809
+ name: coreUtils.generateSlugInternal(name, null) ?? '',
2621
2810
  directory: null,
2622
2811
  status,
2623
2812
  plan_count: 0,
@@ -2632,7 +2821,7 @@ function cmdInitProgress(cwd, raw, options = {}) {
2632
2821
  }
2633
2822
  }
2634
2823
  }
2635
- phases.sort((a, b) => parseInt(a['number'], 10) - parseInt(b['number'], 10));
2824
+ phases.sort((a, b) => comparePhaseNum(a['number'], b['number']));
2636
2825
  // #3581: the frontier is ROADMAP ORDER, not artifact presence. The disk loop
2637
2826
  // above could claim nextPhase from a stray out-of-order artifact directory
2638
2827
  // (a phase-9 UAT evidence dir while roadmap phase 8 was pending and
@@ -2691,9 +2880,13 @@ function cmdInitProgress(cwd, raw, options = {}) {
2691
2880
  paused_at: pausedAt,
2692
2881
  has_work_in_progress: !!currentPhase,
2693
2882
  phase_mvp_mode: phaseMvpMode,
2694
- project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
2883
+ project_exists: pathExistsInternal(cwd, toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'PROJECT.md')))),
2695
2884
  roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
2696
2885
  state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
2886
+ // #4040: partial-init discriminator (see buildInitCompletenessFields) —
2887
+ // also adds planning_exists / requirements_exists / milestones_exists so
2888
+ // progress.md's init_context routing never has to fall back to Glob.
2889
+ ...buildInitCompletenessFields(cwd),
2697
2890
  // #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
2698
2891
  state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
2699
2892
  roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
@@ -3326,7 +3519,9 @@ function cmdSkillManifest(cwd, args, raw) {
3326
3519
  const skillsDir = skillsDirIdx >= 0 && args[skillsDirIdx + 1] ? args[skillsDirIdx + 1] : null;
3327
3520
  const manifest = buildSkillManifest(cwd, skillsDir);
3328
3521
  if (args.includes('--write')) {
3329
- const planDir = node_path_1.default.join(cwd, '.planning');
3522
+ // #3964: write beside the project's own artifacts (planningDir is
3523
+ // project- and workstream-aware), not the flat root.
3524
+ const planDir = planningDir(cwd);
3330
3525
  if (node_fs_1.default.existsSync(planDir)) {
3331
3526
  const manifestPath = node_path_1.default.join(planDir, 'skill-manifest.json');
3332
3527
  (0, shell_command_projection_cjs_1.platformWriteSync)(manifestPath, JSON.stringify(manifest, null, 2));
@@ -3340,6 +3535,7 @@ module.exports = {
3340
3535
  cmdInitNewProject,
3341
3536
  cmdInitNewMilestone,
3342
3537
  cmdInitQuick,
3538
+ cmdInitQuickBatch,
3343
3539
  cmdInitIngestDocs,
3344
3540
  cmdInitOnboard,
3345
3541
  cmdInitResume,