@opengsd/gsd-core 1.14.0 → 1.16.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 (551) 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 +85 -5
  4. package/README.ja-JP.md +3 -3
  5. package/README.ko-KR.md +3 -3
  6. package/README.pt-BR.md +3 -3
  7. package/README.zh-CN.md +3 -3
  8. package/agents/gsd-code-fixer.compact.md +7 -6
  9. package/agents/gsd-code-fixer.md +9 -8
  10. package/agents/gsd-code-reviewer.compact.md +5 -3
  11. package/agents/gsd-code-reviewer.md +8 -6
  12. package/agents/gsd-debug-session-manager.compact.md +17 -2
  13. package/agents/gsd-debug-session-manager.md +17 -2
  14. package/agents/gsd-debugger.md +3 -3
  15. package/agents/gsd-eval-auditor.compact.md +1 -1
  16. package/agents/gsd-eval-auditor.md +1 -1
  17. package/agents/gsd-executor.md +17 -12
  18. package/agents/gsd-intel-updater.compact.md +1 -1
  19. package/agents/gsd-intel-updater.md +1 -1
  20. package/agents/gsd-mempalace-curator.md +2 -2
  21. package/agents/gsd-phase-researcher.md +19 -11
  22. package/agents/gsd-plan-checker.md +15 -9
  23. package/agents/gsd-planner.md +15 -11
  24. package/agents/gsd-project-researcher.compact.md +1 -1
  25. package/agents/gsd-project-researcher.md +1 -1
  26. package/agents/gsd-research-synthesizer.compact.md +1 -1
  27. package/agents/gsd-research-synthesizer.md +1 -1
  28. package/agents/gsd-ui-auditor.compact.md +21 -30
  29. package/agents/gsd-ui-auditor.md +166 -37
  30. package/agents/gsd-ui-researcher.compact.md +1 -1
  31. package/agents/gsd-ui-researcher.md +1 -1
  32. package/agents/gsd-verifier.md +37 -14
  33. package/bin/install.js +764 -287
  34. package/commands/gsd/add-tests.md +6 -1
  35. package/commands/gsd/ai-integration-phase.md +6 -1
  36. package/commands/gsd/audit-fix.md +5 -0
  37. package/commands/gsd/audit-milestone.md +6 -1
  38. package/commands/gsd/autonomous.md +7 -2
  39. package/commands/gsd/capture.md +9 -5
  40. package/commands/gsd/code-review.md +7 -2
  41. package/commands/gsd/complete-milestone.md +4 -0
  42. package/commands/gsd/config.md +7 -3
  43. package/commands/gsd/debug.md +11 -7
  44. package/commands/gsd/discuss-phase.md +7 -3
  45. package/commands/gsd/docs-update.md +12 -7
  46. package/commands/gsd/eval-review.md +6 -1
  47. package/commands/gsd/execute-phase.md +12 -7
  48. package/commands/gsd/extract-learnings.md +5 -0
  49. package/commands/gsd/fast.md +4 -0
  50. package/commands/gsd/forensics.md +5 -1
  51. package/commands/gsd/graphify.md +10 -6
  52. package/commands/gsd/health.md +5 -0
  53. package/commands/gsd/help.md +7 -2
  54. package/commands/gsd/import.md +7 -3
  55. package/commands/gsd/inbox.md +5 -0
  56. package/commands/gsd/ingest-docs.md +5 -1
  57. package/commands/gsd/manager.md +6 -1
  58. package/commands/gsd/map-codebase.md +7 -3
  59. package/commands/gsd/mempalace-capture.md +12 -4
  60. package/commands/gsd/mempalace-recall.md +5 -1
  61. package/commands/gsd/milestone-summary.md +5 -1
  62. package/commands/gsd/mvp-phase.md +8 -3
  63. package/commands/gsd/new-milestone.md +6 -1
  64. package/commands/gsd/new-project.md +5 -0
  65. package/commands/gsd/next.md +6 -1
  66. package/commands/gsd/ns-context.md +4 -0
  67. package/commands/gsd/ns-ideate.md +4 -0
  68. package/commands/gsd/ns-manage.md +4 -0
  69. package/commands/gsd/ns-project.md +4 -0
  70. package/commands/gsd/ns-review.md +4 -0
  71. package/commands/gsd/ns-workflow.md +4 -0
  72. package/commands/gsd/onboard.md +6 -1
  73. package/commands/gsd/pause-work.md +5 -1
  74. package/commands/gsd/phase.md +8 -4
  75. package/commands/gsd/plan-phase.md +6 -1
  76. package/commands/gsd/plan-review-convergence.md +11 -7
  77. package/commands/gsd/pr-branch.md +4 -0
  78. package/commands/gsd/profile-user.md +5 -1
  79. package/commands/gsd/progress.md +7 -2
  80. package/commands/gsd/quick-batch.md +21 -9
  81. package/commands/gsd/quick.md +12 -7
  82. package/commands/gsd/review.md +7 -4
  83. package/commands/gsd/secure-phase.md +6 -1
  84. package/commands/gsd/ship.md +5 -0
  85. package/commands/gsd/sketch.md +7 -2
  86. package/commands/gsd/spec-phase.md +5 -1
  87. package/commands/gsd/spike.md +8 -3
  88. package/commands/gsd/surface.md +5 -1
  89. package/commands/gsd/thread.md +4 -0
  90. package/commands/gsd/ui-phase.md +6 -1
  91. package/commands/gsd/ui-review.md +6 -1
  92. package/commands/gsd/ultraplan-phase.md +5 -1
  93. package/commands/gsd/undo.md +5 -1
  94. package/commands/gsd/update.md +6 -2
  95. package/commands/gsd/validate-phase.md +6 -1
  96. package/commands/gsd/verify-work.md +6 -1
  97. package/commands/gsd/workspace.md +7 -3
  98. package/gsd-core/bin/gsd-tools.cjs +477 -78
  99. package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
  100. package/gsd-core/bin/lib/adr-parser.cjs +3 -1
  101. package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
  102. package/gsd-core/bin/lib/audit.cjs +144 -42
  103. package/gsd-core/bin/lib/broken-windows.cjs +13 -13
  104. package/gsd-core/bin/lib/capability-activation.cjs +9 -4
  105. package/gsd-core/bin/lib/capability-registry.cjs +197 -222
  106. package/gsd-core/bin/lib/capability-validator.cjs +16 -1
  107. package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
  108. package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
  109. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
  110. package/gsd-core/bin/lib/cli-exit.cjs +12 -0
  111. package/gsd-core/bin/lib/codex-agent-toml.cjs +32 -33
  112. package/gsd-core/bin/lib/command-aliases.cjs +7 -0
  113. package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
  114. package/gsd-core/bin/lib/commands.cjs +343 -207
  115. package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
  116. package/gsd-core/bin/lib/config-loader.cjs +65 -4
  117. package/gsd-core/bin/lib/config.cjs +76 -19
  118. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  119. package/gsd-core/bin/lib/coverage.cjs +4 -8
  120. package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
  121. package/gsd-core/bin/lib/decisions.cjs +30 -14
  122. package/gsd-core/bin/lib/drift.cjs +177 -42
  123. package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
  124. package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
  125. package/gsd-core/bin/lib/frontmatter.cjs +426 -234
  126. package/gsd-core/bin/lib/gap-checker.cjs +72 -29
  127. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
  128. package/gsd-core/bin/lib/gate-args.cjs +53 -0
  129. package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
  130. package/gsd-core/bin/lib/gate-config.cjs +46 -0
  131. package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
  132. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
  133. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
  134. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
  135. package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
  136. package/gsd-core/bin/lib/gate-exit.cjs +27 -0
  137. package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
  138. package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
  139. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
  140. package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
  141. package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
  142. package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
  143. package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
  144. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
  145. package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
  146. package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
  147. package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
  148. package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
  149. package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
  150. package/gsd-core/bin/lib/graphify.cjs +10 -2
  151. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
  152. package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
  153. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  154. package/gsd-core/bin/lib/init.cjs +364 -132
  155. package/gsd-core/bin/lib/install-engine.cjs +30 -33
  156. package/gsd-core/bin/lib/install-profiles.cjs +7 -4
  157. package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
  158. package/gsd-core/bin/lib/io.cjs +122 -3
  159. package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
  160. package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
  161. package/gsd-core/bin/lib/milestone.cjs +37 -6
  162. package/gsd-core/bin/lib/model-resolver.cjs +171 -62
  163. package/gsd-core/bin/lib/observability/event.cjs +1 -1
  164. package/gsd-core/bin/lib/observability/logger.cjs +46 -1
  165. package/gsd-core/bin/lib/pattern.cjs +10 -0
  166. package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
  167. package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
  168. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  169. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  170. package/gsd-core/bin/lib/phase-id.cjs +110 -8
  171. package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
  172. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  173. package/gsd-core/bin/lib/phase-status.cjs +360 -0
  174. package/gsd-core/bin/lib/phase.cjs +489 -88
  175. package/gsd-core/bin/lib/plan-document.cjs +142 -20
  176. package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
  177. package/gsd-core/bin/lib/planning-document.cjs +692 -0
  178. package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
  179. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
  180. package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
  181. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  182. package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
  183. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  184. package/gsd-core/bin/lib/profile-output.cjs +6 -3
  185. package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
  186. package/gsd-core/bin/lib/project-root.cjs +41 -2
  187. package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
  188. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
  189. package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
  190. package/gsd-core/bin/lib/report-parser.cjs +269 -0
  191. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  192. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  193. package/gsd-core/bin/lib/roadmap-command-router.cjs +25 -19
  194. package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
  195. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
  196. package/gsd-core/bin/lib/roadmap.cjs +405 -88
  197. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
  198. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
  199. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
  200. package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
  201. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
  202. package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
  203. package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
  204. package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
  205. package/gsd-core/bin/lib/smart-entry.cjs +19 -3
  206. package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
  207. package/gsd-core/bin/lib/state-contract.cjs +15 -18
  208. package/gsd-core/bin/lib/state-document.cjs +100 -22
  209. package/gsd-core/bin/lib/state-transition.cjs +39 -2
  210. package/gsd-core/bin/lib/state.cjs +256 -105
  211. package/gsd-core/bin/lib/surface.cjs +19 -2
  212. package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
  213. package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
  214. package/gsd-core/bin/lib/uat.cjs +432 -7
  215. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  216. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
  217. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  218. package/gsd-core/bin/lib/vendor/README.md +31 -9
  219. package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
  220. package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
  221. package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
  222. package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
  223. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  224. package/gsd-core/bin/lib/verification.cjs +1378 -274
  225. package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
  226. package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
  227. package/gsd-core/bin/lib/verify.cjs +357 -531
  228. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
  229. package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
  230. package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
  231. package/gsd-core/bin/lib/workstream.cjs +11 -2
  232. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  233. package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
  234. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -0
  235. package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
  236. package/gsd-core/references/autonomous-smart-discuss.md +2 -1
  237. package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
  238. package/gsd-core/references/checkpoints.md +5 -3
  239. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  240. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  241. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  242. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  243. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  244. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  245. package/gsd-core/references/edge-probe.md +195 -21
  246. package/gsd-core/references/execute-mvp-tdd.md +5 -10
  247. package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
  248. package/gsd-core/references/execute-phase-response-language.md +1 -1
  249. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  250. package/gsd-core/references/gsd-run-resolver.md +1 -1
  251. package/gsd-core/references/loop-hook-dispatch.md +7 -1
  252. package/gsd-core/references/model-profiles.md +1 -1
  253. package/gsd-core/references/offer-next.md +1 -1
  254. package/gsd-core/references/phase-argument-parsing.md +9 -7
  255. package/gsd-core/references/phase-id-convention.md +28 -0
  256. package/gsd-core/references/planner-gap-closure.md +2 -0
  257. package/gsd-core/references/planner-load-graph-context.md +24 -13
  258. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  259. package/gsd-core/references/planning-config.md +12 -3
  260. package/gsd-core/references/spidr-splitting.md +1 -1
  261. package/gsd-core/references/tdd.md +37 -8
  262. package/gsd-core/references/ui-consideration-probe.md +10 -5
  263. package/gsd-core/references/verifier-phase-gates.md +5 -2
  264. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  265. package/gsd-core/references/verify-mvp-mode.md +2 -2
  266. package/gsd-core/references/workstream-flag.md +33 -3
  267. package/gsd-core/references/worktree-path-safety.md +321 -0
  268. package/gsd-core/templates/README.md +1 -1
  269. package/gsd-core/templates/UAT.md +17 -1
  270. package/gsd-core/templates/config.json +2 -11
  271. package/gsd-core/templates/verification-report.md +1 -1
  272. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  273. package/gsd-core/workflows/add-backlog.md +1 -1
  274. package/gsd-core/workflows/add-phase.md +8 -7
  275. package/gsd-core/workflows/add-tests.md +4 -3
  276. package/gsd-core/workflows/add-todo.md +6 -5
  277. package/gsd-core/workflows/ai-integration-phase.md +13 -4
  278. package/gsd-core/workflows/audit-fix.md +1 -1
  279. package/gsd-core/workflows/audit-milestone.md +4 -3
  280. package/gsd-core/workflows/audit-uat.md +1 -1
  281. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  282. package/gsd-core/workflows/autonomous.md +43 -23
  283. package/gsd-core/workflows/check-todos.md +7 -6
  284. package/gsd-core/workflows/cleanup.md +2 -2
  285. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  286. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
  287. package/gsd-core/workflows/code-review-fix.md +112 -25
  288. package/gsd-core/workflows/code-review.md +146 -135
  289. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
  290. package/gsd-core/workflows/complete-milestone.md +13 -8
  291. package/gsd-core/workflows/debug.md +32 -7
  292. package/gsd-core/workflows/diagnose-issues.md +3 -2
  293. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  294. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  295. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  296. package/gsd-core/workflows/discuss-phase.md +4 -3
  297. package/gsd-core/workflows/do.md +2 -2
  298. package/gsd-core/workflows/docs-update.md +6 -5
  299. package/gsd-core/workflows/edit-phase.md +4 -3
  300. package/gsd-core/workflows/eval-review.md +14 -5
  301. package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
  302. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
  303. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
  304. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
  305. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
  306. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
  307. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
  308. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  309. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  310. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  311. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  312. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  313. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  314. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
  315. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  316. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  317. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
  318. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
  319. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  320. package/gsd-core/workflows/execute-phase.md +96 -178
  321. package/gsd-core/workflows/execute-plan.md +18 -23
  322. package/gsd-core/workflows/explore.md +4 -4
  323. package/gsd-core/workflows/extract-learnings.md +4 -2
  324. package/gsd-core/workflows/fast.md +1 -1
  325. package/gsd-core/workflows/forensics.md +1 -1
  326. package/gsd-core/workflows/graduation.md +1 -1
  327. package/gsd-core/workflows/health.md +3 -2
  328. package/gsd-core/workflows/help/modes/full.compact.md +3 -3
  329. package/gsd-core/workflows/help/modes/full.md +5 -5
  330. package/gsd-core/workflows/help/modes/topic.md +15 -5
  331. package/gsd-core/workflows/import.md +4 -3
  332. package/gsd-core/workflows/inbox.md +2 -2
  333. package/gsd-core/workflows/ingest-docs.md +3 -3
  334. package/gsd-core/workflows/insert-phase.md +4 -3
  335. package/gsd-core/workflows/list-seeds.md +1 -1
  336. package/gsd-core/workflows/list-workspaces.md +1 -1
  337. package/gsd-core/workflows/manager.md +6 -4
  338. package/gsd-core/workflows/map-codebase.md +5 -4
  339. package/gsd-core/workflows/milestone-summary.md +3 -2
  340. package/gsd-core/workflows/mvp-phase.md +14 -14
  341. package/gsd-core/workflows/new-milestone.md +11 -11
  342. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  343. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  344. package/gsd-core/workflows/new-project.md +7 -7
  345. package/gsd-core/workflows/new-workspace.md +2 -2
  346. package/gsd-core/workflows/next.md +1 -1
  347. package/gsd-core/workflows/note.md +1 -1
  348. package/gsd-core/workflows/onboard.md +1 -1
  349. package/gsd-core/workflows/pause-work.md +2 -2
  350. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  351. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  352. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
  353. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  354. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  355. package/gsd-core/workflows/plan-phase.md +50 -24
  356. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  357. package/gsd-core/workflows/plant-seed.md +62 -20
  358. package/gsd-core/workflows/pr-branch.md +113 -13
  359. package/gsd-core/workflows/profile-user.md +2 -2
  360. package/gsd-core/workflows/progress.md +19 -49
  361. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
  362. package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
  363. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
  364. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  365. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  366. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  367. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  368. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  369. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  370. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
  371. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  372. package/gsd-core/workflows/quick-batch.md +15 -10
  373. package/gsd-core/workflows/quick.md +62 -39
  374. package/gsd-core/workflows/reapply-patches.md +9 -3
  375. package/gsd-core/workflows/remove-phase.md +3 -2
  376. package/gsd-core/workflows/remove-workspace.md +2 -2
  377. package/gsd-core/workflows/resume-project.md +3 -2
  378. package/gsd-core/workflows/review.md +33 -17
  379. package/gsd-core/workflows/scan.md +3 -2
  380. package/gsd-core/workflows/secure-phase.md +13 -13
  381. package/gsd-core/workflows/settings-advanced.md +30 -10
  382. package/gsd-core/workflows/settings-integrations.md +2 -3
  383. package/gsd-core/workflows/settings.md +4 -4
  384. package/gsd-core/workflows/ship.md +14 -13
  385. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  386. package/gsd-core/workflows/sketch.md +1 -1
  387. package/gsd-core/workflows/smart-entry.md +2 -2
  388. package/gsd-core/workflows/spec-phase.md +15 -5
  389. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  390. package/gsd-core/workflows/spike.md +1 -1
  391. package/gsd-core/workflows/stats.md +1 -1
  392. package/gsd-core/workflows/sync-skills.md +5 -5
  393. package/gsd-core/workflows/thread.md +2 -2
  394. package/gsd-core/workflows/transition.md +13 -23
  395. package/gsd-core/workflows/ui-phase.md +48 -11
  396. package/gsd-core/workflows/ui-review.md +21 -6
  397. package/gsd-core/workflows/ultraplan-phase.md +3 -2
  398. package/gsd-core/workflows/undo.md +339 -20
  399. package/gsd-core/workflows/update.md +7 -7
  400. package/gsd-core/workflows/validate-phase.md +12 -13
  401. package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
  402. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  403. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
  404. package/gsd-core/workflows/verify-work.md +129 -55
  405. package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
  406. package/hooks/dist/gsd-check-update-worker.js +8 -0
  407. package/hooks/dist/gsd-check-update.js +8 -0
  408. package/hooks/dist/gsd-context-monitor.js +31 -8
  409. package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
  410. package/hooks/dist/gsd-secret-read-guard.js +161 -4
  411. package/hooks/dist/gsd-statusline.js +85 -20
  412. package/hooks/dist/gsd-update-banner.js +8 -0
  413. package/hooks/dist/gsd-validate-commit.sh +63 -4
  414. package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
  415. package/hooks/dist/gsd-workflow-guard.js +5 -4
  416. package/hooks/dist/gsd-worktree-path-guard.js +6 -2
  417. package/hooks/dist/lib/cli-exit.js +12 -0
  418. package/hooks/dist/lib/git-probe.js +17 -1
  419. package/hooks/dist/lib/isolation-sentinel.js +2 -2
  420. package/hooks/gsd-agent-isolation-guard.js +32 -0
  421. package/hooks/gsd-check-update-worker.js +8 -0
  422. package/hooks/gsd-check-update.js +8 -0
  423. package/hooks/gsd-context-monitor.js +31 -8
  424. package/hooks/gsd-cursor-subagent-start.js +8 -0
  425. package/hooks/gsd-secret-read-guard.js +161 -4
  426. package/hooks/gsd-statusline.js +85 -20
  427. package/hooks/gsd-update-banner.js +8 -0
  428. package/hooks/gsd-validate-commit.sh +63 -4
  429. package/hooks/gsd-windsurf-pre-write.js +11 -2
  430. package/hooks/gsd-workflow-guard.js +5 -4
  431. package/hooks/gsd-worktree-path-guard.js +6 -2
  432. package/hooks/hooks.json +5 -5
  433. package/hooks/lib/cli-exit.js +12 -0
  434. package/hooks/lib/git-probe.js +17 -1
  435. package/hooks/lib/isolation-sentinel.js +2 -2
  436. package/package.json +22 -4
  437. package/scripts/build-hooks.js +15 -6
  438. package/scripts/changeset/parse.cjs +52 -4
  439. package/scripts/check-contract-drift.cjs +127 -11
  440. package/scripts/ci-timeout-report.cjs +770 -4
  441. package/scripts/command-contract-helpers.cjs +15 -8
  442. package/scripts/docs-guard-registry.cjs +34 -0
  443. package/scripts/gen-features.cjs +13 -8
  444. package/scripts/gen-hooks-cli-exit.cjs +12 -28
  445. package/scripts/gen-loop-host-contract.cjs +79 -1
  446. package/scripts/gen-platform-conformance-tier.cjs +187 -1
  447. package/scripts/gen-plugin-skills.cjs +87 -1
  448. package/scripts/gen-research-agents.cjs +24 -31
  449. package/scripts/gen-scripts-cli-exit.cjs +30 -3
  450. package/scripts/gen-test-timings.cjs +32 -7
  451. package/scripts/lib/cli-exit.cjs +12 -0
  452. package/scripts/lib/macos-conformance-tier.generated.cjs +34 -2
  453. package/scripts/lib/ndjson-reporter.cjs +31 -5
  454. package/scripts/lib/platform-conformance-tier.generated.cjs +45 -5
  455. package/scripts/lib/registration-ledger-preload.cjs +155 -0
  456. package/scripts/lib/vendor-bundle.cjs +59 -0
  457. package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
  458. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  459. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  460. package/scripts/lint-completion-predicate-drift.cjs +18 -19
  461. package/scripts/lint-descriptions.cjs +7 -3
  462. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +38 -1
  463. package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
  464. package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
  465. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
  466. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  467. package/scripts/lint-phase-enumeration-drift.cjs +12 -8
  468. package/scripts/lint-phase-id-drift.cjs +319 -5
  469. package/scripts/lint-planning-document-positive-control.cjs +329 -0
  470. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  471. package/scripts/lint-response-language-coverage.cjs +3 -0
  472. package/scripts/lint-retired-runtime-name.cjs +619 -0
  473. package/scripts/lint-skill-deps.cjs +7 -3
  474. package/scripts/lint-state-write-path-drift.cjs +93 -0
  475. package/scripts/lint-test-file-count.allowlist.json +38 -9
  476. package/scripts/lint-test-file-count.cjs +34 -1
  477. package/scripts/lint-vendored-deps.cjs +41 -5
  478. package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
  479. package/scripts/mutation-matrix.cjs +50 -5
  480. package/scripts/prompt-injection-scan.sh +4 -0
  481. package/scripts/release-tarball-smoke.cjs +194 -1
  482. package/scripts/require-issue-link-policy.cjs +6 -2
  483. package/scripts/sync-runtime-launcher.cjs +184 -2
  484. package/scripts/verify-npm-publish.cjs +76 -20
  485. package/skills/gsd-add-tests/SKILL.md +6 -1
  486. package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
  487. package/skills/gsd-audit-fix/SKILL.md +5 -0
  488. package/skills/gsd-audit-milestone/SKILL.md +6 -1
  489. package/skills/gsd-autonomous/SKILL.md +7 -2
  490. package/skills/gsd-capture/SKILL.md +9 -5
  491. package/skills/gsd-code-review/SKILL.md +7 -2
  492. package/skills/gsd-complete-milestone/SKILL.md +4 -0
  493. package/skills/gsd-config/SKILL.md +8 -4
  494. package/skills/gsd-debug/SKILL.md +11 -7
  495. package/skills/gsd-discuss-phase/SKILL.md +7 -3
  496. package/skills/gsd-docs-update/SKILL.md +12 -7
  497. package/skills/gsd-eval-review/SKILL.md +6 -1
  498. package/skills/gsd-execute-phase/SKILL.md +12 -7
  499. package/skills/gsd-extract-learnings/SKILL.md +5 -0
  500. package/skills/gsd-fast/SKILL.md +4 -0
  501. package/skills/gsd-forensics/SKILL.md +5 -1
  502. package/skills/gsd-graphify/SKILL.md +10 -6
  503. package/skills/gsd-health/SKILL.md +5 -0
  504. package/skills/gsd-help/SKILL.md +7 -2
  505. package/skills/gsd-import/SKILL.md +7 -3
  506. package/skills/gsd-inbox/SKILL.md +5 -0
  507. package/skills/gsd-ingest-docs/SKILL.md +5 -1
  508. package/skills/gsd-manager/SKILL.md +6 -1
  509. package/skills/gsd-map-codebase/SKILL.md +7 -3
  510. package/skills/gsd-mempalace-capture/SKILL.md +12 -4
  511. package/skills/gsd-mempalace-recall/SKILL.md +5 -1
  512. package/skills/gsd-milestone-summary/SKILL.md +5 -1
  513. package/skills/gsd-mvp-phase/SKILL.md +8 -3
  514. package/skills/gsd-new-milestone/SKILL.md +6 -1
  515. package/skills/gsd-new-project/SKILL.md +5 -0
  516. package/skills/gsd-next/SKILL.md +6 -1
  517. package/skills/gsd-ns-context/SKILL.md +4 -0
  518. package/skills/gsd-ns-ideate/SKILL.md +4 -0
  519. package/skills/gsd-ns-manage/SKILL.md +4 -0
  520. package/skills/gsd-ns-project/SKILL.md +4 -0
  521. package/skills/gsd-ns-review/SKILL.md +4 -0
  522. package/skills/gsd-ns-workflow/SKILL.md +4 -0
  523. package/skills/gsd-onboard/SKILL.md +6 -1
  524. package/skills/gsd-pause-work/SKILL.md +5 -1
  525. package/skills/gsd-phase/SKILL.md +8 -4
  526. package/skills/gsd-plan-phase/SKILL.md +6 -1
  527. package/skills/gsd-plan-review-convergence/SKILL.md +10 -6
  528. package/skills/gsd-pr-branch/SKILL.md +4 -0
  529. package/skills/gsd-profile-user/SKILL.md +5 -1
  530. package/skills/gsd-progress/SKILL.md +7 -2
  531. package/skills/gsd-quick/SKILL.md +16 -10
  532. package/skills/gsd-quick-batch/SKILL.md +21 -9
  533. package/skills/gsd-review/SKILL.md +7 -4
  534. package/skills/gsd-review-backlog/SKILL.md +3 -2
  535. package/skills/gsd-secure-phase/SKILL.md +6 -1
  536. package/skills/gsd-ship/SKILL.md +5 -0
  537. package/skills/gsd-sketch/SKILL.md +7 -2
  538. package/skills/gsd-spec-phase/SKILL.md +5 -1
  539. package/skills/gsd-spike/SKILL.md +8 -3
  540. package/skills/gsd-surface/SKILL.md +5 -1
  541. package/skills/gsd-thread/SKILL.md +4 -0
  542. package/skills/gsd-ui-phase/SKILL.md +6 -1
  543. package/skills/gsd-ui-review/SKILL.md +6 -1
  544. package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
  545. package/skills/gsd-undo/SKILL.md +5 -1
  546. package/skills/gsd-update/SKILL.md +6 -2
  547. package/skills/gsd-validate-phase/SKILL.md +6 -1
  548. package/skills/gsd-verify-work/SKILL.md +6 -1
  549. package/skills/gsd-workspace/SKILL.md +7 -3
  550. package/skills/gsd-workstreams/SKILL.md +6 -6
  551. package/vscode/package.json +1 -1
