@workerstack/repo 0.0.0-stage → 0.1.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 (438) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/LICENSE +21 -0
  3. package/README.md +0 -3
  4. package/agents/global-settings/antigravity.json +3 -0
  5. package/agents/global-settings/claude.json +6 -0
  6. package/agents/global-settings/codex.toml +2 -0
  7. package/agents/global-settings/cursor.json +3 -0
  8. package/agents/global-settings/grok.toml +36 -0
  9. package/agents/global-settings/manifest.json +36 -0
  10. package/agents/grok/hooks/orchestrate-parent.json +60 -0
  11. package/agents/grok/hooks/rtk.json +16 -0
  12. package/agents/grok/hooks/rulesync.json +3 -0
  13. package/agents/grok/roles/scout.toml +5 -0
  14. package/agents/hooks.jsonc +67 -0
  15. package/agents/mcp-policy.jsonc +16 -0
  16. package/agents/rules/overview.md +21 -0
  17. package/agents/settings/claude.json +5 -0
  18. package/agents/skills/ask/SKILL.md +13 -0
  19. package/agents/skills/auto/SKILL.md +13 -0
  20. package/agents/skills/away/SKILL.md +19 -0
  21. package/agents/skills/blast-radius/SKILL.md +54 -0
  22. package/agents/skills/bro/SKILL.md +9 -0
  23. package/agents/skills/browser/SKILL.md +16 -0
  24. package/agents/skills/clasp/SKILL.md +11 -0
  25. package/agents/skills/commit/SKILL.md +35 -0
  26. package/agents/skills/commit-and-push/SKILL.md +9 -0
  27. package/agents/skills/commit-push/SKILL.md +59 -0
  28. package/agents/skills/commit-push-deploy/SKILL.md +74 -0
  29. package/agents/skills/commit-push-release/SKILL.md +75 -0
  30. package/agents/skills/correct/SKILL.md +39 -0
  31. package/agents/skills/do/SKILL.md +21 -0
  32. package/agents/skills/explain/SKILL.md +13 -0
  33. package/agents/skills/google-workspace/SKILL.md +12 -0
  34. package/agents/skills/handoff/SKILL.md +81 -0
  35. package/agents/skills/implement-plan/SKILL.md +29 -0
  36. package/agents/skills/implement-roadmap/SKILL.md +27 -0
  37. package/agents/skills/jev/SKILL.md +17 -0
  38. package/agents/skills/listen/SKILL.md +15 -0
  39. package/agents/skills/pickup/SKILL.md +58 -0
  40. package/agents/skills/principle-attack-the-premise/SKILL.md +24 -0
  41. package/agents/skills/principle-boundary-discipline/SKILL.md +38 -0
  42. package/agents/skills/principle-build-the-lever/SKILL.md +28 -0
  43. package/agents/skills/principle-encode-lessons-in-structure/SKILL.md +15 -0
  44. package/agents/skills/principle-exhaust-the-design-space/SKILL.md +12 -0
  45. package/agents/skills/principle-experience-first/SKILL.md +22 -0
  46. package/agents/skills/principle-explain-the-number/SKILL.md +21 -0
  47. package/agents/skills/principle-fix-root-causes/SKILL.md +24 -0
  48. package/agents/skills/principle-foundational-thinking/SKILL.md +25 -0
  49. package/agents/skills/principle-guard-the-context-window/SKILL.md +16 -0
  50. package/agents/skills/principle-laziness-protocol/SKILL.md +13 -0
  51. package/agents/skills/principle-make-operations-idempotent/SKILL.md +25 -0
  52. package/agents/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +18 -0
  53. package/agents/skills/principle-minimize-reader-load/SKILL.md +22 -0
  54. package/agents/skills/principle-model-the-domain/SKILL.md +26 -0
  55. package/agents/skills/principle-never-block-on-the-human/SKILL.md +17 -0
  56. package/agents/skills/principle-outcome-oriented-execution/SKILL.md +25 -0
  57. package/agents/skills/principle-prove-it-works/SKILL.md +25 -0
  58. package/agents/skills/principle-redesign-from-first-principles/SKILL.md +18 -0
  59. package/agents/skills/principle-separate-before-serializing-shared-state/SKILL.md +20 -0
  60. package/agents/skills/principle-sequence-verifiable-units/SKILL.md +22 -0
  61. package/agents/skills/principle-subtract-before-you-add/SKILL.md +21 -0
  62. package/agents/skills/principle-test-behavior-not-implementation/SKILL.md +24 -0
  63. package/agents/skills/principle-type-system-discipline/SKILL.md +17 -0
  64. package/agents/skills/review-plan/SKILL.md +28 -0
  65. package/agents/skills/review-roadmap/SKILL.md +28 -0
  66. package/agents/skills/show-me/SKILL.md +21 -0
  67. package/agents/skills/speak/SKILL.md +15 -0
  68. package/agents/skills/su/SKILL.md +11 -0
  69. package/agents/skills/teach/SKILL.md +25 -0
  70. package/agents/skills/tmp/SKILL.md +54 -0
  71. package/agents/skills/typescript-best-practices/SKILL.md +32 -0
  72. package/agents/skills/typescript-best-practices/references/patterns.md +328 -0
  73. package/agents/skills/unslop/SKILL.md +62 -0
  74. package/agents/skills/write-plan/SKILL.md +33 -0
  75. package/agents/skills/write-roadmap/SKILL.md +66 -0
  76. package/agents/subagents/implementer-deep.md +57 -0
  77. package/agents/subagents/implementer-fast.md +57 -0
  78. package/agents/subagents/orchestrator.md +43 -0
  79. package/agents/subagents/researcher.md +47 -0
  80. package/agents/subagents/scout.md +44 -0
  81. package/bin/repo.ts +4 -0
  82. package/cli/actionlint-default.test.ts +38 -0
  83. package/cli/actionlint-download.test.ts +162 -0
  84. package/cli/actionlint-real.test.ts +33 -0
  85. package/cli/actionlint.constants.ts +43 -0
  86. package/cli/actionlint.test.ts +108 -0
  87. package/cli/actionlint.ts +178 -0
  88. package/cli/bin.test.ts +54 -0
  89. package/cli/bin.ts +40 -0
  90. package/cli/check-changelog.test.ts +40 -0
  91. package/cli/check-changelog.ts +12 -0
  92. package/cli/check-comments.test.ts +157 -0
  93. package/cli/check-comments.ts +123 -0
  94. package/cli/check-env-modules.test.ts +85 -0
  95. package/cli/check-env-modules.ts +56 -0
  96. package/cli/check-magic.test.ts +139 -0
  97. package/cli/check-magic.ts +120 -0
  98. package/cli/check-manifests.constants.ts +4 -0
  99. package/cli/check-manifests.test.ts +210 -0
  100. package/cli/check-manifests.ts +71 -0
  101. package/cli/check-nightly.test.ts +103 -0
  102. package/cli/check-nightly.ts +37 -0
  103. package/cli/check-ratchets-missing.test.ts +46 -0
  104. package/cli/check-ratchets-mutation.test.ts +49 -0
  105. package/cli/check-ratchets.constants.ts +20 -0
  106. package/cli/check-ratchets.test.ts +190 -0
  107. package/cli/check-ratchets.ts +193 -0
  108. package/cli/check-rejections.test.ts +220 -0
  109. package/cli/check-rejections.ts +153 -0
  110. package/cli/check-reports.ts +37 -0
  111. package/cli/check-tsconfig.test.ts +507 -0
  112. package/cli/check-tsconfig.ts +205 -0
  113. package/cli/commands.test.ts +114 -0
  114. package/cli/commands.ts +218 -0
  115. package/cli/commit-changelog.ts +27 -0
  116. package/cli/commit-msg-changelog.test.ts +93 -0
  117. package/cli/commit-msg-range.test.ts +126 -0
  118. package/cli/commit-msg-red-proof.test.ts +147 -0
  119. package/cli/commit-msg-repo.test.ts +153 -0
  120. package/cli/commit-msg.test.ts +101 -0
  121. package/cli/commit-msg.ts +194 -0
  122. package/cli/commit-range.constants.ts +17 -0
  123. package/cli/commit-range.ts +57 -0
  124. package/cli/config-knip.test.ts +70 -0
  125. package/cli/config-nightly.test.ts +84 -0
  126. package/cli/config-tdd.test.ts +46 -0
  127. package/cli/config.test.ts +576 -0
  128. package/cli/config.ts +261 -0
  129. package/cli/conventional.ts +9 -0
  130. package/cli/coverage-config.ts +62 -0
  131. package/cli/coverage.constants.ts +6 -0
  132. package/cli/coverage.test.ts +199 -0
  133. package/cli/coverage.ts +127 -0
  134. package/cli/env.constants.ts +10 -0
  135. package/cli/env.test.ts +56 -0
  136. package/cli/env.ts +72 -0
  137. package/cli/fixtures/base-config.ts +13 -0
  138. package/cli/fixtures/gate-world.ts +48 -0
  139. package/cli/fixtures/knip-run.ts +38 -0
  140. package/cli/fixtures/mutate-fakes.ts +137 -0
  141. package/cli/fixtures/planted-repo.ts +50 -0
  142. package/cli/fixtures/publish-world.ts +71 -0
  143. package/cli/fixtures/red-proof-repo.ts +72 -0
  144. package/cli/fixtures/release-context.ts +15 -0
  145. package/cli/fixtures/release-world.ts +111 -0
  146. package/cli/fixtures/stub-bin.ts +40 -0
  147. package/cli/guard-diagnostics.test.ts +157 -0
  148. package/cli/guard-diagnostics.ts +195 -0
  149. package/cli/init.test.ts +487 -0
  150. package/cli/init.ts +275 -0
  151. package/cli/knip-check-ignores.test.ts +106 -0
  152. package/cli/knip-check-real.test.ts +65 -0
  153. package/cli/knip-check.constants.ts +46 -0
  154. package/cli/knip-check.test.ts +114 -0
  155. package/cli/knip-check.ts +169 -0
  156. package/cli/knip-schema.ts +67 -0
  157. package/cli/known-failures.constants.ts +22 -0
  158. package/cli/known-failures.test.ts +138 -0
  159. package/cli/known-failures.ts +131 -0
  160. package/cli/lint/as-needs-reason.ts +41 -0
  161. package/cli/lint/boundaries.ts +73 -0
  162. package/cli/lint/class-file.ts +39 -0
  163. package/cli/lint/config-file.ts +32 -0
  164. package/cli/lint/entry-file.ts +54 -0
  165. package/cli/lint/env-in-config.ts +66 -0
  166. package/cli/lint/filename-matches-export.ts +63 -0
  167. package/cli/lint/index-file.ts +22 -0
  168. package/cli/lint/index.ts +47 -0
  169. package/cli/lint/is-reason.ts +6 -0
  170. package/cli/lint/manifest.ts +46 -0
  171. package/cli/lint/names.ts +59 -0
  172. package/cli/lint/no-commented-out-code.ts +105 -0
  173. package/cli/lint/no-mock-of-subject.ts +64 -0
  174. package/cli/lint/no-module-side-effects.ts +94 -0
  175. package/cli/lint/no-module-state.ts +58 -0
  176. package/cli/lint/no-side-effect-import.ts +17 -0
  177. package/cli/lint/no-v8-ignore.ts +18 -0
  178. package/cli/lint/script-rules.ts +9 -0
  179. package/cli/lint/skip-on-platform.constants.ts +8 -0
  180. package/cli/lint/skip-on-platform.ts +118 -0
  181. package/cli/lint/todo-needs-id.ts +63 -0
  182. package/cli/lint/types-file.ts +28 -0
  183. package/cli/lint-schema.ts +32 -0
  184. package/cli/magic/fixtures/magic-repo.ts +64 -0
  185. package/cli/magic/magic-hit.ts +2 -0
  186. package/cli/magic/magic-nodes.ts +44 -0
  187. package/cli/magic/magic-numbers.test.ts +99 -0
  188. package/cli/magic/magic-numbers.ts +117 -0
  189. package/cli/magic/magic-strings.test.ts +38 -0
  190. package/cli/magic/magic-strings.ts +81 -0
  191. package/cli/main.test.ts +853 -0
  192. package/cli/main.ts +292 -0
  193. package/cli/mutate-args.ts +79 -0
  194. package/cli/mutate-check.test.ts +147 -0
  195. package/cli/mutate-deps.ts +42 -0
  196. package/cli/mutate-edges.test.ts +150 -0
  197. package/cli/mutate-files.test.ts +100 -0
  198. package/cli/mutate-files.ts +31 -0
  199. package/cli/mutate-floors.test.ts +91 -0
  200. package/cli/mutate-floors.ts +104 -0
  201. package/cli/mutate-real-deps.ts +57 -0
  202. package/cli/mutate-real.test.ts +96 -0
  203. package/cli/mutate-report.ts +96 -0
  204. package/cli/mutate-run.ts +128 -0
  205. package/cli/mutate-shards.ts +64 -0
  206. package/cli/mutate.constants.ts +67 -0
  207. package/cli/mutate.test.ts +182 -0
  208. package/cli/mutate.ts +64 -0
  209. package/cli/nested-vitest-flags.ts +8 -0
  210. package/cli/nightly-config.constants.ts +14 -0
  211. package/cli/nightly-config.ts +62 -0
  212. package/cli/prompt.test.ts +202 -0
  213. package/cli/prompt.ts +1 -0
  214. package/cli/red-proof-edges.test.ts +78 -0
  215. package/cli/red-proof-failures.test.ts +82 -0
  216. package/cli/red-proof-tree.test.ts +157 -0
  217. package/cli/red-proof-verdict.test.ts +44 -0
  218. package/cli/red-proof.constants.ts +14 -0
  219. package/cli/red-proof.ts +202 -0
  220. package/cli/release/changelog-parse.ts +83 -0
  221. package/cli/release/changelog.test.ts +141 -0
  222. package/cli/release/changelog.ts +106 -0
  223. package/cli/release/gate-refusals.test.ts +85 -0
  224. package/cli/release/gate.test.ts +63 -0
  225. package/cli/release/gate.ts +70 -0
  226. package/cli/release/git.ts +66 -0
  227. package/cli/release/github.test.ts +128 -0
  228. package/cli/release/github.ts +46 -0
  229. package/cli/release/list-dir.test.ts +11 -0
  230. package/cli/release/list-dir.ts +6 -0
  231. package/cli/release/main.test.ts +48 -0
  232. package/cli/release/main.ts +51 -0
  233. package/cli/release/manifest.test.ts +24 -0
  234. package/cli/release/manifest.ts +34 -0
  235. package/cli/release/pack.test.ts +107 -0
  236. package/cli/release/pack.ts +76 -0
  237. package/cli/release/plan.ts +127 -0
  238. package/cli/release/publish-run.test.ts +98 -0
  239. package/cli/release/publish.test.ts +127 -0
  240. package/cli/release/publish.ts +125 -0
  241. package/cli/release/refuse.ts +5 -0
  242. package/cli/release/release-messages.constants.ts +96 -0
  243. package/cli/release/release-refusals.test.ts +149 -0
  244. package/cli/release/release.constants.ts +128 -0
  245. package/cli/release/release.test.ts +199 -0
  246. package/cli/release/release.ts +145 -0
  247. package/cli/release/version.test.ts +118 -0
  248. package/cli/release/version.ts +69 -0
  249. package/cli/release/wait.test.ts +101 -0
  250. package/cli/release/wait.ts +95 -0
  251. package/cli/script-diagnostics.test.ts +76 -0
  252. package/cli/script-diagnostics.ts +62 -0
  253. package/cli/scripts/board.ts +519 -0
  254. package/cli/scripts/browser.ts +994 -0
  255. package/cli/scripts/change-set.ts +105 -0
  256. package/cli/scripts/check-globals.ts +199 -0
  257. package/cli/scripts/ci-skips.constants.ts +17 -0
  258. package/cli/scripts/ci-skips.ts +118 -0
  259. package/cli/scripts/ci-wait-run.ts +28 -0
  260. package/cli/scripts/ci-wait.constants.ts +44 -0
  261. package/cli/scripts/ci-wait.ts +175 -0
  262. package/cli/scripts/ci.constants.ts +15 -0
  263. package/cli/scripts/ci.ts +208 -0
  264. package/cli/scripts/clean.ts +363 -0
  265. package/cli/scripts/comments-step.ts +15 -0
  266. package/cli/scripts/doctor.ts +828 -0
  267. package/cli/scripts/emit-agent-shell-tools.ts +91 -0
  268. package/cli/scripts/emit-mcp-policy.ts +402 -0
  269. package/cli/scripts/folder-map.ts +353 -0
  270. package/cli/scripts/gate-fat-tools.ts +1095 -0
  271. package/cli/scripts/gitignore-guard.ts +338 -0
  272. package/cli/scripts/google-workspace.ts +779 -0
  273. package/cli/scripts/hook-command.ts +72 -0
  274. package/cli/scripts/hook-input.ts +178 -0
  275. package/cli/scripts/hook-io.constants.ts +5 -0
  276. package/cli/scripts/hook-io.ts +46 -0
  277. package/cli/scripts/hooks-union.ts +469 -0
  278. package/cli/scripts/interactive.ts +30 -0
  279. package/cli/scripts/jev.ts +420 -0
  280. package/cli/scripts/job.ts +934 -0
  281. package/cli/scripts/jsonc.ts +9 -0
  282. package/cli/scripts/lessons.ts +564 -0
  283. package/cli/scripts/lint-baseline.ts +233 -0
  284. package/cli/scripts/lint-main.ts +24 -0
  285. package/cli/scripts/lint-skips.ts +139 -0
  286. package/cli/scripts/lint.constants.ts +6 -0
  287. package/cli/scripts/lint.ts +142 -0
  288. package/cli/scripts/listen.ts +962 -0
  289. package/cli/scripts/managed-text.ts +47 -0
  290. package/cli/scripts/orchestrate-parent.ts +1155 -0
  291. package/cli/scripts/parse-need.ts +81 -0
  292. package/cli/scripts/persist-handoff.ts +228 -0
  293. package/cli/scripts/persist-implementation.ts +276 -0
  294. package/cli/scripts/persist-plan.ts +888 -0
  295. package/cli/scripts/persist-roadmap.ts +478 -0
  296. package/cli/scripts/persist-tmp.ts +177 -0
  297. package/cli/scripts/persist.ts +54 -0
  298. package/cli/scripts/phase-files.ts +121 -0
  299. package/cli/scripts/prompt.ts +38 -0
  300. package/cli/scripts/purge-global-mcps.ts +313 -0
  301. package/cli/scripts/rejections-step.ts +37 -0
  302. package/cli/scripts/rtk-grok.ts +102 -0
  303. package/cli/scripts/scrub-spawn-prompt.ts +103 -0
  304. package/cli/scripts/scrub-text-lib.ts +58 -0
  305. package/cli/scripts/session-map.ts +69 -0
  306. package/cli/scripts/setup.ts +862 -0
  307. package/cli/scripts/skill-conflicts.ts +82 -0
  308. package/cli/scripts/speak.ts +370 -0
  309. package/cli/scripts/strategy.ts +168 -0
  310. package/cli/scripts/sync-global-settings.ts +316 -0
  311. package/cli/scripts/turn-steps.ts +249 -0
  312. package/cli/scripts/turn.ts +157 -0
  313. package/cli/scripts/typecheck-step.ts +43 -0
  314. package/cli/scripts/vscode-tasks.ts +175 -0
  315. package/cli/scripts/workspace-root.ts +160 -0
  316. package/cli/scripts/worktree.ts +806 -0
  317. package/cli/spawn.test.ts +34 -0
  318. package/cli/spawn.ts +27 -0
  319. package/cli/staged-change.constants.ts +11 -0
  320. package/cli/staged-change.ts +79 -0
  321. package/cli/stryker-preload.test.ts +50 -0
  322. package/cli/stryker-preload.ts +9 -0
  323. package/cli/sync/agents/frontmatter.test.ts +197 -0
  324. package/cli/sync/agents/frontmatter.ts +140 -0
  325. package/cli/sync/agents/hooks.test.ts +517 -0
  326. package/cli/sync/agents/hooks.ts +401 -0
  327. package/cli/sync/agents/rules.test.ts +229 -0
  328. package/cli/sync/agents/rules.ts +84 -0
  329. package/cli/sync/agents/sources.test.ts +375 -0
  330. package/cli/sync/agents/sources.ts +244 -0
  331. package/cli/sync/agents/subagents.test.ts +149 -0
  332. package/cli/sync/agents/subagents.ts +158 -0
  333. package/cli/sync/agents-text.test.ts +31 -0
  334. package/cli/sync/agents-text.ts +36 -0
  335. package/cli/sync/fixtures/copied.README.md +35 -0
  336. package/cli/sync/fixtures/copied.tgz +0 -0
  337. package/cli/sync/fixtures/maps/golden/INDEX.md +22 -0
  338. package/cli/sync/fixtures/maps-ws.tgz +0 -0
  339. package/cli/sync/git-files.test.ts +340 -0
  340. package/cli/sync/git-files.ts +197 -0
  341. package/cli/sync/git-hooks.test.ts +94 -0
  342. package/cli/sync/golden.test.ts +15 -0
  343. package/cli/sync/hooks-mode.test.ts +99 -0
  344. package/cli/sync/hosts.ts +28 -0
  345. package/cli/sync/knip-config.constants.ts +4 -0
  346. package/cli/sync/knip-config.test.ts +147 -0
  347. package/cli/sync/knip-config.ts +108 -0
  348. package/cli/sync/manifest.test.ts +78 -0
  349. package/cli/sync/manifest.ts +60 -0
  350. package/cli/sync/maps.test.ts +304 -0
  351. package/cli/sync/maps.ts +297 -0
  352. package/cli/sync/migrate.test.ts +2000 -0
  353. package/cli/sync/migrate.ts +1104 -0
  354. package/cli/sync/nightly-jobs.test.ts +63 -0
  355. package/cli/sync/nightly.constants.ts +48 -0
  356. package/cli/sync/nightly.test.ts +100 -0
  357. package/cli/sync/nightly.ts +75 -0
  358. package/cli/sync/outputs.test.ts +351 -0
  359. package/cli/sync/outputs.ts +168 -0
  360. package/cli/sync/oxlint-config.test.ts +178 -0
  361. package/cli/sync/oxlint-config.ts +168 -0
  362. package/cli/sync/release-jobs.test.ts +29 -0
  363. package/cli/sync/release-reports.test.ts +31 -0
  364. package/cli/sync/release-workflow.constants.ts +61 -0
  365. package/cli/sync/release-workflow.test.ts +192 -0
  366. package/cli/sync/release-workflow.ts +86 -0
  367. package/cli/sync/release.constants.ts +93 -0
  368. package/cli/sync/release.test.ts +187 -0
  369. package/cli/sync/release.ts +112 -0
  370. package/cli/sync/repo-dir.test.ts +371 -0
  371. package/cli/sync/repo-dir.ts +205 -0
  372. package/cli/sync/standards.constants.ts +8 -0
  373. package/cli/sync/standards.test.ts +206 -0
  374. package/cli/sync/standards.ts +179 -0
  375. package/cli/sync/stock-history.json +2796 -0
  376. package/cli/sync/stock-history.test.ts +66 -0
  377. package/cli/sync/stock-history.ts +84 -0
  378. package/cli/sync/stock.test.ts +47 -0
  379. package/cli/sync/stock.ts +24 -0
  380. package/cli/sync/trees.test.ts +621 -0
  381. package/cli/sync/trees.ts +280 -0
  382. package/cli/sync/validate.test.ts +299 -0
  383. package/cli/sync/validate.ts +402 -0
  384. package/cli/sync/workspace.test.ts +180 -0
  385. package/cli/sync/workspace.ts +138 -0
  386. package/cli/sync/write.test.ts +341 -0
  387. package/cli/sync/write.ts +231 -0
  388. package/cli/sync.test.ts +1495 -0
  389. package/cli/sync.ts +360 -0
  390. package/cli/tdd-scope.test.ts +36 -0
  391. package/cli/tdd-scope.ts +41 -0
  392. package/cli/test-files.ts +16 -0
  393. package/cli/ts-program.ts +69 -0
  394. package/cli/tsconfig.constants.ts +8 -0
  395. package/cli/workerstack-config.types.ts +21 -0
  396. package/dist/cli/env.d.ts +10 -0
  397. package/dist/cli/env.js +64 -0
  398. package/dist/presets/temp-root-env.d.ts +10 -0
  399. package/dist/presets/temp-root-env.js +20 -0
  400. package/dist/presets/temp-root.constants.d.ts +6 -0
  401. package/dist/presets/temp-root.constants.js +6 -0
  402. package/dist/presets/temp-root.d.ts +2 -0
  403. package/dist/presets/temp-root.js +60 -0
  404. package/dist/presets/vitest.constants.d.ts +16 -0
  405. package/dist/presets/vitest.constants.js +16 -0
  406. package/dist/presets/vitest.d.ts +11 -0
  407. package/dist/presets/vitest.js +67 -0
  408. package/dist/presets/workers-plugin.d.ts +10 -0
  409. package/dist/presets/workers-plugin.js +54 -0
  410. package/package.json +141 -4
  411. package/references/INDEX.md +100 -0
  412. package/references/browser.md +66 -0
  413. package/references/cascade.md +15 -0
  414. package/references/clasp.md +21 -0
  415. package/references/cloudflare.md +36 -0
  416. package/references/google-workspace.md +79 -0
  417. package/references/hooks.md +103 -0
  418. package/references/implementation-format.md +119 -0
  419. package/references/jev.md +56 -0
  420. package/references/lessons.md +73 -0
  421. package/references/listen.md +80 -0
  422. package/references/map.md +107 -0
  423. package/references/output.md +47 -0
  424. package/references/plan-format.md +264 -0
  425. package/references/review-loop.md +48 -0
  426. package/references/roadmap-format.md +104 -0
  427. package/references/rtk.md +27 -0
  428. package/references/scope.md +76 -0
  429. package/references/setup.md +42 -0
  430. package/references/speak.md +59 -0
  431. package/tsconfig/base.json +28 -0
  432. package/tsconfig/bun.d.ts +1 -0
  433. package/tsconfig/bun.json +8 -0
  434. package/tsconfig/reset.d.ts +1 -0
  435. package/tsconfig/strict.json +12 -0
  436. package/tsconfig/web.json +7 -0
  437. package/tsconfig/worker.d.ts +1 -0
  438. package/tsconfig/worker.json +8 -0
