@opengsd/gsd-core 1.4.3 → 1.5.0-rc.1

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 (149) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +3 -3
  3. package/agents/gsd-executor.md +1 -1
  4. package/agents/gsd-plan-checker.md +11 -2
  5. package/agents/gsd-planner.md +11 -7
  6. package/agents/gsd-verifier.md +3 -3
  7. package/bin/install.js +825 -149
  8. package/commands/gsd/autonomous.md +5 -1
  9. package/commands/gsd/ns-manage.md +8 -1
  10. package/commands/gsd/ns-project.md +5 -0
  11. package/commands/gsd/ns-review.md +4 -1
  12. package/commands/gsd/ns-workflow.md +7 -1
  13. package/commands/gsd/plan-review-convergence.md +5 -4
  14. package/commands/gsd/surface.md +12 -5
  15. package/gemini-extension.json +1 -1
  16. package/gsd-core/bin/gsd-tools.cjs +198 -101
  17. package/gsd-core/bin/lib/audit-command-router.cjs +61 -0
  18. package/gsd-core/bin/lib/capability-registry.cjs +417 -0
  19. package/gsd-core/bin/lib/capability-state.cjs +336 -0
  20. package/gsd-core/bin/lib/cli-exit.cjs +22 -3
  21. package/gsd-core/bin/lib/config-loader.cjs +716 -0
  22. package/gsd-core/bin/lib/configuration.cjs +4 -34
  23. package/gsd-core/bin/lib/core-utils.cjs +198 -0
  24. package/gsd-core/bin/lib/core.cjs +57 -1817
  25. package/gsd-core/bin/lib/federated-config.cjs +182 -0
  26. package/gsd-core/bin/lib/graphify-command-router.cjs +74 -0
  27. package/gsd-core/bin/lib/init.cjs +58 -12
  28. package/gsd-core/bin/lib/install-profiles.cjs +157 -3
  29. package/gsd-core/bin/lib/intel-command-router.cjs +116 -0
  30. package/gsd-core/bin/lib/io.cjs +167 -0
  31. package/gsd-core/bin/lib/loop-host-contract.cjs +105 -0
  32. package/gsd-core/bin/lib/loop-resolver.cjs +460 -0
  33. package/gsd-core/bin/lib/model-resolver.cjs +426 -0
  34. package/gsd-core/bin/lib/phase-id.cjs +215 -0
  35. package/gsd-core/bin/lib/phase-locator.cjs +148 -0
  36. package/gsd-core/bin/lib/profile-pipeline.cjs +2 -2
  37. package/gsd-core/bin/lib/roadmap-parser.cjs +443 -0
  38. package/gsd-core/bin/lib/roadmap.cjs +4 -1
  39. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +96 -9
  40. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +2 -1
  41. package/gsd-core/bin/lib/runtime-homes.cjs +40 -0
  42. package/gsd-core/bin/lib/runtime-name-policy.cjs +1 -0
  43. package/gsd-core/bin/lib/shell-command-projection.cjs +13 -0
  44. package/gsd-core/bin/lib/state.cjs +114 -2
  45. package/gsd-core/bin/lib/surface.cjs +66 -14
  46. package/gsd-core/bin/lib/verify.cjs +1 -1
  47. package/gsd-core/bin/shared/model-catalog.json +5 -0
  48. package/gsd-core/bin/shared/runtime-aliases.manifest.json +3 -0
  49. package/gsd-core/references/planner-reviews.md +5 -2
  50. package/gsd-core/templates/phase-prompt.md +7 -7
  51. package/gsd-core/templates/project.md +19 -2
  52. package/gsd-core/templates/summary-complex.md +1 -0
  53. package/gsd-core/templates/summary-minimal.md +1 -0
  54. package/gsd-core/templates/summary-standard.md +1 -0
  55. package/gsd-core/templates/summary.md +1 -0
  56. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  57. package/gsd-core/workflows/add-backlog.md +1 -1
  58. package/gsd-core/workflows/add-phase.md +1 -1
  59. package/gsd-core/workflows/add-tests.md +1 -1
  60. package/gsd-core/workflows/add-todo.md +1 -1
  61. package/gsd-core/workflows/ai-integration-phase.md +1 -1
  62. package/gsd-core/workflows/audit-fix.md +1 -1
  63. package/gsd-core/workflows/audit-milestone.md +1 -1
  64. package/gsd-core/workflows/audit-uat.md +1 -1
  65. package/gsd-core/workflows/autonomous.md +86 -15
  66. package/gsd-core/workflows/check-todos.md +1 -1
  67. package/gsd-core/workflows/cleanup.md +1 -1
  68. package/gsd-core/workflows/code-review-fix.md +6 -4
  69. package/gsd-core/workflows/code-review.md +3 -2
  70. package/gsd-core/workflows/complete-milestone.md +11 -5
  71. package/gsd-core/workflows/debug.md +1 -1
  72. package/gsd-core/workflows/diagnose-issues.md +1 -1
  73. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  74. package/gsd-core/workflows/discuss-phase/modes/auto.md +1 -1
  75. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  76. package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
  77. package/gsd-core/workflows/discuss-phase.md +8 -1
  78. package/gsd-core/workflows/do.md +1 -1
  79. package/gsd-core/workflows/docs-update.md +1 -1
  80. package/gsd-core/workflows/edit-phase.md +1 -1
  81. package/gsd-core/workflows/eval-review.md +4 -1
  82. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  83. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  84. package/gsd-core/workflows/execute-phase.md +8 -1
  85. package/gsd-core/workflows/execute-plan.md +1 -1
  86. package/gsd-core/workflows/explore.md +1 -1
  87. package/gsd-core/workflows/extract-learnings.md +1 -1
  88. package/gsd-core/workflows/forensics.md +1 -1
  89. package/gsd-core/workflows/graduation.md +1 -1
  90. package/gsd-core/workflows/health.md +1 -1
  91. package/gsd-core/workflows/help/modes/full.md +1 -1
  92. package/gsd-core/workflows/import.md +1 -1
  93. package/gsd-core/workflows/ingest-docs.md +1 -1
  94. package/gsd-core/workflows/insert-phase.md +1 -1
  95. package/gsd-core/workflows/list-workspaces.md +1 -1
  96. package/gsd-core/workflows/manager.md +1 -1
  97. package/gsd-core/workflows/map-codebase.md +1 -1
  98. package/gsd-core/workflows/milestone-summary.md +1 -1
  99. package/gsd-core/workflows/mvp-phase.md +1 -1
  100. package/gsd-core/workflows/new-milestone.md +1 -1
  101. package/gsd-core/workflows/new-project.md +1 -1
  102. package/gsd-core/workflows/new-workspace.md +1 -1
  103. package/gsd-core/workflows/next.md +1 -1
  104. package/gsd-core/workflows/pause-work.md +1 -1
  105. package/gsd-core/workflows/plan-milestone-gaps.md +1 -1
  106. package/gsd-core/workflows/plan-phase.md +27 -2
  107. package/gsd-core/workflows/plan-review-convergence.md +60 -33
  108. package/gsd-core/workflows/plant-seed.md +1 -1
  109. package/gsd-core/workflows/profile-user.md +1 -1
  110. package/gsd-core/workflows/progress.md +1 -1
  111. package/gsd-core/workflows/quick.md +2 -2
  112. package/gsd-core/workflows/remove-phase.md +1 -1
  113. package/gsd-core/workflows/remove-workspace.md +1 -1
  114. package/gsd-core/workflows/resume-project.md +1 -1
  115. package/gsd-core/workflows/review.md +1 -1
  116. package/gsd-core/workflows/scan.md +1 -1
  117. package/gsd-core/workflows/secure-phase.md +1 -1
  118. package/gsd-core/workflows/settings-advanced.md +1 -1
  119. package/gsd-core/workflows/settings-integrations.md +1 -1
  120. package/gsd-core/workflows/settings.md +1 -1
  121. package/gsd-core/workflows/ship.md +8 -1
  122. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  123. package/gsd-core/workflows/sketch.md +1 -1
  124. package/gsd-core/workflows/spec-phase.md +1 -1
  125. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  126. package/gsd-core/workflows/spike.md +1 -1
  127. package/gsd-core/workflows/stats.md +1 -1
  128. package/gsd-core/workflows/thread.md +1 -1
  129. package/gsd-core/workflows/transition.md +1 -1
  130. package/gsd-core/workflows/ui-phase.md +1 -1
  131. package/gsd-core/workflows/ui-review.md +1 -1
  132. package/gsd-core/workflows/ultraplan-phase.md +1 -1
  133. package/gsd-core/workflows/validate-phase.md +1 -1
  134. package/gsd-core/workflows/verify-phase.md +1 -1
  135. package/gsd-core/workflows/verify-work.md +8 -1
  136. package/package.json +7 -2
  137. package/scripts/base64-scan.sh +1 -1
  138. package/scripts/changeset/cli.cjs +8 -1
  139. package/scripts/changeset/lint.cjs +38 -2
  140. package/scripts/ci-test-scope.cjs +21 -10
  141. package/scripts/gen-capability-registry.cjs +1808 -0
  142. package/scripts/gen-loop-host-contract.cjs +471 -0
  143. package/scripts/lint-regression-test-names.allowlist.json +269 -0
  144. package/scripts/lint-regression-test-names.cjs +117 -0
  145. package/scripts/lint-test-file-count.allowlist.json +12 -4
  146. package/scripts/prompt-injection-scan.sh +4 -4
  147. package/scripts/run-tests.cjs +79 -16
  148. package/scripts/secret-scan.sh +3 -3
  149. package/scripts/run-cross-platform-tests.cjs +0 -67
