@avi2dg/checks 0.21.0 → 0.23.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 (57) hide show
  1. package/CHANGELOG.md +66 -40
  2. package/CONTRIBUTING.md +14 -10
  3. package/README.md +15 -24
  4. package/bunfig.toml +1 -1
  5. package/dist/effect-channel/index.js +122 -0
  6. package/dist/{index.js → readability/index.js} +8 -120
  7. package/docs/configs/commit-messages.md +5 -1
  8. package/docs/configs/dependency-rules.md +5 -2
  9. package/docs/configs/effect-rules.md +32 -33
  10. package/docs/configs/native-settings.md +74 -0
  11. package/docs/configs/typescript-rules.md +4 -0
  12. package/docs/design.md +26 -27
  13. package/docs/gates/checks-backtest.md +4 -0
  14. package/docs/gates/checks-ci-wiring.md +30 -93
  15. package/docs/gates/checks-comment-gate.md +4 -0
  16. package/docs/gates/checks-commit-identity.md +23 -27
  17. package/docs/gates/checks-docs.md +23 -21
  18. package/docs/gates/checks-flake.md +4 -10
  19. package/docs/gates/checks-lint-coverage.md +5 -1
  20. package/docs/gates/checks-lint.md +22 -104
  21. package/docs/gates/checks-mutation-compare.md +4 -0
  22. package/docs/gates/checks-quarantine-clock.md +4 -0
  23. package/docs/gates/checks-repetition.md +27 -41
  24. package/docs/gates/checks-subsumed-tests.md +4 -0
  25. package/docs/gates/checks-suppressions-ratchet.md +4 -0
  26. package/docs/gates/checks-test-layout.md +16 -8
  27. package/docs/gates/checks-test.md +68 -36
  28. package/docs/gates/checks-vendor.md +20 -13
  29. package/oxlintrc.json +1 -1
  30. package/package.json +10 -21
  31. package/scripts/ci-wiring.ts +28 -97
  32. package/scripts/commit-identity.ts +32 -4
  33. package/scripts/doc-rules.ts +26 -11
  34. package/scripts/doc-templates.ts +2 -1
  35. package/scripts/docs.ts +4 -7
  36. package/scripts/gates.ts +0 -29
  37. package/scripts/git.ts +24 -1
  38. package/scripts/lint.ts +15 -34
  39. package/scripts/range-gate.ts +1 -2
  40. package/scripts/repetition.ts +51 -40
  41. package/scripts/shell-command.ts +7 -1
  42. package/scripts/swc.ts +46 -0
  43. package/scripts/test-layout.ts +40 -56
  44. package/scripts/test-skips.ts +180 -0
  45. package/scripts/test.ts +33 -38
  46. package/scripts/vendor.ts +55 -11
  47. package/dist/feature-rules.js +0 -354
  48. package/docs/configs/quality-file.md +0 -103
  49. package/docs/gates/checks-feature-owners.md +0 -113
  50. package/docs/gates/checks-quality.md +0 -111
  51. package/docs/gates/checks-size-budget.md +0 -107
  52. package/quality.schema.json +0 -514
  53. package/scripts/feature-owners.ts +0 -139
  54. package/scripts/quality-file.ts +0 -353
  55. package/scripts/quality.ts +0 -363
  56. package/scripts/size-budget.ts +0 -285
  57. package/scripts/size-rules.ts +0 -126