@@ -0,0 +1,71 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { CALL_SEPARATOR, QUOTED_SPAN } from "./check-manifests.constants.ts";
4
+ import type { PackageJson, Workspace } from "./sync/workspace.ts";
5
+
6
+ const BUN_PIN = /^bun@\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/;
7
+
8
+ /**
9
+ * `repo check`'s manifest lines, one per problem: the root first, then each workspace package by directory.
10
+ * A root with `workspaces` is not a package, so it needs `private` and `packageManager` but not `sideEffects`.
11
+ */
12
+ export function checkManifests({ root, manifest, packages }: Workspace): string[] {
13
+ const lines: string[] = [];
14
+ const isMonorepo = manifest.workspaces !== undefined;
15
+ if (fs.existsSync(path.join(root, "package.json"))) {
16
+ lines.push(
17
+ ...packageLines("package.json", manifest, !isMonorepo),
18
+ ...packageManagerLines(manifest),
19
+ ...chainedScriptLines(manifest),
20
+ );
21
+ }
22
+ for (const pkg of packages) lines.push(...packageLines(`${pkg.dir}/package.json`, pkg.manifest, true));
23
+ return lines;
24
+ }
25
+
26
+ function packageLines(file: string, manifest: PackageJson, needsSideEffects: boolean): string[] {
27
+ const lines: string[] = [];
28
+ if (manifest.private === undefined) lines.push(`${file}: "private" is missing; set true, or false to publish it`);
29
+ if (manifest.private === true && manifest.version !== undefined) {
30
+ lines.push(`${file}: private packages have no "version"; delete it`);
31
+ }
32
+ if (needsSideEffects && manifest.sideEffects !== false) {
33
+ lines.push(
34
+ manifest.sideEffects === undefined
35
+ ? `${file}: "sideEffects" is missing; set it to false`
36
+ : `${file}: "sideEffects" is ${JSON.stringify(manifest.sideEffects)}; set it to false and import CSS from an app entry`,
37
+ );
38
+ }
39
+ return lines;
40
+ }
41
+
42
+ function packageManagerLines({ packageManager }: PackageJson): string[] {
43
+ if (packageManager === undefined) {
44
+ return [`package.json: "packageManager" is missing; set it to "bun@${Bun.version}"`];
45
+ }
46
+ if (typeof packageManager === "string" && BUN_PIN.test(packageManager)) return [];
47
+ return [
48
+ `package.json: "packageManager" is ${JSON.stringify(packageManager)}; pin an exact version like "bun@${Bun.version}"`,
49
+ ];
50
+ }
51
+
52
+ function chainedScriptLines({ scripts }: PackageJson): string[] {
53
+ const lines: string[] = [];
54
+ const entries = typeof scripts === "object" && scripts !== null ? Object.entries(scripts) : [];
55
+ for (const [name, command] of entries) {
56
+ const calls = typeof command === "string" ? toolCalls(command) : 0;
57
+ if (calls <= 1) continue;
58
+ lines.push(
59
+ `package.json: "${name}" chains ${calls} tool calls with "&&" or ";"; make it one call, such as "repo ci"`,
60
+ );
61
+ }
62
+ return lines;
63
+ }
64
+
65
+ /** The non-empty segments of `command` split on `&&` and `;` outside quotes; `||` and `|` do not split. */
66
+ function toolCalls(command: string): number {
67
+ return command
68
+ .replace(QUOTED_SPAN, "x")
69
+ .split(CALL_SEPARATOR)
70
+ .filter((segment) => segment.trim() !== "").length;
71
+ }
@@ -0,0 +1,103 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { afterEach, describe, expect, it } from "vitest";
6
+ import { checkNightlyAt, nightlyProblems } from "./check-nightly.ts";
7
+ import type { Pack } from "./config.ts";
8
+ import { BASE_CONFIG } from "./fixtures/base-config.ts";
9
+ import { INSTALL_HINT } from "./mutate.constants.ts";
10
+ import type { PackageJson } from "./sync/workspace.ts";
11
+
12
+ const temps: string[] = [];
13
+
14
+ afterEach(() => {
15
+ for (const dir of temps.splice(0)) fs.rmSync(dir, { recursive: true, force: true });
16
+ });
17
+
18
+ const STRYKER: PackageJson = {
19
+ devDependencies: { "@stryker-mutator/core": "10.1.1", "@stryker-mutator/vitest-runner": "10.1.1" },
20
+ };
21
+ const INSTALL_LINE = `the release pack runs mutation tests nightly; ${INSTALL_HINT}`;
22
+ const NO_FILE_LINE =
23
+ "coverage.mutate (src/**/*.ts) matches no tracked file; set coverage.mutate in workerstack.config.ts";
24
+
25
+ const input = (manifest: PackageJson, tracked: string[], packs: Pack[] = ["release"]) => ({
26
+ config: { packs, agents: { hosts: [], skills: [] }, ...BASE_CONFIG },
27
+ workspace: { root: "/repo", manifest, packages: [] },
28
+ tracked,
29
+ });
30
+
31
+ describe("nightlyProblems", () => {
32
+ it("passes a root with both Stryker packages and a tracked file the globs match", () => {
33
+ expect(nightlyProblems(input(STRYKER, ["src/a.ts"]))).toEqual([]);
34
+ });
35
+
36
+ it("names the install when a Stryker package is missing", () => {
37
+ expect(nightlyProblems(input({}, ["src/a.ts"]))).toEqual([INSTALL_LINE]);
38
+ const half = { dependencies: { "@stryker-mutator/core": "10.1.1" } };
39
+ expect(nightlyProblems(input(half, ["src/a.ts"]))).toEqual([INSTALL_LINE]);
40
+ });
41
+
42
+ it("accepts Stryker as a dependency", () => {
43
+ const deps = { dependencies: STRYKER.devDependencies ?? {} };
44
+ expect(nightlyProblems(input(deps, ["src/a.ts"]))).toEqual([]);
45
+ });
46
+
47
+ it("names coverage.mutate when it matches no tracked file, tests and fixtures not counting", () => {
48
+ expect(nightlyProblems(input(STRYKER, ["src/a.test.ts", "lib/b.ts"]))).toEqual([NO_FILE_LINE]);
49
+ });
50
+
51
+ it("reports both problems, install first", () => {
52
+ expect(nightlyProblems(input({}, []))).toEqual([INSTALL_LINE, NO_FILE_LINE]);
53
+ });
54
+
55
+ it("checks nothing without the release pack", () => {
56
+ expect(nightlyProblems(input({}, [], ["docs"]))).toEqual([]);
57
+ });
58
+ });
59
+
60
+ /** A git repo holding `files`, committed or not per `commit`. */
61
+ function repo(files: Record<string, string>, commit = true): string {
62
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "check-nightly-"));
63
+ temps.push(root);
64
+ for (const [rel, text] of Object.entries(files)) {
65
+ fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true });
66
+ fs.writeFileSync(path.join(root, rel), text);
67
+ }
68
+ execFileSync("git", ["init", "-q"], { cwd: root });
69
+ if (commit) execFileSync("git", ["add", "."], { cwd: root });
70
+ return root;
71
+ }
72
+
73
+ const CONFIG = 'export default { packs: ["release"] };\n';
74
+ const MANIFEST = JSON.stringify({ name: "app", ...STRYKER });
75
+
76
+ describe("checkNightlyAt", () => {
77
+ it("reads the config, the root manifest and the tracked files", async () => {
78
+ const root = repo({ ["workerstack.config.ts"]: CONFIG, "package.json": "{}", "lib/a.ts": "" });
79
+ expect(await checkNightlyAt(root)).toEqual([INSTALL_LINE, NO_FILE_LINE]);
80
+ });
81
+
82
+ it("passes a repo with Stryker and a tracked source", async () => {
83
+ const root = repo({ "workerstack.config.ts": CONFIG, "package.json": MANIFEST, "src/a.ts": "" });
84
+ expect(await checkNightlyAt(root)).toEqual([]);
85
+ });
86
+
87
+ it("does not count an untracked file", async () => {
88
+ const root = repo({ "workerstack.config.ts": CONFIG, "package.json": MANIFEST }, true);
89
+ fs.mkdirSync(path.join(root, "src"));
90
+ fs.writeFileSync(path.join(root, "src/a.ts"), "");
91
+ expect(await checkNightlyAt(root)).toEqual([NO_FILE_LINE]);
92
+ });
93
+
94
+ it("leaves a bad config, an unreadable manifest and a missing git to the other checks", async () => {
95
+ expect(await checkNightlyAt(repo({ "workerstack.config.ts": "export default 3;\n" }))).toEqual([]);
96
+ expect(await checkNightlyAt(repo({ "workerstack.config.ts": CONFIG, "package.json": "[" }))).toEqual([]);
97
+ const bare = fs.mkdtempSync(path.join(os.tmpdir(), "check-nightly-bare-"));
98
+ temps.push(bare);
99
+ fs.writeFileSync(path.join(bare, "workerstack.config.ts"), CONFIG);
100
+ fs.writeFileSync(path.join(bare, "package.json"), MANIFEST);
101
+ expect(await checkNightlyAt(bare)).toEqual([]);
102
+ });
103
+ });
@@ -0,0 +1,37 @@
1
+ /** `repo check` under the release pack: the nightly mutation run needs Stryker and files to mutate. */
2
+ import { loadConfig, type ResolvedConfig } from "./config.ts";
3
+ import { INSTALL_HINT, STRYKER_CORE, STRYKER_RUNNER } from "./mutate.constants.ts";
4
+ import { selectFiles } from "./mutate-files.ts";
5
+ import { runGit } from "./sync/standards.ts";
6
+ import { readWorkspace, type Workspace } from "./sync/workspace.ts";
7
+
8
+ /** What the nightly problems are judged from: the config, the workspace and the tracked files. */
9
+ export type NightlyInput = { config: ResolvedConfig; workspace: Workspace; tracked: readonly string[] };
10
+
11
+ /** One line per problem that would make the nightly mutation job fail every night; none without the release pack. */
12
+ export function nightlyProblems({ config, workspace, tracked }: NightlyInput): string[] {
13
+ if (!config.packs.includes("release")) return [];
14
+ const lines: string[] = [];
15
+ const { dependencies = {}, devDependencies = {} } = workspace.manifest;
16
+ const installed = (name: string) => name in dependencies || name in devDependencies;
17
+ if (![STRYKER_CORE, STRYKER_RUNNER].every(installed)) {
18
+ lines.push(`the release pack runs mutation tests nightly; ${INSTALL_HINT}`);
19
+ }
20
+ const globs = config.coverage.mutate;
21
+ if (selectFiles(tracked, globs).length === 0) {
22
+ lines.push(
23
+ `coverage.mutate (${globs.join(", ")}) matches no tracked file; set coverage.mutate in workerstack.config.ts`,
24
+ );
25
+ }
26
+ return lines;
27
+ }
28
+
29
+ /** `nightlyProblems` for the checkout at `root`; a config, manifest or listing that cannot be read is another check's line. */
30
+ export async function checkNightlyAt(root: string): Promise<string[]> {
31
+ const loaded = await loadConfig(root);
32
+ const read = readWorkspace(root);
33
+ const listed = runGit(root, ["ls-files", "-z", "--cached"]);
34
+ if (!loaded.ok || !read.ok || listed.status !== 0) return [];
35
+ const tracked = listed.stdout.split("\0").filter((file) => file !== "");
36
+ return nightlyProblems({ config: loaded.config, workspace: read.workspace, tracked });
37
+ }
@@ -0,0 +1,46 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { afterEach, describe, expect, it } from "vitest";
4
+ import { ratchetProblems } from "./check-ratchets.ts";
5
+ import { removePlanted, repoOnMain, write } from "./fixtures/planted-repo.ts";
6
+
7
+ afterEach(removePlanted);
8
+
9
+ const FLOORS = "coverage-floors.json";
10
+ const FAILURES = "known-failures.json";
11
+ const BASELINE = ".repo/lint-baseline.json";
12
+ const HIGH = 61;
13
+
14
+ const floor = (branches: number) => ({ statements: 80, branches, functions: 90 });
15
+ const job = "cli/scripts/job.ts";
16
+
17
+ describe("ratchetProblems, files gone, unreadable or oddly shaped here", () => {
18
+ const main = {
19
+ [FLOORS]: { [job]: floor(HIGH) },
20
+ [job]: "export {};\n",
21
+ [FAILURES]: ["a > b"],
22
+ [BASELINE]: { "a.ts": { r: 2 } },
23
+ };
24
+
25
+ it("reads a deleted floors, list and baseline file as empty", () => {
26
+ const dir = repoOnMain(main);
27
+ for (const rel of [FLOORS, FAILURES, BASELINE]) fs.rmSync(path.join(dir, rel));
28
+ expect(ratchetProblems(dir)).toEqual([
29
+ `${FLOORS}: ${job} has no floor but main has one and the file exists; restore it`,
30
+ ]);
31
+ });
32
+
33
+ it("reads floors that are not JSON as empty, and a baseline that dropped the rule as zero", () => {
34
+ const dir = repoOnMain(main);
35
+ write(dir, { [FLOORS]: "{", [BASELINE]: { "a.ts": {} } });
36
+ expect(ratchetProblems(dir)).toEqual([
37
+ `${FLOORS}: ${job} has no floor but main has one and the file exists; restore it`,
38
+ ]);
39
+ });
40
+
41
+ it("fails a metric that lost its floor, and skips main rows that are no table", () => {
42
+ const dir = repoOnMain({ ...main, [FLOORS]: { [job]: floor(HIGH), "x.ts": 5 } });
43
+ write(dir, { [FLOORS]: { [job]: { statements: 80, functions: 90 } } });
44
+ expect(ratchetProblems(dir)).toEqual([`${FLOORS}: ${job} branches has no floor but main has ${HIGH}; restore it`]);
45
+ });
46
+ });
@@ -0,0 +1,49 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { afterEach, expect, it } from "vitest";
4
+ import { ratchetProblems } from "./check-ratchets.ts";
5
+ import { removePlanted, repoOnMain, write } from "./fixtures/planted-repo.ts";
6
+
7
+ afterEach(removePlanted);
8
+
9
+ const FILE = "mutation-floors.json";
10
+ const main = { [FILE]: { ".": 89, "packages/a": 70 }, "packages/a/package.json": "{}\n" };
11
+ const paths = { mutationFloors: FILE };
12
+
13
+ it("fails a lowered floor, naming the package and both numbers", () => {
14
+ const dir = repoOnMain(main);
15
+ write(dir, { [FILE]: { ".": 80, "packages/a": 70 } });
16
+ expect(ratchetProblems(dir, paths)).toEqual([`${FILE} lowers . from 89 to 80 against main; floors only rise`]);
17
+ });
18
+
19
+ it("passes an unchanged, raised or added floor", () => {
20
+ const dir = repoOnMain(main);
21
+ write(dir, { [FILE]: { ".": 90, "packages/a": 70, "packages/b": 1 } });
22
+ expect(ratchetProblems(dir, paths)).toEqual([]);
23
+ });
24
+
25
+ it("fails a dropped floor while its package dir exists, and passes one dropped with its package", () => {
26
+ const dir = repoOnMain(main);
27
+ write(dir, { [FILE]: { ".": 89 } });
28
+ expect(ratchetProblems(dir, paths)).toEqual([`${FILE} drops packages/a from 70; floors only rise`]);
29
+ fs.rmSync(path.join(dir, "packages/a"), { recursive: true });
30
+ expect(ratchetProblems(dir, paths)).toEqual([]);
31
+ });
32
+
33
+ it("reads the default path when none is given, and ignores a floors file main lacks", () => {
34
+ const dir = repoOnMain(main);
35
+ write(dir, { [FILE]: { ".": 1, "packages/a": 70 } });
36
+ expect(ratchetProblems(dir)).toEqual([`${FILE} lowers . from 89 to 1 against main; floors only rise`]);
37
+ const fresh = repoOnMain({ "a.txt": "a\n" });
38
+ write(fresh, { [FILE]: { ".": 1 } });
39
+ expect(ratchetProblems(fresh, paths)).toEqual([]);
40
+ });
41
+
42
+ it("treats a floors file of the wrong shape as having no floors", () => {
43
+ const dir = repoOnMain(main);
44
+ write(dir, { [FILE]: "[]\n" });
45
+ expect(ratchetProblems(dir, paths)).toEqual([
46
+ `${FILE} drops . from 89; floors only rise`,
47
+ `${FILE} drops packages/a from 70; floors only rise`,
48
+ ]);
49
+ });
@@ -0,0 +1,20 @@
1
+ /** The names `repo check`'s ratchets share. */
2
+
3
+ /** Where the coverage floors live unless the config says otherwise. */
4
+ export const DEFAULT_FLOORS = "coverage-floors.json";
5
+ /** Where the mutation floors live unless the config says otherwise. */
6
+ export const DEFAULT_MUTATION_FLOORS = "mutation-floors.json";
7
+ /** The git remote a clone's default branch is read from. */
8
+ export const ORIGIN = "origin";
9
+ /** The branch names tried when the current branch is the only one left. */
10
+ export const COMMON_BRANCHES = ["main", "master"] as const;
11
+ /** The `git diff --name-status` letter of a rename. */
12
+ export const RENAME = "R";
13
+ /** Separates the columns of `git diff --name-status`. */
14
+ export const TAB = "\t";
15
+ /** Separates the lines of git's output. */
16
+ export const NEWLINE = "\n";
17
+ /** What `defaultBranch` names when no branch is checked out. */
18
+ export const DETACHED = "HEAD";
19
+ /** The columns of a rename in `git diff --name-status`: the status, the old path and the new one. */
20
+ export const RENAME_COLUMNS = 3;
@@ -0,0 +1,190 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { afterEach, describe, expect, it } from "vitest";
4
+ import { ratchetProblems } from "./check-ratchets.ts";
5
+ import { git, removePlanted, repoOnMain, tempDir, write } from "./fixtures/planted-repo.ts";
6
+
7
+ afterEach(removePlanted);
8
+
9
+ const FLOORS = "coverage-floors.json";
10
+ const FAILURES = "known-failures.json";
11
+ const BASELINE = ".repo/lint-baseline.json";
12
+ const HIGH = 61;
13
+ const LOW = 58;
14
+
15
+ const floor = (branches: number) => ({ statements: 80, branches, functions: 90 });
16
+ const job = "cli/scripts/job.ts";
17
+
18
+ describe("ratchetProblems, floors", () => {
19
+ const main = { [FLOORS]: { [job]: floor(HIGH) }, [job]: "export {};\n" };
20
+
21
+ it("fails a lowered floor", () => {
22
+ const dir = repoOnMain(main);
23
+ write(dir, { [FLOORS]: { [job]: floor(LOW) } });
24
+ expect(ratchetProblems(dir)).toEqual([
25
+ `${FLOORS}: ${job} branches ${LOW} is below main's ${HIGH}; floors only rise`,
26
+ ]);
27
+ });
28
+
29
+ it("passes an unchanged or raised floor", () => {
30
+ const dir = repoOnMain(main);
31
+ write(dir, { [FLOORS]: { [job]: floor(HIGH + 1) } });
32
+ expect(ratchetProblems(dir)).toEqual([]);
33
+ });
34
+
35
+ it("fails a floor dropped while its source exists, and passes one dropped with its source", () => {
36
+ const dir = repoOnMain(main);
37
+ write(dir, { [FLOORS]: {} });
38
+ expect(ratchetProblems(dir)).toEqual([
39
+ `${FLOORS}: ${job} has no floor but main has one and the file exists; restore it`,
40
+ ]);
41
+ fs.rmSync(path.join(dir, job));
42
+ expect(ratchetProblems(dir)).toEqual([]);
43
+ });
44
+
45
+ it("passes a new file at any floor", () => {
46
+ const dir = repoOnMain(main);
47
+ write(dir, { [FLOORS]: { [job]: floor(HIGH), "cli/new.ts": floor(1) } });
48
+ expect(ratchetProblems(dir)).toEqual([]);
49
+ });
50
+ });
51
+
52
+ describe("ratchetProblems, renamed floors", () => {
53
+ const main = { [FLOORS]: { [job]: floor(HIGH) }, [job]: "export {};\n" };
54
+
55
+ it("fails a renamed file whose new key is below the old key's floor", () => {
56
+ const dir = repoOnMain(main);
57
+ git(dir, "mv", job, "cli/scripts/work.ts");
58
+ write(dir, { [FLOORS]: { "cli/scripts/work.ts": floor(LOW) } });
59
+ expect(ratchetProblems(dir)).toEqual([
60
+ `${FLOORS}: cli/scripts/work.ts branches ${LOW} is below main's ${HIGH} (renamed from ${job}); floors only rise`,
61
+ ]);
62
+ });
63
+
64
+ it("passes a renamed file that carries its floor", () => {
65
+ const dir = repoOnMain(main);
66
+ git(dir, "mv", job, "cli/scripts/work.ts");
67
+ write(dir, { [FLOORS]: { "cli/scripts/work.ts": floor(HIGH) } });
68
+ expect(ratchetProblems(dir)).toEqual([]);
69
+ });
70
+
71
+ it("reads the floors from the path it is given", () => {
72
+ const dir = repoOnMain({ "dev/floors.json": { [job]: floor(HIGH) }, [job]: "" });
73
+ write(dir, { "dev/floors.json": { [job]: floor(LOW) } });
74
+ expect(ratchetProblems(dir, { floors: "dev/floors.json" })).toHaveLength(1);
75
+ expect(ratchetProblems(dir)).toEqual([]);
76
+ });
77
+ });
78
+
79
+ describe("ratchetProblems, the main ref", () => {
80
+ const main = { [FLOORS]: { [job]: floor(HIGH) }, [job]: "" };
81
+
82
+ it("still fails a lowered floor when only origin/main exists", () => {
83
+ const origin = repoOnMain(main);
84
+ git(origin, "checkout", "-q", "main");
85
+ const dir = tempDir();
86
+ git(dir, "clone", "-q", origin, dir);
87
+ git(dir, "checkout", "-q", "-b", "feature");
88
+ git(dir, "branch", "-q", "-D", "main");
89
+ write(dir, { [FLOORS]: { [job]: floor(LOW) } });
90
+ expect(ratchetProblems(dir)).toHaveLength(1);
91
+ });
92
+ });
93
+
94
+ describe("ratchetProblems, no main ref", () => {
95
+ it("compares nothing in a repo with no main", () => {
96
+ const dir = tempDir();
97
+ git(dir, "init", "-q", "-b", "work");
98
+ write(dir, { [FLOORS]: { [job]: floor(LOW) }, [FAILURES]: ["a"] });
99
+ git(dir, "add", "-A");
100
+ git(dir, "commit", "-q", "-m", "work");
101
+ expect(ratchetProblems(dir)).toEqual([]);
102
+ });
103
+
104
+ it("compares nothing before the first commit", () => {
105
+ const dir = tempDir();
106
+ git(dir, "init", "-q", "-b", "main");
107
+ write(dir, { [FLOORS]: { [job]: floor(LOW) } });
108
+ expect(ratchetProblems(dir)).toEqual([]);
109
+ });
110
+
111
+ it("compares nothing for a file main does not have", () => {
112
+ const dir = repoOnMain({ "README.md": "x\n" });
113
+ write(dir, { [FLOORS]: { [job]: floor(LOW) }, [FAILURES]: ["a"], [BASELINE]: { "a.ts": { r: 1 } } });
114
+ expect(ratchetProblems(dir)).toEqual([]);
115
+ });
116
+ });
117
+
118
+ describe("ratchetProblems, known failures", () => {
119
+ const main = { [FAILURES]: ["a.test.ts > one", "a.test.ts > two"] };
120
+
121
+ it("fails an entry main's list lacks", () => {
122
+ const dir = repoOnMain(main);
123
+ write(dir, { [FAILURES]: ["a.test.ts > one", "a.test.ts > two", "a.test.ts > three"] });
124
+ expect(ratchetProblems(dir)).toEqual([
125
+ `${FAILURES}: "a.test.ts > three" is not on main's list; fix the case instead of listing it`,
126
+ ]);
127
+ });
128
+
129
+ it("fails a swapped entry though the list is no longer", () => {
130
+ const dir = repoOnMain(main);
131
+ write(dir, { [FAILURES]: ["a.test.ts > one", "a.test.ts > other"] });
132
+ expect(ratchetProblems(dir)).toEqual([
133
+ `${FAILURES}: "a.test.ts > other" is not on main's list; fix the case instead of listing it`,
134
+ ]);
135
+ });
136
+
137
+ it("passes a shrunk list", () => {
138
+ const dir = repoOnMain(main);
139
+ write(dir, { [FAILURES]: ["a.test.ts > one"] });
140
+ expect(ratchetProblems(dir)).toEqual([]);
141
+ });
142
+
143
+ it("reads the list from the path it is given", () => {
144
+ const dir = repoOnMain({ "dev/kf.json": ["x"] });
145
+ write(dir, { "dev/kf.json": ["x", "y"] });
146
+ expect(ratchetProblems(dir, { knownFailures: "dev/kf.json" })).toHaveLength(1);
147
+ });
148
+ });
149
+
150
+ describe("ratchetProblems, the lint baseline", () => {
151
+ const MAGIC = "repo(magic-number)";
152
+ const main = { [BASELINE]: { "a.ts": { [MAGIC]: 2 }, "b.ts": { [MAGIC]: 1 } } };
153
+
154
+ it("fails a rule whose total rises over main's", () => {
155
+ const dir = repoOnMain(main);
156
+ write(dir, { [BASELINE]: { "a.ts": { [MAGIC]: 3 }, "b.ts": { [MAGIC]: 1 } } });
157
+ expect(ratchetProblems(dir)).toEqual([
158
+ `${BASELINE}: ${MAGIC} totals 4, main has 3; fix the new hit instead of baselining it`,
159
+ ]);
160
+ });
161
+
162
+ it("fails a rule that rises in a new file even when another file fell", () => {
163
+ const dir = repoOnMain(main);
164
+ write(dir, { [BASELINE]: { "a.ts": { [MAGIC]: 1 }, "b.ts": { [MAGIC]: 1 }, "c.ts": { [MAGIC]: 2 } } });
165
+ expect(ratchetProblems(dir)).toHaveLength(1);
166
+ });
167
+
168
+ it("passes a rename that keeps the per-rule totals", () => {
169
+ const dir = repoOnMain(main);
170
+ write(dir, { [BASELINE]: { "x.ts": { [MAGIC]: 2 }, "b.ts": { [MAGIC]: 1 } } });
171
+ expect(ratchetProblems(dir)).toEqual([]);
172
+ });
173
+ });
174
+
175
+ describe("ratchetProblems, the lint baseline, lowered and seeded", () => {
176
+ const MAGIC = "repo(magic-number)";
177
+ const main = { [BASELINE]: { "a.ts": { [MAGIC]: 2 }, "b.ts": { [MAGIC]: 1 } } };
178
+
179
+ it("passes a lowered total", () => {
180
+ const dir = repoOnMain(main);
181
+ write(dir, { [BASELINE]: { "a.ts": { [MAGIC]: 1 } } });
182
+ expect(ratchetProblems(dir)).toEqual([]);
183
+ });
184
+
185
+ it("lets a rule main's baseline lacks be seeded", () => {
186
+ const dir = repoOnMain(main);
187
+ write(dir, { [BASELINE]: { "a.ts": { [MAGIC]: 2, "repo(new-rule)": 40 }, "b.ts": { [MAGIC]: 1 } } });
188
+ expect(ratchetProblems(dir)).toEqual([]);
189
+ });
190
+ });