@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,117 @@
1
+ /**
2
+ * Numbers that name nothing: a literal passes as the value of a `const` (directly, or in its array, object or
3
+ * arithmetic), of an enum member or of a `readonly` class property; else only 0 and 1, the identity values, and a 2
4
+ * that scales. A schema bound, an argument of `.max(…)` and its kin on a value with a `parse` method, must be a
5
+ * constant imported from a constants file or package.
6
+ */
7
+ import ts from "typescript";
8
+ import { hitAt, isConstantsModule, isConstDeclaration } from "./magic-nodes.ts";
9
+ import { MAGIC_NUMBER } from "../lint/script-rules.ts";
10
+ import type { MagicHit } from "./magic-hit.ts";
11
+
12
+ const SCHEMA_BOUNDS = ["min", "max", "length", "gt", "gte", "lt", "lte", "multipleOf", "size"];
13
+ /** A schema is a value with this method. */
14
+ const PARSE = "parse";
15
+ const IDENTITIES = [0, 1];
16
+ const SCALE = 2;
17
+ const SCALING = [
18
+ ts.SyntaxKind.AsteriskToken,
19
+ ts.SyntaxKind.SlashToken,
20
+ ts.SyntaxKind.PercentToken,
21
+ ts.SyntaxKind.AsteriskAsteriskToken,
22
+ ];
23
+ const ARITHMETIC = [...SCALING, ts.SyntaxKind.PlusToken, ts.SyntaxKind.MinusToken];
24
+ /** What a literal sits in and still names what the const, enum member or readonly field around it names. */
25
+ const CONTAINERS = [
26
+ ts.SyntaxKind.ParenthesizedExpression,
27
+ ts.SyntaxKind.AsExpression,
28
+ ts.SyntaxKind.SatisfiesExpression,
29
+ ts.SyntaxKind.ArrayLiteralExpression,
30
+ ts.SyntaxKind.ObjectLiteralExpression,
31
+ ts.SyntaxKind.PropertyAssignment,
32
+ ts.SyntaxKind.PrefixUnaryExpression,
33
+ ];
34
+
35
+ const NAMES_NOTHING = (text: string) => `${text} names nothing; give it a named const`;
36
+ const BOUND = (method: string, arg: ts.Node) =>
37
+ `.${method}(${arg.getText()}) is a schema bound; import it from a *.constants.ts file or a constants package`;
38
+
39
+ const isArithmetic = (node: ts.Node) => ts.isBinaryExpression(node) && ARITHMETIC.includes(node.operatorToken.kind);
40
+ const isScaling = (node: ts.Node) => ts.isBinaryExpression(node) && SCALING.includes(node.operatorToken.kind);
41
+
42
+ /** The literal with its minus: `-1` is one value. */
43
+ function unitOf(literal: ts.NumericLiteral): ts.Expression {
44
+ const { parent } = literal;
45
+ return ts.isPrefixUnaryExpression(parent) && parent.operator === ts.SyntaxKind.MinusToken ? parent : literal;
46
+ }
47
+
48
+ /** Whether `unit`, climbed through its containers, is what a `const`, an enum member or a readonly field holds. */
49
+ function isNamed(unit: ts.Node): boolean {
50
+ let node = unit;
51
+ while (CONTAINERS.includes(node.parent.kind) || isArithmetic(node.parent)) node = node.parent;
52
+ const holder = node.parent;
53
+ if (ts.isVariableDeclaration(holder)) return isConstDeclaration(holder);
54
+ if (ts.isPropertyDeclaration(holder)) return (ts.getCombinedModifierFlags(holder) & ts.ModifierFlags.Readonly) !== 0;
55
+ return ts.isEnumMember(holder);
56
+ }
57
+
58
+ /** The method of a schema-bound call `node` is, like `max` in `z.string().max(2048)`; null for any other node. */
59
+ function boundOf(node: ts.Node, checker: ts.TypeChecker): string | null {
60
+ if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression)) return null;
61
+ const method = node.expression.name.text;
62
+ if (!SCHEMA_BOUNDS.includes(method)) return null;
63
+ const receiver = checker.getTypeAtLocation(node.expression.expression);
64
+ return receiver.getProperty(PARSE) === undefined ? null : method;
65
+ }
66
+
67
+ function numberHit(literal: ts.NumericLiteral, checker: ts.TypeChecker): MagicHit | null {
68
+ const unit = unitOf(literal);
69
+ if (ts.isLiteralTypeNode(unit.parent)) return null;
70
+ const magnitude = Number(literal.text);
71
+ const value = unit === literal ? magnitude : -magnitude;
72
+ if (IDENTITIES.includes(value)) return null;
73
+ if (value === SCALE && unit === literal && isScaling(unit.parent)) return null;
74
+ const method = boundOf(unit.parent, checker);
75
+ if (method !== null) return hitAt(unit, MAGIC_NUMBER, BOUND(method, unit));
76
+ return isNamed(unit) ? null : hitAt(unit, MAGIC_NUMBER, NAMES_NOTHING(unit.getText()));
77
+ }
78
+
79
+ /**
80
+ * Whether a bound argument names a local `const` or an import from a module that is not a constants file or
81
+ * package; a parameter, a `let` or anything computed passes, being no fixed number.
82
+ */
83
+ function isLocalBound(arg: ts.Expression, checker: ts.TypeChecker): boolean {
84
+ let root = arg;
85
+ while (ts.isPropertyAccessExpression(root)) root = root.expression;
86
+ if (!ts.isIdentifier(root)) return false;
87
+ const declaration = checker.getSymbolAtLocation(root)?.declarations?.[0];
88
+ if (declaration === undefined) return false;
89
+ const imported = ts.findAncestor(declaration, ts.isImportDeclaration);
90
+ if (imported === undefined) return ts.isVariableDeclaration(declaration) && isConstDeclaration(declaration);
91
+ const specifier =
92
+ imported.moduleSpecifier /* an import that parses names its module in a string literal */ as ts.StringLiteral;
93
+ return !isConstantsModule(specifier.text);
94
+ }
95
+
96
+ function boundHits(call: ts.CallExpression, checker: ts.TypeChecker): MagicHit[] {
97
+ const method = boundOf(call, checker);
98
+ if (method === null) return [];
99
+ return call.arguments
100
+ .filter((arg) => isLocalBound(arg, checker))
101
+ .map((arg) => hitAt(arg, MAGIC_NUMBER, BOUND(method, arg)));
102
+ }
103
+
104
+ /** Every magic number of `file` and every schema bound not imported from a constants home, in source order. */
105
+ export function magicNumbers(file: ts.SourceFile, checker: ts.TypeChecker): MagicHit[] {
106
+ const hits: MagicHit[] = [];
107
+ const visit = (node: ts.Node): void => {
108
+ if (ts.isNumericLiteral(node)) {
109
+ const found = numberHit(node, checker);
110
+ if (found !== null) hits.push(found);
111
+ }
112
+ if (ts.isCallExpression(node)) hits.push(...boundHits(node, checker));
113
+ ts.forEachChild(node, visit);
114
+ };
115
+ visit(file);
116
+ return hits;
117
+ }
@@ -0,0 +1,38 @@
1
+ import { afterEach, expect, it } from "vitest";
2
+ import { cleanTemps, COMPARED, COPIES, hit, magicOf, STRING } from "./fixtures/magic-repo.ts";
3
+
4
+ afterEach(cleanTemps);
5
+
6
+ it("refuses a string compared to string | undefined, unknown or any, from either side", () => {
7
+ const kinds = [
8
+ "export function k(a: string | undefined, b: 'a' | null, c: unknown, d: any): boolean {",
9
+ " return a === 'on' || b === 'a' || 'on' !== c || d != `on`;",
10
+ "}",
11
+ "",
12
+ ].join("\n");
13
+ expect(magicOf({ "src/kinds.ts": kinds })).toEqual([
14
+ hit("src/kinds.ts:2:16", STRING, COMPARED("on")),
15
+ hit("src/kinds.ts:2:37", STRING, COMPARED("on")),
16
+ hit("src/kinds.ts:2:56", STRING, COMPARED("on")),
17
+ ]);
18
+ });
19
+
20
+ it("reports a const copy once at its declaration, through an import alias, and not one in a constants file", () => {
21
+ const files = {
22
+ "src/modes.ts": 'export const SLOW = "slow";\nexport const LAZY = ("lazy") as const;\nexport const SEP = "/";\n',
23
+ "src/modes.constants.ts": 'export const QUICK = "quick";\n',
24
+ "src/use.ts": [
25
+ 'import { LAZY, SEP, SLOW as S } from "./modes.ts";',
26
+ 'import { QUICK } from "./modes.constants.ts";',
27
+ "let late = 'x';",
28
+ "const N = 5;",
29
+ "export const is = (m: string, n: number) =>",
30
+ " m === S || m == S || m === LAZY || m === QUICK || m === SEP || m === late || n === N || m === undefined;",
31
+ "",
32
+ ].join("\n"),
33
+ };
34
+ expect(magicOf(files)).toEqual([
35
+ hit("src/modes.ts:1:14", STRING, COPIES("SLOW", "slow")),
36
+ hit("src/modes.ts:2:14", STRING, COPIES("LAZY", "lazy")),
37
+ ]);
38
+ });
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Strings compared to a value the type checker leaves untyped: in `===` `!==` `==` `!=` or a `case`, a string literal
3
+ * against a `string`, `any` or `unknown` (a literal union, template literal or branded string passes), and a local
4
+ * `const` copy of one, reported at its declaration. An empty or punctuation-only string passes.
5
+ */
6
+ import ts from "typescript";
7
+ import { CONSTANTS_FILE, constString, hitAt, isMeaningful } from "./magic-nodes.ts";
8
+ import { MAGIC_STRING } from "../lint/script-rules.ts";
9
+ import type { MagicHit } from "./magic-hit.ts";
10
+
11
+ /** The checker of the program, and whether a file is one the check reports in. */
12
+ export type Context = { checker: ts.TypeChecker; owns: (fileName: string) => boolean };
13
+
14
+ const EQUALITY = [
15
+ ts.SyntaxKind.EqualsEqualsEqualsToken,
16
+ ts.SyntaxKind.ExclamationEqualsEqualsToken,
17
+ ts.SyntaxKind.EqualsEqualsToken,
18
+ ts.SyntaxKind.ExclamationEqualsToken,
19
+ ];
20
+ const NULLISH = ts.TypeFlags.Null | ts.TypeFlags.Undefined;
21
+ const PLAIN = ts.TypeFlags.String | ts.TypeFlags.Any | ts.TypeFlags.Unknown;
22
+
23
+ const COMPARED = (text: string) =>
24
+ `${JSON.stringify(text)} is compared to a plain string; type the value as a literal union or brand, or import the string from a *.constants.ts file`;
25
+ const COPIES = (name: string, text: string) =>
26
+ `${name} copies ${JSON.stringify(text)} locally to compare to a plain string; move it to a *.constants.ts file`;
27
+
28
+ /** `string`, `any` or `unknown`, alone or in a union beside `null` or `undefined`. */
29
+ function isUntyped(type: ts.Type): boolean {
30
+ if (type.isUnion()) return type.types.some((member) => (member.flags & NULLISH) === 0 && isUntyped(member));
31
+ return (type.flags & PLAIN) !== 0;
32
+ }
33
+
34
+ /** Each side of a comparison with the side it is compared to. */
35
+ function comparedPairs(node: ts.Node): [ts.Expression, ts.Expression][] {
36
+ if (ts.isBinaryExpression(node) && EQUALITY.includes(node.operatorToken.kind))
37
+ return [
38
+ [node.left, node.right],
39
+ [node.right, node.left],
40
+ ];
41
+ return ts.isCaseClause(node) ? [[node.expression, node.parent.parent.expression]] : [];
42
+ }
43
+
44
+ /** The declaration of the `const` an identifier names, through an import alias; null for anything else. */
45
+ function constOf(id: ts.Identifier, checker: ts.TypeChecker): ts.VariableDeclaration | null {
46
+ const symbol = checker.getSymbolAtLocation(id);
47
+ const target =
48
+ symbol !== undefined && (symbol.flags & ts.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(symbol) : symbol;
49
+ const declaration = target?.valueDeclaration;
50
+ return declaration !== undefined && ts.isVariableDeclaration(declaration) ? declaration : null;
51
+ }
52
+
53
+ /** The hit at a local `const` string the identifier names, outside a constants file; null when it names none. */
54
+ function copyHit(id: ts.Identifier, { checker, owns }: Context): MagicHit | null {
55
+ const declaration = constOf(id, checker);
56
+ if (declaration === null) return null;
57
+ const text = constString(declaration);
58
+ const { fileName } = declaration.getSourceFile();
59
+ if (text === null || !owns(fileName) || CONSTANTS_FILE.test(fileName)) return null;
60
+ return hitAt(declaration.name, MAGIC_STRING, COPIES(declaration.name.getText(), text));
61
+ }
62
+
63
+ /** The hit `side` would make compared to a plain string: a literal at itself, a const copy at its declaration. */
64
+ function sideHit(side: ts.Expression, context: Context): MagicHit | null {
65
+ if (isMeaningful(side)) return hitAt(side, MAGIC_STRING, COMPARED(side.text));
66
+ return ts.isIdentifier(side) ? copyHit(side, context) : null;
67
+ }
68
+
69
+ /** Every magic string of `file`; a copy's hit is at its declaration, which `owns` must own. */
70
+ export function magicStrings(file: ts.SourceFile, context: Context): MagicHit[] {
71
+ const hits: MagicHit[] = [];
72
+ const visit = (node: ts.Node): void => {
73
+ for (const [side, other] of comparedPairs(node)) {
74
+ const found = sideHit(side, context);
75
+ if (found !== null && isUntyped(context.checker.getTypeAtLocation(other))) hits.push(found);
76
+ }
77
+ ts.forEachChild(node, visit);
78
+ };
79
+ visit(file);
80
+ return hits;
81
+ }