@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
@@ -0,0 +1,198 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Pinned baseline for scripts/lint-docs-guard-registration.cjs's
5
+ * `docs-guard-exempt` identity ratchet — mirrors
6
+ * scripts/lint-allow-test-rule-refs.cjs's `allow-test-rule` ratchet
7
+ * (scripts/lib/allowlist-ratchet.cjs, ADR-456's pattern).
8
+ *
9
+ * Every test file basename here is a KNOWN, already-reviewed
10
+ * `// docs-guard-exempt: <reason>` marker. Nothing caps how many files may
11
+ * carry the marker in the abstract, but ADDING a new one anywhere in
12
+ * tests/*.test.cjs fails `lint-docs-guard-registration` until this baseline
13
+ * is deliberately updated — so a new exemption always shows up as a
14
+ * reviewable diff here, instead of silently opting a file out of the
15
+ * docs-guard registration requirement with zero signal.
16
+ *
17
+ * A file listed here that no longer exists, or no longer carries a real
18
+ * `docs-guard-exempt:` marker in its first 20 lines, is reported STALE and
19
+ * must be pruned (ratchet-down, same as the sibling gate).
20
+ *
21
+ * Seeded 2026-08-23 (#3753 security follow-up FIX 2) from every real marker
22
+ * found via scripts/lint-docs-guard-registration.cjs's own `findExemption`
23
+ * scan of tests/*.test.cjs — derived, not retyped from memory.
24
+ *
25
+ * Extended 2026-08-23 (#3753 correctness follow-up): the reader-detection
26
+ * fixes (Defects A/B/C) surfaced 86 previously-undetected docs/ readers. 40
27
+ * were genuine docs-content guards (added to DOCS_GUARD_TESTS in
28
+ * scripts/docs-guard-registry.cjs); the 46 added here touch a docs/ path
29
+ * only incidentally (fixture data, external URL citations, comment-only
30
+ * mentions, metadata labels, or scan-exclusion lists) — see each file's own
31
+ * `docs-guard-exempt:` marker for its specific reason.
32
+ */
33
+ const DOCS_GUARD_EXEMPT_BASELINE = [
34
+ 'adr-612-bracket-phase-counting.test.cjs',
35
+ 'adr-parser.test.cjs',
36
+ 'adr-parser.unit.test.cjs',
37
+ 'agent-marker-documentation-guard.test.cjs',
38
+ 'antigravity-upgrades.test.cjs',
39
+ 'capability-cli.test.cjs',
40
+ 'capability-validator-task-content-resolver.test.cjs',
41
+ 'ci-docs-guard-registry.test.cjs',
42
+ 'ci-test-scope.test.cjs',
43
+ 'cline-install.test.cjs',
44
+ 'code-review-depth.test.cjs',
45
+ 'code-review-pipeline-regression.test.cjs',
46
+ 'codebuddy-upgrades.test.cjs',
47
+ 'commands.test.cjs',
48
+ 'commit-docs-bypass.test.cjs',
49
+ 'complexity-trigger.test.cjs',
50
+ 'concurrency-safety.test.cjs',
51
+ 'cursor-imperative-reference.test.cjs',
52
+ 'declarative-reference-antigravity.test.cjs',
53
+ 'declarative-reference-zcode.test.cjs',
54
+ 'emitted-attribution.test.cjs',
55
+ 'eslint-rules.test.cjs',
56
+ 'estimate-calibrate.test.cjs',
57
+ 'gen-context-index.test.cjs',
58
+ 'gen-registry.test.cjs',
59
+ 'gsd-agent-isolation-guard.test.cjs',
60
+ 'hermes-dispatch-upgrade.test.cjs',
61
+ 'install-minimal-hooks.test.cjs',
62
+ 'install-runtime-artifacts.test.cjs',
63
+ 'installer-migration-config-root-marker.test.cjs',
64
+ 'installer-migration-pi-extension-ext.test.cjs',
65
+ 'installer-migrations.test.cjs',
66
+ 'kimi-upgrades.test.cjs',
67
+ 'lint-allow-test-rule-refs.test.cjs',
68
+ 'lint-docs-command-form.test.cjs',
69
+ 'lint-docs-required.test.cjs',
70
+ 'manifest-version-sync.test.cjs',
71
+ 'milestone-archive.test.cjs',
72
+ 'model-resolver.test.cjs',
73
+ 'new-project-mvp-prompt.test.cjs',
74
+ 'onboard-command.test.cjs',
75
+ 'opencode-command-dir-plural.test.cjs',
76
+ 'phase.test.cjs',
77
+ 'pr-branch-planning-filter.test.cjs',
78
+ 'precommit-alias-drift-hook.test.cjs',
79
+ 'removed-but-needed-lint.test.cjs',
80
+ 'repo-invariants.test.cjs',
81
+ 'require-issue-link-policy.test.cjs',
82
+ 'reviewer-manifest-body.test.cjs',
83
+ 'run-tests-harness.test.cjs',
84
+ 'runtime-name-policy.test.cjs',
85
+ 'security-prompt-injection.security.test.cjs',
86
+ 'shipped-reference-cites.test.cjs',
87
+ 'state.test.cjs',
88
+ 'worktree-safety.test.cjs',
89
+ ];
90
+
91
+ /**
92
+ * Security follow-up FIX 3: a per-file fingerprint of every distinct
93
+ * `docs/...` path TOKEN referenced by each baselined file (derived via
94
+ * scripts/lint-docs-guard-registration.cjs's `extractDocsPathReferences`,
95
+ * never retyped from memory). A baselined file whose live fingerprint
96
+ * DIFFERS from the recorded one here fails the lint — the exemption's
97
+ * premise ("this file doesn't really guard shipped docs content") may no
98
+ * longer hold and a human must re-confirm it before the entry is updated.
99
+ * Keeping this a plain, sorted, diffable path list (not a hash) is
100
+ * deliberate: a reviewer can see exactly WHAT changed from the PR diff
101
+ * alone.
102
+ *
103
+ * Seeded 2026-08-23 alongside DOCS_GUARD_EXEMPT_BASELINE above, from the
104
+ * exact same scan.
105
+ */
106
+ const DOCS_GUARD_EXEMPT_DOCS_PATHS = {
107
+ // #2761: cites docs/adr/612-bracket-phase-id-convention.md in an explanatory
108
+ // comment describing ADR-612's Decision 1; the file never reads that (or any)
109
+ // docs/ file — every read call it makes targets a tmpdir .planning fixture.
110
+ 'adr-612-bracket-phase-counting.test.cjs': ['docs/adr/612-bracket-phase-id-convention.md'],
111
+ 'adr-parser.test.cjs': ['docs/adr/0001.md', 'docs/adr/0002.md', 'docs/adr/0010.md', 'docs/adr/NNNN.md'],
112
+ 'adr-parser.unit.test.cjs': ['docs/adr/0001.md', 'docs/adr/0099.md', 'docs/adr/NNNN.md'],
113
+ 'agent-marker-documentation-guard.test.cjs': ['docs/reference', 'docs/reference/workflow-fragments.md'],
114
+ 'antigravity-upgrades.test.cjs': ['docs/cli', 'docs/cli/gcli-migration', 'docs/cli/permissions'],
115
+ 'capability-cli.test.cjs': ['docs/reference/gsd-capability-command.md'],
116
+ // #3970: cites docs/adr/3646-per-task-content-resolution-seam.md in an
117
+ // explanatory comment describing ADR-3646's Decision 3; the file never
118
+ // reads that (or any) docs/ file.
119
+ 'capability-validator-task-content-resolver.test.cjs': ['docs/adr/3646-per-task-content-resolution-seam.md'],
120
+ 'ci-docs-guard-registry.test.cjs': [
121
+ 'docs/AGENTS.md', 'docs/COMMANDS.md', 'docs/INVENTORY.md', 'docs/a.md', 'docs/adr',
122
+ 'docs/adr/0001-example.md', 'docs/adrenaline.md', 'docs/bar.md', 'docs/foo.md', 'docs/how-to/foo.md',
123
+ 'docs/how-to/some-unrelated-guide.md', 'docs/how-to/x.md', 'docs/some-unrelated-file.md',
124
+ 'docs/totally-unrelated.md',
125
+ ],
126
+ 'ci-test-scope.test.cjs': [
127
+ 'docs/a.md', 'docs/adr', 'docs/adr/22-plan-drift-guard.md', 'docs/how-to/configure-model-profiles.md',
128
+ 'docs/installer-migrations.md', 'docs/ja-JP', 'docs/ja-JP/USAGE.md', 'docs/usage.md', 'docs/x.md',
129
+ ],
130
+ 'cline-install.test.cjs': ['docs/guide.md'],
131
+ 'code-review-depth.test.cjs': ['docs/src/auth/x.ts'],
132
+ 'code-review-pipeline-regression.test.cjs': ['docs/DEVELOPMENT.md'],
133
+ 'codebuddy-upgrades.test.cjs': ['docs/cli/sub-agents'],
134
+ 'commands.test.cjs': ['docs/x.md'],
135
+ 'commit-docs-bypass.test.cjs': [
136
+ 'docs/40-design.md', 'docs/CONFIGURATION.md', 'docs/readme.md', 'docs/tracked-var-mentioning',
137
+ ],
138
+ 'complexity-trigger.test.cjs': ['docs/readme.md'],
139
+ // #3884: cites docs/CLI-TOOLS.md:736 in an explanatory comment describing
140
+ // the real `frontmatter get <file> [--field key]` CLI shape; the file
141
+ // never reads that (or any) docs/ file.
142
+ 'concurrency-safety.test.cjs': ['docs/CLI-TOOLS.md'],
143
+ 'cursor-imperative-reference.test.cjs': ['docs/sdk/typescript'],
144
+ 'declarative-reference-antigravity.test.cjs': ['docs/cli/features'],
145
+ 'declarative-reference-zcode.test.cjs': ['docs/reference/host-integration-capability-matrix.md'],
146
+ 'emitted-attribution.test.cjs': ['docs/README.md', 'docs/tests', 'docs/tests/helpers/install-shared.cjs'],
147
+ // #3914: cites docs/adr/3889-process-exit-contract.md ~:350-362 in an
148
+ // explanatory comment describing the intentional computed-property
149
+ // boundary move; the file never reads that (or any) docs/ file.
150
+ 'eslint-rules.test.cjs': ['docs/adr/3889-process-exit-contract.md', 'docs/readme.md'],
151
+ 'estimate-calibrate.test.cjs': [
152
+ 'docs/adr', 'docs/adr/2629-phase-effort-estimation-calibration.md', 'docs/reference',
153
+ 'docs/reference/planning-artifacts.md',
154
+ ],
155
+ 'gen-context-index.test.cjs': ['docs/CONTEXT-INDEX.json', 'docs/INVENTORY-MANIFEST.json'],
156
+ 'gen-registry.test.cjs': ['docs/registries', 'docs/registries/reviewers.json'],
157
+ 'gsd-agent-isolation-guard.test.cjs': ['docs/adr/1239-...md', 'docs/adr/1239-gsd-embeddable-orchestration-engine.md'],
158
+ 'hermes-dispatch-upgrade.test.cjs': ['docs/guides/delegation-patterns.md'],
159
+ 'install-minimal-hooks.test.cjs': ['docs/en/hooks', 'docs/en/users/features/hooks'],
160
+ 'install-runtime-artifacts.test.cjs': ['docs/CONFIGURATION.md', 'docs/adr/58-...md', 'docs/adr/58-runtime-install-policy-module.md', 'docs/cli/slash-commands'],
161
+ 'installer-migration-config-root-marker.test.cjs': ['docs/installer-migrations.md'],
162
+ 'installer-migration-pi-extension-ext.test.cjs': ['docs/installer-migrations.md'],
163
+ 'installer-migrations.test.cjs': ['docs/installer-migrations.md'],
164
+ 'kimi-upgrades.test.cjs': ['docs/reference/host-integration-capability-matrix.md'],
165
+ 'lint-allow-test-rule-refs.test.cjs': ['docs/readme.md'],
166
+ 'lint-docs-command-form.test.cjs': ['docs/adr', 'docs/adr/999-example.md', 'docs/how-to/example.md'],
167
+ 'lint-docs-required.test.cjs': [
168
+ 'docs/COMMANDS.md', 'docs/USER-GUIDE.md', 'docs/adr', 'docs/adr/0001-foo.md', 'docs/adr/0099-new.md',
169
+ 'docs/agents', 'docs/agents/triage-labels.md',
170
+ ],
171
+ 'manifest-version-sync.test.cjs': [],
172
+ // #3884: re-confirmed — the added docs/CLI-TOOLS.md:458 reference is the
173
+ // same class as the existing docs/TESTING-SUITES.md one (a placement-note
174
+ // / explanatory comment citing documented CLI behavior for context, never
175
+ // a read target); the exemption's premise still holds for both.
176
+ 'milestone-archive.test.cjs': ['docs/CLI-TOOLS.md', 'docs/TESTING-SUITES.md'],
177
+ 'model-resolver.test.cjs': ['docs/TESTING-SUITES.md'],
178
+ 'new-project-mvp-prompt.test.cjs': ['docs/CONFIGURATION.md'],
179
+ 'onboard-command.test.cjs': ['docs/adr/0001-runtime.md'],
180
+ 'opencode-command-dir-plural.test.cjs': ['docs/commands'],
181
+ 'phase.test.cjs': ['docs/adr/3524-...md', 'docs/adr/3524-cjs-sdk-hard-seam.md'],
182
+ 'pr-branch-planning-filter.test.cjs': ['docs/readme.md'],
183
+ 'precommit-alias-drift-hook.test.cjs': ['docs/adr/0174-...md', 'docs/adr/0174-retire-gsd-sdk-package-boundary.md'],
184
+ 'removed-but-needed-lint.test.cjs': [
185
+ 'docs/README.md', 'docs/getting-started.md', 'docs/gsd-new-workspace.md', 'docs/setup.md', 'docs/some-doc.md',
186
+ ],
187
+ 'repo-invariants.test.cjs': ['docs/FEATURES.md', 'docs/workflows/README'],
188
+ 'require-issue-link-policy.test.cjs': ['docs/-prefixed', 'docs/CONFIGURATION.md', 'docs/a.md', 'docs/b.md', 'docs/guide.md'],
189
+ 'reviewer-manifest-body.test.cjs': ['docs/how-to/ship-a-reviewer-lane.md'],
190
+ 'run-tests-harness.test.cjs': ['docs/TESTING-SUITES.md'],
191
+ 'runtime-name-policy.test.cjs': ['docs/customize/skills'],
192
+ 'security-prompt-injection.security.test.cjs': ['docs/notes.md'],
193
+ 'shipped-reference-cites.test.cjs': [],
194
+ 'state.test.cjs': ['docs/CONFIGURATION.md', 'docs/reference/state-md.md'],
195
+ 'worktree-safety.test.cjs': ['docs/SUMMARY.md'],
196
+ };
197
+
198
+ module.exports = { DOCS_GUARD_EXEMPT_BASELINE, DOCS_GUARD_EXEMPT_DOCS_PATHS };
@@ -7,6 +7,10 @@
7
7
  "path": "src/vendor/re2js.d.cts",
8
8
  "reason": "Vendored third-party type declaration (#3477): a .d.cts carries no executable code, so no ESLint rule is meaningful; the vendored .cjs it describes is globally ignored as verbatim upstream output. Freshness is enforced by scripts/lint-vendored-deps.cjs, not by lint rules."
9
9
  },
