@opengsd/gsd-core 1.2.0 → 1.3.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 (532) hide show
  1. package/README.ja-JP.md +46 -791
  2. package/README.ko-KR.md +44 -780
  3. package/README.md +42 -218
  4. package/README.pt-BR.md +47 -414
  5. package/README.zh-CN.md +46 -763
  6. package/agents/gsd-ai-researcher.md +2 -2
  7. package/agents/gsd-debug-session-manager.md +1 -1
  8. package/agents/gsd-debugger.md +8 -8
  9. package/agents/gsd-doc-writer.md +7 -6
  10. package/agents/gsd-domain-researcher.md +15 -2
  11. package/agents/gsd-eval-auditor.md +1 -1
  12. package/agents/gsd-eval-planner.md +2 -2
  13. package/agents/gsd-executor.md +21 -8
  14. package/agents/gsd-framework-selector.md +1 -1
  15. package/agents/gsd-intel-updater.md +4 -4
  16. package/agents/gsd-phase-researcher.md +19 -6
  17. package/agents/gsd-plan-checker.md +3 -3
  18. package/agents/gsd-planner.md +36 -23
  19. package/agents/gsd-project-researcher.md +13 -0
  20. package/agents/gsd-research-synthesizer.md +6 -2
  21. package/agents/gsd-roadmapper.md +6 -6
  22. package/agents/gsd-ui-researcher.md +16 -3
  23. package/agents/gsd-user-profiler.md +2 -2
  24. package/agents/gsd-verifier.md +8 -8
  25. package/assets/gsd-logo-2000-transparent.png +0 -0
  26. package/assets/gsd-logo-2000-transparent.svg +17 -0
  27. package/assets/gsd-logo-2000.png +0 -0
  28. package/assets/gsd-logo-2000.svg +21 -0
  29. package/assets/terminal.svg +68 -0
  30. package/bin/install.js +255 -103
  31. package/commands/gsd/add-tests.md +1 -1
  32. package/commands/gsd/ai-integration-phase.md +3 -3
  33. package/commands/gsd/audit-fix.md +1 -1
  34. package/commands/gsd/audit-milestone.md +1 -1
  35. package/commands/gsd/audit-uat.md +1 -1
  36. package/commands/gsd/autonomous.md +2 -2
  37. package/commands/gsd/capture.md +6 -6
  38. package/commands/gsd/cleanup.md +1 -1
  39. package/commands/gsd/code-review.md +1 -1
  40. package/commands/gsd/complete-milestone.md +2 -2
  41. package/commands/gsd/config.md +3 -3
  42. package/commands/gsd/debug.md +1 -1
  43. package/commands/gsd/discuss-phase.md +5 -4
  44. package/commands/gsd/docs-update.md +1 -1
  45. package/commands/gsd/eval-review.md +2 -2
  46. package/commands/gsd/execute-phase.md +2 -2
  47. package/commands/gsd/explore.md +1 -1
  48. package/commands/gsd/extract-learnings.md +2 -2
  49. package/commands/gsd/fast.md +1 -1
  50. package/commands/gsd/forensics.md +1 -1
  51. package/commands/gsd/graphify.md +9 -9
  52. package/commands/gsd/health.md +1 -1
  53. package/commands/gsd/help.md +2 -2
  54. package/commands/gsd/import.md +5 -5
  55. package/commands/gsd/inbox.md +1 -1
  56. package/commands/gsd/ingest-docs.md +4 -4
  57. package/commands/gsd/manager.md +3 -3
  58. package/commands/gsd/map-codebase.md +1 -1
  59. package/commands/gsd/milestone-summary.md +1 -1
  60. package/commands/gsd/mvp-phase.md +4 -4
  61. package/commands/gsd/new-milestone.md +5 -5
  62. package/commands/gsd/new-project.md +5 -5
  63. package/commands/gsd/pause-work.md +2 -2
  64. package/commands/gsd/phase.md +4 -4
  65. package/commands/gsd/plan-phase.md +2 -2
  66. package/commands/gsd/plan-review-convergence.md +4 -4
  67. package/commands/gsd/pr-branch.md +1 -1
  68. package/commands/gsd/profile-user.md +2 -2
  69. package/commands/gsd/progress.md +4 -4
  70. package/commands/gsd/quick.md +1 -1
  71. package/commands/gsd/resume-work.md +1 -1
  72. package/commands/gsd/review.md +3 -2
  73. package/commands/gsd/secure-phase.md +1 -1
  74. package/commands/gsd/settings.md +1 -1
  75. package/commands/gsd/ship.md +2 -2
  76. package/commands/gsd/sketch.md +7 -7
  77. package/commands/gsd/spec-phase.md +2 -2
  78. package/commands/gsd/spike.md +3 -3
  79. package/commands/gsd/stats.md +1 -1
  80. package/commands/gsd/surface.md +4 -4
  81. package/commands/gsd/thread.md +1 -1
  82. package/commands/gsd/ui-phase.md +2 -2
  83. package/commands/gsd/ui-review.md +2 -2
  84. package/commands/gsd/ultraplan-phase.md +2 -2
  85. package/commands/gsd/undo.md +3 -3
  86. package/commands/gsd/update.md +3 -3
  87. package/commands/gsd/validate-phase.md +1 -1
  88. package/commands/gsd/verify-work.md +2 -2
  89. package/commands/gsd/workspace.md +4 -4
  90. package/{get-shit-done → gsd-core}/bin/check-latest-version.cjs +1 -1
  91. package/{get-shit-done → gsd-core}/bin/gsd-tools.cjs +50 -4
  92. package/gsd-core/bin/lib/active-workstream-store.cjs +291 -0
  93. package/gsd-core/bin/lib/adr-parser.cjs +399 -0
  94. package/gsd-core/bin/lib/agent-command-router.cjs +68 -0
  95. package/gsd-core/bin/lib/artifacts.cjs +51 -0
  96. package/gsd-core/bin/lib/audit.cjs +743 -0
  97. package/gsd-core/bin/lib/check-command-router.cjs +342 -0
  98. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +81 -0
  99. package/gsd-core/bin/lib/clock.cjs +95 -0
  100. package/gsd-core/bin/lib/clusters.cjs +128 -0
  101. package/gsd-core/bin/lib/code-review-flags.cjs +59 -0
  102. package/gsd-core/bin/lib/command-aliases.cjs +809 -0
  103. package/gsd-core/bin/lib/command-arg-projection.cjs +55 -0
  104. package/gsd-core/bin/lib/command-routing-hub.cjs +300 -0
  105. package/gsd-core/bin/lib/commands.cjs +1202 -0
  106. package/gsd-core/bin/lib/config-schema.cjs +29 -0
  107. package/gsd-core/bin/lib/config-types.cjs +19 -0
  108. package/gsd-core/bin/lib/config.cjs +714 -0
  109. package/{get-shit-done → gsd-core}/bin/lib/configuration.cjs +76 -85
  110. package/gsd-core/bin/lib/context-utilization.cjs +48 -0
  111. package/gsd-core/bin/lib/core.cjs +2007 -0
  112. package/{get-shit-done → gsd-core}/bin/lib/decisions.cjs +9 -7
  113. package/gsd-core/bin/lib/docs.cjs +252 -0
  114. package/gsd-core/bin/lib/drift.cjs +364 -0
  115. package/gsd-core/bin/lib/fallow-runner.cjs +115 -0
  116. package/gsd-core/bin/lib/frontmatter.cjs +442 -0
  117. package/gsd-core/bin/lib/gap-checker.cjs +257 -0
  118. package/gsd-core/bin/lib/graphify.cjs +496 -0
  119. package/gsd-core/bin/lib/gsd2-import.cjs +456 -0
  120. package/gsd-core/bin/lib/init-command-router.cjs +62 -0
  121. package/gsd-core/bin/lib/init.cjs +1799 -0
  122. package/gsd-core/bin/lib/install-profiles.cjs +526 -0
  123. package/gsd-core/bin/lib/installer-migration-authoring.cjs +122 -0
  124. package/gsd-core/bin/lib/installer-migration-report.cjs +347 -0
  125. package/gsd-core/bin/lib/installer-migrations/000-first-time-baseline.cjs +218 -0
  126. package/gsd-core/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +48 -0
  127. package/gsd-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +94 -0
  128. package/gsd-core/bin/lib/installer-migrations/003-rename-get-shit-done-to-gsd-core.cjs +108 -0
  129. package/gsd-core/bin/lib/installer-migrations.cjs +784 -0
  130. package/gsd-core/bin/lib/intel.cjs +607 -0
  131. package/gsd-core/bin/lib/learnings.cjs +270 -0
  132. package/gsd-core/bin/lib/legacy-cleanup.cjs +253 -0
  133. package/gsd-core/bin/lib/milestone.cjs +373 -0
  134. package/gsd-core/bin/lib/model-catalog.cjs +154 -0
  135. package/gsd-core/bin/lib/model-profiles.cjs +24 -0
  136. package/gsd-core/bin/lib/observability/event.cjs +51 -0
  137. package/gsd-core/bin/lib/observability/logger.cjs +146 -0
  138. package/{get-shit-done → gsd-core}/bin/lib/observability/redaction.cjs +19 -21
  139. package/{get-shit-done → gsd-core}/bin/lib/package-identity.cjs +5 -1
  140. package/gsd-core/bin/lib/phase-command-router.cjs +189 -0
  141. package/gsd-core/bin/lib/phase-lifecycle.cjs +74 -0
  142. package/gsd-core/bin/lib/phase.cjs +1307 -0
  143. package/gsd-core/bin/lib/phases-command-router.cjs +43 -0
  144. package/{get-shit-done → gsd-core}/bin/lib/plan-scan.cjs +18 -24
  145. package/gsd-core/bin/lib/planning-workspace.cjs +245 -0
  146. package/gsd-core/bin/lib/profile-output.cjs +1120 -0
  147. package/gsd-core/bin/lib/profile-pipeline.cjs +517 -0
  148. package/gsd-core/bin/lib/project-root.cjs +119 -0
  149. package/gsd-core/bin/lib/prompt-budget.cjs +305 -0
  150. package/gsd-core/bin/lib/review-reviewer-selection.cjs +121 -0
  151. package/gsd-core/bin/lib/roadmap-command-router.cjs +166 -0
  152. package/gsd-core/bin/lib/roadmap-upgrade.cjs +491 -0
  153. package/gsd-core/bin/lib/roadmap.cjs +600 -0
  154. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +254 -0
  155. package/gsd-core/bin/lib/runtime-homes.cjs +169 -0
  156. package/gsd-core/bin/lib/runtime-name-policy.cjs +96 -0
  157. package/gsd-core/bin/lib/runtime-slash.cjs +119 -0
  158. package/{get-shit-done → gsd-core}/bin/lib/schema-detect.cjs +20 -26
  159. package/gsd-core/bin/lib/secrets.cjs +34 -0
  160. package/gsd-core/bin/lib/security.cjs +407 -0
  161. package/gsd-core/bin/lib/semver-compare.cjs +42 -0
  162. package/gsd-core/bin/lib/shell-command-projection.cjs +524 -0
  163. package/gsd-core/bin/lib/state-command-router.cjs +160 -0
  164. package/{get-shit-done → gsd-core}/bin/lib/state-document.cjs +78 -82
  165. package/gsd-core/bin/lib/state.cjs +2010 -0
  166. package/gsd-core/bin/lib/surface.cjs +406 -0
  167. package/gsd-core/bin/lib/task-command-router.cjs +85 -0
  168. package/gsd-core/bin/lib/template.cjs +237 -0
  169. package/gsd-core/bin/lib/uat.cjs +297 -0
  170. package/gsd-core/bin/lib/ui-safety-gate.cjs +98 -0
  171. package/gsd-core/bin/lib/update-context.cjs +218 -0
  172. package/gsd-core/bin/lib/validate-command-router.cjs +91 -0
  173. package/gsd-core/bin/lib/validate.cjs +112 -0
  174. package/gsd-core/bin/lib/verify-command-router.cjs +44 -0
  175. package/gsd-core/bin/lib/verify.cjs +1451 -0
  176. package/{get-shit-done → gsd-core}/bin/lib/workstream-inventory-builder.cjs +19 -12
  177. package/gsd-core/bin/lib/workstream-inventory.cjs +147 -0
  178. package/{get-shit-done → gsd-core}/bin/lib/workstream-name-policy.cjs +28 -31
  179. package/gsd-core/bin/lib/workstream.cjs +380 -0
  180. package/gsd-core/bin/lib/worktree-safety.cjs +912 -0
  181. package/{get-shit-done → gsd-core}/bin/shared/config-defaults.manifest.json +1 -0
  182. package/{get-shit-done → gsd-core}/bin/shared/config-schema.manifest.json +17 -1
  183. package/{get-shit-done → gsd-core}/bin/shared/model-catalog.json +27 -0
  184. package/{get-shit-done → gsd-core}/references/artifact-types.md +1 -1
  185. package/{get-shit-done → gsd-core}/references/checkpoints.md +1 -1
  186. package/{get-shit-done → gsd-core}/references/few-shot-examples/plan-checker.md +2 -2
  187. package/{get-shit-done → gsd-core}/references/few-shot-examples/verifier.md +12 -12
  188. package/{get-shit-done → gsd-core}/references/model-profile-resolution.md +1 -1
  189. package/{get-shit-done → gsd-core}/references/mvp-concepts.md +1 -1
  190. package/{get-shit-done → gsd-core}/references/planner-graphify-auto-update.md +2 -2
  191. package/{get-shit-done → gsd-core}/references/planner-human-verify-mode.md +1 -1
  192. package/{get-shit-done → gsd-core}/references/planner-mvp-mode.md +1 -1
  193. package/{get-shit-done → gsd-core}/references/ui-brand.md +4 -2
  194. package/{get-shit-done → gsd-core}/references/verification-patterns.md +1 -1
  195. package/gsd-core/references/worktree-branch-check.md +38 -0
  196. package/{get-shit-done → gsd-core}/references/worktree-path-safety.md +4 -26
  197. package/{get-shit-done → gsd-core}/templates/README.md +2 -2
  198. package/{get-shit-done → gsd-core}/templates/codebase/structure.md +10 -10
  199. package/{get-shit-done → gsd-core}/templates/copilot-instructions.md +1 -1
  200. package/{get-shit-done → gsd-core}/templates/phase-prompt.md +10 -10
  201. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -0
  202. package/{get-shit-done → gsd-core}/workflows/add-backlog.md +1 -1
  203. package/{get-shit-done → gsd-core}/workflows/add-phase.md +1 -1
  204. package/{get-shit-done → gsd-core}/workflows/add-tests.md +1 -1
  205. package/{get-shit-done → gsd-core}/workflows/add-todo.md +1 -1
  206. package/{get-shit-done → gsd-core}/workflows/ai-integration-phase.md +4 -4
  207. package/{get-shit-done → gsd-core}/workflows/audit-fix.md +2 -2
  208. package/{get-shit-done → gsd-core}/workflows/audit-milestone.md +3 -1
  209. package/{get-shit-done → gsd-core}/workflows/audit-uat.md +1 -1
  210. package/{get-shit-done → gsd-core}/workflows/autonomous.md +10 -8
  211. package/{get-shit-done → gsd-core}/workflows/check-todos.md +1 -1
  212. package/{get-shit-done → gsd-core}/workflows/cleanup.md +44 -4
  213. package/{get-shit-done → gsd-core}/workflows/code-review-fix.md +4 -4
  214. package/{get-shit-done → gsd-core}/workflows/code-review.md +6 -4
  215. package/{get-shit-done → gsd-core}/workflows/complete-milestone.md +2 -2
  216. package/{get-shit-done → gsd-core}/workflows/debug.md +7 -2
  217. package/{get-shit-done → gsd-core}/workflows/diagnose-issues.md +6 -2
  218. package/{get-shit-done → gsd-core}/workflows/discovery-phase.md +5 -5
  219. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/advisor.md +5 -5
  220. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/auto.md +1 -1
  221. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/chain.md +1 -1
  222. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/power.md +1 -1
  223. package/{get-shit-done → gsd-core}/workflows/discuss-phase-assumptions.md +4 -4
  224. package/{get-shit-done → gsd-core}/workflows/discuss-phase.md +6 -6
  225. package/{get-shit-done → gsd-core}/workflows/do.md +1 -1
  226. package/{get-shit-done → gsd-core}/workflows/docs-update.md +19 -5
  227. package/{get-shit-done → gsd-core}/workflows/edit-phase.md +1 -1
  228. package/{get-shit-done → gsd-core}/workflows/eval-review.md +3 -3
  229. package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/codebase-drift-gate.md +16 -3
  230. package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  231. package/{get-shit-done → gsd-core}/workflows/execute-phase.md +89 -57
  232. package/{get-shit-done → gsd-core}/workflows/execute-plan.md +8 -8
  233. package/{get-shit-done → gsd-core}/workflows/explore.md +5 -3
  234. package/{get-shit-done → gsd-core}/workflows/extract-learnings.md +1 -1
  235. package/{get-shit-done → gsd-core}/workflows/forensics.md +1 -1
  236. package/{get-shit-done → gsd-core}/workflows/graduation.md +1 -1
  237. package/{get-shit-done → gsd-core}/workflows/health.md +1 -1
  238. package/{get-shit-done → gsd-core}/workflows/help/modes/default.md +3 -3
  239. package/{get-shit-done → gsd-core}/workflows/help/modes/full.md +6 -6
  240. package/{get-shit-done → gsd-core}/workflows/import.md +3 -1
  241. package/{get-shit-done → gsd-core}/workflows/ingest-docs.md +5 -5
  242. package/{get-shit-done → gsd-core}/workflows/insert-phase.md +1 -1
  243. package/{get-shit-done → gsd-core}/workflows/list-workspaces.md +1 -1
  244. package/{get-shit-done → gsd-core}/workflows/manager.md +3 -3
  245. package/{get-shit-done → gsd-core}/workflows/map-codebase.md +3 -1
  246. package/{get-shit-done → gsd-core}/workflows/milestone-summary.md +1 -1
  247. package/{get-shit-done → gsd-core}/workflows/mvp-phase.md +7 -7
  248. package/{get-shit-done → gsd-core}/workflows/new-milestone.md +5 -5
  249. package/{get-shit-done → gsd-core}/workflows/new-project.md +8 -8
  250. package/{get-shit-done → gsd-core}/workflows/new-workspace.md +1 -1
  251. package/{get-shit-done → gsd-core}/workflows/next.md +1 -1
  252. package/{get-shit-done → gsd-core}/workflows/pause-work.md +1 -1
  253. package/{get-shit-done → gsd-core}/workflows/plan-milestone-gaps.md +1 -1
  254. package/{get-shit-done → gsd-core}/workflows/plan-phase.md +29 -28
  255. package/{get-shit-done → gsd-core}/workflows/plan-review-convergence.md +10 -10
  256. package/{get-shit-done → gsd-core}/workflows/plant-seed.md +1 -1
  257. package/{get-shit-done → gsd-core}/workflows/profile-user.md +11 -11
  258. package/{get-shit-done → gsd-core}/workflows/progress.md +1 -1
  259. package/{get-shit-done → gsd-core}/workflows/quick.md +7 -29
  260. package/{get-shit-done → gsd-core}/workflows/reapply-patches.md +2 -2
  261. package/{get-shit-done → gsd-core}/workflows/remove-phase.md +1 -1
  262. package/{get-shit-done → gsd-core}/workflows/remove-workspace.md +1 -1
  263. package/{get-shit-done → gsd-core}/workflows/resume-project.md +2 -2
  264. package/{get-shit-done → gsd-core}/workflows/review.md +110 -2
  265. package/{get-shit-done → gsd-core}/workflows/scan.md +3 -1
  266. package/{get-shit-done → gsd-core}/workflows/secure-phase.md +5 -3
  267. package/{get-shit-done → gsd-core}/workflows/settings-advanced.md +196 -6
  268. package/{get-shit-done → gsd-core}/workflows/settings-integrations.md +2 -2
  269. package/{get-shit-done → gsd-core}/workflows/settings.md +16 -2
  270. package/{get-shit-done → gsd-core}/workflows/ship.md +56 -4
  271. package/{get-shit-done → gsd-core}/workflows/sketch-wrap-up.md +1 -1
  272. package/{get-shit-done → gsd-core}/workflows/sketch.md +5 -5
  273. package/{get-shit-done → gsd-core}/workflows/spec-phase.md +2 -2
  274. package/{get-shit-done → gsd-core}/workflows/spike-wrap-up.md +1 -1
  275. package/{get-shit-done → gsd-core}/workflows/spike.md +1 -1
  276. package/{get-shit-done → gsd-core}/workflows/stats.md +1 -1
  277. package/{get-shit-done → gsd-core}/workflows/sync-skills.md +3 -3
  278. package/{get-shit-done → gsd-core}/workflows/thread.md +1 -1
  279. package/{get-shit-done → gsd-core}/workflows/transition.md +2 -2
  280. package/{get-shit-done → gsd-core}/workflows/ui-phase.md +5 -5
  281. package/{get-shit-done → gsd-core}/workflows/ui-review.md +3 -3
  282. package/{get-shit-done → gsd-core}/workflows/ultraplan-phase.md +1 -1
  283. package/{get-shit-done → gsd-core}/workflows/undo.md +2 -2
  284. package/{get-shit-done → gsd-core}/workflows/update.md +41 -16
  285. package/{get-shit-done → gsd-core}/workflows/validate-phase.md +5 -3
  286. package/{get-shit-done → gsd-core}/workflows/verify-phase.md +4 -4
  287. package/{get-shit-done → gsd-core}/workflows/verify-work.md +7 -7
  288. package/hooks/dist/gsd-check-update-worker.js +16 -3
  289. package/hooks/dist/gsd-check-update.js +7 -5
  290. package/hooks/dist/gsd-context-monitor.js +2 -2
  291. package/hooks/dist/gsd-statusline.js +39 -21
  292. package/hooks/dist/gsd-update-banner.js +6 -2
  293. package/hooks/dist/gsd-worktree-path-guard.js +169 -0
  294. package/hooks/dist/managed-hooks-registry.cjs +35 -0
  295. package/hooks/gsd-check-update-worker.js +16 -3
  296. package/hooks/gsd-check-update.js +7 -5
  297. package/hooks/gsd-context-monitor.js +2 -2
  298. package/hooks/gsd-statusline.js +39 -21
  299. package/hooks/gsd-update-banner.js +6 -2
  300. package/hooks/gsd-worktree-path-guard.js +169 -0
  301. package/hooks/managed-hooks-registry.cjs +1 -0
  302. package/package.json +17 -11
  303. package/scripts/affected-tests-lib.cjs +1 -1
  304. package/scripts/base64-scan.sh +12 -0
  305. package/scripts/build-hooks.js +5 -1
  306. package/scripts/changeset/cli.cjs +2 -2
  307. package/scripts/changeset/github-release-notes.cjs +1 -1
  308. package/scripts/changeset/lint.cjs +1 -1
  309. package/scripts/check-alias-drift.cjs +8 -8
  310. package/scripts/check-env.cjs +5 -1
  311. package/scripts/ci-test-scope.cjs +34 -9
  312. package/scripts/command-contract-helpers.cjs +1 -1
  313. package/scripts/fix-slash-commands.cjs +5 -5
  314. package/scripts/gen-inventory-manifest.cjs +3 -3
  315. package/scripts/generate-package-identity.cjs +28 -7
  316. package/scripts/lib/allowlist-ratchet.cjs +136 -0
  317. package/scripts/lint-command-contract.cjs +1 -1
  318. package/scripts/lint-legacy-dir-name.cjs +156 -0
  319. package/scripts/lint-package-identity-drift.cjs +8 -8
  320. package/scripts/lint-pr-check-project-dir.cjs +0 -1
  321. package/scripts/lint-shell-command-projection-drift.cjs +1 -1
  322. package/scripts/lint-skill-deps.cjs +1 -1
  323. package/scripts/lint-test-file-count.allowlist.json +129 -32
  324. package/scripts/lint-test-file-count.cjs +85 -30
  325. package/scripts/mutation-matrix.cjs +219 -0
  326. package/scripts/prompt-injection-scan.sh +5 -1
  327. package/scripts/release-notes/format-github-release-notes.cjs +256 -0
  328. package/scripts/release-tarball-smoke.cjs +9 -9
  329. package/scripts/run-tests.cjs +34 -2
  330. package/scripts/strip-prose-atrefs.cjs +2 -2
  331. package/scripts/sync-runtime-launcher.cjs +2 -2
  332. package/scripts/verify-npm-publish.cjs +252 -0
  333. package/get-shit-done/bin/lib/active-workstream-store.cjs +0 -302
  334. package/get-shit-done/bin/lib/adr-parser.cjs +0 -394
  335. package/get-shit-done/bin/lib/agent-command-router.cjs +0 -65
  336. package/get-shit-done/bin/lib/artifacts.cjs +0 -53
  337. package/get-shit-done/bin/lib/audit.cjs +0 -755
  338. package/get-shit-done/bin/lib/check-command-router.cjs +0 -333
  339. package/get-shit-done/bin/lib/cjs-command-router-adapter.cjs +0 -118
  340. package/get-shit-done/bin/lib/clock.cjs +0 -96
  341. package/get-shit-done/bin/lib/clusters.cjs +0 -135
  342. package/get-shit-done/bin/lib/code-review-flags.cjs +0 -74
  343. package/get-shit-done/bin/lib/command-aliases.cjs +0 -815
  344. package/get-shit-done/bin/lib/command-arg-projection.cjs +0 -62
  345. package/get-shit-done/bin/lib/command-routing-hub.cjs +0 -388
  346. package/get-shit-done/bin/lib/commands.cjs +0 -1188
  347. package/get-shit-done/bin/lib/config-schema.cjs +0 -31
  348. package/get-shit-done/bin/lib/config.cjs +0 -728
  349. package/get-shit-done/bin/lib/context-utilization.cjs +0 -47
  350. package/get-shit-done/bin/lib/core.cjs +0 -2121
  351. package/get-shit-done/bin/lib/docs.cjs +0 -270
  352. package/get-shit-done/bin/lib/drift.cjs +0 -388
  353. package/get-shit-done/bin/lib/fallow-runner.cjs +0 -109
  354. package/get-shit-done/bin/lib/frontmatter.cjs +0 -389
  355. package/get-shit-done/bin/lib/gap-checker.cjs +0 -205
  356. package/get-shit-done/bin/lib/graphify.cjs +0 -592
  357. package/get-shit-done/bin/lib/gsd2-import.cjs +0 -514
  358. package/get-shit-done/bin/lib/init-command-router.cjs +0 -58
  359. package/get-shit-done/bin/lib/init.cjs +0 -2112
  360. package/get-shit-done/bin/lib/install-profiles.cjs +0 -603
  361. package/get-shit-done/bin/lib/installer-migration-authoring.cjs +0 -117
  362. package/get-shit-done/bin/lib/installer-migration-report.cjs +0 -354
  363. package/get-shit-done/bin/lib/installer-migrations/000-first-time-baseline.cjs +0 -220
  364. package/get-shit-done/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +0 -41
  365. package/get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +0 -80
  366. package/get-shit-done/bin/lib/installer-migrations.cjs +0 -778
  367. package/get-shit-done/bin/lib/intel.cjs +0 -708
  368. package/get-shit-done/bin/lib/learnings.cjs +0 -421
  369. package/get-shit-done/bin/lib/milestone.cjs +0 -314
  370. package/get-shit-done/bin/lib/model-catalog.cjs +0 -212
  371. package/get-shit-done/bin/lib/model-profiles.cjs +0 -31
  372. package/get-shit-done/bin/lib/observability/event.cjs +0 -82
  373. package/get-shit-done/bin/lib/observability/logger.cjs +0 -174
  374. package/get-shit-done/bin/lib/phase-command-router.cjs +0 -191
  375. package/get-shit-done/bin/lib/phase-lifecycle.cjs +0 -80
  376. package/get-shit-done/bin/lib/phase.cjs +0 -1607
  377. package/get-shit-done/bin/lib/phases-command-router.cjs +0 -39
  378. package/get-shit-done/bin/lib/planning-workspace.cjs +0 -238
  379. package/get-shit-done/bin/lib/profile-output.cjs +0 -1141
  380. package/get-shit-done/bin/lib/profile-pipeline.cjs +0 -539
  381. package/get-shit-done/bin/lib/project-root.cjs +0 -112
  382. package/get-shit-done/bin/lib/prompt-budget.cjs +0 -399
  383. package/get-shit-done/bin/lib/review-reviewer-selection.cjs +0 -125
  384. package/get-shit-done/bin/lib/roadmap-command-router.cjs +0 -28
  385. package/get-shit-done/bin/lib/roadmap.cjs +0 -650
  386. package/get-shit-done/bin/lib/runtime-artifact-layout.cjs +0 -301
  387. package/get-shit-done/bin/lib/runtime-homes.cjs +0 -222
  388. package/get-shit-done/bin/lib/runtime-name-policy.cjs +0 -83
  389. package/get-shit-done/bin/lib/runtime-slash.cjs +0 -112
  390. package/get-shit-done/bin/lib/secrets.cjs +0 -32
  391. package/get-shit-done/bin/lib/security.cjs +0 -600
  392. package/get-shit-done/bin/lib/semver-compare.cjs +0 -35
  393. package/get-shit-done/bin/lib/shell-command-projection.cjs +0 -500
  394. package/get-shit-done/bin/lib/state-command-router.cjs +0 -252
  395. package/get-shit-done/bin/lib/state.cjs +0 -2038
  396. package/get-shit-done/bin/lib/surface.cjs +0 -470
  397. package/get-shit-done/bin/lib/task-command-router.cjs +0 -81
  398. package/get-shit-done/bin/lib/template.cjs +0 -228
  399. package/get-shit-done/bin/lib/uat.cjs +0 -289
  400. package/get-shit-done/bin/lib/update-context.cjs +0 -209
  401. package/get-shit-done/bin/lib/validate-command-router.cjs +0 -83
  402. package/get-shit-done/bin/lib/validate.cjs +0 -92
  403. package/get-shit-done/bin/lib/verify-command-router.cjs +0 -40
  404. package/get-shit-done/bin/lib/verify.cjs +0 -1511
  405. package/get-shit-done/bin/lib/workstream-inventory.cjs +0 -146
  406. package/get-shit-done/bin/lib/workstream.cjs +0 -389
  407. package/get-shit-done/bin/lib/worktree-safety.cjs +0 -985
  408. package/get-shit-done/workflows/_runtime-launcher.snippet.sh +0 -1
  409. package/scripts/lint-no-source-grep-extras.cjs +0 -81
  410. package/scripts/lint-no-source-grep.cjs +0 -174
  411. package/scripts/lint-shared-module-handsync.cjs +0 -388
  412. package/scripts/shared-module-handsync-allowlist.json +0 -183
  413. /package/{get-shit-done → gsd-core}/bin/shared/runtime-aliases.manifest.json +0 -0
  414. /package/{get-shit-done → gsd-core}/bin/verify-reapply-patches.cjs +0 -0
  415. /package/{get-shit-done → gsd-core}/contexts/dev.md +0 -0
  416. /package/{get-shit-done → gsd-core}/contexts/research.md +0 -0
  417. /package/{get-shit-done → gsd-core}/contexts/review.md +0 -0
  418. /package/{get-shit-done → gsd-core}/references/agent-contracts.md +0 -0
  419. /package/{get-shit-done → gsd-core}/references/ai-evals.md +0 -0
  420. /package/{get-shit-done → gsd-core}/references/ai-frameworks.md +0 -0
  421. /package/{get-shit-done → gsd-core}/references/autonomous-smart-discuss.md +0 -0
  422. /package/{get-shit-done → gsd-core}/references/common-bug-patterns.md +0 -0
  423. /package/{get-shit-done → gsd-core}/references/context-budget.md +0 -0
  424. /package/{get-shit-done → gsd-core}/references/continuation-format.md +0 -0
  425. /package/{get-shit-done → gsd-core}/references/debugger-philosophy.md +0 -0
  426. /package/{get-shit-done → gsd-core}/references/decimal-phase-calculation.md +0 -0
  427. /package/{get-shit-done → gsd-core}/references/doc-conflict-engine.md +0 -0
  428. /package/{get-shit-done → gsd-core}/references/domain-probes.md +0 -0
  429. /package/{get-shit-done → gsd-core}/references/execute-mvp-tdd.md +0 -0
  430. /package/{get-shit-done → gsd-core}/references/executor-examples.md +0 -0
  431. /package/{get-shit-done → gsd-core}/references/gate-prompts.md +0 -0
  432. /package/{get-shit-done → gsd-core}/references/gates.md +0 -0
  433. /package/{get-shit-done → gsd-core}/references/git-integration.md +0 -0
  434. /package/{get-shit-done → gsd-core}/references/git-planning-commit.md +0 -0
  435. /package/{get-shit-done → gsd-core}/references/ios-scaffold.md +0 -0
  436. /package/{get-shit-done → gsd-core}/references/mandatory-initial-read.md +0 -0
  437. /package/{get-shit-done → gsd-core}/references/model-profiles.md +0 -0
  438. /package/{get-shit-done → gsd-core}/references/phase-argument-parsing.md +0 -0
  439. /package/{get-shit-done → gsd-core}/references/planner-antipatterns.md +0 -0
  440. /package/{get-shit-done → gsd-core}/references/planner-chunked.md +0 -0
  441. /package/{get-shit-done → gsd-core}/references/planner-gap-closure.md +0 -0
  442. /package/{get-shit-done → gsd-core}/references/planner-interface-context.md +0 -0
  443. /package/{get-shit-done → gsd-core}/references/planner-reviews.md +0 -0
  444. /package/{get-shit-done → gsd-core}/references/planner-revision.md +0 -0
  445. /package/{get-shit-done → gsd-core}/references/planner-source-audit.md +0 -0
  446. /package/{get-shit-done → gsd-core}/references/planning-config.md +0 -0
  447. /package/{get-shit-done → gsd-core}/references/project-skills-discovery.md +0 -0
  448. /package/{get-shit-done → gsd-core}/references/questioning.md +0 -0
  449. /package/{get-shit-done → gsd-core}/references/revision-loop.md +0 -0
  450. /package/{get-shit-done → gsd-core}/references/scout-codebase.md +0 -0
  451. /package/{get-shit-done → gsd-core}/references/skeleton-template.md +0 -0
  452. /package/{get-shit-done → gsd-core}/references/sketch-interactivity.md +0 -0
  453. /package/{get-shit-done → gsd-core}/references/sketch-theme-system.md +0 -0
  454. /package/{get-shit-done → gsd-core}/references/sketch-tooling.md +0 -0
  455. /package/{get-shit-done → gsd-core}/references/sketch-variant-patterns.md +0 -0
  456. /package/{get-shit-done → gsd-core}/references/spidr-splitting.md +0 -0
  457. /package/{get-shit-done → gsd-core}/references/tdd.md +0 -0
  458. /package/{get-shit-done → gsd-core}/references/thinking-models-debug.md +0 -0
  459. /package/{get-shit-done → gsd-core}/references/thinking-models-execution.md +0 -0
  460. /package/{get-shit-done → gsd-core}/references/thinking-models-planning.md +0 -0
  461. /package/{get-shit-done → gsd-core}/references/thinking-models-research.md +0 -0
  462. /package/{get-shit-done → gsd-core}/references/thinking-models-verification.md +0 -0
  463. /package/{get-shit-done → gsd-core}/references/thinking-partner.md +0 -0
  464. /package/{get-shit-done → gsd-core}/references/universal-anti-patterns.md +0 -0
  465. /package/{get-shit-done → gsd-core}/references/user-profiling.md +0 -0
  466. /package/{get-shit-done → gsd-core}/references/user-story-template.md +0 -0
  467. /package/{get-shit-done → gsd-core}/references/verification-overrides.md +0 -0
  468. /package/{get-shit-done → gsd-core}/references/verify-mvp-mode.md +0 -0
  469. /package/{get-shit-done → gsd-core}/references/workstream-flag.md +0 -0
  470. /package/{get-shit-done → gsd-core}/templates/AI-SPEC.md +0 -0
  471. /package/{get-shit-done → gsd-core}/templates/DEBUG.md +0 -0
  472. /package/{get-shit-done → gsd-core}/templates/SECURITY.md +0 -0
  473. /package/{get-shit-done → gsd-core}/templates/UAT.md +0 -0
  474. /package/{get-shit-done → gsd-core}/templates/UI-SPEC.md +0 -0
  475. /package/{get-shit-done → gsd-core}/templates/VALIDATION.md +0 -0
  476. /package/{get-shit-done → gsd-core}/templates/claude-md.md +0 -0
  477. /package/{get-shit-done → gsd-core}/templates/codebase/architecture.md +0 -0
  478. /package/{get-shit-done → gsd-core}/templates/codebase/concerns.md +0 -0
  479. /package/{get-shit-done → gsd-core}/templates/codebase/conventions.md +0 -0
  480. /package/{get-shit-done → gsd-core}/templates/codebase/integrations.md +0 -0
  481. /package/{get-shit-done → gsd-core}/templates/codebase/stack.md +0 -0
  482. /package/{get-shit-done → gsd-core}/templates/codebase/testing.md +0 -0
  483. /package/{get-shit-done → gsd-core}/templates/config.json +0 -0
  484. /package/{get-shit-done → gsd-core}/templates/context.md +0 -0
  485. /package/{get-shit-done → gsd-core}/templates/continue-here.md +0 -0
  486. /package/{get-shit-done → gsd-core}/templates/debug-subagent-prompt.md +0 -0
  487. /package/{get-shit-done → gsd-core}/templates/dev-preferences.md +0 -0
  488. /package/{get-shit-done → gsd-core}/templates/discovery.md +0 -0
  489. /package/{get-shit-done → gsd-core}/templates/discussion-log.md +0 -0
  490. /package/{get-shit-done → gsd-core}/templates/milestone-archive.md +0 -0
  491. /package/{get-shit-done → gsd-core}/templates/milestone.md +0 -0
  492. /package/{get-shit-done → gsd-core}/templates/planner-subagent-prompt.md +0 -0
  493. /package/{get-shit-done → gsd-core}/templates/project.md +0 -0
  494. /package/{get-shit-done → gsd-core}/templates/requirements.md +0 -0
  495. /package/{get-shit-done → gsd-core}/templates/research-project/ARCHITECTURE.md +0 -0
  496. /package/{get-shit-done → gsd-core}/templates/research-project/FEATURES.md +0 -0
  497. /package/{get-shit-done → gsd-core}/templates/research-project/PITFALLS.md +0 -0
  498. /package/{get-shit-done → gsd-core}/templates/research-project/STACK.md +0 -0
  499. /package/{get-shit-done → gsd-core}/templates/research-project/SUMMARY.md +0 -0
  500. /package/{get-shit-done → gsd-core}/templates/research.md +0 -0
  501. /package/{get-shit-done → gsd-core}/templates/retrospective.md +0 -0
  502. /package/{get-shit-done → gsd-core}/templates/roadmap.md +0 -0
  503. /package/{get-shit-done → gsd-core}/templates/spec.md +0 -0
  504. /package/{get-shit-done → gsd-core}/templates/state.md +0 -0
  505. /package/{get-shit-done → gsd-core}/templates/summary-complex.md +0 -0
  506. /package/{get-shit-done → gsd-core}/templates/summary-minimal.md +0 -0
  507. /package/{get-shit-done → gsd-core}/templates/summary-standard.md +0 -0
  508. /package/{get-shit-done → gsd-core}/templates/summary.md +0 -0
  509. /package/{get-shit-done → gsd-core}/templates/user-profile.md +0 -0
  510. /package/{get-shit-done → gsd-core}/templates/user-setup.md +0 -0
  511. /package/{get-shit-done → gsd-core}/templates/verification-report.md +0 -0
  512. /package/{get-shit-done → gsd-core}/workflows/analyze-dependencies.md +0 -0
  513. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/all.md +0 -0
  514. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/analyze.md +0 -0
  515. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/batch.md +0 -0
  516. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/default.md +0 -0
  517. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/text.md +0 -0
  518. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/checkpoint.json +0 -0
  519. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/context.md +0 -0
  520. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/discussion-log.md +0 -0
  521. /package/{get-shit-done → gsd-core}/workflows/discuss-phase-power.md +0 -0
  522. /package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/per-plan-worktree-gate.md +0 -0
  523. /package/{get-shit-done → gsd-core}/workflows/fast.md +0 -0
  524. /package/{get-shit-done → gsd-core}/workflows/help/modes/brief.md +0 -0
  525. /package/{get-shit-done → gsd-core}/workflows/help/modes/topic.md +0 -0
  526. /package/{get-shit-done → gsd-core}/workflows/help.md +0 -0
  527. /package/{get-shit-done → gsd-core}/workflows/inbox.md +0 -0
  528. /package/{get-shit-done → gsd-core}/workflows/list-phase-assumptions.md +0 -0
  529. /package/{get-shit-done → gsd-core}/workflows/node-repair.md +0 -0
  530. /package/{get-shit-done → gsd-core}/workflows/note.md +0 -0
  531. /package/{get-shit-done → gsd-core}/workflows/pr-branch.md +0 -0
  532. /package/{get-shit-done → gsd-core}/workflows/session-report.md +0 -0
