fallow 3.33.1 → 3.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/schema.json CHANGED
@@ -20,15 +20,22 @@
20
20
  ]
21
21
  },
22
22
  "extends": {
23
- "description": "An ordered array of parent config sources to inherit before this file's own keys apply; each entry is a file-relative path, an `npm:<package>` specifier, or an `https://` URL (`http://` is rejected), deep-merged in order so objects merge field-by-field while arrays and scalars in this file replace the parent's, with cycle and depth guards. Set it to share a base config across a monorepo or team; it is consumed at load and stripped before serialization (serde skip_serializing).",
24
- "type": "array",
25
- "items": {
26
- "type": "string"
27
- },
23
+ "description": "A single parent config source, or an ordered array of them, to inherit before this file's own keys apply; each source is a file-relative path, an `npm:<package>` specifier, or an `https://` URL (`http://` is rejected), deep-merged in order so objects merge field-by-field while arrays and scalars in this file replace the parent's, with cycle and depth guards. Set it to share a base config across a monorepo or team; it is consumed at load and stripped before serialization (serde skip_serializing).",
24
+ "anyOf": [
25
+ {
26
+ "type": "string"
27
+ },
28
+ {
29
+ "type": "array",
30
+ "items": {
31
+ "type": "string"
32
+ }
33
+ }
34
+ ],
28
35
  "writeOnly": true
29
36
  },
30
37
  "entry": {
31
- "description": "An array of project-root-relative glob patterns whose matching files are seeded as manual entry points, on top of the framework and package.json entries fallow discovers automatically, so their transitive imports are not reported as unused. Set it (e.g. `[\"src/main.ts\"]`) when a file is a real runtime root that no plugin or manifest declares; patterns are validated at load and matched against discovered files.",
38
+ "description": "An array of project-root-relative glob patterns whose matching files are seeded as manual entry points, on top of the framework and package.json entries fallow discovers automatically, so their transitive imports are not reported as unused. Set it (e.g. `[\"src/main.ts\"]`) when a file is a real runtime root that no plugin or manifest declares; patterns are validated at load and matched against discovered files. A single `*` stays within one path segment; use `**` to match across directories.",
32
39
  "type": "array",
33
40
  "items": {
34
41
  "type": "string"
@@ -36,7 +43,7 @@
36
43
  "default": []
37
44
  },
38
45
  "ignorePatterns": {
39
- "description": "An array of project-root-relative glob patterns for files to exclude from analysis entirely; entries are unioned with fallow's built-in defaults (**/node_modules/**, **/dist/**, **/build/**, **/.git/**, **/coverage/**, **/*.min.js, **/*.min.mjs, **/*.min.cjs, **/*.bundle.js), so custom globs add to rather than replace them. Set it (e.g. `[\"generated/**\"]`) to drop generated or vendored trees from every detector; patterns are validated at load. A `!`-prefixed entry is an exception that applies after the defaults and the positive patterns: `\"!src/policy/coverage/**\"` brings back hand-written source under a built-in default such as `**/coverage/**`, and `\"!.config/**\"` adds a hidden directory to discovery. Paths under `node_modules` or `.git` can not be lifted, and a `!` entry that names one of these segments is a config error.",
46
+ "description": "An array of project-root-relative glob patterns for files to exclude from analysis entirely; entries are unioned with fallow's built-in defaults (**/node_modules/**, **/dist/**, **/build/**, **/.git/**, **/coverage/**, **/*.min.js, **/*.min.mjs, **/*.min.cjs, **/*.bundle.js), so custom globs add to rather than replace them. Set it (e.g. `[\"generated/**\"]`) to drop generated or vendored trees from every detector; patterns are validated at load. A `!`-prefixed entry is an exception that applies after the defaults and the positive patterns: `\"!src/policy/coverage/**\"` brings back hand-written source under a built-in default such as `**/coverage/**`, and `\"!.config/**\"` adds a hidden directory to discovery. Paths under `node_modules` or `.git` can not be lifted, and a `!` entry that names one of these segments is a config error. A single `*` stays within one path segment; use `**` to match across directories.",
40
47
  "type": "array",
41
48
  "items": {
42
49
  "type": "string"
@@ -44,7 +51,7 @@
44
51
  "default": []
45
52
  },
46
53
  "ignoreFindings": {
47
- "description": "An array of project-root-relative glob patterns whose source-owned dead-code findings are hidden after analysis without excluding matching files from discovery, parsing, resolution, or the module graph. Use `/` as the path separator on every platform. Positive patterns select paths to hide; `!`-prefixed patterns keep matching paths reportable, and a negated-only array reports only those exception paths. A finding with multiple source owners is hidden only when every owner matches, so a cycle, duplicate-export group, or unlisted dependency with any reportable location remains visible. Architecture, policy, suppression-hygiene, and framework-correctness findings remain visible even when a referenced path matches, as do manifest-owned findings that no source file owns: unused dependencies, unused dev and optional dependencies, catalog entries, and dependency overrides. Use `ignorePatterns` instead when a generated or vendored file must not be analyzed at all.",
54
+ "description": "An array of project-root-relative glob patterns whose source-owned dead-code findings are hidden after analysis without excluding matching files from discovery, parsing, resolution, or the module graph. Use `/` as the path separator on every platform. Positive patterns select paths to hide; `!`-prefixed patterns keep matching paths reportable, and a negated-only array reports only those exception paths. A finding with multiple source owners is hidden only when every owner matches, so a cycle, duplicate-export group, or unlisted dependency with any reportable location remains visible. Architecture, policy, suppression-hygiene, and framework-correctness findings remain visible even when a referenced path matches, as do manifest-owned findings that no source file owns: unused dependencies, unused dev and optional dependencies, catalog entries, and dependency overrides. Use `ignorePatterns` instead when a generated or vendored file must not be analyzed at all. A single `*` stays within one path segment; use `**` to match across directories.",
48
55
  "type": "array",
49
56
  "items": {
50
57
  "type": "string"
@@ -94,7 +101,7 @@
94
101
  "default": []
95
102
  },
96
103
  "ignoreExports": {
97
- "description": "A list of per-file rules that exempt named exports from `unused-export` and from duplicate-exports grouping for files matching a glob. Each entry is `{ file: <glob>, exports: [<name>, ...] }` where `exports: [\"*\"]` exempts every export in the file and a name list exempts only those names; built for component-library barrels (shadcn/Radix/bits-ui `index.ts`) that intentionally re-export the same short names across many files.",
104
+ "description": "A list of per-file rules that exempt named exports from `unused-export` and from duplicate-exports grouping for files matching a glob. Each entry is `{ file: <glob>, exports: [<name>, ...] }` where `exports: [\"*\"]` exempts every export in the file and a name list exempts only those names; built for component-library barrels (shadcn/Radix/bits-ui `index.ts`) that intentionally re-export the same short names across many files. A single `*` stays within one path segment; use `**` to match across directories.",
98
105
  "type": "array",
99
106
  "items": {
100
107
  "$ref": "#/$defs/IgnoreExportRule"
@@ -167,6 +174,10 @@
167
174
  "ignore": []
168
175
  }
169
176
  },
177
+ "mutation": {
178
+ "description": "Configures the explicit `fallow mutation` workflow: `runner` (`auto`\nor `vitest`), `operators` (kebab-case names, default each operator),\n`minScore` (0 to 100; a lower score exits with code 1), and\n`concurrency` (half the logical cores). No key starts a run, and the\nside-effect override is a CLI flag only.",
179
+ "$ref": "#/$defs/MutationConfig"
180
+ },
170
181
  "health": {
171
182
  "description": "Sets complexity and health thresholds for `fallow health` (also applied in combined `fallow` and `fallow audit`): `maxCyclomatic` (20), `maxCognitive` (15), `maxCrap` (30.0, findings at or above this are reported), `crapRefactorBand` (5, cyclomatic band below `maxCyclomatic` where a secondary refactor action is added), `maxUnitSize` (max function lines before a large-function finding, 60), `coverage`/`coverageRoot` (Istanbul coverage path and path-prefix strip for accurate CRAP), `ignore` globs (remove files from findings AND the health score), `thresholdOverrides` (per-file/per-function ceilings via `files`/`functions`/`maxCyclomatic`/`maxCognitive`/`maxCrap`/`maxUnitSize`/`reason`), `ownership` (`botPatterns` and `emailMode` for `--ownership`), and `suggestInlineSuppression` (true, emit `suppress-line` action hints in JSON). Raise thresholds to relax which functions are flagged, wire `coverage` for real CRAP scores, or exempt generated/test files via `ignore` (drops them from the score too) or `thresholdOverrides` (keeps them visible under a higher ceiling). The four `max*` thresholds govern findings only and never move `health_score`: its penalties use fixed calibration so grades stay comparable across projects, and `ignore` is the lever that removes files from the score.",
172
183
  "$ref": "#/$defs/HealthConfig",
@@ -190,6 +201,12 @@
190
201
  ],
191
202
  "emailMode": "handle"
192
203
  },
204
+ "changeCoupling": {
205
+ "maxFilesPerCommit": 30,
206
+ "minRevisions": 5,
207
+ "minSharedRevisions": 5,
208
+ "minDegree": 0.3
209
+ },
193
210
  "suggestInlineSuppression": true
194
211
  }
195
212
  },