@@ -1,103 +0,0 @@
1
- # The quality file
2
-
3
- `quality.json` at the repository root says what the repository has opted into, and a reader looks it up to learn what each key holds and which bin reads it.
4
-
5
- ## Keys
6
-
7
- The kit's bins find the file at the git root and read it there:
8
-
9
- ```json
10
- {
11
- "$schema": "./node_modules/@avi2dg/checks/quality.schema.json",
12
- "defaultBranch": "main",
13
- "gates": {
14
- "ci": ["bun run lint", "bun run typecheck", "bun run test"],
15
- "scheduled": ["bunx checks-flake --runs 10 --report flake-report.json"]
16
- },
17
- "runsOn": ["self-hosted", "Linux", "X64", "winbox"],
18
- "commitIdentity": { "authors": [{ "name": "avi2d", "email": "avi2dg@gmail.com" }] },
19
- "sources": {
20
- "production": ["src/**/*.ts"],
21
- "effect": { "paths": ["src/**/*.ts"], "exempt": ["src/host/*.ts"] }
22
- },
23
- "size": { "applies": "ratchet", "tests": { "fileLines": 800 } },
24
- "features": [
25
- {
26
- "name": "billing",
27
- "root": "src/billing",
28
- "entries": ["src/billing/index.ts"],
29
- "allowFrom": ["src/main.ts"],
30
- "proof": "tests/e2e/billing.test.ts"
31
- }
32
- ],
33
- "changeSignal": "advisory",
34
- "agentRules": { "on": [], "off": [] },
35
- "docs": { "pages": { "reference": ["docs/gates/*.md"], "explanation": ["docs/design.md"] } }
36
- }
37
- ```
38
-
39
- <!-- generated quality-keys: bun run build writes it from Quality in scripts/quality-file.ts and scripts/doc-blocks.ts -->
40
-
41
- | Key | Read by | Holds |
42
- | --- | --- | --- |
43
- | `defaultBranch` | `checks-lint`, `checks-ci-wiring`, `checks-quality` | the branch pull requests merge into, `main` when absent |
44
- | `gates.ci` | `checks-ci-wiring`, `checks-quality` | the commands CI runs on every pull request, as [checks-ci-wiring](../gates/checks-ci-wiring.md) says |
45
- | `gates.scheduled` | `checks-ci-wiring` | the commands a schedule runs |
46
- | `gates.lint` | `checks-lint`, `checks-ci-wiring` | the gates `checks-lint` runs when not all apply, as [Gate selection](../gates/checks-lint.md#gate-selection) says |
47
- | `runsOn` | `checks-quality` | the runner labels every job the ci and commitlint workflows run on, `ubuntu-latest` when absent |
48
- | `commitIdentity.authors` | `checks-commit-identity` | the identities allowed to author and commit, as [checks-commit-identity](../gates/checks-commit-identity.md) says |
49
- | `sources.production` | `checks-size-budget`, `checks-repetition`, `checks-quality` | the source the repository ships, as [checks-size-budget](../gates/checks-size-budget.md) and [checks-repetition](../gates/checks-repetition.md) say |
50
- | `sources.effect` | `checks-quality` | the paths held to the Effect rules, and the files under them that are not, as [The Effect rules](effect-rules.md) says |
51
- | `sources.libraries` | `checks-vendor`, `checks-test-layout` | the libraries pinned to a shared read-only clone, as [checks-vendor](../gates/checks-vendor.md) says |
52
- | `size` | `checks-size-budget` | the size budget of production and test files, and how a change is held to it, as [checks-size-budget](../gates/checks-size-budget.md) says |
53
- | `features` | `featureRules`, `checks-feature-owners` | each feature's root, entries, exempt importers and proof, as [checks-feature-owners](../gates/checks-feature-owners.md) says |
54
- | `changeSignal` | `checks-feature-owners` | `advisory` to list the feature owners a change touches |
55
- | `agentRules.on` | agent Rule selection, not the kit | catalogued Rules switched on for this repository |
56
- | `agentRules.off` | agent Rule selection, not the kit | catalogued Rules switched off for this repository |
57
- | `docs.pages` | `checks-docs` | the Diátaxis mode of each page, by glob, as [checks-docs](../gates/checks-docs.md) says |
58
- | `docs.forConsumers` | `checks-docs` | the living docs that speak to a repository installing this one, by glob, whose `bun run` commands name that repository's scripts |
59
-
60
- <!-- end generated quality-keys -->
61
-
62
- Every key is optional.
63
-
64
- ## Schema
65
-
66
- The bins decode the file with one Effect `Schema`, and the package ships `quality.schema.json` emitted from that schema.
67
- The `$schema` line therefore gives an editor the verdict the bins reach, save what no JSON Schema can express across two values, which the bins refuse:
68
-
69
- - a Rule switched both on and off
70
- - a feature entry outside its root
71
- - two features with one name or sharing a root
72
-
73
- A key the schema does not name is refused, not ignored, so a misspelt `sources` cannot switch the Effect rules off unnoticed.
74
-
75
- ## Globs
76
-
77
- A glob in `sources` starts at the repository root, names a directory first, uses `*` only within a segment and `**` only as a whole one, and ends in a file name with an extension.
78
- Those are the globs oxlint, the language service and git all read alike.
79
- oxlint matches `*.ts` at any depth where the other two match it at the root alone, so the schema refuses it, and `**/*.ts` means every depth to all three.
80
- The language service matches nothing for `src/**` and oxlint nothing for `src/lib`, so the schema refuses both, and `src/**/*.ts` and `src/lib/*.ts` say it to all three.
81
-
82
- ## Keys moved from package.json
83
-
84
- A repository with no `quality.json` still has `ciWiring` and `commitIdentity` read from `package.json`, with a notice on each read.
85
- One with both files exits 2 until `package.json` drops them.
86
- The keys map one for one:
87
-
88
- <!-- generated legacy-keys: bun run build writes it from LegacyManifest in scripts/quality-file.ts, QUALITY_FILE in scripts/gates.ts and scripts/doc-blocks.ts -->
89
-
90
- | `package.json` | `quality.json` |
91
- | --- | --- |
92
- | `ciWiring.gates` | `gates.ci` |
93
- | `ciWiring.scheduled` | `gates.scheduled` |
94
- | `ciWiring.lintGates` | `gates.lint` |
95
- | `ciWiring.defaultBranch` | `defaultBranch` |
96
- | `commitIdentity` | `commitIdentity` |
97
-
98
- <!-- end generated legacy-keys -->
99
-
100
- ## Related topics
101
-
102
- - [checks-quality](../gates/checks-quality.md)
103
- - [Why it is shaped this way](../design.md)
@@ -1,113 +0,0 @@
1
- # checks-feature-owners
2
-
3
- `checks-feature-owners` is the gate that holds each declared feature to a runnable proof and lists the feature owners a change touches, and a reader looks it up to declare a feature.
4
-
5
- ## What it checks
6
-
7
- A repository opts a feature in by declaring, in `quality.json`, the directory it owns, the files code outside it imports it through, the files that may reach past those, and the end-to-end test that proves it runs:
8
-
9
- ```json
10
- "features": [
11
- {
12
- "name": "billing",
13
- "root": "src/billing",
14
- "entries": ["src/billing/index.ts"],
15
- "allowFrom": ["src/main.ts", "src/cli/*.ts"],
16
- "proof": "tests/e2e/billing.test.ts"
17
- }
18
- ],
19
- "changeSignal": "advisory"
20
- ```
21
-
22
- `root` is a directory and `entries` are files under it, both without globs.
23
- `allowFrom` holds globs of the same shape as `sources`.
24
- `proof` is a `.test.ts` or `.test.tsx` file under `tests/e2e/`.
25
- Nothing moves, since a root is wherever the feature already lives.
26
- `quality.json` refuses an entry outside its root, a name used twice, and two features sharing a root or one root inside another, so a file has at most one owner.
27
-
28
- The gate fails when a feature's proof cannot prove it:
29
-
30
- - the proof or an entry is not in the head commit
31
- - the proof does not parse
32
- - the proof imports none of the feature's entries
33
-
34
- An import counts when it is a runtime `import`, `export ... from` or `export * from` of a relative path that names an entry.
35
- It names the entry by its own name, by the `.js`, `.jsx`, `.mjs` or `.cjs` spelling of it, or without an extension, the way a directory `index` is imported.
36
- `.js` names a `.tsx` entry as well as a `.ts` one.
37
- `import type` does not count, and neither does a path alias.
38
- The proof runs in `bun run test` like any end-to-end test, which is what shows it passes.
39
-
40
- With `changeSignal` set to `advisory` it also lists each owner the range touches, with the paths it touched under the owner's root or at its proof, and still passes.
41
- Whether a change that spans owners is one coherent slice is for a reviewer to judge.
42
- A rename counts at both of its paths.
43
-
44
- ## What it reads
45
-
46
- It reads `features` and `changeSignal` from `quality.json`, each proof and entry from the head commit, and the paths the range touches.
47
-
48
- ## Arguments
49
-
50
- ```sh
51
- checks-feature-owners <base-ref> <head-ref>
52
- checks-feature-owners <ref>
53
- ```
54
-
55
- With two arguments the range starts where the head branched from the base, at their merge-base.
56
- With one it is that commit against its parent, or against the empty tree for a repository's first commit.
57
-
58
- ## Exit codes
59
-
60
- | Code | When |
61
- | --- | --- |
62
- | 0 | every feature's proof imports one of its entries |
63
- | 1 | a feature's proof cannot prove it |
64
- | 2 | `quality.json` does not decode, which is where a proof outside `tests/e2e/` is refused, or a ref does not resolve |
65
-
66
- ## Sample output
67
-
68
- ```
69
- feature-owners: 1 problem(s) with the features' runnable proofs:
70
- billing: proof tests/e2e/billing.test.ts imports none of its entries, src/billing/index.ts
71
- ```
72
-
73
- With `changeSignal` set to `advisory`:
74
-
75
- ```
76
- feature-owners: advisory, the range touches 2 feature owner(s); a reviewer judges whether they make one slice:
77
- billing: src/billing/charge.ts, src/billing/tax.ts
78
- invoices: src/invoices/tax.ts, tests/e2e/invoices.test.ts
79
- ```
80
-
81
- ## Opting out
82
-
83
- A repository that declares no feature passes.
84
- `quality.json` refuses a `changeSignal` without features, which would map a change to no owner.
85
- A repository that tracks no `.ts` or `.tsx` file leaves it out of `gates.lint`, as [Gate selection](checks-lint.md#gate-selection) says.
86
-
87
- ## Import boundary
88
-
89
- `dist/feature-rules.js` compiles `features` into one dependency-cruiser rule per feature, which `.dependency-cruiser.cjs` spreads beside its own:
90
-
91
- ```js
92
- const { featureRules } = require("@avi2dg/checks/dist/feature-rules.js");
93
-
94
- module.exports = {
95
- extends: "./node_modules/@avi2dg/checks/dependency-cruiser.config.js",
96
- forbidden: [...featureRules(require("./quality.json"))],
97
- };
98
- ```
99
-
100
- A module outside a feature's root that imports a file inside it must import one of the feature's `entries`.
101
- Modules under `tests/` and the files `allowFrom` matches, such as a CLI or a harness, may import any file in it:
102
-
103
- ```
104
- error feature-billing-entries: src/report.ts → src/billing/charge.ts
105
- ```
106
-
107
- `featureRules` decodes its argument with the schema the bins use and throws the schema's refusal when it does not decode, which stops the cruise.
108
- It is an ES module, as `effect` is, so a `.cjs` config loads it through `require`, which needs node 20.19, 22.12 or later.
109
-
110
- ## Related topics
111
-
112
- - [The dependency rules](../configs/dependency-rules.md)
113
- - [The quality file](../configs/quality-file.md)
@@ -1,111 +0,0 @@
1
- # checks-quality
2
-
3
- `checks-quality` is the bin that writes what `quality.json` declares into generated fragments and workflows and checks them, and a reader looks it up when generated text is stale.
4
-
5
- ## What it checks
6
-
7
- oxlint and tsc read their own JSON and nothing else, so `checks-quality generate` writes what `sources.effect` declares into two fragments at the repository root, and the hand-written configs extend them.
8
- Both fragments are committed.
9
-
10
- `oxlintrc.quality.json` holds one override: the declared paths as `files`, the exempt ones as `excludeFiles`, and the kit's Effect rule block, `presets/effect.oxlint.json`.
11
- `tsconfig.quality.json` holds the language-service override: the same paths as `include`, the exempt ones as `exclude`, and `presets/effect.language-service.json`.
12
- A kit release that changes a preset reaches the repository through its next `generate`.
13
- A rule only this repository needs stays in its own `.oxlintrc.json`, whose overrides come after the fragment's and so win.
14
-
15
- `.oxlintrc.json` extends its fragment:
16
-
17
- ```json
18
- {
19
- "extends": ["./node_modules/@avi2dg/checks/oxlintrc.json", "./oxlintrc.quality.json"],
20
- "plugins": ["typescript", "oxc", "eslint", "import"]
21
- }
22
- ```
23
-
24
- `tsconfig.json` extends its fragment:
25
-
26
- ```json
27
- {
28
- "extends": ["@avi2dg/checks/tsconfig.effect.json", "./tsconfig.quality.json"]
29
- }
30
- ```
31
-
32
- GitHub Actions reads its own YAML and nothing else, so `checks-quality generate` also writes the kit recipe workflows whole.
33
- `.github/workflows/ci.yml` runs every `gates.ci` command but the title lint as its own step after a frozen install.
34
- `.github/workflows/commitlint.yml` lints the pull request title with the installed kit config.
35
- Both jobs run on the runner labels `quality.json` `runsOn` lists, or on `ubuntu-latest` when the key is absent.
36
- A self-hosted runner in a public repository runs the code of any pull request from a fork.
37
- A step one repository alone needs lives in another workflow file, never in the recipe.
38
- All generated workflows are committed.
39
-
40
- `checks-quality --check` fails when any of these holds:
41
-
42
- - A fragment is missing, or differs from what `generate` would write from `quality.json` and the installed kit's presets.
43
- - A fragment is left over once `quality.json` stops declaring `sources.effect`.
44
- - A generated workflow is missing, or differs from what `generate` would write from `quality.json` and the kit recipe.
45
- - `.oxlintrc.json` or `tsconfig.json` does not list its fragment in `extends`, so the tool never reads it.
46
- - `.oxlintrc.json` does not extend `./node_modules/@avi2dg/checks/oxlintrc.json`, so the kit's oxlint rules are not loaded.
47
- - `tsconfig.json` does not extend `@avi2dg/checks/tsconfig.effect.json`, the one accepted spelling of the kit's Effect config.
48
- - A `sources.effect.paths` or `sources.production` glob matches no tracked or untracked file, so it holds nothing.
49
-
50
- Two details of the fragments are easy to get wrong, so the kit's tests pin both:
51
-
52
- - A fragment sits at the repository root.
53
- oxlint resolves an override's `files`, and the language service an override's `include`, against the directory of the config holding it.
54
- From `.quality/` the language service reports no error at all on an `async function` planted under a declared path.
55
- - The oxlint fragment always sets `plugins`, to the kit's.
56
- A config in `extends` that sets none brings in oxlint's default plugins, whose category rules then fire across the whole tree.
57
- The override names the kit's plugins beside the preset's `node`, `promise` and `unicorn`, because one that leaves any of the kit's out turns on the category rules of the plugins it adds under every declared path.
58
-
59
- ## What it reads
60
-
61
- It reads the working tree: `quality.json`, the presets of the installed kit, `.oxlintrc.json`, `tsconfig.json`, the two fragments and the generated workflows.
62
- It reads the root `package.json` name, since only the kit's own tree lints titles with its root `commitlint.config.js`.
63
- The name also decides which kit configs `extends` must list, since the kit's own tree extends its root `oxlintrc.json` and `tsconfig.effect.json`.
64
- It looks for `.bun-version` and `.node-version`, and the suite pins its bun and its node to whichever of the two files exists.
65
- It lists the tracked and untracked files to see what each declared glob matches.
66
-
67
- ## Arguments
68
-
69
- ```sh
70
- checks-quality generate
71
- checks-quality --check
72
- ```
73
-
74
- `generate` writes the fragments and the workflows, removes a left-over one, then runs the same check as `--check`.
75
- `--check` writes nothing.
76
-
77
- ## Exit codes
78
-
79
- | Code | When |
80
- | --- | --- |
81
- | 0 | the generated files hold what `quality.json` declares |
82
- | 1 | a generated file is stale, missing or left over, a fragment is not extended, the kit's config is not extended, or a declared glob matches no file |
83
- | 2 | `quality.json` does not decode, or the arguments are neither `generate` nor `--check` |
84
-
85
- ## Sample output
86
-
87
- ```
88
- checks-quality: 2 problem(s) with what quality.json declares:
89
- oxlintrc.quality.json is stale against quality.json and the kit's presets; run checks-quality generate
90
- tsconfig.json does not extend ./tsconfig.quality.json, so the language service never reads it
91
- ```
92
-
93
- A passing run says what the generated files hold:
94
-
95
- ```
96
- checks-quality: oxlintrc.quality.json and tsconfig.quality.json and .github/workflows/ci.yml and .github/workflows/commitlint.yml hold what quality.json declares
97
- ```
98
-
99
- A stale workflow is reported the same way as a stale fragment.
100
-
101
- ## Opting out
102
-
103
- It runs only in a repository that tracks `quality.json`, and a selection in `quality.json` always keeps it, since the file it sits in is what makes it apply.
104
- A repository that declares no `sources.effect` gets no fragment, and the check then refuses a left-over one.
105
- Every repository gets the title lint workflow, and one with `gates.ci` gets the suite with it.
106
-
107
- ## Related topics
108
-
109
- - [The quality file](../configs/quality-file.md)
110
- - [The Effect rules](../configs/effect-rules.md)
111
- - [checks-lint](checks-lint.md)
@@ -1,107 +0,0 @@
1
- # checks-size-budget
2
-
3
- `checks-size-budget` is the gate that holds production and test files to the size budget `quality.json` declares, and a reader looks it up when a file or a function runs over it.
4
-
5
- ## What it checks
6
-
7
- It holds production and test files to the size budget, and lists every other file over it without failing:
8
-
9
- ```json
10
- "sources": { "production": ["src/**/*.ts"] },
11
- "size": { "applies": "ratchet" }
12
- ```
13
-
14
- A production file is one under `sources.production`, and a test file is a tracked `.ts` or `.tsx` file under `tests/`.
15
- A test file keeps to the tests budget, and every other file keeps to the production budget.
16
- It runs oxlint with a configuration of five rules, one for each limit, and the kit's own plugin bundle, which holds the complexity rule.
17
- The kit sets each limit:
18
-
19
- <!-- generated size-limits: bun run build writes it from SIZE_RULES and SIZE_DEFAULTS in scripts/size-rules.ts and scripts/doc-blocks.ts -->
20
-
21
- | Key | Limits | oxlint rule | Production | Tests |
22
- | --- | --- | --- | --- | --- |
23
- | `fileLines` | The most lines a file may hold, blank and comment lines counted | `max-lines` | 400 | 600 |
24
- | `functionLines` | The most lines a function may span, blank and comment lines counted | `max-lines-per-function` | 100 | none |
25
- | `statements` | The most statements a function may hold | `max-statements` | 30 | 50 |
26
- | `complexity` | The highest cognitive complexity a function may reach, a switch counted once | `effect-channel/cognitive-complexity` | 15 | 15 |
27
- | `depth` | The deepest a block may nest inside a function | `max-depth` | 4 | 4 |
28
-
29
- <!-- end generated size-limits -->
30
-
31
- `size.production` and `size.tests` state only a limit that differs from the kit's:
32
-
33
- ```json
34
- "size": {
35
- "applies": "ratchet",
36
- "production": { "complexity": 12 },
37
- "tests": { "fileLines": 800 }
38
- }
39
- ```
40
-
41
- `applies` decides which files the gate holds and what fails them:
42
-
43
- - `ratchet` holds each production and test file the range adds or changes, a rename that edits the file included.
44
- For each file and each rule, it sums how far every site runs over its limit, and fails when that sum is higher at the head than at the base of the range.
45
- A file the range adds starts from zero, so it has to keep within the budget.
46
- A file already over the budget passes while its overrun does not grow, and an edit that shrinks the overrun passes.
47
- An edited rename is compared with the file it was renamed from.
48
- Nothing is committed as a baseline, because the base of the range holds it.
49
- - `all` holds every production and test file, and fails on any overrun in them.
50
-
51
- `applies` is `ratchet` when `size` leaves it out.
52
- A file the range deletes or only renames is not held.
53
- Every other tracked `.ts` or `.tsx` file over the budget, tooling and unchanged files alike, is listed as advisory and never fails the gate.
54
- Under `ratchet` the advisory list also names each site in a held file whose overrun did not grow.
55
- `.d.ts` files are not measured.
56
-
57
- `quality.json` refuses `applies: "changed"`, which `ratchet` replaces.
58
- It refuses a limit set directly under `size`, since each limit goes in `size.production` or `size.tests`.
59
-
60
- ## What it reads
61
-
62
- It reads each file from the head commit rather than the working tree, so an uncommitted edit neither fails nor passes a range, and a pull request's merge checkout measures what the pull request holds.
63
- Under `ratchet` it also reads each held file from the base of the range, under the path the file has at the head, so a file keeps the same budget at both ends.
64
- It reads `sources.production` and `size` from `quality.json`.
65
- oxlint must be on `PATH`, as it is under a package script.
66
-
67
- ## Arguments
68
-
69
- ```sh
70
- checks-size-budget <base-ref> <head-ref>
71
- checks-size-budget <ref>
72
- ```
73
-
74
- With two arguments the range starts where the head branched from the base, at their merge-base.
75
- With one it is that commit against its parent, or against the empty tree for a repository's first commit.
76
-
77
- ## Exit codes
78
-
79
- | Code | When |
80
- | --- | --- |
81
- | 0 | every file it holds keeps within the budget, or under `ratchet` no file's overrun grows |
82
- | 1 | a file it holds runs over the budget, or under `ratchet` a file's overrun grows |
83
- | 2 | `quality.json` does not decode, a ref does not resolve, or oxlint cannot run |
84
-
85
- ## Sample output
86
-
87
- ```
88
- size-budget: 2 overrun(s) grew past the base in the production and test files the range adds or changes:
89
- src/billing/invoice.ts: max-lines over by 31 in total, up from 19
90
- src/billing/invoice.ts: File has too many lines (431). Maximum allowed is 400.
91
- src/billing/ledger.ts: cognitive-complexity over by 3 in total, up from 0
92
- src/billing/ledger.ts:12: function `settle` has a cognitive complexity of 18. Maximum allowed is 15.
93
- size-budget: advisory, 1 overrun(s) where the budget does not hold yet:
94
- tests/e2e/billing.test.ts: File has too many lines (612). Maximum allowed is 600.
95
- ```
96
-
97
- ## Opting out
98
-
99
- A repository that declares no `size` passes.
100
- `quality.json` refuses a `size` without `sources.production`, and `checks-quality` refuses a `sources.production` glob that matches no file.
101
- A repository that tracks no `.ts` or `.tsx` file leaves it out of `gates.lint`, as [Gate selection](checks-lint.md#gate-selection) says.
102
- Moving `applies` from `ratchet` to `all` tightens the budget to every production and test file, once the advisory list names none.
103
-
104
- ## Related topics
105
-
106
- - [The quality file](../configs/quality-file.md)
107
- - [checks-lint](checks-lint.md)