@@ -571,6 +571,55 @@ function sliceMilestoneWindow(content, version) {
571
571
  return null;
572
572
  return content.slice(selected.index, computeMilestoneSectionEnd(content, selected[0], selected.index));
573
573
  }
574
+ /**
575
+ * Enumerate the milestone section ranges recognized by the ROADMAP readers.
576
+ * Markdown boundaries reuse the reader's heading tokenizer, milestone-signal
577
+ * vocabulary, name/version extractor, and section-end owner. Collapsed
578
+ * archives reuse the same `<details><summary>` shape handled by
579
+ * `extractCurrentMilestoneScoped`.
580
+ */
581
+ function milestoneSections(content) {
582
+ const sections = [];
583
+ const headings = (0, markdown_sectionizer_cjs_1.tokenizeHeadings)(content);
584
+ for (const heading of headings) {
585
+ if (heading.level < 1 || heading.level > 3)
586
+ continue;
587
+ if (/^Phase\s+\S/i.test(heading.text))
588
+ continue;
589
+ if (!MILESTONE_HEADING_SIGNAL_PATTERN.test(heading.text))
590
+ continue;
591
+ const extracted = extractMilestoneHeadingName(heading.text);
592
+ const version = extracted?.version ?? null;
593
+ const versionMajor = version?.match(/^v(\d+)/i);
594
+ const milestoneInt = versionMajor ? parseInt(versionMajor[1], 10) : null;
595
+ const lineEnd = content.indexOf('\n', heading.offset);
596
+ const fullLine = content.slice(heading.offset, lineEnd === -1 ? content.length : lineEnd);
597
+ sections.push({
598
+ start: heading.offset,
599
+ end: computeMilestoneSectionEnd(content, fullLine, heading.offset, undefined, headings),
600
+ version,
601
+ milestoneInt: milestoneInt !== null && Number.isSafeInteger(milestoneInt) ? milestoneInt : null,
602
+ });
603
+ }
604
+ const detailsPattern = /<details\b[^>]*>[\s\S]*?<\/details>/gi;
605
+ let detailsMatch;
606
+ while ((detailsMatch = detailsPattern.exec(content)) !== null) {
607
+ const summary = detailsMatch[0].match(/<summary[^>]*>([^<]*)<\/summary>/i)?.[1]?.trim() ?? '';
608
+ if (!MILESTONE_HEADING_SIGNAL_PATTERN.test(summary))
609
+ continue;
610
+ const extracted = extractMilestoneHeadingName(summary);
611
+ const version = extracted?.version ?? null;
612
+ const versionMajor = version?.match(/^v(\d+)/i);
613
+ const milestoneInt = versionMajor ? parseInt(versionMajor[1], 10) : null;
614
+ sections.push({
615
+ start: detailsMatch.index,
616
+ end: detailsMatch.index + detailsMatch[0].length,
617
+ version,
618
+ milestoneInt: milestoneInt !== null && Number.isSafeInteger(milestoneInt) ? milestoneInt : null,
619
+ });
620
+ }
621
+ return sections.sort((a, b) => a.start - b.start || a.end - b.end);
622
+ }
574
623
  /**
575
624
  * #3184: counts RAW phase references — a `#{2,4} Phase <id>:` heading
576
625
  * (fence-aware via `tokenizeHeadings`) or a `#2199` bullet entry — BEFORE any
@@ -600,17 +649,37 @@ function sliceMilestoneWindow(content, version) {
600
649
  // decoy `### [GSD.04] Notes:` outside the window manufactured a false V005
601
650
  // while suppressing the correct V004. The digit anchor forecloses both.
602
651
  const BRACKET_PHASE_ENTRY_HEADING_RE = new RegExp(`^${PHASE_HEADING_PREFIX_SRC}${PHASE_NUMBER_TOKEN_SOURCE}${OPTIONAL_PHASE_TAG_SOURCE}\\s*:`, 'i');
652
+ // #1729: `(?:\s*\([^)\n]{0,200}\))?` tolerates a pre-colon ( ) tag (literal
653
+ // mirror of OPTIONAL_PHASE_TAG_SOURCE). Hoisted out of hasPhaseEntries (#4144
654
+ // round 5 Blocker 1) so a consumer OUTSIDE this file's own phase-entry count —
655
+ // the bracket roadmap migrator's "phase-like but unparsed" refusal
656
+ // (src/roadmap-upgrade.cts) — can ask "is this heading text a phase heading
657
+ // by the readers' own rules" without re-deriving the pattern. A heading with
658
+ // no phase-number token and no trailing colon (`## Phase Details`, `##
659
+ // Phase Lifecycle`, `### Phase Notes`) is NOT a phase heading by this
660
+ // grammar — it is an ordinary section heading that happens to start with the
661
+ // word "Phase".
662
+ const PHASE_HEADING_TEXT_RE = /^(?:\[[^\]]{1,200}\]\s*)?Phase\s+([\w][\w.-]*)(?:\s*\([^)\n]{0,200}\))?\s*:/i;
663
+ /**
664
+ * #4144 round 5 Blocker 1: whether `headingText` — a heading's text with its
665
+ * leading `#{1,6}` markers and surrounding whitespace already stripped
666
+ * (`tokenizeHeadings`'s own `h.text`, or the equivalent for a line a caller
667
+ * already knows is a `#{2,4}` heading) — is a phase heading by the readers'
668
+ * own grammar. The single owner of this test; `hasPhaseEntries` below is
669
+ * itself just the first caller.
670
+ */
671
+ function isPhaseHeadingText(headingText) {
672
+ return PHASE_HEADING_TEXT_RE.test(headingText);
673
+ }
603
674
  function hasPhaseEntries(markdown, phaseIdConvention) {
604
- // #1729: `(?:\s*\([^)\n]{0,200}\))?` tolerates a pre-colon ( ) tag (literal mirror of OPTIONAL_PHASE_TAG_SOURCE).
605
675
  // #3641: the widened grammar engages ONLY when the resolved convention is
606
676
  // 'bracket' — a project that has not opted in runs the legacy pattern
607
677
  // alone, byte-identically.
608
- const phaseHeadingPattern = /^(?:\[[^\]]{1,200}\]\s*)?Phase\s+([\w][\w.-]*)(?:\s*\([^)\n]{0,200}\))?\s*:/i;
609
678
  const bracketMode = phaseIdConvention === 'bracket';