@@ -2,24 +2,27 @@
2
2
  /**
3
3
  * lint-test-file-count.cjs — max 2 test files per production module.
4
4
  *
5
- * Scans sdk/src/query/, sdk/src/, get-shit-done/bin/lib/, bin/ for production
5
+ * Scans sdk/src/query/, sdk/src/, gsd-core/bin/lib/, bin/ for production
6
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 at
8
- * their frozen count (ratchet: may only decrease). --json emits structured output.
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.
9
11
  *
10
12
  * Verdicts: OK_UNDER_LIMIT | OK_IN_ALLOWLIST | FAIL_EXCEEDS_LIMIT |
11
- * FAIL_EXCEEDS_ALLOWLIST | HINT_CAN_REMOVE_FROM_ALLOWLIST
13
+ * FAIL_NOVEL_FILES | FAIL_STALE_ALLOWLIST
12
14
  */
13
15
  'use strict';
14
16
 
15
17
  const fs = require('fs');
16
18
  const path = require('path');
19
+ const { assertWithinAllowlist } = require('./lib/allowlist-ratchet.cjs');
17
20
 
18
21
  const ROOT = path.join(__dirname, '..');
19
22
  const PROD_DIRS = [
20
23
  path.join(ROOT, 'sdk', 'src', 'query'),
21
24
  path.join(ROOT, 'sdk', 'src'),
22
- path.join(ROOT, 'get-shit-done', 'bin', 'lib'),
25
+ path.join(ROOT, 'gsd-core', 'bin', 'lib'),
23
26
  path.join(ROOT, 'bin'),
24
27
  ];
