@avi2dg/checks 0.50.1 → 0.52.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 (45) hide show
  1. package/.bun-version +1 -0
  2. package/CHANGELOG.md +27 -0
  3. package/README.md +24 -249
  4. package/commitlint.config.ts +0 -1
  5. package/dist/mutation/unit-test-order.js +1 -1
  6. package/dist/presets/knip.d.ts +1 -1
  7. package/dist/presets/knip.js +1 -1
  8. package/dist/templates/how-to.md +1 -1
  9. package/dist/templates/readme.md +1 -1
  10. package/dist/templates/tutorial.md +1 -1
  11. package/docs/bins.md +67 -0
  12. package/docs/gates/checks-advisories.md +2 -2
  13. package/docs/gates/checks-browser.md +5 -1
  14. package/docs/gates/checks-ci-wiring.md +18 -9
  15. package/docs/gates/checks-commit-identity.md +6 -3
  16. package/docs/gates/checks-copy.md +4 -0
  17. package/docs/gates/checks-docs.md +24 -3
  18. package/docs/gates/checks-exports.md +1 -1
  19. package/docs/gates/checks-frontend-syntax.md +5 -1
  20. package/docs/gates/checks-lint.md +2 -2
  21. package/docs/gates/checks-mutation-baseline.md +36 -7
  22. package/docs/gates/checks-mutation-compare.md +3 -3
  23. package/docs/gates/checks-mutation-scope.md +1 -1
  24. package/docs/gates/checks-mutation.md +26 -9
  25. package/docs/gates/checks-night-run.md +1 -1
  26. package/docs/gates/checks-secrets.md +2 -2
  27. package/docs/gates/checks-unused.md +1 -1
  28. package/docs/how-to/set-up-a-repository.md +142 -0
  29. package/docs/how-to/turn-on-the-css-families.md +35 -0
  30. package/docs/how-to/upgrade-the-kit.md +42 -0
  31. package/docs/shipped-files.md +36 -0
  32. package/package.json +13 -1
  33. package/src/delivery/bun-pin.ts +19 -5
  34. package/src/delivery/ci-wiring.ts +11 -77
  35. package/src/delivery/commit-identity.ts +14 -7
  36. package/src/delivery/runner-policy.ts +385 -0
  37. package/src/delivery/workflow-references.ts +1 -1
  38. package/src/docs/doc-templates.ts +1 -1
  39. package/src/docs/doc-versions.ts +137 -0
  40. package/src/docs/docs.ts +7 -0
  41. package/src/testing/mutation-baseline-full.ts +68 -0
  42. package/src/testing/mutation-baseline-saved.ts +52 -0
  43. package/src/testing/mutation-baseline.ts +27 -23
  44. package/src/testing/mutation-scope-graph.ts +89 -0
  45. package/src/testing/mutation-scope.ts +48 -93
package/.bun-version ADDED
@@ -0,0 +1 @@
1
+ 1.4.3
package/CHANGELOG.md CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  Every release of `@avi2dg/checks`, newest first, written by the release from its conventional commits.
4
4
 