@@ -220,6 +237,9 @@
220
237
  "unused-component-inputs": "warn",
221
238
  "unused-component-outputs": "warn",
222
239
  "unused-svelte-events": "warn",
240
+ "unused-effect-layers": "warn",
241
+ "unused-tagged-errors": "warn",
242
+ "unproduced-catch-tags": "warn",
223
243
  "unused-server-actions": "warn",
224
244
  "unused-load-data-keys": "warn",
225
245
  "prop-drilling": "off",
@@ -259,7 +279,12 @@
259
279
  "mixed-client-server-barrel": "warn",
260
280
  "misplaced-directive": "warn",
261
281
  "route-collision": "error",
262
- "dynamic-segment-name-conflict": "error"
282
+ "dynamic-segment-name-conflict": "error",
283
+ "weakened-tests": "warn",
284
+ "added-suppression": "warn",
285
+ "test-only-branch": "warn",
286
+ "diverged-clone-sibling": "off",
287
+ "added-dependency": "off"
263
288
  }
264
289
  },
265
290
  "unusedComponentProps": {
@@ -325,7 +350,7 @@
325
350
  }
326
351
  },
327
352
  "dynamicallyLoaded": {
328
- "description": "An array of project-root-relative glob patterns for files loaded at runtime by a mechanism the static graph cannot see (dynamic path resolution, config-driven loading); matching files are seeded as entry points so they and their imports stay reachable. Empty by default; set it (e.g. `[\"plugins/**/*.ts\", \"locales/**/*.json\"]`) for plugin or locale trees pulled in dynamically.",
353
+ "description": "An array of project-root-relative glob patterns for files loaded at runtime by a mechanism the static graph cannot see (dynamic path resolution, config-driven loading); matching files are seeded as entry points so they and their imports stay reachable. Empty by default; set it (e.g. `[\"plugins/**/*.ts\", \"locales/**/*.json\"]`) for plugin or locale trees pulled in dynamically. A single `*` stays within one path segment; use `**` to match across directories.",
329
354
  "type": "array",
330
355
  "items": {
331
356
  "type": "string"
@@ -333,7 +358,7 @@
333
358
  "default": []
334
359
  },
335
360
  "overrides": {
336
- "description": "An ordered list of per-file rule-severity overrides: each entry re-severities specific analysis rules for files its globs match, layered on top of the top-level `rules` defaults. Set to relax or tighten rules for a subset of paths (e.g. downgrade unused-exports to warn under a generated directory); each entry has `files` (glob-pattern array) and `rules` (a partial per-rule severity map of error/warn/off). Entries apply in list order and a file matched by several entries takes every matching entry's overrides (later entries win on conflict); inter-file rules (duplicate-exports, circular-dependencies, re-export-cycle) have no effect in an override (fallow warns during analysis and points to the right mechanism: top-level `ignoreExports` for duplicate-exports, a file-level `// fallow-ignore-file` comment for the others).",
361
+ "description": "An ordered list of per-file rule-severity overrides: each entry re-severities specific analysis rules for files its globs match, layered on top of the top-level `rules` defaults. Set to relax or tighten rules for a subset of paths (e.g. downgrade unused-exports to warn under a generated directory); each entry has `files` (glob-pattern array) and `rules` (a partial per-rule severity map of error/warn/off). Entries apply in list order and a file matched by several entries takes every matching entry's overrides (later entries win on conflict); inter-file rules (duplicate-exports, circular-dependencies, re-export-cycle) have no effect in an override (fallow warns during analysis and points to the right mechanism: top-level `ignoreExports` for duplicate-exports, a file-level `// fallow-ignore-file` comment for the others). A single `*` stays within one path segment; use `**` to match across directories.",
337
362
  "type": "array",
338
363
  "items": {
339
364
  "$ref": "#/$defs/ConfigOverride"
@@ -524,7 +549,7 @@
524
549
  "type": "object",
525
550
  "properties": {
526
551
  "pattern": {
527
- "description": "Project-root-relative glob; the plugin activates when any\ndiscovered file matches it. Validated at load like other user\nglobs (no absolute paths or `..` segments).",
552
+ "description": "Project-root-relative glob; the plugin activates when any\ndiscovered file matches it. Validated at load like other user\nglobs (no absolute paths or `..` segments).\nA single `*` stays within one path segment; use `**` to match across directories.",
528
553
  "type": "string"
529
554
  },
530
555
  "type": {
@@ -606,7 +631,7 @@
606
631
  "type": "object",
607
632
  "properties": {
608
633
  "manifests": {
609
- "description": "Recursive glob selecting the manifest files to read (e.g. `**/kibana.jsonc`).",
634
+ "description": "Recursive glob selecting the manifest files to read (e.g. `**/kibana.jsonc`).\nA single `*` stays within one path segment; use `**` to match across directories.",
610
635
  "type": "string"
611
636
  },
612
637
  "format": {
@@ -702,7 +727,7 @@
702
727
  "type": "object",
703
728
  "properties": {
704
729
  "pattern": {
705
- "description": "Glob pattern for files.",
730
+ "description": "Glob pattern for files.\nA single `*` stays within one path segment; use `**` to match across directories.",
706
731
  "type": "string"
707
732
  },
708
733
  "exports": {
@@ -788,7 +813,7 @@
788
813
  "type": "object",
789
814
  "properties": {
790
815
  "file": {
791
- "description": "Glob pattern for files.",
816
+ "description": "Glob pattern for files.\nA single `*` stays within one path segment; use `**` to match across directories.",
792
817
  "type": "string"
793
818
  },
794
819
  "exports": {
@@ -821,7 +846,7 @@
821
846
  ]
822
847
  },
823
848
  "consumer": {
824
- "description": "Optional glob matched against the consuming workspace `package.json` path (compiled into a glob matcher at config load): when set, the rule suppresses the finding only for consumers whose path matches, and when omitted it applies to every consumer. Use it to suppress a catalog reference in one specific workspace during a staged migration.",
849
+ "description": "Optional glob matched against the consuming workspace `package.json` path (compiled into a glob matcher at config load): when set, the rule suppresses the finding only for consumers whose path matches, and when omitted it applies to every consumer. Use it to suppress a catalog reference in one specific workspace during a staged migration. A single `*` stays within one path segment; use `**` to match across directories.",
825
850
  "type": [
826
851
  "string",
827
852
  "null"
@@ -930,7 +955,7 @@
930
955
  "default": 0.0
931
956
  },
932
957
  "ignore": {
933
- "description": "Additional ignore patterns for duplication analysis.",
958
+ "description": "Additional ignore patterns for duplication analysis.\nA single `*` stays within one path segment; use `**` to match across directories.",
934
959
  "type": "array",
935
960
  "items": {
936
961
  "type": "string"
@@ -1064,7 +1089,7 @@
1064
1089
  "default": 3
1065
1090
  },
1066
1091
  "ignore": {
1067
- "description": "Additional project-root-relative globs excluded only from similar-code\nextraction. Global `ignorePatterns` remain authoritative first.",
1092
+ "description": "Additional project-root-relative globs excluded only from similar-code\nextraction. Global `ignorePatterns` remain authoritative first.\nA single `*` stays within one path segment; use `**` to match across directories.",
1068
1093
  "type": "array",
1069
1094
  "items": {
1070
1095
  "type": "string"
@@ -1074,6 +1099,144 @@
1074
1099
  },
1075
1100
  "additionalProperties": false
1076
1101
  },
1102
+ "MutationConfig": {
1103
+ "description": "Project settings for `fallow mutation`.\n\nProject config cannot widen what a run executes: the override that keeps\nmutants near file system, process, network or database sinks is a CLI\nflag only (`--allow-side-effects`), and no key starts a run.",
1104
+ "type": "object",
1105
+ "properties": {
1106
+ "runner": {
1107
+ "description": "The test runner: `auto`, `vitest`, `node-test` or `bun-test`. `auto`\ndetects it from the project.",
1108
+ "$ref": "#/$defs/MutationRunner",
1109
+ "default": "auto"
1110
+ },
1111
+ "operators": {
1112
+ "description": "The operators to use. Unset uses each operator. `--operators` wins.",
1113
+ "type": [
1114
+ "array",
1115
+ "null"
1116
+ ],
1117
+ "items": {
1118
+ "$ref": "#/$defs/MutationOperatorName"
1119
+ }
1120
+ },
1121
+ "minScore": {
1122
+ "description": "The minimum mutation score, from 0 to 100. When the score of a run is\nlower, `fallow mutation` exits with code 1. Unset never fails a run.\n`--min-score` wins.",
1123
+ "type": [
1124
+ "number",
1125
+ "null"
1126
+ ],
1127
+ "format": "double",
1128
+ "minimum": 0.0,
1129
+ "maximum": 100.0
1130
+ },
1131
+ "concurrency": {
1132
+ "description": "The number of companion processes. Unset uses half the logical cores.\n`--concurrency` wins.",
1133
+ "type": [
1134
+ "integer",
1135
+ "null"
1136
+ ],
1137
+ "format": "uint",
1138
+ "minimum": 1
1139
+ },
1140
+ "typecheck": {
1141
+ "description": "Type-check each survived mutant through the TypeScript-Go companion\nof `--type-aware`. A survivor that does not type-check becomes\n`compile_error` and does not count in the score. Unset or `false`\nchecks no survivor. `--typecheck` turns the check on.",
1142
+ "type": [
1143
+ "boolean",
1144
+ "null"
1145
+ ]
1146
+ }
1147
+ },
1148
+ "additionalProperties": false
1149
+ },
1150
+ "MutationRunner": {
1151
+ "description": "The test runner of `fallow mutation`.",
1152
+ "oneOf": [
1153
+ {
1154
+ "description": "Detect the runner from the project: the `vitest` dependency, the\ntest module that the test files import, a Bun file at the root, or a\n`node --test` script.",
1155
+ "type": "string",
1156
+ "const": "auto"
1157
+ },
1158
+ {
1159
+ "description": "Vitest 4.1 to 5 from the project `node_modules`.",
1160
+ "type": "string",
1161
+ "const": "vitest"
1162
+ },
1163
+ {
1164
+ "description": "`node:test` of Node.js 22.18 or later. Each test file runs in its own\nNode process.",
1165
+ "type": "string",
1166
+ "const": "node-test"
1167
+ },
1168
+ {
1169
+ "description": "`bun test` of Bun 1.4 or later. Each test file runs in its own Bun\nprocess.",
1170
+ "type": "string",
1171
+ "const": "bun-test"
1172
+ }
1173
+ ]
1174
+ },
1175
+ "MutationOperatorName": {
1176
+ "description": "A mutation operator name, kebab-case.",
1177
+ "oneOf": [
1178
+ {
1179
+ "description": "`a + b` to `a - b`, and the other arithmetic pairs.",
1180
+ "type": "string",
1181
+ "const": "arithmetic-operator"
1182
+ },
1183
+ {
1184
+ "description": "`a < b` to `a <= b`, and the other relational pairs.",
1185
+ "type": "string",
1186
+ "const": "relational-operator"
1187
+ },
1188
+ {
1189
+ "description": "`a && b` to `a || b`, and the reverse.",
1190
+ "type": "string",
1191
+ "const": "logical-operator"
1192
+ },
1193
+ {
1194
+ "description": "A condition to its negation.",
1195
+ "type": "string",
1196
+ "const": "negate-condition"
1197
+ },
1198
+ {
1199
+ "description": "A unary operator removed or changed.",
1200
+ "type": "string",
1201
+ "const": "unary-operator"
1202
+ },
1203
+ {
1204
+ "description": "`i++` to `i--`, and the reverse.",
1205
+ "type": "string",
1206
+ "const": "update-operator"
1207
+ },
1208
+ {
1209
+ "description": "A call statement removed.",
1210
+ "type": "string",
1211
+ "const": "removed-call"
1212
+ },
1213
+ {
1214
+ "description": "A return value changed.",
1215
+ "type": "string",
1216
+ "const": "return-value"
1217
+ },
1218
+ {
1219
+ "description": "`true` to `false`, and the reverse.",
1220
+ "type": "string",
1221
+ "const": "boolean-literal"
1222
+ },
1223
+ {
1224
+ "description": "A string literal emptied or filled.",
1225
+ "type": "string",
1226
+ "const": "string-literal"
1227
+ },
1228
+ {
1229
+ "description": "`a?.b` to `a.b`.",
1230
+ "type": "string",
1231
+ "const": "optional-chaining"
1232
+ },
1233
+ {
1234
+ "description": "One token of a regular expression literal changed: an anchor\nremoved, a character class negated, or a class escape with the\nopposite case.",
1235
+ "type": "string",
1236
+ "const": "regex-literal"
1237
+ }
1238
+ ]
1239
+ },
1077
1240
  "HealthConfig": {
1078
1241
  "description": "Configuration for complexity health metrics (`fallow health`).",
1079
1242
  "type": "object",
@@ -1132,7 +1295,7 @@
1132
1295
  "default": null
1133
1296
  },
1134
1297
  "ignore": {
1135
- "description": "Glob patterns to exclude from complexity analysis.",
1298
+ "description": "Glob patterns to exclude from complexity analysis.\nA single `*` stays within one path segment; use `**` to match across directories.",
1136
1299
  "type": "array",
1137
1300
  "items": {
1138
1301
  "type": "string"
@@ -1161,6 +1324,16 @@
1161
1324
  "emailMode": "handle"
1162
1325
  }
1163
1326
  },
1327
+ "changeCoupling": {
1328
+ "description": "Change coupling thresholds for the `change_coupling` section and the\nhidden-coupling refactoring targets. Older fallow versions reject this\nkey as unknown, so pair it with `minimumVersion` set to the release\nthat added it.",
1329
+ "$ref": "#/$defs/ChangeCouplingConfig",
1330
+ "default": {
1331
+ "maxFilesPerCommit": 30,
1332
+ "minRevisions": 5,
1333
+ "minSharedRevisions": 5,
1334
+ "minDegree": 0.3
1335
+ }
1336
+ },
1164
1337
  "suggestInlineSuppression": {
1165
1338
  "description": "Whether health JSON output emits `suppress-line` action hints\nalongside complexity findings (default: `true`). Set to `false` to\nopt out across the project: useful for teams that manage suppressions\nexclusively through `// fallow-ignore-*` comments authored by hand or\nthrough the `fallow.suppress` LSP code action, but who do not want\nCI-driven `suppress-line` action hints in their JSON output.\n`--baseline` activates auto-omission regardless of this setting,\nsince baseline files are a separate suppression mechanism.",
1166
1339
  "type": "boolean",
@@ -1174,7 +1347,7 @@
1174
1347
  "type": "object",
1175
1348
  "properties": {
1176
1349
  "files": {
1177
- "description": "Project-root-relative file globs this override applies to.",
1350
+ "description": "Project-root-relative file globs this override applies to.\nA single `*` stays within one path segment; use `**` to match across directories.",
1178
1351
  "type": "array",
1179
1352
  "items": {
1180
1353
  "type": "string"
@@ -1288,6 +1461,43 @@
1288
1461
  }
1289
1462
  ]
1290
1463
  },
1464
+ "ChangeCouplingConfig": {
1465
+ "description": "Thresholds for change coupling (`change_coupling` in `fallow health`).\n\nThe defaults are the Code Maat defaults. A pair of files is hidden coupling\nwhen each file has `minRevisions` commits, the pair shares\n`minSharedRevisions` commits, the coupling degree reaches `minDegree`, and\nno import or re-export chain connects the two files.",
1466
+ "type": "object",
1467
+ "properties": {
1468
+ "maxFilesPerCommit": {
1469
+ "description": "Skip a commit that changes more analyzed files than this (default:\n30, from 2 to 1000). Bulk commits (renames, format passes) create\nfalse pairs. The upper bound keeps the pair count of one commit small.",
1470
+ "type": "integer",
1471
+ "format": "uint",
1472
+ "minimum": 2,
1473
+ "maximum": 1000,
1474
+ "default": 30
1475
+ },
1476
+ "minRevisions": {
1477
+ "description": "Minimum commits for each file of a pair (default: 5).",
1478
+ "type": "integer",
1479
+ "format": "uint32",
1480
+ "minimum": 0,
1481
+ "default": 5
1482
+ },
1483
+ "minSharedRevisions": {
1484
+ "description": "Minimum commits that change both files of a pair (default: 5).",
1485
+ "type": "integer",
1486
+ "format": "uint32",
1487
+ "minimum": 0,
1488
+ "default": 5
1489
+ },
1490
+ "minDegree": {
1491
+ "description": "Minimum coupling degree, from 0 to 1 (default: 0.3). The degree is the\nnumber of shared commits divided by the mean commit count of the two\nfiles.",
1492
+ "type": "number",
1493
+ "format": "double",
1494
+ "minimum": 0.0,
1495
+ "maximum": 1.0,
1496
+ "default": 0.3
1497
+ }
1498
+ },
1499
+ "additionalProperties": false
1500
+ },
1291
1501
  "TypeAwareConfig": {
1292
1502
  "description": "Shared opt-in configuration for TypeScript semantic analysis.",
1293
1503
  "type": "object",
@@ -1381,22 +1591,22 @@
1381
1591
  "default": "error"
1382
1592
  },
1383
1593
  "unused-store-members": {
1384
- "description": "Store members (Pinia `state` / `getters` / `actions` key, or a\nsetup-store returned key) declared but never accessed by any consumer\nproject-wide. Defaults to `warn`, not `error` like the closed-set\nclass/enum member rules: a store has an OPEN declaration surface\n(plugins, `$onAction`, dynamic dispatch) so analyzer confidence is\ngenuinely lower; warn encodes that without failing CI. Promotable to\n`error` once validated on a codebase.",
1594
+ "description": "Store members (Pinia `state` / `getters` / `actions` key, or a\nsetup-store returned key) declared but never accessed by any consumer\nproject-wide. Defaults to `warn`, not `error` like the closed-set\nclass/enum member rules: a store has an OPEN declaration surface\n(plugins, `$onAction`, dynamic dispatch) so analyzer confidence is\ngenuinely lower. A `warn` finding does not change the CLI exit code\nunless `--fail-on-issues` is set. The dead-code count gate of the GitHub\nAction counts it unless `fail-on-issues` is `false`. Promotable to\n`error` once validated on a codebase.",
1385
1595
  "$ref": "#/$defs/Severity",
1386
1596
  "default": "warn"
1387
1597
  },
1388
1598
  "unprovided-injects": {
1389
- "description": "Vue `inject(KEY)` / Svelte `getContext(KEY)` whose symbol KEY is\n`provide`/`setContext`'d nowhere in the project (the\ninjected-never-provided dead-half). Defaults to `warn`, not `error`:\na DI key has an open provide surface (plugins, app-level provide) so\nanalyzer confidence is lower; warn encodes that without failing CI.",
1599
+ "description": "Vue `inject(KEY)` / Svelte `getContext(KEY)` whose symbol KEY is\n`provide`/`setContext`'d nowhere in the project (the\ninjected-never-provided dead-half). Defaults to `warn`, not `error`: a\nDI key has an open provide surface (plugins, app-level provide) so\nanalyzer confidence is lower. A `warn` finding does not change the CLI\nexit code unless `--fail-on-issues` is set. The dead-code count gate of\nthe GitHub Action counts it unless `fail-on-issues` is `false`.",
1390
1600
  "$ref": "#/$defs/Severity",
1391
1601
  "default": "warn"
1392
1602
  },
1393
1603
  "unrendered-components": {
1394
- "description": "Vue/Svelte single-file component reachable in the module graph but\nrendered nowhere in the project (the imported-but-never-rendered\ndead-half). Defaults to `warn`, not `error`: a component can be rendered\nreflectively (dynamic `<component :is>`), so analyzer confidence is\nlower; warn encodes that without failing CI.",
1604
+ "description": "Vue/Svelte single-file component reachable in the module graph but\nrendered nowhere in the project (the imported-but-never-rendered\ndead-half). Defaults to `warn`, not `error`: a component can be rendered\nreflectively (dynamic `<component :is>`), so analyzer confidence is\nlower. A `warn` finding does not change the CLI exit code unless\n`--fail-on-issues` is set. The dead-code count gate of the GitHub Action\ncounts it unless `fail-on-issues` is `false`.",
1395
1605
  "$ref": "#/$defs/Severity",
1396
1606
  "default": "warn"
1397
1607
  },
1398
1608
  "unused-component-props": {
1399
- "description": "Vue `<script setup>` `defineProps`, Svelte 5 `$props()`, or React\ndeclared prop referenced nowhere inside its own component. The\nsingle-component dead-input direction. Defaults to `warn`, not `error`: a\nprop can be part of a deliberately-stable public component API, so\nanalyzer confidence is lower; warn encodes that without failing CI.",
1609
+ "description": "Vue `<script setup>` `defineProps`, Svelte 5 `$props()`, or React\ndeclared prop referenced nowhere inside its own component. The\nsingle-component dead-input direction. Defaults to `warn`, not `error`:\na prop can be part of a deliberately-stable public component API, so\nanalyzer confidence is lower. A `warn` finding does not change the CLI\nexit code unless `--fail-on-issues` is set. The dead-code count gate of\nthe GitHub Action counts it unless `fail-on-issues` is `false`.",
1400
1610
  "$ref": "#/$defs/Severity",
1401
1611
  "default": "warn"
1402
1612
  },
@@ -1406,37 +1616,52 @@
1406
1616
  "default": "off"
1407
1617
  },
1408
1618
  "unused-component-emits": {
1409
- "description": "Vue `<script setup>` `defineEmits` declared event emitted nowhere inside\nits own single-file component (no `emit('<name>')` call). The single-file\ndead-input direction. Defaults to `warn`, not `error`: an emit can be part\nof a deliberately-stable public component API, so analyzer confidence is\nlower; warn encodes that without failing CI.",
1619
+ "description": "Vue `<script setup>` `defineEmits` declared event emitted nowhere inside\nits own single-file component (no `emit('<name>')` call). The\nsingle-file dead-input direction. Defaults to `warn`, not `error`: an\nemit can be part of a deliberately-stable public component API, so\nanalyzer confidence is lower. A `warn` finding does not change the CLI\nexit code unless `--fail-on-issues` is set. The dead-code count gate of\nthe GitHub Action counts it unless `fail-on-issues` is `false`.",
1410
1620
  "$ref": "#/$defs/Severity",
1411
1621
  "default": "warn"
1412
1622
  },
1413
1623
  "unused-component-inputs": {
1414
- "description": "Angular `@Input()` / signal `input()` / `model()` declared input read\nnowhere inside its own component (neither the inline/external template nor\nthe class body). The single-file dead-input direction, the Angular\nanalogue of `unused-component-prop`. Defaults to `warn`, not `error`: an\ninput can be part of a deliberately-stable public component API, so\nanalyzer confidence is lower; warn encodes that without failing CI.",
1624
+ "description": "Angular `@Input()` / signal `input()` / `model()` declared input read\nnowhere inside its own component (neither the inline/external template\nnor the class body). The single-file dead-input direction, the Angular\nanalogue of `unused-component-prop`. Defaults to `warn`, not `error`: an\ninput can be part of a deliberately-stable public component API, so\nanalyzer confidence is lower. A `warn` finding does not change the CLI\nexit code unless `--fail-on-issues` is set. The dead-code count gate of\nthe GitHub Action counts it unless `fail-on-issues` is `false`.",
1415
1625
  "$ref": "#/$defs/Severity",
1416
1626
  "default": "warn"
1417
1627
  },
1418
1628
  "unused-component-outputs": {
1419
- "description": "Angular `@Output()` / signal `output()` declared output emitted nowhere\ninside its own component (no `this.<output>.emit(...)`). The single-file\ndead-output direction, the Angular analogue of `unused-component-emit`.\nDefaults to `warn`, not `error`: an output can be part of a\ndeliberately-stable public component API, so analyzer confidence is lower;\nwarn encodes that without failing CI.",
1629
+ "description": "Angular `@Output()` / signal `output()` declared output emitted nowhere\ninside its own component (no `this.<output>.emit(...)`). The single-file\ndead-output direction, the Angular analogue of `unused-component-emit`.\nDefaults to `warn`, not `error`: an output can be part of a\ndeliberately-stable public component API, so analyzer confidence is\nlower. A `warn` finding does not change the CLI exit code unless\n`--fail-on-issues` is set. The dead-code count gate of the GitHub Action\ncounts it unless `fail-on-issues` is `false`.",
1420
1630
  "$ref": "#/$defs/Severity",
1421
1631
  "default": "warn"
1422
1632
  },
1423
1633
  "unused-svelte-events": {
1424
- "description": "Svelte component dispatching a custom event via `createEventDispatcher()`\nwhose event name is listened to nowhere in the analyzed project. The\ncross-file dead-output direction (no eslint-plugin-svelte / svelte-check\nrule covers the listener side). Defaults to `warn`, not `error`: a\ndispatched event can be part of a deliberately-stable public component\nAPI, or a listener may be added later, so analyzer confidence is lower;\nwarn encodes that without failing CI.",
1634
+ "description": "Svelte component dispatching a custom event via\n`createEventDispatcher()` whose event name is listened to nowhere in the\nanalyzed project. The cross-file dead-output direction (no\neslint-plugin-svelte / svelte-check rule covers the listener side).\nDefaults to `warn`, not `error`: a dispatched event can be part of a\ndeliberately-stable public component API, or a listener may be added\nlater, so analyzer confidence is lower. A `warn` finding does not change\nthe CLI exit code unless `--fail-on-issues` is set. The dead-code count\ngate of the GitHub Action counts it unless `fail-on-issues` is `false`.",
1635
+ "$ref": "#/$defs/Severity",
1636
+ "default": "warn"
1637
+ },
1638
+ "unused-effect-layers": {
1639
+ "description": "Effect layer composed only into other layers that nothing uses. Gated\non the project declaring `effect`. Defaults to `warn`: code outside the\nanalyzed project can still compose the layer.",
1640
+ "$ref": "#/$defs/Severity",
1641
+ "default": "warn"
1642
+ },
1643
+ "unused-tagged-errors": {
1644
+ "description": "Effect tagged error class that only type positions or `catchTag`\nhandlers reference. Gated on the project declaring `effect`. Defaults\nto `warn`: consumers outside the project can construct the error.",
1645
+ "$ref": "#/$defs/Severity",
1646
+ "default": "warn"
1647
+ },
1648
+ "unproduced-catch-tags": {
1649
+ "description": "`catchTag` handler for a project tag that no code produces, when no\n`unused-tagged-errors` finding covers it. Gated on the project\ndeclaring `effect`. Defaults to `warn`.",
1425
1650
  "$ref": "#/$defs/Severity",
1426
1651
  "default": "warn"
1427
1652
  },
1428
1653
  "unused-server-actions": {
1429
- "description": "Next.js Server Action (an export of a `\"use server\"` file) referenced by\nno code in the project: no import-and-call, no `action={fn}` binding, no\n`<form action={fn}>`. Cross-graph dead-export direction, reclassified out\nof `unused-export` for `\"use server\"` files. Defaults to `warn`, not\n`error`: the rule is new and false-negative-preferring, and reflective\naction-dispatch shapes can hide a real consumer; warn encodes that\nwithout failing CI until corpus-validated.",
1654
+ "description": "Next.js Server Action (an export of a `\"use server\"` file) referenced by\nno code in the project: no import-and-call, no `action={fn}` binding, no\n`<form action={fn}>`. Cross-graph dead-export direction, reclassified\nout of `unused-export` for `\"use server\"` files. Defaults to `warn`, not\n`error`: the rule is new and false-negative-preferring, and reflective\naction-dispatch shapes can hide a real consumer. The rule stays at\n`warn` until corpus validation. A `warn` finding does not change the CLI\nexit code unless `--fail-on-issues` is set. The dead-code count gate of\nthe GitHub Action counts it unless `fail-on-issues` is `false`.",
1430
1655
  "$ref": "#/$defs/Severity",
1431
1656
  "default": "warn"
1432
1657
  },
1433
1658
  "unused-load-data-keys": {
1434
- "description": "SvelteKit `+page.{ts,server.ts,js,server.js}` `load()` return-object key\nread by no consumer: not off the sibling `+page.svelte`'s `data.<key>`,\nnor project-wide via `page.data.<key>` / `$page.data.<key>`. Cross-file\ndead-input direction. Defaults to `warn`, not `error`: the rule is new and\nfalse-negative-preferring (a whole-object `data` pass abstains), and a\nload fetch can have side effects so deletion is a human call; warn encodes\nthat without failing CI until corpus-validated.",
1659
+ "description": "SvelteKit `+page.{ts,server.ts,js,server.js}` `load()` return-object key\nread by no consumer: not off the sibling `+page.svelte`'s `data.<key>`,\nnor project-wide via `page.data.<key>` / `$page.data.<key>`. Cross-file\ndead-input direction. Defaults to `warn`, not `error`: the rule is new\nand false-negative-preferring (a whole-object `data` pass abstains), and\na load fetch can have side effects so deletion is a human call. The rule\nstays at `warn` until corpus validation. A `warn` finding does not\nchange the CLI exit code unless `--fail-on-issues` is set. The dead-code\ncount gate of the GitHub Action counts it unless `fail-on-issues` is\n`false`.",
1435
1660
  "$ref": "#/$defs/Severity",
1436
1661
  "default": "warn"
1437
1662
  },
1438
1663
  "prop-drilling": {
1439
- "description": "React/Preact prop forwarded unchanged through `>= N` intermediate\npass-through components until a component that substantively consumes it.\nA graph-derived health signal. Defaults to `off` (opt-in), like\n`private-type-leak` / `security-*`: the located per-chain records and the\nsmall capped health penalty are dormant until the user enables the rule.",
1664
+ "description": "React/Preact prop forwarded unchanged through `>= N` intermediate\npass-through components until a component that substantively consumes it.\nA graph-derived health signal. Defaults to `off` (opt-in), like\n`private-type-leak` / `security-*`: the located per-chain records and the\nsmall capped health penalty are dormant until the user enables the rule.\n`error` enforces the finding in CI; `warn` stays advisory even under\nstrict flags. Overrides resolve for the source hop and can enable the\nrule while the base rule is off.",
1440
1665
  "$ref": "#/$defs/Severity",
1441
1666
  "default": "off"
1442
1667
  },
@@ -1624,19 +1849,44 @@
1624
1849
  "description": "Sibling Next.js dynamic route segments at one tree position using\ndifferent param spellings (`[id]` vs `[slug]`). Next.js throws \"You\ncannot use different slug names for the same dynamic path\" at dev and\nproduction runtime when the position is hit; `next build` does NOT catch\nit (the build succeeds), so CI passes while the route crashes on its\nfirst request. fallow catches it statically. Defaults to `error`: the\nroute is a deterministic runtime crash on first request, so failing CI\nis the honest signal even though `next build` stays green (this is the\n\"error-runtime\" severity tier, shared with `route-collision`).",
1625
1850
  "$ref": "#/$defs/Severity",
1626
1851
  "default": "error"
1852
+ },
1853
+ "weakened-tests": {
1854
+ "description": "An audit diff that weakens tests: a new skip or focus marker, removed\ntest cases, fewer assertions, or a lowered coverage threshold.\n`fallow audit` only. Defaults to `warn`.",
1855
+ "$ref": "#/$defs/Severity",
1856
+ "default": "warn"
1857
+ },
1858
+ "added-suppression": {
1859
+ "description": "An audit diff that adds a lint, type-check, coverage or Fallow\nsuppression comment. `fallow audit` only. Defaults to `warn`.",
1860
+ "$ref": "#/$defs/Severity",
1861
+ "default": "warn"
1862
+ },
1863
+ "test-only-branch": {
1864
+ "description": "An audit diff that adds a test-environment branch to a non-test source\nfile. `fallow audit` only. Defaults to `warn`.",
1865
+ "$ref": "#/$defs/Severity",
1866
+ "default": "warn"
1867
+ },
1868
+ "diverged-clone-sibling": {
1869
+ "description": "An audit diff that edits one copy of a base clone group so that it no\nlonger matches its siblings, while no sibling changed. `fallow audit`\nonly. Opt-in; defaults to `off`, because copies often differ on\npurpose.",
1870
+ "$ref": "#/$defs/Severity",
1871
+ "default": "off"
1872
+ },
1873
+ "added-dependency": {
1874
+ "description": "An audit diff that adds a dependency to a `package.json`. `fallow\naudit` only. Opt-in; defaults to `off`.",
1875
+ "$ref": "#/$defs/Severity",
1876
+ "default": "off"
1627
1877
  }
1628
1878
  }
1629
1879
  },
1630
1880
  "Severity": {
1631
- "description": "Severity level for rules.\n\nControls whether an issue type causes CI failure (`error`), is reported\nwithout failing (`warn`), or is suppressed entirely (`off`).",
1881
+ "description": "Severity level for rules.\n\nControls whether an issue type sets a non-zero exit code (`error`), is\nreported without an effect on the exit code (`warn`), or is suppressed\nentirely (`off`). `--fail-on-issues` promotes `warn` to `error`. The\ndead-code count gate of the GitHub Action counts `warn` findings unless its\n`fail-on-issues` input is `false`.",
1632
1882
  "oneOf": [
1633
1883
  {
1634
- "description": "Report and fail CI (non-zero exit code).",
1884
+ "description": "Report and set a non-zero exit code.",
1635
1885
  "type": "string",
1636
1886
  "const": "error"
1637
1887
  },
1638
1888
  {
1639
- "description": "Report but don't fail CI.",
1889
+ "description": "Report without an effect on the exit code.",
1640
1890
  "type": "string",
1641
1891
  "const": "warn"
1642
1892
  },
@@ -1747,7 +1997,7 @@
1747
1997
  "type": "string"
1748
1998
  },
1749
1999
  "patterns": {
1750
- "description": "Membership patterns.",
2000
+ "description": "Membership patterns.\nA single `*` stays within one path segment; use `**` to match across directories.",
1751
2001
  "type": "array",
1752
2002
  "items": {
1753
2003
  "type": "string"
@@ -1809,7 +2059,7 @@
1809
2059
  "type": "boolean"
1810
2060
  },
1811
2061
  "allowUnmatched": {
1812
- "description": "Glob patterns for files that may remain unmatched by any zone.",
2062
+ "description": "Glob patterns for files that may remain unmatched by any zone.\nA single `*` stays within one path segment; use `**` to match across directories.",
1813
2063
  "type": "array",
1814
2064
  "items": {
1815
2065
  "type": "string"
@@ -2072,7 +2322,7 @@
2072
2322
  "type": "object",
2073
2323
  "properties": {
2074
2324
  "files": {
2075
- "description": "Glob-pattern string array selecting which source files this override entry applies to (patterns are validated and compiled to matchers at config load). Set to scope the entry's rule severities to a subset of paths (e.g. `[\"src/generated/**\", \"**/*.test.ts\"]`); when several override entries match one file, its severities come from every matching entry, applied in list order (later entries win on conflict).",
2325
+ "description": "Glob-pattern string array selecting which source files this override entry applies to (patterns are validated and compiled to matchers at config load). Set to scope the entry's rule severities to a subset of paths (e.g. `[\"src/generated/**\", \"**/*.test.ts\"]`); when several override entries match one file, its severities come from every matching entry, applied in list order (later entries win on conflict). A single `*` stays within one path segment; use `**` to match across directories.",
2076
2326
  "type": "array",
2077
2327
  "items": {
2078
2328
  "type": "string"
@@ -2302,6 +2552,39 @@
2302
2552
  }
2303
2553
  ]
2304
2554
  },
2555
+ "unused-effect-layers": {
2556
+ "description": "Optional override for [`RulesConfig::unused_effect_layers`].",
2557
+ "anyOf": [
2558
+ {
2559
+ "$ref": "#/$defs/Severity"
2560
+ },
2561
+ {
2562
+ "type": "null"
2563
+ }
2564
+ ]
2565
+ },
2566
+ "unused-tagged-errors": {
2567
+ "description": "Optional override for [`RulesConfig::unused_tagged_errors`].",
2568
+ "anyOf": [
2569
+ {
2570
+ "$ref": "#/$defs/Severity"
2571
+ },
2572
+ {
2573
+ "type": "null"
2574
+ }
2575
+ ]
2576
+ },
2577
+ "unproduced-catch-tags": {
2578
+ "description": "Optional override for [`RulesConfig::unproduced_catch_tags`].",
2579
+ "anyOf": [
2580
+ {
2581
+ "$ref": "#/$defs/Severity"
2582
+ },
2583
+ {
2584
+ "type": "null"
2585
+ }
2586
+ ]
2587
+ },
2305
2588
  "unused-server-actions": {
2306
2589
  "description": "Optional override for [`RulesConfig::unused_server_actions`].",
2307
2590
  "anyOf": [
@@ -2741,6 +3024,61 @@
2741
3024
  "type": "null"
2742
3025
  }
2743
3026
  ]
3027
+ },
3028
+ "weakened-tests": {
3029
+ "description": "Optional override for [`RulesConfig::weakened_tests`].",
3030
+ "anyOf": [
3031
+ {
3032
+ "$ref": "#/$defs/Severity"
3033
+ },
3034
+ {
3035
+ "type": "null"
3036
+ }
3037
+ ]
3038
+ },
3039
+ "added-suppression": {
3040
+ "description": "Optional override for [`RulesConfig::added_suppression`].",
3041
+ "anyOf": [
3042
+ {
3043
+ "$ref": "#/$defs/Severity"
3044
+ },
3045
+ {
3046
+ "type": "null"
3047
+ }
3048
+ ]
3049
+ },
3050
+ "test-only-branch": {
3051
+ "description": "Optional override for [`RulesConfig::test_only_branch`].",
3052
+ "anyOf": [
3053
+ {
3054
+ "$ref": "#/$defs/Severity"
3055
+ },
3056
+ {
3057
+ "type": "null"
3058
+ }
3059
+ ]
3060
+ },
3061
+ "diverged-clone-sibling": {
3062
+ "description": "Optional override for [`RulesConfig::diverged_clone_sibling`].",
3063
+ "anyOf": [
3064
+ {
3065
+ "$ref": "#/$defs/Severity"
3066
+ },
3067
+ {
3068
+ "type": "null"
3069
+ }
3070
+ ]
3071
+ },
3072
+ "added-dependency": {
3073
+ "description": "Optional override for [`RulesConfig::added_dependency`].",
3074
+ "anyOf": [
3075
+ {
3076
+ "$ref": "#/$defs/Severity"
3077
+ },
3078
+ {
3079
+ "type": "null"
3080
+ }
3081
+ ]
2744
3082
  }
2745
3083
  }
2746
3084
  },
@@ -3056,6 +3394,27 @@
3056
3394
  "description": "Selects which findings affect the `fallow audit` verdict: `new-only` (default) fails only on findings introduced by the current changeset (running a base-snapshot attribution pass), while `all` fails on every finding in changed files and skips that pass. Set to `all` to gate the full backlog in changed files; the `--gate` CLI flag overrides this.",
3057
3395
  "$ref": "#/$defs/AuditGate"
3058
3396
  },
3397
+ "deadCode": {
3398
+ "description": "Toggles the dead-code sub-analysis in `fallow audit` (unused files, exports, types, members and dependencies, plus boundary violations and circular dependencies, which come from the same pass). Defaults to on when unset; set `false` to leave it out of the verdict, summary and attribution, on the head and on the base snapshot. `fallow audit --skip dead-code` turns it off for one run and `--only` replaces this selection. The review brief (`--brief`, `fallow review`) keeps every sub-analysis because it reads the module graph.",
3399
+ "type": [
3400
+ "boolean",
3401
+ "null"
3402
+ ]
3403
+ },
3404
+ "health": {
3405
+ "description": "Toggles the health sub-analysis in `fallow audit` (complexity and CRAP findings, plus styling findings, which come from the same pass). Defaults to on when unset; set `false` to leave it out of the verdict, summary and attribution, on the head and on the base snapshot. `fallow audit --skip health` turns it off for one run and `--only` replaces this selection.",
3406
+ "type": [
3407
+ "boolean",
3408
+ "null"
3409
+ ]
3410
+ },
3411
+ "dupes": {
3412
+ "description": "Toggles the duplication sub-analysis in `fallow audit`. Defaults to on when unset; set `false` to leave clone groups out of the verdict, summary and attribution, on the head and on the base snapshot. `fallow audit --skip dupes` turns it off for one run and `--only` replaces this selection.",
3413
+ "type": [
3414
+ "boolean",
3415
+ "null"
3416
+ ]
3417
+ },
3059
3418
  "css": {
3060
3419
  "description": "Toggles styling analytics (CSS and CSS-in-JS) in the `fallow audit` health sub-pass; these findings are descriptive and verdict-neutral by default (they change the exit code only when a css-* rule is set to error). Defaults to on when unset; set `false` to skip styling analysis. The `--no-css` CLI flag forces it off regardless.",
3061
3420
  "type": [
@@ -3092,7 +3451,7 @@
3092
3451
  ]
3093
3452
  },
3094
3453
  "cacheMaxAgeDays": {
3095
- "description": "Garbage-collection threshold, in whole days, for the persistent reusable base-snapshot worktree caches `fallow audit` creates: entries older than this window are swept on each audit run. Set to control cache accumulation; `0` disables the sweep and unset defaults to 30 days. Each sweep also reclaims abandoned entries minted under other repo identities (deleted or moved repos, other git worktrees) once they age past this repo's threshold; entries whose recorded owner root still exists are skipped and stay governed by that repo's own setting. The `FALLOW_AUDIT_CACHE_MAX_AGE_DAYS` environment variable overrides this field.",
3454
+ "description": "Garbage-collection threshold, in whole days, for the persistent reusable base-snapshot worktree caches `fallow audit` creates: entries older than this window are swept on each audit run. Set to control cache accumulation; `0` disables the sweep and unset defaults to 30 days. Each sweep also reclaims abandoned entries minted under other repo identities (deleted or moved repos, other git worktrees) once they age past this repo's threshold; entries whose recorded owner root still exists are skipped and stay governed by that repo's own setting. The same window applies to the base-snapshot files in the project cache directory, counted from their last use; independent of this window, audit keeps only the newest 32 of those files. The `FALLOW_AUDIT_CACHE_MAX_AGE_DAYS` environment variable overrides this field.",
3096
3455
  "type": [
3097
3456
  "integer",
3098
3457
  "null"