@opengsd/gsd-core 1.2.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (503) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja-JP.md +870 -0
  3. package/README.ko-KR.md +861 -0
  4. package/README.md +301 -0
  5. package/README.pt-BR.md +492 -0
  6. package/README.zh-CN.md +842 -0
  7. package/agents/gsd-advisor-researcher.md +127 -0
  8. package/agents/gsd-ai-researcher.md +133 -0
  9. package/agents/gsd-assumptions-analyzer.md +105 -0
  10. package/agents/gsd-code-fixer.md +668 -0
  11. package/agents/gsd-code-reviewer.md +387 -0
  12. package/agents/gsd-codebase-mapper.md +853 -0
  13. package/agents/gsd-debug-session-manager.md +314 -0
  14. package/agents/gsd-debugger.md +1452 -0
  15. package/agents/gsd-doc-classifier.md +168 -0
  16. package/agents/gsd-doc-synthesizer.md +204 -0
  17. package/agents/gsd-doc-verifier.md +217 -0
  18. package/agents/gsd-doc-writer.md +615 -0
  19. package/agents/gsd-domain-researcher.md +153 -0
  20. package/agents/gsd-eval-auditor.md +191 -0
  21. package/agents/gsd-eval-planner.md +154 -0
  22. package/agents/gsd-executor.md +772 -0
  23. package/agents/gsd-framework-selector.md +160 -0
  24. package/agents/gsd-integration-checker.md +470 -0
  25. package/agents/gsd-intel-updater.md +342 -0
  26. package/agents/gsd-nyquist-auditor.md +203 -0
  27. package/agents/gsd-pattern-mapper.md +335 -0
  28. package/agents/gsd-phase-researcher.md +928 -0
  29. package/agents/gsd-plan-checker.md +978 -0
  30. package/agents/gsd-planner.md +1218 -0
  31. package/agents/gsd-project-researcher.md +677 -0
  32. package/agents/gsd-research-synthesizer.md +255 -0
  33. package/agents/gsd-roadmapper.md +688 -0
  34. package/agents/gsd-security-auditor.md +155 -0
  35. package/agents/gsd-ui-auditor.md +495 -0
  36. package/agents/gsd-ui-checker.md +309 -0
  37. package/agents/gsd-ui-researcher.md +380 -0
  38. package/agents/gsd-user-profiler.md +171 -0
  39. package/agents/gsd-verifier.md +917 -0
  40. package/bin/install.js +10936 -0
  41. package/bin/lib/ui-safety-gate.cjs +107 -0
  42. package/commands/gsd/add-tests.md +42 -0
  43. package/commands/gsd/ai-integration-phase.md +37 -0
  44. package/commands/gsd/audit-fix.md +34 -0
  45. package/commands/gsd/audit-milestone.md +37 -0
  46. package/commands/gsd/audit-uat.md +24 -0
  47. package/commands/gsd/autonomous.md +46 -0
  48. package/commands/gsd/capture.md +62 -0
  49. package/commands/gsd/cleanup.md +24 -0
  50. package/commands/gsd/code-review.md +59 -0
  51. package/commands/gsd/complete-milestone.md +143 -0
  52. package/commands/gsd/config.md +56 -0
  53. package/commands/gsd/debug.md +52 -0
  54. package/commands/gsd/discuss-phase.md +76 -0
  55. package/commands/gsd/docs-update.md +49 -0
  56. package/commands/gsd/eval-review.md +33 -0
  57. package/commands/gsd/execute-phase.md +64 -0
  58. package/commands/gsd/explore.md +27 -0
  59. package/commands/gsd/extract-learnings.md +23 -0
  60. package/commands/gsd/fast.md +31 -0
  61. package/commands/gsd/forensics.md +57 -0
  62. package/commands/gsd/graphify.md +199 -0
  63. package/commands/gsd/health.md +31 -0
  64. package/commands/gsd/help.md +28 -0
  65. package/commands/gsd/import.md +41 -0
  66. package/commands/gsd/inbox.md +39 -0
  67. package/commands/gsd/ingest-docs.md +42 -0
  68. package/commands/gsd/manager.md +45 -0
  69. package/commands/gsd/map-codebase.md +83 -0
  70. package/commands/gsd/milestone-summary.md +51 -0
  71. package/commands/gsd/mvp-phase.md +45 -0
  72. package/commands/gsd/new-milestone.md +45 -0
  73. package/commands/gsd/new-project.md +47 -0
  74. package/commands/gsd/ns-context.md +23 -0
  75. package/commands/gsd/ns-ideate.md +24 -0
  76. package/commands/gsd/ns-manage.md +29 -0
  77. package/commands/gsd/ns-project.md +22 -0
  78. package/commands/gsd/ns-review.md +26 -0
  79. package/commands/gsd/ns-workflow.md +28 -0
  80. package/commands/gsd/pause-work.md +43 -0
  81. package/commands/gsd/phase.md +56 -0
  82. package/commands/gsd/plan-phase.md +62 -0
  83. package/commands/gsd/plan-review-convergence.md +59 -0
  84. package/commands/gsd/pr-branch.md +26 -0
  85. package/commands/gsd/profile-user.md +46 -0
  86. package/commands/gsd/progress.md +47 -0
  87. package/commands/gsd/quick.md +174 -0
  88. package/commands/gsd/resume-work.md +30 -0
  89. package/commands/gsd/review-backlog.md +63 -0
  90. package/commands/gsd/review.md +41 -0
  91. package/commands/gsd/secure-phase.md +36 -0
  92. package/commands/gsd/settings.md +29 -0
  93. package/commands/gsd/ship.md +24 -0
  94. package/commands/gsd/sketch.md +60 -0
  95. package/commands/gsd/spec-phase.md +63 -0
  96. package/commands/gsd/spike.md +57 -0
  97. package/commands/gsd/stats.md +19 -0
  98. package/commands/gsd/surface.md +155 -0
  99. package/commands/gsd/thread.md +24 -0
  100. package/commands/gsd/ui-phase.md +35 -0
  101. package/commands/gsd/ui-review.md +33 -0
  102. package/commands/gsd/ultraplan-phase.md +34 -0
  103. package/commands/gsd/undo.md +35 -0
  104. package/commands/gsd/update.md +48 -0
  105. package/commands/gsd/validate-phase.md +36 -0
  106. package/commands/gsd/verify-work.md +39 -0
  107. package/commands/gsd/workspace.md +52 -0
  108. package/commands/gsd/workstreams.md +70 -0
  109. package/get-shit-done/bin/check-latest-version.cjs +106 -0
  110. package/get-shit-done/bin/gsd-tools.cjs +1676 -0
  111. package/get-shit-done/bin/lib/active-workstream-store.cjs +302 -0
  112. package/get-shit-done/bin/lib/adr-parser.cjs +394 -0
  113. package/get-shit-done/bin/lib/agent-command-router.cjs +65 -0
  114. package/get-shit-done/bin/lib/artifacts.cjs +53 -0
  115. package/get-shit-done/bin/lib/audit.cjs +755 -0
  116. package/get-shit-done/bin/lib/check-command-router.cjs +333 -0
  117. package/get-shit-done/bin/lib/cjs-command-router-adapter.cjs +118 -0
  118. package/get-shit-done/bin/lib/clock.cjs +96 -0
  119. package/get-shit-done/bin/lib/clusters.cjs +135 -0
  120. package/get-shit-done/bin/lib/code-review-flags.cjs +74 -0
  121. package/get-shit-done/bin/lib/command-aliases.cjs +815 -0
  122. package/get-shit-done/bin/lib/command-arg-projection.cjs +62 -0
  123. package/get-shit-done/bin/lib/command-routing-hub.cjs +388 -0
  124. package/get-shit-done/bin/lib/commands.cjs +1188 -0
  125. package/get-shit-done/bin/lib/config-schema.cjs +31 -0
  126. package/get-shit-done/bin/lib/config.cjs +728 -0
  127. package/get-shit-done/bin/lib/configuration.cjs +248 -0
  128. package/get-shit-done/bin/lib/context-utilization.cjs +47 -0
  129. package/get-shit-done/bin/lib/core.cjs +2121 -0
  130. package/get-shit-done/bin/lib/decisions.cjs +116 -0
  131. package/get-shit-done/bin/lib/docs.cjs +270 -0
  132. package/get-shit-done/bin/lib/drift.cjs +388 -0
  133. package/get-shit-done/bin/lib/fallow-runner.cjs +109 -0
  134. package/get-shit-done/bin/lib/frontmatter.cjs +389 -0
  135. package/get-shit-done/bin/lib/gap-checker.cjs +205 -0
  136. package/get-shit-done/bin/lib/graphify.cjs +592 -0
  137. package/get-shit-done/bin/lib/gsd2-import.cjs +514 -0
  138. package/get-shit-done/bin/lib/init-command-router.cjs +58 -0
  139. package/get-shit-done/bin/lib/init.cjs +2112 -0
  140. package/get-shit-done/bin/lib/install-profiles.cjs +603 -0
  141. package/get-shit-done/bin/lib/installer-migration-authoring.cjs +117 -0
  142. package/get-shit-done/bin/lib/installer-migration-report.cjs +354 -0
  143. package/get-shit-done/bin/lib/installer-migrations/000-first-time-baseline.cjs +220 -0
  144. package/get-shit-done/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +41 -0
  145. package/get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +80 -0
  146. package/get-shit-done/bin/lib/installer-migrations.cjs +778 -0
  147. package/get-shit-done/bin/lib/intel.cjs +708 -0
  148. package/get-shit-done/bin/lib/learnings.cjs +421 -0
  149. package/get-shit-done/bin/lib/milestone.cjs +314 -0
  150. package/get-shit-done/bin/lib/model-catalog.cjs +212 -0
  151. package/get-shit-done/bin/lib/model-profiles.cjs +31 -0
  152. package/get-shit-done/bin/lib/observability/event.cjs +82 -0
  153. package/get-shit-done/bin/lib/observability/logger.cjs +174 -0
  154. package/get-shit-done/bin/lib/observability/redaction.cjs +50 -0
  155. package/get-shit-done/bin/lib/package-identity.cjs +31 -0
  156. package/get-shit-done/bin/lib/phase-command-router.cjs +191 -0
  157. package/get-shit-done/bin/lib/phase-lifecycle.cjs +80 -0
  158. package/get-shit-done/bin/lib/phase.cjs +1607 -0
  159. package/get-shit-done/bin/lib/phases-command-router.cjs +39 -0
  160. package/get-shit-done/bin/lib/plan-scan.cjs +97 -0
  161. package/get-shit-done/bin/lib/planning-workspace.cjs +238 -0
  162. package/get-shit-done/bin/lib/profile-output.cjs +1141 -0
  163. package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
  164. package/get-shit-done/bin/lib/project-root.cjs +112 -0
  165. package/get-shit-done/bin/lib/prompt-budget.cjs +399 -0
  166. package/get-shit-done/bin/lib/review-reviewer-selection.cjs +125 -0
  167. package/get-shit-done/bin/lib/roadmap-command-router.cjs +28 -0
  168. package/get-shit-done/bin/lib/roadmap.cjs +650 -0
  169. package/get-shit-done/bin/lib/runtime-artifact-layout.cjs +301 -0
  170. package/get-shit-done/bin/lib/runtime-homes.cjs +222 -0
  171. package/get-shit-done/bin/lib/runtime-name-policy.cjs +83 -0
  172. package/get-shit-done/bin/lib/runtime-slash.cjs +112 -0
  173. package/get-shit-done/bin/lib/schema-detect.cjs +165 -0
  174. package/get-shit-done/bin/lib/secrets.cjs +32 -0
  175. package/get-shit-done/bin/lib/security.cjs +600 -0
  176. package/get-shit-done/bin/lib/semver-compare.cjs +35 -0
  177. package/get-shit-done/bin/lib/shell-command-projection.cjs +500 -0
  178. package/get-shit-done/bin/lib/state-command-router.cjs +252 -0
  179. package/get-shit-done/bin/lib/state-document.cjs +263 -0
  180. package/get-shit-done/bin/lib/state.cjs +2038 -0
  181. package/get-shit-done/bin/lib/surface.cjs +470 -0
  182. package/get-shit-done/bin/lib/task-command-router.cjs +81 -0
  183. package/get-shit-done/bin/lib/template.cjs +228 -0
  184. package/get-shit-done/bin/lib/uat.cjs +289 -0
  185. package/get-shit-done/bin/lib/update-context.cjs +209 -0
  186. package/get-shit-done/bin/lib/validate-command-router.cjs +83 -0
  187. package/get-shit-done/bin/lib/validate.cjs +92 -0
  188. package/get-shit-done/bin/lib/verify-command-router.cjs +40 -0
  189. package/get-shit-done/bin/lib/verify.cjs +1511 -0
  190. package/get-shit-done/bin/lib/workstream-inventory-builder.cjs +74 -0
  191. package/get-shit-done/bin/lib/workstream-inventory.cjs +146 -0
  192. package/get-shit-done/bin/lib/workstream-name-policy.cjs +94 -0
  193. package/get-shit-done/bin/lib/workstream.cjs +389 -0
  194. package/get-shit-done/bin/lib/worktree-safety.cjs +985 -0
  195. package/get-shit-done/bin/shared/config-defaults.manifest.json +97 -0
  196. package/get-shit-done/bin/shared/config-schema.manifest.json +175 -0
  197. package/get-shit-done/bin/shared/model-catalog.json +122 -0
  198. package/get-shit-done/bin/shared/runtime-aliases.manifest.json +75 -0
  199. package/get-shit-done/bin/verify-reapply-patches.cjs +352 -0
  200. package/get-shit-done/contexts/dev.md +21 -0
  201. package/get-shit-done/contexts/research.md +22 -0
  202. package/get-shit-done/contexts/review.md +23 -0
  203. package/get-shit-done/references/agent-contracts.md +79 -0
  204. package/get-shit-done/references/ai-evals.md +156 -0
  205. package/get-shit-done/references/ai-frameworks.md +186 -0
  206. package/get-shit-done/references/artifact-types.md +131 -0
  207. package/get-shit-done/references/autonomous-smart-discuss.md +277 -0
  208. package/get-shit-done/references/checkpoints.md +814 -0
  209. package/get-shit-done/references/common-bug-patterns.md +114 -0
  210. package/get-shit-done/references/context-budget.md +85 -0
  211. package/get-shit-done/references/continuation-format.md +253 -0
  212. package/get-shit-done/references/debugger-philosophy.md +76 -0
  213. package/get-shit-done/references/decimal-phase-calculation.md +64 -0
  214. package/get-shit-done/references/doc-conflict-engine.md +91 -0
  215. package/get-shit-done/references/domain-probes.md +125 -0
  216. package/get-shit-done/references/execute-mvp-tdd.md +81 -0
  217. package/get-shit-done/references/executor-examples.md +110 -0
  218. package/get-shit-done/references/few-shot-examples/plan-checker.md +73 -0
  219. package/get-shit-done/references/few-shot-examples/verifier.md +109 -0
  220. package/get-shit-done/references/gate-prompts.md +100 -0
  221. package/get-shit-done/references/gates.md +70 -0
  222. package/get-shit-done/references/git-integration.md +298 -0
  223. package/get-shit-done/references/git-planning-commit.md +40 -0
  224. package/get-shit-done/references/ios-scaffold.md +123 -0
  225. package/get-shit-done/references/mandatory-initial-read.md +2 -0
  226. package/get-shit-done/references/model-profile-resolution.md +38 -0
  227. package/get-shit-done/references/model-profiles.md +245 -0
  228. package/get-shit-done/references/mvp-concepts.md +49 -0
  229. package/get-shit-done/references/phase-argument-parsing.md +61 -0
  230. package/get-shit-done/references/planner-antipatterns.md +89 -0
  231. package/get-shit-done/references/planner-chunked.md +49 -0
  232. package/get-shit-done/references/planner-gap-closure.md +62 -0
  233. package/get-shit-done/references/planner-graphify-auto-update.md +67 -0
  234. package/get-shit-done/references/planner-human-verify-mode.md +57 -0
  235. package/get-shit-done/references/planner-interface-context.md +62 -0
  236. package/get-shit-done/references/planner-mvp-mode.md +53 -0
  237. package/get-shit-done/references/planner-reviews.md +39 -0
  238. package/get-shit-done/references/planner-revision.md +87 -0
  239. package/get-shit-done/references/planner-source-audit.md +73 -0
  240. package/get-shit-done/references/planning-config.md +471 -0
  241. package/get-shit-done/references/project-skills-discovery.md +19 -0
  242. package/get-shit-done/references/questioning.md +162 -0
  243. package/get-shit-done/references/revision-loop.md +97 -0
  244. package/get-shit-done/references/scout-codebase.md +51 -0
  245. package/get-shit-done/references/skeleton-template.md +48 -0
  246. package/get-shit-done/references/sketch-interactivity.md +41 -0
  247. package/get-shit-done/references/sketch-theme-system.md +94 -0
  248. package/get-shit-done/references/sketch-tooling.md +45 -0
  249. package/get-shit-done/references/sketch-variant-patterns.md +81 -0
  250. package/get-shit-done/references/spidr-splitting.md +69 -0
  251. package/get-shit-done/references/tdd.md +330 -0
  252. package/get-shit-done/references/thinking-models-debug.md +44 -0
  253. package/get-shit-done/references/thinking-models-execution.md +50 -0
  254. package/get-shit-done/references/thinking-models-planning.md +62 -0
  255. package/get-shit-done/references/thinking-models-research.md +50 -0
  256. package/get-shit-done/references/thinking-models-verification.md +55 -0
  257. package/get-shit-done/references/thinking-partner.md +96 -0
  258. package/get-shit-done/references/ui-brand.md +160 -0
  259. package/get-shit-done/references/universal-anti-patterns.md +63 -0
  260. package/get-shit-done/references/user-profiling.md +681 -0
  261. package/get-shit-done/references/user-story-template.md +58 -0
  262. package/get-shit-done/references/verification-overrides.md +227 -0
  263. package/get-shit-done/references/verification-patterns.md +612 -0
  264. package/get-shit-done/references/verify-mvp-mode.md +85 -0
  265. package/get-shit-done/references/workstream-flag.md +111 -0
  266. package/get-shit-done/references/worktree-path-safety.md +89 -0
  267. package/get-shit-done/templates/AI-SPEC.md +246 -0
  268. package/get-shit-done/templates/DEBUG.md +169 -0
  269. package/get-shit-done/templates/README.md +77 -0
  270. package/get-shit-done/templates/SECURITY.md +61 -0
  271. package/get-shit-done/templates/UAT.md +265 -0
  272. package/get-shit-done/templates/UI-SPEC.md +100 -0
  273. package/get-shit-done/templates/VALIDATION.md +76 -0
  274. package/get-shit-done/templates/claude-md.md +145 -0
  275. package/get-shit-done/templates/codebase/architecture.md +255 -0
  276. package/get-shit-done/templates/codebase/concerns.md +310 -0
  277. package/get-shit-done/templates/codebase/conventions.md +307 -0
  278. package/get-shit-done/templates/codebase/integrations.md +280 -0
  279. package/get-shit-done/templates/codebase/stack.md +186 -0
  280. package/get-shit-done/templates/codebase/structure.md +285 -0
  281. package/get-shit-done/templates/codebase/testing.md +480 -0
  282. package/get-shit-done/templates/config.json +62 -0
  283. package/get-shit-done/templates/context.md +352 -0
  284. package/get-shit-done/templates/continue-here.md +78 -0
  285. package/get-shit-done/templates/copilot-instructions.md +7 -0
  286. package/get-shit-done/templates/debug-subagent-prompt.md +91 -0
  287. package/get-shit-done/templates/dev-preferences.md +21 -0
  288. package/get-shit-done/templates/discovery.md +146 -0
  289. package/get-shit-done/templates/discussion-log.md +63 -0
  290. package/get-shit-done/templates/milestone-archive.md +123 -0
  291. package/get-shit-done/templates/milestone.md +115 -0
  292. package/get-shit-done/templates/phase-prompt.md +610 -0
  293. package/get-shit-done/templates/planner-subagent-prompt.md +117 -0
  294. package/get-shit-done/templates/project.md +186 -0
  295. package/get-shit-done/templates/requirements.md +231 -0
  296. package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
  297. package/get-shit-done/templates/research-project/FEATURES.md +147 -0
  298. package/get-shit-done/templates/research-project/PITFALLS.md +200 -0
  299. package/get-shit-done/templates/research-project/STACK.md +120 -0
  300. package/get-shit-done/templates/research-project/SUMMARY.md +170 -0
  301. package/get-shit-done/templates/research.md +592 -0
  302. package/get-shit-done/templates/retrospective.md +54 -0
  303. package/get-shit-done/templates/roadmap.md +202 -0
  304. package/get-shit-done/templates/spec.md +307 -0
  305. package/get-shit-done/templates/state.md +195 -0
  306. package/get-shit-done/templates/summary-complex.md +59 -0
  307. package/get-shit-done/templates/summary-minimal.md +41 -0
  308. package/get-shit-done/templates/summary-standard.md +48 -0
  309. package/get-shit-done/templates/summary.md +248 -0
  310. package/get-shit-done/templates/user-profile.md +146 -0
  311. package/get-shit-done/templates/user-setup.md +311 -0
  312. package/get-shit-done/templates/verification-report.md +322 -0
  313. package/get-shit-done/workflows/_runtime-launcher.snippet.sh +1 -0
  314. package/get-shit-done/workflows/add-backlog.md +91 -0
  315. package/get-shit-done/workflows/add-phase.md +113 -0
  316. package/get-shit-done/workflows/add-tests.md +355 -0
  317. package/get-shit-done/workflows/add-todo.md +161 -0
  318. package/get-shit-done/workflows/ai-integration-phase.md +295 -0
  319. package/get-shit-done/workflows/analyze-dependencies.md +96 -0
  320. package/get-shit-done/workflows/audit-fix.md +178 -0
  321. package/get-shit-done/workflows/audit-milestone.md +358 -0
  322. package/get-shit-done/workflows/audit-uat.md +110 -0
  323. package/get-shit-done/workflows/autonomous.md +795 -0
  324. package/get-shit-done/workflows/check-todos.md +180 -0
  325. package/get-shit-done/workflows/cleanup.md +155 -0
  326. package/get-shit-done/workflows/code-review-fix.md +502 -0
  327. package/get-shit-done/workflows/code-review.md +656 -0
  328. package/get-shit-done/workflows/complete-milestone.md +855 -0
  329. package/get-shit-done/workflows/debug.md +232 -0
  330. package/get-shit-done/workflows/diagnose-issues.md +241 -0
  331. package/get-shit-done/workflows/discovery-phase.md +291 -0
  332. package/get-shit-done/workflows/discuss-phase/modes/advisor.md +176 -0
  333. package/get-shit-done/workflows/discuss-phase/modes/all.md +28 -0
  334. package/get-shit-done/workflows/discuss-phase/modes/analyze.md +44 -0
  335. package/get-shit-done/workflows/discuss-phase/modes/auto.md +57 -0
  336. package/get-shit-done/workflows/discuss-phase/modes/batch.md +52 -0
  337. package/get-shit-done/workflows/discuss-phase/modes/chain.md +98 -0
  338. package/get-shit-done/workflows/discuss-phase/modes/default.md +141 -0
  339. package/get-shit-done/workflows/discuss-phase/modes/power.md +44 -0
  340. package/get-shit-done/workflows/discuss-phase/modes/text.md +55 -0
  341. package/get-shit-done/workflows/discuss-phase/templates/checkpoint.json +18 -0
  342. package/get-shit-done/workflows/discuss-phase/templates/context.md +136 -0
  343. package/get-shit-done/workflows/discuss-phase/templates/discussion-log.md +50 -0
  344. package/get-shit-done/workflows/discuss-phase-assumptions.md +675 -0
  345. package/get-shit-done/workflows/discuss-phase-power.md +291 -0
  346. package/get-shit-done/workflows/discuss-phase.md +499 -0
  347. package/get-shit-done/workflows/do.md +111 -0
  348. package/get-shit-done/workflows/docs-update.md +1162 -0
  349. package/get-shit-done/workflows/edit-phase.md +295 -0
  350. package/get-shit-done/workflows/eval-review.md +156 -0
  351. package/get-shit-done/workflows/execute-phase/steps/codebase-drift-gate.md +82 -0
  352. package/get-shit-done/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
  353. package/get-shit-done/workflows/execute-phase/steps/post-merge-gate.md +117 -0
  354. package/get-shit-done/workflows/execute-phase.md +1709 -0
  355. package/get-shit-done/workflows/execute-plan.md +526 -0
  356. package/get-shit-done/workflows/explore.md +144 -0
  357. package/get-shit-done/workflows/extract-learnings.md +243 -0
  358. package/get-shit-done/workflows/fast.md +124 -0
  359. package/get-shit-done/workflows/forensics.md +279 -0
  360. package/get-shit-done/workflows/graduation.md +196 -0
  361. package/get-shit-done/workflows/health.md +224 -0
  362. package/get-shit-done/workflows/help/modes/brief.md +22 -0
  363. package/get-shit-done/workflows/help/modes/default.md +50 -0
  364. package/get-shit-done/workflows/help/modes/full.md +784 -0
  365. package/get-shit-done/workflows/help/modes/topic.md +74 -0
  366. package/get-shit-done/workflows/help.md +24 -0
  367. package/get-shit-done/workflows/import.md +254 -0
  368. package/get-shit-done/workflows/inbox.md +387 -0
  369. package/get-shit-done/workflows/ingest-docs.md +339 -0
  370. package/get-shit-done/workflows/insert-phase.md +152 -0
  371. package/get-shit-done/workflows/list-phase-assumptions.md +178 -0
  372. package/get-shit-done/workflows/list-workspaces.md +57 -0
  373. package/get-shit-done/workflows/manager.md +393 -0
  374. package/get-shit-done/workflows/map-codebase.md +444 -0
  375. package/get-shit-done/workflows/milestone-summary.md +224 -0
  376. package/get-shit-done/workflows/mvp-phase.md +222 -0
  377. package/get-shit-done/workflows/new-milestone.md +635 -0
  378. package/get-shit-done/workflows/new-project.md +1555 -0
  379. package/get-shit-done/workflows/new-workspace.md +240 -0
  380. package/get-shit-done/workflows/next.md +299 -0
  381. package/get-shit-done/workflows/node-repair.md +92 -0
  382. package/get-shit-done/workflows/note.md +158 -0
  383. package/get-shit-done/workflows/pause-work.md +244 -0
  384. package/get-shit-done/workflows/plan-milestone-gaps.md +281 -0
  385. package/get-shit-done/workflows/plan-phase.md +1809 -0
  386. package/get-shit-done/workflows/plan-review-convergence.md +346 -0
  387. package/get-shit-done/workflows/plant-seed.md +230 -0
  388. package/get-shit-done/workflows/pr-branch.md +157 -0
  389. package/get-shit-done/workflows/profile-user.md +453 -0
  390. package/get-shit-done/workflows/progress.md +699 -0
  391. package/get-shit-done/workflows/quick.md +1039 -0
  392. package/get-shit-done/workflows/reapply-patches.md +426 -0
  393. package/get-shit-done/workflows/remove-phase.md +156 -0
  394. package/get-shit-done/workflows/remove-workspace.md +108 -0
  395. package/get-shit-done/workflows/resume-project.md +332 -0
  396. package/get-shit-done/workflows/review.md +623 -0
  397. package/get-shit-done/workflows/scan.md +105 -0
  398. package/get-shit-done/workflows/secure-phase.md +180 -0
  399. package/get-shit-done/workflows/session-report.md +146 -0
  400. package/get-shit-done/workflows/settings-advanced.md +620 -0
  401. package/get-shit-done/workflows/settings-integrations.md +312 -0
  402. package/get-shit-done/workflows/settings.md +552 -0
  403. package/get-shit-done/workflows/ship.md +356 -0
  404. package/get-shit-done/workflows/sketch-wrap-up.md +286 -0
  405. package/get-shit-done/workflows/sketch.md +361 -0
  406. package/get-shit-done/workflows/spec-phase.md +262 -0
  407. package/get-shit-done/workflows/spike-wrap-up.md +307 -0
  408. package/get-shit-done/workflows/spike.md +453 -0
  409. package/get-shit-done/workflows/stats.md +80 -0
  410. package/get-shit-done/workflows/sync-skills.md +182 -0
  411. package/get-shit-done/workflows/thread.md +222 -0
  412. package/get-shit-done/workflows/transition.md +694 -0
  413. package/get-shit-done/workflows/ui-phase.md +328 -0
  414. package/get-shit-done/workflows/ui-review.md +193 -0
  415. package/get-shit-done/workflows/ultraplan-phase.md +199 -0
  416. package/get-shit-done/workflows/undo.md +314 -0
  417. package/get-shit-done/workflows/update.md +443 -0
  418. package/get-shit-done/workflows/validate-phase.md +179 -0
  419. package/get-shit-done/workflows/verify-phase.md +544 -0
  420. package/get-shit-done/workflows/verify-work.md +781 -0
  421. package/hooks/dist/gsd-check-update-worker.js +95 -0
  422. package/hooks/dist/gsd-check-update.js +64 -0
  423. package/hooks/dist/gsd-context-monitor.js +195 -0
  424. package/hooks/dist/gsd-graphify-update.sh +158 -0
  425. package/hooks/dist/gsd-phase-boundary.sh +47 -0
  426. package/hooks/dist/gsd-prompt-guard.js +97 -0
  427. package/hooks/dist/gsd-read-guard.js +101 -0
  428. package/hooks/dist/gsd-read-injection-scanner.js +203 -0
  429. package/hooks/dist/gsd-session-state.sh +59 -0
  430. package/hooks/dist/gsd-statusline.js +548 -0
  431. package/hooks/dist/gsd-update-banner.js +134 -0
  432. package/hooks/dist/gsd-validate-commit.sh +57 -0
  433. package/hooks/dist/gsd-workflow-guard.js +166 -0
  434. package/hooks/dist/lib/git-cmd.js +150 -0
  435. package/hooks/dist/lib/gsd-graphify-rebuild.sh +65 -0
  436. package/hooks/gsd-check-update-worker.js +95 -0
  437. package/hooks/gsd-check-update.js +64 -0
  438. package/hooks/gsd-context-monitor.js +195 -0
  439. package/hooks/gsd-graphify-update.sh +158 -0
  440. package/hooks/gsd-phase-boundary.sh +47 -0
  441. package/hooks/gsd-prompt-guard.js +97 -0
  442. package/hooks/gsd-read-guard.js +101 -0
  443. package/hooks/gsd-read-injection-scanner.js +203 -0
  444. package/hooks/gsd-session-state.sh +59 -0
  445. package/hooks/gsd-statusline.js +548 -0
  446. package/hooks/gsd-update-banner.js +134 -0
  447. package/hooks/gsd-validate-commit.sh +57 -0
  448. package/hooks/gsd-workflow-guard.js +166 -0
  449. package/hooks/lib/git-cmd.js +150 -0
  450. package/hooks/lib/gsd-graphify-rebuild.sh +65 -0
  451. package/hooks/managed-hooks-registry.cjs +34 -0
  452. package/package.json +102 -0
  453. package/scripts/affected-tests-lib.cjs +541 -0
  454. package/scripts/audit-workflow-script-paths.cjs +73 -0
  455. package/scripts/base64-scan.sh +339 -0
  456. package/scripts/build-hooks.js +236 -0
  457. package/scripts/changeset/README.md +129 -0
  458. package/scripts/changeset/cli.cjs +392 -0
  459. package/scripts/changeset/github-release-notes.cjs +199 -0
  460. package/scripts/changeset/lint.cjs +110 -0
  461. package/scripts/changeset/new.cjs +137 -0
  462. package/scripts/changeset/parse.cjs +114 -0
  463. package/scripts/changeset/render.cjs +34 -0
  464. package/scripts/changeset/serialize.cjs +130 -0
  465. package/scripts/check-alias-drift.cjs +108 -0
  466. package/scripts/check-env.cjs +302 -0
  467. package/scripts/check-npm-integrity.cjs +209 -0
  468. package/scripts/ci-guard-runner.cjs +16 -0
  469. package/scripts/ci-prepare-test-scope.cjs +46 -0
  470. package/scripts/ci-rebase-check.cjs +85 -0
  471. package/scripts/ci-test-scope.cjs +302 -0
  472. package/scripts/command-contract-helpers.cjs +64 -0
  473. package/scripts/diff-touches-shipped-paths.cjs +147 -0
  474. package/scripts/fix-slash-commands.cjs +147 -0
  475. package/scripts/gen-inventory-manifest.cjs +109 -0
  476. package/scripts/generate-package-identity.cjs +104 -0
  477. package/scripts/lint-command-contract.cjs +108 -0
  478. package/scripts/lint-descriptions.cjs +83 -0
  479. package/scripts/lint-docs-required.cjs +222 -0
  480. package/scripts/lint-no-source-grep-extras.cjs +81 -0
  481. package/scripts/lint-no-source-grep.cjs +174 -0
  482. package/scripts/lint-package-identity-drift.cjs +141 -0
  483. package/scripts/lint-pr-check-project-dir.cjs +98 -0
  484. package/scripts/lint-shared-module-handsync.cjs +388 -0
  485. package/scripts/lint-shell-command-projection-drift.cjs +57 -0
  486. package/scripts/lint-skill-deps.cjs +180 -0
  487. package/scripts/lint-test-file-count.allowlist.json +36 -0
  488. package/scripts/lint-test-file-count.cjs +190 -0
  489. package/scripts/pr-template-policy.cjs +268 -0
  490. package/scripts/prompt-injection-scan.sh +203 -0
  491. package/scripts/release-tarball-smoke.cjs +627 -0
  492. package/scripts/run-affected-tests.cjs +6 -0
  493. package/scripts/run-cross-platform-tests.cjs +63 -0
  494. package/scripts/run-tests.cjs +282 -0
  495. package/scripts/secret-scan-lint.sh +231 -0
  496. package/scripts/secret-scan.sh +358 -0
  497. package/scripts/setup-branch-protection.sh +236 -0
  498. package/scripts/shared-module-handsync-allowlist.json +183 -0
  499. package/scripts/strip-prose-atrefs.cjs +106 -0
  500. package/scripts/sync-rulesets.sh +34 -0
  501. package/scripts/sync-runtime-launcher.cjs +402 -0
  502. package/scripts/test-failure-reasons.cjs +34 -0
  503. package/scripts/workflow-policy.cjs +450 -0