610
679
  for (const h of (0, markdown_sectionizer_cjs_1.tokenizeHeadings)(markdown)) {
611
680
  if (h.level < 2 || h.level > 4)
612
681
  continue;
613
- if (phaseHeadingPattern.test(h.text))
682
+ if (isPhaseHeadingText(h.text))
614
683
  return true;
615
684
  if (bracketMode && BRACKET_PHASE_ENTRY_HEADING_RE.test(h.text))
616
685
  return true;
@@ -671,6 +740,23 @@ function collectTablePhaseRows(window) {
671
740
  }
672
741
  return rows;
673
742
  }
743
+ /**
744
+ * True when `content` contains a GFM table whose header row is phase-listing
745
+ * SHAPED (`| Phase | ... |`), regardless of whether it also declares a `Name`
746
+ * column. `collectTablePhaseRows` correctly refuses to mint a phase from a
747
+ * `| Phase | Status |`-shaped table (no name column, so no declaration) —
748
+ * but that table's mere presence still signals this roadmap has moved to
749
+ * table-based tracking, not checklist-based tracking. Callers that decide
750
+ * whether to treat bare checklist entries as phase declarations (#4899's
751
+ * roadmap.cts synthesis fallback) must see this signal even when
752
+ * `collectTablePhaseRows` itself returns nothing for the same content —
753
+ * otherwise a thin, name-less Progress table cannot suppress a checklist
754
+ * synthesis it was never meant to coexist with.
755
+ */
756
+ function hasPhaseListingTableHeader(content) {
757
+ const unfenced = (0, markdown_sectionizer_cjs_1.stripFencedCode)(content).text;
758
+ return unfenced.split(/\r?\n/).some((line) => PHASE_LISTING_HEADER_RE.test(line));
759
+ }
674
760
  /**
675
761
  * #3262: the sole owner of "which phase ids does THIS milestone window
676
762
  * declare". Extracted verbatim from `getMilestonePhaseFilter`'s former inline
@@ -840,6 +926,44 @@ function classifyMilestoneWindow(input) {
840
926
  SCOPE.COMPLETE // rows 6, 7
841
927
  );
842
928
  }
929
+ // #5007 (Phase 6 / ADR-4910 §8): the bulk phase-heading-block strip (heading
930
+ // line + body through to the next heading of any level) used by BOTH the
931
+ // <details>-fallback branch and preambleWithoutPhaseDetails inside
932
+ // extractCurrentMilestoneScoped below — literally the same regex, previously
933
+ // duplicated verbatim at both call sites. Composed from
934
+ // phaseHeadingPrefixSrcFor (LABEL_ONLY, no convention argument — reproduces
935
+ // the prior bare `Phase\s+` literal byte-for-byte, same non-widening
936
+ // discipline as the phase.cts counter sites) rather than routed through
937
+ // buildPhaseHeadingScanRegex, since this site needs the whole matched block
938
+ // (heading + body), not a phase-number/title capture. The one real behavior
939
+ // change here is the phase-number token itself: the prior literal admitted
940
+ // any `[\w][\w.-]*` (including non-numeric garbage); PHASE_NUMBER_TOKEN_SOURCE
941
+ // tightens it to the real phase-number grammar (digits, optional trailing
942
+ // letter, dotted subphases) — verified against real phase-number fixtures
943
+ // (plain, decimal, and bracket-tag-bearing) in tests/roadmap-parser.test.cjs.
944
+ const PHASE_HEADING_BLOCK_STRIP_RE = new RegExp(
945
+ // #1729: `(?:\s*\([^)\n]{0,200}\))?` (OPTIONAL_PHASE_TAG_SOURCE) tolerates a pre-colon ( ) tag.
946
+ `^#{2,4}\\s*${phaseHeadingPrefixSrcFor(PHASE_HEADING_BASELINE.LABEL_ONLY)}${PHASE_NUMBER_TOKEN_SOURCE}${OPTIONAL_PHASE_TAG_SOURCE}\\s*:[^\\n]*(?:\\n(?!#{1,6}\\s)[^\\n]*)*\\n?`, 'gim');
947
+ /**
948
+ * #5038: single owner for classifying a `milestone:` scalar as STATE.md spells
949
+ * it. The frontmatter parser (FAILSAFE_SCHEMA) and the raw-regex readers both
950
+ * see YAML null as text, so every reader classifies it here. Recognizes the
951
+ * YAML 1.2 core-schema null spellings (`null`, `Null`, `NULL`, `~`) with an
952
+ * optional trailing ` # comment` and optional surrounding quotes (the
953
+ * frontmatter parser has already stripped them, so the raw readers must agree);
954
+ * a blank value is absent, not null.
955
+ */
956
+ function classifyMilestoneScalar(raw) {
957
+ if (typeof raw !== 'string')
958
+ return { explicitNull: false, version: null };
959
+ const trimmed = raw.trim();
960
+ if (trimmed === '')
961
+ return { explicitNull: false, version: null };
962
+ const bare = trimmed.replace(/\s+#.*$/, '').trim().replace(/^(['"])(.*)\1$/, '$2');
963
+ if (/^(?:null|Null|NULL|~)$/.test(bare))
964
+ return { explicitNull: true, version: null };
965
+ return { explicitNull: false, version: trimmed };
966
+ }
843
967
  /**
844
968
  * Extract the current milestone section from ROADMAP.md by positive lookup,
845
969
  * carrying a `scope` discriminator (ADR-3180 Decision 2) alongside the value.
@@ -874,18 +998,23 @@ function extractCurrentMilestoneScoped(content, cwd, ws, phaseIdConvention) {
874
998
  return { value: stripShippedMilestones(content), scope: SCOPE.COMPLETE };
875
999
  }
876
1000
  let version = null;
1001
+ let stateAssertsNoMilestone = false;
877
1002
  try {
878
1003
  const statePath = node_path_1.default.join(planningDir(cwd, ws), 'STATE.md');
879
1004
  const stateRaw = (0, shell_command_projection_cjs_1.platformReadSync)(statePath);
880
1005
  if (stateRaw !== null) {
881
1006
  const milestoneMatch = stateRaw.match(/^milestone:\s*(.+)/m);
882
1007
  if (milestoneMatch) {
883
- version = milestoneMatch[1].trim();
1008
+ const classified = classifyMilestoneScalar(milestoneMatch[1]);
1009
+ version = classified.version;
1010
+ stateAssertsNoMilestone = classified.explicitNull;
884
1011
  }
885
1012
  }
886
1013
  }
887
1014
  catch { /* ignore */ }
