@therocketcode/gsd-core 1.4.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 (568) hide show
  1. package/.claude-plugin/plugin.json +23 -0
  2. package/GEMINI.md +53 -0
  3. package/LICENSE +21 -0
  4. package/README.ja-JP.md +125 -0
  5. package/README.ko-KR.md +125 -0
  6. package/README.md +144 -0
  7. package/README.pt-BR.md +125 -0
  8. package/README.zh-CN.md +125 -0
  9. package/agents/gsd-advisor-researcher.md +108 -0
  10. package/agents/gsd-ai-researcher.md +114 -0
  11. package/agents/gsd-assumptions-analyzer.md +105 -0
  12. package/agents/gsd-code-fixer.md +668 -0
  13. package/agents/gsd-code-reviewer.md +387 -0
  14. package/agents/gsd-codebase-mapper.md +853 -0
  15. package/agents/gsd-debug-session-manager.md +314 -0
  16. package/agents/gsd-debugger.md +1452 -0
  17. package/agents/gsd-doc-classifier.md +168 -0
  18. package/agents/gsd-doc-synthesizer.md +204 -0
  19. package/agents/gsd-doc-verifier.md +217 -0
  20. package/agents/gsd-doc-writer.md +616 -0
  21. package/agents/gsd-domain-researcher.md +147 -0
  22. package/agents/gsd-eval-auditor.md +191 -0
  23. package/agents/gsd-eval-planner.md +154 -0
  24. package/agents/gsd-executor.md +785 -0
  25. package/agents/gsd-framework-selector.md +160 -0
  26. package/agents/gsd-integration-checker.md +470 -0
  27. package/agents/gsd-intel-updater.md +342 -0
  28. package/agents/gsd-nyquist-auditor.md +203 -0
  29. package/agents/gsd-pattern-mapper.md +335 -0
  30. package/agents/gsd-phase-researcher.md +867 -0
  31. package/agents/gsd-plan-checker.md +978 -0
  32. package/agents/gsd-planner.md +1204 -0
  33. package/agents/gsd-project-researcher.md +611 -0
  34. package/agents/gsd-research-synthesizer.md +259 -0
  35. package/agents/gsd-roadmapper.md +688 -0
  36. package/agents/gsd-security-auditor.md +155 -0
  37. package/agents/gsd-ui-auditor.md +495 -0
  38. package/agents/gsd-ui-checker.md +309 -0
  39. package/agents/gsd-ui-researcher.md +374 -0
  40. package/agents/gsd-user-profiler.md +171 -0
  41. package/agents/gsd-verifier.md +923 -0
  42. package/assets/gsd-logo-2000-transparent.png +0 -0
  43. package/assets/gsd-logo-2000-transparent.svg +17 -0
  44. package/assets/gsd-logo-2000.png +0 -0
  45. package/assets/gsd-logo-2000.svg +21 -0
  46. package/assets/terminal.svg +68 -0
  47. package/bin/install.js +12726 -0
  48. package/bin/lib/ui-safety-gate.cjs +107 -0
  49. package/commands/gsd/add-tests.md +42 -0
  50. package/commands/gsd/ai-integration-phase.md +37 -0
  51. package/commands/gsd/audit-fix.md +34 -0
  52. package/commands/gsd/audit-milestone.md +37 -0
  53. package/commands/gsd/audit-uat.md +24 -0
  54. package/commands/gsd/autonomous.md +48 -0
  55. package/commands/gsd/capture.md +62 -0
  56. package/commands/gsd/cleanup.md +24 -0
  57. package/commands/gsd/code-review.md +59 -0
  58. package/commands/gsd/complete-milestone.md +143 -0
  59. package/commands/gsd/config.md +56 -0
  60. package/commands/gsd/debug.md +52 -0
  61. package/commands/gsd/discover-product.md +65 -0
  62. package/commands/gsd/discuss-phase.md +77 -0
  63. package/commands/gsd/docs-update.md +49 -0
  64. package/commands/gsd/eval-review.md +33 -0
  65. package/commands/gsd/execute-phase.md +66 -0
  66. package/commands/gsd/explore.md +27 -0
  67. package/commands/gsd/extract-learnings.md +23 -0
  68. package/commands/gsd/fast.md +31 -0
  69. package/commands/gsd/forensics.md +57 -0
  70. package/commands/gsd/graphify.md +204 -0
  71. package/commands/gsd/health.md +31 -0
  72. package/commands/gsd/help.md +28 -0
  73. package/commands/gsd/import.md +45 -0
  74. package/commands/gsd/inbox.md +39 -0
  75. package/commands/gsd/ingest-docs.md +42 -0
  76. package/commands/gsd/manager.md +45 -0
  77. package/commands/gsd/map-codebase.md +83 -0
  78. package/commands/gsd/milestone-summary.md +51 -0
  79. package/commands/gsd/model-domain.md +65 -0
  80. package/commands/gsd/mvp-phase.md +45 -0
  81. package/commands/gsd/new-milestone.md +45 -0
  82. package/commands/gsd/new-project.md +47 -0
  83. package/commands/gsd/ns-context.md +23 -0
  84. package/commands/gsd/ns-ideate.md +24 -0
  85. package/commands/gsd/ns-manage.md +29 -0
  86. package/commands/gsd/ns-project.md +22 -0
  87. package/commands/gsd/ns-review.md +26 -0
  88. package/commands/gsd/ns-workflow.md +28 -0
  89. package/commands/gsd/pause-work.md +43 -0
  90. package/commands/gsd/phase.md +56 -0
  91. package/commands/gsd/plan-phase.md +64 -0
  92. package/commands/gsd/plan-review-convergence.md +59 -0
  93. package/commands/gsd/pr-branch.md +26 -0
  94. package/commands/gsd/profile-user.md +46 -0
  95. package/commands/gsd/progress.md +48 -0
  96. package/commands/gsd/quick.md +174 -0
  97. package/commands/gsd/recommend-architecture.md +64 -0
  98. package/commands/gsd/resume-work.md +30 -0
  99. package/commands/gsd/review-backlog.md +63 -0
  100. package/commands/gsd/review.md +42 -0
  101. package/commands/gsd/secure-phase.md +36 -0
  102. package/commands/gsd/settings.md +29 -0
  103. package/commands/gsd/ship.md +24 -0
  104. package/commands/gsd/sketch.md +60 -0
  105. package/commands/gsd/spec-phase.md +63 -0
  106. package/commands/gsd/spike.md +57 -0
  107. package/commands/gsd/stats.md +20 -0
  108. package/commands/gsd/surface.md +155 -0
  109. package/commands/gsd/testing-strategy.md +65 -0
  110. package/commands/gsd/thread.md +24 -0
  111. package/commands/gsd/ui-phase.md +35 -0
  112. package/commands/gsd/ui-review.md +33 -0
  113. package/commands/gsd/ultraplan-phase.md +34 -0
  114. package/commands/gsd/undo.md +35 -0
  115. package/commands/gsd/update.md +49 -0
  116. package/commands/gsd/validate-phase.md +36 -0
  117. package/commands/gsd/verify-work.md +39 -0
  118. package/commands/gsd/workspace.md +52 -0
  119. package/commands/gsd/workstreams.md +70 -0
  120. package/gemini-extension.json +6 -0
  121. package/gsd-core/bin/check-latest-version.cjs +161 -0
  122. package/gsd-core/bin/gsd-tools.cjs +1928 -0
  123. package/gsd-core/bin/lib/active-workstream-store.cjs +291 -0
  124. package/gsd-core/bin/lib/adr-parser.cjs +399 -0
  125. package/gsd-core/bin/lib/agent-command-router.cjs +68 -0
  126. package/gsd-core/bin/lib/artifacts.cjs +51 -0
  127. package/gsd-core/bin/lib/audit.cjs +743 -0
  128. package/gsd-core/bin/lib/check-command-router.cjs +343 -0
  129. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +81 -0
  130. package/gsd-core/bin/lib/cli-exit.cjs +42 -0
  131. package/gsd-core/bin/lib/clock.cjs +95 -0
  132. package/gsd-core/bin/lib/clusters.cjs +132 -0
  133. package/gsd-core/bin/lib/code-review-flags.cjs +59 -0
  134. package/gsd-core/bin/lib/command-aliases.cjs +809 -0
  135. package/gsd-core/bin/lib/command-arg-projection.cjs +55 -0
  136. package/gsd-core/bin/lib/command-routing-hub.cjs +300 -0
  137. package/gsd-core/bin/lib/commands.cjs +1203 -0
  138. package/gsd-core/bin/lib/config-schema.cjs +29 -0
  139. package/gsd-core/bin/lib/config-types.cjs +19 -0
  140. package/gsd-core/bin/lib/config.cjs +738 -0
  141. package/gsd-core/bin/lib/configuration.cjs +239 -0
  142. package/gsd-core/bin/lib/context-utilization.cjs +48 -0
  143. package/gsd-core/bin/lib/core.cjs +2051 -0
  144. package/gsd-core/bin/lib/decisions.cjs +118 -0
  145. package/gsd-core/bin/lib/docs.cjs +252 -0
  146. package/gsd-core/bin/lib/drift.cjs +364 -0
  147. package/gsd-core/bin/lib/fallow-runner.cjs +115 -0
  148. package/gsd-core/bin/lib/frontmatter.cjs +442 -0
  149. package/gsd-core/bin/lib/gap-checker.cjs +257 -0
  150. package/gsd-core/bin/lib/graphify.cjs +496 -0
  151. package/gsd-core/bin/lib/gsd2-import.cjs +456 -0
  152. package/gsd-core/bin/lib/init-command-router.cjs +62 -0
  153. package/gsd-core/bin/lib/init.cjs +1815 -0
  154. package/gsd-core/bin/lib/install-profiles.cjs +584 -0
  155. package/gsd-core/bin/lib/installer-migration-authoring.cjs +122 -0
  156. package/gsd-core/bin/lib/installer-migration-report.cjs +350 -0
  157. package/gsd-core/bin/lib/installer-migrations/000-first-time-baseline.cjs +218 -0
  158. package/gsd-core/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +48 -0
  159. package/gsd-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +94 -0
  160. package/gsd-core/bin/lib/installer-migrations/003-rename-get-shit-done-to-gsd-core.cjs +108 -0
  161. package/gsd-core/bin/lib/installer-migrations.cjs +823 -0
  162. package/gsd-core/bin/lib/intel.cjs +590 -0
  163. package/gsd-core/bin/lib/learnings.cjs +270 -0
  164. package/gsd-core/bin/lib/legacy-cleanup.cjs +253 -0
  165. package/gsd-core/bin/lib/milestone.cjs +373 -0
  166. package/gsd-core/bin/lib/model-catalog.cjs +154 -0
  167. package/gsd-core/bin/lib/model-profiles.cjs +24 -0
  168. package/gsd-core/bin/lib/observability/event.cjs +51 -0
  169. package/gsd-core/bin/lib/observability/logger.cjs +146 -0
  170. package/gsd-core/bin/lib/observability/redaction.cjs +48 -0
  171. package/gsd-core/bin/lib/package-identity.cjs +35 -0
  172. package/gsd-core/bin/lib/package-legitimacy.cjs +368 -0
  173. package/gsd-core/bin/lib/phase-command-router.cjs +189 -0
  174. package/gsd-core/bin/lib/phase-lifecycle.cjs +74 -0
  175. package/gsd-core/bin/lib/phase.cjs +1307 -0
  176. package/gsd-core/bin/lib/phases-command-router.cjs +43 -0
  177. package/gsd-core/bin/lib/plan-scan.cjs +91 -0
  178. package/gsd-core/bin/lib/planning-workspace.cjs +245 -0
  179. package/gsd-core/bin/lib/profile-output.cjs +1120 -0
  180. package/gsd-core/bin/lib/profile-pipeline.cjs +517 -0
  181. package/gsd-core/bin/lib/project-root.cjs +119 -0
  182. package/gsd-core/bin/lib/prompt-budget.cjs +305 -0
  183. package/gsd-core/bin/lib/research-provider.cjs +137 -0
  184. package/gsd-core/bin/lib/research-store.cjs +167 -0
  185. package/gsd-core/bin/lib/review-reviewer-selection.cjs +121 -0
  186. package/gsd-core/bin/lib/roadmap-command-router.cjs +166 -0
  187. package/gsd-core/bin/lib/roadmap-upgrade.cjs +476 -0
  188. package/gsd-core/bin/lib/roadmap.cjs +600 -0
  189. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +312 -0
  190. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +56 -0
  191. package/gsd-core/bin/lib/runtime-homes.cjs +190 -0
  192. package/gsd-core/bin/lib/runtime-name-policy.cjs +96 -0
  193. package/gsd-core/bin/lib/runtime-slash.cjs +119 -0
  194. package/gsd-core/bin/lib/schema-detect.cjs +159 -0
  195. package/gsd-core/bin/lib/secrets.cjs +34 -0
  196. package/gsd-core/bin/lib/security.cjs +480 -0
  197. package/gsd-core/bin/lib/semver-compare.cjs +42 -0
  198. package/gsd-core/bin/lib/shell-command-projection.cjs +533 -0
  199. package/gsd-core/bin/lib/state-command-router.cjs +160 -0
  200. package/gsd-core/bin/lib/state-document.cjs +259 -0
  201. package/gsd-core/bin/lib/state.cjs +2010 -0
  202. package/gsd-core/bin/lib/surface.cjs +449 -0
  203. package/gsd-core/bin/lib/task-command-router.cjs +85 -0
  204. package/gsd-core/bin/lib/template.cjs +237 -0
  205. package/gsd-core/bin/lib/uat.cjs +297 -0
  206. package/gsd-core/bin/lib/ui-safety-gate.cjs +98 -0
  207. package/gsd-core/bin/lib/update-context.cjs +218 -0
  208. package/gsd-core/bin/lib/validate-command-router.cjs +91 -0
  209. package/gsd-core/bin/lib/validate.cjs +112 -0
  210. package/gsd-core/bin/lib/verification-command-router.cjs +31 -0
  211. package/gsd-core/bin/lib/verification.cjs +193 -0
  212. package/gsd-core/bin/lib/verify-command-router.cjs +44 -0
  213. package/gsd-core/bin/lib/verify.cjs +1451 -0
  214. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +81 -0
  215. package/gsd-core/bin/lib/workstream-inventory.cjs +147 -0
  216. package/gsd-core/bin/lib/workstream-name-policy.cjs +91 -0
  217. package/gsd-core/bin/lib/workstream.cjs +380 -0
  218. package/gsd-core/bin/lib/worktree-base-ref.cjs +325 -0
  219. package/gsd-core/bin/lib/worktree-safety.cjs +943 -0
  220. package/gsd-core/bin/shared/config-defaults.manifest.json +98 -0
  221. package/gsd-core/bin/shared/config-schema.manifest.json +192 -0
  222. package/gsd-core/bin/shared/model-catalog.json +149 -0
  223. package/gsd-core/bin/shared/runtime-aliases.manifest.json +75 -0
  224. package/gsd-core/bin/verify-reapply-patches.cjs +349 -0
  225. package/gsd-core/contexts/dev.md +21 -0
  226. package/gsd-core/contexts/research.md +22 -0
  227. package/gsd-core/contexts/review.md +23 -0
  228. package/gsd-core/references/agent-contracts.md +79 -0
  229. package/gsd-core/references/ai-evals.md +156 -0
  230. package/gsd-core/references/ai-frameworks.md +186 -0
  231. package/gsd-core/references/architecture-decision.md +74 -0
  232. package/gsd-core/references/artifact-types.md +131 -0
  233. package/gsd-core/references/auth-in-tests.md +91 -0
  234. package/gsd-core/references/autonomous-smart-discuss.md +277 -0
  235. package/gsd-core/references/checkpoints.md +814 -0
  236. package/gsd-core/references/common-bug-patterns.md +114 -0
  237. package/gsd-core/references/context-budget.md +85 -0
  238. package/gsd-core/references/continuation-format.md +253 -0
  239. package/gsd-core/references/db-test-isolation.md +54 -0
  240. package/gsd-core/references/debugger-philosophy.md +76 -0
  241. package/gsd-core/references/decimal-phase-calculation.md +64 -0
  242. package/gsd-core/references/doc-conflict-engine.md +91 -0
  243. package/gsd-core/references/domain-modeling.md +80 -0
  244. package/gsd-core/references/domain-probes.md +125 -0
  245. package/gsd-core/references/e2e-tiering.md +35 -0
  246. package/gsd-core/references/execute-mvp-tdd.md +81 -0
  247. package/gsd-core/references/executor-examples.md +110 -0
  248. package/gsd-core/references/few-shot-examples/plan-checker.md +73 -0
  249. package/gsd-core/references/few-shot-examples/verifier.md +109 -0
  250. package/gsd-core/references/flaky-test-checklist.md +22 -0
  251. package/gsd-core/references/gate-prompts.md +100 -0
  252. package/gsd-core/references/gates.md +70 -0
  253. package/gsd-core/references/git-integration.md +298 -0
  254. package/gsd-core/references/git-planning-commit.md +40 -0
  255. package/gsd-core/references/ios-scaffold.md +123 -0
  256. package/gsd-core/references/mandatory-initial-read.md +2 -0
  257. package/gsd-core/references/model-profile-resolution.md +38 -0
  258. package/gsd-core/references/model-profiles.md +245 -0
  259. package/gsd-core/references/mvp-concepts.md +49 -0
  260. package/gsd-core/references/phase-argument-parsing.md +61 -0
  261. package/gsd-core/references/planner-antipatterns.md +89 -0
  262. package/gsd-core/references/planner-chunked.md +49 -0
  263. package/gsd-core/references/planner-gap-closure.md +62 -0
  264. package/gsd-core/references/planner-graphify-auto-update.md +67 -0
  265. package/gsd-core/references/planner-human-verify-mode.md +57 -0
  266. package/gsd-core/references/planner-interface-context.md +62 -0
  267. package/gsd-core/references/planner-load-graph-context.md +36 -0
  268. package/gsd-core/references/planner-mvp-mode.md +53 -0
  269. package/gsd-core/references/planner-reviews.md +39 -0
  270. package/gsd-core/references/planner-revision.md +87 -0
  271. package/gsd-core/references/planner-source-audit.md +73 -0
  272. package/gsd-core/references/planning-config.md +473 -0
  273. package/gsd-core/references/product-discovery.md +49 -0
  274. package/gsd-core/references/project-skills-discovery.md +19 -0
  275. package/gsd-core/references/questioning.md +162 -0
  276. package/gsd-core/references/realistic-test-data.md +44 -0
  277. package/gsd-core/references/research-documentation-lookup.md +29 -0
  278. package/gsd-core/references/research-philosophy.md +29 -0
  279. package/gsd-core/references/research-verification-protocol.md +27 -0
  280. package/gsd-core/references/revision-loop.md +97 -0
  281. package/gsd-core/references/scout-codebase.md +51 -0
  282. package/gsd-core/references/skeleton-template.md +48 -0
  283. package/gsd-core/references/sketch-interactivity.md +41 -0
  284. package/gsd-core/references/sketch-theme-system.md +94 -0
  285. package/gsd-core/references/sketch-tooling.md +45 -0
  286. package/gsd-core/references/sketch-variant-patterns.md +81 -0
  287. package/gsd-core/references/spidr-splitting.md +69 -0
  288. package/gsd-core/references/tdd.md +330 -0
  289. package/gsd-core/references/test-containers.md +55 -0
  290. package/gsd-core/references/test-strategy.md +75 -0
  291. package/gsd-core/references/thinking-models-debug.md +44 -0
  292. package/gsd-core/references/thinking-models-execution.md +50 -0
  293. package/gsd-core/references/thinking-models-planning.md +62 -0
  294. package/gsd-core/references/thinking-models-research.md +50 -0
  295. package/gsd-core/references/thinking-models-verification.md +55 -0
  296. package/gsd-core/references/thinking-partner.md +96 -0
  297. package/gsd-core/references/ui-brand.md +162 -0
  298. package/gsd-core/references/universal-anti-patterns.md +63 -0
  299. package/gsd-core/references/user-profiling.md +681 -0
  300. package/gsd-core/references/user-story-template.md +58 -0
  301. package/gsd-core/references/verification-overrides.md +227 -0
  302. package/gsd-core/references/verification-patterns.md +612 -0
  303. package/gsd-core/references/verify-mvp-mode.md +85 -0
  304. package/gsd-core/references/workstream-flag.md +111 -0
  305. package/gsd-core/references/worktree-branch-check.md +38 -0
  306. package/gsd-core/references/worktree-path-safety.md +67 -0
  307. package/gsd-core/templates/AI-SPEC.md +246 -0
  308. package/gsd-core/templates/DEBUG.md +169 -0
  309. package/gsd-core/templates/README.md +77 -0
  310. package/gsd-core/templates/SECURITY.md +61 -0
  311. package/gsd-core/templates/UAT.md +265 -0
  312. package/gsd-core/templates/UI-SPEC.md +100 -0
  313. package/gsd-core/templates/VALIDATION.md +76 -0
  314. package/gsd-core/templates/adr.md +58 -0
  315. package/gsd-core/templates/claude-md.md +145 -0
  316. package/gsd-core/templates/codebase/architecture.md +255 -0
  317. package/gsd-core/templates/codebase/concerns.md +310 -0
  318. package/gsd-core/templates/codebase/conventions.md +307 -0
  319. package/gsd-core/templates/codebase/integrations.md +280 -0
  320. package/gsd-core/templates/codebase/stack.md +186 -0
  321. package/gsd-core/templates/codebase/structure.md +285 -0
  322. package/gsd-core/templates/codebase/testing.md +480 -0
  323. package/gsd-core/templates/config.json +62 -0
  324. package/gsd-core/templates/context.md +352 -0
  325. package/gsd-core/templates/continue-here.md +78 -0
  326. package/gsd-core/templates/copilot-instructions.md +7 -0
  327. package/gsd-core/templates/debug-subagent-prompt.md +91 -0
  328. package/gsd-core/templates/dev-preferences.md +21 -0
  329. package/gsd-core/templates/discovery.md +146 -0
  330. package/gsd-core/templates/discussion-log.md +63 -0
  331. package/gsd-core/templates/domain-model.md +54 -0
  332. package/gsd-core/templates/milestone-archive.md +123 -0
  333. package/gsd-core/templates/milestone.md +115 -0
  334. package/gsd-core/templates/phase-prompt.md +610 -0
  335. package/gsd-core/templates/planner-subagent-prompt.md +117 -0
  336. package/gsd-core/templates/product-brief.md +55 -0
  337. package/gsd-core/templates/project.md +186 -0
  338. package/gsd-core/templates/requirements.md +231 -0
  339. package/gsd-core/templates/research-project/ARCHITECTURE.md +204 -0
  340. package/gsd-core/templates/research-project/FEATURES.md +147 -0
  341. package/gsd-core/templates/research-project/PITFALLS.md +200 -0
  342. package/gsd-core/templates/research-project/STACK.md +120 -0
  343. package/gsd-core/templates/research-project/SUMMARY.md +170 -0
  344. package/gsd-core/templates/research.md +592 -0
  345. package/gsd-core/templates/retrospective.md +54 -0
  346. package/gsd-core/templates/roadmap.md +202 -0
  347. package/gsd-core/templates/spec.md +307 -0
  348. package/gsd-core/templates/state.md +195 -0
  349. package/gsd-core/templates/summary-complex.md +59 -0
  350. package/gsd-core/templates/summary-minimal.md +41 -0
  351. package/gsd-core/templates/summary-standard.md +48 -0
  352. package/gsd-core/templates/summary.md +248 -0
  353. package/gsd-core/templates/test-strategy.md +50 -0
  354. package/gsd-core/templates/user-profile.md +146 -0
  355. package/gsd-core/templates/user-setup.md +311 -0
  356. package/gsd-core/templates/verification-report.md +322 -0
  357. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -0
  358. package/gsd-core/workflows/add-backlog.md +91 -0
  359. package/gsd-core/workflows/add-phase.md +113 -0
  360. package/gsd-core/workflows/add-tests.md +355 -0
  361. package/gsd-core/workflows/add-todo.md +161 -0
  362. package/gsd-core/workflows/ai-integration-phase.md +295 -0
  363. package/gsd-core/workflows/analyze-dependencies.md +96 -0
  364. package/gsd-core/workflows/audit-fix.md +178 -0
  365. package/gsd-core/workflows/audit-milestone.md +360 -0
  366. package/gsd-core/workflows/audit-uat.md +110 -0
  367. package/gsd-core/workflows/autonomous.md +797 -0
  368. package/gsd-core/workflows/check-todos.md +180 -0
  369. package/gsd-core/workflows/cleanup.md +195 -0
  370. package/gsd-core/workflows/code-review-fix.md +502 -0
  371. package/gsd-core/workflows/code-review.md +658 -0
  372. package/gsd-core/workflows/complete-milestone.md +855 -0
  373. package/gsd-core/workflows/debug.md +237 -0
  374. package/gsd-core/workflows/diagnose-issues.md +245 -0
  375. package/gsd-core/workflows/discover-product.md +112 -0
  376. package/gsd-core/workflows/discovery-phase.md +291 -0
  377. package/gsd-core/workflows/discuss-phase/modes/advisor.md +176 -0
  378. package/gsd-core/workflows/discuss-phase/modes/all.md +28 -0
  379. package/gsd-core/workflows/discuss-phase/modes/analyze.md +44 -0
  380. package/gsd-core/workflows/discuss-phase/modes/auto.md +57 -0
  381. package/gsd-core/workflows/discuss-phase/modes/batch.md +52 -0
  382. package/gsd-core/workflows/discuss-phase/modes/chain.md +98 -0
  383. package/gsd-core/workflows/discuss-phase/modes/default.md +141 -0
  384. package/gsd-core/workflows/discuss-phase/modes/power.md +44 -0
  385. package/gsd-core/workflows/discuss-phase/modes/text.md +55 -0
  386. package/gsd-core/workflows/discuss-phase/templates/checkpoint.json +18 -0
  387. package/gsd-core/workflows/discuss-phase/templates/context.md +136 -0
  388. package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +50 -0
  389. package/gsd-core/workflows/discuss-phase-assumptions.md +675 -0
  390. package/gsd-core/workflows/discuss-phase-power.md +291 -0
  391. package/gsd-core/workflows/discuss-phase.md +499 -0
  392. package/gsd-core/workflows/do.md +111 -0
  393. package/gsd-core/workflows/docs-update.md +1176 -0
  394. package/gsd-core/workflows/edit-phase.md +295 -0
  395. package/gsd-core/workflows/eval-review.md +156 -0
  396. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +95 -0
  397. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
  398. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +117 -0
  399. package/gsd-core/workflows/execute-phase.md +1752 -0
  400. package/gsd-core/workflows/execute-plan.md +526 -0
  401. package/gsd-core/workflows/explore.md +146 -0
  402. package/gsd-core/workflows/extract-learnings.md +243 -0
  403. package/gsd-core/workflows/fast.md +124 -0
  404. package/gsd-core/workflows/forensics.md +279 -0
  405. package/gsd-core/workflows/graduation.md +196 -0
  406. package/gsd-core/workflows/health.md +224 -0
  407. package/gsd-core/workflows/help/modes/brief.md +22 -0
  408. package/gsd-core/workflows/help/modes/default.md +50 -0
  409. package/gsd-core/workflows/help/modes/full.md +789 -0
  410. package/gsd-core/workflows/help/modes/topic.md +74 -0
  411. package/gsd-core/workflows/help.md +24 -0
  412. package/gsd-core/workflows/import.md +256 -0
  413. package/gsd-core/workflows/inbox.md +387 -0
  414. package/gsd-core/workflows/ingest-docs.md +340 -0
  415. package/gsd-core/workflows/insert-phase.md +152 -0
  416. package/gsd-core/workflows/list-phase-assumptions.md +178 -0
  417. package/gsd-core/workflows/list-workspaces.md +57 -0
  418. package/gsd-core/workflows/manager.md +393 -0
  419. package/gsd-core/workflows/map-codebase.md +446 -0
  420. package/gsd-core/workflows/milestone-summary.md +224 -0
  421. package/gsd-core/workflows/model-domain.md +162 -0
  422. package/gsd-core/workflows/mvp-phase.md +222 -0
  423. package/gsd-core/workflows/new-milestone.md +635 -0
  424. package/gsd-core/workflows/new-project.md +1555 -0
  425. package/gsd-core/workflows/new-workspace.md +240 -0
  426. package/gsd-core/workflows/next.md +299 -0
  427. package/gsd-core/workflows/node-repair.md +92 -0
  428. package/gsd-core/workflows/note.md +158 -0
  429. package/gsd-core/workflows/pause-work.md +244 -0
  430. package/gsd-core/workflows/plan-milestone-gaps.md +281 -0
  431. package/gsd-core/workflows/plan-phase.md +1814 -0
  432. package/gsd-core/workflows/plan-review-convergence.md +346 -0
  433. package/gsd-core/workflows/plant-seed.md +230 -0
  434. package/gsd-core/workflows/pr-branch.md +157 -0
  435. package/gsd-core/workflows/profile-user.md +453 -0
  436. package/gsd-core/workflows/progress.md +699 -0
  437. package/gsd-core/workflows/quick.md +1017 -0
  438. package/gsd-core/workflows/reapply-patches.md +426 -0
  439. package/gsd-core/workflows/recommend-architecture.md +135 -0
  440. package/gsd-core/workflows/remove-phase.md +156 -0
  441. package/gsd-core/workflows/remove-workspace.md +108 -0
  442. package/gsd-core/workflows/resume-project.md +332 -0
  443. package/gsd-core/workflows/review.md +748 -0
  444. package/gsd-core/workflows/scan.md +107 -0
  445. package/gsd-core/workflows/secure-phase.md +182 -0
  446. package/gsd-core/workflows/session-report.md +146 -0
  447. package/gsd-core/workflows/settings-advanced.md +810 -0
  448. package/gsd-core/workflows/settings-integrations.md +312 -0
  449. package/gsd-core/workflows/settings.md +566 -0
  450. package/gsd-core/workflows/ship.md +405 -0
  451. package/gsd-core/workflows/sketch-wrap-up.md +286 -0
  452. package/gsd-core/workflows/sketch.md +361 -0
  453. package/gsd-core/workflows/spec-phase.md +263 -0
  454. package/gsd-core/workflows/spike-wrap-up.md +307 -0
  455. package/gsd-core/workflows/spike.md +453 -0
  456. package/gsd-core/workflows/stats.md +80 -0
  457. package/gsd-core/workflows/sync-skills.md +182 -0
  458. package/gsd-core/workflows/testing-strategy.md +122 -0
  459. package/gsd-core/workflows/thread.md +222 -0
  460. package/gsd-core/workflows/transition.md +694 -0
  461. package/gsd-core/workflows/ui-phase.md +328 -0
  462. package/gsd-core/workflows/ui-review.md +193 -0
  463. package/gsd-core/workflows/ultraplan-phase.md +199 -0
  464. package/gsd-core/workflows/undo.md +314 -0
  465. package/gsd-core/workflows/update.md +496 -0
  466. package/gsd-core/workflows/validate-phase.md +181 -0
  467. package/gsd-core/workflows/verify-phase.md +544 -0
  468. package/gsd-core/workflows/verify-work.md +781 -0
  469. package/hooks/dist/gsd-check-update-worker.js +108 -0
  470. package/hooks/dist/gsd-check-update.js +66 -0
  471. package/hooks/dist/gsd-config-reload.js +133 -0
  472. package/hooks/dist/gsd-context-monitor.js +195 -0
  473. package/hooks/dist/gsd-cursor-post-tool.js +75 -0
  474. package/hooks/dist/gsd-cursor-session-start.js +52 -0
  475. package/hooks/dist/gsd-graphify-update.sh +158 -0
  476. package/hooks/dist/gsd-phase-boundary.sh +47 -0
  477. package/hooks/dist/gsd-prompt-guard.js +97 -0
  478. package/hooks/dist/gsd-read-guard.js +101 -0
  479. package/hooks/dist/gsd-read-injection-scanner.js +203 -0
  480. package/hooks/dist/gsd-session-state.sh +59 -0
  481. package/hooks/dist/gsd-statusline.js +566 -0
  482. package/hooks/dist/gsd-update-banner.js +138 -0
  483. package/hooks/dist/gsd-validate-commit.sh +57 -0
  484. package/hooks/dist/gsd-workflow-guard.js +167 -0
  485. package/hooks/dist/gsd-worktree-path-guard.js +169 -0
  486. package/hooks/dist/lib/git-cmd.js +150 -0
  487. package/hooks/dist/lib/gsd-graphify-rebuild.sh +65 -0
  488. package/hooks/dist/managed-hooks-registry.cjs +38 -0
  489. package/hooks/gsd-check-update-worker.js +108 -0
  490. package/hooks/gsd-check-update.js +66 -0
  491. package/hooks/gsd-config-reload.js +133 -0
  492. package/hooks/gsd-context-monitor.js +195 -0
  493. package/hooks/gsd-cursor-post-tool.js +75 -0
  494. package/hooks/gsd-cursor-session-start.js +52 -0
  495. package/hooks/gsd-graphify-update.sh +158 -0
  496. package/hooks/gsd-phase-boundary.sh +47 -0
  497. package/hooks/gsd-prompt-guard.js +97 -0
  498. package/hooks/gsd-read-guard.js +101 -0
  499. package/hooks/gsd-read-injection-scanner.js +203 -0
  500. package/hooks/gsd-session-state.sh +59 -0
  501. package/hooks/gsd-statusline.js +566 -0
  502. package/hooks/gsd-update-banner.js +138 -0
  503. package/hooks/gsd-validate-commit.sh +57 -0
  504. package/hooks/gsd-workflow-guard.js +167 -0
  505. package/hooks/gsd-worktree-path-guard.js +169 -0
  506. package/hooks/hooks.json +69 -0
  507. package/hooks/lib/git-cmd.js +150 -0
  508. package/hooks/lib/gsd-graphify-rebuild.sh +65 -0
  509. package/hooks/managed-hooks-registry.cjs +38 -0
  510. package/package.json +115 -0
  511. package/scripts/affected-tests-lib.cjs +542 -0
  512. package/scripts/audit-workflow-script-paths.cjs +73 -0
  513. package/scripts/base64-scan.sh +351 -0
  514. package/scripts/build-hooks.js +247 -0
  515. package/scripts/changeset/README.md +129 -0
  516. package/scripts/changeset/cli.cjs +590 -0
  517. package/scripts/changeset/github-release-notes.cjs +199 -0
  518. package/scripts/changeset/lint.cjs +111 -0
  519. package/scripts/changeset/new.cjs +137 -0
  520. package/scripts/changeset/parse.cjs +114 -0
  521. package/scripts/changeset/render.cjs +34 -0
  522. package/scripts/changeset/serialize.cjs +130 -0
  523. package/scripts/check-alias-drift.cjs +114 -0
  524. package/scripts/check-env.cjs +312 -0
  525. package/scripts/check-npm-integrity.cjs +215 -0
  526. package/scripts/ci-guard-runner.cjs +22 -0
  527. package/scripts/ci-prepare-test-scope.cjs +51 -0
  528. package/scripts/ci-rebase-check.cjs +86 -0
  529. package/scripts/ci-test-scope.cjs +431 -0
  530. package/scripts/command-contract-helpers.cjs +64 -0
  531. package/scripts/diff-touches-shipped-paths.cjs +155 -0
  532. package/scripts/fix-slash-commands.cjs +147 -0
  533. package/scripts/gen-inventory-manifest.cjs +115 -0
  534. package/scripts/gen-research-agents.cjs +276 -0
  535. package/scripts/generate-package-identity.cjs +125 -0
  536. package/scripts/issue-dedupe.cjs +278 -0
  537. package/scripts/lib/allowlist-ratchet.cjs +136 -0
  538. package/scripts/lib/cli-exit.cjs +56 -0
  539. package/scripts/lint-command-contract.cjs +114 -0
  540. package/scripts/lint-descriptions.cjs +87 -0
  541. package/scripts/lint-docs-required.cjs +222 -0
  542. package/scripts/lint-legacy-dir-name.cjs +160 -0
  543. package/scripts/lint-package-identity-drift.cjs +141 -0
  544. package/scripts/lint-pr-check-project-dir.cjs +99 -0
  545. package/scripts/lint-shell-command-projection-drift.cjs +62 -0
  546. package/scripts/lint-skill-deps.cjs +185 -0
  547. package/scripts/lint-test-file-count.allowlist.json +135 -0
  548. package/scripts/lint-test-file-count.cjs +246 -0
  549. package/scripts/mutation-matrix.cjs +222 -0
  550. package/scripts/pr-template-policy.cjs +268 -0
  551. package/scripts/prompt-injection-scan.sh +207 -0
  552. package/scripts/release-notes/discord-release-summary.cjs +373 -0
  553. package/scripts/release-notes/format-github-release-notes.cjs +261 -0
  554. package/scripts/release-tarball-smoke.cjs +629 -0
  555. package/scripts/research-profiles.cjs +149 -0
  556. package/scripts/run-affected-tests.cjs +7 -0
  557. package/scripts/run-cross-platform-tests.cjs +67 -0
  558. package/scripts/run-tests.cjs +315 -0
  559. package/scripts/secret-scan-lint.sh +231 -0
  560. package/scripts/secret-scan.sh +358 -0
  561. package/scripts/setup-branch-protection.sh +236 -0
  562. package/scripts/strip-prose-atrefs.cjs +106 -0
  563. package/scripts/sync-manifest-versions.cjs +119 -0
  564. package/scripts/sync-rulesets.sh +34 -0
  565. package/scripts/sync-runtime-launcher.cjs +399 -0
  566. package/scripts/test-failure-reasons.cjs +34 -0
  567. package/scripts/verify-npm-publish.cjs +240 -0
  568. package/scripts/workflow-policy.cjs +450 -0
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * lint-skill-deps.cjs
4
+ *
5
+ * Two checks:
6
+ *
7
+ * a) Frontmatter to body consistency:
8
+ * For each commands/gsd/*.md, parse requires: and walk the body for
9
+ * references to other GSD skills (pattern: /gsd:<stem> or gsd:<stem>).
10
+ * Fail if a skill body references a skill not listed in requires:.
11
+ *
12
+ * b) Profile closure satisfaction:
13
+ * Load PROFILES from install-profiles.cjs. For each non-full profile,
14
+ * compute closure(profile.base) using the manifest. If any skill in
15
+ * the closure references a skill NOT in the closure, fail.
16
+ *
17
+ * Usage:
18
+ * node scripts/lint-skill-deps.cjs # scans commands/gsd/
19
+ * node scripts/lint-skill-deps.cjs --dir <path> # scan a custom dir (testing)
20
+ *
21
+ * Exits 0 if all pass; exits 1 if any violation.
22
+ */
23
+
24
+ 'use strict';
25
+
26
+ const fs = require('fs');
27
+ const path = require('path');
28
+ const { runMain } = require('./lib/cli-exit.cjs');
29
+
30
+ const PROFILES_MODULE = path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'install-profiles.cjs');
31
+ const { PROFILES, loadSkillsManifest, resolveProfile } = require(PROFILES_MODULE);
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Argument parsing
35
+ // ---------------------------------------------------------------------------
36
+
37
+ let commandsDir = path.join(__dirname, '..', 'commands', 'gsd');
38
+ const args = process.argv.slice(2);
39
+ for (let i = 0; i < args.length; i++) {
40
+ if (args[i] === '--dir' && args[i + 1]) {
41
+ commandsDir = args[i + 1];
42
+ i++;
43
+ }
44
+ }
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // Reference extraction from skill body
48
+ // ---------------------------------------------------------------------------
49
+
50
+ function extractBodyReferences(body) {
51
+ const refs = new Set();
52
+ const re = /(?:\/?)gsd:([a-z0-9_-]+)/g;
53
+ let m;
54
+ while ((m = re.exec(body)) !== null) {
55
+ refs.add(m[1]);
56
+ }
57
+ return refs;
58
+ }
59
+
60
+ function extractBody(content) {
61
+ const fmEnd = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/m);
62
+ if (!fmEnd) return content;
63
+ return content.slice(fmEnd[0].length);
64
+ }
65
+
66
+ // ---------------------------------------------------------------------------
67
+ // Check a: frontmatter to body consistency
68
+ // ---------------------------------------------------------------------------
69
+
70
+ function checkFrontmatterBodyConsistency(manifest, allStems) {
71
+ const violations = [];
72
+
73
+ for (const [stem, declared] of manifest) {
74
+ if (stem.startsWith('_calls_agents_')) continue;
75
+ const filePath = path.join(commandsDir, stem + '.md');
76
+ let content;
77
+ try {
78
+ content = fs.readFileSync(filePath, 'utf8');
79
+ } catch {
80
+ continue;
81
+ }
82
+ const body = extractBody(content);
83
+ const referenced = extractBodyReferences(body);
84
+ const declaredSet = new Set(declared);
85
+ for (const ref of referenced) {
86
+ if (ref === stem) continue;
87
+ if (!allStems.has(ref)) {
88
+ violations.push({
89
+ stem,
90
+ filePath,
91
+ undeclared: ref,
92
+ message: 'body references unknown skill gsd:' + ref,
93
+ });
94
+ continue;
95
+ }
96
+ if (!declaredSet.has(ref)) {
97
+ violations.push({
98
+ stem,
99
+ filePath,
100
+ undeclared: ref,
101
+ message: 'body references gsd:' + ref + ' but requires: does not list it',
102
+ });
103
+ }
104
+ }
105
+ }
106
+
107
+ return violations;
108
+ }
109
+
110
+ // ---------------------------------------------------------------------------
111
+ // Check b: profile closure satisfaction
112
+ // ---------------------------------------------------------------------------
113
+
114
+ function checkProfileClosure(manifest) {
115
+ const violations = [];
116
+
117
+ for (const profileName of Object.keys(PROFILES)) {
118
+ const base = PROFILES[profileName];
119
+ if (base === '*') continue;
120
+ const resolved = resolveProfile({ modes: [profileName], manifest });
121
+ if (resolved.skills === '*') continue;
122
+
123
+ const closure = resolved.skills;
124
+ for (const stem of closure) {
125
+ const deps = manifest.get(stem) || [];
126
+ for (const dep of deps) {
127
+ if (!closure.has(dep)) {
128
+ violations.push({
129
+ profile: profileName,
130
+ stem,
131
+ missingDep: dep,
132
+ message: 'profile "' + profileName + '" includes "' + stem + '" which requires "' + dep + '", but "' + dep + '" is not in the closure',
133
+ });
134
+ }
135
+ }
136
+ }
137
+ }
138
+
139
+ return violations;
140
+ }
141
+
142
+ // ---------------------------------------------------------------------------
143
+ // Main
144
+ // ---------------------------------------------------------------------------
145
+
146
+ function main() {
147
+ const manifest = loadSkillsManifest(commandsDir);
148
+ const allStems = new Set(
149
+ [...manifest.keys()].filter((k) => !k.startsWith('_calls_agents_'))
150
+ );
151
+
152
+ const consistencyViolations = checkFrontmatterBodyConsistency(manifest, allStems);
153
+ const closureViolations = checkProfileClosure(manifest);
154
+
155
+ const totalViolations = consistencyViolations.length + closureViolations.length;
156
+
157
+ if (totalViolations === 0) {
158
+ const checked = manifest.size;
159
+ process.stdout.write('ok lint-skill-deps: ' + checked + ' skill(s) checked, 0 violations\n');
160
+ return 0;
161
+ }
162
+
163
+ process.stderr.write('\nERROR lint-skill-deps: ' + totalViolations + ' violation(s) found\n\n');
164
+
165
+ if (consistencyViolations.length > 0) {
166
+ process.stderr.write('Frontmatter to body consistency violations (' + consistencyViolations.length + '):\n\n');
167
+ for (const v of consistencyViolations) {
168
+ process.stderr.write(' ' + v.filePath + '\n');
169
+ process.stderr.write(' ' + v.message + '\n\n');
170
+ }
171
+ process.stderr.write('Fix: add missing deps to requires: in the skill frontmatter.\n\n');
172
+ }
173
+
174
+ if (closureViolations.length > 0) {
175
+ process.stderr.write('Profile closure violations (' + closureViolations.length + '):\n\n');
176
+ for (const v of closureViolations) {
177
+ process.stderr.write(' ' + v.message + '\n');
178
+ }
179
+ process.stderr.write('\nFix: add the missing skills to the profile base set in install-profiles.cjs.\n\n');
180
+ }
181
+
182
+ return 1;
183
+ }
184
+
185
+ runMain(main);
@@ -0,0 +1,135 @@
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.",
3
+ "modules": {
4
+ "audit": {
5
+ "files": [
6
+ "audit-fix-command.test.cjs",
7
+ "bug-2659-audit-open-crash.test.cjs",
8
+ "bug-2836-audit-open-summary-uat-drift.test.cjs",
9
+ "bug-2911-audit-open-output-shape.test.cjs"
10
+ ],
11
+ "issue": "192"
12
+ },
13
+ "config": {
14
+ "files": [
15
+ "bug-2943-config-get-context-window-default.test.cjs",
16
+ "bug-321-config-defaults-clone-strategy.test.cjs",
17
+ "bug-3227-config-set-model-overrides.test.cjs",
18
+ "bug-442-config-dir-equals-in-path.test.cjs",
19
+ "config-field-docs.test.cjs",
20
+ "config-get-default.test.cjs",
21
+ "config-schema.property.test.cjs",
22
+ "config.test.cjs"
23
+ ],
24
+ "issue": "TBD"
25
+ },
26
+ "graphify": {
27
+ "files": [
28
+ "bug-622-graphify-optional-graph-html.test.cjs",
29
+ "graphify-auto-update.test.cjs",
30
+ "graphify-query.test.cjs",
31
+ "graphify-visualization.test.cjs",
32
+ "graphify.test.cjs"
33
+ ],
34
+ "issue": "622"
35
+ },
36
+ "intel": {
37
+ "files": [
38
+ "bug-2351-intel-kilo-layout.test.cjs",
39
+ "bug-3290-intel-updater-layout-block.test.cjs",
40
+ "intel.test.cjs"
41
+ ],
42
+ "issue": "TBD"
43
+ },
44
+ "milestone": {
45
+ "files": [
46
+ "bug-730-milestone-phase-details-scope.test.cjs",
47
+ "milestone-archive.test.cjs",
48
+ "milestone-helper.test.cjs",
49
+ "milestone-prefixed-convention.test.cjs",
50
+ "milestone-summary.test.cjs",
51
+ "milestone.test.cjs"
52
+ ],
53
+ "issue": "TBD"
54
+ },
55
+ "phase": {
56
+ "files": [
57
+ "bug-214-phase-researcher-write-truncation-contract.test.cjs",
58
+ "phase-dependency-levels.test.cjs",
59
+ "phase.test.cjs"
60
+ ],
61
+ "issue": "597"
62
+ },
63
+ "roadmap": {
64
+ "files": [
65
+ "bug-2661-roadmap-sync-parallel.test.cjs",
66
+ "bug-3128-roadmap-plan-count-slug-layout.test.cjs",
67
+ "bug-3599-roadmap-get-phase-project-code-prefix.test.cjs",
68
+ "enh-2447-roadmap-wave-deps.test.cjs",
69
+ "roadmap-mode-field.test.cjs",
70
+ "roadmap-phase-fallback.test.cjs",
71
+ "roadmap.test.cjs"
72
+ ],
73
+ "issue": "TBD"
74
+ },
75
+ "runtime-artifact-layout": {
76
+ "files": [
77
+ "runtime-artifact-layout-install-profiles.test.cjs",
78
+ "runtime-artifact-layout-surface.test.cjs",
79
+ "runtime-artifact-layout.test.cjs"
80
+ ],
81
+ "issue": "TBD"
82
+ },
83
+ "security": {
84
+ "files": [
85
+ "security-prompt-injection.test.cjs",
86
+ "security-scan.test.cjs",
87
+ "security.test.cjs"
88
+ ],
89
+ "issue": "TBD"
90
+ },
91
+ "state": {
92
+ "files": [
93
+ "bug-21-state-md-template-frontmatter.test.cjs",
94
+ "bug-2630-state-frontmatter-milestone-switch.test.cjs",
95
+ "bug-3127-state-begin-phase-idempotent.test.cjs",
96
+ "bug-3242-state-update-progress-trample.test.cjs",
97
+ "bug-3286-state-write-routing.test.cjs",
98
+ "bug-3454-state-dollar-backreference-growth.test.cjs",
99
+ "bug-397-state-preserve-executor-authored.test.cjs",
100
+ "state-acquirestatelock-non-eexist.test.cjs",
101
+ "state-prune.test.cjs",
102
+ "state.test.cjs"
103
+ ],
104
+ "issue": "180"
105
+ },
106
+ "verify": {
107
+ "files": [
108
+ "bug-2969-verify-reapply-patches.test.cjs",
109
+ "bug-2994-verify-reapply-patches-installed-path.test.cjs",
110
+ "bug-3381-verify-work-workstream.test.cjs",
111
+ "bug-3657-verify-reapply-patches-pristine-drift.test.cjs",
112
+ "verify-health.test.cjs",
113
+ "verify-mvp-uat.test.cjs",
114
+ "verify-npm-publish.test.cjs",
115
+ "verify-test-quality.test.cjs",
116
+ "verify-work-auto-transition.test.cjs",
117
+ "verify.test.cjs"
118
+ ],
119
+ "issue": "3767"
120
+ },
121
+ "install": {
122
+ "files": [
123
+ "bug-410-install-defaults-test-mode-guard.test.cjs",
124
+ "enh-776-install-gemini-hook-events.test.cjs",
125
+ "install-minimal-hooks.test.cjs",
126
+ "install-path-detection.test.cjs",
127
+ "install-regressions.test.cjs",
128
+ "install-runtime-artifacts.test.cjs",
129
+ "install-update-marker.test.cjs",
130
+ "install.test.cjs"
131
+ ],
132
+ "issue": "TBD"
133
+ }
134
+ }
135
+ }
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * lint-test-file-count.cjs — max 2 test files per production module.
4
+ *
5
+ * Scans sdk/src/query/, sdk/src/, gsd-core/bin/lib/, bin/ for production
6
+ * modules, then counts matching test files in tests/ and sdk/src (recursive). Cap is 2
7
+ * (primary + one integration). Over-limit clusters must be in the allowlist with the
8
+ * EXACT set of test filenames grandfathered (identity ratchet via allowlist-ratchet.cjs).
9
+ * Adding a new test file to a capped module is a novel offender; removing one requires
10
+ * pruning the allowlist entry (stale). --json emits structured output.
11
+ *
12
+ * Verdicts: OK_UNDER_LIMIT | OK_IN_ALLOWLIST | FAIL_EXCEEDS_LIMIT |
13
+ * FAIL_NOVEL_FILES | FAIL_STALE_ALLOWLIST
14
+ */
15
+ 'use strict';
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const { assertWithinAllowlist } = require('./lib/allowlist-ratchet.cjs');
20
+ const { runMain } = require('./lib/cli-exit.cjs');
21
+
22
+ const ROOT = path.join(__dirname, '..');
23
+ const PROD_DIRS = [
24
+ path.join(ROOT, 'sdk', 'src', 'query'),
25
+ path.join(ROOT, 'sdk', 'src'),
26
+ path.join(ROOT, 'gsd-core', 'bin', 'lib'),
27
+ path.join(ROOT, 'bin'),
28
+ ];
29
+ const TEST_DIRS = [
30
+ path.join(ROOT, 'tests'),
31
+ path.join(ROOT, 'sdk', 'src'),
32
+ ];
33
+ const ALLOWLIST_PATH = path.join(__dirname, 'lint-test-file-count.allowlist.json');
34
+ const MAX_FILES = 2;
35
+
36
+ const Verdict = Object.freeze({
37
+ OK_UNDER_LIMIT: 'OK_UNDER_LIMIT',
38
+ OK_IN_ALLOWLIST: 'OK_IN_ALLOWLIST',
39
+ FAIL_EXCEEDS_LIMIT: 'FAIL_EXCEEDS_LIMIT',
40
+ FAIL_NOVEL_FILES: 'FAIL_NOVEL_FILES',
41
+ FAIL_STALE_ALLOWLIST: 'FAIL_STALE_ALLOWLIST',
42
+ });
43
+
44
+ function isTestFile(name) {
45
+ return name.endsWith('.test.ts') || name.endsWith('.test.cjs');
46
+ }
47
+
48
+ function listFiles(dir, pred) {
49
+ try {
50
+ return fs.readdirSync(dir, { withFileTypes: true })
51
+ .filter(e => e.isFile() && pred(e.name))
52
+ .map(e => path.join(dir, e.name));
53
+ } catch (_) { return []; }
54
+ }
55
+
56
+ function findTestFilesRecursive(dir) {
57
+ const out = [];
58
+ let entries;
59
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); }
60
+ catch (_) { return out; }
61
+ for (const e of entries) {
62
+ const full = path.join(dir, e.name);
63
+ if (e.isDirectory()) out.push(...findTestFilesRecursive(full));
64
+ else if (isTestFile(e.name)) out.push(full);
65
+ }
66
+ return out;
67
+ }
68
+
69
+ function prodPrefix(filename) {
70
+ return filename.replace(/\.(cjs|ts|js)$/, '');
71
+ }
72
+
73
+ // Strip .test.{cjs,ts} and .integration.test.ts, then strip issue stamps.
74
+ function testEffectivePrefix(testName) {
75
+ const bare = testName
76
+ .replace(/\.integration\.test\.(ts|cjs)$/, '')
77
+ .replace(/\.test\.(ts|cjs)$/, '');
78
+ const m = bare.match(/^(?:feat|bug|enh|fix)-\d+(?:-\d+)*-(.+)$/);
79
+ return m ? m[1] : bare;
80
+ }
81
+
82
+ function collectProdPrefixes() {
83
+ const map = new Map();
84
+ for (const dir of PROD_DIRS) {
85
+ for (const f of listFiles(dir, n =>
86
+ !isTestFile(n) &&
87
+ !/\.(generated|md|json)(\.|$)/.test(n) &&
88
+ /\.(ts|cjs|js)$/.test(n)
89
+ )) {
90
+ const prefix = prodPrefix(path.basename(f));
91
+ if (!map.has(prefix)) map.set(prefix, f);
92
+ }
93
+ }
94
+ return map;
95
+ }
96
+
97
+ function collectAllTestFiles() {
98
+ const seen = new Set();
99
+ const all = [];
100
+ for (const dir of TEST_DIRS) {
101
+ for (const f of findTestFilesRecursive(dir)) {
102
+ if (!seen.has(f)) { seen.add(f); all.push(f); }
103
+ }
104
+ }
105
+ return all;
106
+ }
107
+
108
+ function buildTestMap(prodPrefixes, allTestFiles) {
109
+ const map = new Map([...prodPrefixes.keys()].map(p => [p, []]));
110
+ for (const tf of allTestFiles) {
111
+ const ep = testEffectivePrefix(path.basename(tf));
112
+ for (const prefix of prodPrefixes.keys()) {
113
+ if (ep === prefix || ep.startsWith(prefix + '-')) {
114
+ map.get(prefix).push(tf);
115
+ break;
116
+ }
117
+ }
118
+ }
119
+ return map;
120
+ }
121
+
122
+ function loadAllowlist() {
123
+ try { return JSON.parse(fs.readFileSync(ALLOWLIST_PATH, 'utf-8')).modules || {}; }
124
+ catch (_) { return {}; }
125
+ }
126
+
127
+ /**
128
+ * Evaluate one module's test files against the allowlist.
129
+ *
130
+ * For modules under the default cap (≤ MAX_FILES): simple count check.
131
+ * For modules with an allowlist entry: identity check via assertWithinAllowlist.
132
+ * - count now ≤ MAX_FILES → FAIL_STALE_ALLOWLIST (all known files are stale; prune entry)
133
+ * - novel files (in current but not in known) → FAIL_NOVEL_FILES
134
+ * - stale files (in known but not in current) → FAIL_STALE_ALLOWLIST
135
+ * - exact match → OK_IN_ALLOWLIST
136
+ * For modules over the cap with no allowlist entry: FAIL_EXCEEDS_LIMIT.
137
+ *
138
+ * Returns { verdict, prefix, count, knownFiles, novel, stale, files }
139
+ */
140
+ function evaluateLint({ prefix, testFiles, allowlist }) {
141
+ const count = testFiles.length;
142
+ const entry = allowlist[prefix];
143
+ const currentNames = testFiles.map(f => path.basename(f));
144
+
145
+ if (entry !== undefined) {
146
+ const knownFiles = Array.isArray(entry.files) ? entry.files : [];
147
+ // If the module is now at or under the default cap, the entire allowlist entry is
148
+ // stale and must be removed — this is a ratchet-DOWN failure, not a hint.
149
+ // All known files are stale (the whole entry can go).
150
+ if (count <= MAX_FILES) {
151
+ return {
152
+ verdict: Verdict.FAIL_STALE_ALLOWLIST,
153
+ prefix, count,
154
+ knownFiles,
155
+ novel: [],
156
+ stale: knownFiles.slice().sort(),
157
+ files: testFiles,
158
+ };
159
+ }
160
+ // Identity check via assertWithinAllowlist
161
+ const messages = [];
162
+ const { novel, stale } = assertWithinAllowlist({
163
+ label: prefix,
164
+ current: currentNames,
165
+ known: knownFiles,
166
+ fail: (msg) => messages.push(msg),
167
+ pruneHint: 'scripts/lint-test-file-count.allowlist.json',
168
+ });
169
+
170
+ if (novel.length > 0) {
171
+ return { verdict: Verdict.FAIL_NOVEL_FILES, prefix, count, knownFiles, novel, stale, files: testFiles };
172
+ }
173
+ if (stale.length > 0) {
174
+ return { verdict: Verdict.FAIL_STALE_ALLOWLIST, prefix, count, knownFiles, novel, stale, files: testFiles };
175
+ }
176
+ return { verdict: Verdict.OK_IN_ALLOWLIST, prefix, count, knownFiles, novel: [], stale: [], files: testFiles };
177
+ }
178
+
179
+ if (count <= MAX_FILES) {
180
+ return { verdict: Verdict.OK_UNDER_LIMIT, prefix, count, knownFiles: null, novel: [], stale: [], files: testFiles };
181
+ }
182
+ return { verdict: Verdict.FAIL_EXCEEDS_LIMIT, prefix, count, knownFiles: null, novel: [], stale: [], files: testFiles };
183
+ }
184
+
185
+ function run() {
186
+ const jsonMode = process.argv.includes('--json');
187
+ const prodPrefixes = collectProdPrefixes();
188
+ const allTestFiles = collectAllTestFiles();
189
+ const testMap = buildTestMap(prodPrefixes, allTestFiles);
190
+ const allowlist = loadAllowlist();
191
+
192
+ const results = [];
193
+ for (const [prefix, files] of testMap) {
194
+ if (files.length === 0) continue;
195
+ results.push(evaluateLint({ prefix, testFiles: files, allowlist }));
196
+ }
197
+
198
+ const failures = results.filter(r =>
199
+ r.verdict === Verdict.FAIL_EXCEEDS_LIMIT ||
200
+ r.verdict === Verdict.FAIL_NOVEL_FILES ||
201
+ r.verdict === Verdict.FAIL_STALE_ALLOWLIST);
202
+
203
+ if (jsonMode) {
204
+ console.log(JSON.stringify({ ok: failures.length === 0, results, failures, hints: [] }, null, 2));
205
+ return failures.length > 0 ? 1 : 0;
206
+ }
207
+
208
+ if (failures.length === 0) {
209
+ const inAllowlist = results.filter(r => r.verdict === Verdict.OK_IN_ALLOWLIST).length;
210
+ console.log(`ok lint-test-file-count: ${results.length} module(s) checked, 0 failures` +
211
+ (inAllowlist > 0 ? `, ${inAllowlist} allowlisted` : ''));
212
+ return 0;
213
+ }
214
+
215
+ process.stderr.write(`\nERROR lint-test-file-count: ${failures.length} module(s) exceed the test-file limit\n\n`);
216
+ for (const f of failures) {
217
+ if (f.verdict === Verdict.FAIL_EXCEEDS_LIMIT) {
218
+ process.stderr.write(` ${f.prefix}: ${f.count} files (limit ${MAX_FILES}) — not in allowlist\n`);
219
+ for (const tf of f.files) process.stderr.write(` ${path.relative(ROOT, tf)}\n`);
220
+ } else if (f.verdict === Verdict.FAIL_NOVEL_FILES) {
221
+ process.stderr.write(` ${f.prefix}: ${f.novel.length} NEW test file(s) not in allowlist\n`);
222
+ for (const n of f.novel) process.stderr.write(` + ${n}\n`);
223
+ } else if (f.verdict === Verdict.FAIL_STALE_ALLOWLIST) {
224
+ if (f.count <= MAX_FILES) {
225
+ const staleList = f.stale.join(', ');
226
+ process.stderr.write(` "${f.prefix}": now at ${f.count} file(s) (≤ ${MAX_FILES}) — remove its entry from the allowlist (stale: ${staleList})\n`);
227
+ } else {
228
+ process.stderr.write(` ${f.prefix}: ${f.stale.length} allowlisted file(s) no longer present — prune allowlist\n`);
229
+ for (const s of f.stale) process.stderr.write(` - ${s}\n`);
230
+ }
231
+ }
232
+ }
233
+ process.stderr.write('\nFix: consolidate test files per module (one primary + one integration).\n');
234
+ process.stderr.write('Or update scripts/lint-test-file-count.allowlist.json with PR justification.\n\n');
235
+ return 1;
236
+ }
237
+
238
+ module.exports = {
239
+ Verdict, evaluateLint, testEffectivePrefix, prodPrefix,
240
+ _collectProdPrefixes: collectProdPrefixes,
241
+ _collectAllTestFiles: collectAllTestFiles,
242
+ _buildTestMap: buildTestMap,
243
+ _loadAllowlist: loadAllowlist,
244
+ };
245
+
246
+ if (require.main === module) runMain(run);