5
+ ## 0.52.0
6
+
7
+ Released 2026-10-25.
8
+
9
+ ### Features
10
+
11
+ - **docs:** short front door README and refuse hand copied pinned versions [#206](https://github.com/avi2d/checks/pull/206)
12
+ - **testing:** add 28-day refresh window for restored mutation baselines [#205](https://github.com/avi2d/checks/pull/205)
13
+
14
+ ### Fixes
15
+
16
+ - **delivery:** refuse fork-reachable self-hosted runners, read fleet pins from config [#204](https://github.com/avi2d/checks/pull/204)
17
+ - upgrade fast-uri and zod past the October advisories [#202](https://github.com/avi2d/checks/pull/202)
18
+
19
+ ## 0.51.0
20
+
21
+ Released 2026-10-23.
22
+
23
+ ### Features
24
+
25
+ - **testing:** reuse full baseline results for unchanged files [#197](https://github.com/avi2d/checks/pull/197)
26
+
27
+ ### Fixes
28
+
29
+ - **delivery:** accept GitHub display name on commits GitHub made [#198](https://github.com/avi2d/checks/pull/198)
30
+ - **testing:** correct unit test fallback order wording to Bun default directory order [#195](https://github.com/avi2d/checks/pull/195)
31
+
5
32
  ## 0.50.1
6
33
 
7
34
  Released 2026-10-20.
package/README.md CHANGED
@@ -1,276 +1,51 @@
1
1
  # checks
2
2
 
3
- `@avi2dg/checks` is the kit of deterministic checks a TypeScript repository installs to hold its code, tests, commits, CI wiring and docs to one shared standard.
4
- It ships the lint gates `checks-lint` runs over each pull request, the test runners, and a `defineConfig` for oxlint, Knip, dependency-cruiser and stylelint.
5
- It also ships the configs a repository extends for tsc, commitlint, bun and Stryker.
6
- Each repository owns its workflows and native tool configs, as [Native settings](docs/configs/native-settings.md) maps.
3
+ `@avi2dg/checks` turns each rule a reviewer would otherwise have to remember into a program that runs on every pull request.
4
+ One command, `checks-lint`, judges a TypeScript repository's code, tests, commits, CI wiring and docs, and each failure names the file or line to fix.
5
+ Every Bun repository it holds moves to a new rule by upgrading one package, rather than by copying configs between repositories.
7
6
 
8
7
  ## Before you begin
9
8
 
10
- <!-- generated prerequisites: bun run build writes it from package.json, .bun-version and scripts/doc-blocks.ts -->
11
-
12
9
  - A git repository, whose history the range gates read.
13
- - Bun 1.4.3, which runs every bin.
14
- - The peer dependencies, at the exact versions the kit pins:
15
- - `@effect/tsgo` 0.45.0
16
- - `@swc/core` 1.16.2
17
- - `dependency-cruiser` 18.4.0
18
- - `effect` 4.0.0
19
- - `jscpd` 5.3.2
20
- - `oxlint` 1.83.0
21
- - `oxlint-tsgolint` 7.0.2002
22
- - `typescript` 7.0.2
23
- - The optional peers, which only an opt-in check loads, at the exact versions the kit pins:
24
- - `@axe-core/playwright` 4.13.0
25
- - `html-validate` 11.16.0
26
- - `playwright-core` 1.63.0
27
- - `postcss-html` 2.0.0
28
- - `postcss-value-parser` 4.2.0
29
- - `stylelint` 17.16.0
30
- - `stylelint-config-standard` 40.0.0
31
- - `stylelint-plugin-use-baseline` 1.4.7
32
-
33
- <!-- end generated prerequisites -->
10
+ - Bun, at the version the kit's `.bun-version` pins.
34
11
 
35
12
  ## Install
36
13
 
37
- To consume the kit from a repository:
14
+ To hold a repository to the kit:
38
15
 
39
- 1. Add the kit and its peers:
40
-
41
- <!-- generated install: bun run build writes it from package.json and scripts/doc-blocks.ts -->
16
+ 1. Add the kit:
42
17
 
43
18
  ```sh
44
- bun add -d @avi2dg/checks @effect/tsgo@0.45.0 @swc/core@1.16.2 dependency-cruiser@18.4.0 effect@4.0.0 jscpd@5.3.2 oxlint@1.83.0 oxlint-tsgolint@7.0.2002 typescript@7.0.2
45
- ```
46
-
47
- <!-- end generated install -->
48
-
49
- 1. Write `oxlint.config.ts` with the kit's builder, saying whether the sources are Effect programs:
50
-
51
- ```ts
52
- import { defineConfig } from "@avi2dg/checks/oxlint";
53
-
54
- export default defineConfig({ effect: true });
19
+ bun add -d @avi2dg/checks
55
20
  ```
56
21
 
57
- 1. Keep oxlint out of `node_modules/` through `.gitignore`:
58
-
59
- ```
60
- node_modules/
61
- ```
62
-
63
- 1. Extend the tsconfig fragment in `tsconfig.json`:
64
-
65
- ```json
66
- {
67
- "extends": "@avi2dg/checks/tsconfig.effect.json"
68
- }
69
- ```
70
-
71
- 1. Copy the bunfig preset:
22
+ 1. Pin the Bun version the kit runs on:
72
23
 
73
24
  ```sh
74
- cp node_modules/@avi2dg/checks/bunfig.toml bunfig.toml
75
- ```
76
-
77
- 1. Name the files nothing imports in `knip.config.ts`:
78
-
79
- ```ts
80
- import { defineConfig } from "@avi2dg/checks/knip";
81
-
82
- export default defineConfig({ entry: ["src/index.ts"] });
83
- ```
84
-
85
- 1. Write `dependency-cruiser.config.ts` only when the kit's import rules need an entry point or a boundary of the repository's own:
86
-
87
- ```ts
88
- import { defineConfig } from "@avi2dg/checks/dependency-cruiser";
89
-
90
- export default defineConfig({ orphans: ["^src/bin[.]ts$"] });
91
- ```
92
-
93
- 1. Add scripts to `package.json`, replacing the build entry with the repository's own build command:
94
-
95
- ```json
96
- "build": "bun build src/index.ts --outdir dist --target node && checks-effect-scope",
97
- "lint": "oxlint && checks-lint",
98
- "typecheck": "tsc --noEmit && effect-tsgo diagnostics --project tsconfig.json --format text --strict",
99
- "test": "checks-test"
100
- ```
101
-
102
- 1. Write the Bun version [Before you begin](#before-you-begin) names to `.bun-version`, which [checks-ci-wiring](docs/gates/checks-ci-wiring.md#bun-version) holds every setup-bun step to.
103
-
104
- 1. Run the scripts on every pull request in `.github/workflows/ci.yml`, fetching the whole history the range needs:
105
-
106
- ```yaml
107
- on:
108
- pull_request:
109
- jobs:
110
- checks:
111
- runs-on: ubuntu-latest
112
- steps:
113
- - uses: actions/checkout@v5
114
- with:
115
- fetch-depth: 0
116
- - uses: oven-sh/setup-bun@v2
117
- with:
118
- bun-version-file: .bun-version
119
- - run: bun install --frozen-lockfile
120
- - run: bun run build
121
- - run: git diff --exit-code
122
- - run: bun run lint
123
- - run: bun run typecheck
124
- - run: bun run test
25
+ cp node_modules/@avi2dg/checks/.bun-version .bun-version
125
26
  ```
126
27
 
127
- Lint the pull request title in the same job with one step:
28
+ 1. Run the gates:
128
29
 
129
- ```yaml
130
- - id: title
131
- name: lint the title
132
- env:
133
- PR_TITLE: ${{ github.event.pull_request.title }}
134
- GH_TOKEN: ${{ github.token }}
135
- run: bunx checks-commit-title
136
- ```
137
-
138
- A repository whose branch protection requires `commitlint` keeps that required status name while `commitlint.yml` goes away.
139
- The same job reports the title step's outcome under that name on every run, which needs `statuses: write`:
140
-
141
- ```yaml
142
- - name: report the title as commitlint
143
- if: always()
144
- env:
145
- GH_TOKEN: ${{ github.token }}
146
- HEAD_SHA: ${{ github.event.pull_request.head.sha }}
147
- OUTCOME: ${{ steps.title.outcome }}
148
- run: |
149
- state=failure
150
- if [ "$OUTCOME" = success ]; then state=success; fi
151
- gh api "repos/$GITHUB_REPOSITORY/statuses/${HEAD_SHA:-$GITHUB_SHA}" -f state="$state" -f context=commitlint -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" --silent
30
+ ```sh
31
+ bunx checks-lint
152
32
  ```
153
33
 
154
- A private repository sets `runs-on: ${{ vars.CI_RUNS_ON || 'ubuntu-latest' }}` on each job, as [checks-ci-wiring](docs/gates/checks-ci-wiring.md#runners) requires.
155
- `checks-effect-scope` writes the Effect paths of `oxlint.config.ts` and the kit's severities into `tsconfig.json`, as [The Effect rules](docs/configs/effect-rules.md#language-service) says.
156
- `bun run lint` then ends with `checks-lint: <count> gate(s) pass`.
157
-
158
- ## What runs
159
-
160
- `checks-lint` runs each of these gates that applies to the repository, and names every one that fails.
161
- A gate reads either the working tree or the range `checks-lint` resolves.
162
- The table groups the gates by vector, the part of a repository each one judges.
163
-
164
- <!-- generated gates: bun run build writes it from KIT_GATES in src/core/gates.ts and scripts/doc-blocks.ts -->
165
-
166
- | Vector | Gate | Reads | Runs in |
167
- | --- | --- | --- | --- |
168
- | complexity | [`checks-suppressions-ratchet`](docs/gates/checks-suppressions-ratchet.md) | the range | every repository |
169
- | complexity | [`checks-repetition`](docs/gates/checks-repetition.md) | the range | a repository tracking `*.ts` or `*.tsx` |
170
- | complexity | [`checks-unused`](docs/gates/checks-unused.md) | the working tree | a repository tracking `*.ts` or `*.tsx` or `*.astro` |
171
- | complexity | [`checks-exports`](docs/gates/checks-exports.md) | the range | a repository tracking `*.ts` or `*.tsx` |
172
- | quality | [`checks-lint-coverage`](docs/gates/checks-lint-coverage.md) | the working tree | a repository tracking `*.ts` or `*.tsx` or `*.astro` |
173
- | quality | [`checks-comment-gate`](docs/gates/checks-comment-gate.md) | the range | every repository |
174
- | quality | [`checks-effect-scope`](docs/gates/checks-effect-scope.md) | the working tree | a repository tracking `oxlint.config.ts` |
175
- | quality | [`checks-frontend-syntax`](docs/gates/checks-frontend-syntax.md) | the working tree | a repository tracking `frontend-syntax.json` |
176
- | quality | [`checks-css-size`](docs/gates/checks-css-size.md) | the working tree | a repository tracking `*.css` |
177
- | quality | [`checks-no-plain-js`](docs/gates/checks-no-plain-js.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
178
- | testing | [`checks-test-layout`](docs/gates/checks-test-layout.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
179
- | testing | [`checks-quarantine-clock`](docs/gates/checks-quarantine-clock.md) | the range | every repository |
180
- | docs | [`checks-docs`](docs/gates/checks-docs.md) | the range, and every agent file at the head commit | every repository |
181
- | docs | [`checks-copy`](docs/gates/checks-copy.md) | the working tree | a repository tracking `copy.json` |
182
- | delivery | [`checks-commit-identity`](docs/gates/checks-commit-identity.md) | the range | every repository |
183
- | delivery | [`checks-ci-wiring`](docs/gates/checks-ci-wiring.md) | the working tree | every repository |
184
- | delivery | [`checks-secrets`](docs/gates/checks-secrets.md) | the range | every repository |
185
- | dependencies | [`checks-imports`](docs/gates/checks-imports.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
186
- | dependencies | [`checks-advisories`](docs/gates/checks-advisories.md) | the range | a repository tracking `bun.lock` |
187
-
188
- <!-- end generated gates -->
189
-
190
- These bins run on their own:
191
-
192
- - [`checks-test`](docs/gates/checks-test.md) runs the suite as `scripts.test` and refuses a skip without a reason at its test site.
193
- - [`checks-flake`](docs/gates/checks-flake.md) runs the suite on a schedule and records the seeds a flaky test fails with.
194
- - [`checks-mutation`](docs/gates/checks-mutation.md) runs Stryker for scoped checks and refuses a full run outside CI.
195
- - [`checks-mutation-compare`](docs/gates/checks-mutation-compare.md) compares the mutants of two reports and lists each one that regresses.
196
- - [`checks-mutation-baseline`](docs/gates/checks-mutation-baseline.md) restores the newest mutation baseline from `main`, saves it on a self-hosted runner's disk in place of an artifact, and deletes superseded baselines after a `main` run.
197
- - [`checks-mutation-scope`](docs/gates/checks-mutation-scope.md) turns a branch's diff into the files its mutation runs mutate.
198
- - [`checks-subsumed-tests`](docs/gates/checks-subsumed-tests.md) lists each test another test subsumes in a mutation run.
199
- - [`checks-night-run`](docs/gates/checks-night-run.md) opens or comments on one GitHub issue per finding of a night run on `main`, each file whose mutation score fell and each failing test.
200
- - [`checks-changelog`](docs/gates/checks-changelog.md) writes the pending release into `CHANGELOG.md` from the conventional commits since the last release.
201
- - [`checks-release-notes`](docs/gates/checks-release-notes.md) writes one `CHANGELOG.md` section to a file for a GitHub release.
202
- - [`checks-release-report`](docs/gates/checks-release-report.md) tells whether the history holds unreleased features or fixes since the last tag.
203
- - [`checks-release-pr`](docs/gates/checks-release-pr.md) opens or refreshes the pull request that releases the next version, and dispatches its checks.
204
- - [`checks-release-tag`](docs/gates/checks-release-tag.md) tags a landed release commit with its version and dispatches the release workflow on the tag.
205
- - [`checks-vendor`](docs/gates/checks-vendor.md) pins each library its `prepare` arguments name to a shared read-only clone and links it under `repos/`.
206
- - [`checks-browser`](docs/gates/checks-browser.md) opens a product's built pages in Chrome and fails on the layout, keyboard, motion, accessibility, nesting and asset checks its `browser-checks.json` declares.
207
- - [`checks-commit-title`](docs/gates/checks-commit-title.md) lints the pull request title in one step of the `ci` job.
208
- - [`checks-docs-only`](docs/gates/checks-docs-only.md) tells whether a change touches only top-level Markdown and Markdown under `docs/`, so a docs-only change skips the full run.
34
+ Each gate that fails names the file it needs, and [Set up a repository](docs/how-to/set-up-a-repository.md) writes every one.
35
+ A repository the kit holds ends with `checks-lint: <count> gate(s) pass`.
209
36
 
210
- `checks-lint` has [its own page](docs/gates/checks-lint.md), which says which range it resolves.
211
- oxlint runs through its own tool, as the pages under Related topics say.
37
+ ## Find the page you need
212
38
 
213
- ## Upgrade
214
-
215
- To move a repository to a newer release of the kit:
216
-
217
- 1. Run the install line again, which moves the kit to its newest release and the peers to the versions it pins.
218
- A repository that opted in to `checks-browser`, `checks-frontend-syntax` or `checks-copy` also reruns the `bun add` line on its page.
219
- 1. Run `bun run build`, whose `checks-effect-scope` rewrites the Effect override and the kit's severities in `tsconfig.json` when a release changes them.
220
- A severity key the release drops stays in `tsconfig.json` until the repository removes it.
221
- 1. Copy `node_modules/@avi2dg/checks/bunfig.toml` over `bunfig.toml` again, since `checks-test-layout` compares the copy with the installed preset.
222
- 1. Run `bun run lint`, `bun run typecheck` and `bun run test`.
223
-
224
- The repository's lockfile pins the kit, so a repository moves only when it runs these steps.
225
- [CHANGELOG.md](CHANGELOG.md), shipped in the package, lists what each release changed.
226
-
227
- ## Turn on the CSS families a repository needs
228
-
229
- A repository that declares `frontend-syntax.json` writes `stylelint.config.ts` with the families it needs:
230
-
231
- ```ts
232
- import { defineConfig } from "@avi2dg/checks/stylelint";
233
-
234
- export default defineConfig({
235
- baseline: "widely",
236
- tokens: ["src/styles/tokens.css"],
237
- bem: true,
238
- flatSelectors: true,
239
- noPageHas: true,
240
- });
241
- ```
242
-
243
- [checks-frontend-syntax](docs/gates/checks-frontend-syntax.md#what-it-reads) says what each key takes and which family it turns on.
244
- `noPageHas` sees a `:has` nested under a page selector only together with `flatSelectors`, which refuses the nesting.
245
-
246
- ## Where things are
247
-
248
- Every path is relative to the installed package, `node_modules/@avi2dg/checks/`.
249
-
250
- <!-- generated shipped: bun run build writes it from package.json and scripts/doc-blocks.ts -->
251
-
252
- | Path | What it holds |
39
+ | To | Read |
253
40
  | --- | --- |
254
- | `CHANGELOG.md` | every release, and what it changed |
255
- | `docs/` | a reference page per bin and per shared config, and why the kit is shaped this way |
256
- | `bunfig.toml` | the bunfig preset a repository copies |
257
- | `commitlint.config.ts` | the shared commitlint config |
258
- | `dependency-cruiser.config.js` | the kit's dependency-cruiser rules as a base a `.dependency-cruiser.cjs` extends by path, which the build writes |
259
- | `knip-base.json` | the Knip `include` setting, for a configuration that spreads it |
260
- | `src/` | every bin, which a package script calls by its `checks-` name, the modules the bins import, and the Effect language service severities under `src/quality/presets/` |
261
- | `dist/` | the compiled oxlint plugins, the config builders `@avi2dg/checks/oxlint`, `@avi2dg/checks/knip`, `@avi2dg/checks/dependency-cruiser` and `@avi2dg/checks/stylelint` resolve to, and the doc templates, one template per kind of doc file |
262
- | `oxlintrc.json` | the oxlint `base` as a config a `.oxlintrc.json` extends by path, which the build writes |
263
- | `stryker.preset.js` | the Stryker mutation-testing preset, which refuses a full run outside CI |
264
- | `tsconfig.effect.json` | the tsconfig fragment with the shared compiler options and the Effect language-service block |
265
- | `ts-reset.d.ts` | the two ts-reset rules `tsconfig.effect.json` lists in `files` |
266
-
267
- <!-- end generated shipped -->
41
+ | write every file the gates ask for | [Set up a repository](docs/how-to/set-up-a-repository.md) |
42
+ | move to a newer release | [Upgrade the kit](docs/how-to/upgrade-the-kit.md) |
43
+ | turn on the CSS checks | [Turn on the CSS families](docs/how-to/turn-on-the-css-families.md) |
44
+ | look up a gate or a bin | [The bins](docs/bins.md) |
45
+ | look up a shared config | [Native settings](docs/configs/native-settings.md) |
46
+ | find a file the package ships | [The shipped files](docs/shipped-files.md) |
47
+ | learn why the kit is shaped this way | [Why it is shaped this way](docs/design.md) |
268
48
 
269
49
  ## Related topics
270
50
 
271
- - [Native settings](docs/configs/native-settings.md)
272
- - [The Effect rules](docs/configs/effect-rules.md)
273
- - [The TypeScript rules](docs/configs/typescript-rules.md)
274
- - [The dependency rules](docs/configs/dependency-rules.md)
275
- - [The commit message lint](docs/configs/commit-messages.md)
276
- - [Why it is shaped this way](docs/design.md)
51
+ - [CHANGELOG.md](CHANGELOG.md)
@@ -2,7 +2,6 @@ import configConventional from "@commitlint/config-conventional";
2
2
 
3
3
  const houseTypes: ReadonlyArray<string> = [
4
4
  "theme",
5
- "herdr",
6
5
  "renamer",
7
6
  "shell",
8
7
  "pi",
@@ -150,7 +150,7 @@ var timedFiles = Effect2.fn("timedFiles")(function* (listed) {
150
150
  return fastestFirst(yield* fileSeconds(yield* fs.readFileString(outfile)));
151
151
  }, Effect2.scoped);
152
152
  var NodeServices = NodeChildProcessSpawner.layer.pipe(Layer.provideMerge(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer)));
153
- var runOrder = (listed) => Effect2.runPromise(timedFiles(listed).pipe(Effect2.map((timed) => inRunOrder(listed, timed)), Effect2.catch((failure) => Console.error(`checks: ${failure.message}, so each static mutant runs the unit tests in path order`).pipe(Effect2.as(listed))), Effect2.provide(NodeServices)));
153
+ var runOrder = (listed) => Effect2.runPromise(timedFiles(listed).pipe(Effect2.map((timed) => inRunOrder(listed, timed)), Effect2.catch((failure) => Console.error(`checks: ${failure.message}, so each static mutant runs the unit tests in Bun's default directory order`).pipe(Effect2.as(listed))), Effect2.provide(NodeServices)));
154
154
  export {
155
155
  fastestFirst,
156
156
  inRunOrder,
@@ -2,5 +2,5 @@ import type { KnipConfiguration } from "knip";
2
2
  export type ChecksKnipConfig = Omit<KnipConfiguration, "entry" | "include"> & {
3
3
  readonly entry: readonly string[];
4
4
  };
5
- export declare const DEFAULT_ENTRY: readonly ["tests/**/*.test.ts", "dependency-cruiser.config.ts"];
5
+ export declare const DEFAULT_ENTRY: readonly ["tests/**/*.test.ts", "dependency-cruiser.config.ts", "oxlint.config.ts"];
6
6
  export declare function defineConfig({ entry, ...rest }: ChecksKnipConfig): KnipConfiguration;
@@ -1,5 +1,5 @@
1
1
  // src/quality/presets/knip.ts
2
- var DEFAULT_ENTRY = ["tests/**/*.test.ts", "dependency-cruiser.config.ts"];
2
+ var DEFAULT_ENTRY = ["tests/**/*.test.ts", "dependency-cruiser.config.ts", "oxlint.config.ts"];
3
3
  var REFUSED_ENTRY = "@avi2dg/checks/knip: set entry to the files nothing imports, or [] when package.json scripts and tests name them all";
4
4
  function isGlobList(value) {
5
5
  return Array.isArray(value) && value.every((glob) => typeof glob === "string" && glob !== "");
@@ -6,7 +6,7 @@
6
6
 
7
7
  <Leave this section out when the task needs nothing set up first.>
8
8
 
9
- - <each prerequisite, with the version it is tested on>
9
+ - <each prerequisite, naming the file that pins its version rather than the version>
10
10
 
11
11
  ## <Part of the task, verb first>
12
12
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Before you begin
6
6
 
7
- - <each prerequisite, with the version it is tested on>
7
+ - <each prerequisite, naming the file that pins its version rather than the version>
8
8
 
9
9
  ## Install
10
10
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Before you begin
6
6
 
7
- - <each prerequisite, with the version it is tested on>
7
+ - <each prerequisite, naming the file that pins its version rather than the version>
8
8
 
9
9
  ## <Step, verb first>
10
10
 
package/docs/bins.md ADDED
@@ -0,0 +1,67 @@
1
+ ---
2
+ kind: reference
3
+ audience: consumers
4
+ ---
5
+ # The bins
6
+
7
+ The kit ships one bin per check, each named `checks-` and called from a package script.
8
+
9
+ ## What runs
10
+
11
+ `checks-lint` runs each of these gates that applies to the repository, and names every one that fails.
12
+ A gate reads either the working tree or the range `checks-lint` resolves.
13
+ The table groups the gates by vector, the part of a repository each one judges.
14
+
15
+ <!-- generated gates: bun run build writes it from KIT_GATES in src/core/gates.ts and scripts/doc-blocks.ts -->
16
+
17
+ | Vector | Gate | Reads | Runs in |
18
+ | --- | --- | --- | --- |
19
+ | complexity | [`checks-suppressions-ratchet`](gates/checks-suppressions-ratchet.md) | the range | every repository |
20
+ | complexity | [`checks-repetition`](gates/checks-repetition.md) | the range | a repository tracking `*.ts` or `*.tsx` |
21
+ | complexity | [`checks-unused`](gates/checks-unused.md) | the working tree | a repository tracking `*.ts` or `*.tsx` or `*.astro` |
22
+ | complexity | [`checks-exports`](gates/checks-exports.md) | the range | a repository tracking `*.ts` or `*.tsx` |
23
+ | quality | [`checks-lint-coverage`](gates/checks-lint-coverage.md) | the working tree | a repository tracking `*.ts` or `*.tsx` or `*.astro` |
24
+ | quality | [`checks-comment-gate`](gates/checks-comment-gate.md) | the range | every repository |
25
+ | quality | [`checks-effect-scope`](gates/checks-effect-scope.md) | the working tree | a repository tracking `oxlint.config.ts` |
26
+ | quality | [`checks-frontend-syntax`](gates/checks-frontend-syntax.md) | the working tree | a repository tracking `frontend-syntax.json` |
27
+ | quality | [`checks-css-size`](gates/checks-css-size.md) | the working tree | a repository tracking `*.css` |
28
+ | quality | [`checks-no-plain-js`](gates/checks-no-plain-js.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
29
+ | testing | [`checks-test-layout`](gates/checks-test-layout.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
30
+ | testing | [`checks-quarantine-clock`](gates/checks-quarantine-clock.md) | the range | every repository |
31
+ | docs | [`checks-docs`](gates/checks-docs.md) | the range, and every agent file at the head commit | every repository |
32
+ | docs | [`checks-copy`](gates/checks-copy.md) | the working tree | a repository tracking `copy.json` |
33
+ | delivery | [`checks-commit-identity`](gates/checks-commit-identity.md) | the range | every repository |
34
+ | delivery | [`checks-ci-wiring`](gates/checks-ci-wiring.md) | the working tree | every repository |
35
+ | delivery | [`checks-secrets`](gates/checks-secrets.md) | the range | every repository |
36
+ | dependencies | [`checks-imports`](gates/checks-imports.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
37
+ | dependencies | [`checks-advisories`](gates/checks-advisories.md) | the range | a repository tracking `bun.lock` |
38
+
39
+ <!-- end generated gates -->
40
+
41
+ These bins run on their own:
42
+
43
+ - [`checks-test`](gates/checks-test.md) runs the suite as `scripts.test` and refuses a skip without a reason at its test site.
44
+ - [`checks-flake`](gates/checks-flake.md) runs the suite on a schedule and records the seeds a flaky test fails with.
45
+ - [`checks-mutation`](gates/checks-mutation.md) runs Stryker for scoped checks and refuses a full run outside CI.
46
+ - [`checks-mutation-compare`](gates/checks-mutation-compare.md) compares the mutants of two reports and lists each one that regresses.
47
+ - [`checks-mutation-baseline`](gates/checks-mutation-baseline.md) restores the newest mutation baseline from `main`, saves it on a self-hosted runner's disk in place of an artifact, and deletes superseded baselines after a `main` run.
48
+ - [`checks-mutation-scope`](gates/checks-mutation-scope.md) turns a branch's diff into the files its mutation runs mutate.
49
+ - [`checks-subsumed-tests`](gates/checks-subsumed-tests.md) lists each test another test subsumes in a mutation run.
50
+ - [`checks-night-run`](gates/checks-night-run.md) opens or comments on one GitHub issue per finding of a night run on `main`, each file whose mutation score fell and each failing test.
51
+ - [`checks-changelog`](gates/checks-changelog.md) writes the pending release into `CHANGELOG.md` from the conventional commits since the last release.
52
+ - [`checks-release-notes`](gates/checks-release-notes.md) writes one `CHANGELOG.md` section to a file for a GitHub release.
53
+ - [`checks-release-report`](gates/checks-release-report.md) tells whether the history holds unreleased features or fixes since the last tag.
54
+ - [`checks-release-pr`](gates/checks-release-pr.md) opens or refreshes the pull request that releases the next version, and dispatches its checks.
55
+ - [`checks-release-tag`](gates/checks-release-tag.md) tags a landed release commit with its version and dispatches the release workflow on the tag.
56
+ - [`checks-vendor`](gates/checks-vendor.md) pins each library its `prepare` arguments name to a shared read-only clone and links it under `repos/`.
57
+ - [`checks-browser`](gates/checks-browser.md) opens a product's built pages in Chrome and fails on the layout, keyboard, motion, accessibility, nesting and asset checks its `browser-checks.json` declares.
58
+ - [`checks-commit-title`](gates/checks-commit-title.md) lints the pull request title in one step of the `ci` job.
59
+ - [`checks-docs-only`](gates/checks-docs-only.md) tells whether a change touches only top-level Markdown and Markdown under `docs/`, so a docs-only change skips the full run.
60
+
61
+ `checks-lint` has [its own page](gates/checks-lint.md), which says which range it resolves.
62
+ oxlint runs through its own tool, as [Native settings](configs/native-settings.md) says.
63
+
64
+ ## Related topics
65
+
66
+ - [Set up a repository](how-to/set-up-a-repository.md)
67
+ - [Native settings](configs/native-settings.md)
@@ -22,8 +22,8 @@ It reads `bun.lock` at the base and at the head of the range from git, not from
22
22
  It scans copies of both in a scratch directory with an empty config, so a repository's own `osv-scanner.toml` takes no part.
23
23
  It reads the advisories OSV.dev exports for npm, which hold GitHub's reviewed advisories and OpenSSF's reports of malicious packages.
24
24
 
25
- It runs OSV-Scanner 2.6.0, pinned by the SHA-256 of each platform's build.
26
- On first use it downloads the build from the scanner's GitHub release into `~/.cache/avi2dg-checks/osv-scanner/2.6.0/`.
25
+ It runs the OSV-Scanner release `src/dependencies/osv-scanner.ts` pins, by the SHA-256 of each platform's build.
26
+ On first use it downloads the build from the scanner's GitHub release into `~/.cache/avi2dg-checks/osv-scanner/<version>/`.
27
27
  It checks the SHA-256 again on every run and exits 2 on a copy that differs.
28
28
  Builds are pinned for macOS and Linux, each on x64 and arm64.
29
29
  On any other platform it exits 2, and no setting runs a scanner other than the pinned build.
@@ -156,10 +156,14 @@ So are a `motion` check with no state whose `reducedMotion` is `reduce`, a `keyb
156
156
  It drives the Chrome the machine has, which `CHROME_PATH` names, or Chrome's standard install when it is unset.
157
157
  The product installs the optional peers the runner loads, at the versions the kit pins:
158
158
 
159
+ <!-- generated install: bun run build writes it from package.json and scripts/doc-blocks.ts -->
160
+
159
161
  ```sh
160
- bun add -d playwright-core@1.63.0 @axe-core/playwright@4.13.0 html-validate@11.16.0
162
+ bun add -d @axe-core/playwright@4.13.0 html-validate@11.16.0 playwright-core@1.63.0
161
163
  ```
162
164
 
165
+ <!-- end generated install -->
166
+
163
167
  ## Arguments
164
168
 
165
169
  ```sh
@@ -47,10 +47,18 @@ The call counts as a command of its own or inside a command substitution, never
47
47
  A here-document that `sh`, `bash`, `dash`, `ksh` or `zsh` reads is a script, and its calls count.
48
48
  The text of any other here-document is data, so a call there counts only inside a command substitution when the delimiter is unquoted.
49
49
  A mutation job never names `CI_RUNS_ON` directly in `runs-on`, as `vars.CI_RUNS_ON` or `vars['CI_RUNS_ON']`, so an override for an outage cannot send its mutation runs to hosted runners.
50
- Any other job that names `CI_RUNS_ON` in `runs-on` carries exactly the hosted-default expression `${{ vars.CI_RUNS_ON || 'ubuntu-latest' }}`.
51
- In a private repository each mutation job carries exactly the labels `[self-hosted, Linux, X64, winbox]`.
52
- Every other job there carries exactly the hosted-default expression, or exactly the labels `[self-hosted, macOS, iphone]` of the Mac CI runner that holds the iPhone Simulator.
53
- A public repository may keep `runs-on: ubuntu-latest` on every job, because a pull request from a fork runs its own code on the runner.
50
+ In a private repository any other job that names `CI_RUNS_ON` in `runs-on` carries exactly the hosted-default expression `${{ vars.CI_RUNS_ON || 'ubuntu-latest' }}`.
51
+ A public repository carries no self-hosted runner on a job a fork can reach, because a pull request from a fork would run its own code on that runner.
52
+ A fork reaches a job through `pull_request`, `pull_request_target`, `pull_request_review`, `pull_request_review_comment` or `issue_comment`, directly, through a local reusable workflow a reached job calls, or through a `workflow_run` trigger that names a reached workflow.
53
+ Such a job refuses a literal `self-hosted` label, a label that interpolates an expression, a label in a set declared under `checks.mutationRunner` or `checks.selfHostedRunners`, a runner `group` and any other expression.
54
+ A `runs-on` that is exactly `${{ matrix.<key> }}` judges each matrix value as its own labels.
55
+ The values for the key are the combinations its axis values form, without combinations an `exclude` entry removes, plus its `include` rows, which merge into the original combinations they match and otherwise run as their own combinations.
56
+ It refuses a value that names `self-hosted` or falls inside a label set declared under `checks.mutationRunner` or `checks.selfHostedRunners`.
57
+ Any other expression refuses as unresolvable.
58
+ A job on `push` or another trigger no fork reaches may still name self-hosted labels.
59
+ In a private repository each mutation job carries exactly the labels the consumer declares in `package.json` under `checks.mutationRunner`.
60
+ Every other job there carries exactly the hosted-default expression, or exactly one of the label sets the consumer declares under `checks.selfHostedRunners`.
61
+ A repository without those declarations fails each job they would pin until it declares them.
54
62
  The check knows a repository is private only from GitHub's event, so a run outside CI judges only the rules that hold in either.
55
63
 
56
64
  ### Bun version
@@ -68,18 +76,19 @@ Else the `package.json` at the workspace root reads the same way.
68
76
  Else setup-bun installs latest.
69
77
  A blank version counts as none.
70
78
  A repository passes by writing the fleet version to `.bun-version` and naming that file in each step's `with.bun-version-file`.
79
+ The fleet version is the version the kit ships in its own `.bun-version`.
71
80
  The step fails the check when the version is missing or differs from the fleet bun version.
72
81
  A range fails because it differs from the fleet version.
73
82
  A version built from an expression fails because it cannot be shown equal before the run.
74
83
  This rule skips a repository with no setup-bun step.
75
- The fleet bun version equals the dotfiles mise pin.
76
- A bump moves both together, so a kit release that moves the fleet version turns each consumer red until its pin follows.
84
+ A kit release that moves the fleet version turns each consumer red until its pin follows.
77
85
  Each refusal names the workflow file and line, the version found and where it was read, and the fleet version.
78
86
 
79
87
  ## What it reads
80
88
 
81
- The bin reads `.github/workflows/*.yml`, `*.yaml`, the `scripts` in `package.json` and the shell scripts those steps and scripts run from the working tree.
89
+ The bin reads `.github/workflows/*.yml`, `*.yaml`, the `scripts` and `checks` runners in `package.json` and the shell scripts those steps and scripts run from the working tree.
82
90
  It reads each file a setup-bun step names for its version.
91
+ It reads the fleet pin from the kit's own `.bun-version`.
83
92
  It reads the target branch from `GITHUB_BASE_REF`, then from `refs/remotes/origin/HEAD` and then from the event file `GITHUB_EVENT_PATH` names.
84
93
  It reads whether the repository is private from `repository.private` in that event file.
85
94
  It parses the workflows with `Bun.YAML` without executing them.
@@ -94,7 +103,7 @@ It takes no arguments.
94
103
  | --- | --- |
95
104
  | 0 | Every required command has a reachable step. |
96
105
  | 1 | A required command is missing or blocked, a job runs on the wrong runner, a workflow names a missing workflow or job, or a setup-bun step drifts from the fleet bun version. |
97
- | 2 | A workflow or `package.json` cannot be decoded. |
106
+ | 2 | A workflow or `package.json` cannot be decoded, or the kit's own `.bun-version` is missing, unreadable or blank. |
98
107
 
99
108
  ## Sample output
100
109
 
@@ -110,7 +119,7 @@ A mutation job that names `CI_RUNS_ON` in `runs-on` produces a report like this:
110
119
 
111
120
  ```
112
121
  ci-wiring: 1 job(s) run on the wrong runner:
113
- .github/workflows/mutation-compare.yml job mutation-compare: a mutation job reads CI_RUNS_ON, so an override moves its mutation runs off winbox; set runs-on: [self-hosted, Linux, X64, winbox]
122
+ .github/workflows/mutation-compare.yml job mutation-compare: a mutation job reads CI_RUNS_ON, so an override moves its mutation runs off [self-hosted, gpu, x64]; set runs-on: [self-hosted, gpu, x64]
114
123
  ```
115
124
 
116
125
  A reference to a missing workflow produces a report like this:
@@ -11,6 +11,9 @@ audience: consumers
11
11
  The author and committer of each commit must be allowed.
12
12
  A commit whose trailer block carries a `Co-authored-by` trailer, as git parses it, is refused.
13
13
  `GitHub <noreply@github.com>` is allowed as committer only.
14
+ A commit that GitHub committed allows any author name with an allowed email.
15
+ GitHub authors a web merge under the account's display name.
16
+ The same author on a commit with any other committer must match the allowed name too.
14
17
  `github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>` is allowed as author only of a commit whose subject is `chore: release <version>`, with or without the pull request number a squash merge adds.
15
18
  GitHub attributes the release commit [checks-release-pr](checks-release-pr.md) makes to that bot, since it commits through the workflow token.
16
19
  Such a commit may carry a `Co-authored-by` trailer naming that bot, since GitHub adds one to some squash merges of a pull request the bot opened, and every other trailer is refused.
@@ -21,7 +24,7 @@ Such a commit may carry a `Co-authored-by` trailer naming that bot, since GitHub
21
24
  Each person can be any form npm allows, an object with `name` and optional `email` and `url`, or a string such as `Avi <avi@example.com> (https://example.com)`.
22
25
  A person with both a name and an email is an allowed author.
23
26
  A person without an email is ignored.
24
- When no person carries an email, the kit allows `avi2d <avi2dg@gmail.com>`.
27
+ When no person carries an email, no identity is allowed, so the check fails every commit until the repository declares its owners.
25
28
  The bin reads commits from git and parses their trailer blocks.
26
29
 
27
30
  ## Arguments
@@ -39,7 +42,7 @@ With one argument, it checks that commit alone.
39
42
  | Code | Result |
40
43
  | --- | --- |
41
44
  | 0 | Every commit carries an allowed identity. |
42
- | 1 | A commit carries a foreign identity. |
45
+ | 1 | A commit carries a foreign identity, or `package.json` declares no authors. |
43
46
  | 2 | A ref, argument or `package.json` cannot be decoded. |
44
47
 
45
48
  ## Sample output
@@ -48,7 +51,7 @@ With one argument, it checks that commit alone.
48
51
  commit-identity: 1 of 1 commit(s) in HEAD carry a foreign identity:
49
52
  79fa94f9f027 feat: foreign
50
53
  author someone <someone@example.com>
51
- allowed: avi2d <avi2dg@gmail.com>
54
+ allowed: Repo Owner <owner@example.com>
52
55
  ```
53
56
 
54
57
  ## When it runs
@@ -66,10 +66,14 @@ It reads the working tree, so an uncommitted file is judged like a committed one
66
66
 
67
67
  A repository that declares an HTML file installs the optional peer the gate loads for it, at the version the kit pins:
68
68
 
69
+ <!-- generated install: bun run build writes it from package.json and scripts/doc-blocks.ts -->
70
+
69
71
  ```sh
70
72
  bun add -d html-validate@11.16.0
71
73
  ```
72
74
 
75
+ <!-- end generated install -->
76
+
73
77
  ## Arguments
74
78
 
75
79
  ```sh