@@ -0,0 +1,269 @@
1
+ [
2
+ "bug-10-semver-policy-consolidation.test.cjs",
3
+ "bug-130-finishinstall-opencode-testmode.test.cjs",
4
+ "bug-131-release-tarball-smoke-explicit-home.test.cjs",
5
+ "bug-14-progress-auto-flag-dropped.test.cjs",
6
+ "bug-167-query-meta-command.test.cjs",
7
+ "bug-17-askuserquestion-option-cap.test.cjs",
8
+ "bug-170-workflow-fallback-install-hint.test.cjs",
9
+ "bug-1736-local-install-commands.test.cjs",
10
+ "bug-1754-js-hook-guard.test.cjs",
11
+ "bug-1817-sh-hook-guard.test.cjs",
12
+ "bug-1818-unknown-flags.test.cjs",
13
+ "bug-1826-phases-clear-confirm.test.cjs",
14
+ "bug-1829-inherit-model-profile.test.cjs",
15
+ "bug-1834-sh-hooks-installed.test.cjs",
16
+ "bug-1891-file-resolution.test.cjs",
17
+ "bug-190-bridge-collapse.test.cjs",
18
+ "bug-1906-hook-relative-paths.test.cjs",
19
+ "bug-1908-uninstall-manifest.test.cjs",
20
+ "bug-1924-preserve-user-artifacts.test.cjs",
21
+ "bug-1967-cache-invalidation.test.cjs",
22
+ "bug-1974-context-exhaustion-record.test.cjs",
23
+ "bug-2002-offer-next-context.test.cjs",
24
+ "bug-2004-pr-branch-milestone.test.cjs",
25
+ "bug-21-state-md-template-frontmatter.test.cjs",
26
+ "bug-211-launcher-home-fallback.test.cjs",
27
+ "bug-2136-sh-hook-version.test.cjs",
28
+ "bug-214-phase-researcher-write-truncation-contract.test.cjs",
29
+ "bug-214-writer-agents-write-truncation-contract.test.cjs",
30
+ "bug-222-research-synthesizer-write-contract.test.cjs",
31
+ "bug-224-pick-stdout-capture.test.cjs",
32
+ "bug-2248-local-install-statusline.test.cjs",
33
+ "bug-2256-model-overrides-transport.test.cjs",
34
+ "bug-2268-parallel-discuss.test.cjs",
35
+ "bug-2344-read-guard-claudecode-env.test.cjs",
36
+ "bug-2346-agent-read-loop-guards.test.cjs",
37
+ "bug-2351-intel-kilo-layout.test.cjs",
38
+ "bug-2376-opencode-windows-home-path.test.cjs",
39
+ "bug-2384-post-merge-deletion-audit.test.cjs",
40
+ "bug-2388-plan-phase-no-branch-rename.test.cjs",
41
+ "bug-2396-makefile-test-priority.test.cjs",
42
+ "bug-2399-commit-docs-plan-phase.test.cjs",
43
+ "bug-2410-stream-checkpoint-heartbeats.test.cjs",
44
+ "bug-2418-antigravity-bare-path.test.cjs",
45
+ "bug-2419-project-researcher-agent.test.cjs",
46
+ "bug-2421-planner-grep-gate-hygiene.test.cjs",
47
+ "bug-2424-reapply-patches-baseline-detection.test.cjs",
48
+ "bug-2432-quick-plan-predispatch-commit.test.cjs",
49
+ "bug-2451-context-monitor-over-report.test.cjs",
50
+ "bug-2470-update-md-claude-path.test.cjs",
51
+ "bug-2492-context-coverage-gate.test.cjs",
52
+ "bug-2501-resurrection-detection.test.cjs",
53
+ "bug-2502-insert-phase-state-update.test.cjs",
54
+ "bug-2504-uat-foundation-phases.test.cjs",
55
+ "bug-2506-settings-profile-nonclaude-warning.test.cjs",
56
+ "bug-2516-inherit-model-execute-phase.test.cjs",
57
+ "bug-2520-read-guard-hook-subprocess-env.test.cjs",
58
+ "bug-2523-quick-deferred-items.test.cjs",
59
+ "bug-2530-valid-config-keys.test.cjs",
60
+ "bug-2543-gsd-slash-namespace.test.cjs",
61
+ "bug-2545-copilot-unreplaced-paths.test.cjs",
62
+ "bug-2549-2550-2552-discuss-phase-context.test.cjs",
63
+ "bug-2554-decimal-phase-filter.test.cjs",
64
+ "bug-2557-gemini-local-hook-paths.test.cjs",
65
+ "bug-2559-stale-search-year.test.cjs",
66
+ "bug-260-worktree-path-guard.test.cjs",
67
+ "bug-2601-inherit-model-profile.test.cjs",
68
+ "bug-261-worktree-force-add-guard.test.cjs",
69
+ "bug-2630-state-frontmatter-milestone-switch.test.cjs",
70
+ "bug-2638-sub-repos-canonical-location.test.cjs",
71
+ "bug-2643-skill-frontmatter-name.test.cjs",
72
+ "bug-2659-audit-open-crash.test.cjs",
73
+ "bug-2660-one-liner-extraction.test.cjs",
74
+ "bug-2661-roadmap-sync-parallel.test.cjs",
75
+ "bug-2686-review-fix-worktree.test.cjs",
76
+ "bug-2698-crlf-install.test.cjs",
77
+ "bug-2760-codex-install-defensive.test.cjs",
78
+ "bug-2769-requirements-header-variants.test.cjs",
79
+ "bug-2770-annotate-deps-int-coerce.test.cjs",
80
+ "bug-2771-user-profile-manifest.test.cjs",
81
+ "bug-2772-gitmodules-path-intersection.test.cjs",
82
+ "bug-2784-update-cache-clear-path.test.cjs",
83
+ "bug-279-codex-agent-mapping.test.cjs",
84
+ "bug-2794-opencode-model-profile-overrides.test.cjs",
85
+ "bug-2798-context-window-config-key.test.cjs",
86
+ "bug-2801-ingest-docs-handler.test.cjs",
87
+ "bug-2808-skill-hyphen-name.test.cjs",
88
+ "bug-2831-opencode-home-path-prefix.test.cjs",
89
+ "bug-2836-audit-open-summary-uat-drift.test.cjs",
90
+ "bug-2838-summary-rescue-gitignored-planning.test.cjs",
91
+ "bug-2839-review-fix-transactional-cleanup.test.cjs",
92
+ "bug-2851-workflow-bare-gsd-tools.test.cjs",
93
+ "bug-2866-codex-strip-no-trailing-newline.test.cjs",
94
+ "bug-2876-skill-frontmatter-quote.test.cjs",
95
+ "bug-2911-audit-open-output-shape.test.cjs",
96
+ "bug-2912-progress-context-authority.test.cjs",
97
+ "bug-2916-handle-branching-default-base.test.cjs",
98
+ "bug-2942-detect-custom-skills.test.cjs",
99
+ "bug-2943-config-get-context-window-default.test.cjs",
100
+ "bug-2948-spike-wrap-up-dispatch.test.cjs",
101
+ "bug-2949-sketch-wrap-up-dispatch.test.cjs",
102
+ "bug-2950-stale-command-refs.test.cjs",
103
+ "bug-2954-help-md-slash-command-stubs.test.cjs",
104
+ "bug-2957-claude-global-postinstall-message.test.cjs",
105
+ "bug-2969-verify-reapply-patches.test.cjs",
106
+ "bug-2973-profile-user-skills-path.test.cjs",
107
+ "bug-2979-hook-absolute-node.test.cjs",
108
+ "bug-2986-config-schema-mutation-killers.test.cjs",
109
+ "bug-2990-code-fixer-worktree-branch.test.cjs",
110
+ "bug-2992-check-latest-version.test.cjs",
111
+ "bug-2994-verify-reapply-patches-installed-path.test.cjs",
112
+ "bug-2995-post-install-script-paths.test.cjs",
113
+ "bug-2998-pristine-dir-populated.test.cjs",
114
+ "bug-3017-codex-hook-absolute-node.test.cjs",
115
+ "bug-3018-codex-discuss-fallback.test.cjs",
116
+ "bug-3019-help-passthrough.test.cjs",
117
+ "bug-3037-gemini-duplicate-commands.test.cjs",
118
+ "bug-3050-update-backup-eacces-nonfatal.test.cjs",
119
+ "bug-3054-stale-gsd-next-references.test.cjs",
120
+ "bug-3072-optional-sketch-findings-guard.test.cjs",
121
+ "bug-3083-resume-route-clear.test.cjs",
122
+ "bug-3086-git-create-tag-config-gate.test.cjs",
123
+ "bug-3087-planner-directive-language.test.cjs",
124
+ "bug-3096-ai-integration-phase-parallel-race.test.cjs",
125
+ "bug-3097-3099-executor-worktree-path-safety.test.cjs",
126
+ "bug-3120-secure-phase-empty-register.test.cjs",
127
+ "bug-3126-global-skills-base-runtime-path.test.cjs",
128
+ "bug-3127-state-begin-phase-idempotent.test.cjs",
129
+ "bug-3128-roadmap-plan-count-slug-layout.test.cjs",
130
+ "bug-3129-validate-commit-git-bypass.test.cjs",
131
+ "bug-3130-update-npx-robust-invocation.test.cjs",
132
+ "bug-3135-capture-backlog-workflow.test.cjs",
133
+ "bug-3150-stats-json-decimal-phase-gaps.test.cjs",
134
+ "bug-3156-plan-phase-opencode-dispatch.test.cjs",
135
+ "bug-3163-codex-agents-md.test.cjs",
136
+ "bug-3168-task-to-agent-rename.test.cjs",
137
+ "bug-3181-node-cellar-path.test.cjs",
138
+ "bug-3195-quick-resurrection-guard.test.cjs",
139
+ "bug-3197-gsd-tools-config-whitelist.test.cjs",
140
+ "bug-321-config-defaults-clone-strategy.test.cjs",
141
+ "bug-3212-execute-phase-stall-safe-resume.test.cjs",
142
+ "bug-3227-config-set-model-overrides.test.cjs",
143
+ "bug-3236-capture-seed-one-shot.test.cjs",
144
+ "bug-3242-state-update-progress-trample.test.cjs",
145
+ "bug-3243-dotted-command-form.test.cjs",
146
+ "bug-3245-codex-toml-floats.test.cjs",
147
+ "bug-3257-nested-plans-undercount.test.cjs",
148
+ "bug-3258-no-stale-gsd-intel-references.test.cjs",
149
+ "bug-3275-fmstr-non-string-scalars.test.cjs",
150
+ "bug-3285-codex-hooks-state-allowed.test.cjs",
151
+ "bug-3286-state-write-routing.test.cjs",
152
+ "bug-3288-model-catalog-install-path.test.cjs",
153
+ "bug-3290-intel-updater-layout-block.test.cjs",
154
+ "bug-33-settings-model-profile-adaptive.test.cjs",
155
+ "bug-3320-planner-deep-work-rules.test.cjs",
156
+ "bug-3321-verifier-runs-probes.test.cjs",
157
+ "bug-3346-codex-aot-toml-key.test.cjs",
158
+ "bug-3357-codex-legacy-hooks-json-migration.test.cjs",
159
+ "bug-3360-codex-execute-phase-worktrees.test.cjs",
160
+ "bug-338-local-install-settings-local-json.test.cjs",
161
+ "bug-3381-verify-work-workstream.test.cjs",
162
+ "bug-3384-secondary-defects.test.cjs",
163
+ "bug-3407-pristine-stale-content.test.cjs",
164
+ "bug-3413-shell-command-projection.test.cjs",
165
+ "bug-3418-progress-flag-routing.test.cjs",
166
+ "bug-3426-codex-windows-hooks.test.cjs",
167
+ "bug-3427-3433-codex-install-shape.test.cjs",
168
+ "bug-3430-planner-phase-contract.test.cjs",
169
+ "bug-3431-debug-command-yaml.test.cjs",
170
+ "bug-3441-path-action-projection.test.cjs",
171
+ "bug-3442-codex-legacy-hooks-json-migration.test.cjs",
172
+ "bug-3442-shim-projection-drift-guard.test.cjs",
173
+ "bug-3446-resume-continue-here-discovery.test.cjs",
174
+ "bug-3454-state-dollar-backreference-growth.test.cjs",
175
+ "bug-3489-complete-phase-idempotent.test.cjs",
176
+ "bug-3491-nested-git-worktree.test.cjs",
177
+ "bug-3509-path-spaces.test.cjs",
178
+ "bug-3516-reapply-patches-gsd-update-filter.test.cjs",
179
+ "bug-3521-quick-cleanup-cwd-pin.test.cjs",
180
+ "bug-3523-cjs-loadconfig-branching-strategy-warning.test.cjs",
181
+ "bug-3537-padded-id-against-unpadded-roadmap.test.cjs",
182
+ "bug-3541-installer-migration-prompt-user-resolution.test.cjs",
183
+ "bug-3542-executor-git-stash-prohibition.test.cjs",
184
+ "bug-3562-codex-install-skill-surface.test.cjs",
185
+ "bug-3566-codex-hooks-feature-canonical-key.test.cjs",
186
+ "bug-3571-configuration-manifest-install-path.test.cjs",
187
+ "bug-3582-codex-skills-materialized.test.cjs",
188
+ "bug-3584-runtime-slash-emitters.test.cjs",
189
+ "bug-3584-runtime-slash-formatter.test.cjs",
190
+ "bug-3588-npm-audit-clean.test.cjs",
191
+ "bug-3599-roadmap-get-phase-project-code-prefix.test.cjs",
192
+ "bug-3605-stale-research-insert-phase-agent-refs.test.cjs",
193
+ "bug-3608-antigravity-update-runtime-classification.test.cjs",
194
+ "bug-3610-installer-migration-bundled-hooks-classification.test.cjs",
195
+ "bug-3628-bundled-hook-classifier-whitelist.test.cjs",
196
+ "bug-3631-router-raw-flag.test.cjs",
197
+ "bug-3657-verify-reapply-patches-pristine-drift.test.cjs",
198
+ "bug-3659-applysurface-prune-skill-dirs.test.cjs",
199
+ "bug-3668-workflow-runtime-resolution.test.cjs",
200
+ "bug-3670-cursor-local-install-migration-lock.test.cjs",
201
+ "bug-3677-agent-colon-namespace-leak.test.cjs",
202
+ "bug-3678-executor-commit-docs-respect.test.cjs",
203
+ "bug-3683-command-colon-namespace-leak.test.cjs",
204
+ "bug-3683-command-cross-reference-invariant.test.cjs",
205
+ "bug-3683-workflow-colon-namespace-leak.test.cjs",
206
+ "bug-3689-resume-glob-nomatch.test.cjs",
207
+ "bug-3691-annotate-deps-plans-block-variants.test.cjs",
208
+ "bug-3706-ui-safety-gate-false-positives.test.cjs",
209
+ "bug-3707-locked-worktree-cleanup.test.cjs",
210
+ "bug-3727-code-review-fix-flag-dispatch.test.cjs",
211
+ "bug-3735-profiles-core-includes-surface.test.cjs",
212
+ "bug-3739-gap-checker-padded-prefix-context.test.cjs",
213
+ "bug-376-claude-js-hook-gsd-rewriter.test.cjs",
214
+ "bug-378-update-check-scoped-name.test.cjs",
215
+ "bug-3784-gsd-settings-model-profile-ui-omits-adaptive.test.cjs",
216
+ "bug-3805-fast-md-log-to-state-schema.test.cjs",
217
+ "bug-3808-codex-adapter-text-mode-fallback.test.cjs",
218
+ "bug-3810-no-gsd-sdk-runtime-refs.test.cjs",
219
+ "bug-384-agents-runtime-aware.test.cjs",
220
+ "bug-397-state-preserve-executor-authored.test.cjs",
221
+ "bug-410-install-defaults-test-mode-guard.test.cjs",
222
+ "bug-416-archive-dir-null.test.cjs",
223
+ "bug-442-config-dir-equals-in-path.test.cjs",
224
+ "bug-444-resolver-local-claude-install.test.cjs",
225
+ "bug-447-gap-analysis-phase-req-ids.test.cjs",
226
+ "bug-474-clock-seam-date-determinism.test.cjs",
227
+ "bug-492-effort-manifest-fallback.test.cjs",
228
+ "bug-500-planned-phase-progress-corruption.test.cjs",
229
+ "bug-501-flat-phase-details-milestone-leak.test.cjs",
230
+ "bug-503-update-agent-antigravity-detection.test.cjs",
231
+ "bug-505-remove-dead-sdk-verification.test.cjs",
232
+ "bug-549-total-phases-overcounts-with-phase-section-heading.test.cjs",
233
+ "bug-557-details-summary-milestone-strip.test.cjs",
234
+ "bug-570-codex-leak-scanner.test.cjs",
235
+ "bug-571-doc-writer-fix-mode-edit-only.test.cjs",
236
+ "bug-580-local-sh-hook-bash-wrapper.test.cjs",
237
+ "bug-619-codebase-drift-gate-shim.test.cjs",
238
+ "bug-621-plan-phase-gap-analysis-gsd-run.test.cjs",
239
+ "bug-622-graphify-optional-graph-html.test.cjs",
240
+ "bug-630-wave-cleanup-orchestrator-root.test.cjs",
241
+ "bug-637-workflow-no-hardcoded-home-tool.test.cjs",
242
+ "bug-641-files-from-suite-token.test.cjs",
243
+ "bug-663-redos-roadmap-phase-parsing.test.cjs",
244
+ "bug-685-windowshide-spawn.test.cjs",
245
+ "bug-687-agy-timeout.test.cjs",
246
+ "bug-704-codex-launcher-path-corruption.test.cjs",
247
+ "bug-730-milestone-phase-details-scope.test.cjs",
248
+ "bug-782-cline-skills-emission.test.cjs",
249
+ "bug-783-kilo-global-skills-base.test.cjs",
250
+ "bug-851-codex-quick-adapter-agent-type-fallback.test.cjs",
251
+ "bug-853-bg-dispatch-runtime-gating.test.cjs",
252
+ "bug-866-profile-pipeline-temp-root.test.cjs",
253
+ "bug-891-non-claude-runtime-home-fallback.test.cjs",
254
+ "bug-892-validate-checklist-roadmap-phases.test.cjs",
255
+ "bug-905-state-syncstatefrontmatter-preserve-scalars.test.cjs",
256
+ "bug-924-claude-flat-skill-layout.test.cjs",
257
+ "bug-925-context-monitor-hook-event-name.test.cjs",
258
+ "bug-936-no-nested-spawner-wrap.test.cjs",
259
+ "bug-941-managed-hooks-registry-manifest.test.cjs",
260
+ "bug-947-hermes-gsd-prefix.test.cjs",
261
+ "bug-948-state-noop-write-guard.test.cjs",
262
+ "bug-950-quick-summary-status-complete.test.cjs",
263
+ "bug-967-verify-key-links-strict-paths.test.cjs",
264
+ "bug-969-test-infra-flake-hardening.test.cjs",
265
+ "bug-974-graphify-budget-missing-value.test.cjs",
266
+ "bug-977-fnm-multishell-path.test.cjs",
267
+ "bug-978-milestone-complete-force.test.cjs",
268
+ "bug-983-trae-windsurf-claude-path-leak.test.cjs"
269
+ ]
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * lint-regression-test-names.cjs — ban NEW top-level bug-NNNN test files.
6
+ *
7
+ * ## Why
8
+ *
9
+ * The 2026-06 CI audit found 244 one-off `tests/bug-NNNN-*.test.cjs` files —
10
+ * ~38% of the suite. `node --test` spawns one child process per FILE, so file
11
+ * count (not test count) is the unit of CI overhead, and it is worst on the
12
+ * Windows lanes where every spawn is Defender-scanned. Each regression test
13
+ * belongs in the owning module's main test file as a regression case (e.g. a
14
+ * `describe('regressions')` block in `tests/<module>.test.cjs`), where it
15
+ * costs zero additional processes.
16
+ *
17
+ * ## What this enforces
18
+ *
19
+ * Identity ratchet (scripts/lib/allowlist-ratchet.cjs) over basenames matching
20
+ * /^bug-\d+.*\.test\.cjs$/ in tests/:
21
+ * - A NEW bug-* file (not in the allowlist) fails: fold the regression into
22
+ * the owning module's test file instead.
23
+ * - A REMOVED bug-* file with a stale allowlist entry also fails: prune the
24
+ * entry from scripts/lint-regression-test-names.allowlist.json so the
25
+ * baseline only ever shrinks.
26
+ *
27
+ * ## --update (allowlist drift repair)
28
+ *
29
+ * `node scripts/lint-regression-test-names.cjs --update` regenerates the
30
+ * allowlist from the files currently in tests/ and reports what changed.
31
+ * Use it when the failure is INHERITED drift, not your own new file — e.g.
32
+ * the base branch merged bug-* files without feeding the allowlist (the
33
+ * #947/#948/#950 race after the ratchet landed), or after a rebase. The
34
+ * allowlist is a snapshot artifact: regenerate it AFTER rebasing, never
35
+ * carry a pre-rebase copy through.
36
+ *
37
+ * See docs/TESTING-SUITES.md ("Regression tests") for the placement policy.
38
+ */
39
+
40
+ const fs = require('fs');
41
+ const path = require('path');
42
+ const { assertWithinAllowlist } = require('./lib/allowlist-ratchet.cjs');
43
+ const { ExitError, runMain } = require('./lib/cli-exit.cjs');
44
+
45
+ const ROOT = path.join(__dirname, '..');
46
+ // Env overrides exist for the lint's own tests only (sandbox fixture dirs).
47
+ const TESTS_DIR = process.env.GSD_LINT_REGRESSION_TESTS_DIR || path.join(ROOT, 'tests');
48
+ const ALLOWLIST_PATH =
49
+ process.env.GSD_LINT_REGRESSION_ALLOWLIST ||
50
+ path.join(__dirname, 'lint-regression-test-names.allowlist.json');
51
+
52
+ const BUG_FILE_RE = /^bug-\d+.*\.test\.cjs$/;
53
+
54
+ function main() {
55
+ const args = process.argv.slice(2);
56
+ const update = args.includes('--update');
57
+ const unknown = args.filter(a => a !== '--update');
58
+ if (unknown.length > 0) {
59
+ throw new ExitError(2, `lint-regression-test-names: unknown argument(s): ${unknown.join(', ')}`);
60
+ }
61
+
62
+ const current = fs
63
+ .readdirSync(TESTS_DIR)
64
+ .filter(f => BUG_FILE_RE.test(f))
65
+ .sort();
66
+ const known = JSON.parse(fs.readFileSync(ALLOWLIST_PATH, 'utf8'));
67
+
68
+ if (update) {
69
+ const knownSet = new Set(known);
70
+ const currentSet = new Set(current);
71
+ const added = current.filter(f => !knownSet.has(f));
72
+ const pruned = known.filter(f => !currentSet.has(f));
73
+ if (added.length === 0 && pruned.length === 0) {
74
+ console.log(`lint-regression-test-names --update: allowlist already in sync (${current.length} entries)`);
75
+ return;
76
+ }
77
+ fs.writeFileSync(ALLOWLIST_PATH, JSON.stringify(current, null, 2) + '\n');
78
+ console.log(
79
+ `lint-regression-test-names --update: ${known.length} -> ${current.length} entries` +
80
+ (added.length ? ` | grandfathered: ${added.join(', ')}` : '') +
81
+ (pruned.length ? ` | pruned: ${pruned.join(', ')}` : '')
82
+ );
83
+ console.log('Commit the regenerated allowlist with your change.');
84
+ return;
85
+ }
86
+
87
+ const failures = [];
88
+ const { novel } = assertWithinAllowlist({
89
+ label: 'regression-test-names',
90
+ current,
91
+ known,
92
+ fail: msg => failures.push(msg),
93
+ pruneHint: 'edit scripts/lint-regression-test-names.allowlist.json',
94
+ });
95
+
96
+ if (failures.length > 0) {
97
+ for (const msg of failures) console.error(msg);
98
+ if (novel.length > 0) {
99
+ console.error(
100
+ '\nIf this PR added the file(s) above: new bug-NNNN test files are not ' +
101
+ "accepted — add the regression case to the owning module's test file " +
102
+ "(e.g. a describe('regressions') block in tests/<module>.test.cjs) instead.\n" +
103
+ 'If the file(s) came from the base branch (inherited allowlist drift, ' +
104
+ 'e.g. after a rebase): run ' +
105
+ '`node scripts/lint-regression-test-names.cjs --update` and commit the ' +
106
+ 'regenerated allowlist. See docs/TESTING-SUITES.md.'
107
+ );
108
+ }
109
+ throw new ExitError(1);
110
+ }
111
+
112
+ console.log(
113
+ `ok lint-regression-test-names: ${current.length} grandfathered bug-* file(s), no novel offenders`
114
+ );
115
+ }
116
+
117
+ runMain(main);
@@ -1,8 +1,9 @@
1
1
  {
2
- "_doc": "Baseline of modules currently exceeding the 2-test-file limit. Each entry locks in TODAY's exact test filenames as the allowlisted set (identity ratchet). Adding a NEW test file to a capped module fails (novel). Removing one requires pruning this list (stale, ratchet-down). When a cluster drops to ≤ 2, remove its entry entirely. New entries require justification in PR description.",
2
+ "_doc": "Baseline of modules currently exceeding the 2-test-file limit. Each entry locks in TODAY's exact test filenames as the allowlisted set (identity ratchet). Adding a NEW test file to a capped module fails (novel). Removing one requires pruning this list (stale, ratchet-down). When a cluster drops to \u2264 2, remove its entry entirely. New entries require justification in PR description.",
3
3
  "modules": {
4
4
  "audit": {
5
5
  "files": [
6
+ "audit-command-cutover.test.cjs",
6
7
  "audit-fix-command.test.cjs",
7
8
  "bug-2659-audit-open-crash.test.cjs",
8
9
  "bug-2836-audit-open-summary-uat-drift.test.cjs",
@@ -26,7 +27,9 @@
26
27
  "graphify": {
27
28
  "files": [
28
29
  "bug-622-graphify-optional-graph-html.test.cjs",
29
- "graphify-auto-update.test.cjs",
30
+ "bug-974-graphify-budget-missing-value.test.cjs",
31
+ "graphify-auto-update.slow.test.cjs",
32
+ "graphify-command-cutover.test.cjs",
30
33
  "graphify-query.test.cjs",
31
34
  "graphify-visualization.test.cjs",
32
35
  "graphify.test.cjs"
@@ -37,6 +40,7 @@
37
40
  "files": [
38
41
  "bug-2351-intel-kilo-layout.test.cjs",
39
42
  "bug-3290-intel-updater-layout-block.test.cjs",
43
+ "intel-command-cutover.test.cjs",
40
44
  "intel.test.cjs"
41
45
  ],
42
46
  "issue": "TBD"
@@ -44,6 +48,7 @@
44
48
  "milestone": {
45
49
  "files": [
46
50
  "bug-730-milestone-phase-details-scope.test.cjs",
51
+ "bug-978-milestone-complete-force.test.cjs",
47
52
  "milestone-archive.test.cjs",
48
53
  "milestone-helper.test.cjs",
49
54
  "milestone-prefixed-convention.test.cjs",
@@ -82,8 +87,8 @@
82
87
  },
83
88
  "security": {
84
89
  "files": [
85
- "security-prompt-injection.test.cjs",
86
- "security-scan.test.cjs",
90
+ "security-prompt-injection.security.test.cjs",
91
+ "security-scan.security.test.cjs",
87
92
  "security.test.cjs"
88
93
  ],
89
94
  "issue": "TBD"
@@ -98,6 +103,7 @@
98
103
  "bug-3454-state-dollar-backreference-growth.test.cjs",
99
104
  "bug-397-state-preserve-executor-authored.test.cjs",
100
105
  "bug-905-state-syncstatefrontmatter-preserve-scalars.test.cjs",
106
+ "bug-948-state-noop-write-guard.test.cjs",
101
107
  "state-acquirestatelock-non-eexist.test.cjs",
102
108
  "state-prune.test.cjs",
103
109
  "state.test.cjs"
@@ -110,6 +116,7 @@
110
116
  "bug-2994-verify-reapply-patches-installed-path.test.cjs",
111
117
  "bug-3381-verify-work-workstream.test.cjs",
112
118
  "bug-3657-verify-reapply-patches-pristine-drift.test.cjs",
119
+ "bug-967-verify-key-links-strict-paths.test.cjs",
113
120
  "verify-health.test.cjs",
114
121
  "verify-mvp-uat.test.cjs",
115
122
  "verify-npm-publish.test.cjs",
@@ -124,6 +131,7 @@
124
131
  "bug-410-install-defaults-test-mode-guard.test.cjs",
125
132
  "enh-776-install-gemini-hook-events.test.cjs",
126
133
  "install-minimal-hooks.test.cjs",
134
+ "install-nested-layout.test.cjs",
127
135
  "install-path-detection.test.cjs",
128
136
  "install-regressions.test.cjs",
129
137
  "install-runtime-artifacts.test.cjs",
@@ -69,15 +69,15 @@ ALLOWLIST=(
69
69
  'scripts/prompt-injection-scan.sh'
70
70
  'scripts/base64-scan.sh'
71
71
  'scripts/secret-scan.sh'
72
- 'tests/security-scan.test.cjs'
72
+ 'tests/security-scan.security.test.cjs'
73
73
  'tests/security.test.cjs'
74
- 'tests/prompt-injection-scan.test.cjs'
74
+ 'tests/prompt-injection-scan.security.test.cjs'
75
75
  'tests/verify.test.cjs'
76
76
  'gsd-core/bin/lib/security.cjs'
77
77
  'hooks/gsd-prompt-guard.js'
78
78
  'hooks/gsd-read-injection-scanner.js'
79
- 'tests/read-injection-scanner.test.cjs'
80
- 'tests/security-prompt-injection.test.cjs'
79
+ 'tests/read-injection-scanner.security.test.cjs'
80
+ 'tests/security-prompt-injection.security.test.cjs'
81
81
  'tests/fixtures/adversarial/security/'
82
82
  'SECURITY.md'
83
83
  # These files contain intentional injection examples / security-model prose
@@ -20,7 +20,7 @@
20
20
  // See docs/TESTING-SUITES.md for full grouping policy.
21
21
  'use strict';
22
22
 
23
- const { readdirSync, existsSync } = require('fs');
23
+ const { readdirSync } = require('fs');
24
24
  const { join } = require('path');
25
25
  const { execFileSync } = require('child_process');
26
26
  const { ExitError, runMain } = require('./lib/cli-exit.cjs');
@@ -31,21 +31,84 @@ const SUITES = ['all', 'unit', 'integration', 'install', 'security', 'slow'];
31
31
  // src/*.cts and gitignored, so on a clean checkout (fresh CI, before any build)
32
32
  // the artifact is absent — yet test files require it. This is the universal
33
33
  // chokepoint every test path funnels through (test:unit, --files-from, direct
34
- // invocation), so build the artifact here if missing. It is a no-op once built
35
- // (dev, pretest, a prior run in the same job), which keeps the harness test's
36
- // spawned invocations side-effect-free. Paths resolve from __dirname (not cwd),
37
- // so it works regardless of GSD_TEST_DIR / temp-dir cwd. NOTE: the sentinel is
38
- // the pilot module; revisit (or switch to an unconditional quiet build) as more
39
- // modules migrate into src/.
40
- function ensureBuiltArtifacts() {
41
- const root = join(__dirname, '..');
42
- const sentinel = join(root, 'gsd-core', 'bin', 'lib', 'semver-compare.cjs');
43
- if (existsSync(sentinel)) return;
34
+ // invocation), so build the artifact here.
35
+ //
36
+ // Strategy (incremental + re-emit-on-missing, closes both #969 failure modes):
37
+ // 1. Run tsc incrementally (fast ~380ms no-op when sources unchanged).
38
+ // 2. Verify every src/*.cts (non-.d.cts) maps to a non-empty gsd-core/bin/lib/*.cjs.
39
+ // 3. If any expected .cjs is missing or zero-bytes (persistent-mirror scenario:
40
+ // tsc no-ops because tsbuildinfo looks current even though the file was deleted),
41
+ // delete the tsbuildinfo and run tsc ONCE MORE (clean re-emit), then re-verify.
42
+ //
43
+ // Common case: fast incremental no-op. Stale/deleted-output case: detected by
44
+ // the cheap existsSync loop and force-rebuilt. Paths resolve from __dirname so
45
+ // it works regardless of GSD_TEST_DIR / temp-dir cwd.
46
+ function ensureBuiltArtifacts(overrides = {}) {
47
+ const { existsSync, readdirSync, statSync, unlinkSync } = require('fs');
48
+ const root = overrides.root || join(__dirname, '..');
49
+ const srcDir = overrides.srcDir || join(root, 'src');
50
+ const outDir = overrides.outDir || join(root, 'gsd-core', 'bin', 'lib');
51
+ const tsBuildInfoPath = overrides.tsBuildInfoPath || join(root, 'tsconfig.build.tsbuildinfo');
52
+ const tsconfigPath = overrides.tsconfigPath || join(root, 'tsconfig.build.json');
44
53
  const tscBin = require.resolve('typescript/bin/tsc');
45
- execFileSync(process.execPath, [tscBin, '-p', join(root, 'tsconfig.build.json')], {
46
- cwd: root,
47
- stdio: 'inherit',
48
- });
54
+ const tscArgs = [tscBin, '-p', tsconfigPath];
55
+
56
+ // Build the 1:1 map of expected output paths from src/*.cts sources.
57
+ // Excludes *.d.cts (declaration-only files that produce no output).
58
+ // Handles subdirectories (e.g. src/installer-migrations/*.cts → gsd-core/bin/lib/installer-migrations/*.cjs).
59
+ function gatherExpectedOutputs() {
60
+ const expected = [];
61
+ function scan(dir, relBase) {
62
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
63
+ if (entry.isDirectory()) {
64
+ scan(join(dir, entry.name), relBase ? `${relBase}/${entry.name}` : entry.name);
65
+ } else if (entry.name.endsWith('.cts') && !entry.name.endsWith('.d.cts')) {
66
+ const stem = entry.name.slice(0, -'.cts'.length);
67
+ const rel = relBase ? `${relBase}/${stem}.cjs` : `${stem}.cjs`;
68
+ expected.push(join(outDir, rel));
69
+ }
70
+ }
71
+ }
72
+ scan(srcDir, '');
73
+ return expected;
74
+ }
75
+
76
+ function checkMissingOutputs(expectedPaths) {
77
+ return expectedPaths.filter(p => !existsSync(p) || statSync(p).size === 0);
78
+ }
79
+
80
+ // #996 placed the tsbuildinfo inside gsd-core/bin/ (a copied/shipped tree), which
81
+ // raced install-test copies. It now lives at the repo root. Best-effort purge any
82
+ // stale bin-local copy so persistent workspaces/mirrors self-heal (no-op on a temp
83
+ // override root or a clean checkout).
84
+ const legacyTsBuildInfo = join(root, 'gsd-core', 'bin', 'tsconfig.build.tsbuildinfo');
85
+ try { if (existsSync(legacyTsBuildInfo)) unlinkSync(legacyTsBuildInfo); } catch { /* best-effort */ }
86
+
87
+ // Step 1: incremental build (fast no-op when sources unchanged).
88
+ execFileSync(process.execPath, tscArgs, { cwd: root, stdio: 'inherit' });
89
+
90
+ // Step 2: verify expected outputs.
91
+ const expected = gatherExpectedOutputs();
92
+ const missing = checkMissingOutputs(expected);
93
+
94
+ // Step 3: if any output is missing/zero-bytes, force a clean re-emit.
95
+ // This handles the persistent-mirror case where tsc's incremental no-op left
96
+ // a deleted .cjs unregenerated (tsbuildinfo recorded it as up-to-date).
97
+ if (missing.length > 0) {
98
+ if (existsSync(tsBuildInfoPath)) {
99
+ unlinkSync(tsBuildInfoPath);
100
+ }
101
+ execFileSync(process.execPath, tscArgs, { cwd: root, stdio: 'inherit' });
102
+ // Re-verify after clean re-emit; surface any remaining gaps loudly.
103
+ const stillMissing = checkMissingOutputs(expected);
104
+ if (stillMissing.length > 0) {
105
+ const names = stillMissing.map(p => require('path').basename(p)).join(', ');
106
+ throw new Error(
107
+ `ensureBuiltArtifacts: tsc clean re-emit still missing outputs: ${names}. ` +
108
+ `Check src/ for compilation errors.`
109
+ );
110
+ }
111
+ }
49
112
  }
50
113
  const MARKED_SUITES = ['integration', 'install', 'security', 'slow'];
51
114
 
@@ -320,4 +383,4 @@ if (require.main === module) {
320
383
  runMain(main);
321
384
  }
322
385
 
323
- module.exports = { suiteOf };
386
+ module.exports = { suiteOf, ensureBuiltArtifacts };
@@ -218,9 +218,9 @@ should_skip_file() {
218
218
  # Skip the scan scripts themselves and test files
219
219
  case "$file" in
220
220
  */secret-scan.sh) return 0 ;;
221
- */secret-scan-lint.test.cjs) return 0 ;;
222
- */security-scan.test.cjs) return 0 ;;
223
- */security-prompt-injection.test.cjs) return 0 ;;
221
+ */secret-scan-lint.security.test.cjs) return 0 ;;
222
+ */security-scan.security.test.cjs) return 0 ;;
223
+ */security-prompt-injection.security.test.cjs) return 0 ;;
224
224
  tests/fixtures/adversarial/security/*|*/tests/fixtures/adversarial/security/*) return 0 ;;
225
225
  esac
226
226
  return 1