888
- if (!version) {
1015
+ // #5038: an explicit `milestone: null` is a deliberate "no milestone" — do
1016
+ // not let the in-progress bullet guess one (same stance as getMilestoneInfo).
1017
+ if (!version && !stateAssertsNoMilestone) {
889
1018
  const inProgressMatch = content.match(/(?:🚧|🔄)\s*\*\*v(\d+\.\d+)\s/);
890
1019
  if (inProgressMatch) {
891
1020
  version = 'v' + inProgressMatch[1];
@@ -964,8 +1093,9 @@ function extractCurrentMilestoneScoped(content, cwd, ws, phaseIdConvention) {
964
1093
  const firstMilestoneMatch = content.match(anyMilestoneOrDetails);
965
1094
  const preambleCutoff = firstMilestoneMatch ? firstMilestoneMatch.index : detailsOpenIdx;
966
1095
  const preamble = (0, markdown_sectionizer_cjs_1.stripTaggedBlocks)(content.slice(0, preambleCutoff), 'details')
967
- // #1729: `(?:\s*\([^)\n]{0,200}\))?` tolerates a pre-colon ( ) tag (literal mirror of OPTIONAL_PHASE_TAG_SOURCE).
968
- .replace(/^#{2,4}\s*Phase\s+[\w][\w.-]*(?:\s*\([^)\n]{0,200}\))?\s*:[^\n]*(?:\n(?!#{1,6}\s)[^\n]*)*\n?/gim, '')
1096
+ // #5007 (Phase 6 / ADR-4910 §8): shared owner, see
1097
+ // PHASE_HEADING_BLOCK_STRIP_RE above.
1098
+ .replace(PHASE_HEADING_BLOCK_STRIP_RE, '')
969
1099
  .replace(/^#{1,4}\s*Phase Details\b[^\n]*\n?/gim, '');
970
1100
  const value = preamble + content.slice(detailsOpenIdx, detailsEnd);
971
1101
  return {
@@ -1200,15 +1330,23 @@ function extractCurrentMilestoneScoped(content, cwd, ws, phaseIdConvention) {
1200
1330
  // every phase (phase_count: 0, exit 0). Only strip preamble phase details when
1201
1331
  // the selected milestone section actually contains its own — otherwise the
1202
1332
  // preamble phases ARE this milestone's phases and must be preserved.
1203
- const currentSectionHasPhaseDetails = /^#{2,4}\s*Phase\s+\S/im.test(currentSection);
1333
+ // #5007 (Phase 6 / ADR-4910 §8): a pure "does this section have ANY phase
1334
+ // heading" boolean — same shape as phase.cts:1691's anyHeadingPattern
1335
+ // (composed directly from phaseHeadingPrefixSrcFor, no shared owner exposes
1336
+ // a captureless existence check), but this site's terminal token is `\S`
1337
+ // (any non-whitespace), not phase.cts:1691's `\d` — kept as `\S` to
1338
+ // reproduce this site's own prior behavior byte-for-byte rather than
1339
+ // forcing the two sites onto an identical terminal token that would be a
1340
+ // behavior change here.
1341
+ const currentSectionHasPhaseDetails = new RegExp(`^#{2,4}\\s*${phaseHeadingPrefixSrcFor(PHASE_HEADING_BASELINE.LABEL_ONLY)}\\S`, 'im').test(currentSection);
1204
1342
  const preambleBase = (0, markdown_sectionizer_cjs_1.stripTaggedBlocks)(beforeMilestones, 'details');
1205
1343
  // #3235: the conditional wraps the REPLACE, not the pattern. This used to select between the
1206
1344
  // strip regex and a `/$/` sentinel, which made the do-not-strip branch an identity replacement
1207
1345
  // (CodeQL js/identity-replacement, alert 53) -- correct, but it left both branches sharing one
1208
1346
  // replacement argument, so changing `''` would silently give the no-op branch a real effect.
1209
- // #1729: `(?:\s*\([^)\n]{0,200}\))?` tolerates a pre-colon ( ) tag (literal mirror of OPTIONAL_PHASE_TAG_SOURCE).
1347
+ // #5007 (Phase 6 / ADR-4910 §8): shared owner, see PHASE_HEADING_BLOCK_STRIP_RE above.
1210
1348
  const preambleWithoutPhaseDetails = currentSectionHasPhaseDetails
1211
- ? preambleBase.replace(/^#{2,4}\s*Phase\s+[\w][\w.-]*(?:\s*\([^)\n]{0,200}\))?\s*:[^\n]*(?:\n(?!#{1,6}\s)[^\n]*)*\n?/gim, '')
1349
+ ? preambleBase.replace(PHASE_HEADING_BLOCK_STRIP_RE, '')
1212
1350
  : preambleBase;
1213
1351
  // Unconditional in BOTH branches -- the #730 `Phase Details` heading strip is independent of
1214
1352
  // whether the selected milestone section carries phase details of its own.
@@ -1618,14 +1756,22 @@ function getMilestoneInfo(cwd) {
1618
1756
  if (roadmap === null)
1619
1757
  throw new Error('missing');
1620
1758
  let stateVersion = null;
1759
+ // #5038: true only when the `milestone:` key is PRESENT and classifies as
1760
+ // an explicit null (any spelling classifyMilestoneScalar accepts), as
1761
+ // opposed to ABSENT. Gates the ROADMAP auto-derivation fallback, which
1762
+ // only bootstraps a milestone for a project that never mentioned one.
1763
+ let explicitlyNoMilestone = false;
1621
1764
  if (cwd) {
1622
1765
  try {
1623
1766
  const statePath = node_path_1.default.join(planningDir(cwd), 'STATE.md');
1624
1767
  const stateRaw = (0, shell_command_projection_cjs_1.platformReadSync)(statePath);
1625
1768
  if (stateRaw !== null) {
1626
1769
  const m = stateRaw.match(/^milestone:\s*(.+)/m);
1627
- if (m)
1628
- stateVersion = m[1].trim();
1770
+ if (m) {
1771
+ const classified = classifyMilestoneScalar(m[1]);
1772
+ explicitlyNoMilestone = classified.explicitNull;
1773
+ stateVersion = classified.version;
1774
+ }
1629
1775
  }
1630
1776
  }
1631
1777
  catch {
@@ -1682,6 +1828,11 @@ function getMilestoneInfo(cwd) {
1682
1828
  // or heading-but-nameless). §7.2 rule 4 — never fabricate a name.
1683
1829
  return scoped({ version: stateVersion, name: null }, SCOPE.TRUNCATED);
1684
1830
  }
1831
+ // #5038: an explicit null is a deliberate "no milestone"; do not let the
1832
+ // auto-derivation fallback below replace it with a guessed version.
1833
+ if (explicitlyNoMilestone) {
1834
+ return scoped(null, SCOPE.UNSCOPED);
1835
+ }
1685
1836
  // No STATE.md version. The 🚧 in-progress bullet is still consulted first
1686
1837
  // (unchanged from the pre-#3216 fallback).
1687
1838
  const inProgressMatch = roadmap.match(/🚧\s*\*\*v(\d+(?:\.\d+)+)\s+([^*]+)\*\*/);
@@ -2015,17 +2166,21 @@ function currentMilestoneRawRanges(content, cwd) {
2015
2166
  if (!cwd)
2016
2167
  return null;
2017
2168
  let version = null;
2169
+ let stateAssertsNoMilestone = false;
2018
2170
  try {
2019
2171
  const statePath = node_path_1.default.join(planningDir(cwd), 'STATE.md');
2020
2172
  const stateRaw = (0, shell_command_projection_cjs_1.platformReadSync)(statePath);
2021
2173
  if (stateRaw !== null) {
2022
2174
  const milestoneMatch = stateRaw.match(/^milestone:\s*(.+)/m);
2023
- if (milestoneMatch)
2024
- version = milestoneMatch[1].trim();
2175
+ if (milestoneMatch) {
2176
+ const classified = classifyMilestoneScalar(milestoneMatch[1]);
2177
+ version = classified.version;
2178
+ stateAssertsNoMilestone = classified.explicitNull;
2179
+ }
2025
2180
  }
2026
2181
  }
2027
2182
  catch { /* ignore */ }
2028
- if (!version) {
2183
+ if (!version && !stateAssertsNoMilestone) {
2029
2184
  const inProgressMatch = content.match(/(?:🚧|🔄)\s*\*\*v(\d+\.\d+)\s/);
2030
2185
  if (inProgressMatch)
2031
2186
  version = 'v' + inProgressMatch[1];
@@ -2056,6 +2211,69 @@ function currentMilestoneRawRanges(content, cwd) {
2056
2211
  }
2057
2212
  return { primary: { start: sectionStart, end: sectionEnd }, details };
2058
2213
  }
2214
+ /**
2215
+ * #4731 — extract a bold-labeled phase field (Goal, Requirements, ...) reading
2216
+ * past hard-wrapped continuation lines. The roadmapper soft-wraps long fields
2217
+ * at ~85 chars, so a single-line capture silently truncated every wrapped
2218
+ * Goal/Requirements. Stops at: another `**Field**` label line, a blank line,
2219
+ * or any heading. Wrapped lines are trimmed and joined with single spaces; a
2220
+ * single-line field is returned unchanged (trimmed). Returns null when the
2221
+ * label is absent.
2222
+ */
2223
+ function extractPhaseFieldMultiline(section, label) {
2224
+ // #2769 label shapes: `**X:**`, `**X**:`, and the spaced `**X** :`.
2225
+ // #4837: anchored to line start (`^[ \t]*`, `m` flag) so an inline
2226
+ // `**Label**` mention embedded in an EARLIER field's own body text cannot
2227
+ // shadow the real field's own declaration line. `[ \t]*` (not `\s*`) keeps
2228
+ // the anchor scoped to same-line leading whitespace under the `m` flag.
2229
+ const labelRe = new RegExp('^[ \\t]*\\*\\*' + label + '(?::\\*\\*|\\*\\*\\s*:?)\\s*([^\\n]+)', 'im');
2230
+ const match = section.match(labelRe);
2231
+ if (!match)
2232
+ return null;
2233
+ const startIdx = match.index ?? 0;
2234
+ const after = section.slice(startIdx + match[0].length);
2235
+ const firstLine = match[1].trim();
2236
+ // #4837 (isolated-review finding): the continuation loop's fence-stop check
2237
+ // only ever sees lines AFTER the label's own line — a fence opener on the
2238
+ // SAME line as the label (`**Requirements:** ```js`) was invisible to it,
2239
+ // leaking one line of fence content before the closing fence line
2240
+ // coincidentally matched the same stop check. Checked here too, so a fence
2241
+ // opening on the label's own line is caught just as conservatively.
2242
+ if (/^(?:`{3,}|~{3,})/.test(firstLine))
2243
+ return null;
2244
+ const contLines = [];
2245
+ const lines = after.split('\n');
2246
+ for (let li = 0; li < lines.length; li++) {
2247
+ const raw = lines[li];
2248
+ // The split's first element is the remainder of the captured first line's
2249
+ // own newline — an empty leading element is the line break, not a blank
2250
+ // continuation line.
2251
+ if (li === 0 && !raw.trim())
2252
+ continue;
2253
+ if (!raw.trim())
2254
+ break;
2255
+ // #4837: a list item is a structural boundary — the real corruption
2256
+ // vector (a `- Deferred to Phase N: OTHER-ID` bullet folding a foreign
2257
+ // REQ-ID into this field's citation-scan input).
2258
+ if (/^\s*[-*+]\s/.test(raw))
2259
+ break;
2260
+ // #4837: case-insensitive label-start character class — a
2261
+ // lowercase-first-letter label (`**requirements:**`) is as much a field
2262
+ // boundary as a capitalized one.
2263
+ if (/^\s*\*\*[A-Za-z][A-Za-z ]*:?(\*\*)?:?\s/.test(raw))
2264
+ break;
2265
+ if (/^\s*#{1,4}\s/.test(raw))
2266
+ break;
2267
+ if (/^\s*\|/.test(raw))
2268
+ break;
2269
+ // #4837: a fenced code block opener stops the scan — folding fence
2270
+ // content is never safe, and stopping early is conservative.
2271
+ if (/^\s*(?:`{3,}|~{3,})/.test(raw))
2272
+ break;
2273
+ contLines.push(raw.trim());
2274
+ }
2275
+ return [firstLine, ...contLines].join(' ').trim() || null;
2276
+ }
2059
2277
  module.exports = {
2060
2278
  stripShippedMilestones,
2061
2279
  extractCurrentMilestone,
@@ -2065,6 +2283,7 @@ module.exports = {
2065
2283
  replaceInCurrentMilestone,
2066
2284
  getRoadmapPhaseInternal,
2067
2285
  getMilestoneInfo,
2286
+ classifyMilestoneScalar,
2068
2287
  getMilestonePhaseFilter,
2069
2288
  currentMilestoneRawRanges,
2070
2289
  withPhaseSection,
@@ -2077,6 +2296,7 @@ module.exports = {
2077
2296
  // own doc comment. milestone.cts's destructive-consumer guard consumes
2078
2297
  // this instead of composing locate+select+section-end itself.
2079
2298
  sliceMilestoneWindow,
2299
+ milestoneSections,
2080
2300
  hasVersionedMilestones,
2081
2301
  hasMilestoneSectioning,
2082
2302
  // #3642: the >=1 sibling buildStateFrontmatter's unbounded branch consumes.
@@ -2090,9 +2310,16 @@ module.exports = {
2090
2310
  // guards and the edit-phase workflow's pre/post capture are built on.
2091
2311
  scanMilestonePhaseIds,
2092
2312
  collectTablePhaseRows,
2313
+ hasPhaseListingTableHeader,
2093
2314
  findMilestoneScopeHeadingLines,
2094
2315
  // #3641: the scope axis's phase-ENTRY predicate, exported so roadmap
2095
2316
  // validate's V004 document-level check routes through the same single
2096
2317
  // owner (and its convention gate) instead of a private inline copy.
2318
+ extractPhaseFieldMultiline,
2097
2319
  hasPhaseEntries,
2320
+ // #4144 round 5 Blocker 1: the readers' own phase-heading grammar, so the
2321
+ // bracket roadmap migrator's "phase-like but unparsed" refusal
2322
+ // (src/roadmap-upgrade.cts) can gate on it instead of a private, looser
2323
+ // "starts with the word Phase" regex.
2324
+ isPhaseHeadingText,
2098
2325
  };