@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
@@ -0,0 +1,329 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * PlanningDoc positive-control lint (ADR-4910 §7, "Every parser ships a
6
+ * positive control per accepted grammar", epic #4906 Phase 6 / #5007).
7
+ *
8
+ * `NodeKind` (`src/planning-document.cts`, compiled to
9
+ * `gsd-core/bin/lib/planning-document.cjs`) is the single-source union naming
10
+ * every grammar `parsePlanningDoc` accepts: `frontmatter` / `section` /
11
+ * `boldField` / `table` / `checklist`. This lint asserts one positive-control
12
+ * fixture per declared grammar, under `tests/fixtures/planning-document/`,
13
+ * each of which must round-trip through the real `parsePlanningDoc` and
14
+ * actually produce a node of that kind — not merely "the parser didn't
15
+ * throw". Per CONTRIBUTING.md's fixture-provenance rule (#2371), every
16
+ * fixture here is authored independently, never copied from
17
+ * `src/planning-document.cts`'s own docstring examples or from
18
+ * `tests/planning-document.test.cjs`'s existing fixtures.
19
+ *
20
+ * The `accepted` set (`NodeKind`) is a TypeScript-only type, erased by
21
+ * compilation — it carries no runtime value in the built `.cjs` seam. So this
22
+ * lint reads it directly out of `src/planning-document.cts`'s own source
23
+ * text (the `export type NodeKind = ...;` declaration), the same way
24
+ * `scripts/lint-phase-id-drift.cjs` reads source text for its own literal
25
+ * checks — NOT by importing a type, which is impossible from a `.cjs`
26
+ * script. This is what makes the guarantee live: a NEW grammar kind added to
27
+ * `NodeKind` with no registry entry fails this lint immediately, before any
28
+ * fixture is even written, closing the "parser without one fails the build"
29
+ * requirement in ADR-4910 §7.
30
+ *
31
+ * Modeled on `scripts/lint-table-schema-drift.cjs`'s registry/exit-code/
32
+ * error-message structure — a hardcoded `{grammar -> fixture file}` map,
33
+ * exit 0 clean / exit 1 with a per-entry reason on drift, wired into
34
+ * `lint:ci` — but the ASSERTION is stricter than that script's verbatim-
35
+ * substring check: proof the grammar is genuinely *accepted* (the fixture
36
+ * parses without error and yields a node of that kind), per ADR-4910 §7's
37
+ * own text, not just "a string appears somewhere".
38
+ */
39
+
40
+ const fs = require('node:fs');
41
+ const path = require('node:path');
42
+
43
+ const PLANNING_DOCUMENT_SRC = path.join('src', 'planning-document.cts');
44
+ const PLANNING_DOCUMENT_LIB = path.join('gsd-core', 'bin', 'lib', 'planning-document.cjs');
45
+ const FIXTURE_DIR = path.join('tests', 'fixtures', 'planning-document');
46
+
47
+ // grammar kind (must match a `NodeKind` union member verbatim) -> the ONE
48
+ // canonical positive-control fixture file (relative to FIXTURE_DIR) that
49
+ // proves that grammar is accepted (ADR-4910 §7).
50
+ const POSITIVE_CONTROL_REGISTRY = {
51
+ frontmatter: 'frontmatter.md',
52
+ section: 'section.md',
53
+ boldField: 'boldfield.md',
54
+ table: 'table.md',
55
+ checklist: 'checklist.md',
56
+ };
57
+
58
+ // Any real entry from `PLANNING_ARTIFACTS` satisfies `parsePlanningDoc`'s
59
+ // artifact-kind gate equally — the specific name does not affect which
60
+ // grammars a fixture's BODY is recognised as containing.
61
+ const FIXTURE_ARTIFACT_NAME = 'ROADMAP.md';
62
+
63
+ // Test-only env var name. `resolveRegistry` below JSON-parses this (when set)
64
+ // and shallow-merges it over `POSITIVE_CONTROL_REGISTRY`, so a test can spawn
65
+ // THIS SAME, otherwise-unmodified, script file as a real child process
66
+ // against a deliberately broken registry entry (a missing entry, or one
67
+ // pointed at a nonexistent fixture) — proving the lint genuinely fails the
68
+ // build, per ADR-4910 §7's "a parser without one fails the build" guarantee
69
+ // — without ever touching the real registry or fixture files.
70
+ //
71
+ // This env var alone is NEVER sufficient to activate the override — a bare
72
+ // `process.env` lookup would mean a stray, accidentally-inherited copy of
73
+ // this variable (a leftover shell `export`, a misconfigured CI environment,
74
+ // a compromised dependency's postinstall script) could silently swap the
75
+ // registry in a REAL `npm run lint:ci` / `npm run lint:planning-document-
76
+ // positive-control` invocation, with nothing in the code enforcing otherwise
77
+ // (flagged by both the security review and the code-review Standards axis
78
+ // on #5007 Phase 6: the old comment asserted "no real invocation ever sets
79
+ // this" as a convention, not a fact the code made true).
80
+ //
81
+ // What now makes it true, by construction: `scanRepo` only reads this env
82
+ // var via `resolveRegistry` when its caller ALSO passes `allowOverride ===
83
+ // true`, which `main()` only does when the `--test-registry-override` CLI
84
+ // flag is present in argv (see `parseArgs`). The test file spawns this
85
+ // script as a real child process (`tests/helpers/process-seam.cjs`'s
86
+ // `runNode`, over `spawnSync`) — a process boundary that can only carry data
87
+ // in via `env`/`argv`, so the override cannot be passed as an in-process
88
+ // function parameter here the way it can be for the pure functions below.
89
+ // Requiring BOTH the env var and the CLI flag closes the gap: neither
90
+ // `lint:ci` nor `lint:planning-document-positive-control` (see package.json)
91
+ // ever passes `--test-registry-override` in their fixed argv, and unlike an
92
+ // env var, a CLI flag is never accidentally "leaked" into a fixed npm-script
93
+ // invocation. See tests/lint-planning-document-positive-control.test.cjs.
94
+ const TEST_REGISTRY_OVERRIDE_ENV_VAR = 'LINT_PLANNING_DOCUMENT_POSITIVE_CONTROL_TEST_REGISTRY_OVERRIDE';
95
+
96
+ /** CLI flag gate for the test-only override (see `TEST_REGISTRY_OVERRIDE_ENV_VAR`
97
+ * above). Must be passed explicitly in argv — never inferred from env — for
98
+ * `resolveRegistry`'s env-var override to be honored at all. */
99
+ const TEST_REGISTRY_OVERRIDE_CLI_FLAG = '--test-registry-override';
100
+
101
+ /** Resolve the registry to scan against: the real hardcoded registry, unless
102
+ * BOTH `allowOverride` is `true` (only ever set by the
103
+ * `--test-registry-override` CLI flag, see `TEST_REGISTRY_OVERRIDE_CLI_FLAG`)
104
+ * AND the test-only override env var is set and parses as JSON, in which
105
+ * case its keys are shallow-merged on top (see
106
+ * `TEST_REGISTRY_OVERRIDE_ENV_VAR`). Without `allowOverride === true`, the
107
+ * env var is never even read. */
108
+ function resolveRegistry(env, allowOverride) {
109
+ if (!allowOverride) return POSITIVE_CONTROL_REGISTRY;
110
+ const override = env[TEST_REGISTRY_OVERRIDE_ENV_VAR];
111
+ if (!override) return POSITIVE_CONTROL_REGISTRY;
112
+ try {
113
+ const parsed = JSON.parse(override);
114
+ return { ...POSITIVE_CONTROL_REGISTRY, ...parsed };
115
+ } catch {
116
+ return POSITIVE_CONTROL_REGISTRY;
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Extract the live `NodeKind` union members from `planning-document.cts`'s
122
+ * own source text — the "accepted grammars" set (ADR-4910 §4a) — read
123
+ * directly from source (never from the compiled seam, which erases the TS
124
+ * type) so a newly added grammar kind is detected even before any registry
125
+ * entry or fixture exists for it.
126
+ *
127
+ * Pure: takes a `readFile(relPath) -> string|null` accessor so tests can
128
+ * inject a scratch source file without touching the real repo tree.
129
+ */
130
+ function readLiveGrammarKinds(readFile) {
131
+ const text = readFile(PLANNING_DOCUMENT_SRC);
132
+ if (text == null) {
133
+ return { ok: false, reason: `cannot read ${PLANNING_DOCUMENT_SRC}` };
134
+ }
135
+ const m = /export type NodeKind\s*=\s*([^;]+);/.exec(text);
136
+ if (!m) {
137
+ return {
138
+ ok: false,
139
+ reason: `could not find 'export type NodeKind = ...;' in ${PLANNING_DOCUMENT_SRC} — has the type been renamed or removed?`,
140
+ };
141
+ }
142
+ const kinds = [...m[1].matchAll(/'([^']+)'/g)].map((mm) => mm[1]);
143
+ if (kinds.length === 0) {
144
+ return {
145
+ ok: false,
146
+ reason: `the 'NodeKind' union in ${PLANNING_DOCUMENT_SRC} matched but contained no string-literal members`,
147
+ };
148
+ }
149
+ return { ok: true, value: kinds };
150
+ }
151
+
152
+ /**
153
+ * Pure: given the live grammar-kind list, the hardcoded registry, a
154
+ * `readFixture(fileName) -> string|null` accessor, the real `parsePlanningDoc`
155
+ * function, and the artifact name to parse fixtures as, find every gap.
156
+ * Returns `[{ kind, fixture?, reason }]`; empty when clean.
157
+ *
158
+ * Checks, per live grammar kind:
159
+ * 1. a registry entry exists at all (the §7 "parser without one fails the
160
+ * build" guarantee — this fires even with an EMPTY registry);
161
+ * 2. the registered fixture file exists and is readable;
162
+ * 3. the fixture parses successfully via the real parser;
163
+ * 4. the parsed document actually contains a node of that kind (proof the
164
+ * grammar was recognised, not just "didn't throw").
165
+ * Also flags a registry entry naming a grammar the parser no longer
166
+ * declares (a stale entry), so the registry cannot silently drift wider
167
+ * than the parser either.
168
+ */
169
+ function findPositiveControlGaps(liveKinds, registry, readFixture, parsePlanningDocFn, artifactName) {
170
+ const violations = [];
171
+
172
+ for (const kind of liveKinds) {
173
+ const fixtureName = registry[kind];
174
+ if (!fixtureName) {
175
+ violations.push({
176
+ kind,
177
+ reason:
178
+ `parser declares grammar '${kind}' (NodeKind) but POSITIVE_CONTROL_REGISTRY has no entry for it — ` +
179
+ 'add one and a matching fixture under tests/fixtures/planning-document/',
180
+ });
181
+ continue;
182
+ }
183
+
184
+ const content = readFixture(fixtureName);
185
+ if (content == null) {
186
+ violations.push({
187
+ kind,
188
+ fixture: fixtureName,
189
+ reason: `fixture file not found or unreadable: ${path.join(FIXTURE_DIR, fixtureName)}`,
190
+ });
191
+ continue;
192
+ }
193
+
194
+ const result = parsePlanningDocFn(content, artifactName);
195
+ if (!result.ok) {
196
+ violations.push({
197
+ kind,
198
+ fixture: fixtureName,
199
+ reason: `fixture failed to parse via parsePlanningDoc: ${result.reason}`,
200
+ });
201
+ continue;
202
+ }
203
+
204
+ const hasKind = result.value.nodes.some((n) => n.kind === kind);
205
+ if (!hasKind) {
206
+ violations.push({
207
+ kind,
208
+ fixture: fixtureName,
209
+ reason: `fixture parsed successfully but produced no '${kind}' node — it does not actually exercise this grammar`,
210
+ });
211
+ }
212
+ }
213
+
214
+ for (const kind of Object.keys(registry)) {
215
+ if (!liveKinds.includes(kind)) {
216
+ violations.push({
217
+ kind,
218
+ fixture: registry[kind],
219
+ reason: `registry entry names grammar '${kind}', which is not in the parser's live NodeKind union — stale entry, remove it`,
220
+ });
221
+ }
222
+ }
223
+
224
+ return violations;
225
+ }
226
+
227
+ /**
228
+ * Load the built seam and the real source/fixture tree rooted at `root`, and
229
+ * run `findPositiveControlGaps` against them. Returns the same shape as
230
+ * `findPositiveControlGaps`. If the seam hasn't been built yet, or the
231
+ * `NodeKind` union can't be located, reports a single actionable violation
232
+ * rather than throwing.
233
+ *
234
+ * `allowOverride` (default `false`) must be explicitly `true` for the
235
+ * test-only env-var registry override to be honored at all — see
236
+ * `resolveRegistry` and `TEST_REGISTRY_OVERRIDE_ENV_VAR`'s header comment.
237
+ */
238
+ function scanRepo(root, env, allowOverride = false) {
239
+ const readFile = (relPath) => {
240
+ try {
241
+ return fs.readFileSync(path.join(root, relPath), 'utf8');
242
+ } catch {
243
+ return null;
244
+ }
245
+ };
246
+ const readFixture = (fileName) => readFile(path.join(FIXTURE_DIR, fileName));
247
+
248
+ const live = readLiveGrammarKinds(readFile);
249
+ if (!live.ok) {
250
+ return [{ kind: null, reason: live.reason }];
251
+ }
252
+
253
+ const libPath = path.join(root, PLANNING_DOCUMENT_LIB);
254
+ let seam;
255
+ try {
256
+ seam = require(libPath);
257
+ } catch (e) {
258
+ return [
259
+ {
260
+ kind: null,
261
+ reason: `cannot load the planning-document seam at ${path.relative(root, libPath)} — run 'npm run build:lib' first (${e.message})`,
262
+ },
263
+ ];
264
+ }
265
+
266
+ const registry = resolveRegistry(env || process.env, allowOverride);
267
+ return findPositiveControlGaps(live.value, registry, readFixture, seam.parsePlanningDoc, FIXTURE_ARTIFACT_NAME);
268
+ }
269
+
270
+ /** Parse a bare `--root <path>` CLI override (defaults to the real repo root)
271
+ * and the `--test-registry-override` flag that gates `resolveRegistry`'s
272
+ * env-var override (see `TEST_REGISTRY_OVERRIDE_CLI_FLAG`'s header comment).
273
+ * No real invocation (`npm run lint:ci`, `npm run lint:planning-document-
274
+ * positive-control`) ever passes this flag. */
275
+ function parseArgs(argv) {
276
+ let root = path.join(__dirname, '..');
277
+ let allowTestRegistryOverride = false;
278
+ for (let i = 0; i < argv.length; i++) {
279
+ if (argv[i] === '--root' && argv[i + 1]) {
280
+ root = path.resolve(argv[i + 1]);
281
+ i += 1;
282
+ } else if (argv[i] === TEST_REGISTRY_OVERRIDE_CLI_FLAG) {
283
+ allowTestRegistryOverride = true;
284
+ }
285
+ }
286
+ return { root, allowTestRegistryOverride };
287
+ }
288
+
289
+ function main() {
290
+ const { root, allowTestRegistryOverride } = parseArgs(process.argv.slice(2));
291
+ const violations = scanRepo(root, process.env, allowTestRegistryOverride);
292
+ if (violations.length === 0) {
293
+ process.stdout.write(
294
+ 'ok planning-document-positive-control: every declared PlanningDoc grammar has a passing positive-control fixture\n',
295
+ );
296
+ return;
297
+ }
298
+ process.stderr.write(
299
+ 'planning-document-positive-control: PlanningDoc grammar(s) missing or failing a positive-control fixture (ADR-4910 §7).\n',
300
+ );
301
+ process.stderr.write(
302
+ 'Add/fix a fixture under tests/fixtures/planning-document/ and register it in POSITIVE_CONTROL_REGISTRY in\n' +
303
+ 'scripts/lint-planning-document-positive-control.cjs — each fixture must round-trip through parsePlanningDoc\n' +
304
+ 'and yield a node of the declared kind.\n',
305
+ );
306
+ for (const v of violations) {
307
+ const id = v.kind ?? '?';
308
+ const loc = v.fixture ? ` (${path.join(FIXTURE_DIR, v.fixture)})` : '';
309
+ process.stderr.write(` ${id}${loc}: ${v.reason}\n`);
310
+ }
311
+ process.exitCode = 1;
312
+ }
313
+
314
+ if (require.main === module) main();
315
+
316
+ module.exports = {
317
+ findPositiveControlGaps,
318
+ readLiveGrammarKinds,
319
+ resolveRegistry,
320
+ scanRepo,
321
+ parseArgs,
322
+ POSITIVE_CONTROL_REGISTRY,
323
+ FIXTURE_ARTIFACT_NAME,
324
+ PLANNING_DOCUMENT_SRC,
325
+ PLANNING_DOCUMENT_LIB,
326
+ FIXTURE_DIR,
327
+ TEST_REGISTRY_OVERRIDE_ENV_VAR,
328
+ TEST_REGISTRY_OVERRIDE_CLI_FLAG,
329
+ };
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * PR-branch `.planning/` path-classification drift guard (ADR-4910 §8, epic
6
+ * #4906 Phase 5; issues #4605, #4606).
7
+ *
8
+ * `src/pr-branch-patterns.cts` (compiled to
9
+ * `gsd-core/bin/lib/pr-branch-patterns.cjs`) is the single-source-of-truth
10
+ * registry for the three `.planning/` path-classification values
11
+ * `gsd-core/workflows/pr-branch.md` needs: `TRANSIENT_DIRS_SRC`,
12
+ * `STRUCTURAL_RE_SRC`, and `MILESTONE_PHASES_RE_SRC`. A workflow markdown
13
+ * file has no module system — it cannot `require()` that `.cts` source at
14
+ * runtime — so its `create_pr_branch`/`verify` steps carry a hand-copied
15
+ * mirror of each value inside a `NAME="..."` bash assignment. This guard
16
+ * asserts each mirror still matches its canonical value VERBATIM, so the two
17
+ * copies can never silently drift apart (the exact bug class ADR-2143 §3
18
+ * names for markdown-mirrored source-of-truth values, applied here to a
19
+ * bash-variable mirror instead of a pipe-table header).
20
+ *
21
+ * Modeled directly on `scripts/lint-table-schema-drift.cjs`: a standalone
22
+ * node script (not a node:test), pure detector function + `scanRepo` seam,
23
+ * wired into `lint:ci`, exit 0 clean / exit 1 + message on drift.
24
+ */
25
+
26
+ const fs = require('node:fs');
27
+ const path = require('node:path');
28
+
29
+ // Canonical-source-constant name -> the exact bash variable name it mirrors
30
+ // inside gsd-core/workflows/pr-branch.md.
31
+ const PATTERN_VARS = {
32
+ TRANSIENT_DIRS_SRC: 'TRANSIENT_DIRS',
33
+ STRUCTURAL_RE_SRC: 'STRUCTURAL_RE',
34
+ MILESTONE_PHASES_RE_SRC: 'MILESTONE_PHASES_RE',
35
+ };
36
+
37
+ const WORKFLOW_REL_PATH = path.join('gsd-core', 'workflows', 'pr-branch.md');
38
+
39
+ /** Build the exact `NAME="value"` bash assignment line for one pattern. */
40
+ function buildAssignment(bashVar, value) {
41
+ return `${bashVar}="${value}"`;
42
+ }
43
+
44
+ /**
45
+ * Pure: given `patterns` (a `{ SRC_CONST_NAME: value }` map, shaped like the
46
+ * `pr-branch-patterns.cjs` seam) and a `readFile(relPath) -> string|null`
47
+ * accessor, find every pattern whose exact `NAME="value"` assignment does
48
+ * not appear verbatim in the canonical workflow file. Returns
49
+ * `[{ constName, bashVar, expected, reason }]`; empty when clean.
50
+ */
51
+ function findPrBranchPatternDrift(patterns, readFile, vars = PATTERN_VARS, workflowPath = WORKFLOW_REL_PATH) {
52
+ const violations = [];
53
+ const content = readFile(workflowPath);
54
+
55
+ for (const [constName, bashVar] of Object.entries(vars)) {
56
+ const value = patterns[constName];
57
+ if (typeof value !== 'string') {
58
+ violations.push({
59
+ constName,
60
+ bashVar,
61
+ expected: null,
62
+ reason: `${constName} missing or not a string in the pr-branch-patterns seam`,
63
+ });
64
+ continue;
65
+ }
66
+
67
+ if (content == null) {
68
+ violations.push({
69
+ constName,
70
+ bashVar,
71
+ expected: buildAssignment(bashVar, value),
72
+ reason: 'source file not found or unreadable',
73
+ });
74
+ continue;
75
+ }
76
+
77
+ const expected = buildAssignment(bashVar, value);
78
+ if (!content.includes(expected)) {
79
+ violations.push({
80
+ constName,
81
+ bashVar,
82
+ expected,
83
+ reason: 'assignment not found verbatim in canonical workflow file',
84
+ });
85
+ }
86
+ }
87
+ return violations;
88
+ }
89
+
90
+ /**
91
+ * Load the built seam and scan the real repo tree. Returns the same shape as
92
+ * `findPrBranchPatternDrift`. If the seam hasn't been built yet (`npm run
93
+ * build:lib`), reports a single actionable violation rather than throwing.
94
+ */
95
+ function scanRepo(root) {
96
+ const seamPath = path.join(root, 'gsd-core', 'bin', 'lib', 'pr-branch-patterns.cjs');
97
+ let seam;
98
+ try {
99
+ seam = require(seamPath);
100
+ } catch (e) {
101
+ return [{
102
+ constName: null,
103
+ bashVar: null,
104
+ expected: null,
105
+ reason: `cannot load the pr-branch-patterns seam at ${path.relative(root, seamPath)} — run 'npm run build:lib' first (${e.message})`,
106
+ }];
107
+ }
108
+
109
+ const readFile = (relPath) => {
110
+ try {
111
+ return fs.readFileSync(path.join(root, relPath), 'utf8');
112
+ } catch {
113
+ return null;
114
+ }
115
+ };
116
+
117
+ return findPrBranchPatternDrift(seam, readFile);
118
+ }
119
+
120
+ function main() {
121
+ const root = path.join(__dirname, '..');
122
+ const violations = scanRepo(root);
123
+ if (violations.length === 0) {
124
+ process.stdout.write(
125
+ 'ok pr-branch-pattern-drift: every pr-branch-patterns.cts constant appears verbatim in gsd-core/workflows/pr-branch.md\n',
126
+ );
127
+ return;
128
+ }
129
+ process.stderr.write(
130
+ 'pr-branch-pattern-drift: pr-branch-patterns.cts constant(s) whose assignment is absent from gsd-core/workflows/pr-branch.md (ADR-4910 §8, #4605).\n',
131
+ );
132
+ process.stderr.write(
133
+ 'Either update gsd-core/workflows/pr-branch.md to mirror the canonical value verbatim, or update\n'
134
+ + 'src/pr-branch-patterns.cts to match — the two must never drift.\n',
135
+ );
136
+ for (const v of violations) {
137
+ const id = v.bashVar ? `${v.constName} (${v.bashVar})` : (v.constName ?? '?');
138
+ const expected = v.expected ? ` — expected ${JSON.stringify(v.expected)}` : '';
139
+ process.stderr.write(` ${id}: ${v.reason}${expected}\n`);
140
+ }
141
+ process.exitCode = 1;
142
+ }
143
+
144
+ if (require.main === module) main();
145
+
146
+ module.exports = {
147
+ findPrBranchPatternDrift, scanRepo, buildAssignment, PATTERN_VARS, WORKFLOW_REL_PATH,
148
+ };
@@ -78,7 +78,10 @@ const EXACT_INLINE_DIRECTIVE_WORKFLOWS = new Set([
78
78
  'discuss-phase/modes/text.md',
79
79
  'discuss-phase/templates/context.md',
80
80
  'discuss-phase/templates/discussion-log.md',
81
+ 'execute-phase/steps/code-review-disposition.md',
81
82
  'execute-phase/steps/codebase-drift-gate.md',
83
+ 'execute-phase/steps/gap-closure-artifacts.md',
84
+ 'execute-phase/steps/regression-gate.md',
82
85
  'execute-phase/steps/regression-gate-run.md',
83
86
  'execute-phase/steps/worktree-recovery-policy.md',
84
87
  'help/modes/brief.md',