@@ -0,0 +1,199 @@
1
+ 'use strict';
2
+
3
+ const cp = require('node:child_process');
4
+ const path = require('node:path');
5
+
6
+ const { parseFragment } = require('./parse.cjs');
7
+ const { packageName, repoSlug: defaultRepoSlug } = require('../../get-shit-done/bin/lib/package-identity.cjs');
8
+
9
+ const SECTION_ORDER = ['Fixed', 'Added', 'Changed', 'Deprecated', 'Removed', 'Security'];
10
+
11
+ const FIXED_GROUPS = [
12
+ {
13
+ title: 'Verification, update & review safety',
14
+ pattern: /\b(verifier|verification|verify|probe|probes|debt|tbd|fixme|xxx|detect-custom-files|review|summary|blocker|critical)\b/i,
15
+ },
16
+ {
17
+ title: 'State, planning & execution',
18
+ pattern: /\b(state|planning|planner|plan-phase|phase|roadmap|execute|executor|worktree|worktrees|resolve-model|init\.progress|model override|human_needed|ship preflight)\b/i,
19
+ },
20
+ {
21
+ title: 'Install & runtime conversion',
22
+ pattern: /\b(install|installer|runtime|windows|powershell|codex|gemini|antigravity|hook|hooks|gsd-sdk|sdk readiness|cjs|model-catalog|path|shim)\b/i,
23
+ },
24
+ ];
25
+
26
+ const REMOVED_GROUPS = [
27
+ {
28
+ title: 'Intel updater',
29
+ pattern: /\b(intel|gsd-intel-updater|layout detection)\b/i,
30
+ },
31
+ ];
32
+
33
+ function runGit(repo, args) {
34
+ return cp.execFileSync('git', args, {
35
+ cwd: repo,
36
+ encoding: 'utf8',
37
+ stdio: ['ignore', 'pipe', 'pipe'],
38
+ });
39
+ }
40
+
41
+ function validateGitRef({ repo, ref, label }) {
42
+ if (typeof ref !== 'string' || ref.trim() !== ref || ref.length === 0) {
43
+ throw new Error(`Invalid git ref for ${label}: expected a non-empty trimmed string`);
44
+ }
45
+ if (
46
+ ref.startsWith('-') ||
47
+ ref.includes('..') ||
48
+ ref.includes('//') ||
49
+ !/^[A-Za-z0-9._/-]+$/.test(ref)
50
+ ) {
51
+ throw new Error(`Invalid git ref for ${label}: ${ref}`);
52
+ }
53
+ runGit(repo, ['rev-parse', '--verify', `${ref}^{commit}`]);
54
+ return ref;
55
+ }
56
+
57
+ function changedFragmentPaths({ repo, fromRef, toRef }) {
58
+ const from = validateGitRef({ repo, ref: fromRef, label: 'fromRef' });
59
+ const to = validateGitRef({ repo, ref: toRef, label: 'toRef' });
60
+ const out = runGit(repo, ['diff', '--name-only', `${from}..${to}`, '--', '.changeset']);
61
+ return out
62
+ .split(/\r?\n/)
63
+ .filter(Boolean)
64
+ .filter((file) => /^\.changeset\/[^/]+\.md$/.test(file));
65
+ }
66
+
67
+ function readFileAtRef({ repo, ref, file }) {
68
+ return runGit(repo, ['show', `${ref}:${file}`]);
69
+ }
70
+
71
+ function loadFragmentsFromRange({ repo, fromRef, toRef }) {
72
+ const files = changedFragmentPaths({ repo, fromRef, toRef });
73
+ const fragments = [];
74
+ const failures = [];
75
+
76
+ for (const file of files) {
77
+ try {
78
+ const src = readFileAtRef({ repo, ref: toRef, file });
79
+ const parsed = parseFragment(src);
80
+ if (parsed.ok) {
81
+ fragments.push({
82
+ ...parsed.fragment,
83
+ file,
84
+ slug: path.basename(file, '.md'),
85
+ });
86
+ } else {
87
+ failures.push({ file, reason: parsed.reason, detail: parsed.detail || null });
88
+ }
89
+ } catch (e) {
90
+ failures.push({ file, reason: 'read_failed', detail: e.message });
91
+ }
92
+ }
93
+
94
+ return { fragments, failures };
95
+ }
96
+
97
+ function classifyGroup(fragment) {
98
+ const haystack = `${fragment.slug || ''}\n${fragment.body || ''}`;
99
+ const groups = fragment.type === 'Removed' ? REMOVED_GROUPS : FIXED_GROUPS;
100
+ const match = groups.find((group) => group.pattern.test(haystack));
101
+ if (match) return match.title;
102
+ if (fragment.type === 'Removed') return 'Removed';
103
+ if (fragment.type === 'Fixed') return 'Other fixes';
104
+ return fragment.type;
105
+ }
106
+
107
+ function buildGithubReleaseNotesIr({ fragments }) {
108
+ const sections = [];
109
+ for (const type of SECTION_ORDER) {
110
+ const typed = fragments.filter((fragment) => fragment.type === type);
111
+ if (typed.length === 0) continue;
112
+
113
+ const groupMap = new Map();
114
+ for (const fragment of typed) {
115
+ const groupTitle = classifyGroup(fragment);
116
+ if (!groupMap.has(groupTitle)) groupMap.set(groupTitle, []);
117
+ groupMap.get(groupTitle).push(fragment);
118
+ }
119
+
120
+ sections.push({
121
+ type,
122
+ groups: Array.from(groupMap, ([title, bullets]) => ({ title, bullets })),
123
+ });
124
+ }
125
+ return { sections };
126
+ }
127
+
128
+ function formatBullet(fragment) {
129
+ if (!Number.isInteger(fragment.pr) || fragment.pr <= 0) {
130
+ throw new Error(`Fragment ${fragment.slug || fragment.file || '<unknown>'} missing valid pr field`);
131
+ }
132
+ const body = `${fragment.body.trim()} (#${fragment.pr})`;
133
+ const lines = body.split(/\r?\n/);
134
+ return lines.map((line, index) => (index === 0 ? `- ${line}` : ` ${line}`)).join('\n');
135
+ }
136
+
137
+ function compareUrl({ repoSlug, fromRef, toRef }) {
138
+ const normalizedSlug = String(repoSlug || '').trim();
139
+ if (!/^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/.test(normalizedSlug)) {
140
+ throw new Error(`Invalid repoSlug format: ${repoSlug} (expected "owner/repo")`);
141
+ }
142
+ return `https://github.com/${normalizedSlug}/compare/${fromRef}...${toRef}`;
143
+ }
144
+
145
+ function serializeGithubReleaseNotes({
146
+ ir,
147
+ fromRef,
148
+ toRef,
149
+ repoSlug = defaultRepoSlug,
150
+ installCommand = `npx ${packageName}@latest`,
151
+ }) {
152
+ if (installCommand.includes('`')) {
153
+ throw new Error('installCommand cannot contain backtick characters');
154
+ }
155
+ const lines = [];
156
+ for (const section of ir.sections) {
157
+ lines.push(`## ${section.type}`);
158
+ lines.push('');
159
+ for (const group of section.groups) {
160
+ lines.push(`### ${group.title}`);
161
+ for (const bullet of group.bullets) {
162
+ lines.push(formatBullet(bullet));
163
+ }
164
+ lines.push('');
165
+ }
166
+ }
167
+ lines.push('---');
168
+ lines.push('');
169
+ lines.push(`Install/upgrade: \`${installCommand}\``);
170
+ lines.push('');
171
+ lines.push(`**Full Changelog**: ${compareUrl({ repoSlug, fromRef, toRef })}`);
172
+ lines.push('');
173
+ return lines.join('\n');
174
+ }
175
+
176
+ function renderGithubReleaseNotes(options) {
177
+ const { fragments, failures } = loadFragmentsFromRange(options);
178
+ if (failures.length > 0) {
179
+ return { ok: false, fragments, failures, body: null };
180
+ }
181
+ const ir = buildGithubReleaseNotesIr({ fragments });
182
+ return {
183
+ ok: true,
184
+ fragments,
185
+ failures: [],
186
+ ir,
187
+ body: serializeGithubReleaseNotes({ ir, ...options }),
188
+ };
189
+ }
190
+
191
+ module.exports = {
192
+ changedFragmentPaths,
193
+ loadFragmentsFromRange,
194
+ buildGithubReleaseNotesIr,
195
+ serializeGithubReleaseNotes,
196
+ renderGithubReleaseNotes,
197
+ classifyGroup,
198
+ validateGitRef,
199
+ };
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Changeset-fragment lint (#2975).
6
+ *
7
+ * Pure verdict function evaluateLint({ changedFiles, labels }) returns
8
+ * { ok, reason } using the LINT_REASON enum. The CLI wrapper calls it with
9
+ * the PR diff (via `git diff --name-only origin/main...HEAD` or the GitHub
10
+ * Actions event payload) and the labels list (via the GitHub event).
11
+ *
12
+ * Tests assert on the typed verdict, never on free text.
13
+ */
14
+
15
+ const LINT_REASON = Object.freeze({
16
+ OK_FRAGMENT_PRESENT: 'ok_fragment_present',
17
+ OK_OPT_OUT_LABEL: 'ok_opt_out_label',
18
+ OK_NO_USER_FACING_CHANGES: 'ok_no_user_facing_changes',
19
+ FAIL_MISSING_FRAGMENT: 'fail_missing_fragment',
20
+ });
21
+
22
+ const OPT_OUT_LABEL = 'no-changelog';
23
+
24
+ // Files counted as "user-facing" — touching any of these requires either a
25
+ // fragment or an explicit opt-out label. Test/CI/docs/lock files do not.
26
+ const USER_FACING_PREFIXES = [
27
+ 'bin/',
28
+ 'get-shit-done/',
29
+ 'agents/',
30
+ 'commands/',
31
+ 'hooks/',
32
+ 'sdk/src/',
33
+ 'sdk/prompts/',
34
+ ];
35
+
36
+ // Exact-match user-facing files. Any direct edit to one of these without a
37
+ // fragment also fails the lint — closes the bypass where a contributor edits
38
+ // CHANGELOG.md directly to sneak past the new workflow.
39
+ const USER_FACING_FILES = new Set(['CHANGELOG.md']);
40
+
41
+ function isUserFacing(file) {
42
+ if (USER_FACING_FILES.has(file)) return true;
43
+ return USER_FACING_PREFIXES.some((p) => file.startsWith(p));
44
+ }
45
+
46
+ function isFragment(file) {
47
+ return /^\.changeset\/[^/]+\.md$/.test(file) && !file.endsWith('/README.md');
48
+ }
49
+
50
+ function evaluateLint({ changedFiles, labels }) {
51
+ if (changedFiles.some(isFragment)) {
52
+ return { ok: true, reason: LINT_REASON.OK_FRAGMENT_PRESENT };
53
+ }
54
+ if (labels.includes(OPT_OUT_LABEL)) {
55
+ return { ok: true, reason: LINT_REASON.OK_OPT_OUT_LABEL };
56
+ }
57
+ if (!changedFiles.some(isUserFacing)) {
58
+ return { ok: true, reason: LINT_REASON.OK_NO_USER_FACING_CHANGES };
59
+ }
60
+ return { ok: false, reason: LINT_REASON.FAIL_MISSING_FRAGMENT };
61
+ }
62
+
63
+ function main() {
64
+ const fs = require('node:fs');
65
+ const cp = require('node:child_process');
66
+ // GitHub Actions event payload path
67
+ const eventPath = process.env.GITHUB_EVENT_PATH;
68
+ let labels = [];
69
+ if (eventPath && fs.existsSync(eventPath)) {
70
+ try {
71
+ const event = JSON.parse(fs.readFileSync(eventPath, 'utf8'));
72
+ labels = (event.pull_request?.labels || []).map((l) => l.name);
73
+ } catch { /* fall through */ }
74
+ }
75
+ const base = process.env.GITHUB_BASE_REF || 'main';
76
+ let changedFiles = [];
77
+ try {
78
+ // Use execFileSync with an argv array — the base ref is interpolated
79
+ // into a refspec argument, but execFileSync does not invoke a shell, so
80
+ // even a malicious GITHUB_BASE_REF cannot inject shell syntax. The
81
+ // refspec-bound metacharacters that git itself rejects (e.g. spaces in
82
+ // ref names) are caught by git's own arg parser.
83
+ const out = cp.execFileSync(
84
+ 'git',
85
+ ['diff', '--name-only', `origin/${base}...HEAD`],
86
+ { encoding: 'utf8' },
87
+ );
88
+ changedFiles = out.split('\n').filter(Boolean);
89
+ } catch (e) {
90
+ process.stderr.write(`could not compute diff: ${e.message}\n`);
91
+ process.exit(2);
92
+ }
93
+
94
+ const verdict = evaluateLint({ changedFiles, labels });
95
+ if (process.argv.includes('--json')) {
96
+ process.stdout.write(JSON.stringify({ ...verdict, changedFiles, labels }, null, 2) + '\n');
97
+ } else if (verdict.ok) {
98
+ process.stdout.write(`ok changeset-lint: ${verdict.reason}\n`);
99
+ } else {
100
+ process.stderr.write(`\nERROR changeset-lint: ${verdict.reason}\n`);
101
+ process.stderr.write(`PR touches user-facing files but does not include a .changeset/*.md fragment.\n`);
102
+ process.stderr.write(`Run \`npm run changeset\` to create one, or add the \`${OPT_OUT_LABEL}\` label\n`);
103
+ process.stderr.write(`if this PR genuinely has no user-facing impact (test refactor, CI tweak, etc.).\n`);
104
+ }
105
+ process.exit(verdict.ok ? 0 : 1);
106
+ }
107
+
108
+ if (require.main === module) main();
109
+
110
+ module.exports = { evaluateLint, LINT_REASON, OPT_OUT_LABEL, isUserFacing, isFragment };
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Scaffolds a new changeset fragment (#2975).
6
+ *
7
+ * npm run changeset -- --type Fixed --pr 1234 --body "fix the thing"
8
+ *
9
+ * Writes `.changeset/<adjective>-<noun>-<noun>.md` with frontmatter
10
+ * + body. The random three-word filename minimizes filename collision
11
+ * across concurrent PRs.
12
+ */
13
+
14
+ const fs = require('node:fs');
15
+ const path = require('node:path');
16
+
17
+ // Small word lists — keep the function simple and dependency-free.
18
+ // Together this gives ~40 * 40 * 40 = 64,000 distinct names. The lint
19
+ // rejects any duplicate filename, so collisions are caught even when
20
+ // the random draw repeats.
21
+ const ADJECTIVES = [
22
+ 'silly', 'brave', 'calm', 'eager', 'gentle', 'happy', 'jolly', 'kind',
23
+ 'lively', 'merry', 'nimble', 'plucky', 'quick', 'sturdy', 'witty', 'zesty',
24
+ 'bold', 'clever', 'daring', 'fierce', 'graceful', 'humble', 'lucky', 'noble',
25
+ 'proud', 'rapid', 'sharp', 'tidy', 'vivid', 'wise', 'agile', 'curious',
26
+ 'eager', 'gallant', 'mellow', 'patient', 'serene', 'steady', 'sturdy', 'sunny',
27
+ ];
28
+ const NOUNS_A = [
29
+ 'bears', 'birds', 'cats', 'dogs', 'elks', 'foxes', 'goats', 'hawks',
30
+ 'ibex', 'jays', 'koalas', 'lynx', 'moles', 'newts', 'otters', 'pumas',
31
+ 'quails', 'rams', 'seals', 'tigers', 'voles', 'wolves', 'yaks', 'zebras',
32
+ 'badgers', 'cranes', 'deer', 'eagles', 'finches', 'geese', 'herons', 'jaguars',
33
+ 'lemurs', 'mice', 'orcas', 'pandas', 'ravens', 'sloths', 'tunas', 'wasps',
34
+ ];
35
+ const NOUNS_B = [
36
+ 'dance', 'sing', 'leap', 'run', 'jump', 'climb', 'fly', 'swim',
37
+ 'rest', 'wake', 'roam', 'greet', 'wander', 'gather', 'forage', 'travel',
38
+ 'glide', 'sprint', 'tumble', 'wave', 'cheer', 'rally', 'parade', 'march',
39
+ 'hop', 'frolic', 'caper', 'romp', 'zip', 'dart', 'snooze', 'munch',
40
+ 'chatter', 'squeak', 'howl', 'bark', 'purr', 'roar', 'hum', 'click',
41
+ ];
42
+
43
+ function pick(arr) {
44
+ return arr[Math.floor(Math.random() * arr.length)];
45
+ }
46
+
47
+ function generateFragmentName() {
48
+ return `${pick(ADJECTIVES)}-${pick(NOUNS_A)}-${pick(NOUNS_B)}`;
49
+ }
50
+
51
+ // Allowed Keep-a-Changelog section types. Used by both scaffoldFragment
52
+ // (sanitization at write time) and parse.cjs (validation at consume time).
53
+ const ALLOWED_TYPES = new Set(['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security']);
54
+
55
+ function scaffoldFragment({ repo, type, pr, body }) {
56
+ // Sanitize: reject any type value not on the allowlist BEFORE embedding it
57
+ // in frontmatter. A newline in `type` would corrupt the fragment; an
58
+ // unrecognized value would be rejected later by parse.cjs but with a
59
+ // confusing diagnostic. Catch both at the write boundary.
60
+ if (!ALLOWED_TYPES.has(type)) {
61
+ throw new Error(
62
+ `scaffoldFragment: type=${JSON.stringify(type)} is not one of [${[...ALLOWED_TYPES].join(', ')}]`,
63
+ );
64
+ }
65
+ const dir = path.join(repo, '.changeset');
66
+ fs.mkdirSync(dir, { recursive: true });
67
+ const content = `---\ntype: ${type}\npr: ${pr}\n---\n${body}\n`;
68
+ // Atomic create: writeFileSync with `flag: 'wx'` fails (EEXIST) when the
69
+ // file already exists, so concurrent invocations can't race past
70
+ // `existsSync` and overwrite each other. Re-roll the random name on
71
+ // collision; fail loudly after exhausting the retry budget.
72
+ for (let i = 0; i < 16; i++) {
73
+ const name = generateFragmentName();
74
+ const target = path.join(dir, `${name}.md`);
75
+ try {
76
+ fs.writeFileSync(target, content, { flag: 'wx' });
77
+ return target;
78
+ } catch (e) {
79
+ if (e.code !== 'EEXIST') throw e;
80
+ // collision — try another random draw
81
+ }
82
+ }
83
+ throw new Error(
84
+ 'scaffoldFragment: 16 random filename draws all collided; ' +
85
+ 'expand the word lists or investigate corrupted .changeset/ state',
86
+ );
87
+ }
88
+
89
+ function parseArgs(argv) {
90
+ const opts = { type: null, pr: null, body: null, repo: process.cwd() };
91
+ // Validate flag values: argv[++i] could be undefined (flag with no value)
92
+ // or another flag (silently misparsed). Match the cli.cjs convention: return
93
+ // { ok: true, opts } on success, { ok: false, error } on malformed input.
94
+ const requireValue = (flag, i) => {
95
+ const v = argv[i + 1];
96
+ if (v === undefined || v.startsWith('--')) {
97
+ return { ok: false, error: `missing value for ${flag}` };
98
+ }
99
+ return { ok: true, value: v };
100
+ };
101
+
102
+ for (let i = 0; i < argv.length; i++) {
103
+ const a = argv[i];
104
+ if (a === '--type' || a === '--pr' || a === '--body' || a === '--repo') {
105
+ const r = requireValue(a, i);
106
+ if (!r.ok) return { ok: false, error: r.error };
107
+ if (a === '--type') opts.type = r.value;
108
+ else if (a === '--pr') opts.pr = Number(r.value);
109
+ else if (a === '--body') opts.body = r.value;
110
+ else if (a === '--repo') opts.repo = r.value;
111
+ i++;
112
+ continue;
113
+ }
114
+ return { ok: false, error: `unknown argument: ${a}` };
115
+ }
116
+ return { ok: true, opts };
117
+ }
118
+
119
+ function main() {
120
+ const parsed = parseArgs(process.argv.slice(2));
121
+ if (!parsed.ok) {
122
+ process.stderr.write(`${parsed.error}\n`);
123
+ process.stderr.write('usage: changeset/new.cjs --type <Fixed|Added|...> --pr NNNN --body "..."\n');
124
+ process.exit(2);
125
+ }
126
+ const { opts } = parsed;
127
+ if (!opts.type || !opts.pr || !opts.body) {
128
+ process.stderr.write('usage: changeset/new.cjs --type <Fixed|Added|...> --pr NNNN --body "..."\n');
129
+ process.exit(2);
130
+ }
131
+ const file = scaffoldFragment(opts);
132
+ process.stdout.write(`${path.relative(process.cwd(), file)}\n`);
133
+ }
134
+
135
+ if (require.main === module) main();
136
+
137
+ module.exports = { generateFragmentName, scaffoldFragment, parseArgs, ALLOWED_TYPES };
@@ -0,0 +1,114 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Parses a changeset fragment file (text → typed record).
5
+ *
6
+ * ---
7
+ * type: Fixed
8
+ * pr: 2975
9
+ * ---
10
+ * <markdown body>
11
+ *
12
+ * Returns { ok: true, fragment: { type, pr, body, docsExempt } } on success,
13
+ * { ok: false, reason: FRAGMENT_ERROR.X, detail } on failure.
14
+ *
15
+ * `docsExempt` is `null` when the body contains no docs-exempt marker, or the
16
+ * trimmed reason string when the body contains `<!-- docs-exempt: <reason> -->`
17
+ * (#3213). The marker is stripped from `body` at parse time so it never bleeds
18
+ * into the CHANGELOG.md or GitHub release-notes serializers, which append the
19
+ * `(#NNNN)` PR suffix verbatim to the body's last line.
20
+ *
21
+ * The reason field is a frozen enum so tests assert on stable codes,
22
+ * not free-text error messages (CONTRIBUTING.md: "Prohibited: Raw
23
+ * Text Matching on Test Outputs").
24
+ */
25
+ const FRAGMENT_ERROR = Object.freeze({
26
+ MISSING_FRONTMATTER: 'missing_frontmatter',
27
+ MISSING_TYPE: 'missing_type',
28
+ INVALID_TYPE: 'invalid_type',
29
+ MISSING_PR: 'missing_pr',
30
+ INVALID_PR: 'invalid_pr',
31
+ EMPTY_BODY: 'empty_body',
32
+ });
33
+
34
+ const ALLOWED_TYPES = new Set(['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security']);
35
+
36
+ // HTML comment marking a fragment as exempt from the docs-required lint (#3213).
37
+ // Form: `<!-- docs-exempt: <reason> -->`. The reason is the *required* human
38
+ // audit trail — without it the exemption has no paper-trail value, so a bare
39
+ // `<!-- docs-exempt -->` or empty `<!-- docs-exempt: -->` is intentionally
40
+ // rejected (the colon and a non-whitespace first reason char are mandatory).
41
+ //
42
+ // Anchored with `^...$` + `m` flag so the marker only counts when it occupies
43
+ // its own line. Inline mentions inside paragraphs (e.g. backtick-wrapped
44
+ // syntax examples in documentation) are not matched — they cannot
45
+ // accidentally exempt a fragment.
46
+ //
47
+ // The trailing `\r?` consumes the CR character of a CRLF line terminator,
48
+ // which the `$` boundary (multiline mode) does not — so Windows-authored
49
+ // fragments produce the same `body` shape as LF-authored ones. The reason
50
+ // character class `[^\r\n>]` excludes `\r` for the same reason: a CRLF
51
+ // fragment's reason text never carries a trailing `\r`.
52
+ //
53
+ // Bounded character class `[^\r\n>]` keeps the regex linear-time — no
54
+ // catastrophic backtracking on adversarial input. The leading `\S` anchor
55
+ // inside the capture group forces at least one non-whitespace character in
56
+ // the reason; trailing whitespace before `-->` is consumed by the outer
57
+ // `[ \t]*-->` and is not part of the captured reason.
58
+ const DOCS_EXEMPT_RE = /^[ \t]*<!--[ \t]*docs-exempt[ \t]*:[ \t]*(\S[^\r\n>]*?)[ \t]*-->[ \t]*\r?$/im;
59
+
60
+ function extractDocsExempt(body) {
61
+ const m = body.match(DOCS_EXEMPT_RE);
62
+ if (!m) return { docsExempt: null, body };
63
+ const reason = (m[1] || '').trim();
64
+ // Strip the marker line and tidy up the surrounding whitespace. The cleanup
65
+ // is CRLF-aware so Windows-authored fragments don't leave residual `\r`
66
+ // characters that would shift the `(#NNNN)` PR suffix to a blank line in
67
+ // the rendered CHANGELOG.md / GitHub release-notes bullet.
68
+ const cleaned = body
69
+ .replace(DOCS_EXEMPT_RE, '')
70
+ .replace(/[ \t\r]+$/gm, '') // strip trailing \r/spaces on each line
71
+ .replace(/(?:\r?\n){3,}/g, '\n\n') // collapse 3+ blank lines (CRLF-aware)
72
+ .replace(/[\r\n]+$/, ''); // strip every trailing line terminator
73
+ return { docsExempt: reason, body: cleaned };
74
+ }
75
+
76
+ function parseFragment(src) {
77
+ const fmMatch = src.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
78
+ if (!fmMatch) return { ok: false, reason: FRAGMENT_ERROR.MISSING_FRONTMATTER };
79
+ const [, fmBlock, body] = fmMatch;
80
+
81
+ const fields = {};
82
+ for (const line of fmBlock.split(/\r?\n/)) {
83
+ const m = line.match(/^([a-zA-Z0-9_-]+):\s*(.*)$/);
84
+ if (m) fields[m[1]] = m[2].trim();
85
+ }
86
+
87
+ if (!fields.type) return { ok: false, reason: FRAGMENT_ERROR.MISSING_TYPE };
88
+ if (!ALLOWED_TYPES.has(fields.type)) {
89
+ return { ok: false, reason: FRAGMENT_ERROR.INVALID_TYPE, detail: fields.type };
90
+ }
91
+ if (!fields.pr) return { ok: false, reason: FRAGMENT_ERROR.MISSING_PR };
92
+ const pr = Number(fields.pr);
93
+ if (!Number.isInteger(pr) || pr <= 0) {
94
+ return { ok: false, reason: FRAGMENT_ERROR.INVALID_PR, detail: fields.pr };
95
+ }
96
+ // Use trim() only for the emptiness check; preserve the body verbatim
97
+ // (including significant leading/trailing whitespace, code blocks, etc.)
98
+ // so render → serialize round-trips exactly. Strip the single trailing
99
+ // line terminator added by editors so byte-equality holds for typical
100
+ // fragments. CRLF-aware: a Windows-authored fragment trims `\r\n` so the
101
+ // marker line in extractDocsExempt does not leave residual `\r` characters
102
+ // for downstream serializers to attach `(#NNNN)` to (#3213).
103
+ if (!body.trim()) return { ok: false, reason: FRAGMENT_ERROR.EMPTY_BODY };
104
+ let verbatimBody;
105
+ if (body.endsWith('\r\n')) verbatimBody = body.slice(0, -2);
106
+ else if (body.endsWith('\n')) verbatimBody = body.slice(0, -1);
107
+ else verbatimBody = body;
108
+ const { docsExempt, body: visibleBody } = extractDocsExempt(verbatimBody);
109
+ if (!visibleBody.trim()) return { ok: false, reason: FRAGMENT_ERROR.EMPTY_BODY };
110
+
111
+ return { ok: true, fragment: { type: fields.type, pr, body: visibleBody, docsExempt } };
112
+ }
113
+
114
+ module.exports = { parseFragment, extractDocsExempt, FRAGMENT_ERROR, ALLOWED_TYPES, DOCS_EXEMPT_RE };
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Pure renderer for the changeset-fragment workflow (#2975).
5
+ *
6
+ * Returns a typed Changelog IR — no file I/O. The IR is the contract that
7
+ * tests assert on; the markdown serializer is a separate concern.
8
+ *
9
+ * IR shape: {
10
+ * releaseHeader: { version: string, date: string },
11
+ * sections: [{ type: string, bullets: [{ pr: number, body: string }] }],
12
+ * priorChangelog: string | null,
13
+ * }
14
+ */
15
+ // Keep a Changelog (https://keepachangelog.com) standard section order.
16
+ const SECTION_ORDER = ['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security'];
17
+
18
+ function renderChangelog({ fragments, version, date, priorChangelog }) {
19
+ const byType = new Map();
20
+ for (const f of fragments) {
21
+ if (!byType.has(f.type)) byType.set(f.type, []);
22
+ byType.get(f.type).push({ pr: f.pr, body: f.body });
23
+ }
24
+ const sections = SECTION_ORDER
25
+ .filter((type) => byType.has(type))
26
+ .map((type) => ({ type, bullets: byType.get(type) }));
27
+ return {
28
+ releaseHeader: { version, date },
29
+ sections,
30
+ priorChangelog: priorChangelog || null,
31
+ };
32
+ }
33
+
34
+ module.exports = { renderChangelog };