@opengsd/gsd-core 1.10.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (544) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/agents/gsd-code-fixer.md +1 -1
  4. package/agents/gsd-debug-session-manager.md +12 -1
  5. package/agents/gsd-debugger.md +1 -1
  6. package/agents/gsd-doc-synthesizer.md +2 -4
  7. package/agents/gsd-dom-verifier.md +169 -0
  8. package/agents/gsd-eval-auditor.md +1 -1
  9. package/agents/gsd-executor.md +22 -14
  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 +5 -3
  13. package/agents/gsd-pattern-mapper.md +11 -0
  14. package/agents/gsd-phase-researcher.md +23 -2
  15. package/agents/gsd-plan-checker.md +50 -53
  16. package/agents/gsd-planner.md +50 -50
  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 +63 -4
  21. package/agents/gsd-ui-researcher.md +41 -3
  22. package/agents/gsd-user-profiler.md +3 -0
  23. package/agents/gsd-verifier.md +13 -4
  24. package/bin/install.js +1448 -1103
  25. package/commands/gsd/code-review.md +1 -1
  26. package/commands/gsd/discuss-phase.md +1 -1
  27. package/commands/gsd/execute-phase.md +1 -1
  28. package/commands/gsd/import.md +1 -1
  29. package/commands/gsd/map-codebase.md +1 -1
  30. package/commands/gsd/mempalace-capture.md +1 -1
  31. package/commands/gsd/mempalace-recall.md +1 -1
  32. package/commands/gsd/new-milestone.md +1 -1
  33. package/commands/gsd/quick.md +9 -5
  34. package/commands/gsd/review-backlog.md +2 -1
  35. package/commands/gsd/verify-work.md +1 -1
  36. package/gsd-core/bin/gsd-tools.cjs +1035 -138
  37. package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
  38. package/gsd-core/bin/lib/adr-parser.cjs +13 -7
  39. package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
  40. package/gsd-core/bin/lib/api-coverage.cjs +33 -14
  41. package/gsd-core/bin/lib/artifacts.cjs +5 -0
  42. package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
  43. package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
  44. package/gsd-core/bin/lib/audit.cjs +1026 -268
  45. package/gsd-core/bin/lib/broken-windows.cjs +306 -28
  46. package/gsd-core/bin/lib/capability-consent.cjs +149 -15
  47. package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
  48. package/gsd-core/bin/lib/capability-lock.cjs +10 -4
  49. package/gsd-core/bin/lib/capability-registry.cjs +845 -130
  50. package/gsd-core/bin/lib/capability-source.cjs +92 -0
  51. package/gsd-core/bin/lib/capability-state.cjs +18 -3
  52. package/gsd-core/bin/lib/capability-trust.cjs +444 -25
  53. package/gsd-core/bin/lib/capability-validator.cjs +700 -40
  54. package/gsd-core/bin/lib/capability-writer.cjs +3 -2
  55. package/gsd-core/bin/lib/check-command-router.cjs +216 -42
  56. package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
  57. package/gsd-core/bin/lib/cli-exit.cjs +496 -10
  58. package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
  59. package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
  60. package/gsd-core/bin/lib/command-aliases.cjs +22 -0
  61. package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
  62. package/gsd-core/bin/lib/command-roster.cjs +44 -1
  63. package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
  64. package/gsd-core/bin/lib/commands.cjs +1172 -108
  65. package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
  66. package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
  67. package/gsd-core/bin/lib/config-loader.cjs +187 -23
  68. package/gsd-core/bin/lib/config.cjs +102 -3
  69. package/gsd-core/bin/lib/configuration.cjs +129 -37
  70. package/gsd-core/bin/lib/core-utils.cjs +208 -33
  71. package/gsd-core/bin/lib/decisions.cjs +23 -0
  72. package/gsd-core/bin/lib/edge-probe.cjs +9 -1
  73. package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
  74. package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
  75. package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
  76. package/gsd-core/bin/lib/frontmatter.cjs +899 -229
  77. package/gsd-core/bin/lib/gap-checker.cjs +95 -10
  78. package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
  79. package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
  80. package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
  81. package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
  82. package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
  83. package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
  84. package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
  85. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
  86. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
  87. package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
  88. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
  89. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
  90. package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
  91. package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
  92. package/gsd-core/bin/lib/host-integration.cjs +39 -6
  93. package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
  94. package/gsd-core/bin/lib/init-command-router.cjs +118 -21
  95. package/gsd-core/bin/lib/init.cjs +439 -168
  96. package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
  97. package/gsd-core/bin/lib/install-engine.cjs +811 -259
  98. package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
  99. package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
  100. package/gsd-core/bin/lib/install-profiles.cjs +212 -61
  101. package/gsd-core/bin/lib/install-scope.cjs +270 -0
  102. package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
  103. package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
  104. package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
  105. package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
  106. package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
  107. package/gsd-core/bin/lib/intel.cjs +101 -26
  108. package/gsd-core/bin/lib/io.cjs +170 -15
  109. package/gsd-core/bin/lib/learnings.cjs +85 -14
  110. package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
  111. package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
  112. package/gsd-core/bin/lib/markdown-table.cjs +183 -22
  113. package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
  114. package/gsd-core/bin/lib/milestone.cjs +842 -73
  115. package/gsd-core/bin/lib/model-catalog.cjs +232 -16
  116. package/gsd-core/bin/lib/model-resolver.cjs +193 -68
  117. package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
  118. package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
  119. package/gsd-core/bin/lib/pattern.cjs +122 -0
  120. package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
  121. package/gsd-core/bin/lib/phase-id.cjs +514 -40
  122. package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
  123. package/gsd-core/bin/lib/phase-locator.cjs +262 -34
  124. package/gsd-core/bin/lib/phase.cjs +1038 -214
  125. package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
  126. package/gsd-core/bin/lib/plan-document.cjs +263 -0
  127. package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
  128. package/gsd-core/bin/lib/plan-scan.cjs +98 -3
  129. package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
  130. package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
  131. package/gsd-core/bin/lib/planning-scope.cjs +31 -0
  132. package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
  133. package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
  134. package/gsd-core/bin/lib/probe-core.cjs +5 -2
  135. package/gsd-core/bin/lib/profile-output.cjs +1 -1
  136. package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
  137. package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
  138. package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
  139. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
  140. package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
  141. package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
  142. package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
  143. package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
  144. package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
  145. package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
  146. package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
  147. package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
  148. package/gsd-core/bin/lib/roadmap.cjs +442 -96
  149. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
  150. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
  151. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
  152. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
  153. package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
  154. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
  155. package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
  156. package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
  157. package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
  158. package/gsd-core/bin/lib/security.cjs +104 -5
  159. package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
  160. package/gsd-core/bin/lib/smart-entry.cjs +133 -23
  161. package/gsd-core/bin/lib/spec-section.cjs +12 -7
  162. package/gsd-core/bin/lib/state-command-router.cjs +52 -19
  163. package/gsd-core/bin/lib/state-contract.cjs +359 -0
  164. package/gsd-core/bin/lib/state-document.cjs +338 -8
  165. package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
  166. package/gsd-core/bin/lib/state-transition.cjs +846 -176
  167. package/gsd-core/bin/lib/state.cjs +2589 -369
  168. package/gsd-core/bin/lib/surface.cjs +33 -11
  169. package/gsd-core/bin/lib/task-command-router.cjs +111 -1
  170. package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
  171. package/gsd-core/bin/lib/teams-status.cjs +4 -1
  172. package/gsd-core/bin/lib/text-lines.cjs +80 -0
  173. package/gsd-core/bin/lib/token-scanner.cjs +76 -0
  174. package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
  175. package/gsd-core/bin/lib/uat.cjs +1761 -167
  176. package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
  177. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
  178. package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
  179. package/gsd-core/bin/lib/unusable-input.cjs +37 -0
  180. package/gsd-core/bin/lib/update-context.cjs +8 -2
  181. package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
  182. package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
  183. package/gsd-core/bin/lib/validate.cjs +20 -6
  184. package/gsd-core/bin/lib/vendor/README.md +75 -0
  185. package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
  186. package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
  187. package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
  188. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  189. package/gsd-core/bin/lib/verification.cjs +272 -9
  190. package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
  191. package/gsd-core/bin/lib/verify.cjs +453 -918
  192. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
  193. package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
  194. package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
  195. package/gsd-core/bin/lib/workstream.cjs +2 -2
  196. package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
  197. package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
  198. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
  199. package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
  200. package/gsd-core/bin/shared/exit-codes.json +8 -0
  201. package/gsd-core/bin/shared/exit-codes.sh +20 -0
  202. package/gsd-core/bin/shared/model-catalog.json +8 -1
  203. package/gsd-core/references/agent-contracts.md +44 -26
  204. package/gsd-core/references/api-coverage.md +24 -2
  205. package/gsd-core/references/autonomous-smart-discuss.md +3 -3
  206. package/gsd-core/references/checkpoints.md +39 -21
  207. package/gsd-core/references/context-budget.md +1 -1
  208. package/gsd-core/references/decimal-phase-calculation.md +5 -5
  209. package/gsd-core/references/dispatch-isolation-gate.md +138 -0
  210. package/gsd-core/references/doc-conflict-engine.md +1 -1
  211. package/gsd-core/references/edge-probe.md +8 -0
  212. package/gsd-core/references/execute-mvp-tdd.md +4 -6
  213. package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
  214. package/gsd-core/references/execute-phase-context-guard.md +1 -1
  215. package/gsd-core/references/execute-phase-response-language.md +1 -1
  216. package/gsd-core/references/execute-phase-wave-guard.md +17 -11
  217. package/gsd-core/references/failing-direction.md +78 -0
  218. package/gsd-core/references/gate-prompts.md +1 -1
  219. package/gsd-core/references/git-integration.md +5 -5
  220. package/gsd-core/references/git-planning-commit.md +5 -4
  221. package/gsd-core/references/gsd-run-resolver.md +1 -1
  222. package/gsd-core/references/loop-hook-dispatch.md +61 -2
  223. package/gsd-core/references/model-profiles.md +12 -4
  224. package/gsd-core/references/mvp-concepts.md +9 -9
  225. package/gsd-core/references/nyquist-compliance.md +74 -0
  226. package/gsd-core/references/offer-next.md +3 -5
  227. package/gsd-core/references/phase-argument-parsing.md +3 -3
  228. package/gsd-core/references/planner-failing-direction.md +53 -0
  229. package/gsd-core/references/planner-guidance.md +3 -9
  230. package/gsd-core/references/planner-human-verify-mode.md +15 -1
  231. package/gsd-core/references/planner-preconditions.md +1 -1
  232. package/gsd-core/references/planner-reviews.md +1 -1
  233. package/gsd-core/references/planner-revision.md +1 -1
  234. package/gsd-core/references/planner-verify-command-grounding.md +17 -0
  235. package/gsd-core/references/planning-config.md +44 -13
  236. package/gsd-core/references/reviewer-instances.md +31 -0
  237. package/gsd-core/references/revision-loop.md +1 -1
  238. package/gsd-core/references/runtime-aware-dispatch.md +1 -1
  239. package/gsd-core/references/specless-probe-fallback.md +1 -1
  240. package/gsd-core/references/tdd.md +1 -3
  241. package/gsd-core/references/ui-brand.md +65 -21
  242. package/gsd-core/references/ui-consideration-probe.md +1 -1
  243. package/gsd-core/references/universal-anti-patterns.md +5 -5
  244. package/gsd-core/references/verifier-phase-gates.md +192 -0
  245. package/gsd-core/references/verify-command-path-resolvability.md +42 -0
  246. package/gsd-core/references/verify-mvp-mode.md +2 -2
  247. package/gsd-core/references/workstream-flag.md +33 -17
  248. package/gsd-core/templates/README.md +1 -1
  249. package/gsd-core/templates/SECURITY.md +3 -3
  250. package/gsd-core/templates/UI-SPEC.md +25 -3
  251. package/gsd-core/templates/VALIDATION.md +3 -3
  252. package/gsd-core/templates/discussion-log.md +1 -1
  253. package/gsd-core/templates/phase-prompt.md +5 -4
  254. package/gsd-core/templates/state.md +11 -4
  255. package/gsd-core/templates/verification-report.md +9 -1
  256. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  257. package/gsd-core/workflows/add-backlog.md +1 -1
  258. package/gsd-core/workflows/add-phase.md +3 -3
  259. package/gsd-core/workflows/add-tests.md +3 -8
  260. package/gsd-core/workflows/add-todo.md +1 -1
  261. package/gsd-core/workflows/ai-integration-phase.md +13 -20
  262. package/gsd-core/workflows/audit-fix.md +12 -3
  263. package/gsd-core/workflows/audit-milestone.md +9 -9
  264. package/gsd-core/workflows/audit-uat.md +17 -2
  265. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
  266. package/gsd-core/workflows/autonomous.md +11 -27
  267. package/gsd-core/workflows/check-todos.md +1 -1
  268. package/gsd-core/workflows/cleanup.md +64 -5
  269. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
  270. package/gsd-core/workflows/code-review-fix.md +38 -11
  271. package/gsd-core/workflows/code-review.md +159 -52
  272. package/gsd-core/workflows/complete-milestone.md +151 -23
  273. package/gsd-core/workflows/debug.md +12 -8
  274. package/gsd-core/workflows/diagnose-issues.md +47 -15
  275. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  276. package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
  277. package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
  278. package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
  279. package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
  280. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  281. package/gsd-core/workflows/discuss-phase.md +1 -1
  282. package/gsd-core/workflows/do.md +3 -6
  283. package/gsd-core/workflows/docs-update.md +5 -4
  284. package/gsd-core/workflows/edit-phase.md +27 -2
  285. package/gsd-core/workflows/eval-review.md +7 -14
  286. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  287. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
  288. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  289. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  290. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
  291. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
  292. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
  293. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
  294. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
  295. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
  296. package/gsd-core/workflows/execute-phase.md +72 -100
  297. package/gsd-core/workflows/execute-plan.md +52 -15
  298. package/gsd-core/workflows/explore.md +131 -4
  299. package/gsd-core/workflows/extract-learnings.md +1 -1
  300. package/gsd-core/workflows/fast.md +10 -2
  301. package/gsd-core/workflows/forensics.md +1 -1
  302. package/gsd-core/workflows/graduation.md +5 -5
  303. package/gsd-core/workflows/health.md +76 -10
  304. package/gsd-core/workflows/import.md +18 -15
  305. package/gsd-core/workflows/inbox.md +4 -5
  306. package/gsd-core/workflows/ingest-docs.md +49 -16
  307. package/gsd-core/workflows/insert-phase.md +5 -5
  308. package/gsd-core/workflows/list-seeds.md +5 -3
  309. package/gsd-core/workflows/list-workspaces.md +1 -1
  310. package/gsd-core/workflows/manager.md +12 -23
  311. package/gsd-core/workflows/map-codebase.md +1 -1
  312. package/gsd-core/workflows/milestone-summary.md +1 -1
  313. package/gsd-core/workflows/mvp-phase.md +8 -5
  314. package/gsd-core/workflows/new-milestone.md +22 -29
  315. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  316. package/gsd-core/workflows/new-project.md +26 -40
  317. package/gsd-core/workflows/new-workspace.md +1 -1
  318. package/gsd-core/workflows/next.md +14 -2
  319. package/gsd-core/workflows/pause-work.md +1 -1
  320. package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
  321. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
  322. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
  323. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
  324. package/gsd-core/workflows/plan-phase.md +162 -59
  325. package/gsd-core/workflows/plan-review-convergence.md +96 -11
  326. package/gsd-core/workflows/plant-seed.md +2 -2
  327. package/gsd-core/workflows/pr-branch.md +187 -51
  328. package/gsd-core/workflows/profile-user.md +16 -14
  329. package/gsd-core/workflows/progress.md +61 -18
  330. package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
  331. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
  332. package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
  333. package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
  334. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
  335. package/gsd-core/workflows/quick.md +55 -44
  336. package/gsd-core/workflows/remove-phase.md +4 -4
  337. package/gsd-core/workflows/remove-workspace.md +2 -2
  338. package/gsd-core/workflows/resume-project.md +8 -12
  339. package/gsd-core/workflows/review.md +219 -20
  340. package/gsd-core/workflows/scan.md +1 -1
  341. package/gsd-core/workflows/secure-phase.md +3 -3
  342. package/gsd-core/workflows/session-report.md +2 -1
  343. package/gsd-core/workflows/settings-advanced.md +7 -9
  344. package/gsd-core/workflows/settings-integrations.md +64 -31
  345. package/gsd-core/workflows/settings.md +69 -7
  346. package/gsd-core/workflows/ship.md +116 -50
  347. package/gsd-core/workflows/sketch-wrap-up.md +11 -17
  348. package/gsd-core/workflows/sketch.md +12 -18
  349. package/gsd-core/workflows/smart-entry.md +3 -5
  350. package/gsd-core/workflows/spec-phase.md +53 -13
  351. package/gsd-core/workflows/spike-wrap-up.md +7 -11
  352. package/gsd-core/workflows/spike.md +20 -31
  353. package/gsd-core/workflows/stats.md +2 -2
  354. package/gsd-core/workflows/sync-skills.md +64 -9
  355. package/gsd-core/workflows/thread.md +11 -7
  356. package/gsd-core/workflows/transition.md +49 -14
  357. package/gsd-core/workflows/ui-phase.md +15 -21
  358. package/gsd-core/workflows/ui-review.md +8 -12
  359. package/gsd-core/workflows/ultraplan-phase.md +5 -13
  360. package/gsd-core/workflows/undo.md +8 -16
  361. package/gsd-core/workflows/update.md +7 -11
  362. package/gsd-core/workflows/validate-phase.md +3 -3
  363. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
  364. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  365. package/gsd-core/workflows/verify-work.md +66 -25
  366. package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
  367. package/hooks/dist/gsd-check-update-worker.js +56 -13
  368. package/hooks/dist/gsd-check-update.js +19 -1
  369. package/hooks/dist/gsd-config-reload.js +18 -12
  370. package/hooks/dist/gsd-context-monitor.js +19 -10
  371. package/hooks/dist/gsd-cursor-post-tool.js +3 -1
  372. package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
  373. package/hooks/dist/gsd-cursor-session-start.js +2 -1
  374. package/hooks/dist/gsd-cursor-stop.js +2 -1
  375. package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
  376. package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
  377. package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
  378. package/hooks/dist/gsd-graphify-update.sh +22 -18
  379. package/hooks/dist/gsd-node-runner.sh +76 -0
  380. package/hooks/dist/gsd-phase-boundary.sh +1 -0
  381. package/hooks/dist/gsd-prompt-guard.js +37 -27
  382. package/hooks/dist/gsd-read-guard.js +16 -7
  383. package/hooks/dist/gsd-read-injection-scanner.js +55 -32
  384. package/hooks/dist/gsd-session-state.sh +1 -0
  385. package/hooks/dist/gsd-statusline.js +231 -24
  386. package/hooks/dist/gsd-update-banner.js +22 -1
  387. package/hooks/dist/gsd-validate-commit.sh +80 -6
  388. package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
  389. package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
  390. package/hooks/dist/gsd-workflow-guard.js +162 -46
  391. package/hooks/dist/gsd-worktree-path-guard.js +36 -21
  392. package/hooks/dist/gsd-write-guard.js +35 -25
  393. package/hooks/dist/lib/cli-exit.js +560 -0
  394. package/hooks/dist/lib/exit-code-registry.js +98 -0
  395. package/hooks/dist/lib/git-cmd.js +92 -59
  396. package/hooks/dist/lib/git-probe.js +84 -0
  397. package/hooks/dist/lib/hook-exit.js +81 -0
  398. package/hooks/dist/lib/injection-patterns.js +45 -0
  399. package/hooks/dist/lib/isolation-deny-reason.js +39 -0
  400. package/hooks/dist/lib/isolation-sentinel.js +9 -0
  401. package/hooks/dist/managed-hooks-registry.cjs +3 -0
  402. package/hooks/gsd-agent-isolation-guard.js +158 -30
  403. package/hooks/gsd-check-update-worker.js +56 -13
  404. package/hooks/gsd-check-update.js +19 -1
  405. package/hooks/gsd-config-reload.js +18 -12
  406. package/hooks/gsd-context-monitor.js +19 -10
  407. package/hooks/gsd-cursor-post-tool.js +3 -1
  408. package/hooks/gsd-cursor-pre-tool.js +2 -3
  409. package/hooks/gsd-cursor-session-start.js +2 -1
  410. package/hooks/gsd-cursor-stop.js +2 -1
  411. package/hooks/gsd-cursor-subagent-start.js +83 -3
  412. package/hooks/gsd-cursor-subagent-stop.js +6 -3
  413. package/hooks/gsd-ensure-canonical-path.js +2 -1
  414. package/hooks/gsd-graphify-update.sh +22 -18
  415. package/hooks/gsd-node-runner.sh +76 -0
  416. package/hooks/gsd-phase-boundary.sh +1 -0
  417. package/hooks/gsd-prompt-guard.js +37 -27
  418. package/hooks/gsd-read-guard.js +16 -7
  419. package/hooks/gsd-read-injection-scanner.js +55 -32
  420. package/hooks/gsd-session-state.sh +1 -0
  421. package/hooks/gsd-statusline.js +231 -24
  422. package/hooks/gsd-update-banner.js +22 -1
  423. package/hooks/gsd-validate-commit.sh +80 -6
  424. package/hooks/gsd-windsurf-pre-command.js +16 -11
  425. package/hooks/gsd-windsurf-pre-write.js +22 -13
  426. package/hooks/gsd-workflow-guard.js +162 -46
  427. package/hooks/gsd-worktree-path-guard.js +36 -21
  428. package/hooks/gsd-write-guard.js +35 -25
  429. package/hooks/lib/cli-exit.js +560 -0
  430. package/hooks/lib/exit-code-registry.js +98 -0
  431. package/hooks/lib/git-cmd.js +92 -59
  432. package/hooks/lib/git-probe.js +84 -0
  433. package/hooks/lib/hook-exit.js +81 -0
  434. package/hooks/lib/injection-patterns.js +45 -0
  435. package/hooks/lib/isolation-deny-reason.js +39 -0
  436. package/hooks/lib/isolation-sentinel.js +9 -0
  437. package/hooks/managed-hooks-registry.cjs +3 -0
  438. package/package.json +28 -11
  439. package/pi/gsd.cjs +19 -5
  440. package/scripts/base64-scan.sh +74 -12
  441. package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
  442. package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
  443. package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
  444. package/scripts/build-hooks.js +5 -0
  445. package/scripts/changeset/lint.cjs +60 -5
  446. package/scripts/check-alias-drift.cjs +7 -43
  447. package/scripts/check-contract-drift.cjs +297 -0
  448. package/scripts/check-glossary-refs.cjs +77 -15
  449. package/scripts/check-mutation-score-ratchet.cjs +156 -0
  450. package/scripts/ci-check-job-near-cap.cjs +49 -0
  451. package/scripts/ci-pr-mergeability.cjs +262 -0
  452. package/scripts/ci-test-scope.cjs +64 -14
  453. package/scripts/ci-timeout-report.cjs +230 -0
  454. package/scripts/command-contract-helpers.cjs +903 -1
  455. package/scripts/docs-guard-registry.cjs +396 -0
  456. package/scripts/gen-adr-index.cjs +728 -38
  457. package/scripts/gen-capability-registry.cjs +11 -21
  458. package/scripts/gen-context-index.cjs +2 -11
  459. package/scripts/gen-exit-code-docs.cjs +318 -0
  460. package/scripts/gen-exit-code-registry.cjs +891 -0
  461. package/scripts/gen-features.cjs +836 -0
  462. package/scripts/gen-health-docs.cjs +390 -0
  463. package/scripts/gen-hooks-cli-exit.cjs +239 -0
  464. package/scripts/gen-install-tree-fixtures.cjs +2 -2
  465. package/scripts/gen-inventory-manifest.cjs +50 -4
  466. package/scripts/gen-loop-host-contract.cjs +138 -25
  467. package/scripts/gen-registry.cjs +3 -14
  468. package/scripts/gen-scripts-cli-exit.cjs +185 -0
  469. package/scripts/gen-state-md-docs.cjs +727 -0
  470. package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
  471. package/scripts/lib/alias-drift-families.cjs +46 -0
  472. package/scripts/lib/ci-job-timing.cjs +72 -0
  473. package/scripts/lib/cli-exit.cjs +546 -44
  474. package/scripts/lib/drift-scan.cjs +308 -0
  475. package/scripts/lib/exit-code-registry.cjs +98 -0
  476. package/scripts/lib/ndjson-reporter.cjs +119 -0
  477. package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
  478. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
  479. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
  480. package/scripts/lint-canary-version-leak.cjs +73 -0
  481. package/scripts/lint-command-contract.cjs +96 -13
  482. package/scripts/lint-completion-predicate-drift.cjs +933 -0
  483. package/scripts/lint-completion-ratio-drift.cjs +214 -0
  484. package/scripts/lint-default-flip-documentation.cjs +193 -0
  485. package/scripts/lint-docs-guard-registration.cjs +495 -0
  486. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
  487. package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
  488. package/scripts/lint-eslint-glob-coverage.cjs +340 -0
  489. package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
  490. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
  491. package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
  492. package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
  493. package/scripts/lint-milestone-window-drift.cjs +468 -0
  494. package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
  495. package/scripts/lint-phase-enumeration-drift.cjs +492 -0
  496. package/scripts/lint-plan-count-drift.cjs +318 -0
  497. package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
  498. package/scripts/lint-planning-prompt-drift.cjs +471 -0
  499. package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
  500. package/scripts/lint-regression-test-names.cjs +15 -13
  501. package/scripts/lint-removed-but-needed.cjs +488 -0
  502. package/scripts/lint-seam-enforcement.cjs +182 -0
  503. package/scripts/lint-slug-derivation-drift.cjs +921 -0
  504. package/scripts/lint-source-test-name-collision.cjs +241 -0
  505. package/scripts/lint-state-field-drift.cjs +805 -0
  506. package/scripts/lint-state-write-path-drift.cjs +950 -0
  507. package/scripts/lint-test-file-count.allowlist.json +137 -8
  508. package/scripts/lint-test-file-count.cjs +25 -3
  509. package/scripts/lint-unreachable-guard-drift.cjs +830 -0
  510. package/scripts/lint-vendored-deps.cjs +297 -0
  511. package/scripts/mutation-matrix.cjs +599 -50
  512. package/scripts/pr-changed-files.cjs +63 -0
  513. package/scripts/pr-template-policy.cjs +14 -4
  514. package/scripts/prompt-injection-scan.sh +100 -14
  515. package/scripts/require-issue-link-policy.cjs +192 -0
  516. package/scripts/secret-scan.sh +75 -13
  517. package/scripts/select-docs-guards.cjs +56 -0
  518. package/scripts/sync-runtime-launcher.cjs +24 -7
  519. package/skills/gsd-autonomous/SKILL.md +0 -1
  520. package/skills/gsd-code-review/SKILL.md +1 -1
  521. package/skills/gsd-discuss-phase/SKILL.md +1 -1
  522. package/skills/gsd-execute-phase/SKILL.md +1 -2
  523. package/skills/gsd-import/SKILL.md +1 -1
  524. package/skills/gsd-map-codebase/SKILL.md +1 -1
  525. package/skills/gsd-mempalace-capture/SKILL.md +1 -1
  526. package/skills/gsd-mempalace-recall/SKILL.md +1 -1
  527. package/skills/gsd-new-milestone/SKILL.md +1 -1
  528. package/skills/gsd-next/SKILL.md +0 -1
  529. package/skills/gsd-plan-phase/SKILL.md +0 -1
  530. package/skills/gsd-progress/SKILL.md +0 -1
  531. package/skills/gsd-quick/SKILL.md +9 -5
  532. package/skills/gsd-review-backlog/SKILL.md +2 -1
  533. package/skills/gsd-stats/SKILL.md +0 -1
  534. package/skills/gsd-verify-work/SKILL.md +1 -1
  535. package/vscode/package.json +1 -1
  536. package/bin/lib/ui-safety-gate.cjs +0 -107
  537. package/gsd-core/workflows/discovery-phase.md +0 -298
  538. package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
  539. package/gsd-core/workflows/verify-phase.md +0 -574
  540. package/scripts/affected-tests-lib.cjs +0 -554
  541. package/scripts/lint-allow-test-rule-refs.cjs +0 -162
  542. package/scripts/lint-emitted-drift-ack.cjs +0 -344
  543. package/scripts/run-affected-tests.cjs +0 -7
  544. package/scripts/run-tests.cjs +0 -1051