25
28
  const TEST_DIRS = [
@@ -30,11 +33,11 @@ const ALLOWLIST_PATH = path.join(__dirname, 'lint-test-file-count.allowlist.json
30
33
  const MAX_FILES = 2;
31
34
 
32
35
  const Verdict = Object.freeze({
33
- OK_UNDER_LIMIT: 'OK_UNDER_LIMIT',
34
- OK_IN_ALLOWLIST: 'OK_IN_ALLOWLIST',
35
- FAIL_EXCEEDS_LIMIT: 'FAIL_EXCEEDS_LIMIT',
36
- FAIL_EXCEEDS_ALLOWLIST: 'FAIL_EXCEEDS_ALLOWLIST',
37
- HINT_CAN_REMOVE_FROM_ALLOWLIST: 'HINT_CAN_REMOVE_FROM_ALLOWLIST',
36
+ OK_UNDER_LIMIT: 'OK_UNDER_LIMIT',
37
+ OK_IN_ALLOWLIST: 'OK_IN_ALLOWLIST',
38
+ FAIL_EXCEEDS_LIMIT: 'FAIL_EXCEEDS_LIMIT',
39
+ FAIL_NOVEL_FILES: 'FAIL_NOVEL_FILES',
40
+ FAIL_STALE_ALLOWLIST: 'FAIL_STALE_ALLOWLIST',
38
41
  });
39
42
 
40
43
  function isTestFile(name) {
@@ -120,17 +123,62 @@ function loadAllowlist() {
120
123
  catch (_) { return {}; }
121
124
  }
122
125
 
126
+ /**
127
+ * Evaluate one module's test files against the allowlist.
128
+ *
129
+ * For modules under the default cap (≤ MAX_FILES): simple count check.
130
+ * For modules with an allowlist entry: identity check via assertWithinAllowlist.
131
+ * - count now ≤ MAX_FILES → FAIL_STALE_ALLOWLIST (all known files are stale; prune entry)
132
+ * - novel files (in current but not in known) → FAIL_NOVEL_FILES
133
+ * - stale files (in known but not in current) → FAIL_STALE_ALLOWLIST
134
+ * - exact match → OK_IN_ALLOWLIST
135
+ * For modules over the cap with no allowlist entry: FAIL_EXCEEDS_LIMIT.
136
+ *
137
+ * Returns { verdict, prefix, count, knownFiles, novel, stale, files }
138
+ */
123
139
  function evaluateLint({ prefix, testFiles, allowlist }) {
124
140
  const count = testFiles.length;
125
141
  const entry = allowlist[prefix];
126
- const ceiling = entry ? entry.current : null;
142
+ const currentNames = testFiles.map(f => path.basename(f));
143
+
127
144
  if (entry !== undefined) {
128
- if (count <= MAX_FILES) return { verdict: Verdict.HINT_CAN_REMOVE_FROM_ALLOWLIST, prefix, count, ceiling, files: testFiles };
129
- if (count <= ceiling) return { verdict: Verdict.OK_IN_ALLOWLIST, prefix, count, ceiling, files: testFiles };
130
- return { verdict: Verdict.FAIL_EXCEEDS_ALLOWLIST, prefix, count, ceiling, files: testFiles };
145
+ const knownFiles = Array.isArray(entry.files) ? entry.files : [];
146
+ // If the module is now at or under the default cap, the entire allowlist entry is
147
+ // stale and must be removed — this is a ratchet-DOWN failure, not a hint.
148
+ // All known files are stale (the whole entry can go).
149
+ if (count <= MAX_FILES) {
150
+ return {
151
+ verdict: Verdict.FAIL_STALE_ALLOWLIST,
152
+ prefix, count,
153
+ knownFiles,
154
+ novel: [],
155
+ stale: knownFiles.slice().sort(),
156
+ files: testFiles,
157
+ };
158
+ }
159
+ // Identity check via assertWithinAllowlist
160
+ const messages = [];
161
+ const { novel, stale } = assertWithinAllowlist({
162
+ label: prefix,
163
+ current: currentNames,
164
+ known: knownFiles,
165
+ fail: (msg) => messages.push(msg),
166
+ pruneHint: 'scripts/lint-test-file-count.allowlist.json',
167
+ });
168
+
169
+ if (novel.length > 0) {
170
+ return { verdict: Verdict.FAIL_NOVEL_FILES, prefix, count, knownFiles, novel, stale, files: testFiles };
171
+ }
172
+ if (stale.length > 0) {
173
+ return { verdict: Verdict.FAIL_STALE_ALLOWLIST, prefix, count, knownFiles, novel, stale, files: testFiles };
174
+ }
175
+ return { verdict: Verdict.OK_IN_ALLOWLIST, prefix, count, knownFiles, novel: [], stale: [], files: testFiles };
176
+ }
177
+
178
+ if (count <= MAX_FILES) {
179
+ return { verdict: Verdict.OK_UNDER_LIMIT, prefix, count, knownFiles: null, novel: [], stale: [], files: testFiles };
131
180
  }
132
- if (count <= MAX_FILES) return { verdict: Verdict.OK_UNDER_LIMIT, prefix, count, ceiling: null, files: testFiles };
133
- return { verdict: Verdict.FAIL_EXCEEDS_LIMIT, prefix, count, ceiling: null, files: testFiles };
181
+ return { verdict: Verdict.FAIL_EXCEEDS_LIMIT, prefix, count, knownFiles: null, novel: [], stale: [], files: testFiles };
134
182
  }
135
183
 
136
184
  function run() {
@@ -147,35 +195,42 @@ function run() {
147
195
  }
148
196
 
149
197
  const failures = results.filter(r =>
150
- r.verdict === Verdict.FAIL_EXCEEDS_LIMIT || r.verdict === Verdict.FAIL_EXCEEDS_ALLOWLIST);
151
- const hints = results.filter(r => r.verdict === Verdict.HINT_CAN_REMOVE_FROM_ALLOWLIST);
198
+ r.verdict === Verdict.FAIL_EXCEEDS_LIMIT ||
199
+ r.verdict === Verdict.FAIL_NOVEL_FILES ||
200
+ r.verdict === Verdict.FAIL_STALE_ALLOWLIST);
152
201
 
153
202
  if (jsonMode) {
154
- console.log(JSON.stringify({ ok: failures.length === 0, results, failures, hints }, null, 2));
203
+ console.log(JSON.stringify({ ok: failures.length === 0, results, failures, hints: [] }, null, 2));
155
204
  process.exit(failures.length > 0 ? 1 : 0);
156
205
  }
157
206
 
158
207
  if (failures.length === 0) {
159
208
  const inAllowlist = results.filter(r => r.verdict === Verdict.OK_IN_ALLOWLIST).length;
160
209
  console.log(`ok lint-test-file-count: ${results.length} module(s) checked, 0 failures` +
161
- (inAllowlist > 0 ? `, ${inAllowlist} allowlisted` : '') +
162
- (hints.length > 0 ? `, ${hints.length} hint(s)` : ''));
163
- for (const h of hints) {
164
- console.log(` hint: "${h.prefix}" is allowlisted at ${h.ceiling} but now has ${h.count} — remove from allowlist`);
165
- }
210
+ (inAllowlist > 0 ? `, ${inAllowlist} allowlisted` : ''));
166
211
  process.exit(0);
167
212
  }
168
213
 
169
214
  process.stderr.write(`\nERROR lint-test-file-count: ${failures.length} module(s) exceed the test-file limit\n\n`);
170
215
  for (const f of failures) {
171
- const tag = f.verdict === Verdict.FAIL_EXCEEDS_LIMIT
172
- ? `${f.count} files (limit ${MAX_FILES})`
173
- : `${f.count} files (allowlist ceiling ${f.ceiling})`;
174
- process.stderr.write(` ${f.prefix}: ${tag}\n`);
175
- for (const tf of f.files) process.stderr.write(` ${path.relative(ROOT, tf)}\n`);
216
+ if (f.verdict === Verdict.FAIL_EXCEEDS_LIMIT) {
217
+ process.stderr.write(` ${f.prefix}: ${f.count} files (limit ${MAX_FILES}) — not in allowlist\n`);
218
+ for (const tf of f.files) process.stderr.write(` ${path.relative(ROOT, tf)}\n`);
219
+ } else if (f.verdict === Verdict.FAIL_NOVEL_FILES) {
220
+ process.stderr.write(` ${f.prefix}: ${f.novel.length} NEW test file(s) not in allowlist\n`);
221
+ for (const n of f.novel) process.stderr.write(` + ${n}\n`);
222
+ } else if (f.verdict === Verdict.FAIL_STALE_ALLOWLIST) {
223
+ if (f.count <= MAX_FILES) {
224
+ const staleList = f.stale.join(', ');
225
+ process.stderr.write(` "${f.prefix}": now at ${f.count} file(s) (≤ ${MAX_FILES}) — remove its entry from the allowlist (stale: ${staleList})\n`);
226
+ } else {
227
+ process.stderr.write(` ${f.prefix}: ${f.stale.length} allowlisted file(s) no longer present — prune allowlist\n`);
228
+ for (const s of f.stale) process.stderr.write(` - ${s}\n`);
229
+ }
230
+ }
176
231
  }
177
232
  process.stderr.write('\nFix: consolidate test files per module (one primary + one integration).\n');
178
- process.stderr.write('Or add the module to scripts/lint-test-file-count.allowlist.json with PR justification.\n\n');
233
+ process.stderr.write('Or update scripts/lint-test-file-count.allowlist.json with PR justification.\n\n');
179
234
  process.exit(1);
180
235
  }
181
236
 
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * scripts/mutation-matrix.cjs
6
+ *
7
+ * Single source of truth for the ADR-457 Stryker mutation gate dynamic matrix.
8
+ *
9
+ * Computes which covered modules changed vs a base ref and emits a GitHub
10
+ * Actions matrix JSON so CI can run one Stryker shard per changed module in
11
+ * parallel rather than a single serial run over all modules.
12
+ *
13
+ * Usage:
14
+ * node scripts/mutation-matrix.cjs --base origin/next
15
+ * printf 'src/config-schema.cts\n' | node scripts/mutation-matrix.cjs
16
+ * node scripts/mutation-matrix.cjs --base origin/next --print
17
+ *
18
+ * Output (stdout, default): JSON object
19
+ * {
20
+ * "has_work": "true"|"false",
21
+ * "matrix": {
22
+ * "include": [
23
+ * { "name": "<module>", "mutate": "gsd-core/bin/lib/<module>.cjs", "tests": "<space-joined test files>" },
24
+ * ...
25
+ * ]
26
+ * }
27
+ * }
28
+ *
29
+ * Exit codes: 0 always (empty matrix is not an error, has_work "false").
30
+ */
31
+
32
+ const { execFileSync } = require('child_process');
33
+ const { readFileSync } = require('fs');
34
+
35
+ // ── Single source of truth: covered modules ───────────────────────────────────
36
+ // Each entry: { cjs: '<built artifact>', tests: ['tests/...', ...] }
37
+ // A module is "covered" iff its tests are wired into the Stryker command runner
38
+ // (stryker.config.mjs commandRunner.command). Mutating an uncovered module can
39
+ // only ever produce survived mutants — so we scope strictly to these 6.
40
+ const COVERED = {
41
+ 'context-utilization': {
42
+ cjs: 'gsd-core/bin/lib/context-utilization.cjs',
43
+ tests: [
44
+ 'tests/context-utilization.property.test.cjs',
45
+ ],
46
+ },
47
+ 'prompt-budget': {
48
+ cjs: 'gsd-core/bin/lib/prompt-budget.cjs',
49
+ tests: [
50
+ 'tests/prompt-budget.property.test.cjs',
51
+ 'tests/prompt-budget.unit.test.cjs',
52
+ ],
53
+ },
54
+ frontmatter: {
55
+ cjs: 'gsd-core/bin/lib/frontmatter.cjs',
56
+ tests: [
57
+ 'tests/frontmatter.property.test.cjs',
58
+ 'tests/frontmatter.unit.test.cjs',
59
+ ],
60
+ },
61
+ 'adr-parser': {
62
+ cjs: 'gsd-core/bin/lib/adr-parser.cjs',
63
+ tests: [
64
+ 'tests/adr-parser.property.test.cjs',
65
+ 'tests/adr-parser.test.cjs',
66
+ 'tests/adr-parser.unit.test.cjs',
67
+ ],
68
+ },
69
+ 'config-schema': {
70
+ cjs: 'gsd-core/bin/lib/config-schema.cjs',
71
+ tests: [
72
+ 'tests/config-schema.property.test.cjs',
73
+ ],
74
+ },
75
+ 'active-workstream-store': {
76
+ cjs: 'gsd-core/bin/lib/active-workstream-store.cjs',
77
+ tests: [
78
+ 'tests/active-workstream-store.test.cjs',
79
+ 'tests/active-workstream-store.unit.test.cjs',
80
+ ],
81
+ },
82
+ };
83
+
84
+ // ── Files that, when changed, invalidate ALL modules ─────────────────────────
85
+ // Changes to the Stryker config, this script itself, or any covered test file
86
+ // affect all mutation scores and must force a full re-run.
87
+ const GLOBAL_TRIGGERS = new Set([
88
+ 'stryker.config.mjs',
89
+ 'scripts/mutation-matrix.cjs',
90
+ ]);
91
+
92
+ // Also flag all test files that belong to any covered module as global triggers.
93
+ for (const mod of Object.values(COVERED)) {
94
+ for (const t of mod.tests) {
95
+ GLOBAL_TRIGGERS.add(t);
96
+ }
97
+ }
98
+
99
+ // ── Argument parsing ──────────────────────────────────────────────────────────
100
+ function parseArgs(argv) {
101
+ const out = { base: null, print: false };
102
+ for (let i = 0; i < argv.length; i++) {
103
+ const arg = argv[i];
104
+ if (arg === '--base') {
105
+ out.base = argv[++i];
106
+ if (!out.base || out.base.startsWith('--')) {
107
+ throw new Error('--base requires a value');
108
+ }
109
+ } else if (arg.startsWith('--base=')) {
110
+ out.base = arg.slice('--base='.length);
111
+ if (!out.base) throw new Error('--base requires a value');
112
+ } else if (arg === '--print') {
113
+ out.print = true;
114
+ } else if (arg === '--help' || arg === '-h') {
115
+ console.log([
116
+ 'Usage:',
117
+ ' node scripts/mutation-matrix.cjs --base <ref> [--print]',
118
+ ' printf "src/foo.cts\\n" | node scripts/mutation-matrix.cjs [--print]',
119
+ '',
120
+ 'Options:',
121
+ ' --base <ref> Git ref to diff against (default: origin/${GITHUB_BASE_REF:-next})',
122
+ ' --print Human-readable output instead of JSON',
123
+ ].join('\n'));
124
+ process.exit(0);
125
+ } else {
126
+ throw new Error(`unknown argument: ${arg}`);
127
+ }
128
+ }
129
+ return out;
130
+ }
131
+
132
+ // ── Changed-file resolution ───────────────────────────────────────────────────
133
+ function resolveChangedFiles(args) {
134
+ // When --base is provided, always use git diff (regardless of stdin).
135
+ // When --base is absent AND stdin is not a TTY (isTTY is falsy / undefined),
136
+ // read a newline-delimited file list from stdin.
137
+ if (!args.base && process.stdin.isTTY !== true) {
138
+ const raw = readFileSync(process.stdin.fd, 'utf8');
139
+ return raw.split('\n').map(l => l.trim()).filter(Boolean);
140
+ }
141
+
142
+ // Otherwise (--base given, or stdin is a real TTY), diff against the base ref.
143
+ const defaultBase = `origin/${process.env.GITHUB_BASE_REF || 'next'}`;
144
+ const base = args.base || defaultBase;
145
+ const stdout = execFileSync('git', ['diff', '--name-only', `${base}...HEAD`], {
146
+ encoding: 'utf8',
147
+ });
148
+ return stdout.split('\n').map(l => l.trim()).filter(Boolean);
149
+ }
150
+
151
+ // ── Module classification ─────────────────────────────────────────────────────
152
+ function computeMatrix(changedFiles) {
153
+ // Check for global triggers first — if any hit, include every covered module.
154
+ const allModuleNames = Object.keys(COVERED);
155
+ for (const f of changedFiles) {
156
+ if (GLOBAL_TRIGGERS.has(f)) {
157
+ return allModuleNames;
158
+ }
159
+ }
160
+
161
+ // Otherwise find which modules have their src/*.cts changed.
162
+ const changed = new Set();
163
+ for (const f of changedFiles) {
164
+ // Match src/<module>.cts (top-level src/, not nested)
165
+ const m = f.match(/^src\/([^/]+)\.cts$/);
166
+ if (m && COVERED[m[1]]) {
167
+ changed.add(m[1]);
168
+ }
169
+ }
170
+ return [...changed];
171
+ }
172
+
173
+ // ── Output formatting ─────────────────────────────────────────────────────────
174
+ function buildResult(moduleNames) {
175
+ const include = moduleNames.map(name => ({
176
+ name,
177
+ mutate: COVERED[name].cjs,
178
+ tests: COVERED[name].tests.join(' '),
179
+ }));
180
+
181
+ return {
182
+ has_work: include.length > 0 ? 'true' : 'false',
183
+ matrix: { include },
184
+ };
185
+ }
186
+
187
+ function printHuman(result, changedFiles) {
188
+ console.log(`Changed files (${changedFiles.length}):`);
189
+ for (const f of changedFiles) console.log(` ${f}`);
190
+ console.log('');
191
+ console.log(`has_work: ${result.has_work}`);
192
+ console.log(`Shards (${result.matrix.include.length}):`);
193
+ for (const shard of result.matrix.include) {
194
+ console.log(` [${shard.name}]`);
195
+ console.log(` mutate: ${shard.mutate}`);
196
+ console.log(` tests: ${shard.tests}`);
197
+ }
198
+ }
199
+
200
+ // ── Main ──────────────────────────────────────────────────────────────────────
201
+ function main() {
202
+ try {
203
+ const args = parseArgs(process.argv.slice(2));
204
+ const changedFiles = resolveChangedFiles(args);
205
+ const moduleNames = computeMatrix(changedFiles);
206
+ const result = buildResult(moduleNames);
207
+
208
+ if (args.print) {
209
+ printHuman(result, changedFiles);
210
+ } else {
211
+ console.log(JSON.stringify(result, null, 2));
212
+ }
213
+ } catch (err) {
214
+ console.error(`mutation-matrix: ${err.message}`);
215
+ process.exit(2);
216
+ }
217
+ }
218
+
219
+ main();
@@ -73,13 +73,17 @@ ALLOWLIST=(
73
73
  'tests/security.test.cjs'
74
74
  'tests/prompt-injection-scan.test.cjs'
75
75
  'tests/verify.test.cjs'
76
- 'get-shit-done/bin/lib/security.cjs'
76
+ 'gsd-core/bin/lib/security.cjs'
77
77
  'hooks/gsd-prompt-guard.js'
78
78
  'hooks/gsd-read-injection-scanner.js'
79
79
  'tests/read-injection-scanner.test.cjs'
80
80
  'tests/security-prompt-injection.test.cjs'
81
81
  'tests/fixtures/adversarial/security/'
82
82
  'SECURITY.md'
83
+ # These files contain intentional injection examples / security-model prose
84
+ # and are not attack vectors — they explain/demonstrate injection patterns.
85
+ 'TEST-EXAMPLES.md'
86
+ 'docs/explanation/security-model.md'
83
87
  )
84
88
 
85
89
  is_allowlisted() {
@@ -0,0 +1,256 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const os = require('os');
5
+ const fs = require('fs');
6
+ const { execFileSync } = require('child_process');
7
+
8
+ /**
9
+ * Classify a What's-Changed bullet line into 'Feature', 'Fix', or 'Enhancement'.
10
+ * @param {string} bulletLine - Full bullet line including the leading `* ` or `- ` marker.
11
+ * @returns {'Feature'|'Fix'|'Enhancement'}
12
+ */
13
+ function classifyTitle(bulletLine) {
14
+ // Strip leading `* ` or `- ` marker
15
+ const withoutMarker = bulletLine.replace(/^[*-]\s+/, '');
16
+
17
+ // Extract title = text before ` by @`
18
+ const byIdx = withoutMarker.indexOf(' by @');
19
+ const title = (byIdx !== -1 ? withoutMarker.slice(0, byIdx) : withoutMarker).trim();
20
+
21
+ if (/^feat(?:ure)?\s*(?:\(|!|:)/i.test(title)) return 'Feature';
22
+ if (/^fix\s*(?:\(|!|:)/i.test(title)) return 'Fix';
23
+ return 'Enhancement';
24
+ }
25
+
26
+ /**
27
+ * Reformat GitHub's auto-generated release notes into the repo's hand-curated format.
28
+ *
29
+ * @param {object} opts
30
+ * @param {string} opts.generatedBody - The raw GitHub-generated release body.
31
+ * @param {string} opts.version - Version string (e.g. "1.3.0-rc.1"), no leading "v".
32
+ * @param {boolean} opts.prerelease - Whether this is a pre-release.
33
+ * @param {string} opts.packageName - npm package name (e.g. "@opengsd/gsd-core").
34
+ * @returns {string} Formatted release body (no trailing newline).
35
+ */
36
+ function formatReleaseNotes({ generatedBody, version, prerelease, packageName }) {
37
+ const lines = generatedBody.split('\n');
38
+
39
+ const featureBullets = [];
40
+ const fixBullets = [];
41
+ const enhancementBullets = [];
42
+ const newContributorBullets = [];
43
+ let fullChangelogLine = null;
44
+
45
+ let inWhatsChanged = false;
46
+ let inNewContributors = false;
47
+
48
+ for (const line of lines) {
49
+ const trimmed = line.trim();
50
+
51
+ // Detect section headings
52
+ if (trimmed === '## What\'s Changed') {
53
+ inWhatsChanged = true;
54
+ inNewContributors = false;
55
+ continue;
56
+ }
57
+
58
+ if (trimmed === '## New Contributors') {
59
+ inWhatsChanged = false;
60
+ inNewContributors = true;
61
+ continue;
62
+ }
63
+
64
+ // Full changelog line ends the What's Changed section
65
+ if (trimmed.startsWith('**Full Changelog**:')) {
66
+ inWhatsChanged = false;
67
+ inNewContributors = false;
68
+ fullChangelogLine = trimmed;
69
+ continue;
70
+ }
71
+
72
+ // Any other `##` heading ends current section
73
+ if (trimmed.startsWith('## ')) {
74
+ inWhatsChanged = false;
75
+ inNewContributors = false;
76
+ continue;
77
+ }
78
+
79
+ // Collect bullets
80
+ if (inWhatsChanged && (trimmed.startsWith('* ') || trimmed.startsWith('- '))) {
81
+ const category = classifyTitle(trimmed);
82
+ if (category === 'Feature') featureBullets.push(trimmed);
83
+ else if (category === 'Fix') fixBullets.push(trimmed);
84
+ else enhancementBullets.push(trimmed);
85
+ continue;
86
+ }
87
+
88
+ if (inNewContributors && (trimmed.startsWith('* ') || trimmed.startsWith('- '))) {
89
+ newContributorBullets.push(trimmed);
90
+ continue;
91
+ }
92
+ }
93
+
94
+ // Build Install block
95
+ let installBlock;
96
+ if (prerelease) {
97
+ installBlock = [
98
+ '## Install',
99
+ '',
100
+ 'This pre-release is published to npm under the `next` dist-tag.',
101
+ '',
102
+ '```bash',
103
+ `npm i ${packageName}@${version}`,
104
+ '# or',
105
+ `npm i ${packageName}@next`,
106
+ '```',
107
+ ].join('\n');
108
+ } else {
109
+ installBlock = [
110
+ '## Install',
111
+ '',
112
+ '```bash',
113
+ `npm i ${packageName}@${version}`,
114
+ '# or',
115
+ `npm i ${packageName}@latest`,
116
+ '```',
117
+ ].join('\n');
118
+ }
119
+
120
+ // Assemble groups (omit empty ones)
121
+ const groups = [];
122
+
123
+ // Group A: Install
124
+ groups.push(installBlock);
125
+
126
+ // Group B: What's Changed heading
127
+ groups.push('## What\'s Changed');
128
+
129
+ // Group C: Features
130
+ if (featureBullets.length > 0) {
131
+ groups.push('### Feature\n' + featureBullets.join('\n'));
132
+ }
133
+
134
+ // Group D: Enhancements
135
+ if (enhancementBullets.length > 0) {
136
+ groups.push('### Enhancement\n' + enhancementBullets.join('\n'));
137
+ }
138
+
139
+ // Group E: Fixes
140
+ if (fixBullets.length > 0) {
141
+ groups.push('### Fix\n' + fixBullets.join('\n'));
142
+ }
143
+
144
+ // Group F: New Contributors
145
+ if (newContributorBullets.length > 0) {
146
+ groups.push('## New Contributors\n' + newContributorBullets.join('\n'));
147
+ }
148
+
149
+ // Group G: Full Changelog
150
+ if (fullChangelogLine) {
151
+ groups.push(fullChangelogLine);
152
+ }
153
+
154
+ return groups.join('\n\n');
155
+ }
156
+
157
+ // CLI entry point
158
+ if (require.main === module) {
159
+ try {
160
+ const argv = process.argv.slice(2);
161
+
162
+ let tag = null;
163
+ let repo = null;
164
+ let packageName = null;
165
+ let prerelease = null;
166
+ let useStdin = false;
167
+ let doApply = false;
168
+
169
+ for (let i = 0; i < argv.length; i++) {
170
+ const arg = argv[i];
171
+ if (arg === '--tag') {
172
+ tag = argv[++i];
173
+ } else if (arg === '--repo') {
174
+ repo = argv[++i];
175
+ } else if (arg === '--package') {
176
+ packageName = argv[++i];
177
+ } else if (arg === '--prerelease') {
178
+ prerelease = true;
179
+ } else if (arg === '--latest') {
180
+ prerelease = false;
181
+ } else if (arg === '--stdin') {
182
+ useStdin = true;
183
+ } else if (arg === '--apply') {
184
+ doApply = true;
185
+ }
186
+ }
187
+
188
+ // Derive version from tag
189
+ const version = tag ? tag.replace(/^v/, '') : null;
190
+
191
+ // Resolve package name if not provided
192
+ if (!packageName) {
193
+ const repoRoot = path.resolve(__dirname, '..', '..');
194
+ const pkgJson = JSON.parse(fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8'));
195
+ packageName = pkgJson.name;
196
+ }
197
+
198
+ let generatedBody;
199
+
200
+ if (useStdin) {
201
+ // Read from stdin
202
+ if (!version) {
203
+ throw new Error('--stdin mode requires --tag or --version to derive version');
204
+ }
205
+ if (prerelease === null) {
206
+ throw new Error('--stdin mode requires --prerelease or --latest');
207
+ }
208
+ generatedBody = fs.readFileSync('/dev/stdin', 'utf8');
209
+ } else {
210
+ // Fetch from gh
211
+ if (!tag) {
212
+ throw new Error('--tag <tag> is required');
213
+ }
214
+
215
+ const ghArgs = ['release', 'view', tag, '--json', 'body', '-q', '.body'];
216
+ if (repo) ghArgs.push('--repo', repo);
217
+
218
+ generatedBody = execFileSync('gh', ghArgs, { encoding: 'utf8' });
219
+
220
+ // Determine prerelease if not forced
221
+ if (prerelease === null) {
222
+ try {
223
+ const ghPreArgs = ['release', 'view', tag, '--json', 'isPrerelease', '-q', '.isPrerelease'];
224
+ if (repo) ghPreArgs.push('--repo', repo);
225
+ const result = execFileSync('gh', ghPreArgs, { encoding: 'utf8' }).trim();
226
+ prerelease = result === 'true';
227
+ } catch (_e) {
228
+ // Final fallback: check if tag contains `-` after version digits
229
+ prerelease = /-/.test(version);
230
+ }
231
+ }
232
+ }
233
+
234
+ const formatted = formatReleaseNotes({ generatedBody, version, prerelease, packageName });
235
+
236
+ if (doApply) {
237
+ const tmpFile = path.join(os.tmpdir(), `release-notes-${Date.now()}.md`);
238
+ fs.writeFileSync(tmpFile, formatted, 'utf8');
239
+ try {
240
+ const ghArgs = ['release', 'edit', tag, '--notes-file', tmpFile];
241
+ if (repo) ghArgs.push('--repo', repo);
242
+ execFileSync('gh', ghArgs, { encoding: 'utf8' });
243
+ process.stderr.write(`Release notes updated for ${tag}\n`);
244
+ } finally {
245
+ fs.unlinkSync(tmpFile);
246
+ }
247
+ } else {
248
+ process.stdout.write(formatted + '\n');
249
+ }
250
+ } catch (err) {
251
+ process.stderr.write((err.message || String(err)) + '\n');
252
+ process.exit(1);
253
+ }
254
+ }
255
+
256
+ module.exports = { formatReleaseNotes, classifyTitle };