10
+ {
11
+ "path": "src/vendor/js-yaml.d.cts",
12
+ "reason": "Vendored third-party type declaration (ADR-3473 §8.1, #3881): a .d.cts carries no executable code, so no ESLint rule is meaningful; the vendored js-yaml .cjs it describes is globally ignored as verbatim upstream output (gsd-core/bin/lib/vendor/**). Freshness is enforced by scripts/lint-vendored-deps.cjs, not by lint rules — same precedent as src/vendor/re2js.d.cts above."
13
+ },
10
14
  {
11
15
  "path": "tests/fixtures/brand-typing/bad-calibrated-as-sample-basis.cts",
12
16
  "reason": "Deliberate MUST-NOT-COMPILE type-error fixture (#3059): type-aware linting would fail by design; it exists to prove the compiler rejects it."
@@ -2,10 +2,16 @@
2
2
  'use strict';
3
3
 
4
4
  /**
5
- * lint-fix-has-regression-test.cjs — gate: every fix(#NNNN) commit must
5
+ * lint-fix-has-regression-tests.cjs — gate: every fix(#NNNN) commit must
6
6
  * include at least one behavioral test file (tests/*.test.cjs) that is NOT
7
7
  * an auto-generated fixture/baseline.
8
8
  *
9
+ * Renamed (was `lint-fix-has-regression-test.cjs`, singular): the old
10
+ * basename matched Node's `*-test.EXT` test-collection pattern, so the
11
+ * remote push-gate runner collected and executed this SOURCE file as a
12
+ * test while GitHub CI (which globs only tests/**\/*.test.cjs) never saw
13
+ * it — see scripts/lint-source-test-name-collision.cjs.
14
+ *
9
15
  * ## Why
10
16
  *
11
17
  * CONTRIBUTING.md:47: "Fix it. Write a test that would have caught the bug."
@@ -82,7 +88,7 @@ function getChangedTestFiles(baseRef) {
82
88
 
83
89
  function main() {
84
90
  if (process.env.GSD_SKIP_REGRESSION_TEST_GATE === '1') {
85
- console.log('lint-fix-has-regression-test: SKIPPED (GSD_SKIP_REGRESSION_TEST_GATE=1)');
91
+ console.log('lint-fix-has-regression-tests: SKIPPED (GSD_SKIP_REGRESSION_TEST_GATE=1)');
86
92
  return;
87
93
  }
88
94
 
@@ -92,12 +98,12 @@ function main() {
92
98
  try {
93
99
  fixCommits = getFixCommits(baseRef);
94
100
  } catch {
95
- console.log(`lint-fix-has-regression-test: no fix/feat commits found vs ${baseRef}, skipping`);
101
+ console.log(`lint-fix-has-regression-tests: no fix/feat commits found vs ${baseRef}, skipping`);
96
102
  return;
97
103
  }
98
104
 
99
105
  if (fixCommits.length === 0) {
100
- console.log('lint-fix-has-regression-test: no fix/feat commits, passing');
106
+ console.log('lint-fix-has-regression-tests: no fix/feat commits, passing');
101
107
  return;
102
108
  }
103
109
 
@@ -113,7 +119,7 @@ function main() {
113
119
  .map((c) => ` ${c.sha} ${c.subject}`)
114
120
  .join('\n');
115
121
  throw new ExitError(1,
116
- `lint-fix-has-regression-test: ${fixCommits.length} fix/feat commit(s) but ZERO behavioral test files (*.test.cjs) in the diff.\n` +
122
+ `lint-fix-has-regression-tests: ${fixCommits.length} fix/feat commit(s) but ZERO behavioral test files (*.test.cjs) in the diff.\n` +
117
123
  `Auto-generated fixtures (tests/fixtures/, *-baseline.json) do NOT count.\n\n` +
118
124
  `Fix commits:\n${commitList}\n\n` +
119
125
  `CONTRIBUTING.md:47: "Write a test that would have caught the bug."\n` +
@@ -123,7 +129,7 @@ function main() {
123
129
  }
124
130
 
125
131
  console.log(
126
- `lint-fix-has-regression-test: PASS — ${fixCommits.length} fix/feat commit(s), ` +
132
+ `lint-fix-has-regression-tests: PASS — ${fixCommits.length} fix/feat commit(s), ` +
127
133
  `${testFiles.length} behavioral test file(s): ${testFiles.join(', ')}`
128
134
  );
129
135
  }
@@ -58,7 +58,7 @@
58
58
  * real, non-mocked `buildPlanningSnapshot(tmpCwd)` call (see
59
59
  * `tests/health-diagnostic-rules/root-existence.test.cjs`). This guard
60
60
  * therefore verifies the fixture-proof invariant STATICALLY against the
61
- * test files' own text — mirroring `scripts/lint-fix-has-regression-test.cjs`'s
61
+ * test files' own text — mirroring `scripts/lint-fix-has-regression-tests.cjs`'s
62
62
  * house style — rather than dynamically re-running fixture-building code
63
63
  * this guard does not own.
64
64
  */
@@ -82,14 +82,70 @@ const CONSISTENCY_TEST_FILE = path.join(REPO_ROOT, 'tests', 'health-diagnostic-r
82
82
  const CONSISTENCY_CODE_PREFIX_RE = /^C\d{3}$/;
83
83
 
84
84
  // Phase 12 (#3310, ADR-3180 §8.5 extension) — the S0NN namespace's own
85
- // fixture-proof pass. These 7 codes are NOT collected in any exported
86
- // `Rule[]` array: `cmdStateValidate` (src/state.cts) builds `Diagnostic[]`
87
- // directly via a local `stateDiagnostic()` helper, not via the rule-table
88
- // evaluator (out of scope for the RULES/CONSISTENCY_RULES-keyed passes
89
- // above). The list is therefore hardcoded here instead of read from the
90
- // compiled module.
85
+ // fixture-proof pass. These codes are NOT collected in any exported `Rule[]`
86
+ // array: `cmdStateValidate` (src/state.cts) builds `Diagnostic[]` directly via
87
+ // a local `stateDiagnostic()` helper, not via the rule-table evaluator (out of
88
+ // scope for the RULES/CONSISTENCY_RULES-keyed passes above).
89
+ //
90
+ // #3696: the list is DISCOVERED from the source, not hardcoded. It used to be a
91
+ // literal `['S001', ..., 'S007']`, which is precisely the shape ADR-3180
92
+ // Decision 4(a) forbids — "guards discover call sites by whole-repo scan, never
93
+ // by an allowlist of known files" — because such a guard can only ever be as
94
+ // complete as the author's recall. Adding S008/S009 to `cmdStateValidate` left
95
+ // this pass reporting a confident, green "7 code(s), all fixture-covered" while
96
+ // two new codes had no fixture requirement at all: a zero it did not earn. The
97
+ // scan below cannot report a code it has not read out of the source.
91
98
  const STATE_VALIDATE_TEST_FILE = path.join(REPO_ROOT, 'tests', 'state.test.cjs');
92
- const STATE_VALIDATE_CODES = ['S001', 'S002', 'S003', 'S004', 'S005', 'S006', 'S007'];
99
+ const STATE_VALIDATE_SOURCE_FILE = path.join(REPO_ROOT, 'src', 'state.cts');
100
+ // `g` is required by String.prototype.matchAll, which (unlike .exec) does not
101
+ // carry lastIndex across calls — so this constant is safe to share.
102
+ // #3696 review: `\s*` before `(` too. Requiring no space silently dropped a
103
+ // `stateDiagnostic ('S010', …)` call site from the discovered set, and since the
104
+ // fail-closed check below only fires on a FULLY empty result, a partial miss
105
+ // escaped the fixture-proof check entirely — the same "only as complete as the
106
+ // author's recall" failure this rewrite exists to prevent.
107
+ const STATE_DIAGNOSTIC_CALL_RE = /\bstateDiagnostic\s*\(\s*(['"`])(S\d{3})\1/g;
108
+
109
+ /**
110
+ * Every S0NN code `cmdStateValidate` can emit, read off its
111
+ * `stateDiagnostic(...)` call sites in `sourceText`.
112
+ *
113
+ * Takes the source TEXT rather than reading the path itself, so the discovery
114
+ * rule is exercisable against controlled fixtures — including the fail-closed
115
+ * path below, which is the branch that matters and which a path-reading
116
+ * function could only be tested on by mutating the real `src/state.cts`.
117
+ *
118
+ * Fails closed. An empty result means the helper was renamed or its call shape
119
+ * changed, and a guard that answers "0 codes, all covered" to that is worse than
120
+ * no guard — so it raises instead. Line/regex-based (not full AST) per this
121
+ * repo's existing lint-guard house style, same as TITLED_BLOCK_RE below.
122
+ */
123
+ function discoverStateValidateCodes(sourceText, sourceLabel = formatRepoRelative(STATE_VALIDATE_SOURCE_FILE)) {
124
+ const codes = [...sourceText.matchAll(STATE_DIAGNOSTIC_CALL_RE)].map((m) => m[2]);
125
+ const unique = [...new Set(codes)].sort();
126
+ if (unique.length === 0) {
127
+ throw new ExitError(
128
+ 1,
129
+ `lint-health-diagnostic-rule-table: found no stateDiagnostic() call sites in ${sourceLabel}.\n`
130
+ + ' This pass discovers the S0NN code set from those call sites (#3696), so an empty\n'
131
+ + ' result means the helper was renamed or its call shape changed — not that there are\n'
132
+ + ' no codes. Update STATE_DIAGNOSTIC_CALL_RE to match the new shape.\n',
133
+ );
134
+ }
135
+ return unique;
136
+ }
137
+
138
+ function readStateValidateSource() {
139
+ if (!fs.existsSync(STATE_VALIDATE_SOURCE_FILE)) {
140
+ throw new ExitError(
141
+ 1,
142
+ `lint-health-diagnostic-rule-table: cannot discover S0NN codes — ${formatRepoRelative(STATE_VALIDATE_SOURCE_FILE)} not found.\n`,
143
+ );
144
+ }
145
+ return fs.readFileSync(STATE_VALIDATE_SOURCE_FILE, 'utf8');
146
+ }
147
+
148
+ const STATE_VALIDATE_CODES = discoverStateValidateCodes(readStateValidateSource());
93
149
 
94
150
  // Matches `describe(`/`test(`/`it(` calls whose first argument is a string
95
151
  // literal, capturing that literal as the block's title. Line/regex-based
@@ -401,4 +457,5 @@ module.exports = {
401
457
  CONSISTENCY_TEST_FILE,
402
458
  STATE_VALIDATE_TEST_FILE,
403
459
  STATE_VALIDATE_CODES,
460
+ discoverStateValidateCodes,
404
461
  };
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * scripts/lint-mutation-test-derivation-drift.cjs
6
+ *
7
+ * #3881 follow-up ("one YAML parser" mutation-matrix piece 2): guards the
8
+ * derivation engine in scripts/mutation-matrix.cjs against the exact drift
9
+ * class PR #3888 shipped — a test file added on a branch that directly
10
+ * `require()`s a covered module's built artifact AND names itself after that
11
+ * module (`<module>.test.cjs` / `<module>.property.test.cjs` /
12
+ * `<module>-anything.test.cjs`), yet is never wired into that module's
13
+ * mutation shard.
14
+ *
15
+ * `scripts/mutation-matrix.cjs`'s `computeModuleTests` already derives most of
16
+ * a module's `tests` array automatically from exactly that (require + naming)
17
+ * signal, so a NEWLY drifting file of that shape is normally impossible — it
18
+ * would be auto-included the moment it exists. What this guard catches is the
19
+ * one case the derivation cannot self-correct: a file matching BOTH signals
20
+ * that the module's own `excludeTests` withholds. `excludeTests` entries are
21
+ * a deliberate, reasoned decision (see mutation-matrix.cjs's per-module
22
+ * comments) — this guard does not second-guess that decision, but it DOES
23
+ * verify every such file is EITHER accounted for in `tests` (auto-derived or
24
+ * `extraTests`) OR named in `excludeTests`. A file satisfying both signals
25
+ * that is in NEITHER list is exactly the drift #3888 shipped: nobody made a
26
+ * decision about it at all.
27
+ *
28
+ * Pure core (`findDrift`) so tests can drive it against a synthetic COVERED +
29
+ * requiring-files map without touching the real tests/ tree; `main()` wires
30
+ * it to the real repo for `npm run lint:ci`.
31
+ */
32
+
33
+ const path = require('node:path');
34
+ const { ExitError, runMain } = require('./lib/cli-exit.cjs');
35
+
36
+ /**
37
+ * Pure: for every module in `covered`, every file in `requiringFiles[module]`
38
+ * that ALSO matches the module's naming rule must be present in either
39
+ * `covered[module].tests` (already `tests/`-prefixed, as computeModuleTests
40
+ * emits it) or `covered[module].excludeTests` (bare basenames). Anything
41
+ * matching both signals but present in neither is reported as drift.
42
+ *
43
+ * @param {object} covered - mutation-matrix.cjs's COVERED (post `computeModuleTests`)
44
+ * @param {(moduleName: string) => string[]} findRequiringTestFiles - basenames requiring the module's artifact
45
+ * @param {(moduleName: string, file: string) => boolean} matchesModuleNamingRule
46
+ * @returns {{module: string, file: string}[]}
47
+ */
48
+ function findDrift(covered, findRequiringTestFiles, matchesModuleNamingRule) {
49
+ const drift = [];
50
+ for (const [moduleName, entry] of Object.entries(covered)) {
51
+ const testsSet = new Set((entry.tests || []).map((t) => path.basename(t)));
52
+ const excludeSet = new Set(entry.excludeTests || []);
53
+ for (const file of findRequiringTestFiles(moduleName)) {
54
+ if (!matchesModuleNamingRule(moduleName, file)) continue;
55
+ if (testsSet.has(file) || excludeSet.has(file)) continue;
56
+ drift.push({ module: moduleName, file });
57
+ }
58
+ }
59
+ return drift;
60
+ }
61
+
62
+ function main() {
63
+ const {
64
+ COVERED,
65
+ findRequiringTestFiles,
66
+ matchesModuleNamingRule,
67
+ } = require('./mutation-matrix.cjs');
68
+
69
+ const drift = findDrift(COVERED, findRequiringTestFiles, matchesModuleNamingRule);
70
+
71
+ if (drift.length === 0) {
72
+ console.log(`ok mutation-test-derivation-drift: every module-named test file requiring a covered module has an explicit disposition (${Object.keys(COVERED).length} modules checked)`);
73
+ return;
74
+ }
75
+
76
+ console.error('mutation-test-derivation-drift: test file(s) require a covered module and match its naming rule, but have no disposition in scripts/mutation-matrix.cjs (neither auto-derived/extraTests nor excludeTests):');
77
+ for (const d of drift) {
78
+ console.error(` [${d.module}] tests/${d.file}`);
79
+ }
80
+ console.error('\n remedy: in scripts/mutation-matrix.cjs, either let it auto-derive (do nothing further if it already appears in COVERED[<module>].tests), or add it to extraTests, or add a REASONED excludeTests entry explaining why it is deliberately withheld from the mutation shard.');
81
+ throw new ExitError(1);
82
+ }
83
+
84
+ module.exports = { findDrift };
85
+
86
+ if (require.main === module) runMain(main);
@@ -62,20 +62,35 @@
62
62
  * outstanding WORK wants the live set"): a LOOKUP, DIAGNOSTIC or ARCHIVAL
63
63
  * pass wants the physical set; only "which phases belong to this milestone"
64
64
  * wants the scoped set.
65
- * - `src/roadmap.cts` `cmdRoadmapAnalyze`: builds `_phaseDirNames` as a
66
- * heading->directory LOOKUP INDEX, not a milestone enumeration. It must
67
- * see the PHYSICAL set so a heading already scoped by
68
- * `extractCurrentMilestoneScoped` can find its directory; filtering it
69
- * through the owner would scope the same set twice.
65
+ * - `src/roadmap.cts` `cmdRoadmapAnalyze` — MIGRATED (#3882, ADR-3473 §8.2):
66
+ * `_phaseDirNames`, a heading->directory LOOKUP INDEX (not a milestone
67
+ * enumeration; must see the PHYSICAL set so a heading already scoped by
68
+ * `extractCurrentMilestoneScoped` can find its directory), now calls
69
+ * `listAllPhaseDirs(phasesDir, { includeSentinels: true })` instead of a
70
+ * hand-rolled `readdirSync` — no longer exempted, since there is nothing
71
+ * left in this function for either detector to catch.
72
+ * - `src/init.cts` `cmdInitMilestoneOp`'s `diskPhaseDirs` — MIGRATED (#3882,
73
+ * ADR-3473 §8.2): the same heading->directory LOOKUP INDEX shape as
74
+ * `cmdRoadmapAnalyze`'s `_phaseDirNames` above, now calls
75
+ * `listAllPhaseDirs(phasesDir, { includeSentinels: true })`. Its sibling
76
+ * readdirSync (the no-ROADMAP-headings-found fallback) was already routed
77
+ * through `listMilestonePhaseDirs` before this phase and remains so — no
78
+ * longer exempted; the function's other former exemption reason
79
+ * (`detectHasPriorPhases`/`detectUiPhaseActive`, unrelated call sites in
80
+ * the same file) is unaffected.
70
81
  * - `src/verify.cts` `cmdValidateHealth`: a project-wide HEALTH-CHECK sweep
71
82
  * (config drift, phase-directory naming, duplicate-directory collisions,
72
83
  * unsummarized-plan detection) — same "sweep everything, report gaps"
73
84
  * shape as `collectDiskPhases` and the `audit.cts` scanners; it must see
74
85
  * every phase directory regardless of milestone window to catch a
75
86
  * naming/duplicate defect wherever it lives.
76
- * - `src/verify.cts` `cmdVerifySchemaDrift`: resolves ONE caller-supplied
87
+ * - `src/verify.cts` `resolvePhaseDirByToken`: resolves ONE caller-supplied
77
88
  * `phase` argument to its directory (falling back to an exact-name
78
89
  * match) — a single-phase LOOKUP, not a current-milestone enumeration.
90
+ * Originally `cmdVerifySchemaDrift`'s own inline block; #3348 lifted it
91
+ * into this shared helper (also used by the new `cmdVerifyContextDrift`)
92
+ * without changing what question it asks, so the exemption moved with
93
+ * the call site rather than multiplying.
79
94
  * - `src/init.cts` `detectHasPriorPhases`: answers "has this project EVER
80
95
  * completed a phase", explicitly excluding the current one. A history
81
96
  * probe across all milestones, not a current-milestone enumeration.
@@ -117,8 +132,10 @@
117
132
  * `--include-archived` merge are phase LOCATION and archive
118
133
  * enumeration, not current-milestone enumeration; both legitimately
119
134
  * read the physical set. Its ENUMERATION path routes through the owner.
120
- * - `src/roadmap-parser.cts` `getMilestonePhaseFilter` and its #3262-extracted
121
- * set-building owner `scanMilestonePhaseIds` (the same two heading/
135
+ * - `src/roadmap-parser.cts` `getMilestonePhaseFilter` and its shared
136
+ * set-building implementation `scanMilestonePhaseIdSets` (the public
137
+ * `scanMilestonePhaseIds` wrapper remains a directly iterable Set; the
138
+ * same two heading/
122
139
  * #3577 `collectTablePhaseRows` — the table-scan sibling feeding the same
123
140
  * membership set; its local 999-only exclusion mirrors the owner's
124
141
  * deliberate NOT-isSentinelPhaseId choice (a leading 0 is a real decimal
@@ -131,6 +148,18 @@
131
148
  * ("00.1" is a real phase, not milestone 0). This scan asks a narrower
132
149
  * question — "which phase ids does this milestone's window declare" —
133
150
  * where only the 999 icebox range is excluded.
151
+ * - `src/state.cts` `countRoadmapPhaseHeadings`: its bracket branch composes
152
+ * bracket-milestone sentinel detection through `isSentinelPhaseId`, but
153
+ * retains a separate bare-token `999` rule. That rule intentionally does
154
+ * NOT use the convention-blind canonical predicate: the latter also reads
155
+ * leading `0`/`00.1` as milestone-0 sentinels, while a legacy-spelled bare
156
+ * zero token inside an opted-in bracket project is a real mid-migration
157
+ * phase. This is the state-counter twin of the roadmap-parser exemption.
158
+ * The guard has no per-detector exemption scope: it ORs the enumeration
159
+ * and sentinel detectors before consulting this function-only map. The
160
+ * whole-function exemption is therefore accepted; it is bounded because
161
+ * this counter performs no phases-directory `readdirSync` and needs the
162
+ * exemption only for its intentional bare-token `999` sentinel literal.
134
163
  * - `src/state.cts` `cmdStateValidate` ("Gate 1: Validate STATE.md against
135
164
  * filesystem"): resolves ONE directory — the disk match for STATE.md's
136
165
  * own `Current Phase` field — by prefix, a single-phase LOOKUP, not an
@@ -280,17 +309,19 @@ const OWNER_FILES = new Set([
280
309
  // `lint-milestone-window-drift.cjs`'s FUNCTION_SCOPED_EXEMPTIONS mechanism.
281
310
  // See the header comment for the full written reason behind each entry.
282
311
  const FUNCTION_SCOPED_EXEMPTIONS = new Map([
283
- [path.join('src', 'roadmap.cts'), new Set(['cmdRoadmapAnalyze'])],
284
- [path.join('src', 'verify.cts'), new Set(['cmdValidateHealth', 'cmdVerifySchemaDrift'])],
285
- [path.join('src', 'init.cts'), new Set(['detectHasPriorPhases', 'detectUiPhaseActive', 'cmdInitMilestoneOp'])],
312
+ [path.join('src', 'verify.cts'), new Set(['cmdValidateHealth', 'resolvePhaseDirByToken'])],
313
+ [path.join('src', 'init.cts'), new Set(['detectHasPriorPhases', 'detectUiPhaseActive'])],
286
314
  [path.join('src', 'milestone.cts'), new Set(['archivePhaseDirectories', 'cmdMilestoneComplete', 'cmdPhasesClear'])],
287
- [path.join('src', 'phase.cts'), new Set(['cmdPhasesList', 'cmdPhaseNextDecimal', 'cmdPhasePlanIndex', 'cmdPhaseInsert', 'renameDecimalPhases', 'renameIntegerPhases'])],
315
+ // #3849: collectSiblingWorktreePhaseNums reads a SIBLING worktree's phases dir —
316
+ // a different checkout listMilestonePhaseDirs (cwd-scoped) cannot serve; the
317
+ // allocators' own on-disk scans stay unexempted.
318
+ [path.join('src', 'phase.cts'), new Set(['cmdPhasesList', 'cmdPhaseNextDecimal', 'cmdPhasePlanIndex', 'cmdPhaseInsert', 'renameDecimalPhases', 'renameIntegerPhases', 'collectSiblingWorktreePhaseNums'])],
288
319
  [path.join('src', 'audit.cts'), new Set(['listAuditPhaseTargets'])],
289
320
  [path.join('src', 'commands.cts'), new Set(['cmdHistoryDigest'])],
290
- [path.join('src', 'state.cts'), new Set(['cmdStateValidate', 'cmdStateSync', 'cmdStateRebuild'])],
321
+ [path.join('src', 'state.cts'), new Set(['cmdStateValidate', 'cmdStateSync', 'cmdStateRebuild', 'countRoadmapPhaseHeadings'])],
291
322
  [path.join('src', 'roadmap-upgrade.cts'), new Set(['computeMigrationPlan'])],
292
323
  [path.join('src', 'smart-entry.cts'), new Set(['detectVerifyFailed'])],
293
- [path.join('src', 'roadmap-parser.cts'), new Set(['getMilestonePhaseFilter', 'scanMilestonePhaseIds', 'collectTablePhaseRows'])],
324
+ [path.join('src', 'roadmap-parser.cts'), new Set(['getMilestonePhaseFilter', 'scanMilestonePhaseIdSets', 'collectTablePhaseRows'])],
294
325
  [path.join('src', 'planning-snapshot.cts'), new Set(['buildAllPhaseDirNamesField'])],
295
326
  ]);
296
327