@@ -0,0 +1,193 @@
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-parser.test.cjs',
35
+ 'adr-parser.unit.test.cjs',
36
+ 'agent-marker-documentation-guard.test.cjs',
37
+ 'antigravity-upgrades.test.cjs',
38
+ 'capability-cli.test.cjs',
39
+ 'capability-validator-task-content-resolver.test.cjs',
40
+ 'ci-docs-guard-registry.test.cjs',
41
+ 'ci-test-scope.test.cjs',
42
+ 'cline-install.test.cjs',
43
+ 'code-review-depth.test.cjs',
44
+ 'code-review-pipeline-regression.test.cjs',
45
+ 'codebuddy-upgrades.test.cjs',
46
+ 'commands.test.cjs',
47
+ 'commit-docs-bypass.test.cjs',
48
+ 'complexity-trigger.test.cjs',
49
+ 'concurrency-safety.test.cjs',
50
+ 'cursor-imperative-reference.test.cjs',
51
+ 'declarative-reference-antigravity.test.cjs',
52
+ 'declarative-reference-zcode.test.cjs',
53
+ 'emitted-attribution.test.cjs',
54
+ 'eslint-rules.test.cjs',
55
+ 'estimate-calibrate.test.cjs',
56
+ 'gen-context-index.test.cjs',
57
+ 'gen-registry.test.cjs',
58
+ 'gsd-agent-isolation-guard.test.cjs',
59
+ 'hermes-dispatch-upgrade.test.cjs',
60
+ 'install-minimal-hooks.test.cjs',
61
+ 'install-runtime-artifacts.test.cjs',
62
+ 'installer-migration-config-root-marker.test.cjs',
63
+ 'installer-migration-pi-extension-ext.test.cjs',
64
+ 'installer-migrations.test.cjs',
65
+ 'kimi-upgrades.test.cjs',
66
+ 'lint-allow-test-rule-refs.test.cjs',
67
+ 'lint-docs-command-form.test.cjs',
68
+ 'lint-docs-required.test.cjs',
69
+ 'manifest-version-sync.test.cjs',
70
+ 'milestone-archive.test.cjs',
71
+ 'model-resolver.test.cjs',
72
+ 'new-project-mvp-prompt.test.cjs',
73
+ 'onboard-command.test.cjs',
74
+ 'opencode-command-dir-plural.test.cjs',
75
+ 'phase.test.cjs',
76
+ 'pr-branch-planning-filter.test.cjs',
77
+ 'precommit-alias-drift-hook.test.cjs',
78
+ 'removed-but-needed-lint.test.cjs',
79
+ 'repo-invariants.test.cjs',
80
+ 'require-issue-link-policy.test.cjs',
81
+ 'reviewer-manifest-body.test.cjs',
82
+ 'run-tests-harness.test.cjs',
83
+ 'runtime-name-policy.test.cjs',
84
+ 'security-prompt-injection.security.test.cjs',
85
+ 'shipped-reference-cites.test.cjs',
86
+ 'state.test.cjs',
87
+ 'worktree-safety.test.cjs',
88
+ ];
89
+
90
+ /**
91
+ * Security follow-up FIX 3: a per-file fingerprint of every distinct
92
+ * `docs/...` path TOKEN referenced by each baselined file (derived via
93
+ * scripts/lint-docs-guard-registration.cjs's `extractDocsPathReferences`,
94
+ * never retyped from memory). A baselined file whose live fingerprint
95
+ * DIFFERS from the recorded one here fails the lint — the exemption's
96
+ * premise ("this file doesn't really guard shipped docs content") may no
97
+ * longer hold and a human must re-confirm it before the entry is updated.
98
+ * Keeping this a plain, sorted, diffable path list (not a hash) is
99
+ * deliberate: a reviewer can see exactly WHAT changed from the PR diff
100
+ * alone.
101
+ *
102
+ * Seeded 2026-08-23 alongside DOCS_GUARD_EXEMPT_BASELINE above, from the
103
+ * exact same scan.
104
+ */
105
+ const DOCS_GUARD_EXEMPT_DOCS_PATHS = {
106
+ 'adr-parser.test.cjs': ['docs/adr/0001.md', 'docs/adr/0002.md', 'docs/adr/0010.md', 'docs/adr/NNNN.md'],
107
+ 'adr-parser.unit.test.cjs': ['docs/adr/0001.md', 'docs/adr/0099.md', 'docs/adr/NNNN.md'],
108
+ 'agent-marker-documentation-guard.test.cjs': ['docs/reference', 'docs/reference/workflow-fragments.md'],
109
+ 'antigravity-upgrades.test.cjs': ['docs/cli', 'docs/cli/gcli-migration', 'docs/cli/permissions'],
110
+ 'capability-cli.test.cjs': ['docs/reference/gsd-capability-command.md'],
111
+ // #3970: cites docs/adr/3646-per-task-content-resolution-seam.md in an
112
+ // explanatory comment describing ADR-3646's Decision 3; the file never
113
+ // reads that (or any) docs/ file.
114
+ 'capability-validator-task-content-resolver.test.cjs': ['docs/adr/3646-per-task-content-resolution-seam.md'],
115
+ 'ci-docs-guard-registry.test.cjs': [
116
+ 'docs/AGENTS.md', 'docs/COMMANDS.md', 'docs/INVENTORY.md', 'docs/a.md', 'docs/adr',
117
+ 'docs/adr/0001-example.md', 'docs/adrenaline.md', 'docs/bar.md', 'docs/foo.md', 'docs/how-to/foo.md',
118
+ 'docs/how-to/some-unrelated-guide.md', 'docs/how-to/x.md', 'docs/some-unrelated-file.md',
119
+ 'docs/totally-unrelated.md',
120
+ ],
121
+ 'ci-test-scope.test.cjs': [
122
+ 'docs/a.md', 'docs/adr', 'docs/adr/22-plan-drift-guard.md', 'docs/how-to/configure-model-profiles.md',
123
+ 'docs/installer-migrations.md', 'docs/ja-JP', 'docs/ja-JP/USAGE.md', 'docs/usage.md', 'docs/x.md',
124
+ ],
125
+ 'cline-install.test.cjs': ['docs/guide.md'],
126
+ 'code-review-depth.test.cjs': ['docs/src/auth/x.ts'],
127
+ 'code-review-pipeline-regression.test.cjs': ['docs/DEVELOPMENT.md'],
128
+ 'codebuddy-upgrades.test.cjs': ['docs/cli/sub-agents'],
129
+ 'commands.test.cjs': ['docs/x.md'],
130
+ 'commit-docs-bypass.test.cjs': [
131
+ 'docs/40-design.md', 'docs/CONFIGURATION.md', 'docs/readme.md', 'docs/tracked-var-mentioning',
132
+ ],
133
+ 'complexity-trigger.test.cjs': ['docs/readme.md'],
134
+ // #3884: cites docs/CLI-TOOLS.md:736 in an explanatory comment describing
135
+ // the real `frontmatter get <file> [--field key]` CLI shape; the file
136
+ // never reads that (or any) docs/ file.
137
+ 'concurrency-safety.test.cjs': ['docs/CLI-TOOLS.md'],
138
+ 'cursor-imperative-reference.test.cjs': ['docs/sdk/typescript'],
139
+ 'declarative-reference-antigravity.test.cjs': ['docs/cli/features'],
140
+ 'declarative-reference-zcode.test.cjs': ['docs/reference/host-integration-capability-matrix.md'],
141
+ 'emitted-attribution.test.cjs': ['docs/README.md', 'docs/tests', 'docs/tests/helpers/install-shared.cjs'],
142
+ // #3914: cites docs/adr/3889-process-exit-contract.md ~:350-362 in an
143
+ // explanatory comment describing the intentional computed-property
144
+ // boundary move; the file never reads that (or any) docs/ file.
145
+ 'eslint-rules.test.cjs': ['docs/adr/3889-process-exit-contract.md', 'docs/readme.md'],
146
+ 'estimate-calibrate.test.cjs': [
147
+ 'docs/adr', 'docs/adr/2629-phase-effort-estimation-calibration.md', 'docs/reference',
148
+ 'docs/reference/planning-artifacts.md',
149
+ ],
150
+ 'gen-context-index.test.cjs': ['docs/CONTEXT-INDEX.json', 'docs/INVENTORY-MANIFEST.json'],
151
+ 'gen-registry.test.cjs': ['docs/registries', 'docs/registries/reviewers.json'],
152
+ 'gsd-agent-isolation-guard.test.cjs': ['docs/adr/1239-...md', 'docs/adr/1239-gsd-embeddable-orchestration-engine.md'],
153
+ 'hermes-dispatch-upgrade.test.cjs': ['docs/guides/delegation-patterns.md'],
154
+ 'install-minimal-hooks.test.cjs': ['docs/en/hooks', 'docs/en/users/features/hooks'],
155
+ 'install-runtime-artifacts.test.cjs': ['docs/CONFIGURATION.md', 'docs/adr/58-...md', 'docs/adr/58-runtime-install-policy-module.md', 'docs/cli/slash-commands'],
156
+ 'installer-migration-config-root-marker.test.cjs': ['docs/installer-migrations.md'],
157
+ 'installer-migration-pi-extension-ext.test.cjs': ['docs/installer-migrations.md'],
158
+ 'installer-migrations.test.cjs': ['docs/installer-migrations.md'],
159
+ 'kimi-upgrades.test.cjs': ['docs/reference/host-integration-capability-matrix.md'],
160
+ 'lint-allow-test-rule-refs.test.cjs': ['docs/readme.md'],
161
+ 'lint-docs-command-form.test.cjs': ['docs/adr', 'docs/adr/999-example.md', 'docs/how-to/example.md'],
162
+ 'lint-docs-required.test.cjs': [
163
+ 'docs/COMMANDS.md', 'docs/USER-GUIDE.md', 'docs/adr', 'docs/adr/0001-foo.md', 'docs/adr/0099-new.md',
164
+ 'docs/agents', 'docs/agents/triage-labels.md',
165
+ ],
166
+ 'manifest-version-sync.test.cjs': [],
167
+ // #3884: re-confirmed — the added docs/CLI-TOOLS.md:458 reference is the
168
+ // same class as the existing docs/TESTING-SUITES.md one (a placement-note
169
+ // / explanatory comment citing documented CLI behavior for context, never
170
+ // a read target); the exemption's premise still holds for both.
171
+ 'milestone-archive.test.cjs': ['docs/CLI-TOOLS.md', 'docs/TESTING-SUITES.md'],
172
+ 'model-resolver.test.cjs': ['docs/TESTING-SUITES.md'],
173
+ 'new-project-mvp-prompt.test.cjs': ['docs/CONFIGURATION.md'],
174
+ 'onboard-command.test.cjs': ['docs/adr/0001-runtime.md'],
175
+ 'opencode-command-dir-plural.test.cjs': ['docs/commands'],
176
+ 'phase.test.cjs': ['docs/adr/3524-...md', 'docs/adr/3524-cjs-sdk-hard-seam.md'],
177
+ 'pr-branch-planning-filter.test.cjs': ['docs/readme.md'],
178
+ 'precommit-alias-drift-hook.test.cjs': ['docs/adr/0174-...md', 'docs/adr/0174-retire-gsd-sdk-package-boundary.md'],
179
+ 'removed-but-needed-lint.test.cjs': [
180
+ 'docs/README.md', 'docs/getting-started.md', 'docs/gsd-new-workspace.md', 'docs/setup.md', 'docs/some-doc.md',
181
+ ],
182
+ 'repo-invariants.test.cjs': ['docs/FEATURES.md', 'docs/workflows/README'],
183
+ 'require-issue-link-policy.test.cjs': ['docs/-prefixed', 'docs/CONFIGURATION.md', 'docs/a.md', 'docs/b.md', 'docs/guide.md'],
184
+ 'reviewer-manifest-body.test.cjs': ['docs/how-to/ship-a-reviewer-lane.md'],
185
+ 'run-tests-harness.test.cjs': ['docs/TESTING-SUITES.md'],
186
+ 'runtime-name-policy.test.cjs': ['docs/customize/skills'],
187
+ 'security-prompt-injection.security.test.cjs': ['docs/notes.md'],
188
+ 'shipped-reference-cites.test.cjs': [],
189
+ 'state.test.cjs': ['docs/CONFIGURATION.md', 'docs/reference/state-md.md'],
190
+ 'worktree-safety.test.cjs': ['docs/SUMMARY.md'],
191
+ };
192
+
193
+ module.exports = { DOCS_GUARD_EXEMPT_BASELINE, DOCS_GUARD_EXEMPT_DOCS_PATHS };
@@ -0,0 +1,38 @@
1
+ [
2
+ {
3
+ "path": "gsd-core/bin/lib/vendor/re2js.d.cts",
4
+ "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."
5
+ },
6
+ {
7
+ "path": "src/vendor/re2js.d.cts",
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
+ },
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
+ },
14
+ {
15
+ "path": "tests/fixtures/brand-typing/bad-calibrated-as-sample-basis.cts",
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."
17
+ },
18
+ {
19
+ "path": "tests/fixtures/brand-typing/bad-double-calibration.cts",
20
+ "reason": "Deliberate MUST-NOT-COMPILE type-error fixture (#3059): type-aware linting would fail by design; it exists to prove the compiler rejects it."
21
+ },
22
+ {
23
+ "path": "tests/fixtures/brand-typing/bad-raw-against-budget.cts",
24
+ "reason": "Deliberate MUST-NOT-COMPILE type-error fixture (#3059): type-aware linting would fail by design; it exists to prove the compiler rejects it."
25
+ },
26
+ {
27
+ "path": "tests/fixtures/brand-typing/bad-rebrand-calibrated-as-raw.cts",
28
+ "reason": "Deliberate MUST-NOT-COMPILE type-error fixture (#3059): type-aware linting would fail by design; it exists to prove the compiler rejects it."
29
+ },
30
+ {
31
+ "path": "tests/fixtures/brand-typing/bad-unbranded-number-as-raw.cts",
32
+ "reason": "Deliberate MUST-NOT-COMPILE type-error fixture (#3059): type-aware linting would fail by design; it exists to prove the compiler rejects it."
33
+ },
34
+ {
35
+ "path": "tests/fixtures/brand-typing/ok-correct-composition.cts",
36
+ "reason": "Positive-control counterpart to the bad-* must-not-compile fixtures (#3059); kept in the same exemption so the pair stays together."
37
+ }
38
+ ]
@@ -0,0 +1,340 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * lint-eslint-glob-coverage.cjs — ESLint `files:` glob coverage drift guard (#3059).
6
+ *
7
+ * ## What this enforces
8
+ *
9
+ * `eslint.config.mjs` is a flat config: a tracked source file is only linted
10
+ * if it matches at least one config object's `files:` glob (or a global,
11
+ * files-less block). A file matching NO glob resolves to zero reachable
12
+ * rules and `eslint .` silently exits 0 on it — the #3059 defect class (62
13
+ * tracked source files found with this shape). This guard walks every
14
+ * tracked `.cjs/.cts/.js/.mjs` source file, resolves its real ESLint config,
15
+ * and fails when a file resolves to zero rules and isn't a deliberately
16
+ * exempted, reasoned allowlist entry.
17
+ *
18
+ * This checks rule REACHABILITY (does at least one rule apply to this file
19
+ * at all, any severity), not rule SEVERITY (whether an applicable rule is
20
+ * `error` vs `warn` vs `off`) — severity coverage is a separate gate, #1885
21
+ * F17. A file with one `off` rule reachable still counts as "covered" here:
22
+ * it proves the file was deliberately targeted by a `files:` glob, which is
23
+ * the thing #3059 is about.
24
+ *
25
+ * ## Goodhart rationale
26
+ *
27
+ * A coverage metric is trivially gameable by padding the allowlist instead
28
+ * of fixing the glob, so every knob here is built to resist that:
29
+ * - Every allowlist entry MUST carry a non-empty `reason` — an unreasoned
30
+ * entry is indistinguishable from "quietly made the metric look better".
31
+ * - The allowlist only ratchets DOWN: an entry whose path now resolves to
32
+ * >=1 rule (`allowlist_stale`) is a failure, forcing prompt removal
33
+ * rather than letting stale exemptions accumulate as free cover for
34
+ * future accidental escapes at the same path.
35
+ * - A tracked-file-count floor (`tracked_count_below_floor`) exists so a
36
+ * broken or empty `git ls-files` (e.g. wrong cwd, detached worktree)
37
+ * can't report a vacuous "0 escapes out of 0 checked" clean run.
38
+ *
39
+ * ## Ignored vs. unmatched (the discrimination this script makes)
40
+ *
41
+ * ESLint's `ignores:` blocks are the one legitimate "this file is not meant
42
+ * to be linted" decision (e.g. the ADR-457 tsc-emitted `.cjs` artifacts
43
+ * under `gsd-core/bin/lib/`) and must NOT be reported as uncovered. But
44
+ * `ESLint#isPathIgnored` cannot be trusted uniformly across extensions:
45
+ * for ESLint's default-lintable extensions (`.js`/`.mjs`/`.cjs`), it
46
+ * reports `true` only when the path matches an explicit `ignores:` glob —
47
+ * verified empirically: an unmatched top-level `.cjs` probe file reports
48
+ * `isPathIgnored() === false` with an empty resolved rule set, not `true`.
49
+ * For `.cts` (and any other non-default extension), flat config requires an
50
+ * EXPLICIT `files:` glob match to be linted at all; a `.cts` file matching
51
+ * no `files:` glob ALSO reports `isPathIgnored() === true` — indistinguishable,
52
+ * via this API, from a genuine `ignores:` entry (verified with a scratch
53
+ * `.cts` fixture under `tests/fixtures/`). This repo's `ignores:` list never
54
+ * contains a `.cts` path (ADR-457 retires only the emitted `.cjs`; the
55
+ * `.cts` source is always meant to stay linted), so for `.cts` specifically
56
+ * an `isPathIgnored() === true` verdict can only mean "matches no `files:`
57
+ * glob" and is therefore treated as UNCOVERED, not ignored. See
58
+ * `resolveFileCoverage` below.
59
+ *
60
+ * ## Why `bin/install.js` is NOT in the allowlist
61
+ *
62
+ * The allowlist below is exclusively for files that resolve to ZERO rules —
63
+ * it is a registry of accepted escapes, not a general-purpose "reasons for
64
+ * how a file is configured" log. The `bin/install.js` / `bin/gsd-mcp-server.js`
65
+ * / `scripts/build-hooks.js` family is deliberately covered by a minimal,
66
+ * 2-rule block in `eslint.config.mjs` per ADR-1703 (targeting only the
67
+ * portability defect surface, not a full style sweep of ~12k lines of
68
+ * generated code) — see the comment at that block in `eslint.config.mjs`.
69
+ * Because 2 rules is non-empty, that family already passes this guard
70
+ * without needing an allowlist entry, and adding one anyway would itself be
71
+ * flagged `allowlist_stale` (see the ratchet above). The allowlist exemption
72
+ * surface deliberately cannot be used to re-state a decision that is already
73
+ * recorded in the config; #3059 is the guard, ADR-1703 is the decision.
74
+ */
75
+
76
+ const fs = require('fs');
77
+ const path = require('path');
78
+
79
+ const ROOT = path.join(__dirname, '..');
80
+ const ALLOWLIST_PATH = path.join(__dirname, 'lint-eslint-glob-coverage.allowlist.json');
81
+
82
+ const SOURCE_EXT_RE = /\.(cjs|cts|js|mjs)$/;
83
+
84
+ // ESLint's flat-config default-lintable extensions: a file with one of these
85
+ // extensions that matches no `files:` glob still reports `isPathIgnored()
86
+ // === false` (with an empty resolved rule set) — so for these extensions,
87
+ // `isPathIgnored() === true` reliably means an explicit `ignores:` match.
88
+ const DEFAULT_LINTABLE_EXT_RE = /\.(js|mjs|cjs)$/;
89
+
90
+ const MIN_TRACKED_SOURCE_FILES = 500;
91
+
92
+ /**
93
+ * Runs `git ls-files` and returns the tracked source files (repo-relative,
94
+ * POSIX-normalized, filtered to SOURCE_EXT_RE). Never throws: a git failure
95
+ * (non-zero exit or timeout) produces a degraded `{ ok: false }` result so
96
+ * callers can turn it into a `git_failed` violation instead of crashing.
97
+ *
98
+ * @param {object} [opts]
99
+ * @param {Function} [opts.execFile] - injectable sync exec function with the
100
+ * `execFileSync(cmd, args, options)` signature; defaults to
101
+ * `child_process.execFileSync`.
102
+ */
103
+ function listTrackedSourceFiles({ execFile } = {}) {
104
+ const run = execFile || require('child_process').execFileSync;
105
+ let stdout;
106
+ try {
107
+ // The test runner and CI execute inside a container where this repo is
108
+ // owned by a different UID than the running user; bare `git ls-files`
109
+ // then refuses with "detected dubious ownership" unless the path is in
110
+ // `safe.directory`, and this guard degrades to a `git_failed` violation
111
+ // — exactly where it must run to be a useful gate (#3059). `-c
112
+ // safe.directory=*` scopes the override to THIS invocation only (it
113
+ // never writes to any config file, global or local), and the wildcard
114
+ // is fine here because this command only ever enumerates tracked paths
115
+ // in the repo the guard is already executing inside.
116
+ stdout = run('git', ['-c', 'safe.directory=*', 'ls-files'], {
117
+ cwd: ROOT,
118
+ encoding: 'utf8',
119
+ // 30s — `git ls-files` on this tree returns ~1175 paths in <1s; 30s is
120
+ // the CLAUDE.md git ceiling, generous for a cold index.
121
+ timeout: 30000,
122
+ });
123
+ } catch (err) {
124
+ return { ok: false, files: [], error: (err && err.message) || String(err) };
125
+ }
126
+
127
+ const files = String(stdout)
128
+ // CRLF-safe: `git ls-files` output may carry \r\n on a Windows checkout
129
+ // or a git config with core.autocrlf set (DEFECT.CRLF class).
130
+ .split(/\r?\n/)
131
+ .filter((line) => line.length > 0)
132
+ // Unconditional backslash normalization (never path.sep-gated): the
133
+ // guard's own process may run on any platform regardless of what
134
+ // produced the tracked-file listing.
135
+ .map((line) => line.replace(/\\/g, '/'))
136
+ .filter((line) => SOURCE_EXT_RE.test(line));
137
+
138
+ return { ok: true, files };
139
+ }
140
+
141
+ /** Loads and parses the allowlist JSON file. */
142
+ function loadAllowlist() {
143
+ const raw = fs.readFileSync(ALLOWLIST_PATH, 'utf8');
144
+ return JSON.parse(raw);
145
+ }
146
+
147
+ /**
148
+ * Resolves the ESLint coverage verdict for a single tracked file. See the
149
+ * "Ignored vs. unmatched" header section for the extension-dependent
150
+ * discrimination rationale.
151
+ *
152
+ * @param {import('eslint').ESLint} eslint
153
+ * @param {string} relPath - repo-relative POSIX path
154
+ * @returns {Promise<{ ignored: boolean, ruleCount: number }>}
155
+ */
156
+ async function resolveFileCoverage(eslint, relPath) {
157
+ const absPath = path.join(ROOT, relPath);
158
+ const ignored = await eslint.isPathIgnored(absPath);
159
+
160
+ if (ignored) {
161
+ if (DEFAULT_LINTABLE_EXT_RE.test(relPath)) {
162
+ // .js/.mjs/.cjs: isPathIgnored() only reports true for an explicit
163
+ // `ignores:` glob match — a recorded decision.
164
+ return { ignored: true, ruleCount: 0 };
165
+ }
166
+ // .cts (or any non-default extension): isPathIgnored() can't
167
+ // distinguish "explicit ignores: match" from "no files: glob matched
168
+ // it at all" — and this repo's ignores: list never targets .cts, so
169
+ // treat it as the latter (uncovered), never as ignored.
170
+ return { ignored: false, ruleCount: 0 };
171
+ }
172
+
173
+ const config = await eslint.calculateConfigForFile(absPath);
174
+ const ruleCount = config && config.rules ? Object.keys(config.rules).length : 0;
175
+ return { ignored: false, ruleCount };
176
+ }
177
+
178
+ /** Builds the default real-ESLint-backed resolveConfig function. */
179
+ function createDefaultResolveConfig() {
180
+ const { ESLint } = require('eslint');
181
+ const eslint = new ESLint({ cwd: ROOT });
182
+ return (relPath) => resolveFileCoverage(eslint, relPath);
183
+ }
184
+
185
+ /**
186
+ * The pure coverage predicate. All I/O is injectable via `deps` so tests
187
+ * never need a temp repo, a real subprocess, or a real ESLint instance:
188
+ *
189
+ * @param {object} [deps]
190
+ * @param {string[] | { ok: boolean, files?: string[], error?: string }} [deps.trackedFiles]
191
+ * Either a plain array of tracked source paths (success shorthand), or a
192
+ * `listTrackedSourceFiles()`-shaped result object (so a git failure can be
193
+ * injected directly). Defaults to a real `listTrackedSourceFiles()` call.
194
+ * @param {(relPath: string) => Promise<{ignored:boolean,ruleCount:number}> | {ignored:boolean,ruleCount:number}} [deps.resolveConfig]
195
+ * Per-file coverage resolver. Defaults to a real ESLint instance.
196
+ * @param {Array<{path:string,reason?:string}>} [deps.allowlist] - defaults to
197
+ * the real `loadAllowlist()`.
198
+ * @param {number} [deps.minTrackedFiles] - defaults to MIN_TRACKED_SOURCE_FILES.
199
+ * @returns {Promise<{ ok: boolean, escapes: Array<{path:string}>, violations: Array<{kind:string,path:string|null,detail:string}>, checked: number }>}
200
+ */
201
+ async function checkGlobCoverage(deps = {}) {
202
+ const minTrackedFiles =
203
+ typeof deps.minTrackedFiles === 'number' ? deps.minTrackedFiles : MIN_TRACKED_SOURCE_FILES;
204
+
205
+ const violations = [];
206
+
207
+ let trackedResult;
208
+ if (deps.trackedFiles === undefined) {
209
+ trackedResult = listTrackedSourceFiles();
210
+ } else if (Array.isArray(deps.trackedFiles)) {
211
+ trackedResult = { ok: true, files: deps.trackedFiles };
212
+ } else {
213
+ trackedResult = deps.trackedFiles;
214
+ }
215
+
216
+ if (!trackedResult.ok) {
217
+ violations.push({
218
+ kind: 'git_failed',
219
+ path: null,
220
+ detail: trackedResult.error || 'listTrackedSourceFiles() failed',
221
+ });
222
+ return { ok: false, escapes: [], violations, checked: 0 };
223
+ }
224
+
225
+ const trackedFiles = trackedResult.files;
226
+
227
+ if (trackedFiles.length < minTrackedFiles) {
228
+ violations.push({
229
+ kind: 'tracked_count_below_floor',
230
+ path: null,
231
+ detail: `tracked source file count ${trackedFiles.length} is below the floor of ${minTrackedFiles} — a broken or empty git ls-files must never report a vacuous clean run`,
232
+ });
233
+ }
234
+
235
+ const trackedSet = new Set(trackedFiles);
236
+ const allowlist = deps.allowlist === undefined ? loadAllowlist() : deps.allowlist;
237
+
238
+ const seenAllowlistPaths = new Set();
239
+ const allowlistPathSet = new Set();
240
+ for (const entry of allowlist) {
241
+ const entryPath = entry && entry.path;
242
+
243
+ if (seenAllowlistPaths.has(entryPath)) {
244
+ violations.push({
245
+ kind: 'allowlist_duplicate',
246
+ path: entryPath,
247
+ detail: 'path appears more than once in the allowlist',
248
+ });
249
+ } else {
250
+ seenAllowlistPaths.add(entryPath);
251
+ }
252
+ allowlistPathSet.add(entryPath);
253
+
254
+ if (!Object.prototype.hasOwnProperty.call(entry, 'reason')) {
255
+ violations.push({
256
+ kind: 'allowlist_missing_reason',
257
+ path: entryPath,
258
+ detail: 'allowlist entry is missing a "reason" key',
259
+ });
260
+ } else if (typeof entry.reason !== 'string' || entry.reason.trim() === '') {
261
+ violations.push({
262
+ kind: 'allowlist_empty_reason',
263
+ path: entryPath,
264
+ detail: 'allowlist entry "reason" is empty or whitespace-only',
265
+ });
266
+ }
267
+
268
+ if (!trackedSet.has(entryPath)) {
269
+ violations.push({
270
+ kind: 'allowlist_missing_path',
271
+ path: entryPath,
272
+ detail: 'allowlisted path is not a tracked source file',
273
+ });
274
+ }
275
+ }
276
+
277
+ const resolveConfig = deps.resolveConfig || createDefaultResolveConfig();
278
+
279
+ const escapes = [];
280
+ let checked = 0;
281
+
282
+ for (const file of trackedFiles) {
283
+ checked += 1;
284
+ const result = await resolveConfig(file);
285
+ const isAllowlisted = allowlistPathSet.has(file);
286
+
287
+ if (result.ignored) {
288
+ // A recorded ESLint `ignores:` decision — never an escape, regardless
289
+ // of allowlist membership.
290
+ continue;
291
+ }
292
+
293
+ if (result.ruleCount === 0) {
294
+ if (isAllowlisted) continue;
295
+ escapes.push({ path: file });
296
+ violations.push({
297
+ kind: 'uncovered',
298
+ path: file,
299
+ detail: 'resolves to 0 reachable ESLint rules and is not allowlisted',
300
+ });
301
+ } else if (isAllowlisted) {
302
+ violations.push({
303
+ kind: 'allowlist_stale',
304
+ path: file,
305
+ detail: 'allowlisted path now resolves to >=1 ESLint rule — prune the entry, the allowlist only ratchets down',
306
+ });
307
+ }
308
+ }
309
+
310
+ return { ok: violations.length === 0, escapes, violations, checked };
311
+ }
312
+
313
+ if (require.main === module) {
314
+ checkGlobCoverage()
315
+ .then((result) => {
316
+ if (result.violations.length > 0) {
317
+ console.error(
318
+ `lint-eslint-glob-coverage: ${result.violations.length} violation(s) across ${result.checked} tracked source file(s) (${result.escapes.length} uncovered escape(s))`
319
+ );
320
+ for (const v of result.violations) {
321
+ console.error(` [${v.kind}] ${v.path === null ? '(n/a)' : v.path}${v.detail ? ' — ' + v.detail : ''}`);
322
+ }
323
+ process.exitCode = 1;
324
+ } else {
325
+ console.log(`ok lint-eslint-glob-coverage: ${result.checked} tracked source file(s), 0 escapes`);
326
+ }
327
+ })
328
+ .catch((err) => {
329
+ console.error(err && err.stack ? err.stack : String(err));
330
+ process.exitCode = 1;
331
+ });
332
+ }
333
+
334
+ module.exports = {
335
+ checkGlobCoverage,
336
+ listTrackedSourceFiles,
337
+ loadAllowlist,
338
+ SOURCE_EXT_RE,
339
+ MIN_TRACKED_SOURCE_FILES,
340
+ };
@@ -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
  }